/// <summary> /// Executes the specified view /// </summary> public BisResultContext ExecuteView(BiViewDefinition viewDef, IDictionary <string, object> parameters, int offset, int?count) { viewDef = BiUtils.ResolveRefs(viewDef) as BiViewDefinition; var retVal = this.ExecuteQuery(viewDef.Query, parameters, viewDef.AggregationDefinitions?.ToArray(), offset, count); if (viewDef.Pivot != null) { retVal = ApplicationServiceContext.Current.GetService <IBiPivotProvider>().Pivot(retVal, viewDef.Pivot); } return(retVal); }
/// <summary> /// Execute the specified view /// </summary> public BisResultContext ExecuteView(BiViewDefinition viewDef, IDictionary <string, object> parameters, int offset, int?count) { try { var parmDict = parameters.ToDictionary(o => o.Key, o => o.Value); if (!parmDict.ContainsKey("_count")) { parmDict.Add("_count", count); } if (!parmDict.ContainsKey("_offset")) { parmDict.Add("_offset", offset); } var startTime = DateTime.Now; using (var client = this.GetRestClient()) { var results = client.Get <IEnumerable <dynamic> >($"Query/{viewDef.Id}", parameters.ToArray()); return(new BisResultContext(viewDef.Query, parameters, this, results, startTime)); } } catch (System.Net.WebException e) { var wr = e.Response as HttpWebResponse; this.m_tracer.TraceWarning("Remote service indicated failure: {0}", e); if (wr?.StatusCode == HttpStatusCode.NotFound) { throw new KeyNotFoundException($"Could not find definition with id {viewDef.Id}", e); } else { throw new Exception($"Error fetching BIS definition {viewDef.Id }", e); } } catch (Exception e) { this.m_tracer.TraceError($"Error executing BIS query {viewDef.Name} - {e}"); throw new Exception($"Error executing BIS query {viewDef.Name}", e); throw; } }
/// <summary> /// Hydrate the query /// </summary> /// <param name="queryId"></param> /// <returns></returns> private BisResultContext HydrateQuery(String queryId) { AuditData audit = new AuditData(DateTimeOffset.Now, ActionType.Execute, OutcomeIndicator.Success, EventIdentifierType.Query, AuditUtil.CreateAuditActionCode(EventTypeCodes.SecondaryUseQuery)); try { // First we want to grab the appropriate source for this ID var viewDef = this.m_metadataRepository.Get <BiViewDefinition>(queryId); if (viewDef == null) { var queryDef = this.m_metadataRepository.Get <BiQueryDefinition>(queryId); if (queryDef == null) // Parameter value { var parmDef = this.m_metadataRepository.Get <BiParameterDefinition>(queryId); if (parmDef == null) { throw new KeyNotFoundException($"Could not find a Parameter, Query or View to hydrate named {queryId}"); } queryDef = parmDef?.Values as BiQueryDefinition; queryDef.Id = queryDef.Id ?? queryId; } viewDef = new BiViewDefinition() { Id = queryDef.Id, Query = queryDef }; } viewDef = SanteDB.BI.Util.BiUtils.ResolveRefs(viewDef) as BiViewDefinition; var dsource = viewDef.Query?.DataSources.FirstOrDefault(o => o.Name == "main") ?? viewDef.Query?.DataSources.FirstOrDefault(); if (dsource == null) { throw new KeyNotFoundException("Query does not contain a data source"); } IBiDataSource providerImplementation = null; if (dsource.ProviderType != null && this.m_metadataRepository.IsLocal) { providerImplementation = this.m_serviceManager.CreateInjected(dsource.ProviderType) as IBiDataSource; } else { providerImplementation = ApplicationServiceContext.Current.GetService <IBiDataSource>(); // Global default } // Populate data about the query audit.AuditableObjects.Add(new AuditableObject() { IDTypeCode = AuditableObjectIdType.ReportNumber, LifecycleType = AuditableObjectLifecycle.Report, ObjectId = queryId, QueryData = RestOperationContext.Current.IncomingRequest.Url.Query, Role = AuditableObjectRole.Query, Type = AuditableObjectType.SystemObject }); var parameters = this.CreateParameterDictionary(); // Aggregations and groups? if (RestOperationContext.Current.IncomingRequest.QueryString["_groupBy"] != null) { var aggRx = new Regex(@"(\w*)\((.*?)\)"); viewDef.AggregationDefinitions = new List <BiAggregationDefinition>() { new BiAggregationDefinition() { Groupings = RestOperationContext.Current.IncomingRequest.QueryString.GetValues("_groupBy").Select(o => new BiSqlColumnReference() { ColumnSelector = o.Contains("::") ? $"CAST({o.Substring(0, o.IndexOf(":"))} AS {o.Substring(o.IndexOf(":") + 2)})" : o, Name = o.Contains("::") ? o.Substring(0, o.IndexOf(":")) : o }).ToList(), Columns = RestOperationContext.Current.IncomingRequest.QueryString.GetValues("_select").Select(o => { var match = aggRx.Match(o); if (!match.Success) { throw new InvalidOperationException("Aggregation function must be in format AGGREGATOR(COLUMN)"); } return(new BiAggregateSqlColumnReference() { Aggregation = (BiAggregateFunction)Enum.Parse(typeof(BiAggregateFunction), match.Groups[1].Value, true), ColumnSelector = match.Groups[2].Value, Name = match.Groups[2].Value }); }).ToList() } }; } int offset = 0, count = 100; if (!Int32.TryParse(RestOperationContext.Current.IncomingRequest.QueryString["_offset"] ?? "0", out offset)) { throw new FormatException("_offset is not in the correct format"); } if (!Int32.TryParse(RestOperationContext.Current.IncomingRequest.QueryString["_count"] ?? "100", out count)) { throw new FormatException("_count is not in the correct format"); } var queryData = providerImplementation.ExecuteView(viewDef, parameters, offset, count); return(queryData); } catch (KeyNotFoundException) { audit.Outcome = OutcomeIndicator.MinorFail; throw; } catch (Exception e) { audit.Outcome = OutcomeIndicator.MinorFail; this.m_tracer.TraceError("Error rendering query: {0}", e); throw new FaultException(500, $"Error rendering query {queryId}", e); } finally { AuditUtil.AddLocalDeviceActor(audit); AuditUtil.AddUserActor(audit); AuditUtil.SendAudit(audit); } }