public static DbSelectExpression RemoveColumn(this DbSelectExpression select, DbColumnDeclaration column)
        {
            List <DbColumnDeclaration> columns = new List <DbColumnDeclaration>(select.Columns);

            columns.Remove(column);
            return(select.SetColumns(columns));
        }
Пример #2
0
 public DbDeclaration(IEnumerable<DbVariableDeclaration> variables, 
     DbSelectExpression source)
     : base(DbExpressionType.Declaration, typeof(void))
 {
     _variables = variables.AsReadOnly();
     _source = source;
 }
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     Expression saveCurrentFrom = this.currentFrom;
     this.currentFrom = this.VisitSource(select.From);
     try
     {
         Expression where = this.Visit(select.Where);
         ReadOnlyCollection<DbOrderExpression> orderBy = this.VisitOrderBy(select.OrderBy);
         ReadOnlyCollection<Expression> groupBy = this.VisitExpressionList(select.GroupBy);
         Expression skip = this.Visit(select.Skip);
         Expression take = this.Visit(select.Take);
         ReadOnlyCollection<DbColumnDeclaration> columns = this.VisitColumnDeclarations(select.Columns);
         if (this.currentFrom != select.From
             || where != select.Where
             || orderBy != select.OrderBy
             || groupBy != select.GroupBy
             || take != select.Take
             || skip != select.Skip
             || columns != select.Columns
             )
         {
             return new DbSelectExpression(select.Alias, columns, this.currentFrom, where, orderBy, groupBy, select.IsDistinct, skip, take);
         }
         return select;
     }
     finally
     {
         this.currentFrom = saveCurrentFrom;
     }
 }
Пример #4
0
        internal static bool IsNameMapProjection(DbSelectExpression select)
        {
            if (select.From is DbTableExpression)
            {
                return(false);
            }
            DbSelectExpression fromSelect = select.From as DbSelectExpression;

            if (fromSelect == null || select.Columns.Count != fromSelect.Columns.Count)
            {
                return(false);
            }
            ReadOnlyCollection <DbColumnDeclaration> 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++)
            {
                DbColumnExpression col = select.Columns[i].Expression as DbColumnExpression;
                if (col == null || !(col.Name == fromColumns[i].Name))
                {
                    return(false);
                }
            }
            return(true);
        }
        protected virtual bool CompareSelect(DbSelectExpression a, DbSelectExpression b)
        {
            ScopedDictionary <DbTableAlias, DbTableAlias> save = _aliasScope;

            try
            {
                if (!Compare(a.From, b.From))
                {
                    return(false);
                }

                _aliasScope = new ScopedDictionary <DbTableAlias, DbTableAlias>(save);
                MapAliases(a.From, b.From);

                return(Compare(a.Where, b.Where) &&
                       CompareOrderList(a.OrderBy, b.OrderBy) &&
                       CompareExpressionList(a.GroupBy, b.GroupBy) &&
                       Compare(a.Skip, b.Skip) &&
                       Compare(a.Take, b.Take) &&
                       a.IsDistinct == b.IsDistinct &&
                       CompareColumnDeclarations(a.Columns, b.Columns));
            }
            finally
            {
                _aliasScope = save;
            }
        }
Пример #6
0
        protected override Expression VisitProjection(DbProjectionExpression proj)
        {
            // don't parameterize the projector or aggregator!
            DbSelectExpression select = (DbSelectExpression)this.Visit(proj.Select);

            return(this.UpdateProjection(proj, select, proj.Projector, proj.Aggregator));
        }
Пример #7
0
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            Expression saveCurrentFrom = this.currentFrom;

            this.currentFrom = this.VisitSource(select.From);
            try
            {
                Expression where = this.Visit(select.Where);
                ReadOnlyCollection <DbOrderExpression> orderBy = this.VisitOrderBy(select.OrderBy);
                ReadOnlyCollection <Expression>        groupBy = this.VisitExpressionList(select.GroupBy);
                Expression skip = this.Visit(select.Skip);
                Expression take = this.Visit(select.Take);
                ReadOnlyCollection <DbColumnDeclaration> columns = this.VisitColumnDeclarations(select.Columns);
                if (this.currentFrom != select.From ||
                    where != select.Where ||
                    orderBy != select.OrderBy ||
                    groupBy != select.GroupBy ||
                    take != select.Take ||
                    skip != select.Skip ||
                    columns != select.Columns
                    )
                {
                    return(new DbSelectExpression(select.Alias, columns, this.currentFrom, where, orderBy, groupBy, select.IsDistinct, skip, take));
                }
                return(select);
            }
            finally
            {
                this.currentFrom = saveCurrentFrom;
            }
        }
Пример #8
0
        protected virtual Expression VisitDeclaration(DbDeclaration decl)
        {
            ReadOnlyCollection <DbVariableDeclaration> variables = VisitVariableDeclarations(decl.Variables);
            DbSelectExpression source = (DbSelectExpression)Visit(decl.Source);

            return(UpdateDeclaration(decl, variables, source));
        }
Пример #9
0
        protected virtual Expression VisitProjection(DbProjectionExpression proj)
        {
            DbSelectExpression select    = (DbSelectExpression)Visit(proj.Select);
            Expression         projector = Visit(proj.Projector);

            return(UpdateProjection(proj, select, projector, proj.Aggregator));
        }
Пример #10
0
        internal static bool HasAggregates(DbSelectExpression expression)
        {
            AggregateChecker checker = new AggregateChecker();

            checker.Visit(expression);
            return(checker.hasAggregate);
        }
 private bool CanJoinOnClient(DbSelectExpression select)
 {
     // can add singleton (1:0,1) join if no grouping/aggregates or distinct
     return(!select.IsDistinct &&
            (select.GroupBy == null || select.GroupBy.Count == 0) &&
            !AggregateChecker.HasAggregates(select));
 }
Пример #12
0
 public DbDeclaration(IEnumerable <DbVariableDeclaration> variables,
                      DbSelectExpression source)
     : base(DbExpressionType.Declaration, typeof(void))
 {
     _variables = variables.AsReadOnly();
     _source    = source;
 }
Пример #13
0
        protected virtual Expression VisitIn(DbInExpression ixp)
        {
            Expression         expr   = Visit(ixp.Expression);
            DbSelectExpression select = (DbSelectExpression)Visit(ixp.Select);
            ReadOnlyCollection <Expression> values = VisitExpressionList(ixp.Values);

            return(UpdateIn(ixp, expr, select, values));
        }
 public static DbSelectExpression SetWhere(this DbSelectExpression select, Expression where)
 {
     if (where != select.Where)
     {
         return(new DbSelectExpression(select.Alias, select.Columns, select.From, where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take));
     }
     return(select);
 }
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     // only consider aggregates in these locations
     this.Visit(select.Where);
     this.VisitOrderBy(select.OrderBy);
     this.VisitColumnDeclarations(select.Columns);
     return select;
 }
Пример #16
0
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     DbTableAlias newAlias = new DbTableAlias();
     this.map[select.Alias] = newAlias;
     select = (DbSelectExpression)base.VisitSelect(select);
     return new DbSelectExpression(newAlias, select.Columns, select.From, select.Where, select.OrderBy, 
         select.GroupBy, select.IsDistinct, select.Skip, select.Take);
 }
Пример #17
0
        protected override Expression VisitProjection(DbProjectionExpression projection)
        {
            // visit mapping in reverse order
            Expression         projector = this.Visit(projection.Projector);
            DbSelectExpression select    = (DbSelectExpression)this.Visit(projection.Select);

            return(this.UpdateProjection(projection, select, projector, projection.Aggregator));
        }
Пример #18
0
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     // only consider aggregates in these locations
     this.Visit(select.Where);
     this.VisitOrderBy(select.OrderBy);
     this.VisitColumnDeclarations(select.Columns);
     return(select);
 }
Пример #19
0
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            bool saveIsOuterMostSelect = this.isOuterMostSelect;

            try
            {
                this.isOuterMostSelect = false;
                select = (DbSelectExpression)base.VisitSelect(select);

                bool hasOrderBy          = select.OrderBy != null && select.OrderBy.Count > 0;
                bool hasGroupBy          = select.GroupBy != null && select.GroupBy.Count > 0;
                bool canHaveOrderBy      = saveIsOuterMostSelect || select.Take != null || select.Skip != null;
                bool canReceiveOrderings = canHaveOrderBy && !hasGroupBy && !select.IsDistinct;

                if (hasOrderBy)
                {
                    this.PrependOrderings(select.OrderBy);
                }

                IEnumerable <DbOrderExpression> orderings = null;
                if (canReceiveOrderings)
                {
                    orderings = this.gatheredOrderings;
                }
                else if (canHaveOrderBy)
                {
                    orderings = select.OrderBy;
                }
                bool canPassOnOrderings = !saveIsOuterMostSelect && !hasGroupBy && !select.IsDistinct;
                ReadOnlyCollection <DbColumnDeclaration> columns = select.Columns;
                if (this.gatheredOrderings != null)
                {
                    if (canPassOnOrderings)
                    {
                        var producedAliases = DeclaredAliasGatherer.Gather(select.From);
                        // reproject order expressions using this select's alias so the outer select will have properly formed expressions
                        BindResult project = this.RebindOrderings(this.gatheredOrderings, select.Alias, producedAliases, select.Columns);
                        this.gatheredOrderings = null;
                        this.PrependOrderings(project.Orderings);
                        columns = project.Columns;
                    }
                    else
                    {
                        this.gatheredOrderings = null;
                    }
                }
                if (orderings != select.OrderBy || columns != select.Columns)
                {
                    select = new DbSelectExpression(select.Alias, columns, select.From, select.Where, orderings, select.GroupBy, select.IsDistinct, select.Skip, select.Take);
                }
                return(select);
            }
            finally
            {
                this.isOuterMostSelect = saveIsOuterMostSelect;
            }
        }
        protected override Expression VisitProjection(DbProjectionExpression proj)
        {
            DbSelectExpression save = this.currentSelect;

            this.currentSelect = proj.Select;
            try
            {
                if (!this.isTopLevel)
                {
                    if (this.CanJoinOnClient(this.currentSelect))
                    {
                        // make a query that combines all the constraints from the outer queries into a single select
                        DbSelectExpression newOuterSelect = (DbSelectExpression)QueryDuplicator.Duplicate(save);

                        // remap any references to the outer select to the new alias;
                        DbSelectExpression newInnerSelect = (DbSelectExpression)ColumnMapper.Map(proj.Select, newOuterSelect.Alias, save.Alias);
                        // add outer-join test
                        DbProjectionExpression newInnerProjection = new DbProjectionExpression(newInnerSelect, proj.Projector).AddOuterJoinTest();
                        newInnerSelect = newInnerProjection.Select;
                        Expression newProjector = newInnerProjection.Projector;

                        DbTableAlias newAlias = new DbTableAlias();
                        var          pc       = ColumnProjector.ProjectColumns(this.language.CanBeColumn, newProjector, newOuterSelect.Columns, newAlias, newOuterSelect.Alias, newInnerSelect.Alias);

                        DbJoinExpression   join         = new DbJoinExpression(DbJoinType.OuterApply, newOuterSelect, newInnerSelect, null);
                        DbSelectExpression joinedSelect = new DbSelectExpression(newAlias, pc.Columns, join, null, null, null, proj.IsSingleton, null, null);

                        // apply client-join treatment recursively
                        this.currentSelect = joinedSelect;
                        newProjector       = this.Visit(pc.Projector);

                        // compute keys (this only works if join condition was a single column comparison)
                        List <Expression> outerKeys = new List <Expression>();
                        List <Expression> innerKeys = new List <Expression>();
                        if (this.GetEquiJoinKeyExpressions(newInnerSelect.Where, newOuterSelect.Alias, outerKeys, innerKeys))
                        {
                            // outerKey needs to refer to the outer-scope's alias
                            var outerKey = outerKeys.Select(k => ColumnMapper.Map(k, save.Alias, newOuterSelect.Alias));
                            // innerKey needs to refer to the new alias for the select with the new join
                            var innerKey = innerKeys.Select(k => ColumnMapper.Map(k, joinedSelect.Alias, ((DbColumnExpression)k).Alias));
                            DbProjectionExpression newProjection = new DbProjectionExpression(joinedSelect, newProjector, proj.Aggregator);
                            return(new DbClientJoinExpression(newProjection, outerKey, innerKey));
                        }
                    }
                }
                else
                {
                    this.isTopLevel = false;
                }

                return(base.VisitProjection(proj));
            }
            finally
            {
                this.currentSelect = save;
            }
        }
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     if (first)
     {
         first = false;
         return base.VisitSelect(select);
     }
     return select;
 }
Пример #22
0
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     if (first)
     {
         first = false;
         return(base.VisitSelect(select));
     }
     return(select);
 }
 public static DbSelectExpression SetFrom(this DbSelectExpression select, Expression from)
 {
     if (select.From != from)
     {
         return(new DbSelectExpression(select.Alias, select.Columns, from, select.Where, select.OrderBy,
                                       select.GroupBy, select.IsDistinct, select.Skip, select.Take));
     }
     return(select);
 }
Пример #24
0
            private static bool CanMergeWithFrom(DbSelectExpression select, bool isTopLevel)
            {
                DbSelectExpression fromSelect = GetLeftMostSelect(select.From);

                if (fromSelect == null)
                {
                    return(false);
                }
                if (!IsColumnProjection(fromSelect))
                {
                    return(false);
                }
                bool selHasNameMapProjection = IsNameMapProjection(select);
                bool selHasOrderBy           = select.OrderBy != null && select.OrderBy.Count > 0;
                bool selHasGroupBy           = select.GroupBy != null && select.GroupBy.Count > 0;
                bool selHasAggregates        = AggregateChecker.HasAggregates(select);
                bool frmHasOrderBy           = fromSelect.OrderBy != null && fromSelect.OrderBy.Count > 0;
                bool frmHasGroupBy           = fromSelect.GroupBy != null && fromSelect.GroupBy.Count > 0;

                // both cannot have orderby
                if (selHasOrderBy && frmHasOrderBy)
                {
                    return(false);
                }
                // both cannot have groupby
                if (selHasGroupBy && frmHasGroupBy)
                {
                    return(false);
                }
                // cannot move forward order-by if outer has group-by
                if (frmHasOrderBy && (selHasGroupBy || selHasAggregates || select.IsDistinct))
                {
                    return(false);
                }
                // cannot move forward group-by if outer has where clause
                if (frmHasGroupBy /*&& (select.Where != null)*/) // need to assert projection is the same in order to move group-by forward
                {
                    return(false);
                }
                // cannot move forward a take if outer has take or skip or distinct
                if (fromSelect.Take != null && (select.Take != null || select.Skip != null || select.IsDistinct || selHasAggregates || selHasGroupBy))
                {
                    return(false);
                }
                // cannot move forward a skip if outer has skip or distinct
                if (fromSelect.Skip != null && (select.Skip != null || select.IsDistinct || selHasAggregates || selHasGroupBy))
                {
                    return(false);
                }
                // cannot move forward a distinct if outer has take, skip, groupby or a different projection
                if (fromSelect.IsDistinct && (select.Take != null || select.Skip != null || !selHasNameMapProjection ||
                                              selHasGroupBy || selHasAggregates || (selHasOrderBy && !isTopLevel)))
                {
                    return(false);
                }
                return(true);
            }
 public DbProjectionExpression(DbSelectExpression source, 
     Expression projector, LambdaExpression aggregator)
     : base(DbExpressionType.Projection, (aggregator != null) ? 
     aggregator.Body.Type : typeof(IEnumerable<>).MakeGenericType(projector.Type))
 {
     this._select = source;
     this._projector = projector;
     this._aggregator = aggregator;
 }
 public DbProjectionExpression(DbSelectExpression source,
                               Expression projector, LambdaExpression aggregator)
     : base(DbExpressionType.Projection, (aggregator != null) ?
            aggregator.Body.Type : typeof(IEnumerable <>).MakeGenericType(projector.Type))
 {
     this._select     = source;
     this._projector  = projector;
     this._aggregator = aggregator;
 }
 public static DbSelectExpression SetDistinct(this DbSelectExpression select, bool isDistinct)
 {
     if (select.IsDistinct != isDistinct)
     {
         return(new DbSelectExpression(select.Alias, select.Columns, select.From, select.Where, select.OrderBy,
                                       select.GroupBy, isDistinct, select.Skip, select.Take));
     }
     return(select);
 }
Пример #28
0
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            DbTableAlias newAlias = new DbTableAlias();

            this.map[select.Alias] = newAlias;
            select = (DbSelectExpression)base.VisitSelect(select);
            return(new DbSelectExpression(newAlias, select.Columns, select.From, select.Where, select.OrderBy,
                                          select.GroupBy, select.IsDistinct, select.Skip, select.Take));
        }
Пример #29
0
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            bool saveIsOuterMostSelect = this.isOuterMostSelect;
            try
            {
                this.isOuterMostSelect = false;
                select = (DbSelectExpression)base.VisitSelect(select);

                bool hasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;
                bool hasGroupBy = select.GroupBy != null && select.GroupBy.Count > 0;
                bool canHaveOrderBy = saveIsOuterMostSelect || select.Take != null || select.Skip != null;
                bool canReceiveOrderings = canHaveOrderBy && !hasGroupBy && !select.IsDistinct;

                if (hasOrderBy)
                {
                    this.PrependOrderings(select.OrderBy);
                }

                IEnumerable<DbOrderExpression> orderings = null;
                if (canReceiveOrderings)
                {
                    orderings = this.gatheredOrderings;
                }
                else if (canHaveOrderBy)
                {
                    orderings = select.OrderBy;
                }
                bool canPassOnOrderings = !saveIsOuterMostSelect && !hasGroupBy && !select.IsDistinct;
                ReadOnlyCollection<DbColumnDeclaration> columns = select.Columns;
                if (this.gatheredOrderings != null)
                {
                    if (canPassOnOrderings)
                    {
                        var producedAliases = DeclaredAliasGatherer.Gather(select.From);
                        // reproject order expressions using this select's alias so the outer select will have properly formed expressions
                        BindResult project = this.RebindOrderings(this.gatheredOrderings, select.Alias, producedAliases, select.Columns);
                        this.gatheredOrderings = null;
                        this.PrependOrderings(project.Orderings);
                        columns = project.Columns;
                    }
                    else
                    {
                        this.gatheredOrderings = null;
                    }
                }
                if (orderings != select.OrderBy || columns != select.Columns)
                {
                    select = new DbSelectExpression(select.Alias, columns, select.From, select.Where, orderings, select.GroupBy, select.IsDistinct, select.Skip, select.Take);
                }
                return select;
            }
            finally
            {
                this.isOuterMostSelect = saveIsOuterMostSelect;
            }
        }
        protected override Expression VisitProjection(DbProjectionExpression proj)
        {
            DbSelectExpression save = this.currentSelect;
            this.currentSelect = proj.Select;
            try
            {
                if (!this.isTopLevel)
                {
                    if (this.CanJoinOnClient(this.currentSelect))
                    {
                        // make a query that combines all the constraints from the outer queries into a single select
                        DbSelectExpression newOuterSelect = (DbSelectExpression)QueryDuplicator.Duplicate(save);

                        // remap any references to the outer select to the new alias;
                        DbSelectExpression newInnerSelect = (DbSelectExpression)ColumnMapper.Map(proj.Select, newOuterSelect.Alias, save.Alias);
                        // add outer-join test
                        DbProjectionExpression newInnerProjection = new DbProjectionExpression(newInnerSelect, proj.Projector).AddOuterJoinTest();
                        newInnerSelect = newInnerProjection.Select;
                        Expression newProjector = newInnerProjection.Projector;

                        DbTableAlias newAlias = new DbTableAlias();
                        var pc = ColumnProjector.ProjectColumns(this.language.CanBeColumn, newProjector, newOuterSelect.Columns, newAlias, newOuterSelect.Alias, newInnerSelect.Alias);

                        DbJoinExpression join = new DbJoinExpression(DbJoinType.OuterApply, newOuterSelect, newInnerSelect, null);
                        DbSelectExpression joinedSelect = new DbSelectExpression(newAlias, pc.Columns, join, null, null, null, proj.IsSingleton, null, null);

                        // apply client-join treatment recursively
                        this.currentSelect = joinedSelect;
                        newProjector = this.Visit(pc.Projector); 

                        // compute keys (this only works if join condition was a single column comparison)
                        List<Expression> outerKeys = new List<Expression>();
                        List<Expression> innerKeys = new List<Expression>();
                        if (this.GetEquiJoinKeyExpressions(newInnerSelect.Where, newOuterSelect.Alias, outerKeys, innerKeys))
                        {
                            // outerKey needs to refer to the outer-scope's alias
                            var outerKey = outerKeys.Select(k => ColumnMapper.Map(k, save.Alias, newOuterSelect.Alias));
                            // innerKey needs to refer to the new alias for the select with the new join
                            var innerKey = innerKeys.Select(k => ColumnMapper.Map(k, joinedSelect.Alias, ((DbColumnExpression)k).Alias));
                            DbProjectionExpression newProjection = new DbProjectionExpression(joinedSelect, newProjector, proj.Aggregator);
                            return new DbClientJoinExpression(newProjection, outerKey, innerKey);
                        }
                    }
                }
                else
                {
                    this.isTopLevel = false;
                }

                return base.VisitProjection(proj);
            }
            finally 
            {
                this.currentSelect = save;
            }
        }
 public static DbSelectExpression RemoveOrderExpression(this DbSelectExpression select, DbOrderExpression ordering)
 {
     if (select.OrderBy != null && select.OrderBy.Count > 0)
     {
         List <DbOrderExpression> orderby = new List <DbOrderExpression>(select.OrderBy);
         orderby.Remove(ordering);
         return(select.SetOrderBy(orderby));
     }
     return(select);
 }
Пример #32
0
        protected DbScalarExpression UpdateScalar(DbScalarExpression scalar,
                                                  DbSelectExpression select)
        {
            if (select != scalar.Select)
            {
                return(new DbScalarExpression(scalar.Type, select));
            }

            return(scalar);
        }
Пример #33
0
        protected DbProjectionExpression UpdateProjection(DbProjectionExpression proj,
                                                          DbSelectExpression select, Expression projector, LambdaExpression aggregator)
        {
            if (select != proj.Select || projector != proj.Projector || aggregator != proj.Aggregator)
            {
                return(new DbProjectionExpression(select, projector, aggregator));
            }

            return(proj);
        }
        protected DbSubqueryExpression(DbExpressionType expressionType, 
            Type type, DbSelectExpression select)
            : base(expressionType, type)
        {
            Debug.Assert(expressionType == DbExpressionType.Scalar || 
                expressionType == DbExpressionType.Exists || 
                expressionType == DbExpressionType.In);

            _select = select;
        }
        protected DbSubqueryExpression(DbExpressionType expressionType,
                                       Type type, DbSelectExpression select)
            : base(expressionType, type)
        {
            Debug.Assert(expressionType == DbExpressionType.Scalar ||
                         expressionType == DbExpressionType.Exists ||
                         expressionType == DbExpressionType.In);

            _select = select;
        }
        public static DbSelectExpression RemoveRedundantFrom(this DbSelectExpression select)
        {
            DbSelectExpression fromSelect = select.From as DbSelectExpression;

            if (fromSelect != null)
            {
                return(SubqueryRemover.Remove(select, fromSelect));
            }
            return(select);
        }
Пример #37
0
 private static bool IsRedudantSubquery(DbSelectExpression select)
 {
     return((IsSimpleProjection(select) || IsNameMapProjection(select)) &&
            !select.IsDistinct &&
            select.Take == null &&
            select.Skip == null &&
            select.Where == null &&
            (select.OrderBy == null || select.OrderBy.Count == 0) &&
            (select.GroupBy == null || select.GroupBy.Count == 0));
 }
Пример #38
0
        protected DbExistsExpression UpdateExists(DbExistsExpression exists,
                                                  DbSelectExpression select)
        {
            if (select != exists.Select)
            {
                return(new DbExistsExpression(select));
            }

            return(exists);
        }
 public static DbSelectExpression RemoveGroupExpression(this DbSelectExpression select, Expression expression)
 {
     if (select.GroupBy != null && select.GroupBy.Count > 0)
     {
         List <Expression> groupby = new List <Expression>(select.GroupBy);
         groupby.Remove(expression);
         return(select.SetGroupBy(groupby));
     }
     return(select);
 }
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     var saveColumns = this.columns;
     this.columns = ReferencedColumnGatherer.Gather(select).ToLookup(c => c.Alias);
     var saveLastJoin = this.lastJoin;
     this.lastJoin = null;
     var result = base.VisitSelect(select);
     this.columns = saveColumns;
     this.lastJoin = saveLastJoin;
     return result;
 }
Пример #41
0
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     if (this.selectsToRemove.Contains(select))
     {
         return this.Visit(select.From);
     }
     else
     {
         return base.VisitSelect(select);
     }
 }
 protected override Expression VisitClientJoin(DbClientJoinExpression join)
 {
     // treat client joins as new top level
     var saveTop = this.isTopLevel;
     var saveSelect = this.currentSelect;
     this.isTopLevel = true;
     this.currentSelect = null;
     Expression result = base.VisitClientJoin(join);
     this.isTopLevel = saveTop;
     this.currentSelect = saveSelect;
     return result;
 }
 internal static bool IsSimpleProjection(DbSelectExpression select)
 {
     foreach (DbColumnDeclaration decl in select.Columns)
     {
         DbColumnExpression col = decl.Expression as DbColumnExpression;
         if (col == null || decl.Name != col.Name)
         {
             return false;
         }
     }
     return true;
 }
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            select = (DbSelectExpression)base.VisitSelect(select);

            // first remove all purely redundant subqueries
            List<DbSelectExpression> redundant = RedundantSubqueryGatherer.Gather(select.From);
            if (redundant != null)
            {
                select = SubqueryRemover.Remove(select, redundant);
            }

            return select;
        }
 internal static bool IsNameMapProjection(DbSelectExpression select)
 {
     if (select.From is DbTableExpression) return false;
     DbSelectExpression fromSelect = select.From as DbSelectExpression;
     if (fromSelect == null || select.Columns.Count != fromSelect.Columns.Count)
         return false;
     ReadOnlyCollection<DbColumnDeclaration> 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++)
     {
         DbColumnExpression col = select.Columns[i].Expression as DbColumnExpression;
         if (col == null || !(col.Name == fromColumns[i].Name))
             return false;
     }
     return true;
 }
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     var saveWhere = this.currentWhere;
     try
     {
         this.currentWhere = select.Where;
         var result = (DbSelectExpression)base.VisitSelect(select);
         if (this.currentWhere != result.Where)
         {
             return result.SetWhere(this.currentWhere);
         }
         return result;
     }
     finally
     {
         this.currentWhere = saveWhere;
     }
 }
 protected override Expression VisitSelect(DbSelectExpression select)
 {
     select = (DbSelectExpression)base.VisitSelect(select);
     if (lookup.Contains(select.Alias))
     {
         List<DbColumnDeclaration> aggColumns = new List<DbColumnDeclaration>(select.Columns);
         foreach (DbAggregateSubqueryExpression ae in lookup[select.Alias])
         {
             string name = "agg" + aggColumns.Count;
             DbColumnDeclaration cd = new DbColumnDeclaration(name, ae.AggregateInGroupSelect);
             this.map.Add(ae, new DbColumnExpression(ae.Type, null, ae.GroupByAlias, name));
             aggColumns.Add(cd);
         }
         return new DbSelectExpression(select.Alias, aggColumns, select.From, select.Where, select.OrderBy, 
             select.GroupBy, select.IsDistinct, select.Skip, select.Take);
     }
     return select;
 }
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            select = (DbSelectExpression)base.VisitSelect(select);

            // look for redundant column declarations
            List<DbColumnDeclaration> cols = select.Columns.OrderBy(c => c.Name).ToList();
            BitArray removed = new BitArray(select.Columns.Count);
            bool anyRemoved = false;
            for (int i = 0, n = cols.Count; i < n - 1; i++)
            {
                DbColumnDeclaration ci = cols[i];
                DbColumnExpression cix = ci.Expression as DbColumnExpression;
                DbDataType qt = cix != null ? cix.DbType : null;
                DbColumnExpression cxi = new DbColumnExpression(ci.Expression.Type, qt, select.Alias, ci.Name);
                for (int j = i + 1; j < n; j++)
                {
                    if (!removed.Get(j))
                    {
                        DbColumnDeclaration cj = cols[j];
                        if (SameExpression(ci.Expression, cj.Expression))
                        {
                            // any reference to 'j' should now just be a reference to 'i'
                            DbColumnExpression cxj = new DbColumnExpression(cj.Expression.Type, qt, select.Alias, cj.Name);
                            this.map.Add(cxj, cxi);
                            removed.Set(j, true);
                            anyRemoved = true;
                        }
                    }
                }
            }
            if (anyRemoved)
            {
                List<DbColumnDeclaration> newDecls = new List<DbColumnDeclaration>();
                for (int i = 0, n = cols.Count; i < n; i++)
                {
                    if (!removed.Get(i))
                    {
                        newDecls.Add(cols[i]);
                    }
                }
                select = select.SetColumns(newDecls);
            }
            return select;
        }
        protected override Expression VisitProjection(DbProjectionExpression proj)
        {
            if (isTopLevel)
            {
                isTopLevel = false;
                this.currentSelect = proj.Select;
                Expression projector = this.Visit(proj.Projector);
                if (projector != proj.Projector || this.currentSelect != proj.Select)
                {
                    return new DbProjectionExpression(this.currentSelect, projector, proj.Aggregator);
                }
                return proj;
            }

            if (proj.IsSingleton && this.CanJoinOnServer(this.currentSelect))
            {
                DbTableAlias newAlias = new DbTableAlias();
                this.currentSelect = this.currentSelect.AddRedundantSelect(newAlias);

                // remap any references to the outer select to the new alias;
                DbSelectExpression source = (DbSelectExpression)ColumnMapper.Map(proj.Select, newAlias, this.currentSelect.Alias);

                // add outer-join test
                DbProjectionExpression pex = new DbProjectionExpression(source, proj.Projector).AddOuterJoinTest();

                var pc = ColumnProjector.ProjectColumns(this.language.CanBeColumn, pex.Projector, this.currentSelect.Columns, 
                    this.currentSelect.Alias, newAlias, proj.Select.Alias);

                DbJoinExpression join = new DbJoinExpression(DbJoinType.OuterApply, this.currentSelect.From, pex.Select, null);

                this.currentSelect = new DbSelectExpression(this.currentSelect.Alias, pc.Columns, join, null);
                return this.Visit(pc.Projector);
            }

            var saveTop = this.isTopLevel;
            var saveSelect = this.currentSelect;
            this.isTopLevel = true;
            this.currentSelect = null;
            Expression result = base.VisitProjection(proj);
            this.isTopLevel = saveTop;
            this.currentSelect = saveSelect;
            return result;
        }
        protected override Expression VisitSelect(DbSelectExpression select)
        {
            select = (DbSelectExpression)base.VisitSelect(select);
            if (select.Skip != null)
            {
                DbSelectExpression newSelect = select.SetSkip(null).SetTake(null);
                bool canAddColumn = !select.IsDistinct && (select.GroupBy == null || select.GroupBy.Count == 0);
                if (!canAddColumn)
                {
                    newSelect = newSelect.AddRedundantSelect(new DbTableAlias());
                }
                newSelect = newSelect.AddColumn(new DbColumnDeclaration("rownum", new DbRowNumberExpression(select.OrderBy)));

                // add layer for WHERE clause that references new rownum column
                newSelect = newSelect.AddRedundantSelect(new DbTableAlias());
                newSelect = newSelect.RemoveColumn(newSelect.Columns.Single(c => c.Name == "rownum"));

                var newAlias = ((DbSelectExpression)newSelect.From).Alias;
                DbColumnExpression rnCol = new DbColumnExpression(typeof(int), null, newAlias, "rownum");
                Expression where;
                if (select.Take != null)
                {
                    where = new DbBetweenExpression(rnCol, Expression.Add(select.Skip, Expression.Constant(1)), 
                        Expression.Add(select.Skip, select.Take));
                }
                else
                {
                    where = rnCol.GreaterThan(select.Skip);
                }
                if (newSelect.Where != null)
                {
                    where = newSelect.Where.And(where);
                }
                newSelect = newSelect.SetWhere(where);

                select = newSelect;
            }
            return select;
        }
 internal static bool HasAggregates(DbSelectExpression expression)
 {
     AggregateChecker checker = new AggregateChecker();
     checker.Visit(expression);
     return checker.hasAggregate;
 }
 private static bool CanMergeWithFrom(DbSelectExpression select, bool isTopLevel)
 {
     DbSelectExpression fromSelect = GetLeftMostSelect(select.From);
     if (fromSelect == null)
         return false;
     if (!IsColumnProjection(fromSelect))
         return false;
     bool selHasNameMapProjection = IsNameMapProjection(select);
     bool selHasOrderBy = select.OrderBy != null && select.OrderBy.Count > 0;
     bool selHasGroupBy = select.GroupBy != null && select.GroupBy.Count > 0;
     bool selHasAggregates = AggregateChecker.HasAggregates(select);
     bool frmHasOrderBy = fromSelect.OrderBy != null && fromSelect.OrderBy.Count > 0;
     bool frmHasGroupBy = fromSelect.GroupBy != null && fromSelect.GroupBy.Count > 0;
     // both cannot have orderby
     if (selHasOrderBy && frmHasOrderBy)
         return false;
     // both cannot have groupby
     if (selHasGroupBy && frmHasGroupBy)
         return false;
     // cannot move forward order-by if outer has group-by
     if (frmHasOrderBy && (selHasGroupBy || selHasAggregates || select.IsDistinct))
         return false;
     // cannot move forward group-by if outer has where clause
     if (frmHasGroupBy /*&& (select.Where != null)*/) // need to assert projection is the same in order to move group-by forward
         return false;
     // cannot move forward a take if outer has take or skip or distinct
     if (fromSelect.Take != null && (select.Take != null || select.Skip != null || select.IsDistinct || selHasAggregates || selHasGroupBy))
         return false;
     // cannot move forward a skip if outer has skip or distinct
     if (fromSelect.Skip != null && (select.Skip != null || select.IsDistinct || selHasAggregates || selHasGroupBy))
         return false;
     // cannot move forward a distinct if outer has take, skip, groupby or a different projection
     if (fromSelect.IsDistinct && (select.Take != null || select.Skip != null || !selHasNameMapProjection || 
         selHasGroupBy || selHasAggregates || (selHasOrderBy && !isTopLevel)))
         return false;
     return true;
 }
 internal static bool IsInitialProjection(DbSelectExpression select)
 {
     return select.From is DbTableExpression;
 }
 protected DbSelectExpression UpdateSelect(DbSelectExpression select, 
     Expression from, Expression where, IEnumerable<DbOrderExpression> orderBy, 
     IEnumerable<Expression> groupBy, Expression skip, Expression take,
     bool isDistinct, IEnumerable<DbColumnDeclaration> columns)
 {
     if (from != select.From || where != select.Where || 
         orderBy != select.OrderBy || groupBy != select.GroupBy || 
         take != select.Take || skip != select.Skip || 
         isDistinct != select.IsDistinct || columns != select.Columns)
         return new DbSelectExpression(select.Alias, columns, from, where, 
             orderBy, groupBy, isDistinct, skip, take);
     
     return select;
 }
 protected virtual Expression VisitSelect(DbSelectExpression select)
 {
     Expression from = VisitSource(select.From);
     Expression where = Visit(select.Where);
     Expression skip = Visit(select.Skip);
     Expression take = Visit(select.Take);
     ReadOnlyCollection<DbOrderExpression> orderBy = 
         VisitOrderBy(select.OrderBy);
     ReadOnlyCollection<Expression> groupBy = 
         VisitExpressionList(select.GroupBy);
     ReadOnlyCollection<DbColumnDeclaration> columns = 
         VisitColumnDeclarations(select.Columns);
     
     return UpdateSelect(select, from, where, orderBy, groupBy, 
         skip, take, select.IsDistinct, columns);
 }
 protected DbDeclaration UpdateDeclaration(DbDeclaration decl, 
     IEnumerable<DbVariableDeclaration> variables, DbSelectExpression source)
 {
     if (variables != decl.Variables || source != decl.Source)
         return new DbDeclaration(variables, source);
     
     return decl;
 }
 protected DbProjectionExpression UpdateProjection(DbProjectionExpression proj, 
     DbSelectExpression select, Expression projector, LambdaExpression aggregator)
 {
     if (select != proj.Select || projector != proj.Projector || aggregator != proj.Aggregator)
         return new DbProjectionExpression(select, projector, aggregator);
     
     return proj;
 }
 protected DbInExpression UpdateIn(DbInExpression ixp, Expression expression, 
     DbSelectExpression select, IEnumerable<Expression> values)
 {
     if (expression != ixp.Expression || 
         select != ixp.Select || values != ixp.Values)
     {
         if (select != null)
             return new DbInExpression(expression, select);
         
         return new DbInExpression(expression, values);
     }
     return ixp;
 }
 protected DbExistsExpression UpdateExists(DbExistsExpression exists, 
     DbSelectExpression select)
 {
     if (select != exists.Select)
         return new DbExistsExpression(select);
     
     return exists;
 }
 protected DbScalarExpression UpdateScalar(DbScalarExpression scalar, 
     DbSelectExpression select)
 {
     if (select != scalar.Select)
         return new DbScalarExpression(scalar.Type, select);
     
     return scalar;
 }