private string BuildSql(CohortQueryBuilderDependency dependency, ParameterManager parameterManager) { //if we are fully cached on everything if (dependency.SqlFullyCached != null) { SetTargetServer(GetCacheServer(), " dependency is cached"); //run on the cache server CountOfCachedSubQueries++; //it is cached return(dependency.SqlFullyCached.Use(parameterManager)); //run the fully cached sql } switch (CacheUsageDecision) { case CacheUsage.MustUse: throw new QueryBuildingException("Could not build final SQL because " + dependency + " is not fully cached and CacheUsageDecision is " + CacheUsageDecision); case CacheUsage.Opportunistic: //The cache and dataset are on the same server so run it SetTargetServer(DependenciesSingleServer.GetDistinctServer(), "data and cache are on the same server"); return(dependency.SqlPartiallyCached?.Use(parameterManager) ?? dependency.SqlCacheless.Use(parameterManager)); case CacheUsage.AllOrNothing: //It's not fully cached so we have to run it entirely uncached SetTargetServer(DependenciesSingleServer.GetDistinctServer(), "cache and data are on seperate servers / access credentials and not all datasets are in the cache"); return(dependency.SqlCacheless.Use(parameterManager)); default: throw new ArgumentOutOfRangeException(); } }
private CohortQueryBuilderDependency AddDependency(AggregateConfiguration cohortSet) { if (cohortSet.Catalogue.IsApiCall()) { if (CacheManager == null) { throw new Exception($"Caching must be enabled to execute API call '{cohortSet}'"); } if (!PluginCohortCompilers.Any(c => c.ShouldRun(cohortSet))) { throw new Exception($"No PluginCohortCompilers claimed to support '{cohortSet}' in their ShouldRun method"); } } var join = ChildProvider.AllJoinUses.Where(j => j.AggregateConfiguration_ID == cohortSet.ID).ToArray(); if (join.Length > 1) { throw new NotSupportedException($"There are {join.Length} joins configured to AggregateConfiguration {cohortSet}"); } var d = new CohortQueryBuilderDependency(cohortSet, join.SingleOrDefault(), ChildProvider, PluginCohortCompilers); _dependencies.Add(d); return(d); }
private void HandleDependency(CohortQueryBuilderDependency dependency, bool isPatientIndexTable, ITableInfo dependantTable) { _log.AppendLine($"Found dependant table '{dependantTable}' (Server:{dependantTable.Server} DatabaseType:{dependantTable.DatabaseType})"); //if dependencies are on different servers / access credentials if (DependenciesSingleServer != null) { if (!DependenciesSingleServer.TryAdd(dependantTable)) { //we can no longer establish a consistent connection to all the dependencies _log.AppendLine($"Found problematic dependant table '{dependantTable}'"); //if there's no cache server that's a problem! if (CacheServer == null) { throw new QueryBuildingException($"Table {dependantTable} is on a different server (or uses different access credentials) from previously seen dependencies and no QueryCache is configured"); } //there is a cache server, perhaps we can dodge 'dependantTable' by going to cache instead bool canUseCacheForDependantTable = (isPatientIndexTable ? dependency.SqlJoinableCached : dependency.SqlFullyCached) != null; //can we go to the cache server instead? if (canUseCacheForDependantTable && DependenciesSingleServer.TryAdd(CacheServer)) { _log.AppendLine($"Avoided problematic dependant table '{dependantTable}' by using the cache"); } else { DependenciesSingleServer = null; //there IS a cache so we now Must use it if (CacheUsageDecision != CacheUsage.MustUse) { SetCacheUsage(CacheUsage.MustUse, $"Table {dependantTable} is on a different server (or uses different access credentials) from previously seen dependencies. Therefore the QueryCache MUST be used for all dependencies"); } } } } if (DependenciesSingleServer != null && CacheServer != null && CacheUsageDecision == CacheUsage.Opportunistic) { //We can only do opportunistic joins if the Cache and Data server are on the same server bool canCombine = DependenciesSingleServer.AddWouldBePossible(CacheServer); if (!canCombine) { SetCacheUsage(CacheUsage.AllOrNothing, "All datasets are on one server/access credentials while Cache is on a separate one"); } } }
private CohortQueryBuilderDependency AddDependency(AggregateConfiguration cohortSet) { var join = ChildProvider.AllJoinUses.Where(j => j.AggregateConfiguration_ID == cohortSet.ID).ToArray(); if (join.Length > 1) { throw new NotSupportedException($"There are {join.Length} joins configured to AggregateConfiguration {cohortSet}"); } var d = new CohortQueryBuilderDependency(cohortSet, join.SingleOrDefault(), ChildProvider); _dependencies.Add(d); return(d); }