private void CheckTriggerIntact(DiscoveredTable table, ICheckNotifier notifier, out bool runSynchronizationAgain) { TriggerChecks checker = new TriggerChecks(table); checker.Check(notifier); runSynchronizationAgain = checker.TriggerCreated; }
private void CheckUpdateTriggers(IEnumerable <ITableInfo> allTableInfos) { // Check that the update triggers are present/enabled foreach (var tableInfo in allTableInfos) { TriggerChecks checker = new TriggerChecks(_databaseConfiguration.DeployInfo[LoadBubble.Live].ExpectTable(tableInfo.GetRuntimeName(), tableInfo.Schema)); checker.Check(_notifier); } }
public void Check(ICheckNotifier notifier) { var columnsToDump = TableInfo.PreLoadDiscardedColumns; var duplicates = columnsToDump.GroupBy(k => k.GetRuntimeName()).Where(c => c.Count() > 1).ToArray(); foreach (var duplicate in duplicates) { notifier.OnCheckPerformed( new CheckEventArgs( "There are " + duplicate.Count() + " PreLoadDiscardedColumns called '" + duplicate.Key + "' for TableInfo '" + TableInfo + "'", CheckResult.Fail)); } //columns that exist in live but are supposedly dropped during load var liveColumns = TableInfo.ColumnInfos.ToArray(); foreach (var preLoadDiscardedColumn in columnsToDump) { var match = liveColumns.FirstOrDefault(c => c.GetRuntimeName().Equals(preLoadDiscardedColumn.GetRuntimeName())); if (match != null) { if (preLoadDiscardedColumn.Destination != DiscardedColumnDestination.Dilute) { notifier.OnCheckPerformed(new CheckEventArgs("TableInfo " + TableInfo + " declares both a PreLoadDiscardedColumn '" + preLoadDiscardedColumn + "' and a ColumnInfo with the same name", CheckResult.Fail)); return; } if (match.IsPrimaryKey && preLoadDiscardedColumn.Destination == DiscardedColumnDestination.Dilute) { notifier.OnCheckPerformed(new CheckEventArgs("TableInfo " + TableInfo + " declares a PreLoadDiscardedColumn '" + preLoadDiscardedColumn + "' but there is a matching ColumnInfo of the same name which IsPrimaryKey", CheckResult.Fail)); return; } } } if (!HasAtLeastOneColumnToStoreInDump) { notifier.OnCheckPerformed(new CheckEventArgs("No columns require dumping from TableInfo " + _tableInfo + " so checking is not needed", CheckResult.Success, null)); return; } var tables = _dumpDatabase.DiscoverTables(false); bool stagingTableFound = tables.Any(t => t.GetRuntimeName().Equals(GetStagingRuntimeName())); ConfirmDependencies(_dumpDatabase, notifier); //detect ongoing loads/dirty cleanup if (stagingTableFound) { bool shouldDrop = notifier.OnCheckPerformed(new CheckEventArgs("STAGING table found " + GetStagingRuntimeName() + " in ANO database", CheckResult.Fail, null, "Drop table " + GetStagingRuntimeName())); if (shouldDrop) { DropStaging(); } } else { notifier.OnCheckPerformed(new CheckEventArgs("Confirmed absence of Table " + GetStagingRuntimeName() + "(this will be created during load)", CheckResult.Success, null)); } //confirm that there is a ColumnInfo for every Dilute column var columnInfos = _tableInfo.ColumnInfos.ToArray(); foreach (var dilutedColumn in ColumnsToRouteToSomewhereElse.Where(c => c.Destination == DiscardedColumnDestination.Dilute)) { if (!columnInfos.Any(c => c.GetRuntimeName().Equals(dilutedColumn.RuntimeColumnName))) { notifier.OnCheckPerformed(new CheckEventArgs("PreLoadDiscardedColumn called " + dilutedColumn.GetRuntimeName() + " is marked for Dilution but does not appear in the TableInfo object's ColumnInfo collection. Diluted columns must appear both in the LIVE database (in diluted state) and in IdentifierDump (in pristene state) which means that for every PreLoadDiscardedColumn which has the destination Dilution, there must be a ColumnInfo with the same name in LIVE", CheckResult.Fail, null)); } } //if there are any columns due to be stored in the Identifier dump if (ColumnsToRouteToSomewhereElse.Any(c => c.GoesIntoIdentifierDump())) { //see if table exists IdentifierDumperSynchronizer synchronizer = new IdentifierDumperSynchronizer(this, _externalDatabaseServer); synchronizer.Synchronize(notifier); //make sure there is a backup trigger enabled on the Identifier dump so that we version updates TriggerChecks triggerChecker = new TriggerChecks(_dumpDatabase.ExpectTable(GetRuntimeName())); // primary keys - ignoring transforms for ANO triggerChecker.Check(notifier); } }
public void TriggerImplementationTest(DatabaseType type) { var db = GetCleanedServer(type); var tbl = db.CreateTable("MyTable", new[] { new DatabaseColumnRequest("name", new DatabaseTypeRequest(typeof(string), 30), false), new DatabaseColumnRequest("bubbles", new DatabaseTypeRequest(typeof(int))) }); var factory = new TriggerImplementerFactory(type); var implementer = factory.Create(tbl); Assert.AreEqual(TriggerStatus.Missing, implementer.GetTriggerStatus()); Assert.AreEqual(2, tbl.DiscoverColumns().Length); implementer = factory.Create(tbl); //no primary keys Assert.Throws <TriggerException>(() => implementer.CreateTrigger(new ThrowImmediatelyCheckNotifier())); tbl.CreatePrimaryKey(tbl.DiscoverColumn("name")); implementer = factory.Create(tbl); implementer.CreateTrigger(new ThrowImmediatelyCheckNotifier()); Assert.AreEqual(4, tbl.DiscoverColumns().Length); var archiveTable = tbl.Database.ExpectTable(tbl.GetRuntimeName() + "_Archive"); Assert.IsTrue(archiveTable.Exists()); Assert.AreEqual(7, archiveTable.DiscoverColumns().Count()); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("name"))); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("bubbles"))); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("hic_dataLoadrunID", StringComparison.CurrentCultureIgnoreCase))); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("hic_validFrom", StringComparison.CurrentCultureIgnoreCase))); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("hic_validTo", StringComparison.CurrentCultureIgnoreCase))); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("hic_userID", StringComparison.CurrentCultureIgnoreCase))); Assert.AreEqual(1, archiveTable.DiscoverColumns().Count(c => c.GetRuntimeName().Equals("hic_status"))); //is the trigger now existing Assert.AreEqual(TriggerStatus.Enabled, implementer.GetTriggerStatus()); //does it function as expected using (var con = tbl.Database.Server.GetConnection()) { con.Open(); var cmd = tbl.Database.Server.GetCommand(string.Format("INSERT INTO {0}(name,bubbles) VALUES('bob',1)", tbl.GetRuntimeName()), con); cmd.ExecuteNonQuery(); Assert.AreEqual(1, tbl.GetRowCount()); Assert.AreEqual(0, archiveTable.GetRowCount()); cmd = tbl.Database.Server.GetCommand(string.Format("UPDATE {0} set bubbles=2", tbl.GetRuntimeName()), con); cmd.ExecuteNonQuery(); Assert.AreEqual(1, tbl.GetRowCount()); Assert.AreEqual(1, archiveTable.GetRowCount()); var archive = archiveTable.GetDataTable(); var dr = archive.Rows.Cast <DataRow>().Single(); Assert.AreEqual(((DateTime)dr["hic_validTo"]).Date, DateTime.Now.Date); } //do the strict check too Assert.IsTrue(implementer.CheckUpdateTriggerIsEnabledAndHasExpectedBody()); tbl.AddColumn("amagad", new DatabaseTypeRequest(typeof(float), null, new DecimalSize(2, 2)), true, 30); implementer = factory.Create(tbl); Assert.Throws <IrreconcilableColumnDifferencesInArchiveException>(() => implementer.CheckUpdateTriggerIsEnabledAndHasExpectedBody()); archiveTable.AddColumn("amagad", new DatabaseTypeRequest(typeof(float), null, new DecimalSize(2, 2)), true, 30); var checks = new TriggerChecks(tbl); checks.Check(new AcceptAllCheckNotifier()); Assert.IsTrue(implementer.CheckUpdateTriggerIsEnabledAndHasExpectedBody()); //does it function as expected using (var con = tbl.Database.Server.GetConnection()) { con.Open(); Assert.AreEqual(1, tbl.GetRowCount()); Assert.AreEqual(1, archiveTable.GetRowCount()); var cmd = tbl.Database.Server.GetCommand(string.Format("UPDATE {0} set amagad=1.0", tbl.GetRuntimeName()), con); cmd.ExecuteNonQuery(); cmd = tbl.Database.Server.GetCommand(string.Format("UPDATE {0} set amagad=.09", tbl.GetRuntimeName()), con); cmd.ExecuteNonQuery(); Assert.AreEqual(1, tbl.GetRowCount()); Assert.AreEqual(3, archiveTable.GetRowCount()); var archive = archiveTable.GetDataTable(); Assert.AreEqual(1, archive.Rows.Cast <DataRow>().Count(r => Equals(r["amagad"], (decimal)1.00))); Assert.AreEqual(2, archive.Rows.Cast <DataRow>().Count(r => r["amagad"] == DBNull.Value)); } string problems; string worked; implementer.DropTrigger(out problems, out worked); Assert.IsTrue(string.IsNullOrEmpty(problems)); Assert.AreEqual(TriggerStatus.Missing, implementer.GetTriggerStatus()); }