public ExecuteCommandAddCatalogueToCohortIdentificationSetContainer(IBasicActivateItems activator, CatalogueCombineable catalogueCombineable, CohortAggregateContainer targetCohortAggregateContainer) : this(activator, targetCohortAggregateContainer) { _catalogueCombineable = catalogueCombineable; _targetCohortAggregateContainer = targetCohortAggregateContainer; UpdateIsImpossibleFor(catalogueCombineable); }
public void Remove(CohortAggregateContainer parent, CohortAggregateContainer child) { CatalogueRepository.Delete("DELETE FROM CohortAggregateSubContainer WHERE CohortAggregateContainer_ChildID = @CohortAggregateContainer_ChildID", new Dictionary <string, object> { { "CohortAggregateContainer_ChildID", child.ID } }); }
public void Container_Subcontainering() { var container = new CohortAggregateContainer(CatalogueRepository, SetOperation.UNION); var container2 = new CohortAggregateContainer(CatalogueRepository, SetOperation.INTERSECT); try { Assert.AreEqual(0, container.GetSubContainers().Length); Assert.AreEqual(0, container.GetSubContainers().Length); //set container to parent container.AddChild(container2); //container 1 should now contain container 2 Assert.AreEqual(1, container.GetSubContainers().Length); Assert.Contains(container2, container.GetSubContainers()); //container 2 should not have any children Assert.AreEqual(0, container2.GetSubContainers().Length); } finally { container.DeleteInDatabase(); //container 2 was contained within container 1 so should have also been deleted Assert.Throws <KeyNotFoundException>( () => CatalogueRepository.GetObjectByID <CohortAggregateContainer>(container2.ID)); } }
public ExecuteCommandUnMergeCohortIdentificationConfiguration(IBasicActivateItems activator, CohortAggregateContainer container) : base(activator) { _target = container; if (_target == null) { SetImpossible("No root container"); return; } if (!_target.IsRootContainer()) { SetImpossible("Only root containers can be unmerged"); return; } if (_target.GetAggregateConfigurations().Any()) { SetImpossible("Container must contain only subcontainers (i.e. no aggregate sets)"); return; } if (_target.GetSubContainers().Count() <= 1) { SetImpossible("Container must have 2 or more immediate subcontainers for unmerging"); return; } }
public void BuildFor(CohortAggregateContainer container, ParameterManager parameterManager) { ThrowIfAlreadyBuilt(); IsForContainer = true; _log.AppendLine("Starting Build for " + container); //gather dependencies foreach (var cohortSet in ChildProvider.GetAllChildrenRecursively(container).OfType <AggregateConfiguration>().Where(IsEnabled).OrderBy(ac => ac.Order)) { AddDependency(cohortSet); } if (!Dependencies.Any()) { throw new QueryBuildingException($"There are no AggregateConfigurations under the SET container '{container}'"); } LogDependencies(); BuildDependenciesSql(parameterManager.ParametersFoundSoFarInQueryGeneration[ParameterLevel.Global].ToArray()); MakeCacheDecision(); Sql = BuildSql(container, parameterManager); }
/// <summary> /// Rebuilds the CohortCompiler diagram which shows all the currently configured tasks /// </summary> /// <param name="cancelTasks"></param> private void RecreateAllTasks(bool cancelTasks = true) { if (cancelTasks) { Compiler.CancelAllTasks(false); } tlvConfiguration.ClearObjects(); tlvConfiguration.Enabled = true; _cic.CreateRootContainerIfNotExists(); //if there is no root container,create one _root = _cic.RootCohortAggregateContainer; _globals = _cic.GetAllParameters(); //Could have configured/unconfigured a joinable state foreach (var j in Compiler.Tasks.Keys.OfType <JoinableTask>()) { j.RefreshIsUsedState(); } try { tlvConfiguration.AddObject(new CohortIdentificationHeader()); tlvConfiguration.AddObject(new JoinableCollectionNode(_cic, _cic.GetAllJoinables())); tlvConfiguration.ExpandAll(); } catch (Exception e) { tlvConfiguration.Enabled = false; ExceptionViewer.Show("Failed to populate tree of Tasks", e); } }
public CohortAggregateContainerCommand(CohortAggregateContainer aggregateContainer) { AggregateContainer = aggregateContainer; AllSubContainersRecursively = AggregateContainer.GetAllSubContainersRecursively(); ParentContainerIfAny = AggregateContainer.GetParentContainerIfAny(); }
private CohortIdentificationConfiguration CreateCohortIdentificationConfiguration(ExtractionFilter inclusionFilter1) { //Create the top level configuration object var cic = new CohortIdentificationConfiguration(_repos.CatalogueRepository, "Tayside Lung Cancer Cohort"); //create a UNION container for Inclusion Criteria var container = new CohortAggregateContainer(_repos.CatalogueRepository, SetOperation.UNION); container.Name = "Inclusion Criteria"; container.SaveToDatabase(); cic.RootCohortAggregateContainer_ID = container.ID; cic.SaveToDatabase(); //Create a new cohort set to the 'Inclusion Criteria' based on the filters Catalogue var cata = inclusionFilter1.ExtractionInformation.CatalogueItem.Catalogue; var ac = cic.CreateNewEmptyConfigurationForCatalogue(cata, (a, b) => { throw new Exception("Problem encountered with chi column(s)"); }, false); container.AddChild(ac, 0); //Add the filter to the WHERE logic of the cohort set var whereContainer = new AggregateFilterContainer(_repos.CatalogueRepository, FilterContainerOperation.OR); ac.Name = "People with " + inclusionFilter1.Name; ac.RootFilterContainer_ID = whereContainer.ID; cic.EnsureNamingConvention(ac); //this will put cicx at the front and cause implicit SaveToDatabase FilterImporter filterImporter = new FilterImporter(new AggregateFilterFactory(_repos.CatalogueRepository), null); var cloneFilter = filterImporter.ImportFilter(inclusionFilter1, null); whereContainer.AddChild(cloneFilter); return(cic); }
public CohortQueryBuilder(CohortAggregateContainer c, IEnumerable <ISqlParameter> globals, ICoreChildProvider childProvider) : this(globals, childProvider) { //set ourselves up to run with the root container container = c; SetChildProviderIfNull(); }
public string DescribeProblem(CohortAggregateContainer container) { //if it's a root container don't check if (_childProvider.AllCohortIdentificationConfigurations.Any(c => c.RootCohortAggregateContainer_ID == container.ID)) { return(null); } //count children that are not disabled, there should be at least 2 var children = _childProvider.GetChildren(container); var enabledChildren = children.Where(o => !(o is IDisableable d) || !d.IsDisabled).ToArray(); if (enabledChildren.Length == 0) { return("Empty SET containers have no effect (and will be ignored)"); } if (enabledChildren.Length == 1) { return("SET container operations have no effect if there is only one child within"); } //are there any children with the same order in this container? if (children.OfType <IOrderable>().GroupBy(o => o.Order).Any(g => g.Count() > 1)) { return("Child order is ambiguous, show the Order column and reorder contents"); } return(null); }
public CohortAggregateContainer CreateCohortAggregateContainer(CohortAggregateContainer rootContainer) { var operation = GetSetOperation(); if (rootContainer.Operation != SetOperation.EXCEPT) { throw new ArgumentException("rootContainer"); } var container = new CohortAggregateContainer(_activator.RepositoryLocator.CatalogueRepository, operation); if (_isInclusionCriteria) { container.Order = 1; container.Name = operation + " - Inclusion Criteria"; } else { container.Order = 2; container.Name = operation + " - Exclusion Criteria"; } container.SaveToDatabase(); rootContainer.AddChild(container); return(container); }
private string WriteContainers(CohortAggregateContainer container, IQuerySyntaxHelper syntaxHelper, Dictionary <CohortQueryBuilderDependency, string> sqlDictionary, int tabs) { string sql = ""; //Things we need to output var toWriteOut = container.GetOrderedContents().Where(IsEnabled).ToArray(); if (toWriteOut.Any()) { sql += Environment.NewLine + TabIn("(", tabs) + Environment.NewLine; } else { throw new QueryBuildingException($"Container '{container}' is empty, Disable it if you don't want it run'"); } bool firstEntityWritten = false; foreach (IOrderable toWrite in toWriteOut) { if (firstEntityWritten) { sql += Environment.NewLine + TabIn(GetSetOperationSql(container.Operation, syntaxHelper.DatabaseType) + Environment.NewLine + Environment.NewLine, tabs); } if (toWrite is AggregateConfiguration) { sql += TabIn(sqlDictionary.Single(kvp => Equals(kvp.Key.CohortSet, toWrite)).Value, tabs); } if (toWrite is CohortAggregateContainer sub) { sql += WriteContainers(sub, syntaxHelper, sqlDictionary, tabs + 1); } //we have now written the first thing at this level of recursion - all others will need to be separated by the OPERATION e.g. UNION firstEntityWritten = true; if (StopContainerWhenYouReach != null && StopContainerWhenYouReach.Equals(toWrite)) { if (tabs != 0) { throw new NotSupportedException("Stopping prematurely only works when the aggregate to stop at is in the top level container"); } else { break; } } } //if we outputted anything if (toWriteOut.Any()) { sql += Environment.NewLine + TabIn(")", tabs) + Environment.NewLine; } return(sql); }
/// <summary> /// Adds all AggregateConfigurations and CohortAggregateContainers in the specified container or subcontainers. Passing addSubcontainerTasks false will still process the subcontainers /// but will only add AggregateConfigurations to the task list /// </summary> /// <param name="globals"></param> /// <param name="container"></param> /// <param name="addSubcontainerTasks">The root container is always added to the task list but you could skip subcontainer totals if all you care about is the final total for the cohort /// and you don't have a dependant UI etc. Passing false will add all joinables, subqueries etc and the root container (final answer for who is in cohort) only.</param> /// <returns></returns> public List <ICompileable> AddTasksRecursively(ISqlParameter[] globals, CohortAggregateContainer container, bool addSubcontainerTasks = true) { var toReturn = new List <ICompileable>(); //if it is the root container or we are adding tasks for all containers including subcontainers if (CohortIdentificationConfiguration.RootCohortAggregateContainer_ID == container.ID || addSubcontainerTasks) { toReturn.Add(AddTask(container, globals)); } foreach (IOrderable c in container.GetOrderedContents()) { var aggregateContainer = c as CohortAggregateContainer; var aggregate = c as AggregateConfiguration; if (aggregateContainer != null) { toReturn.AddRange(AddTasksRecursively(globals, aggregateContainer, addSubcontainerTasks)); } if (aggregate != null) { toReturn.Add(AddTask(aggregate, globals)); } } return(toReturn); }
public void Remove(CohortAggregateContainer parent, AggregateConfiguration child) { CatalogueRepository.Delete("DELETE FROM CohortAggregateContainer_AggregateConfiguration WHERE CohortAggregateContainer_ID = @CohortAggregateContainer_ID AND AggregateConfiguration_ID = @AggregateConfiguration_ID", new Dictionary <string, object> { { "CohortAggregateContainer_ID", parent.ID }, { "AggregateConfiguration_ID", child.ID } }); }
public void Add(CohortAggregateContainer parent, CohortAggregateContainer child) { CatalogueRepository.Insert("INSERT INTO CohortAggregateSubContainer(CohortAggregateContainer_ParentID,CohortAggregateContainer_ChildID) VALUES (@CohortAggregateContainer_ParentID, @CohortAggregateContainer_ChildID)", new Dictionary <string, object> { { "CohortAggregateContainer_ParentID", parent.ID }, { "CohortAggregateContainer_ChildID", child.ID } }); }
/// <summary> /// Asserts that the given <paramref name="container"/> ran successfully and fetched it's results from the cache (if any) with the /// given <paramref name="expectedCacheUsageCount"/> /// </summary> /// <param name="compiler"></param> /// <param name="container"></param> /// <param name="expectedCacheUsageCount">The amount you expect to be used of the cache e.g. "2/2" </param> private void AssertCacheUsed(CohortCompiler compiler, CohortAggregateContainer container, string expectedCacheUsageCount) { //cache should have been used var containerResult = compiler.Tasks.Single(t => t.Key is AggregationContainerTask c && c.Container.Equals(container)); Assert.AreEqual(CompilationState.Finished, containerResult.Key.State); Assert.AreEqual(expectedCacheUsageCount, containerResult.Key.GetCachedQueryUseCount()); }
private string BuildSql(CohortAggregateContainer container, ParameterManager parameterManager) { Dictionary <CohortQueryBuilderDependency, string> sqlDictionary; //if we are fully cached on everything if (Dependencies.All(d => d.SqlFullyCached != null)) { SetTargetServer(GetCacheServer(), "all dependencies are fully cached"); //run on the cache server //all are cached CountOfCachedSubQueries = CountOfSubQueries; sqlDictionary = Dependencies.ToDictionary(k => k, v => v.SqlFullyCached.Use(parameterManager)); //run the fully cached sql } else { string uncached = "CacheUsageDecision is " + CacheUsageDecision + " and the following were not cached:" + string.Join(Environment.NewLine, Dependencies.Where(d => d.SqlFullyCached == null)); switch (CacheUsageDecision) { case CacheUsage.MustUse: throw new QueryBuildingException( "Could not build final SQL because some queries are not fully cached and " + uncached); case CacheUsage.Opportunistic: //The cache and dataset are on the same server so run it SetTargetServer(DependenciesSingleServer.GetDistinctServer(), "not all dependencies are cached while " + uncached); CountOfCachedSubQueries = Dependencies.Count(d => d.SqlFullyCached != null); sqlDictionary = Dependencies.ToDictionary(k => k, v => v.SqlFullyCached?.Use(parameterManager) ?? v.SqlPartiallyCached?.Use(parameterManager) ?? v.SqlCacheless.Use(parameterManager)); //run the fully cached sql break; case CacheUsage.AllOrNothing: //It's not fully cached so we have to run it entirely uncached SetTargetServer(DependenciesSingleServer.GetDistinctServer(), "not all dependencies are cached while " + uncached); //cannot use any of the caches because it's all or nothing CountOfCachedSubQueries = 0; sqlDictionary = Dependencies.ToDictionary(k => k, v => v.SqlCacheless.Use(parameterManager)); //run the fully uncached sql break; default: throw new ArgumentOutOfRangeException(); } } return(WriteContainers(container, TargetServer.GetQuerySyntaxHelper(), sqlDictionary, 0)); }
public void Test_AggregateConfigurationOrder_MovingAggregatesBetweenContainers() { GetObjects(out Catalogue cata, out CohortIdentificationConfiguration cic); //we should be able to add it to root container var cmd = new ExecuteCommandAddCatalogueToCohortIdentificationSetContainer(ItemActivator, new CatalogueCommand(cata), cic.RootCohortAggregateContainer); cmd.Execute(); //create a subcontainer var subcontainer = new CohortAggregateContainer(Repository, SetOperation.INTERSECT); cic.RootCohortAggregateContainer.AddChild(subcontainer); //add the second ac to the subcontainer var cmd2 = new ExecuteCommandAddCatalogueToCohortIdentificationSetContainer(ItemActivator, new CatalogueCommand(cata), subcontainer); cmd2.Execute(); //should now look like this: //Root // INTERSECT // Ac2 // Ac 1 // var all = cic.RootCohortAggregateContainer.GetOrderedContents().ToArray(); var ac1 = (AggregateConfiguration)all[1]; var ac2 = (AggregateConfiguration)subcontainer.GetOrderedContents().Single(); var intersect = (CohortAggregateContainer)all[0]; Assert.AreEqual(0, intersect.Order); Assert.AreEqual(1, ac1.Order); Assert.AreEqual(0, ac2.Order); //now move the Ac2 to Root (problematic since both Ac 2 and the INTERSECT have Order 0 - in their own separate containers) var cmd3 = new ExecuteCommandMoveAggregateIntoContainer(ItemActivator, new AggregateConfigurationCommand(ac2), cic.RootCohortAggregateContainer); cmd3.Execute(); all = cic.RootCohortAggregateContainer.GetOrderedContents().ToArray(); //should now look like this //Root // Ac2 // INTERSECT (empty) // Ac 1 ac2 = (AggregateConfiguration)all[0]; intersect = (CohortAggregateContainer)all[1]; ac1 = (AggregateConfiguration)all[2]; Assert.AreEqual(0, ac2.Order); Assert.AreEqual(1, intersect.Order); Assert.AreEqual(2, ac1.Order); }
public AggregationContainerTask(CohortAggregateContainer container, CohortCompiler compiler) : base(compiler) { Container = container; SubContainers = Container.GetSubContainers(); ContainedConfigurations = Container.GetAggregateConfigurations(); _parentContainers = Container.GetAllParentContainers().ToArray(); }
public ExecuteCommandAddCohortSubContainer(IBasicActivateItems activator, CohortAggregateContainer container) : base(activator) { this._container = container; if (container.ShouldBeReadOnly(out string reason)) { SetImpossible(reason); } }
/// <summary> /// Returns cached answers without running database queries /// </summary> /// <param name="parent"></param> /// <returns></returns> public override IOrderable[] GetChildren(CohortAggregateContainer parent) { if (_contents.ContainsKey(parent.ID)) { return(_contents[parent.ID].ToArray()); } return(new IOrderable[0]); }
public override void Execute() { base.Execute(); var newContainer = new CohortAggregateContainer(Activator.RepositoryLocator.CatalogueRepository, SetOperation.UNION); _container.AddChild(newContainer); Publish(_container); }
public CohortAggregateContainer GetParent(CohortAggregateContainer child) { return(CatalogueRepository.SelectAllWhere <CohortAggregateContainer>("SELECT CohortAggregateContainer_ParentID FROM CohortAggregateSubContainer WHERE CohortAggregateContainer_ChildID=@CohortAggregateContainer_ChildID", "CohortAggregateContainer_ParentID", new Dictionary <string, object> { { "CohortAggregateContainer_ChildID", child.ID } }).SingleOrDefault()); }
private ExecuteCommandAddAggregateConfigurationToCohortIdentificationSetContainer(IBasicActivateItems activator, CohortAggregateContainer targetCohortAggregateContainer) : base(activator) { _targetCohortAggregateContainer = targetCohortAggregateContainer; if (targetCohortAggregateContainer.ShouldBeReadOnly(out string reason)) { SetImpossible(reason); } }
public ExecuteCommandAddCatalogueToCohortIdentificationSetContainer(IActivateItems activator, CatalogueCommand catalogueCommand, CohortAggregateContainer targetCohortAggregateContainer) : base(activator) { _catalogueCommand = catalogueCommand; _targetCohortAggregateContainer = targetCohortAggregateContainer; if (!catalogueCommand.ContainsAtLeastOneExtractionIdentifier) { SetImpossible("Catalogue " + catalogueCommand.Catalogue + " does not contain any IsExtractionIdentifier columns"); } }
public AggregationContainerTask(CohortAggregateContainer container, CohortCompiler compiler) : base(compiler) { Container = container; SubContainers = compiler.CoreChildProvider.GetChildren(Container).OfType <CohortAggregateContainer>().ToArray(); ContainedConfigurations = compiler.CoreChildProvider.GetChildren(Container).OfType <AggregateConfiguration>().ToArray(); var d = compiler.CoreChildProvider.GetDescendancyListIfAnyFor(Container); _parentContainers = d?.Parents?.OfType <CohortAggregateContainer>()?.ToArray() ?? new CohortAggregateContainer[0]; }
public ExecuteCommandReOrderAggregate(IActivateItems activator, AggregateConfigurationCombineable sourceAggregateCommand, CohortAggregateContainer targetCohortAggregateContainer, InsertOption insertOption) : this(activator, targetCohortAggregateContainer, insertOption) { _sourceAggregateCommand = sourceAggregateCommand; _parentContainer = targetCohortAggregateContainer.GetParentContainerIfAny(); if (!sourceAggregateCommand.ContainerIfAny.Equals(_parentContainer)) { SetImpossible("Cannot ReOrder, you should first move both objects into the same container (UNION / EXCEPT / INTERSECT)"); return; } }
/// <summary> /// Creates a new AggregateConfiguration based on the Catalogue and returns it as an AggregateConfigurationCommand, you should only use this method during EXECUTE as you do not /// want to be randomly creating these as the user waves an object around over the user interface trying to decide where to drop it. /// </summary> /// <param name="cohortAggregateContainer"></param> /// <param name="importMandatoryFilters"></param> /// <param name="caller"></param> /// <returns></returns> public AggregateConfigurationCommand GenerateAggregateConfigurationFor(CohortAggregateContainer cohortAggregateContainer, bool importMandatoryFilters = true, [CallerMemberName] string caller = null) { var cic = cohortAggregateContainer.GetCohortIdentificationConfiguration(); if (cic == null) { return(null); } return(GenerateAggregateConfigurationFor(cic, importMandatoryFilters)); }
public void Add(CohortAggregateContainer parent, AggregateConfiguration child, int order) { CatalogueRepository.Insert( "INSERT INTO CohortAggregateContainer_AggregateConfiguration (CohortAggregateContainer_ID, AggregateConfiguration_ID, [Order]) VALUES (@CohortAggregateContainer_ID, @AggregateConfiguration_ID, @Order)", new Dictionary <string, object> { { "CohortAggregateContainer_ID", parent.ID }, { "AggregateConfiguration_ID", child.ID }, { "Order", order } }); }
public ExecuteCommandReOrderAggregateContainer(IActivateItems activator, CohortAggregateContainerCombineable sourceCohortAggregateContainerCombineable, AggregateConfiguration targetAggregate, InsertOption insertOption) : this(activator, targetAggregate, insertOption) { _sourceCohortAggregateContainerCombineable = sourceCohortAggregateContainerCombineable; _targetParent = targetAggregate.GetCohortAggregateContainerIfAny(); //if they do not share the same parent container if (!_sourceCohortAggregateContainerCombineable.ParentContainerIfAny.Equals(_targetParent)) { SetImpossible("First move objects into the same parent container"); } }