示例#1
0
        public string GetCommand()
        {
            var repo = new MemoryCatalogueRepository();

            var qb = new QueryBuilder("distinct", null);

            qb.AddColumn(new ColumnInfoToIColumn(repo, _keyColumn)
            {
                Order = 0
            });
            qb.AddColumn(new ColumnInfoToIColumn(repo, _descriptionColumn)
            {
                Order = 1
            });
            qb.TopX = 100;


            var container = new SpontaneouslyInventedFilterContainer(repo, null, null, FilterContainerOperation.AND);

            if (!string.IsNullOrWhiteSpace(tbCode.Text))
            {
                var codeFilter = new SpontaneouslyInventedFilter(repo, container, _keyColumn.GetFullyQualifiedName() + " LIKE '" + tbCode.Text + "%'", "Key Starts", "", null);
                container.AddChild(codeFilter);
            }

            if (!string.IsNullOrWhiteSpace(tbDescription.Text))
            {
                var codeFilter = new SpontaneouslyInventedFilter(repo, container, _descriptionColumn.GetFullyQualifiedName() + " LIKE '%" + tbDescription.Text + "%'", "Description Contains", "", null);
                container.AddChild(codeFilter);
            }

            qb.RootFilterContainer = container;

            return(qb.SQL);
        }
        private void AddDistributionColumns(QueryBuilder qb)
        {
            var repo = new MemoryRepository();

            qb.AddColumn(new SpontaneouslyInventedColumn(repo, "CountTotal", "count(1)"));
            qb.AddColumn(new SpontaneouslyInventedColumn(repo, "CountNull", "SUM(CASE WHEN " + GetColumnSelectSql() + " IS NULL THEN 1 ELSE 0  END)"));
            qb.AddColumn(new SpontaneouslyInventedColumn(repo, "CountZero", "SUM(CASE WHEN " + GetColumnSelectSql() + " = 0 THEN 1  ELSE 0 END)"));

            qb.AddColumn(new SpontaneouslyInventedColumn(repo, "Max", "max(" + GetColumnSelectSql() + ")"));
            qb.AddColumn(new SpontaneouslyInventedColumn(repo, "Min", "min(" + GetColumnSelectSql() + ")"));

            switch (ColumnInfo.GetQuerySyntaxHelper().DatabaseType)
            {
            case DatabaseType.MicrosoftSQLServer:
                qb.AddColumn(new SpontaneouslyInventedColumn(repo, "stdev ", "stdev(" + GetColumnSelectSql() + ")"));
                break;

            case DatabaseType.MySql:
            case DatabaseType.Oracle:
                qb.AddColumn(new SpontaneouslyInventedColumn(repo, "stddev ", "stddev(" + GetColumnSelectSql() + ")"));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            qb.AddColumn(new SpontaneouslyInventedColumn(repo, "avg", "avg(" + GetColumnSelectSql() + ")"));
        }
示例#3
0
        private void GetWhitelist(IDataLoadEventListener listener)
        {
            _whitelist = new HashSet <string>();

            var db     = DataAccessPortal.GetInstance().ExpectDatabase(PatientIdWhitelistColumnInfo.TableInfo, DataAccessContext.DataLoad);
            var server = db.Server;

            var qb = new QueryBuilder("distinct", null);

            qb.AddColumn(new ColumnInfoToIColumn(new MemoryRepository(), PatientIdWhitelistColumnInfo));

            var sql = qb.SQL;

            listener.OnNotify(this, new NotifyEventArgs(ProgressEventType.Information, "Downloading Whitelist with SQL:" + sql));

            using (var con = server.GetConnection())
            {
                con.Open();
                var r = server.GetCommand(sql, con).ExecuteReader();

                while (r.Read())
                {
                    var o = r[PatientIdWhitelistColumnInfo.GetRuntimeName()];
                    if (o == null || o == DBNull.Value)
                    {
                        continue;
                    }

                    _whitelist.Add(o.ToString());
                }
            }

            listener.OnNotify(this, new NotifyEventArgs(_whitelist.Count == 0 ? ProgressEventType.Error : ProgressEventType.Information, "Whitelist contained " + _whitelist.Count + " identifiers"));
        }
示例#4
0
        public void TestQueryBuilder_MySql_Normal()
        {
            var t = new TableInfo(CatalogueRepository, "`db`.`tbl`");

            t.DatabaseType = DatabaseType.MySql;
            t.SaveToDatabase();

            var col = new ColumnInfo(CatalogueRepository, "`db`.`tbl`.`col`", "varchar(10)", t);

            Assert.AreEqual("col", col.GetRuntimeName());

            var cata           = new Catalogue(CatalogueRepository, "cata");
            var catalogueItem  = new CatalogueItem(CatalogueRepository, cata, "col");
            var extractionInfo = new ExtractionInformation(CatalogueRepository, catalogueItem, col, col.Name);

            var qb = new QueryBuilder(null, null);

            qb.AddColumn(extractionInfo);
            Assert.AreEqual(CollapseWhitespace(
                                @"SELECT 
`db`.`tbl`.`col`
FROM 
`db`.`tbl`"
                                ), CollapseWhitespace(qb.SQL));
        }
        private DataTable GetDataTable(int timeout, int?topX)
        {
            var qb = new QueryBuilder("distinct", null);

            if (topX != null)
            {
                qb.TopX = topX.Value;
            }
            qb.AddColumn(_extractionInformation);

            var server = _extractionInformation.CatalogueItem.Catalogue.GetDistinctLiveDatabaseServer(DataAccessContext.DataExport, true);

            var colName = _extractionInformation.GetRuntimeName();

            DataTable dt = new DataTable();

            dt.Columns.Add(colName);

            using (var con = server.GetConnection())
            {
                con.Open();
                var cmd = server.GetCommand(qb.SQL, con);
                cmd.CommandTimeout = timeout;

                var r = cmd.ExecuteReader();

                while (r.Read())
                {
                    dt.Rows.Add(new[] { r[colName] });
                }
            }

            return(dt);
        }
示例#6
0
        private static HashSet <string> FetchTable(ColumnInfo columnInfo)
        {
            var logger = LogManager.GetCurrentClassLogger();
            HashSet <string> toReturn = new HashSet <string>(StringComparer.CurrentCultureIgnoreCase);

            var qb = new QueryBuilder(limitationSQL: null, hashingAlgorithm: null);

            qb.AddColumn(new ColumnInfoToIColumn(new MemoryRepository(), columnInfo));

            string sql = qb.SQL;

            logger.Info("Running PatientID fetch SQL:" + sql);

            DiscoveredTable server = columnInfo.TableInfo.Discover(DataAccessContext.DataExport);

            using (DbConnection con = server.Database.Server.GetConnection())
            {
                con.Open();
                DbCommand    cmd    = server.GetCommand(sql, con);
                DbDataReader reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    toReturn.Add(reader[0].ToString());
                }
            }

            logger.Info($"Found {toReturn.Count} patients in the reject list");

            return(toReturn);
        }
示例#7
0
        private string GetMappingTableSql()
        {
            var repo = new MemoryCatalogueRepository();

            var qb = new QueryBuilder("DISTINCT", null, null);

            qb.AddColumn(new ColumnInfoToIColumn(repo, MappingFromColumn));
            qb.AddColumn(new ColumnInfoToIColumn(repo, MappingToColumn));

            if (!string.IsNullOrWhiteSpace(WHERELogic))
            {
                var container = new SpontaneouslyInventedFilterContainer(repo, null, null, FilterContainerOperation.AND);
                var filter    = new SpontaneouslyInventedFilter(repo, container, WHERELogic, "WHERELogic", null, null);
                container.AddChild(filter);

                qb.RootFilterContainer = container;
            }

            return(qb.SQL);
        }
示例#8
0
        public void Test_IsPrimaryExtractionTable_TwoTables()
        {
            var c1 = WhenIHaveA <ColumnInfo>();
            var c2 = WhenIHaveA <ColumnInfo>();

            c1.TableInfo.IsPrimaryExtractionTable = true;
            c1.TableInfo.SaveToDatabase();

            c2.TableInfo.IsPrimaryExtractionTable = true;
            c2.TableInfo.SaveToDatabase();

            QueryBuilder builder = new QueryBuilder(null, null);

            builder.AddColumn(new ColumnInfoToIColumn(Repository, c1));
            builder.AddColumn(new ColumnInfoToIColumn(Repository, c2));

            var ex = Assert.Throws <QueryBuildingException>(() => { var s = builder.SQL; });

            StringAssert.Contains("There are multiple tables marked as IsPrimaryExtractionTable", ex.Message);
        }
示例#9
0
        /// <summary>
        /// Creates a query builder with all the columns required to match rows on the
        /// </summary>
        /// <returns></returns>
        protected virtual QueryBuilder GetQueryBuilder()
        {
            var qb = new QueryBuilder("distinct", null);

            foreach (var col in Columns.AllColumns)
            {
                qb.AddColumn(col);
            }

            qb.RootFilterContainer = GetWhereLogic();

            return(qb);
        }
示例#10
0
        public void Test_TwoTables_JoinFound()
        {
            //4 tables
            var c1 = WhenIHaveA <ColumnInfo>();
            var c2 = WhenIHaveA <ColumnInfo>();

            //1 is primary
            c1.TableInfo.IsPrimaryExtractionTable = true;
            c1.TableInfo.SaveToDatabase();

            var j1 = new JoinInfo(Repository, c2, c1, ExtractionJoinType.Inner, null);

            QueryBuilder builder = new QueryBuilder(null, null);

            builder.AddColumn(new ColumnInfoToIColumn(Repository, c1));
            builder.AddColumn(new ColumnInfoToIColumn(Repository, c2));

            StringAssert.Contains("JOIN", builder.SQL);

            //we have 1 legit join go go team!
            Assert.AreEqual(1, builder.JoinsUsedInQuery.Count);
            Assert.AreEqual(j1, builder.JoinsUsedInQuery[0]);
        }
        public string GetSql()
        {
            var qb = new QueryBuilder(null, null, new[] { GetTableInfo() });

            if (ViewType == ViewType.TOP_100)
            {
                qb.TopX = 100;
            }

            if (ViewType == ViewType.Distribution)
            {
                AddDistributionColumns(qb);
            }
            else
            {
                qb.AddColumn(GetIColumn());
            }

            var filter    = GetFilterIfAny();
            var container = GetContainerIfAny();

            if (filter != null && container != null)
            {
                throw new Exception("Cannot generate SQL with both filter and container");
            }

            if (filter != null && !string.IsNullOrWhiteSpace(filter.WhereSQL))
            {
                qb.RootFilterContainer = new SpontaneouslyInventedFilterContainer(new MemoryCatalogueRepository(), null, new[] { filter }, FilterContainerOperation.AND);
            }
            else if (container != null)
            {
                qb.RootFilterContainer = container;
            }

            if (ViewType == ViewType.Aggregate)
            {
                qb.AddCustomLine("count(*) as Count,", QueryComponent.QueryTimeColumn);
            }

            var sql = qb.SQL;

            if (ViewType == ViewType.Aggregate)
            {
                sql += " GROUP BY " + GetColumnSelectSql();
            }

            return(sql);
        }
示例#12
0
        public void TestQueryBuilder_MySql_Top35()
        {
            var t = new TableInfo(CatalogueRepository, "`db`.`tbl`");

            t.DatabaseType = DatabaseType.MySql;
            t.SaveToDatabase();

            var col = new ColumnInfo(CatalogueRepository, "`db`.`tbl`.`col`", "varchar(10)", t);

            Assert.AreEqual("col", col.GetRuntimeName());

            var cata           = new Catalogue(CatalogueRepository, "cata");
            var catalogueItem  = new CatalogueItem(CatalogueRepository, cata, "col");
            var extractionInfo = new ExtractionInformation(CatalogueRepository, catalogueItem, col, col.Name);

            var qb = new QueryBuilder(null, null);

            qb.TopX = 35;
            qb.AddColumn(extractionInfo);
            Assert.AreEqual(
                CollapseWhitespace(
                    @"SELECT 
`db`.`tbl`.`col`
FROM 
`db`.`tbl`
LIMIT 35")
                , CollapseWhitespace(qb.SQL));


            //editting the topX should invalidate the SQL automatically
            qb.TopX = 50;
            Assert.AreEqual(
                CollapseWhitespace(
                    @"SELECT 
`db`.`tbl`.`col`
FROM 
`db`.`tbl`
LIMIT 50")
                , CollapseWhitespace(qb.SQL));
        }
示例#13
0
        public void TestQueryBuilder_MicrosoftSQLServer_Top35()
        {
            var t = new TableInfo(CatalogueRepository, "[db]..[tbl]");

            t.DatabaseType = DatabaseType.MicrosoftSQLServer;
            t.SaveToDatabase();

            var col = new ColumnInfo(CatalogueRepository, "[db]..[tbl].[col]", "varchar(10)", t);

            Assert.AreEqual("col", col.GetRuntimeName());

            var cata           = new Catalogue(CatalogueRepository, "cata");
            var catalogueItem  = new CatalogueItem(CatalogueRepository, cata, "col");
            var extractionInfo = new ExtractionInformation(CatalogueRepository, catalogueItem, col, col.Name);

            var qb = new QueryBuilder(null, null);

            qb.TopX = 35;
            qb.AddColumn(extractionInfo);
            Assert.AreEqual(
                CollapseWhitespace(
                    @"SELECT 
TOP 35
[db]..[tbl].[col]
FROM 
[db]..[tbl]")
                , CollapseWhitespace(qb.SQL));


            //editting the topX should invalidate the SQL automatically
            qb.TopX = 50;
            Assert.AreEqual(
                CollapseWhitespace(
                    @"SELECT 
TOP 50
[db]..[tbl].[col]
FROM 
[db]..[tbl]")
                , CollapseWhitespace(qb.SQL));
        }
        public string GetSql()
        {
            var qb = new QueryBuilder(null, null, new [] { ColumnInfo.TableInfo });

            if (ViewType == ViewType.TOP_100)
            {
                qb.TopX = 100;
            }

            if (ViewType == ViewType.Distribution)
            {
                AddDistributionColumns(qb);
            }
            else
            {
                qb.AddColumn(new ColumnInfoToIColumn(new MemoryRepository(), ColumnInfo));
            }

            var filter = GetFilterIfAny();

            if (filter != null && !string.IsNullOrWhiteSpace(filter.WhereSQL))
            {
                qb.RootFilterContainer = new SpontaneouslyInventedFilterContainer(new MemoryCatalogueRepository(), null, new[] { filter }, FilterContainerOperation.AND);
            }

            if (ViewType == ViewType.Aggregate)
            {
                qb.AddCustomLine("count(*),", QueryComponent.QueryTimeColumn);
            }

            var sql = qb.SQL;

            if (ViewType == ViewType.Aggregate)
            {
                sql += " GROUP BY " + ColumnInfo;
            }

            return(sql);
        }
示例#15
0
        public void Test_DatabaseTypeQueryWithParameter_IntParameter(DatabaseType dbType)
        {
            //Pick the destination server
            var tableName = TestDatabaseNames.GetConsistentName("tbl");

            //make sure there's a database ready to receive the data
            var db = GetCleanedServer(dbType);

            db.Create(true);


            //this is the table we are uploading
            var dt = new DataTable();

            dt.Columns.Add("numbercol");
            dt.Rows.Add(10);
            dt.Rows.Add(15);
            dt.Rows.Add(20);
            dt.Rows.Add(25);
            dt.TableName = tableName;
            try
            {
                ///////////////////////UPLOAD THE DataTable TO THE DESTINATION////////////////////////////////////////////
                var uploader = new DataTableUploadDestination();
                uploader.PreInitialize(db, new ThrowImmediatelyDataLoadJob());
                uploader.ProcessPipelineData(dt, new ThrowImmediatelyDataLoadJob(), new GracefulCancellationToken());
                uploader.Dispose(new ThrowImmediatelyDataLoadJob(), null);

                var tbl = db.ExpectTable(tableName);

                var importer = new TableInfoImporter(CatalogueRepository, tbl);
                importer.DoImport(out var ti, out var ci);

                var engineer = new ForwardEngineerCatalogue(ti, ci, true);
                engineer.ExecuteForwardEngineering(out var cata, out var cis, out var ei);
                /////////////////////////////////////////////////////////////////////////////////////////////////////////

                /////////////////////////////////THE ACTUAL PROPER TEST////////////////////////////////////
                //create an extraction filter
                var extractionInformation = ei.Single();
                var filter = new ExtractionFilter(CatalogueRepository, "Filter by numbers", extractionInformation);
                filter.WhereSQL = extractionInformation.SelectSQL + " = @n";
                filter.SaveToDatabase();

                //create the parameters for filter (no globals, masters or scope adjacent parameters)
                new ParameterCreator(filter.GetFilterFactory(), null, null).CreateAll(filter, null);

                var p = filter.GetAllParameters().Single();
                Assert.AreEqual("@n", p.ParameterName);
                p.ParameterSQL = p.ParameterSQL.Replace("varchar(50)", "int"); //make it int
                p.Value        = "20";
                p.SaveToDatabase();

                var qb = new QueryBuilder(null, null);
                qb.AddColumn(extractionInformation);
                qb.RootFilterContainer = new SpontaneouslyInventedFilterContainer(new MemoryCatalogueRepository(), null, new[] { filter }, FilterContainerOperation.AND);

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

                    string sql = qb.SQL;

                    var cmd = db.Server.GetCommand(sql, con);
                    var r   = cmd.ExecuteReader();
                    Assert.IsTrue(r.Read());
                    Assert.AreEqual(
                        20,
                        r[extractionInformation.GetRuntimeName()]);
                }
                ///////////////////////////////////////////////////////////////////////////////////////
            }
            finally
            {
                db.Drop();
            }
        }
示例#16
0
        private void Initialize()
        {
            //Figure out which UID columns exist in the Catalogue, do not require file path to be in Catalogue
            _columnSet = QueryToExecuteColumnSet.Create(_catalogue, false);

            //Tells us the DBMS type
            var syntax = _catalogue.GetQuerySyntaxHelper();

            //For storing the OR container and filter(s)
            var memory = new MemoryCatalogueRepository();

            //builds SQL we will run in lookup stage
            _queryBuilder = new QueryBuilder(null, null);

            //all we care about is if the uid appears if it does then we are rejecting it
            _queryBuilder.TopX = 1;

            //Filter is OR i.e. StudyInstanceUID = @StudyInstanceUID OR SeriesInstanceUID = @SeriesInstanceUID
            var container = _queryBuilder.RootFilterContainer = new SpontaneouslyInventedFilterContainer(memory, null, null, FilterContainerOperation.OR);

            //Build SELECT and WHERE bits of the query
            if (_columnSet.StudyTagColumn != null)
            {
                _queryBuilder.AddColumn(_columnSet.StudyTagColumn);

                string whereSql =
                    $"{_columnSet.StudyTagColumn.SelectSQL} = {syntax.ParameterSymbol}{QueryToExecuteColumnSet.DefaultStudyIdColumnName}";

                _studyFilter = new SpontaneouslyInventedFilter(memory, container, whereSql, "Study UID Filter", "", null);
                container.AddChild(_studyFilter);
            }


            if (_columnSet.SeriesTagColumn != null)
            {
                _queryBuilder.AddColumn(_columnSet.SeriesTagColumn);

                string whereSql =
                    $"{_columnSet.SeriesTagColumn.SelectSQL} = {syntax.ParameterSymbol}{QueryToExecuteColumnSet.DefaultSeriesIdColumnName}";

                _seriesFilter = new SpontaneouslyInventedFilter(memory, container, whereSql, "Series UID Filter", "", null);
                container.AddChild(_seriesFilter);
            }

            if (_columnSet.InstanceTagColumn != null)
            {
                _queryBuilder.AddColumn(_columnSet.InstanceTagColumn);

                string whereSql =
                    $"{_columnSet.InstanceTagColumn.SelectSQL} = {syntax.ParameterSymbol}{QueryToExecuteColumnSet.DefaultInstanceIdColumnName}";

                _instanceFilter = new SpontaneouslyInventedFilter(memory, container, whereSql, "Instance UID Filter", "", null);
                container.AddChild(_instanceFilter);
            }

            // Make sure the query builder looks valid
            if (!_queryBuilder.SelectColumns.Any())
            {
                throw new NotSupportedException($"Blacklist Catalogue {_catalogue} (ID={_catalogue.ID}) did not have any Core ExtractionInformation columns corresponding to any of the image UID tags (e.g. StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID).");
            }

            try
            {
                // make sure we can connect to the server
                _server = _catalogue.GetDistinctLiveDatabaseServer(DataAccessContext.DataExport, true);
                _server.TestConnection();
            }
            catch (Exception e)
            {
                throw new Exception($"Failed to test connection for Catalogue {_catalogue}", e);
            }

            // run a test lookup query against the remote database
            DoLookup("test1", "test2", "test3");
        }
示例#17
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();
        }
示例#18
0
        private void GeneratePreviews()
        {
            if (preview == null)
            {
                preview = new DataTable();
                preview.Columns.Add(_columnInfo.GetRuntimeName(LoadStage.PostLoad));
                preview.Columns.Add(ANOTable.ANOPrefix + _columnInfo.GetRuntimeName(LoadStage.PostLoad));

                var server = DataAccessPortal.GetInstance().ExpectServer(ColumnInfo.TableInfo, DataAccessContext.DataLoad);

                using (var con = server.GetConnection())
                {
                    con.Open();

                    lblPreviewDataIsFictional.Visible = false;

                    var qb = new QueryBuilder(null, null, new[] { ColumnInfo.TableInfo });
                    qb.AddColumn(new ColumnInfoToIColumn(new MemoryRepository(), _columnInfo));
                    qb.TopX = 10;

                    bool rowsRead = false;

                    using (DbCommand cmd = server.GetCommand(qb.SQL, con))
                    {
                        cmd.CommandTimeout = Convert.ToInt32(ntimeout.Value);
                        using (var r = cmd.ExecuteReader())
                        {
                            while (r.Read())
                            {
                                preview.Rows.Add(r[_columnInfo.GetRuntimeName(LoadStage.PostLoad)], DBNull.Value);
                                rowsRead = true;
                            }
                        }
                    }

                    if (!rowsRead)
                    {
                        lblPreviewDataIsFictional.Visible = true;
                        if (_columnInfo.GetRuntimeDataType(LoadStage.AdjustRaw).ToLower().Contains("char"))
                        {
                            preview.Rows.Add("?", DBNull.Value);
                            preview.Rows.Add("?", DBNull.Value);
                            preview.Rows.Add("?", DBNull.Value);
                            preview.Rows.Add("?", DBNull.Value);
                        }
                        else if (_columnInfo.GetRuntimeDataType(LoadStage.AdjustRaw).ToLower().Contains("date"))
                        {
                            preview.Rows.Add("1977-08-16", DBNull.Value);
                            preview.Rows.Add("1977-08-16", DBNull.Value);
                            preview.Rows.Add("1977-08-16", DBNull.Value);
                            preview.Rows.Add("1977-08-16", DBNull.Value);
                        }
                        else
                        {
                            preview.Rows.Add("-1", DBNull.Value);
                            preview.Rows.Add("-1", DBNull.Value);
                            preview.Rows.Add("-1", DBNull.Value);
                            preview.Rows.Add("-1", DBNull.Value);
                        }
                    }

                    con.Close();
                }
            }

            if (ANOTable != null)
            {
                try
                {
                    if (preview.Rows.Count != 0)
                    {
                        checksUI1.Clear();
                        ANOTransformer transformer = new ANOTransformer(ANOTable, new FromCheckNotifierToDataLoadEventListener(checksUI1));
                        transformer.Transform(preview, preview.Columns[0], preview.Columns[1], true);
                    }
                }
                catch (Exception e)
                {
                    checksUI1.OnCheckPerformed(new CheckEventArgs(e.Message, CheckResult.Fail, e));
                }
            }

            dgPreview.DataSource = preview;
        }
        public void Execute()
        {
            if (_planManager.TargetDatabase == null)
            {
                throw new Exception("PlanManager has no TargetDatabase set");
            }

            var memoryRepo = new MemoryCatalogueRepository();

            using (_catalogueRepository.BeginNewTransactedConnection())
            {
                try
                {
                    //for each skipped table
                    foreach (var skippedTable in _planManager.SkippedTables)
                    {
                        //we might have to refactor or port JoinInfos to these tables so we should establish what the parenthood of them was
                        foreach (ColumnInfo columnInfo in skippedTable.ColumnInfos)
                        {
                            GetNewColumnInfoForOld(columnInfo, true);
                        }
                    }

                    //for each table that isn't being skipped
                    foreach (var oldTableInfo in _planManager.TableInfos.Except(_planManager.SkippedTables))
                    {
                        List <DatabaseColumnRequest> columnsToCreate = new List <DatabaseColumnRequest>();

                        Dictionary <string, ColumnInfo> migratedColumns = new Dictionary <string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);

                        var querybuilderForMigratingTable = new QueryBuilder(null, null);

                        //for each column we are not skipping (Drop) work out the endpoint datatype (planner knows this)
                        foreach (ColumnInfo columnInfo in oldTableInfo.ColumnInfos)
                        {
                            var columnPlan = _planManager.GetPlanForColumnInfo(columnInfo);

                            if (columnPlan.Plan != Plan.Drop)
                            {
                                //add the column verbatim to the query builder because we know we have to read it from source
                                querybuilderForMigratingTable.AddColumn(new ColumnInfoToIColumn(memoryRepo, columnInfo));

                                string colName = columnInfo.GetRuntimeName();

                                //if it is being ano tabled then give the table name ANO as a prefix
                                if (columnPlan.Plan == Plan.ANO)
                                {
                                    colName = "ANO" + colName;
                                }

                                migratedColumns.Add(colName, columnInfo);

                                columnsToCreate.Add(new DatabaseColumnRequest(colName, columnPlan.GetEndpointDataType(), !columnInfo.IsPrimaryKey)
                                {
                                    IsPrimaryKey = columnInfo.IsPrimaryKey
                                });
                            }
                        }

                        SelectSQLForMigrations.Add(oldTableInfo, querybuilderForMigratingTable);

                        //Create the actual table
                        var tbl = _planManager.TargetDatabase.CreateTable(oldTableInfo.GetRuntimeName(), columnsToCreate.ToArray());

                        //import the created table
                        TableInfoImporter importer = new TableInfoImporter(_catalogueRepository, tbl);
                        importer.DoImport(out var newTableInfo, out var newColumnInfos);

                        //Audit the parenthood of the TableInfo/ColumnInfos
                        AuditParenthood(oldTableInfo, newTableInfo);

                        foreach (ColumnInfo newColumnInfo in newColumnInfos)
                        {
                            var oldColumnInfo = migratedColumns[newColumnInfo.GetRuntimeName()];

                            var columnPlan = _planManager.GetPlanForColumnInfo(oldColumnInfo);

                            if (columnPlan.Plan == Plan.ANO)
                            {
                                newColumnInfo.ANOTable_ID = columnPlan.ANOTable.ID;
                                newColumnInfo.SaveToDatabase();
                            }

                            //if there was a dilution configured we need to setup a virtual DLE load only column of the input type (this ensures RAW has a valid datatype)
                            if (columnPlan.Plan == Plan.Dilute)
                            {
                                //Create a discarded (load only) column with name matching the new columninfo
                                var discard = new PreLoadDiscardedColumn(_catalogueRepository, newTableInfo, newColumnInfo.GetRuntimeName());

                                //record that it exists to support dilution and that the data type matches the input (old) ColumnInfo (i.e. not the new data type!)
                                discard.Destination = DiscardedColumnDestination.Dilute;
                                discard.SqlDataType = oldColumnInfo.Data_type;
                                discard.SaveToDatabase();

                                DilutionOperationsForMigrations.Add(discard, columnPlan.Dilution);
                            }

                            AuditParenthood(oldColumnInfo, newColumnInfo);
                        }

                        if (DilutionOperationsForMigrations.Any())
                        {
                            newTableInfo.IdentifierDumpServer_ID = _planManager.GetIdentifierDumpServer().ID;
                            newTableInfo.SaveToDatabase();
                        }
                    }

                    NewCatalogue        = _planManager.Catalogue.ShallowClone();
                    NewCatalogue.Name   = "ANO" + _planManager.Catalogue.Name;
                    NewCatalogue.Folder = new CatalogueFolder(NewCatalogue, "\\anonymous" + NewCatalogue.Folder.Path);
                    NewCatalogue.SaveToDatabase();

                    AuditParenthood(_planManager.Catalogue, NewCatalogue);

                    //For each of the old ExtractionInformations (95% of the time that's just a reference to a ColumnInfo e.g. '[People].[Height]' but 5% of the time it's some horrible aliased transform e.g. 'dbo.RunMyCoolFunction([People].[Height]) as BigHeight'
                    foreach (CatalogueItem oldCatalogueItem in _planManager.Catalogue.CatalogueItems)
                    {
                        var oldColumnInfo = oldCatalogueItem.ColumnInfo;

                        //catalogue item is not connected to any ColumnInfo
                        if (oldColumnInfo == null)
                        {
                            continue;
                        }

                        var columnPlan = _planManager.GetPlanForColumnInfo(oldColumnInfo);

                        //we are not migrating it anyway
                        if (columnPlan.Plan == Plan.Drop)
                        {
                            continue;
                        }

                        ColumnInfo newColumnInfo = GetNewColumnInfoForOld(oldColumnInfo);

                        var newCatalogueItem = oldCatalogueItem.ShallowClone(NewCatalogue);

                        //and rewire it's ColumnInfo to the cloned child one
                        newCatalogueItem.ColumnInfo_ID = newColumnInfo.ID;

                        //If the old CatalogueItem had the same name as it's underlying ColumnInfo then we should use the new one otherwise just copy the old name whatever it was
                        newCatalogueItem.Name = oldCatalogueItem.Name.Equals(oldColumnInfo.Name) ? newColumnInfo.GetRuntimeName() : oldCatalogueItem.Name;

                        //add ANO to the front if the underlying column was annoed
                        if (newColumnInfo.GetRuntimeName().StartsWith("ANO") && !newCatalogueItem.Name.StartsWith("ANO"))
                        {
                            newCatalogueItem.Name = "ANO" + newCatalogueItem.Name;
                        }

                        newCatalogueItem.SaveToDatabase();

                        var oldExtractionInformation = oldCatalogueItem.ExtractionInformation;

                        //if the plan is to make the ColumnInfo extractable
                        if (columnPlan.ExtractionCategoryIfAny != null)
                        {
                            //Create a new ExtractionInformation for the new Catalogue
                            var newExtractionInformation = new ExtractionInformation(_catalogueRepository, newCatalogueItem, newColumnInfo, newColumnInfo.Name);

                            newExtractionInformation.ExtractionCategory = columnPlan.ExtractionCategoryIfAny.Value;
                            newExtractionInformation.SaveToDatabase();

                            //if it was previously extractable
                            if (oldExtractionInformation != null)
                            {
                                var refactorer = new SelectSQLRefactorer();

                                //restore the old SQL as it existed in the origin table
                                newExtractionInformation.SelectSQL = oldExtractionInformation.SelectSQL;

                                //do a refactor on the old column name for the new column name
                                refactorer.RefactorColumnName(newExtractionInformation, oldColumnInfo, newColumnInfo.Name, true);

                                //also refactor any other column names that might be referenced by the transform SQL e.g. it could be a combo column name where forename + surname is the value of the ExtractionInformation
                                foreach (var kvpOtherCols in _parenthoodDictionary.Where(kvp => kvp.Key is ColumnInfo))
                                {
                                    //if it's one we have already done, dont do it again
                                    if (Equals(kvpOtherCols.Value, newColumnInfo))
                                    {
                                        continue;
                                    }

                                    //otherwise do a non strict refactoring (don't worry if you don't finda ny references)
                                    refactorer.RefactorColumnName(newExtractionInformation, (ColumnInfo)kvpOtherCols.Key, ((ColumnInfo)(kvpOtherCols.Value)).Name, false);
                                }

                                //make the new one exactly as extractable
                                newExtractionInformation.Order = oldExtractionInformation.Order;
                                newExtractionInformation.Alias = oldExtractionInformation.Alias;
                                newExtractionInformation.IsExtractionIdentifier = oldExtractionInformation.IsExtractionIdentifier;
                                newExtractionInformation.HashOnDataRelease      = oldExtractionInformation.HashOnDataRelease;
                                newExtractionInformation.IsPrimaryKey           = oldExtractionInformation.IsPrimaryKey;
                                newExtractionInformation.SaveToDatabase();
                            }

                            AuditParenthood(oldCatalogueItem, newCatalogueItem);

                            if (oldExtractionInformation != null)
                            {
                                AuditParenthood(oldExtractionInformation, newExtractionInformation);
                            }
                        }
                    }

                    var existingJoinInfos        = _catalogueRepository.GetAllObjects <JoinInfo>();
                    var existingLookups          = _catalogueRepository.GetAllObjects <Lookup>();
                    var existingLookupComposites = _catalogueRepository.GetAllObjects <LookupCompositeJoinInfo>();

                    //migrate join infos
                    foreach (JoinInfo joinInfo in _planManager.GetJoinInfosRequiredCatalogue())
                    {
                        var newFk = GetNewColumnInfoForOld(joinInfo.ForeignKey);
                        var newPk = GetNewColumnInfoForOld(joinInfo.PrimaryKey);

                        //already exists
                        if (!existingJoinInfos.Any(ej => ej.ForeignKey_ID == newFk.ID && ej.PrimaryKey_ID == newPk.ID))
                        {
                            new JoinInfo(_catalogueRepository, newFk, newPk, joinInfo.ExtractionJoinType, joinInfo.Collation); //create it
                        }
                    }

                    //migrate Lookups
                    foreach (Lookup lookup in _planManager.GetLookupsRequiredCatalogue())
                    {
                        //Find the new columns in the ANO table that match the old lookup columns
                        var newDesc = GetNewColumnInfoForOld(lookup.Description);
                        var newFk   = GetNewColumnInfoForOld(lookup.ForeignKey);
                        var newPk   = GetNewColumnInfoForOld(lookup.PrimaryKey);

                        //see if we already have a Lookup declared for the NEW columns (unlikely)
                        Lookup newLookup = existingLookups.SingleOrDefault(l => l.Description_ID == newDesc.ID && l.ForeignKey_ID == newFk.ID);

                        //create new Lookup that mirrors the old but references the ANO columns instead
                        if (newLookup == null)
                        {
                            newLookup = new Lookup(_catalogueRepository, newDesc, newFk, newPk, lookup.ExtractionJoinType, lookup.Collation);
                        }

                        //also mirror any composite (secondary, tertiary join column pairs needed for the Lookup to operate correclty e.g. where TestCode 'HAB1' means 2 different things depending on healthboard)
                        foreach (LookupCompositeJoinInfo compositeJoin in lookup.GetSupplementalJoins().Cast <LookupCompositeJoinInfo>())
                        {
                            var newCompositeFk = GetNewColumnInfoForOld(compositeJoin.ForeignKey);
                            var newCompositePk = GetNewColumnInfoForOld(compositeJoin.PrimaryKey);

                            if (!existingLookupComposites.Any(c => c.ForeignKey_ID == newCompositeFk.ID && c.PrimaryKey_ID == newCompositePk.ID))
                            {
                                new LookupCompositeJoinInfo(_catalogueRepository, newLookup, newCompositeFk, newCompositePk, compositeJoin.Collation);
                            }
                        }
                    }

                    //create new data load confguration
                    LoadMetadata = new LoadMetadata(_catalogueRepository, "Anonymising " + NewCatalogue);
                    LoadMetadata.EnsureLoggingWorksFor(NewCatalogue);

                    NewCatalogue.LoadMetadata_ID = LoadMetadata.ID;
                    NewCatalogue.SaveToDatabase();

                    if (_planManager.DateColumn != null)
                    {
                        LoadProgressIfAny            = new LoadProgress(_catalogueRepository, LoadMetadata);
                        LoadProgressIfAny.OriginDate = _planManager.StartDate;
                        LoadProgressIfAny.SaveToDatabase();

                        //date column based migration only works for single TableInfo migrations (see Plan Manager checks)
                        var qb = SelectSQLForMigrations.Single(kvp => !kvp.Key.IsLookupTable()).Value;
                        qb.RootFilterContainer = new SpontaneouslyInventedFilterContainer(memoryRepo, null,
                                                                                          new[]
                        {
                            new SpontaneouslyInventedFilter(memoryRepo, null, _planManager.DateColumn + " >= @startDate", "After batch start date", "", null),
                            new SpontaneouslyInventedFilter(memoryRepo, null, _planManager.DateColumn + " <= @endDate", "Before batch end date", "", null),
                        }
                                                                                          , FilterContainerOperation.AND);
                    }
                    try
                    {
                        foreach (QueryBuilder qb in SelectSQLForMigrations.Values)
                        {
                            Console.WriteLine(qb.SQL);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Failed to generate migration SQL", e);
                    }

                    _catalogueRepository.EndTransactedConnection(true);
                }
                catch (Exception ex)
                {
                    _catalogueRepository.EndTransactedConnection(false);
                    throw new Exception("Failed to create ANO version, transaction rolled back succesfully", ex);
                }
            }
        }
示例#20
0
        public void Test_FourTables_MultipleRoutes()
        {
            //4 tables
            var c1 = WhenIHaveA <ColumnInfo>();

            c1.Name = "c1";
            c1.SaveToDatabase();
            c1.TableInfo.Name = "t1";
            c1.TableInfo.IsPrimaryExtractionTable = true;  //t1 is primary
            c1.TableInfo.SaveToDatabase();

            var c2 = WhenIHaveA <ColumnInfo>();

            c2.Name = "c2";
            c2.SaveToDatabase();
            c2.TableInfo.Name = "t2";
            c2.TableInfo.SaveToDatabase();

            var c3 = WhenIHaveA <ColumnInfo>();

            c3.Name = "c3";
            c3.SaveToDatabase();
            c3.TableInfo.Name = "t3";
            c3.TableInfo.SaveToDatabase();

            var c4 = WhenIHaveA <ColumnInfo>();

            c4.Name = "c4";
            c4.SaveToDatabase();
            c4.TableInfo.Name = "t4";
            c4.TableInfo.SaveToDatabase();


            /*       c2
             *     /    \
             *   c1      c4
             *     \   /
             *       c3
             *
             * */

            var j1 = new JoinInfo(Repository, c2, c1, ExtractionJoinType.Inner, null);
            var j2 = new JoinInfo(Repository, c3, c1, ExtractionJoinType.Inner, null);
            var j3 = new JoinInfo(Repository, c4, c2, ExtractionJoinType.Inner, null);
            var j4 = new JoinInfo(Repository, c4, c3, ExtractionJoinType.Inner, null);


            QueryBuilder builder = new QueryBuilder(null, null);

            builder.AddColumn(new ColumnInfoToIColumn(Repository, c1));
            builder.AddColumn(new ColumnInfoToIColumn(Repository, c2));
            builder.AddColumn(new ColumnInfoToIColumn(Repository, c3));
            builder.AddColumn(new ColumnInfoToIColumn(Repository, c4));

            Console.WriteLine(builder.SQL);

            //should be using only 3 of the 4 joins because we already have a route to c4 without a fourth join
            Assert.AreEqual(3, builder.JoinsUsedInQuery.Count);
            Assert.Contains(j1, builder.JoinsUsedInQuery);
            Assert.Contains(j2, builder.JoinsUsedInQuery);
            Assert.Contains(j3, builder.JoinsUsedInQuery);
        }
        public void OpportunisticJoinRequired()
        {
            var memory = new MemoryRepository();

            //tables and columns
            TableInfo  head = new TableInfo(CatalogueRepository, "Head");
            ColumnInfo col1 = new ColumnInfo(CatalogueRepository, "TestResultSetNumber", "int", head);
            ColumnInfo col2 = new ColumnInfo(CatalogueRepository, "PK", "int", head);

            TableInfo  result = new TableInfo(CatalogueRepository, "[biochemistry]..[Result]");
            ColumnInfo col3   = new ColumnInfo(CatalogueRepository, "FK", "int", result);
            ColumnInfo col4   = new ColumnInfo(CatalogueRepository, "Code", "varchar(10)", result);
            ColumnInfo col5   = new ColumnInfo(CatalogueRepository, "[biochemistry]..[Result].[OmgBob]", "varchar(10)", result);

            //we can join on col2 = col3
            new JoinInfo(CatalogueRepository, col3, col2, ExtractionJoinType.Right, "");

            //CASE 1 : Only 1 column used so no join needed
            var queryBuilder = new QueryBuilder(null, null);
            var icol1        = new ColumnInfoToIColumn(memory, col1);

            icol1.Order = 1;
            queryBuilder.AddColumn(icol1);

            TableInfo primary;
            var       tablesUsed = SqlQueryBuilderHelper.GetTablesUsedInQuery(queryBuilder, out primary, null);

            Assert.AreEqual(1, tablesUsed.Count);
            Assert.AreEqual(head, tablesUsed[0]);

            //CASE 2 : 2 columns used one from each table so join is needed
            queryBuilder = new QueryBuilder(null, null);
            queryBuilder.AddColumn(new ColumnInfoToIColumn(memory, col1));

            var icol4 = new ColumnInfoToIColumn(memory, col4);

            icol4.Order = 2;
            queryBuilder.AddColumn(icol4);

            tablesUsed = SqlQueryBuilderHelper.GetTablesUsedInQuery(queryBuilder, out primary, null);

            Assert.AreEqual(2, tablesUsed.Count);
            Assert.AreEqual(head, tablesUsed[0]);
            Assert.AreEqual(result, tablesUsed[1]);

            Assert.AreEqual(CollapseWhitespace(@"SELECT 
TestResultSetNumber,
Code
FROM 
[biochemistry]..[Result] Right JOIN Head ON FK = PK"), CollapseWhitespace(queryBuilder.SQL));

            var memoryRepository = new MemoryCatalogueRepository();

            var spontContainer = new SpontaneouslyInventedFilterContainer(memoryRepository, null, null, FilterContainerOperation.AND);

            var spontFilter = new SpontaneouslyInventedFilter(memoryRepository, spontContainer, "[biochemistry]..[Result].[OmgBob] = 'T'",
                                                              "My Filter", "Causes spontaneous requirement for joining compeltely", null);

            spontContainer.AddChild(spontFilter);


            //CASE 3 : Only 1 column from Head but filter contains a reference to Result column
            queryBuilder = new QueryBuilder(null, null);
            queryBuilder.AddColumn(new ColumnInfoToIColumn(memory, col1));

            //without the filter
            tablesUsed = SqlQueryBuilderHelper.GetTablesUsedInQuery(queryBuilder, out primary, null);
            Assert.AreEqual(1, tablesUsed.Count);

            //set the filter
            queryBuilder.RootFilterContainer = spontContainer;

            //this is super sneaky but makes the queryBuilder populate it's Filters property... basically your not supposed to use SqlQueryBuilderHelper for this kind of thing
            Console.WriteLine(queryBuilder.SQL);
            queryBuilder.ParameterManager.ClearNonGlobals();

            //with the filter
            tablesUsed = SqlQueryBuilderHelper.GetTablesUsedInQuery(queryBuilder, out primary, null);
            Assert.AreEqual(2, tablesUsed.Count);
        }