internal static bool CanLift(SqlSource source, HashSet <SqlAlias> aliasesForLifting, HashSet <SqlExpression> liftedExpressions) { Visitor v = new Visitor(false, aliasesForLifting, liftedExpressions); v.VisitSource(source); return(v.canLiftAll); }
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 static List <List <SqlColumn> > Lift(SqlSource source, HashSet <SqlAlias> aliasesForLifting, HashSet <SqlExpression> liftedExpressions) { Visitor v = new Visitor(true, aliasesForLifting, liftedExpressions); v.VisitSource(source); return(v.lifted); }
internal override SqlSource VisitJoin(SqlJoin join) { if (join.JoinType == SqlJoinType.CrossApply) { // Visit the left side as usual. join.Left = this.VisitSource(join.Left); // Visit the condition as usual. join.Condition = this.VisitExpression(join.Condition); // Visit the right, with the expressionSink set. SelectScope s = expressionSink; expressionSink = new SelectScope(); expressionSink.LeftProduction = SqlGatherProducedAliases.Gather(join.Left); join.Right = this.VisitSource(join.Right); // Were liftable expressions found? SqlSource newSource = join; foreach (List <SqlColumn> cols in expressionSink.Lifted) { newSource = PushSourceDown(newSource, cols); } expressionSink = s; return(newSource); } return(base.VisitJoin(join)); }
static internal List <SqlColumn> GatherColumns(SqlSource source) { List <SqlColumn> columns = new List <SqlColumn>(); new Visitor(columns).Visit(source); return(columns); }
internal override SqlSource VisitJoin(SqlJoin join) { SqlSource left = this.VisitSource(join.Left); SqlSource right = this.VisitSource(join.Right); SqlExpression cond = (SqlExpression)this.Visit(join.Condition); return(new SqlJoin(join.JoinType, left, right, cond, join.SourceExpression)); }
internal SqlJoin(SqlJoinType type, SqlSource left, SqlSource right, SqlExpression cond, Expression sourceExpression) : base(SqlNodeType.Join, sourceExpression) { JoinType = type; Left = left; Right = right; Condition = cond; }
internal static SqlExpression Lift(SqlSource source, HashSet <SqlAlias> aliasesForLifting) { System.Diagnostics.Debug.Assert(source != null); System.Diagnostics.Debug.Assert(aliasesForLifting != null); Visitor v = new Visitor(true, aliasesForLifting, null); v.VisitSource(source); return(v.lifted); }
internal static bool CanLift(SqlSource source, HashSet <SqlAlias> aliasesForLifting, HashSet <SqlExpression> liftedExpressions) { System.Diagnostics.Debug.Assert(source != null); System.Diagnostics.Debug.Assert(aliasesForLifting != null); Visitor v = new Visitor(false, aliasesForLifting, liftedExpressions); v.VisitSource(source); return(v.canLiftAll); }
private bool HasTrivialSource(SqlSource node) { SqlAlias alias = node as SqlAlias; if (alias == null) { return(false); } return(alias.Node is SqlSelect); }
private bool HasTrivialSource(SqlSource node) { SqlJoin join = node as SqlJoin; if (join != null) { return(this.HasTrivialSource(join.Left) && this.HasTrivialSource(join.Right)); } return(node is SqlAlias); }
internal SqlJoin MakeJoin(SqlJoinType joinType, SqlSource location, SqlAlias alias, SqlExpression condition, Expression source) { if (joinType == SqlJoinType.LeftOuter) { var sqlSelect = alias.Node as SqlSelect; if (sqlSelect != null && sqlSelect.Selection != null && sqlSelect.Selection.NodeType != SqlNodeType.OptionalValue) { sqlSelect.Selection = new SqlOptionalValue(new SqlColumn("test", Unary(SqlNodeType.OuterJoinedValue, Value(typeof(int?), TypeProvider.From(typeof(int)), 1, false, source))), sqlSelect.Selection); } } return(new SqlJoin(joinType, location, alias, condition, source)); }
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); }
private SqlUnion GetUnion(SqlSource source) { SqlAlias alias = source as SqlAlias; if (alias != null) { SqlUnion union = alias.Node as SqlUnion; if (union != null) { return(union); } } return(null); }
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); }
internal override SqlSource VisitSource(SqlSource node) { node = (SqlSource)this.Visit(node); SqlAlias alias = node as SqlAlias; if (alias != null) { SqlSelect sel = alias.Node as SqlSelect; if (sel != null && this.IsTrivialSelect(sel)) { this.removedMap[alias] = alias; node = sel.From; } } return(node); }
private void GetSelectionsBeforeJoin(SqlSource source, List <List <SqlColumn> > selections) { SqlJoin join = source as SqlJoin; if (join != null) { return; } SqlAlias alias = source as SqlAlias; if (alias != null) { SqlSelect select = alias.Node as SqlSelect; if (select != null) { this.GetSelectionsBeforeJoin(select.From, selections); selections.Add(select.Row.Columns); } } }
private bool IsSingletonSelect(SqlSource source) { SqlAlias alias = source as SqlAlias; if (alias == null) { return(false); } SqlSelect select = alias.Node as SqlSelect; if (select == null) { return(false); } if (select.From != null) { return(false); } return(true); }
private bool HasEmptySource(SqlSource node) { SqlAlias alias = node as SqlAlias; if (alias == null) { return(false); } SqlSelect sel = alias.Node as SqlSelect; if (sel == null) { return(false); } return(sel.Row.Columns.Count == 0 && sel.From == null && sel.Where == null && sel.GroupBy.Count == 0 && sel.Having == null && sel.OrderBy.Count == 0); }
internal SqlJoin MakeJoin(SqlJoinType joinType, SqlSource location, SqlAlias alias, SqlExpression condition, Expression source) { // if the new item is on the right side of some outer join then fixup the projection to reflect that it can possibly be null if (joinType == SqlJoinType.LeftOuter) { SqlSelect sel = alias.Node as SqlSelect; if (sel != null && sel.Selection != null && sel.Selection.NodeType != SqlNodeType.OptionalValue) { // replace selection w/ optional + outer-joined-value sel.Selection = new SqlOptionalValue( new SqlColumn( "test", this.Unary(SqlNodeType.OuterJoinedValue, this.Value(typeof(int?), this.typeProvider.From(typeof(int)), 1, false, source)) ), sel.Selection ); } } return(new SqlJoin(joinType, location, alias, condition, source)); }
internal void BuildEqivalenceMap(SqlSource scope) { this.map = new Dictionary <SqlColumn, SqlColumn>(); this.Visit(scope); }
internal virtual SqlSource VisitSource(SqlSource source) { return((SqlSource)this.Visit(source)); }
internal override SqlSource VisitSource(SqlSource source) { return(source); }
internal override SqlSource VisitSource(SqlSource source) { source = base.VisitSource(source); SqlJoin join = source as SqlJoin; if (join != null) { if (join.JoinType == SqlJoinType.OuterApply) { // Reduce outer-apply into left-outer-join HashSet <SqlAlias> leftProducedAliases = SqlGatherProducedAliases.Gather(join.Left); HashSet <SqlExpression> liftedExpressions = new HashSet <SqlExpression>(); if (SqlPredicateLifter.CanLift(join.Right, leftProducedAliases, liftedExpressions) && SqlSelectionLifter.CanLift(join.Right, leftProducedAliases, liftedExpressions) && !SqlAliasDependencyChecker.IsDependent(join.Right, leftProducedAliases, liftedExpressions)) { SqlExpression liftedPredicate = SqlPredicateLifter.Lift(join.Right, leftProducedAliases); List <List <SqlColumn> > liftedSelections = SqlSelectionLifter.Lift(join.Right, leftProducedAliases, liftedExpressions); join.JoinType = SqlJoinType.LeftOuter; join.Condition = liftedPredicate; if (liftedSelections != null) { foreach (List <SqlColumn> selection in liftedSelections) { source = this.PushSourceDown(source, selection); } } } else { this.AnnotateSqlIncompatibility(join, SqlProvider.ProviderMode.Sql2000); } } else if (join.JoinType == SqlJoinType.CrossApply) { // reduce cross apply with special nested left-outer-join's into a single left-outer-join // // SELECT x.*, y.* // FROM X // CROSS APPLY ( // SELECT y.* // FROM ( // SELECT ? // ) // LEFT OUTER JOIN ( // SELECT y.* FROM Y // ) AS y // // ==> // // SELECT x.*, y.* // FROM X // LEFT OUTER JOIN ( // SELECT y.* FROM Y // ) SqlJoin leftOuter = this.GetLeftOuterWithUnreferencedSingletonOnLeft(join.Right); if (leftOuter != null) { HashSet <SqlAlias> leftProducedAliases = SqlGatherProducedAliases.Gather(join.Left); HashSet <SqlExpression> liftedExpressions = new HashSet <SqlExpression>(); if (SqlPredicateLifter.CanLift(leftOuter.Right, leftProducedAliases, liftedExpressions) && SqlSelectionLifter.CanLift(leftOuter.Right, leftProducedAliases, liftedExpressions) && !SqlAliasDependencyChecker.IsDependent(leftOuter.Right, leftProducedAliases, liftedExpressions) ) { SqlExpression liftedPredicate = SqlPredicateLifter.Lift(leftOuter.Right, leftProducedAliases); List <List <SqlColumn> > liftedSelections = SqlSelectionLifter.Lift(leftOuter.Right, leftProducedAliases, liftedExpressions); // add intermediate selections this.GetSelectionsBeforeJoin(join.Right, liftedSelections); // push down all selections foreach (List <SqlColumn> selection in liftedSelections.Where(s => s.Count > 0)) { source = this.PushSourceDown(source, selection); } join.JoinType = SqlJoinType.LeftOuter; join.Condition = this.factory.AndAccumulate(leftOuter.Condition, liftedPredicate); join.Right = leftOuter.Right; } else { this.AnnotateSqlIncompatibility(join, SqlProvider.ProviderMode.Sql2000); } } } // re-balance join tree of left-outer-joins to expose LOJ w/ leftside unreferenced while (join.JoinType == SqlJoinType.LeftOuter) { // look for buried left-outer-joined-with-unreferenced singleton SqlJoin leftLeftOuter = this.GetLeftOuterWithUnreferencedSingletonOnLeft(join.Left); if (leftLeftOuter == null) { break; } List <List <SqlColumn> > liftedSelections = new List <List <SqlColumn> >(); // add intermediate selections this.GetSelectionsBeforeJoin(join.Left, liftedSelections); // push down all selections foreach (List <SqlColumn> selection in liftedSelections) { source = this.PushSourceDown(source, selection); } // bubble this one up on-top of this 'join'. SqlSource jRight = join.Right; SqlExpression jCondition = join.Condition; join.Left = leftLeftOuter.Left; join.Right = leftLeftOuter; join.Condition = leftLeftOuter.Condition; leftLeftOuter.Left = leftLeftOuter.Right; leftLeftOuter.Right = jRight; leftLeftOuter.Condition = jCondition; } } return(source); }