public static DbSelectExpression RemoveColumn(this DbSelectExpression select, DbColumnDeclaration column) { List <DbColumnDeclaration> columns = new List <DbColumnDeclaration>(select.Columns); columns.Remove(column); return(select.SetColumns(columns)); }
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; } }
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; } }
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)); }
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; } }
protected virtual Expression VisitDeclaration(DbDeclaration decl) { ReadOnlyCollection <DbVariableDeclaration> variables = VisitVariableDeclarations(decl.Variables); DbSelectExpression source = (DbSelectExpression)Visit(decl.Source); return(UpdateDeclaration(decl, variables, source)); }
protected virtual Expression VisitProjection(DbProjectionExpression proj) { DbSelectExpression select = (DbSelectExpression)Visit(proj.Select); Expression projector = Visit(proj.Projector); return(UpdateProjection(proj, select, projector, proj.Aggregator)); }
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)); }
public DbDeclaration(IEnumerable <DbVariableDeclaration> variables, DbSelectExpression source) : base(DbExpressionType.Declaration, typeof(void)) { _variables = variables.AsReadOnly(); _source = source; }
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; }
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); }
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)); }
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); }
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; }
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); }
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); }
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)); }
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); }
protected DbScalarExpression UpdateScalar(DbScalarExpression scalar, DbSelectExpression select) { if (select != scalar.Select) { return(new DbScalarExpression(scalar.Type, select)); } return(scalar); }
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; }
public static DbSelectExpression RemoveRedundantFrom(this DbSelectExpression select) { DbSelectExpression fromSelect = select.From as DbSelectExpression; if (fromSelect != null) { return(SubqueryRemover.Remove(select, fromSelect)); } return(select); }
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)); }
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; }
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; }