示例#1
0
        /// <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)));
        }
示例#2
0
        /// <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>());
            }
        }