public void CommitResults_CreatesTablessuccessfully() { DataTable dt = new DataTable(); dt.Columns.Add("MyCol"); dt.Rows.Add("0101010101"); dt.Rows.Add("0201010101"); dt.Rows.Add("0101310101"); //commit it 3 times, should just overwrite _manager.CommitResults(new CacheCommitIdentifierList(_config, SomeComplexBitOfSqlCode, dt, _myColSpecification, 30)); _manager.CommitResults(new CacheCommitIdentifierList(_config, SomeComplexBitOfSqlCode, dt, _myColSpecification, 30)); _manager.CommitResults(new CacheCommitIdentifierList(_config, SomeComplexBitOfSqlCode, dt, _myColSpecification, 30)); var resultsTableName = _manager.GetLatestResultsTableUnsafe(_config, AggregateOperation.IndexedExtractionIdentifierList); Assert.AreEqual("IndexedExtractionIdentifierList_AggregateConfiguration" + _config.ID, resultsTableName.GetRuntimeName()); var table = DataAccessPortal.GetInstance() .ExpectDatabase(QueryCachingDatabaseServer, DataAccessContext.InternalDataProcessing) .ExpectTable(resultsTableName.GetRuntimeName()); Assert.IsTrue(table.Exists()); var col = table.DiscoverColumn("MyCol"); Assert.IsNotNull(col); Assert.AreEqual("varchar(10)", col.DataType.SQLType); using (var con = DataAccessPortal.GetInstance().ExpectServer(QueryCachingDatabaseServer, DataAccessContext.InternalDataProcessing).GetConnection()) { con.Open(); var dt2 = new DataTable(); SqlDataAdapter da = new SqlDataAdapter("Select * from " + resultsTableName.GetFullyQualifiedName(), (SqlConnection)con); da.Fill(dt2); Assert.AreEqual(dt.Rows.Count, dt2.Rows.Count); con.Close(); } Assert.IsNotNull(_manager.GetLatestResultsTable(_config, AggregateOperation.IndexedExtractionIdentifierList, SomeComplexBitOfSqlCode)); Assert.IsNull(_manager.GetLatestResultsTable(_config, AggregateOperation.IndexedExtractionIdentifierList, "select name,height,scalecount from fish")); }
private void btnCache_Click(object sender, EventArgs e) { try { CachedAggregateConfigurationResultsManager cacheManager = GetCacheManager(); var args = new CacheCommitExtractableAggregate(AggregateConfiguration, QueryEditor.Text, (DataTable)dataGridView1.DataSource, Timeout); cacheManager.CommitResults(args); var result = cacheManager.GetLatestResultsTable(AggregateConfiguration, AggregateOperation.ExtractableAggregateResults, QueryEditor.Text); if (result == null) { throw new NullReferenceException("CommitResults passed but GetLatestResultsTable returned false (when we tried to refetch the table name from the cache)"); } MessageBox.Show("DataTable successfully submitted to:" + result.GetFullyQualifiedName()); btnClearFromCache.Enabled = true; } catch (Exception exception) { ExceptionViewer.Show(exception); } }
public string GetSQLForAggregate(AggregateConfiguration aggregate, int tabDepth, bool isJoinAggregate = false, string overrideSelectList = null, string overrideLimitationSQL = null, int topX = -1) { string toReturn = ""; CountOfSubQueries++; string tabs = ""; string tabplusOne = ""; if (tabDepth != -1) { GetTabs(tabDepth, out tabs, out tabplusOne); } //make sure it is a valid configuration string reason; if (!aggregate.IsAcceptableAsCohortGenerationSource(out reason)) { throw new QueryBuildingException("Cannot generate a cohort using AggregateConfiguration " + aggregate + " because:" + reason); } //get the extraction identifier (method IsAcceptableAsCohortGenerationSource will ensure this linq returns 1 so no need to check again) AggregateDimension extractionIdentifier = aggregate.AggregateDimensions.Single(d => d.IsExtractionIdentifier); //create a builder but do it manually, we care about group bys etc or count(*) even AggregateBuilder builder; //we are getting SQL for a cohort identification aggregate without a HAVING/count statement so it is actually just 'select patientIdentifier from tableX' if (string.IsNullOrWhiteSpace(aggregate.HavingSQL) && string.IsNullOrWhiteSpace(aggregate.CountSQL)) { //select list is the extraction identifier string selectList; if (!isJoinAggregate) { selectList = extractionIdentifier.SelectSQL + (extractionIdentifier.Alias != null ? " " + extractionIdentifier.Alias: ""); } else { //unless we are also including other columns because this is a patient index joinable inception query selectList = string.Join("," + Environment.NewLine + tabs, aggregate.AggregateDimensions.Select(e => e.SelectSQL + (e.Alias != null ? " " + e.Alias : ""))); //joinable patient index tables have patientIdentifier + 1 or more other columns } if (overrideSelectList != null) { selectList = overrideSelectList; } string limitationSQL = overrideLimitationSQL ?? "distinct"; //select list is either [chi] or [chi],[mycolumn],[myexcitingcol] (in the case of a patient index table) builder = new AggregateBuilder(limitationSQL, selectList, aggregate, aggregate.ForcedJoins); //false makes it skip them in the SQL it generates (it uses them only in determining JOIN requirements etc but since we passed in the select SQL explicitly it should be the equivellent of telling the query builder to generate a regular select if (!isJoinAggregate) { builder.AddColumn(extractionIdentifier, false); } else { builder.AddColumnRange(aggregate.AggregateDimensions.ToArray(), false); } } else { if (overrideSelectList != null) { throw new NotSupportedException("Cannot override Select list on aggregates that have HAVING / Count SQL configured in them"); } builder = new AggregateBuilder("distinct", aggregate.CountSQL, aggregate, aggregate.ForcedJoins); //add the extraction information and do group by it if (!isJoinAggregate) { builder.AddColumn(extractionIdentifier, true); } else { builder.AddColumnRange(aggregate.AggregateDimensions.ToArray(), true);//it's a joinable inception query (See JoinableCohortAggregateConfiguration) - these are allowed additional columns } builder.DoNotWriteOutOrderBy = true; } if (topX != -1) { builder.AggregateTopX = new SpontaneouslyInventedAggregateTopX(new MemoryRepository(), topX, AggregateTopXOrderByDirection.Descending, null); } AddJoinablesToBuilder(builder, aggregate, tabDepth); //set the where container builder.RootFilterContainer = aggregate.RootFilterContainer; string builderSqlVerbatimForCheckingAgainstCache = null; if (CacheServer != null) { builderSqlVerbatimForCheckingAgainstCache = GetSqlForBuilderForCheckingAgainstCache(builder); } //we will be harnessing the parameters via ImportAndElevate so do not add them to the SQL directly builder.DoNotWriteOutParameters = true; var builderSqlWithoutParameters = builder.SQL; //if we have caching if (CacheServer != null) { CachedAggregateConfigurationResultsManager manager = new CachedAggregateConfigurationResultsManager(CacheServer); var existingTable = manager.GetLatestResultsTable(aggregate, isJoinAggregate? AggregateOperation.JoinableInceptionQuery: AggregateOperation.IndexedExtractionIdentifierList, builderSqlVerbatimForCheckingAgainstCache); //if we have the answer already if (existingTable != null) { //reference the answer table CountOfCachedSubQueries++; toReturn += tabplusOne + CachedAggregateConfigurationResultsManager.CachingPrefix + aggregate.Name + @"*/" + Environment.NewLine; toReturn += tabplusOne + "select * from " + existingTable.GetFullyQualifiedName() + Environment.NewLine; return(toReturn); } //we do not have an uptodate answer available in the cache :( } //get the SQL from the builder (for the current configuration) - without parameters string currentBlock = builderSqlWithoutParameters; //import parameters unless caching was used Dictionary <string, string> renameOperations; ParameterManager.ImportAndElevateResolvedParametersFromSubquery(builder.ParameterManager, out renameOperations); //rename in the SQL too! foreach (KeyValuePair <string, string> kvp in renameOperations) { currentBlock = ParameterCreator.RenameParameterInSQL(currentBlock, kvp.Key, kvp.Value); } //tab in the current block toReturn += tabplusOne + currentBlock.Replace("\r\n", "\r\n" + tabplusOne); return(toReturn); }