/// <summary> /// The get data async. /// </summary> /// <param name="context"> /// The context. /// </param> /// <param name="multiPartQuery"> /// The multi part query. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> internal override IAsyncEnumerable <Row> GetRows(IInternalExecutionContext context, [NotNull] IMultiPartQuery multiPartQuery) { var fieldReplacer = GenericVisitor.Create((SourceFieldExpression e) => CustomExpression.MakeField(e.SourceName, e.FieldName, e.Type)); var query = multiPartQuery.WildcardAliases.Contains(this.alias) ? new Query( fieldReplacer.Visit(multiPartQuery.FilterExpression), multiPartQuery.OrderByExpressions.Select(o => new OrderByExpression(fieldReplacer.Visit(o.Expression), o.Ascending)), multiPartQuery.Count) : new Query( multiPartQuery.Fields.Where(f => f.SourceAlias == this.alias).Select(f => f.FieldName), fieldReplacer.Visit(multiPartQuery.FilterExpression), multiPartQuery.OrderByExpressions.Select(o => new OrderByExpression(fieldReplacer.Visit(o.Expression), o.Ascending)), multiPartQuery.Count); var rowBuilder = new RowBuilder(this.alias); return(context .CreateAsyncEnumerable(async() => (await this.selectPlan.ExecuteAsync(context)).QueryResults.First().Rows) .Select(rowBuilder.Attach) .Where(query.GetFilter(context)?.GetRowFilter()) .OrderBy(query.GetSortOrders(context))); }
/// <summary> /// The get rows. /// </summary> /// <param name="context"> /// The context. /// </param> /// <param name="multiPartQuery"> /// The multi-part query. /// </param> /// <returns> /// The <see cref="IAsyncEnumerable{Row}"/>. /// </returns> internal override IAsyncEnumerable <Row> GetRows([NotNull] IInternalExecutionContext context, [NotNull] IMultiPartQuery multiPartQuery) { var functionName = context.GetDisplayName(this.dataSource); var fieldReplacer = GenericVisitor.Create((SourceFieldExpression e) => CustomExpression.MakeField(e.SourceName, e.FieldName, e.Type)); var query = multiPartQuery.WildcardAliases.Contains(this.alias) ? new Query( fieldReplacer.Visit(multiPartQuery.FilterExpression), multiPartQuery.OrderByExpressions.Select(o => new OrderByExpression(fieldReplacer.Visit(o.Expression), o.Ascending)), multiPartQuery.Count) : new Query( multiPartQuery.Fields.Where(f => f.SourceAlias == this.alias).Select(f => f.FieldName), fieldReplacer.Visit(multiPartQuery.FilterExpression), multiPartQuery.OrderByExpressions.Select(o => new OrderByExpression(fieldReplacer.Visit(o.Expression), o.Ascending)), multiPartQuery.Count); Expression unsupportedFilters = null; IOrderByExpression[] unsupportedOrderByExpressions = null; // ReSharper disable once SuspiciousTypeConversion.Global, implemented in other assemblies. var expressionSupport = this.dataSource as IDataSourceFilterSupport; if (expressionSupport != null) { var parts = query.FilterExpression.SplitByAndExpressions().Cast <CompareExpression>().ToArray(); var filters = parts.ToLookup(p => expressionSupport.SupportsExpression(p), e => (Expression)e); var supportedFilter = filters[true].DefaultIfEmpty().Aggregate(Expression.AndAlso); unsupportedFilters = filters[false].DefaultIfEmpty().Aggregate(Expression.AndAlso); if (!query.RetrieveAllFields) { query = new Query(query.Fields.Concat(unsupportedFilters.GetFields().Select(u => u.FieldName)).Distinct(), supportedFilter, query.OrderByExpressions, query.Count); } if (unsupportedFilters != null) { context.Logger.Warning($"Data source {functionName} {this.alias} has unsupported filter {unsupportedFilters}. This could impact performance."); } } // ReSharper disable once SuspiciousTypeConversion.Global, implemented in other assemblies. var orderBySupport = this.dataSource as IDataSourceOrderBySupport; if (orderBySupport != null && !orderBySupport.SupportsOrderBy(query.OrderByExpressions)) { unsupportedOrderByExpressions = query.OrderByExpressions.ToArray(); if (!query.RetrieveAllFields) { query = new Query(query.Fields.Concat(unsupportedOrderByExpressions.SelectMany(e => e.Expression.GetFields().Select(f => f.FieldName))).Distinct(), query.FilterExpression, null, query.Count); } context.Logger.Warning($"Data source {functionName} {this.alias} has unsupported ORDER BY {string.Join(", ", unsupportedOrderByExpressions.Select(u => u.Expression + " " + (u.Ascending ? "ASC" : "DESC")))}. This could impact performance."); } var sourceName = functionName + (query.FilterExpression == null ? string.Empty : $" with query '{query.FilterExpression}'"); context.Logger.Verbose($"Retrieving data from {sourceName}."); try { var result = this.dataSource.GetRows(context, new RowBuilder(this.alias), query).AfterLastElement(count => context.Logger.Verbose($"Retrieved {count} items from {sourceName}.")); if (unsupportedFilters != null) { result = result.Where(unsupportedFilters.GetRowFilter()); } if (unsupportedOrderByExpressions != null) { result.OrderBy(unsupportedOrderByExpressions); } return(result); } catch (Exception e) { context.Logger.Error($"An error occurred while querying {sourceName}: {e.Message}."); return(context.CreateEmptyAsyncEnumerable <Row>()); } }