Beispiel #1
0
        // Constructors

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="handlers">The handlers.</param>
        /// <param name="request">The request.</param>
        /// <param name="tableDescriptor">The table descriptor.</param>
        /// <param name="filterDataSource">The filter data source.</param>
        /// <param name="origin">The origin.</param>
        /// <param name="source">The source.</param>
        public SqlIncludeProvider(
            HandlerAccessor handlers, QueryRequest request,
            TemporaryTableDescriptor tableDescriptor, Func <IEnumerable <Tuple> > filterDataSource,
            IncludeProvider origin, ExecutableProvider source)
            : base(handlers, request, tableDescriptor, origin, new [] { source })
        {
            this.filterDataSource = filterDataSource;
            Initialize();
        }
        protected SqlExpression CreateIncludeViaComplexConditionExpression(
            IncludeProvider provider, Func <object> valueAccessor,
            IList <SqlExpression> sourceColumns, out QueryParameterBinding binding)
        {
            var filterTupleDescriptor = provider.FilteredColumnsExtractionTransform.Descriptor;
            var mappings = filterTupleDescriptor.Select(type => Driver.GetTypeMapping(type));

            binding = new QueryRowFilterParameterBinding(mappings, valueAccessor);
            var resultExpression = SqlDml.DynamicFilter(binding);

            resultExpression.Expressions.AddRange(provider.FilteredColumns.Select(index => sourceColumns[index]));
            return(resultExpression);
        }
        protected override Provider VisitInclude(IncludeProvider provider)
        {
            int sourceLength = provider.Source.Header.Length;

            mappings[provider.Source] = Merge(mappings[provider].Where(i => i < sourceLength), provider.FilteredColumns);
            var source = VisitCompilable(provider.Source);

            mappings[provider] = Merge(mappings[provider], mappings[provider.Source]);
            if (source == provider.Source)
            {
                return(provider);
            }
            var filteredColumns = provider.FilteredColumns.Select(el => mappings[provider].IndexOf(el)).ToArray();

            return(new IncludeProvider(source, provider.Algorithm, provider.IsInlined,
                                       provider.FilterDataSource, provider.ResultColumnName, filteredColumns));
        }
        protected SqlExpression CreateIncludeViaTemporaryTableExpression(
            IncludeProvider provider, IList <SqlExpression> sourceColumns,
            out TemporaryTableDescriptor tableDescriptor)
        {
            var filterTupleDescriptor = provider.FilteredColumnsExtractionTransform.Descriptor;
            var filteredColumns       = provider.FilteredColumns.Select(index => sourceColumns[index]).ToList();

            tableDescriptor = DomainHandler.TemporaryTableManager
                              .BuildDescriptor(Mapping, Guid.NewGuid().ToString(), filterTupleDescriptor);
            var filterQuery = tableDescriptor.QueryStatement.ShallowClone();
            var tableRef    = filterQuery.From;

            for (int i = 0; i < filterTupleDescriptor.Count; i++)
            {
                filterQuery.Where &= filteredColumns[i] == tableRef[i];
            }
            var resultExpression = SqlDml.Exists(filterQuery);

            return(resultExpression);
        }
Beispiel #5
0
 /// <summary>
 /// Compiles <see cref="IncludeProvider"/>.
 /// </summary>
 /// <param name="provider">Include provider.</param>
 protected abstract TResult VisitInclude(IncludeProvider provider);
        /// <inheritdoc/>
        protected override SqlProvider VisitInclude(IncludeProvider provider)
        {
            var                      source           = Compile(provider.Source);
            var                      resultQuery      = ExtractSqlSelect(provider, source);
            var                      sourceColumns    = ExtractColumnExpressions(resultQuery);
            var                      bindings         = source.Request.ParameterBindings;
            var                      filterDataSource = provider.FilterDataSource.CachingCompile();
            var                      requestOptions   = QueryRequestOptions.Empty;
            SqlExpression            resultExpression;
            TemporaryTableDescriptor tableDescriptor = null;
            QueryParameterBinding    extraBinding    = null;
            var                      algorithm       = provider.Algorithm;

            if (!temporaryTablesSupported)
            {
                algorithm = IncludeAlgorithm.ComplexCondition;
            }
            switch (algorithm)
            {
            case IncludeAlgorithm.Auto:
                var complexConditionExpression = CreateIncludeViaComplexConditionExpression(
                    provider, BuildRowFilterParameterAccessor(filterDataSource, true),
                    sourceColumns, out extraBinding);
                var temporaryTableExpression = CreateIncludeViaTemporaryTableExpression(
                    provider, sourceColumns, out tableDescriptor);
                resultExpression = SqlDml.Variant(extraBinding,
                                                  complexConditionExpression, temporaryTableExpression);
                anyTemporaryTablesRequired = true;
                break;

            case IncludeAlgorithm.ComplexCondition:
                resultExpression = CreateIncludeViaComplexConditionExpression(
                    provider, BuildRowFilterParameterAccessor(filterDataSource, false),
                    sourceColumns, out extraBinding);
                if (!anyTemporaryTablesRequired)
                {
                    requestOptions |= QueryRequestOptions.AllowOptimization;
                }
                break;

            case IncludeAlgorithm.TemporaryTable:
                resultExpression = CreateIncludeViaTemporaryTableExpression(
                    provider, sourceColumns, out tableDescriptor);
                anyTemporaryTablesRequired = true;
                break;

            default:
                throw new ArgumentOutOfRangeException("provider.Algorithm");
            }
            resultExpression = GetBooleanColumnExpression(resultExpression);
            var calculatedColumn = provider.Header.Columns[provider.Header.Length - 1];

            AddInlinableColumn(provider, calculatedColumn, resultQuery, resultExpression);
            if (extraBinding != null)
            {
                bindings = bindings.Concat(EnumerableUtils.One(extraBinding));
            }
            var request = CreateQueryRequest(Driver, resultQuery, bindings, provider.Header.TupleDescriptor, requestOptions);

            return(new SqlIncludeProvider(Handlers, request, tableDescriptor, filterDataSource, provider, source));
        }