Example #1
0
        public Dictionary <TableInfo, DiscoveredTable> GetIsolationTables()
        {
            var db = IsolationDatabase.Discover(DataAccessContext.InternalDataProcessing);

            return(TablesToIsolate.ToDictionary(
                       tableInfo => tableInfo,
                       tableInfo => db.ExpectTable(PrimaryKeyCollisionIsolationMutilation.GetIsolationTableName(tableInfo))
                       ));
        }
        private void MigrateRecords(ColumnInfo deleteOn, string deleteValue)
        {
            var deleteOnColumnName = GetRAWColumnNameFullyQualified(deleteOn);

            using (var con = _raw.Server.GetConnection())
            {
                con.Open();

                //if we are deleting on a child table we need to look up the primary table primary key (e.g. StudyInstanceUID) we should then migrate that data instead (for all tables)
                if (!deleteOn.Equals(_primaryTablePk))
                {
                    var oldValue = deleteValue;

                    deleteValue        = GetPrimaryKeyValueFor(deleteOn, deleteValue, con);
                    deleteOnColumnName = GetRAWColumnNameFullyQualified(_primaryTablePk);

                    if (deleteValue == null)
                    {
                        throw new Exception("Primary key value not found for " + oldValue);
                    }

                    _job.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Corresponding primary key is '" + deleteValue + "' ('" + deleteOnColumnName + "')"));
                }

                //pull all records that we must isolate in all joined tables
                Dictionary <TableInfo, DataTable> toPush = new Dictionary <TableInfo, DataTable>();

                foreach (TableInfo tableInfo in TablesToIsolate)
                {
                    toPush.Add(tableInfo, PullTable(tableInfo, con, deleteOnColumnName, deleteValue));
                }

                //push the results to isolation
                foreach (KeyValuePair <TableInfo, DataTable> kvp in toPush)
                {
                    var toDatabase = IsolationDatabase.Discover(DataAccessContext.DataLoad);
                    var toTable    = toDatabase.ExpectTable(GetIsolationTableName(kvp.Key));

                    using (var bulkInsert = toTable.BeginBulkInsert())
                        bulkInsert.Upload(kvp.Value);
                }

                foreach (TableInfo t in TablesToIsolate.Reverse())
                {
                    DeleteRows(t, deleteOnColumnName, deleteValue, con);
                }
            }
        }
Example #3
0
        private void MigrateRecords(ColumnInfo deleteOn, object[] deleteValues)
        {
            var deleteOnColumnName = GetRAWColumnNameFullyQualified(deleteOn);

            using (var con = _raw.Server.GetConnection())
            {
                con.Open();

                //if we are deleting on a child table we need to look up the primary table primary key (e.g. StudyInstanceUID) we should then migrate that data instead (for all tables)
                if (!deleteOn.Equals(_primaryTablePk))
                {
                    deleteValues       = GetPrimaryKeyValuesFor(deleteOn, deleteValues, con);
                    deleteOnColumnName = GetRAWColumnNameFullyQualified(_primaryTablePk);
                }

                //pull all records that we must isolate in all joined tables
                Dictionary <TableInfo, DataTable> toPush = new Dictionary <TableInfo, DataTable>();

                foreach (TableInfo tableInfo in TablesToIsolate)
                {
                    toPush.Add(tableInfo, PullTable(tableInfo, con, deleteOnColumnName, deleteValues));
                }

                //push the results to isolation
                foreach (KeyValuePair <TableInfo, DataTable> kvp in toPush)
                {
                    var toDatabase = IsolationDatabase.Discover(DataAccessContext.DataLoad);
                    var toTable    = toDatabase.ExpectTable(GetIsolationTableName(kvp.Key));

                    using (var bulkInsert = toTable.BeginBulkInsert())
                        bulkInsert.Upload(kvp.Value);
                }

                foreach (TableInfo t in TablesToIsolate.Reverse())
                {
                    DeleteRows(t, deleteOnColumnName, deleteValues, con);
                }

                con.Close();
            }
        }
Example #4
0
        public void Check(ICheckNotifier notifier)
        {
            //if there is only one or no tables that's fine (mandatory will check for null itself)
            if (TablesToIsolate == null)
            {
                throw new Exception("No tables have been selected");
            }

            //make sure there is only one primary key per table and that it's a string
            foreach (TableInfo t in TablesToIsolate)
            {
                if (t.ColumnInfos.Count(c => c.IsPrimaryKey) != 1)
                {
                    throw new Exception("Table '" + t + "' did not have exactly 1 IsPrimaryKey column");
                }
            }

            //if there are multiple tables then we must know how to join them
            if (TablesToIsolate.Length > 1 && TablesToIsolate.Count(t => t.IsPrimaryExtractionTable) != 1)
            {
                var primaryTables = TablesToIsolate.Where(t => t.IsPrimaryExtractionTable).ToArray();

                notifier.OnCheckPerformed(
                    new CheckEventArgs(
                        $"There are {TablesToIsolate.Length} tables to operate on but {primaryTables.Length} are marked IsPrimaryExtractionTable ({string.Join(",",primaryTables.Select(t=>t.Name))}).  This should be set on a single top level table only e.g. Study",
                        CheckResult.Fail));
            }

            try
            {
                //if there are multiple tables we need to know how to join them on a 1 column to 1 basis
                BuildJoinOrder(true);
            }
            catch (Exception e)
            {
                notifier.OnCheckPerformed(new CheckEventArgs("Failed to build join order", CheckResult.Fail, e));
                return;
            }

            //This is where we put the duplicate records
            var db = IsolationDatabase.Discover(DataAccessContext.DataLoad);

            if (!db.Exists())
            {
                throw new Exception("IsolationDatabase did not exist");
            }

            //Make sure the isolation tables exist and the schema matches RAW
            foreach (var tableInfo in TablesToIsolate)
            {
                var table = db.ExpectTable(GetIsolationTableName(tableInfo));

                if (!table.Exists())
                {
                    bool fix = notifier.OnCheckPerformed(
                        new CheckEventArgs("Isolation table '" + table.GetFullyQualifiedName() + "' did not exist",
                                           CheckResult.Fail, null, "Create isolation table?"));

                    if (fix)
                    {
                        CreateIsolationTable(table, tableInfo);
                    }
                    else
                    {
                        throw new Exception("User rejected change");
                    }
                }
                else
                {
                    ValidateIsolationTableSchema(table, tableInfo, notifier);
                }
            }
        }
Example #5
0
        private void BuildJoinOrder(bool isChecks)
        {
            _qb = new QueryBuilder(null, null);

            var memory = new MemoryRepository();

            foreach (TableInfo t in TablesToIsolate)
            {
                _qb.AddColumn(new ColumnInfoToIColumn(memory, t.ColumnInfos.First()));
            }

            _primaryTable   = TablesToIsolate.Length == 1 ? TablesToIsolate[0] : TablesToIsolate.Single(t => t.IsPrimaryExtractionTable);
            _primaryTablePk = _primaryTable.ColumnInfos.Single(c => c.IsPrimaryKey);

            _qb.PrimaryExtractionTable = _primaryTable;

            _qb.RegenerateSQL();

            _joins = _qb.JoinsUsedInQuery ?? new List <JoinInfo>();

            _fromSql = SqlQueryBuilderHelper.GetFROMSQL(_qb);

            if (!isChecks)
            {
                foreach (TableInfo tableInfo in TablesToIsolate)
                {
                    _fromSql = _fromSql.Replace(tableInfo.GetFullyQualifiedName(), GetRAWTableNameFullyQualified(tableInfo));
                }
            }

            if (_joins.Any(j => j.GetSupplementalJoins().Any()))
            {
                throw new Exception("Supplemental (2 column) joins are not supported when resolving multi table primary key collisions");
            }

            //order the tables in order of dependency
            List <TableInfo> tables = new List <TableInfo>();

            TableInfo next = _primaryTable;

            int overflow = 10;

            while (next != null)
            {
                tables.Add(next);
                var jnext = _joins.SingleOrDefault(j => j.PrimaryKey.TableInfo.Equals(next));
                if (jnext == null)
                {
                    break;
                }

                next = jnext.ForeignKey.TableInfo;

                if (overflow-- == 0)
                {
                    throw new Exception("Joins resulted in a loop overflow");
                }
            }

            TablesToIsolate = tables.ToArray();
        }