private void PushDown(SqlColumn column) { SqlSelect select = new SqlSelect(new SqlNop(column.ClrType, column.SqlType, column.SourceExpression), this.currentSelect.From, this.currentSelect.SourceExpression); this.currentSelect.From = new SqlAlias(select); select.Row.Columns.Add(column); }
private void GatherUnionExpressions(SqlNode node, List <SqlExpression> exprs) { SqlUnion union = node as SqlUnion; if (union != null) { this.GatherUnionExpressions(union.Left, exprs); this.GatherUnionExpressions(union.Right, exprs); } else { SqlSelect sel = node as SqlSelect; if (sel != null) { SqlAliasRef aref = sel.Selection as SqlAliasRef; if (aref != null) { this.GatherUnionExpressions(aref.Alias.Node, exprs); } else { exprs.Add(sel.Selection); } } } }
internal override SqlSelect VisitSelect(SqlSelect select) { this.Visit(select.Row); this.Visit(select.Where); return(select); }
private SqlSource PushSourceDown(SqlSource sqlSource, List <SqlColumn> cols) { SqlSelect ns = new SqlSelect(new SqlNop(cols[0].ClrType, cols[0].SqlType, sqlSource.SourceExpression), sqlSource, sqlSource.SourceExpression); ns.Row.Columns.AddRange(cols); return(new SqlAlias(ns)); }
private SqlJoin GetLeftOuterWithUnreferencedSingletonOnLeft(SqlSource source) { SqlAlias alias = source as SqlAlias; if (alias != null) { SqlSelect select = alias.Node as SqlSelect; if (select != null && select.Where == null && select.Top == null && select.GroupBy.Count == 0 && select.OrderBy.Count == 0) { return(this.GetLeftOuterWithUnreferencedSingletonOnLeft(select.From)); } } SqlJoin join = source as SqlJoin; if (join == null || join.JoinType != SqlJoinType.LeftOuter) { return(null); } if (!this.IsSingletonSelect(join.Left)) { return(null); } HashSet <SqlAlias> p = SqlGatherProducedAliases.Gather(join.Left); HashSet <SqlAlias> c = SqlGatherConsumedAliases.Gather(join.Right); if (p.Overlaps(c)) { return(null); } return(join); }
internal override SqlSelect VisitSelect(SqlSelect select) { /* * We're travelling through <expression> of something like: * * SELECT <expression> * FROM <alias> * * Inside the expression there may be a reference to <alias> that * represents the dynamic type that we're trying to discover. * * In this case, the type relationship between AliasRef and Alias is * T to IEnumerable<T>. * * We need to remember to 'unpivot' the type of IEnumerable<T> to * get the correct dynamic type. * * Since SELECTs may be nested, we use a stack of pivots. * */ this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, true); VisitExpression(select.Selection); this.UnwrapSequences = this.UnwrapSequences.Last; return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { SqlSelect saveSelect = this.outerSelect; this.outerSelect = select; // big-joins may need to lift PK's out for default ordering, so don't allow big-join if we see these this.canJoin &= select.GroupBy.Count == 0 && select.Top == null && !select.IsDistinct; bool saveIsTopLevel = this.isTopLevel; this.isTopLevel = false; select = this.VisitSelectCore(select); this.isTopLevel = saveIsTopLevel; select.Selection = this.VisitExpression(select.Selection); this.isTopLevel = saveIsTopLevel; this.outerSelect = saveSelect; if (select.IsDistinct && HierarchyChecker.HasHierarchy(select.Selection)) { // distinct across heirarchy is a NO-OP select.IsDistinct = false; } return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { int i = 0; List <SqlOrderExpression> orders = select.OrderBy; while (i < orders.Count) { SqlExpression expr = orders[i].Expression; while (expr.NodeType == SqlNodeType.DiscriminatedType) { expr = ((SqlDiscriminatedType)expr).Discriminator; } switch (expr.NodeType) { case SqlNodeType.Value: case SqlNodeType.Parameter: orders.RemoveAt(i); break; default: ++i; break; } } return(base.VisitSelect(select)); }
internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select, Type clrType) { ProviderType sqlType = null; switch (nt) { case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: clrType = select.Selection.ClrType; sqlType = select.Selection.SqlType; break; case SqlNodeType.Multiset: if (clrType == null) { clrType = typeof(List <>).MakeGenericType(select.Selection.ClrType); } sqlType = typeProvider.GetApplicationType((int)ConverterSpecialTypes.Table); break; case SqlNodeType.Exists: clrType = typeof(bool); sqlType = typeProvider.From(typeof(bool)); break; } return(new SqlSubSelect(nt, clrType, sqlType, select)); }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { // allow one big-join per query? if ((this.options & Options.EnableBigJoin) != 0 && !this.hasBigJoin && this.canJoin && this.isTopLevel && this.outerSelect != null && !MultisetChecker.HasMultiset(sms.Select.Selection) && BigJoinChecker.CanBigJoin(sms.Select)) { sms.Select = this.VisitSelect(sms.Select); SqlAlias alias = new SqlAlias(sms.Select); SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, this.outerSelect.From, alias, null, sms.SourceExpression); this.outerSelect.From = join; this.outerSelect.OrderingType = SqlOrderingType.Always; // make joined expression SqlExpression expr = (SqlExpression)SqlDuplicator.Copy(sms.Select.Selection); // make count expression SqlSelect copySelect = (SqlSelect)SqlDuplicator.Copy(sms.Select); SqlAlias copyAlias = new SqlAlias(copySelect); SqlSelect countSelect = new SqlSelect(sql.Unary(SqlNodeType.Count, null, sms.SourceExpression), copyAlias, sms.SourceExpression); countSelect.OrderingType = SqlOrderingType.Never; SqlExpression count = sql.SubSelect(SqlNodeType.ScalarSubSelect, countSelect); // make joined collection SqlJoinedCollection jc = new SqlJoinedCollection(sms.ClrType, sms.SqlType, expr, count, sms.SourceExpression); this.hasBigJoin = true; return(jc); } else { return(QueryExtractor.Extract(sms, this.parentParameters)); } }
internal static bool CanBigJoin(SqlSelect select) { Visitor v = new Visitor(); v.Visit(select); return(v.canBigJoin); }
internal override SqlSelect VisitSelect(SqlSelect select) { Scope save = this.current; this.current = new Scope(select.Where, this.current); SqlSelect result = base.VisitSelect(select); bool stopHoisting = select.IsDistinct || select.GroupBy.Count > 0 || this.aggregateChecker.HasAggregates(select) || select.Top != null || this.rowNumberChecker.HasRowNumber(select); // Shift as much of the current WHERE to the parent as possible. if (this.current != null) { if (this.current.Parent != null && !stopHoisting) { this.current.Parent.Where = sql.AndAccumulate(this.current.Parent.Where, this.current.Where); this.current.Where = null; } select.Where = this.current.Where; } this.current = save; return(result); }
internal override SqlExpression VisitAliasRef(SqlAliasRef aref) { SqlNode node = aref.Alias.Node; if (node is SqlTable || node is SqlTableValuedFunctionCall) { return(aref); } SqlUnion union = node as SqlUnion; if (union != null) { return(this.ExpandUnion(union)); } SqlSelect ss = node as SqlSelect; if (ss != null) { return(this.VisitExpression(ss.Selection)); } SqlExpression exp = node as SqlExpression; if (exp != null) { return(this.VisitExpression(exp)); } throw Error.CouldNotHandleAliasRef(node.NodeType); }
internal override SqlSelect VisitSelect(SqlSelect select) { bool saveForceReferenceAll = this.forceReferenceAll; this.forceReferenceAll = false; bool saveIsTopLevel = this.isTopLevel; try { if (this.isTopLevel) { // top-level projection references columns! select.Selection = this.VisitExpression(select.Selection); } this.isTopLevel = false; for (int i = select.Row.Columns.Count - 1; i >= 0; i--) { SqlColumn c = select.Row.Columns[i]; bool safeToRemove = !saveForceReferenceAll && !this.referenceMap.ContainsKey(c) // don't remove anything from a distinct select (except maybe a literal value) since it would change the meaning of the comparison && !select.IsDistinct // don't remove an aggregate expression that may be the only expression that forces the grouping (since it would change the cardinality of the results) && !(select.GroupBy.Count == 0 && this.aggregateChecker.HasAggregates(c.Expression)); if (safeToRemove) { select.Row.Columns.RemoveAt(i); } else { this.VisitExpression(c.Expression); } } select.Top = this.VisitExpression(select.Top); for (int i = select.OrderBy.Count - 1; i >= 0; i--) { select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression); } select.Having = this.VisitExpression(select.Having); for (int i = select.GroupBy.Count - 1; i >= 0; i--) { select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]); } select.Where = this.VisitExpression(select.Where); select.From = this.VisitSource(select.From); } finally { this.isTopLevel = saveIsTopLevel; this.forceReferenceAll = saveForceReferenceAll; } return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { foreach (SqlColumn c in select.Row.Columns) { this.columns.Add(c); } return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { if (this.isTopLevel) { select.Selection = sDeflator.VisitExpression(select.Selection); } return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { base.VisitSelect(select); if (select.Where != null) { this.CheckJoinCondition(select.Where); } return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { // big-joins may need to lift PK's out for default ordering, so don't allow big-join if we see these this.canBigJoin &= select.GroupBy.Count == 0 && select.Top == null && !select.IsDistinct; if (!this.canBigJoin) { return(select); } return(base.VisitSelect(select)); }
internal override SqlSelect VisitSelect(SqlSelect select) { bool saveTop = this.topLevel; this.topLevel = false; select = this.VisitSelectCore(select); this.topLevel = saveTop; select.Selection = this.VisitExpression(select.Selection); return(select); }
private bool HasTrivialProjection(SqlSelect select) { foreach (SqlColumn c in select.Row.Columns) { if (c.Expression != null && c.Expression.NodeType != SqlNodeType.ColumnRef) { return(false); } } return(true); }
internal override SqlStatement VisitUpdate(SqlUpdate su) { SqlSelect ss = (SqlSelect)this.Visit(su.Select); List <SqlAssign> assignments = new List <SqlAssign>(su.Assignments.Count); foreach (SqlAssign sa in su.Assignments) { assignments.Add((SqlAssign)this.Visit(sa)); } return(new SqlUpdate(ss, assignments, su.SourceExpression)); }
internal override SqlSelect VisitSelectCore(SqlSelect select) { bool saveIsTopLevel = this.isTopLevel; this.isTopLevel = false; try { return(base.VisitSelectCore(select)); } finally { this.isTopLevel = saveIsTopLevel; } }
internal override SqlSelect VisitSelect(SqlSelect select) { SqlSelect save = this.currentSelect; try { this.currentSelect = select; return(base.VisitSelect(select)); } finally { this.currentSelect = save; } }
private bool IsFoundInGroup(SqlSelect select) { // does the column happen to be listed in the group-by clause? foreach (SqlExpression exp in select.GroupBy) { if (this.RefersToColumn(exp, this.found) || this.RefersToColumn(exp, this.match)) { return(true); } } return(false); }
internal override SqlSelect VisitSelect(SqlSelect select) { SelectScope s = expressionSink; // Don't lift through a TOP. if (select.Top != null) { expressionSink = null; } // Don't lift through a GROUP BY (or implicit GROUP BY). if (select.GroupBy.Count > 0 || this.aggregateChecker.HasAggregates(select)) { expressionSink = null; } // Don't lift through DISTINCT if (select.IsDistinct) { expressionSink = null; } if (expressionSink != null) { List <SqlColumn> keep = new List <SqlColumn>(); List <SqlColumn> lift = new List <SqlColumn>(); foreach (SqlColumn sc in select.Row.Columns) { bool referencesLeftsideAliases = SqlAliasesReferenced.ReferencesAny(sc.Expression, expressionSink.LeftProduction); bool isLockedExpression = expressionSink.ReferencedExpressions.Contains(sc); if (referencesLeftsideAliases && !isLockedExpression) { lift.Add(sc); } else { keep.Add(sc); } } select.Row.Columns.Clear(); select.Row.Columns.AddRange(keep); if (lift.Count > 0) { expressionSink.Lifted.Push(lift); } } SqlSelect sel = base.VisitSelect(select); expressionSink = s; return(sel); }
private bool IsTrivialSelect(SqlSelect select) { if (select.OrderBy.Count != 0 || select.GroupBy.Count != 0 || select.Having != null || select.Top != null || select.IsDistinct || select.Where != null) { return(false); } return(this.HasTrivialSource(select.From) && this.HasTrivialProjection(select)); }
internal override SqlSelect VisitSelect(SqlSelect select) { SqlSource from = this.VisitSource(select.From); List <SqlExpression> gex = null; if (select.GroupBy.Count > 0) { gex = new List <SqlExpression>(select.GroupBy.Count); foreach (SqlExpression sqlExpr in select.GroupBy) { gex.Add((SqlExpression)this.Visit(sqlExpr)); } } SqlExpression having = (SqlExpression)this.Visit(select.Having); List <SqlOrderExpression> lex = null; if (select.OrderBy.Count > 0) { lex = new List <SqlOrderExpression>(select.OrderBy.Count); foreach (SqlOrderExpression sox in select.OrderBy) { SqlOrderExpression nsox = new SqlOrderExpression(sox.OrderType, (SqlExpression)this.Visit(sox.Expression)); lex.Add(nsox); } } SqlExpression top = (SqlExpression)this.Visit(select.Top); SqlExpression where = (SqlExpression)this.Visit(select.Where); SqlRow row = (SqlRow)this.Visit(select.Row); SqlExpression selection = this.VisitExpression(select.Selection); SqlSelect n = new SqlSelect(selection, from, select.SourceExpression); if (gex != null) { n.GroupBy.AddRange(gex); } n.Having = having; if (lex != null) { n.OrderBy.AddRange(lex); } n.OrderingType = select.OrderingType; n.Row = row; n.Top = top; n.IsDistinct = select.IsDistinct; n.IsPercent = select.IsPercent; n.Where = where; n.DoNotOutput = select.DoNotOutput; return(n); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { SqlSelect innerSelect = this.VisitSelect(ss.Select); if (!this.aggregateChecker.HasAggregates(innerSelect)) { innerSelect.Top = this.sql.ValueFromObject(1, ss.SourceExpression); } innerSelect.OrderingType = SqlOrderingType.Blocked; SqlAlias alias = new SqlAlias(innerSelect); this.currentSelect.From = new SqlJoin(SqlJoinType.OuterApply, this.currentSelect.From, alias, null, ss.SourceExpression); return(new SqlColumnRef(innerSelect.Row.Columns[0])); }
private void ConvertColumnsToMax(SqlSelect select, out bool changed, out bool containsLongExpressions) { SqlRow row = select.Row; changed = false; containsLongExpressions = false; foreach (SqlColumn col in row.Columns) { bool columnChanged; containsLongExpressions = containsLongExpressions || col.SqlType.IsLargeType; col.Expression = ConvertToMax(col.Expression, out columnChanged); changed = changed || columnChanged; } }
internal override SqlSelect VisitSelect(SqlSelect select) { SqlSource from = VisitSource(select.From); List <SqlExpression> list = null; if (select.GroupBy.Count > 0) { list = new List <SqlExpression>(select.GroupBy.Count); foreach (var item2 in select.GroupBy) { list.Add((SqlExpression)Visit(item2)); } } var having = (SqlExpression)Visit(select.Having); List <SqlOrderExpression> list2 = null; if (select.OrderBy.Count > 0) { list2 = new List <SqlOrderExpression>(select.OrderBy.Count); foreach (var item3 in select.OrderBy) { var item = new SqlOrderExpression(item3.OrderType, (SqlExpression)Visit(item3.Expression)); list2.Add(item); } } var top = (SqlExpression)Visit(select.Top); var where = (SqlExpression)Visit(select.Where); var row = (SqlRow)Visit(select.Row); SqlExpression selection = VisitExpression(select.Selection); var sqlSelect = new SqlSelect(selection, from, select.SourceExpression); if (list != null) { sqlSelect.GroupBy.AddRange(list); } sqlSelect.Having = having; if (list2 != null) { sqlSelect.OrderBy.AddRange(list2); } sqlSelect.OrderingType = select.OrderingType; sqlSelect.Row = row; sqlSelect.Top = top; sqlSelect.IsDistinct = select.IsDistinct; sqlSelect.IsPercent = select.IsPercent; sqlSelect.Where = where; sqlSelect.DoNotOutput = select.DoNotOutput; return(sqlSelect); }