Пример #1
0
    protected internal override Expression VisitProjection(ProjectionExpression proj)
    {
        using (Scope())
        {
            var oldOuterMostSelect = outerMostSelect;
            outerMostSelect = proj.Select;

            var oldHasProjectionInProjector = hasProjectionInProjector;
            hasProjectionInProjector = false;

            Expression       projector = this.Visit(proj.Projector);
            SelectExpression source    = (SelectExpression)this.Visit(proj.Select);

            hasProjectionInProjector  = oldHasProjectionInProjector;
            hasProjectionInProjector |= true;

            outerMostSelect = oldOuterMostSelect;


            if (source != proj.Select || projector != proj.Projector)
            {
                return(new ProjectionExpression(source, projector, proj.UniqueFunction, proj.Type));
            }

            return(proj);
        }
    }
Пример #2
0
    protected internal override Expression VisitProjection(ProjectionExpression proj)
    {
        var oldCg     = this.cg;
        var oldSelect = this.currentSelect;

        try
        {
            var s = this.currentSelect = proj.Select;

            Expression projector = this.Visit(proj.Projector);


            SelectExpression source = this.cg == null ? proj.Select :
                                      new SelectExpression(s.Alias, s.IsDistinct, s.Top, this.cg.Columns.NotNull(), s.From, s.Where, s.OrderBy, s.GroupBy, s.SelectOptions);

            if (source != proj.Select || projector != proj.Projector)
            {
                return(new ProjectionExpression(source, projector, proj.UniqueFunction, proj.Type));
            }

            return(proj);
        }
        finally
        {
            this.cg            = oldCg;
            this.currentSelect = oldSelect;
        }
    }
        internal static bool IsNameMapProjection(SelectExpression select)
        {
            if (select.From is TableExpression)
            {
                return(false);
            }
            SelectExpression?fromSelect = select.From as SelectExpression;

            if (fromSelect == null || select.Columns.Count != fromSelect.Columns.Count)
            {
                return(false);
            }
            ReadOnlyCollection <ColumnDeclaration> fromColumns = fromSelect.Columns;

            // test that all columns in 'select' are refering to columns in the same position
            // in from.
            for (int i = 0, n = select.Columns.Count; i < n; i++)
            {
                ColumnExpression?col = select.Columns[i].Expression as ColumnExpression;
                if (col == null || !(col.Name == fromColumns[i].Name))
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #4
0
 private InExpression(
     SqlExpression item,
     SqlExpression?values,
     SelectExpression?subquery,
     bool negated,
     RelationalTypeMapping?typeMapping)
     : base(typeof(bool), typeMapping)
 {
     Item      = item;
     Subquery  = subquery;
     Values    = values;
     IsNegated = negated;
 }
Пример #5
0
        public virtual InExpression Update(
            [NotNull] SqlExpression item,
            [CanBeNull] SqlExpression?values,
            [CanBeNull] SelectExpression?subquery)
        {
            Check.NotNull(item, nameof(item));

            if (values != null &&
                subquery != null)
            {
                throw new ArgumentException(RelationalStrings.EitherOfTwoValuesMustBeNull(nameof(values), nameof(subquery)));
            }

            return(item != Item || subquery != Subquery || values != Values
                ? new InExpression(item, values, subquery, IsNegated, TypeMapping)
                : this);
        }
Пример #6
0
    private InExpression(
        SqlExpression item,
        SqlExpression?values,
        SelectExpression?subquery,
        bool negated,
        RelationalTypeMapping?typeMapping)
        : base(typeof(bool), typeMapping)
    {
#if DEBUG
        if (subquery?.IsMutable() == true)
        {
            throw new InvalidOperationException();
        }
#endif
        Item      = item;
        Subquery  = subquery;
        Values    = values;
        IsNegated = negated;
    }
Пример #7
0
        public static string ToQueryString <TEntity>(
            this IQueryable <TEntity> query)
            where TEntity : class
        {
            IEnumerator <TEntity>?enumerator = query
                                               .Provider
                                               .Execute <IEnumerable <TEntity> >(query.Expression)
                                               .GetEnumerator();

            var relationalCommandCache = enumerator.Private("_relationalCommandCache");

            SelectExpression?selectExpression = relationalCommandCache
                                                .Private <SelectExpression>("_selectExpression");

            IQuerySqlGeneratorFactory?factory = relationalCommandCache
                                                .Private <IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");

            QuerySqlGenerator? sqlGenerator = factory.Create();
            IRelationalCommand?command      = sqlGenerator.GetCommand(selectExpression);

            return(command.CommandText);
        }
Пример #8
0
 public SelectExpression?Remap(SelectExpression?sqlExpression)
 => (SelectExpression?)Visit(sqlExpression);
Пример #9
0
    protected internal override Expression VisitSelect(SelectExpression select)
    {
        bool isOuterMost = select == outerMostSelect;

        if (select.IsOrderAlsoByKeys || select.HasIndex || select.Top != null && hasProjectionInProjector)
        {
            if (gatheredKeys == null)
            {
                gatheredKeys = new List <ColumnExpression>();
            }
        }

        List <ColumnExpression>?savedKeys = null;

        if (gatheredKeys != null && (select.IsDistinct || select.GroupBy.HasItems() || select.IsAllAggregates))
        {
            savedKeys = gatheredKeys.ToList();
        }

        if ((AggregateFinder.GetAggregates(select.Columns)?.Any(a => a.AggregateFunction.OrderMatters()) ?? false) && select.From is SelectExpression from)
        {
            var oldOuterMostSelect = outerMostSelect;
            outerMostSelect = from;

            select = (SelectExpression)base.VisitSelect(select);

            outerMostSelect = oldOuterMostSelect;
        }
        else
        {
            select = (SelectExpression)base.VisitSelect(select);
        }


        if (savedKeys != null)
        {
            gatheredKeys = savedKeys;
        }

        List <ColumnDeclaration>?newColumns = null;

        if (select.GroupBy.HasItems())
        {
            gatheredOrderings = null;

            if (gatheredKeys != null)
            {
                ColumnGenerator cg = new ColumnGenerator(select.Columns);

                var newKeys = new List <ColumnDeclaration>();

                foreach (var ge in select.GroupBy)
                {
                    var cd = cg.Columns.NotNull().FirstOrDefault(a => DbExpressionComparer.AreEqual(a.Expression, ge));

                    if (cd != null)
                    {
                        newKeys.Add(cd);
                    }
                    else
                    {
                        newKeys.Add(cg.NewColumn(ge));
                    }
                }

                if (cg.Columns.Count() != select.Columns.Count)
                {
                    newColumns = cg.Columns.NotNull().ToList();
                }

                gatheredKeys.AddRange(newKeys.Select(cd => new ColumnExpression(cd.Expression.Type, select.Alias, cd.Name)));
            }
        }

        if (select.IsAllAggregates)
        {
            if (gatheredKeys != null)
            {
                gatheredKeys.AddRange(select.Columns.Select(cd => new ColumnExpression(cd.Expression.Type, select.Alias, cd.Name)));
            }
        }

        if (select.IsDistinct)
        {
            gatheredOrderings = null;

            if (gatheredKeys != null)
            {
                gatheredKeys.AddRange(select.Columns.Select(cd => cd.GetReference(select.Alias)));
            }
        }

        if (select.IsReverse && !gatheredOrderings.IsNullOrEmpty())
        {
            gatheredOrderings = gatheredOrderings.Select(o => new OrderExpression(
                                                             o.OrderType == OrderType.Ascending ? OrderType.Descending : OrderType.Ascending,
                                                             o.Expression)).ToReadOnly();
        }

        if (select.OrderBy.Count > 0)
        {
            this.PrependOrderings(select.OrderBy);
        }

        ReadOnlyCollection <OrderExpression>?orderings = null;

        if (isOuterMost && !IsCountSumOrAvg(select) || select.Top != null)
        {
            AppendKeys();

            orderings         = gatheredOrderings;
            gatheredOrderings = null;
        }

        if (AreEqual(select.OrderBy, orderings) && !select.IsReverse && newColumns == null)
        {
            return(select);
        }

        return(new SelectExpression(select.Alias, select.IsDistinct, select.Top, (IEnumerable <ColumnDeclaration>?)newColumns ?? select.Columns,
                                    select.From, select.Where, orderings, select.GroupBy, select.SelectOptions & ~SelectOptions.Reverse));
    }
Пример #10
0
        protected internal override Expression VisitProjection(ProjectionExpression proj)
        {
            if (currentSource == null)
            {
                currentSource = WithoutOrder(proj.Select);

                Expression projector = this.Visit(proj.Projector);

                if (projector != proj.Projector)
                {
                    proj = new ProjectionExpression(proj.Select, projector, proj.UniqueFunction, proj.Type);
                }

                currentSource = null;
                return(proj);
            }
            else
            {
                HashSet <ColumnExpression> columns = ExternalColumnGatherer.Gatherer(proj, currentSource.Alias);

                if (columns.Count == 0)
                {
                    Expression projector = Visit(proj.Projector);

                    ConstantExpression key   = Expression.Constant(0);
                    Type            kvpType  = typeof(KeyValuePair <,>).MakeGenericType(key.Type, projector.Type);
                    ConstructorInfo ciKVP    = kvpType.GetConstructor(new[] { key.Type, projector.Type }) !;
                    Type            projType = proj.UniqueFunction == null ? typeof(IEnumerable <>).MakeGenericType(kvpType) : kvpType;

                    var childProj = new ProjectionExpression(proj.Select,
                                                             Expression.New(ciKVP, key, projector), proj.UniqueFunction, projType);

                    return(new ChildProjectionExpression(childProj,
                                                         Expression.Constant(0), inMList != null, inMList ?? proj.Type, new LookupToken()));
                }
                else
                {
                    SelectExpression external;
                    IEnumerable <ColumnExpression> externalColumns;

                    if (!IsKey(currentSource, columns))
                    {
                        Alias           aliasDistinct     = aliasGenerator.GetUniqueAlias(currentSource.Alias.Name + "D");
                        ColumnGenerator generatorDistinct = new ColumnGenerator();

                        List <ColumnDeclaration> columnDistinct = columns.Select(ce => generatorDistinct.MapColumn(ce)).ToList();
                        external = new SelectExpression(aliasDistinct, true, null, columnDistinct, currentSource, null, null, null, 0);


                        Dictionary <ColumnExpression, ColumnExpression> distinctReplacements = columnDistinct.ToDictionary(
                            cd => (ColumnExpression)cd.Expression,
                            cd => cd.GetReference(aliasDistinct));

                        proj = (ProjectionExpression)ColumnReplacer.Replace(proj, distinctReplacements);

                        externalColumns = distinctReplacements.Values.ToHashSet();
                    }
                    else
                    {
                        external        = currentSource;
                        externalColumns = columns;
                    }

                    ColumnGenerator          generatorSM       = new ColumnGenerator();
                    List <ColumnDeclaration> columnsSMExternal = externalColumns.Select(ce => generatorSM.MapColumn(ce)).ToList();
                    List <ColumnDeclaration> columnsSMInternal = proj.Select.Columns.Select(cd => generatorSM.MapColumn(cd.GetReference(proj.Select.Alias))).ToList();

                    SelectExpression @internal = ExtractOrders(proj.Select, out List <OrderExpression>?innerOrders);

                    Alias            aliasSM    = aliasGenerator.GetUniqueAlias(@internal.Alias.Name + "SM");
                    SelectExpression selectMany = new SelectExpression(aliasSM, false, null, columnsSMExternal.Concat(columnsSMInternal),
                                                                       new JoinExpression(JoinType.CrossApply,
                                                                                          external,
                                                                                          @internal, null), null, innerOrders, null, 0);

                    SelectExpression old = currentSource;
                    currentSource = WithoutOrder(selectMany);

                    var selectManyReplacements = selectMany.Columns.ToDictionary(
                        cd => (ColumnExpression)cd.Expression,
                        cd => cd.GetReference(aliasSM));

                    Expression projector = ColumnReplacer.Replace(proj.Projector, selectManyReplacements);

                    projector = Visit(projector);

                    currentSource = old;

                    Expression      key      = TupleReflection.TupleChainConstructor(columnsSMExternal.Select(cd => MakeEquatable(cd.GetReference(aliasSM))));
                    Type            kvpType  = typeof(KeyValuePair <,>).MakeGenericType(key.Type, projector.Type);
                    ConstructorInfo ciKVP    = kvpType.GetConstructor(new[] { key.Type, projector.Type }) !;
                    Type            projType = proj.UniqueFunction == null ? typeof(IEnumerable <>).MakeGenericType(kvpType) : kvpType;

                    var childProj = new ProjectionExpression(selectMany,
                                                             Expression.New(ciKVP, key, projector), proj.UniqueFunction, projType);

                    return(new ChildProjectionExpression(childProj,
                                                         TupleReflection.TupleChainConstructor(columns.Select(a => MakeEquatable(a))), inMList != null, inMList ?? proj.Type, new LookupToken()));
                }
            }
        }
Пример #11
0
 protected SubqueryExpression(DbExpressionType nodeType, Type type, SelectExpression?select)
     : base(nodeType, type)
 {
     System.Diagnostics.Debug.Assert(nodeType == DbExpressionType.Scalar || nodeType == DbExpressionType.Exists || nodeType == DbExpressionType.In);
     this.Select = select;
 }