public static bool WillProduceAtMostOneRow(AlgebraNode algebraNode) { AtMostOneRowChecker atMostOneRowChecker = new AtMostOneRowChecker(); atMostOneRowChecker.Visit(algebraNode); return(atMostOneRowChecker.WillProduceAtMostOneRow); }
private AlgebraNode GetLastAlgebraNode() { AlgebraNode result = _lastAlgebraNode; _lastAlgebraNode = null; return(result); }
public static RowBufferEntry[] GetDefinedValueEntries(AlgebraNode node) { DefinedValuesFinder definedValuesFinder = new DefinedValuesFinder(); definedValuesFinder.Visit(node); return(definedValuesFinder.GetDefinedValueEntries()); }
public override TableReference VisitDerivedTableReference(DerivedTableReference node) { AlgebraNode algebrizedQuery = Convert(node.Query); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); for (int i = 0; i < node.DerivedTableBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = node.DerivedTableBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = algebrizedQuery.OutputList[i]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedQuery; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); SetLastAlgebraNode(computeScalarAlgebraNode); return(node); }
private ShowPlanElement ConvertNode(AlgebraNode node) { Visit(node); ShowPlanElement result = _currentElement; _currentElement = null; return(result); }
public static ShowPlanElement Convert(AlgebraNode algebraNode) { if (algebraNode == null) return new ShowPlanElement(ShowPlanOperator.Select, new ShowPlanProperty[0]); ShowPlanBuilder showPlanBuilder = new ShowPlanBuilder(); return showPlanBuilder.ConvertNode(algebraNode); }
private static ResultAlgebraNode Convert(CommonTableBinding currentCommonTableBinding, QueryNode queryNode) { Algebrizer algebrizer = new Algebrizer(currentCommonTableBinding); AlgebraNode result = algebrizer.ConvertAstNode(queryNode); result = new SubqueryExpander().VisitAlgebraNode(result); return((ResultAlgebraNode)result); }
private static AlgebraNode WrapWithFilter(AlgebraNode input, ExpressionNode predicate) { if (predicate == null) return input; FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = input; filterAlgebraNode.Predicate = predicate; return filterAlgebraNode; }
private AlgebraNode GetOrCreateInput() { AlgebraNode lastNode = GetAndResetLastNode(); if (lastNode != null) { return(lastNode); } return(CreateConstantScan()); }
public static ShowPlanElement Convert(AlgebraNode algebraNode) { if (algebraNode == null) { return(new ShowPlanElement(ShowPlanOperator.Select, new ShowPlanProperty[0])); } ShowPlanBuilder showPlanBuilder = new ShowPlanBuilder(); return(showPlanBuilder.ConvertNode(algebraNode)); }
private void SetLastIterator(AlgebraNode owner, Iterator iterator) { if (_includeStatistics && owner.StatisticsIterator == null) { owner.StatisticsIterator = new StatisticsIterator(); owner.StatisticsIterator.RowBuffer = iterator.RowBuffer; owner.StatisticsIterator.Input = iterator; iterator = owner.StatisticsIterator; } _lastIterator = iterator; }
private static AlgebraNode WrapWithFilter(AlgebraNode input, ExpressionNode predicate) { if (predicate == null) { return(input); } FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = input; filterAlgebraNode.Predicate = predicate; return(filterAlgebraNode); }
private bool CheckIfNodeHasDependenciesToOuterReferences(AlgebraNode node) { foreach (RowBufferEntry rowBufferEntryReference in AstUtil.GetRowBufferEntryReferences(node)) { foreach (RowBufferEntry[] outerReferences in _outerReferences) { if (ArrayHelpers.Contains(outerReferences, rowBufferEntryReference)) { return(true); } } } return(false); }
public override TableReference VisitNamedTableReference(NamedTableReference node) { CommonTableBinding tableBindingAsCommonTable = node.TableRefBinding.TableBinding as CommonTableBinding; if (tableBindingAsCommonTable == null) { // It is a regular table reference. Emit just a table node. List <ColumnValueDefinition> definedValues = new List <ColumnValueDefinition>(); foreach (ColumnRefBinding columnRefBinding in node.TableRefBinding.ColumnRefs) { definedValues.Add(columnRefBinding.ValueDefinition); } TableAlgebraNode algebraNode = new TableAlgebraNode(); algebraNode.TableRefBinding = node.TableRefBinding; algebraNode.DefinedValues = definedValues.ToArray(); SetLastAlgebraNode(algebraNode); } else { // It is a reference to a CTE. Instead of emitting a table node we have to replace the // reference to the CTE by the algebrized representation of the CTE. One could speak // of "inlining" the CTE. if (tableBindingAsCommonTable == _currentCommonTableBinding) { // This should never happen. The JoinAlgebraNode should ignore these table references. Debug.Fail("The current common table binding should never be reached as a table reference."); } AlgebraNode algebrizedCte; if (tableBindingAsCommonTable.IsRecursive) { algebrizedCte = AlgebrizeRecursiveCte(tableBindingAsCommonTable); } else { algebrizedCte = Convert(tableBindingAsCommonTable.AnchorMember); } // In order to use the CTE we have to instantiate it. See commonets in InstantiateCte() for // details. AlgebraNode computeScalarAlgebraNode = InstantiateCte(algebrizedCte, tableBindingAsCommonTable, node.TableRefBinding); SetLastAlgebraNode(computeScalarAlgebraNode); } return(node); }
public override ExpressionNode VisitSingleRowSubselect(SingleRowSubselect expression) { AlgebraNode inputNode = GetOrCreateInput(); ResultAlgebraNode algebrizedSubquery = Algebrizer.Convert(expression.Query); ResultAlgebraNode assertedSubquery = CreateAssertedSubquery(algebrizedSubquery); JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode(); joinAlgebraNode.PassthruPredicate = CurrentPassthruPredicate; joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; joinAlgebraNode.Left = inputNode; joinAlgebraNode.Right = assertedSubquery; SetLastAlgebraNode(joinAlgebraNode); return(new RowBufferEntryExpression(assertedSubquery.OutputList[0])); }
public override AstNode Visit(AstNode node) { node = base.Visit(node); AlgebraNode algebraNode = node as AlgebraNode; if (algebraNode != null && algebraNode.OutputList != null) { for (int i = 0; i < algebraNode.OutputList.Length; i++) { algebraNode.OutputList[i] = ReplaceRowBuffer(algebraNode.OutputList[i]); } } return(node); }
private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding) { // Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times. // Since same row buffer entries means that the underlying data will be stored in the same physical data slot this // will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that // operates on the same column will always compare data coming from the same join side (and therefor will always // evaluate to true). // // Some notes on the implementation: // // 1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough; // instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc. // 2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions // are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same // expression AST instances. That means that replacing the row buffers leads to failure. // HACK: This is a workaround for issue 2. However, // I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query. algebrizedCte = (AlgebraNode)algebrizedCte.Clone(); CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer(); cteTableDefinedValuesReinitializer.Visit(algebrizedCte); RowBufferEntry[] outputList = algebrizedCte.OutputList; int skipRecursionLevel = commonTableBinding.IsRecursive ? 1 : 0; // Rename the query columns to the CTE columns List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedCte; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); return(computeScalarAlgebraNode); }
public override ExpressionNode VisitExistsSubselect(ExistsSubselect expression) { AlgebraNode input = GetAndResetLastNode(); ResultAlgebraNode algebrizedQuery = Algebrizer.Convert(expression.Query); if (!expression.Negated && AstUtil.WillProduceAtLeastOneRow(algebrizedQuery)) { if (input == null) { SetLastAlgebraNode(CreateConstantScan()); } else { SetLastAlgebraNode(input); } return(LiteralExpression.FromBoolean(true)); } if (!expression.Negated && !ProbingEnabled && input == null) { SetLastAlgebraNode(algebrizedQuery); return(LiteralExpression.FromBoolean(true)); } else { if (input == null) { input = CreateConstantScan(); } RowBufferEntry probeColumn = CreateProbeColumn(); JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode(); joinAlgebraNode.PassthruPredicate = CurrentPassthruPredicate; joinAlgebraNode.ProbeBufferEntry = probeColumn; joinAlgebraNode.Left = input; joinAlgebraNode.Right = algebrizedQuery; joinAlgebraNode.Op = expression.Negated ? JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin : JoinAlgebraNode.JoinOperator.LeftSemiJoin; SetLastAlgebraNode(joinAlgebraNode); return(CreateProbeColumnRef(probeColumn)); } }
public static bool JoinDoesNotDependOn(JoinAlgebraNode joinNode, AlgebraNode joinSide) { RowBufferEntry[] joinSideDefinedValues = GetDefinedValueEntries(joinSide); if (joinNode.Predicate != null) { RowBufferEntry[] referencedRowBufferEntries = GetRowBufferEntryReferences(joinNode.Predicate); foreach (RowBufferEntry joinSideDefinedValue in joinSideDefinedValues) { if (ArrayHelpers.Contains(referencedRowBufferEntries, joinSideDefinedValue)) { return(false); } } } return(true); }
public void SwapSides() { AlgebraNode oldLeft = _left; _left = _right; _right = oldLeft; switch (_op) { case JoinOperator.LeftOuterJoin: _op = JoinOperator.RightOuterJoin; break; case JoinOperator.LeftSemiJoin: _op = JoinOperator.RightSemiJoin; break; case JoinOperator.LeftAntiSemiJoin: _op = JoinOperator.RightAntiSemiJoin; break; case JoinOperator.RightOuterJoin: _op = JoinOperator.LeftOuterJoin; break; case JoinOperator.RightSemiJoin: _op = JoinOperator.LeftSemiJoin; break; case JoinOperator.RightAntiSemiJoin: _op = JoinOperator.LeftAntiSemiJoin; break; case JoinOperator.InnerJoin: case JoinOperator.FullOuterJoin: // Nothing to do. break; default: throw ExceptionBuilder.UnhandledCaseLabel(_op); } }
public override QueryNode VisitBinaryQuery(BinaryQuery query) { switch (query.Op) { case BinaryQueryOperator.Intersect: case BinaryQueryOperator.Except: { ResultAlgebraNode left = ((ResultAlgebraNode)ConvertAstNode(query.Left)); ResultAlgebraNode right = ((ResultAlgebraNode)ConvertAstNode(query.Right)); // Create distinct sort SortAlgebraNode sortAlgebraNode = new SortAlgebraNode(); sortAlgebraNode.Distinct = true; sortAlgebraNode.Input = left; sortAlgebraNode.SortEntries = left.OutputList; sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length); // Insert left (anti) semi join to (except) intersect left and right. ExpressionBuilder expressionBuilder = new ExpressionBuilder(); for (int i = 0; i < left.OutputList.Length; i++) { RowBufferEntryExpression leftExpr = new RowBufferEntryExpression(); leftExpr.RowBufferEntry = left.OutputList[i]; RowBufferEntryExpression rightExpr = new RowBufferEntryExpression(); rightExpr.RowBufferEntry = right.OutputList[i]; expressionBuilder.Push(leftExpr); expressionBuilder.Push(rightExpr); expressionBuilder.PushBinary(BinaryOperator.Equal); expressionBuilder.Push(leftExpr); expressionBuilder.PushIsNull(); expressionBuilder.Push(rightExpr); expressionBuilder.PushIsNull(); expressionBuilder.PushBinary(BinaryOperator.LogicalAnd); expressionBuilder.PushBinary(BinaryOperator.LogicalOr); } expressionBuilder.PushNAry(LogicalOperator.And); ExpressionNode joinCondition = expressionBuilder.Pop(); JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode(); if (query.Op == BinaryQueryOperator.Intersect) { joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin; } else { joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin; } joinAlgebraNode.Left = sortAlgebraNode; joinAlgebraNode.Right = right; joinAlgebraNode.Predicate = joinCondition; SetLastAlgebraNode(joinAlgebraNode); ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode(); resultAlgebraNode.Input = GetLastAlgebraNode(); resultAlgebraNode.OutputList = left.OutputList; resultAlgebraNode.ColumnNames = left.ColumnNames; SetLastAlgebraNode(resultAlgebraNode); break; } case BinaryQueryOperator.Union: case BinaryQueryOperator.UnionAll: { // Build a flat list with all inputs. List <QueryNode> inputList = AstUtil.FlattenBinaryQuery(query); AlgebraNode[] inputs = new AlgebraNode[inputList.Count]; for (int i = 0; i < inputs.Length; i++) { inputs[i] = ConvertAstNode(inputList[i]); } int outputColumnCount = inputs[0].OutputList.Length; UnitedValueDefinition[] definedValues = new UnitedValueDefinition[outputColumnCount]; List <RowBufferEntry> definedValueEntries = new List <RowBufferEntry>(); for (int i = 0; i < outputColumnCount; i++) { RowBufferEntry rowBufferEntry = new RowBufferEntry(inputs[0].OutputList[i].DataType); definedValueEntries.Add(rowBufferEntry); UnitedValueDefinition definedValue = new UnitedValueDefinition(); definedValue.Target = rowBufferEntry; List <RowBufferEntry> dependencies = new List <RowBufferEntry>(); foreach (ResultAlgebraNode node in inputs) { dependencies.Add(node.OutputList[i]); } definedValue.DependendEntries = dependencies.ToArray(); definedValues[i] = definedValue; } ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = inputs; concatAlgebraNode.DefinedValues = definedValues; SetLastAlgebraNode(concatAlgebraNode); if (query.Op == BinaryQueryOperator.Union) { SortAlgebraNode sortAlgebraNode = new SortAlgebraNode(); sortAlgebraNode.Distinct = true; sortAlgebraNode.Input = GetLastAlgebraNode(); sortAlgebraNode.SortEntries = definedValueEntries.ToArray(); sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length); SetLastAlgebraNode(sortAlgebraNode); } ResultAlgebraNode unionResultAlgebraNode = new ResultAlgebraNode(); unionResultAlgebraNode.Input = GetLastAlgebraNode(); unionResultAlgebraNode.ColumnNames = ((ResultAlgebraNode)inputs[0]).ColumnNames; unionResultAlgebraNode.OutputList = definedValueEntries.ToArray(); SetLastAlgebraNode(unionResultAlgebraNode); break; } } return(query); }
private static AlgebraNode InstantiateCte(AlgebraNode algebrizedCte, CommonTableBinding commonTableBinding, TableRefBinding commonTableRefBinding) { // Replace row buffers to base tables by new ones. This must be done because a CTE could be referenced multiple times. // Since same row buffer entries means that the underlying data will be stored in the same physical data slot this // will lead to problems if, for example, two instances of the same CTE are joined together. Any join condition that // operates on the same column will always compare data coming from the same join side (and therefor will always // evaluate to true). // // Some notes on the implementation: // // 1. Note that just replacing references to row buffers of base tables in RowBufferExpression is not enough; // instead they must also be replaced in output lists, defined value references (esp. ConcatAlgebraNode) etc. // 2. Also note that although the QueryNodes are re-algebrized every time a CTE is references the expressions // are still copied from the QueryNodes (instead of cloned). Therefore two algrebrized CTEs will share the same // expression AST instances. That means that replacing the row buffers leads to failure. // HACK: This is a workaround for issue 2. However, // I am not quite sure how one should implement row buffer entry replacement without cloning the algebrized query. algebrizedCte = (AlgebraNode) algebrizedCte.Clone(); CteTableDefinedValuesReinitializer cteTableDefinedValuesReinitializer = new CteTableDefinedValuesReinitializer(); cteTableDefinedValuesReinitializer.Visit(algebrizedCte); RowBufferEntry[] outputList = algebrizedCte.OutputList; int skipRecursionLevel = commonTableBinding.IsRecursive ? 1 : 0; // Rename the query columns to the CTE columns List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); for (int i = 0; i < commonTableRefBinding.ColumnRefs.Length; i++) { RowBufferEntry targetRowBufferEntry = commonTableRefBinding.ColumnRefs[i].ValueDefinition.Target; RowBufferEntry sourceRowBufferEntry = outputList[i + skipRecursionLevel]; ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = targetRowBufferEntry; definedValue.Expression = new RowBufferEntryExpression(sourceRowBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedCte; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); return computeScalarAlgebraNode; }
public override TableReference VisitJoinedTableReference(JoinedTableReference node) { TableReference nonCteTableRef; if (IsTableReferenceToCurrentCommonTableBinding(node.Left)) { nonCteTableRef = node.Right; } else if (IsTableReferenceToCurrentCommonTableBinding(node.Right)) { nonCteTableRef = node.Left; } else { nonCteTableRef = null; } if (nonCteTableRef != null) { Debug.Assert(node.JoinType == JoinType.Inner); AlgebraNode algebrizedPath = ConvertAstNode(nonCteTableRef); SetLastAlgebraNode(algebrizedPath); if (node.Condition != null) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = GetLastAlgebraNode(); filterAlgebraNode.Predicate = node.Condition; SetLastAlgebraNode(filterAlgebraNode); } return(node); } JoinAlgebraNode algebraNode = new JoinAlgebraNode(); algebraNode.Left = ConvertAstNode(node.Left); algebraNode.Right = ConvertAstNode(node.Right); algebraNode.Predicate = node.Condition; switch (node.JoinType) { case JoinType.Inner: algebraNode.Op = JoinAlgebraNode.JoinOperator.InnerJoin; break; case JoinType.LeftOuter: algebraNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; break; case JoinType.RightOuter: algebraNode.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; break; case JoinType.FullOuter: algebraNode.Op = JoinAlgebraNode.JoinOperator.FullOuterJoin; break; } SetLastAlgebraNode(algebraNode); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { if (node.Predicate == null || !AstUtil.ContainsSubselect(node.Predicate)) { return(base.VisitJoinAlgebraNode(node)); } node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); switch (node.Op) { case JoinAlgebraNode.JoinOperator.InnerJoin: { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Predicate = node.Predicate; filterAlgebraNode.Input = node; node.Predicate = null; SetLastAlgebraNode(node); _probingEnabledStack.Push(false); filterAlgebraNode.Predicate = VisitExpression(filterAlgebraNode.Predicate); _probingEnabledStack.Pop(); filterAlgebraNode.Input = GetAndResetLastNode(); return(filterAlgebraNode); } case JoinAlgebraNode.JoinOperator.LeftOuterJoin: { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Predicate = node.Predicate; filterAlgebraNode.Input = node.Right; node.Right = filterAlgebraNode; node.Predicate = null; SetLastAlgebraNode(filterAlgebraNode.Input); _probingEnabledStack.Push(false); filterAlgebraNode.Predicate = VisitExpression(filterAlgebraNode.Predicate); _probingEnabledStack.Pop(); filterAlgebraNode.Input = GetAndResetLastNode(); return(node); } case JoinAlgebraNode.JoinOperator.RightOuterJoin: { node.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; AlgebraNode oldLeft = node.Left; node.Left = node.Right; node.Right = oldLeft; goto case JoinAlgebraNode.JoinOperator.LeftOuterJoin; } case JoinAlgebraNode.JoinOperator.FullOuterJoin: // TODO: Support subqueries in FULL OUTER JOIN. throw ExceptionBuilder.InternalError("FULL OUTER JOIN containing a subselect predicate in ON clause is not supported."); default: throw ExceptionBuilder.UnhandledCaseLabel(node.Op); } }
public override QueryNode VisitBinaryQuery(BinaryQuery query) { switch (query.Op) { case BinaryQueryOperator.Intersect: case BinaryQueryOperator.Except: { ResultAlgebraNode left = ((ResultAlgebraNode)ConvertAstNode(query.Left)); ResultAlgebraNode right = ((ResultAlgebraNode)ConvertAstNode(query.Right)); // Create distinct sort SortAlgebraNode sortAlgebraNode = new SortAlgebraNode(); sortAlgebraNode.Distinct = true; sortAlgebraNode.Input = left; sortAlgebraNode.SortEntries = left.OutputList; sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length); // Insert left (anti) semi join to (except) intersect left and right. ExpressionBuilder expressionBuilder = new ExpressionBuilder(); for (int i = 0; i < left.OutputList.Length; i++) { RowBufferEntryExpression leftExpr = new RowBufferEntryExpression(); leftExpr.RowBufferEntry = left.OutputList[i]; RowBufferEntryExpression rightExpr = new RowBufferEntryExpression(); rightExpr.RowBufferEntry = right.OutputList[i]; expressionBuilder.Push(leftExpr); expressionBuilder.Push(rightExpr); expressionBuilder.PushBinary(BinaryOperator.Equal); expressionBuilder.Push(leftExpr); expressionBuilder.PushIsNull(); expressionBuilder.Push(rightExpr); expressionBuilder.PushIsNull(); expressionBuilder.PushBinary(BinaryOperator.LogicalAnd); expressionBuilder.PushBinary(BinaryOperator.LogicalOr); } expressionBuilder.PushNAry(LogicalOperator.And); ExpressionNode joinCondition = expressionBuilder.Pop(); JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode(); if (query.Op == BinaryQueryOperator.Intersect) joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin; else joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin; joinAlgebraNode.Left = sortAlgebraNode; joinAlgebraNode.Right = right; joinAlgebraNode.Predicate = joinCondition; SetLastAlgebraNode(joinAlgebraNode); ResultAlgebraNode resultAlgebraNode = new ResultAlgebraNode(); resultAlgebraNode.Input = GetLastAlgebraNode(); resultAlgebraNode.OutputList = left.OutputList; resultAlgebraNode.ColumnNames = left.ColumnNames; SetLastAlgebraNode(resultAlgebraNode); break; } case BinaryQueryOperator.Union: case BinaryQueryOperator.UnionAll: { // Build a flat list with all inputs. List<QueryNode> inputList = AstUtil.FlattenBinaryQuery(query); AlgebraNode[] inputs = new AlgebraNode[inputList.Count]; for (int i = 0; i < inputs.Length; i++) inputs[i] = ConvertAstNode(inputList[i]); int outputColumnCount = inputs[0].OutputList.Length; UnitedValueDefinition[] definedValues = new UnitedValueDefinition[outputColumnCount]; List<RowBufferEntry> definedValueEntries = new List<RowBufferEntry>(); for (int i = 0; i < outputColumnCount; i++) { RowBufferEntry rowBufferEntry = new RowBufferEntry(inputs[0].OutputList[i].DataType); definedValueEntries.Add(rowBufferEntry); UnitedValueDefinition definedValue = new UnitedValueDefinition(); definedValue.Target = rowBufferEntry; List<RowBufferEntry> dependencies = new List<RowBufferEntry>(); foreach (ResultAlgebraNode node in inputs) dependencies.Add(node.OutputList[i]); definedValue.DependendEntries = dependencies.ToArray(); definedValues[i] = definedValue; } ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = inputs; concatAlgebraNode.DefinedValues = definedValues; SetLastAlgebraNode(concatAlgebraNode); if (query.Op == BinaryQueryOperator.Union) { SortAlgebraNode sortAlgebraNode = new SortAlgebraNode(); sortAlgebraNode.Distinct = true; sortAlgebraNode.Input = GetLastAlgebraNode(); sortAlgebraNode.SortEntries = definedValueEntries.ToArray(); sortAlgebraNode.SortOrders = CreateAscendingSortOrders(sortAlgebraNode.SortEntries.Length); SetLastAlgebraNode(sortAlgebraNode); } ResultAlgebraNode unionResultAlgebraNode = new ResultAlgebraNode(); unionResultAlgebraNode.Input = GetLastAlgebraNode(); unionResultAlgebraNode.ColumnNames = ((ResultAlgebraNode)inputs[0]).ColumnNames; unionResultAlgebraNode.OutputList = definedValueEntries.ToArray(); SetLastAlgebraNode(unionResultAlgebraNode); break; } } return query; }
public virtual AlgebraNode VisitAlgebraNode(AlgebraNode node) { return((AlgebraNode)Visit(node)); }
internal static ShowPlan Build(AlgebraNode root) { ShowPlanElement rootElement = ShowPlanBuilder.Convert(root); return new ShowPlan(rootElement); }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { if (expression.Op != BinaryOperator.LogicalAnd && expression.Op != BinaryOperator.LogicalOr) { return(base.VisitBinaryExpression(expression)); } if (expression.Op == BinaryOperator.LogicalAnd) { // AND expression.Left = VisitExpression(expression.Left); expression.Right = VisitExpression(expression.Right); return(expression); } else { // OR AlgebraNode input = GetAndResetLastNode(); _probingEnabledStack.Push(false); List <ExpressionNode> scalarOrParts = new List <ExpressionNode>(); List <AlgebraNode> algebrizedOrParts = new List <AlgebraNode>(); foreach (ExpressionNode orPart in AstUtil.SplitCondition(LogicalOperator.Or, expression)) { if (!AstUtil.ContainsSubselect(orPart)) { scalarOrParts.Add(orPart); } else { ExpressionNode replacedOrPart = VisitExpression(orPart); FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = GetAndResetLastNode(); filterAlgebraNode.Predicate = replacedOrPart; algebrizedOrParts.Add(filterAlgebraNode); } } if (scalarOrParts.Count > 0) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.Or, scalarOrParts); filterAlgebraNode.Input = CreateConstantScan(); algebrizedOrParts.Insert(0, filterAlgebraNode); } _probingEnabledStack.Pop(); ConcatAlgebraNode concat = new ConcatAlgebraNode(); concat.DefinedValues = new UnitedValueDefinition[0]; concat.Inputs = algebrizedOrParts.ToArray(); RowBufferEntry probeColumn = CreateProbeColumn(); JoinAlgebraNode leftSemiJoinBetweenInputAndConcat = new JoinAlgebraNode(); leftSemiJoinBetweenInputAndConcat.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin; leftSemiJoinBetweenInputAndConcat.PassthruPredicate = CurrentPassthruPredicate; leftSemiJoinBetweenInputAndConcat.ProbeBufferEntry = probeColumn; leftSemiJoinBetweenInputAndConcat.Left = input; leftSemiJoinBetweenInputAndConcat.Right = concat; SetLastAlgebraNode(leftSemiJoinBetweenInputAndConcat); return(CreateProbeColumnRef(probeColumn)); } }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); bool leftIsNull = node.Left is NullScanAlgebraNode; bool rightIsNull = node.Right is NullScanAlgebraNode; bool joinConditionAlwaysFalse = false; if (node.Predicate != null) { ExpressionNode predicate = node.Predicate; ConstantExpression predicateAsConstant = predicate as ConstantExpression; if (predicateAsConstant != null) { if (predicateAsConstant.AsBoolean) { node.Predicate = null; } else { joinConditionAlwaysFalse = true; } } } if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin) { node.SwapSides(); } switch (node.Op) { case JoinAlgebraNode.JoinOperator.InnerJoin: if (joinConditionAlwaysFalse || leftIsNull || rightIsNull) { return(CreateNullScan(node.OutputList)); } break; case JoinAlgebraNode.JoinOperator.FullOuterJoin: if (leftIsNull && rightIsNull) { return(CreateNullScan(node.OutputList)); } if (leftIsNull) { return(PadRightWithNullsOnLeftSide(node, RowBufferCreationMode.KeepExisting)); } if (rightIsNull) { return(PadLeftWithNullsOnRightSide(node, RowBufferCreationMode.KeepExisting)); } if (joinConditionAlwaysFalse) { AlgebraNode left = PadLeftWithNullsOnRightSide(node, RowBufferCreationMode.CreateNew); AlgebraNode right = PadRightWithNullsOnLeftSide(node, RowBufferCreationMode.CreateNew); ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[] { left, right }; List <RowBufferEntry> outputList = new List <RowBufferEntry>(); List <UnitedValueDefinition> definedValues = new List <UnitedValueDefinition>(); for (int i = 0; i < node.Left.OutputList.Length; i++) { int leftIndex = i; int rightIndex = node.Right.OutputList.Length + i; UnitedValueDefinition definedValue = new UnitedValueDefinition(); definedValue.Target = node.Left.OutputList[leftIndex]; definedValue.DependendEntries = new RowBufferEntry[] { left.OutputList[leftIndex], right.OutputList[rightIndex] }; definedValues.Add(definedValue); outputList.Add(definedValue.Target); } for (int i = 0; i < node.Right.OutputList.Length; i++) { int leftIndex = node.Left.OutputList.Length + i; int rightIndex = i; UnitedValueDefinition definedValue = new UnitedValueDefinition(); definedValue.Target = node.Right.OutputList[rightIndex]; definedValue.DependendEntries = new RowBufferEntry[] { left.OutputList[leftIndex], right.OutputList[rightIndex] }; definedValues.Add(definedValue); outputList.Add(definedValue.Target); } concatAlgebraNode.DefinedValues = definedValues.ToArray(); concatAlgebraNode.OutputList = outputList.ToArray(); return(concatAlgebraNode); } break; case JoinAlgebraNode.JoinOperator.LeftOuterJoin: if (leftIsNull) { return(CreateNullScan(node.OutputList)); } if (rightIsNull || joinConditionAlwaysFalse) { return(PadLeftWithNullsOnRightSide(node, RowBufferCreationMode.KeepExisting)); } break; case JoinAlgebraNode.JoinOperator.LeftSemiJoin: if (leftIsNull || rightIsNull || joinConditionAlwaysFalse) { return(CreateNullScan(node.OutputList)); } if (node.Predicate == null && AstUtil.WillProduceAtLeastOneRow(node.Right)) { return(node.Left); } break; case JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin: if (leftIsNull) { return(CreateNullScan(node.OutputList)); } if (rightIsNull || joinConditionAlwaysFalse) { return(node.Left); } if (node.Predicate == null && AstUtil.WillProduceAtLeastOneRow(node.Right)) { return(CreateNullScan(node.OutputList)); } break; } return(node); }
private void SetLastAlgebraNode(AlgebraNode algebraNode) { _lastAlgebraNode = algebraNode; }
private static FilterAlgebraNode GetFilterFromAndParts(IList<ExpressionNode> andParts, AlgebraNode input) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = input; filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andParts); return filterAlgebraNode; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); if (node.Predicate != null && (node.OuterReferences == null || node.OuterReferences.Length == 0) && ( node.Op == JoinAlgebraNode.JoinOperator.InnerJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) ) { RowBufferEntry[] leftDefinedEntries = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedEntries = AstUtil.GetDefinedValueEntries(node.Right); EqualPredicatesExtractor equalPredicatesExtractor = new EqualPredicatesExtractor(leftDefinedEntries, rightDefinedEntries); ExpressionNode probeResidual = equalPredicatesExtractor.VisitExpression(node.Predicate); BinaryExpression[] equalPredicates = equalPredicatesExtractor.GetEqualPredicates(); if (equalPredicates.Length > 0) { BinaryExpression equalPredicate = equalPredicates[0]; ExpressionBuilder expressionBuilder = new ExpressionBuilder(); expressionBuilder.Push(probeResidual); if (equalPredicates.Length > 1) { for (int i = 1; i < equalPredicates.Length; i++) { expressionBuilder.Push(equalPredicates[i]); } expressionBuilder.PushNAry(LogicalOperator.And); } probeResidual = expressionBuilder.Pop(); if (probeResidual is ConstantExpression) { probeResidual = null; } AlgebraNode leftInput = node.Left; AlgebraNode rightInput = node.Right; if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; leftInput = node.Right; rightInput = node.Left; ExpressionNode oldLeft = equalPredicate.Left; equalPredicate.Left = equalPredicate.Right; equalPredicate.Right = oldLeft; } RowBufferEntry leftEntry; RowBufferEntryExpression leftAsRowBufferEntryExpression = equalPredicate.Left as RowBufferEntryExpression; if (leftAsRowBufferEntryExpression != null) { leftEntry = leftAsRowBufferEntryExpression.RowBufferEntry; } else { leftEntry = new RowBufferEntry(equalPredicate.Left.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = leftEntry; definedValue.Expression = equalPredicate.Left; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = leftInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue }; leftInput = computeScalarAlgebraNode; } RowBufferEntry rightEntry; RowBufferEntryExpression rightAsRowBufferEntryExpression = equalPredicate.Right as RowBufferEntryExpression; if (rightAsRowBufferEntryExpression != null) { rightEntry = rightAsRowBufferEntryExpression.RowBufferEntry; } else { rightEntry = new RowBufferEntry(equalPredicate.Right.ExpressionType); ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rightEntry; definedValue.Expression = equalPredicate.Right; ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = rightInput; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { definedValue }; rightInput = computeScalarAlgebraNode; } HashMatchAlgebraNode hashMatchAlgebraNode = new HashMatchAlgebraNode(); hashMatchAlgebraNode.Op = node.Op; hashMatchAlgebraNode.Left = leftInput; hashMatchAlgebraNode.Right = rightInput; hashMatchAlgebraNode.BuildKeyEntry = leftEntry; hashMatchAlgebraNode.ProbeEntry = rightEntry; hashMatchAlgebraNode.ProbeResidual = probeResidual; return(hashMatchAlgebraNode); } } return(node); }
private bool CheckIfNodeHasDependenciesToOuterReferences(AlgebraNode node) { foreach (RowBufferEntry rowBufferEntryReference in AstUtil.GetRowBufferEntryReferences(node)) { foreach (RowBufferEntry[] outerReferences in _outerReferences) { if (ArrayHelpers.Contains(outerReferences, rowBufferEntryReference)) return true; } } return false; }
public virtual AlgebraNode VisitAlgebraNode(AlgebraNode node) { return (AlgebraNode)Visit(node); }
private static AlgebraNode AlgebrizeRecursiveCte(CommonTableBinding commonTableBinding) { // It is a recursive query. // // Create row buffer entry that is used to guard the recursion and the primary table spool // that spools the results needed by nested recursion calls. ExpressionBuilder expressionBuilder = new ExpressionBuilder(); StackedTableSpoolAlgebraNode primaryTableSpool = new StackedTableSpoolAlgebraNode(); RowBufferEntry anchorRecursionLevel; RowBufferEntry[] anchorOutput; AlgebraNode anchorNode; #region Anchor member { // Emit anchor member. AlgebraNode algebrizedAnchor = Convert(commonTableBinding.AnchorMember); // Emit compute scalar that initializes the recursion level to 0. anchorRecursionLevel = new RowBufferEntry(typeof(int)); ComputedValueDefinition computedValueDefinition1 = new ComputedValueDefinition(); computedValueDefinition1.Target = anchorRecursionLevel; computedValueDefinition1.Expression = LiteralExpression.FromInt32(0); ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = algebrizedAnchor; computeScalarAlgebraNode.DefinedValues = new ComputedValueDefinition[] { computedValueDefinition1 }; anchorOutput = algebrizedAnchor.OutputList; anchorNode = computeScalarAlgebraNode; } #endregion RowBufferEntry incrementedRecursionLevel; RowBufferEntry[] tableSpoolOutput; AlgebraNode tableSpoolNode; #region Table spool { // Emit table spool reference. RowBufferEntry recursionLevelRefEntry = new RowBufferEntry(typeof(int)); tableSpoolOutput = new RowBufferEntry[anchorOutput.Length]; for (int i = 0; i < tableSpoolOutput.Length; i++) { tableSpoolOutput[i] = new RowBufferEntry(anchorOutput[i].DataType); } StackedTableSpoolRefAlgebraNode tableSpoolReference = new StackedTableSpoolRefAlgebraNode(); tableSpoolReference.PrimarySpool = primaryTableSpool; tableSpoolReference.DefinedValues = ArrayHelpers.JoinArrays(new RowBufferEntry[] { recursionLevelRefEntry }, tableSpoolOutput); // Emit compute scalar that increases the recursion level by one and renames // columns from the spool to the CTE column buffer entries. expressionBuilder.Push(new RowBufferEntryExpression(recursionLevelRefEntry)); expressionBuilder.Push(LiteralExpression.FromInt32(1)); expressionBuilder.PushBinary(BinaryOperator.Add); incrementedRecursionLevel = new RowBufferEntry(typeof(int)); ComputedValueDefinition incremenedRecLevelValueDefinition = new ComputedValueDefinition(); incremenedRecLevelValueDefinition.Target = incrementedRecursionLevel; incremenedRecLevelValueDefinition.Expression = expressionBuilder.Pop(); CteColumnMappingFinder cteColumnMappingFinder = new CteColumnMappingFinder(commonTableBinding, tableSpoolOutput); foreach (QueryNode recursiveMember in commonTableBinding.RecursiveMembers) { cteColumnMappingFinder.Visit(recursiveMember); } CteColumnMapping[] cteColumnMappings = cteColumnMappingFinder.GetMappings(); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); definedValues.Add(incremenedRecLevelValueDefinition); foreach (CteColumnMapping cteColumnMapping in cteColumnMappings) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = cteColumnMapping.VirtualBufferEntry; definedValue.Expression = new RowBufferEntryExpression(cteColumnMapping.SpoolBufferEntry); definedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = tableSpoolReference; computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); tableSpoolNode = computeScalarAlgebraNode; } #endregion RowBufferEntry[] recursiveOutput; AlgebraNode recursiveNode; #region Recursive member(s) { // Emit all recursive parts. The join conditions to the recursive part are replaced by simple filters // in the nested Convert() call. ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[commonTableBinding.RecursiveMembers.Length]; for (int i = 0; i < commonTableBinding.RecursiveMembers.Length; i++) { concatAlgebraNode.Inputs[i] = Convert(commonTableBinding, commonTableBinding.RecursiveMembers[i]); } concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length]; for (int i = 0; i < anchorOutput.Length; i++) { List <RowBufferEntry> dependencies = new List <RowBufferEntry>(); foreach (ResultAlgebraNode algebrizedRecursivePart in concatAlgebraNode.Inputs) { dependencies.Add(algebrizedRecursivePart.OutputList[i]); } concatAlgebraNode.DefinedValues[i] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[i].Target = new RowBufferEntry(anchorOutput[i].DataType); concatAlgebraNode.DefinedValues[i].DependendEntries = dependencies.ToArray(); } // Calculate the recursive output. recursiveOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length]; for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++) { recursiveOutput[i] = concatAlgebraNode.DefinedValues[i].Target; } // Emit cross join JoinAlgebraNode crossJoinNode = new JoinAlgebraNode(); crossJoinNode.Left = tableSpoolNode; crossJoinNode.Right = concatAlgebraNode; // Emit assert that ensures that the recursion level is <= 100. expressionBuilder.Push(new RowBufferEntryExpression(incrementedRecursionLevel)); expressionBuilder.Push(LiteralExpression.FromInt32(100)); expressionBuilder.PushBinary(BinaryOperator.Greater); CaseExpression caseExpression = new CaseExpression(); caseExpression.WhenExpressions = new ExpressionNode[1]; caseExpression.WhenExpressions[0] = expressionBuilder.Pop(); caseExpression.ThenExpressions = new ExpressionNode[1]; caseExpression.ThenExpressions[0] = LiteralExpression.FromInt32(0); AssertAlgebraNode assertAlgebraNode = new AssertAlgebraNode(); assertAlgebraNode.Input = crossJoinNode; assertAlgebraNode.AssertionType = AssertionType.BelowRecursionLimit; assertAlgebraNode.Predicate = caseExpression; recursiveNode = assertAlgebraNode; } #endregion RowBufferEntry[] algebrizedOutput; AlgebraNode algebrizedCte; #region Combination { // Create concat node to combine anchor and recursive part. ConcatAlgebraNode concatAlgebraNode = new ConcatAlgebraNode(); concatAlgebraNode.Inputs = new AlgebraNode[2]; concatAlgebraNode.Inputs[0] = anchorNode; concatAlgebraNode.Inputs[1] = recursiveNode; concatAlgebraNode.DefinedValues = new UnitedValueDefinition[anchorOutput.Length + 1]; concatAlgebraNode.DefinedValues[0] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[0].Target = new RowBufferEntry(anchorRecursionLevel.DataType); concatAlgebraNode.DefinedValues[0].DependendEntries = new RowBufferEntry[] { anchorRecursionLevel, incrementedRecursionLevel }; for (int i = 0; i < anchorOutput.Length; i++) { concatAlgebraNode.DefinedValues[i + 1] = new UnitedValueDefinition(); concatAlgebraNode.DefinedValues[i + 1].Target = new RowBufferEntry(anchorOutput[i].DataType); concatAlgebraNode.DefinedValues[i + 1].DependendEntries = new RowBufferEntry[] { anchorOutput[i], recursiveOutput[i] }; } algebrizedOutput = new RowBufferEntry[concatAlgebraNode.DefinedValues.Length]; for (int i = 0; i < concatAlgebraNode.DefinedValues.Length; i++) { algebrizedOutput[i] = concatAlgebraNode.DefinedValues[i].Target; } // Assign the combination as the input to the primray spool primaryTableSpool.Input = concatAlgebraNode; // The primary spool represents the result of the "inlined" CTE. algebrizedCte = primaryTableSpool; } #endregion algebrizedCte.OutputList = algebrizedOutput; return(algebrizedCte); }
public override ExpressionNode VisitAllAnySubselect(AllAnySubselect expression) { expression.Left = VisitExpression(expression.Left); ResultAlgebraNode algebrizedQuery = Algebrizer.Convert(expression.Query); ExpressionNode leftExpression = expression.Left; RowBufferEntryExpression rightExpression = new RowBufferEntryExpression(); rightExpression.RowBufferEntry = algebrizedQuery.OutputList[0]; ExpressionBuilder expressionBuilder = new ExpressionBuilder(); expressionBuilder.Push(leftExpression); expressionBuilder.Push(rightExpression); expressionBuilder.PushBinary(expression.Op); bool negated = (expression.Type == AllAnySubselect.AllAnyType.All); if (negated) { expressionBuilder.PushUnary(UnaryOperator.LogicalNot); expressionBuilder.Push(leftExpression); expressionBuilder.PushIsNull(); expressionBuilder.Push(rightExpression); expressionBuilder.PushIsNull(); expressionBuilder.PushNAry(LogicalOperator.Or); } ExpressionNode filterPredicate = expressionBuilder.Pop(); FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = algebrizedQuery; filterAlgebraNode.Predicate = filterPredicate; AlgebraNode input = GetAndResetLastNode(); if (!negated && !ProbingEnabled && input == null) { SetLastAlgebraNode(filterAlgebraNode); return(LiteralExpression.FromBoolean(true)); } else { if (input == null) { input = CreateConstantScan(); } RowBufferEntry probeColumn = CreateProbeColumn(); JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode(); joinAlgebraNode.PassthruPredicate = CurrentPassthruPredicate; joinAlgebraNode.ProbeBufferEntry = probeColumn; joinAlgebraNode.Left = input; joinAlgebraNode.Right = filterAlgebraNode; joinAlgebraNode.Op = negated ? JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin : JoinAlgebraNode.JoinOperator.LeftSemiJoin; SetLastAlgebraNode(joinAlgebraNode); return(CreateProbeColumnRef(probeColumn)); } }
private AlgebraNode GetAndResetLastNode() { AlgebraNode result = _lastAlgebraNode; _lastAlgebraNode = null; return result; }
private ShowPlanElement ConvertNode(AlgebraNode node) { Visit(node); ShowPlanElement result = _currentElement; _currentElement = null; return result; }
public static bool WillProduceAtMostOneRow(AlgebraNode algebraNode) { AtMostOneRowChecker atMostOneRowChecker = new AtMostOneRowChecker(); atMostOneRowChecker.Visit(algebraNode); return atMostOneRowChecker.WillProduceAtMostOneRow; }
private static FilterAlgebraNode GetFilterFromAndParts(IList <ExpressionNode> andParts, AlgebraNode input) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = input; filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andParts); return(filterAlgebraNode); }
private Iterator ConvertAlgebraNode(AlgebraNode algebraNode) { Visit(algebraNode); Iterator iterator = GetLastIterator(); return iterator; }
public static RowBufferEntry[] GetDefinedValueEntries(AlgebraNode node) { DefinedValuesFinder definedValuesFinder = new DefinedValuesFinder(); definedValuesFinder.Visit(node); return definedValuesFinder.GetDefinedValueEntries(); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Check if node only consists of INNER join nodes and simple table reference nodes. // This algorithm assumes that the table references have been lineraized so that // // - JoinedTableReference appear on the LHS only (the last one must be NamedTableReference ovbiviously) // - NamedTableReference appear on the RHS only // // While scanning the node's children we create a list of all JoinedTableReferences and // NamedTableReferences. InnerJoinTableExtractor innerJoinTableExtractor = new InnerJoinTableExtractor(); innerJoinTableExtractor.Visit(node); if (!innerJoinTableExtractor.ConsistsOnlyOfInnerJoinsFiltersAndTables) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return(node); } else { TableAlgebraNode[] algebraNodes = innerJoinTableExtractor.GetTableNodes(); Dictionary <TableRefBinding, TableAlgebraNode> tableRefToNodeDictionary = new Dictionary <TableRefBinding, TableAlgebraNode>(); List <TableRefBinding> tableList = new List <TableRefBinding>(); foreach (TableAlgebraNode algebraNode in algebraNodes) { tableRefToNodeDictionary.Add(algebraNode.TableRefBinding, algebraNode); tableList.Add(algebraNode.TableRefBinding); } // Create a mapping RowBufferEntry -> ColumnRefBinding Dictionary <RowBufferEntry, ColumnRefBinding> rowBufferColumnDictionary = new Dictionary <RowBufferEntry, ColumnRefBinding>(); foreach (TableRefBinding tableRefBinding in tableList) { foreach (ColumnRefBinding columnRefBinding in tableRefBinding.ColumnRefs) { rowBufferColumnDictionary.Add(columnRefBinding.ValueDefinition.Target, columnRefBinding); } } // Create list of all possible join conditions and remaining AND-parts. List <JoinCondition> joinConditionList = new List <JoinCondition>(); List <ExpressionNode> andPartList = new List <ExpressionNode>(); ExpressionNode filter = AstUtil.CombineConditions(LogicalOperator.And, innerJoinTableExtractor.GetFilters()); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, filter)) { JoinCondition joinCondition = ConvertToJoinCondition(rowBufferColumnDictionary, andPart); if (joinCondition != null) { joinConditionList.Add(joinCondition); } else { andPartList.Add(andPart); } } // After creating the list of all join conditions and AND-parts we have all we need to create // an optimimal join order between all tables of this part of the table tree. JoinOrder bestJoinOrder = GetBestJoinOrder(tableList.ToArray(), joinConditionList.ToArray(), andPartList.ToArray()); // Get all tables that are introduced by this join order Dictionary <RowBufferEntry, ColumnValueDefinition> introducedColumns = GetIntroducedColumns(bestJoinOrder); // Combine AND-part list with all unused join conditions. andPartList.AddRange(bestJoinOrder.UnusedConditions); // Now we will re-create this part of the tree using the this join order. AlgebraNode lastAlgebraNode = null; for (int joinIndex = 0; joinIndex < bestJoinOrder.Joins.Length; joinIndex++) { Join join = bestJoinOrder.Joins[joinIndex]; AlgebraNode tableInput; TableAlgebraNode tableNode = tableRefToNodeDictionary[join.TableRefBinding]; ExpressionNode tableFilter = ExtractConditionsApplicableToTable(introducedColumns, andPartList, join.TableRefBinding); if (tableFilter == null) { tableInput = tableNode; } else { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = tableNode; filterAlgebraNode.Predicate = tableFilter; tableInput = filterAlgebraNode; } if (lastAlgebraNode == null) { // This was the first one. lastAlgebraNode = tableInput; } else { // Not the first one, we can create a join with the current table reference // and last table reference. // Get all AND-parts that can be applied to the tables already joined. // This expression is merged to one condition. ExpressionNode[] applicableAndParts = GetAndPartsApplicableToJoin(introducedColumns, bestJoinOrder, joinIndex, andPartList, true); ExpressionNode condition = AstUtil.CombineConditions(LogicalOperator.And, applicableAndParts); ExpressionNode joinCondition; if (join.JoinCondition == null) { joinCondition = null; } else { joinCondition = join.JoinCondition.ToExpression(); } ExpressionNode completeCondition = AstUtil.CombineConditions(LogicalOperator.And, condition, joinCondition); JoinAlgebraNode joinAlgebraNode = new JoinAlgebraNode(); joinAlgebraNode.Op = JoinAlgebraNode.JoinOperator.InnerJoin; joinAlgebraNode.Left = lastAlgebraNode; joinAlgebraNode.Right = tableInput; joinAlgebraNode.Predicate = completeCondition; // Next time this newly created join is the last table reference. lastAlgebraNode = joinAlgebraNode; } } return(lastAlgebraNode); } }
public static bool JoinDoesNotDependOn(JoinAlgebraNode joinNode, AlgebraNode joinSide) { RowBufferEntry[] joinSideDefinedValues = GetDefinedValueEntries(joinSide); if (joinNode.Predicate != null) { RowBufferEntry[] referencedRowBufferEntries = GetRowBufferEntryReferences(joinNode.Predicate); foreach (RowBufferEntry joinSideDefinedValue in joinSideDefinedValues) { if (ArrayHelpers.Contains(referencedRowBufferEntries, joinSideDefinedValue)) return false; } } return true; }