public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // For easier handling we replace right operations by equivalent // left operations. if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin) { node.SwapSides(); return VisitAlgebraNode(node); } // Visit children bool semiJoinContext; semiJoinContext = (node.Op == JoinAlgebraNode.JoinOperator.RightSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin); _semiJoinContextFlagStack.Push(semiJoinContext); node.Left = VisitAlgebraNode(node.Left); _semiJoinContextFlagStack.Pop(); semiJoinContext = (node.Op == JoinAlgebraNode.JoinOperator.LeftSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin); _semiJoinContextFlagStack.Push(semiJoinContext); node.Right = VisitAlgebraNode(node.Right); _semiJoinContextFlagStack.Pop(); return node; }
private static AlgebraNode PadLeftWithNullsOnRightSide(JoinAlgebraNode node, RowBufferCreationMode rowBufferCreationMode) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = node.Left; List <RowBufferEntry> outputList = new List <RowBufferEntry>(); outputList.AddRange(node.Left.OutputList); List <ComputedValueDefinition> definedValues = new List <ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Right.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); if (rowBufferCreationMode == RowBufferCreationMode.KeepExisting) { definedValue.Target = rowBufferEntry; } else { definedValue.Target = new RowBufferEntry(rowBufferEntry.DataType); } definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); definedValues.Add(definedValue); outputList.Add(definedValue.Target); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = outputList.ToArray(); return(computeScalarAlgebraNode); }
private AlgebraNode PushOverJoin(ComputeScalarAlgebraNode node) { JoinAlgebraNode joinAlgebraNode = (JoinAlgebraNode)node.Input; RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(joinAlgebraNode.Right); List <ComputedValueDefinition> remainingValueDefinitions = new List <ComputedValueDefinition>(); List <ComputedValueDefinition> leftPushedValueDefinitions = new List <ComputedValueDefinition>(); List <ComputedValueDefinition> rightPushedValueDefinitions = new List <ComputedValueDefinition>(); bool canPushToLeftSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; bool canPushToRightSide = joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && joinAlgebraNode.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin; foreach (ComputedValueDefinition valueDefinition in node.DefinedValues) { RowBufferEntry[] referencedValues = AstUtil.GetRowBufferEntryReferences(valueDefinition.Expression); bool referencesProbeColumn = ArrayHelpers.Contains(referencedValues, joinAlgebraNode.ProbeBufferEntry); if (!referencesProbeColumn && canPushToLeftSide && AstUtil.DoesNotReference(referencedValues, rightDefinedValues)) { leftPushedValueDefinitions.Add(valueDefinition); } else if (!referencesProbeColumn && canPushToRightSide && AstUtil.DoesNotReference(referencedValues, leftDefinedValues)) { rightPushedValueDefinitions.Add(valueDefinition); } else { remainingValueDefinitions.Add(valueDefinition); } } if (leftPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = leftPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Left; joinAlgebraNode.Left = VisitAlgebraNode(computeScalarAlgebraNode); } if (rightPushedValueDefinitions.Count > 0) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.DefinedValues = rightPushedValueDefinitions.ToArray(); computeScalarAlgebraNode.Input = joinAlgebraNode.Right; joinAlgebraNode.Right = VisitAlgebraNode(computeScalarAlgebraNode); } if (remainingValueDefinitions.Count == 0) { return(joinAlgebraNode); } node.DefinedValues = remainingValueDefinitions.ToArray(); return(node); }
private static AlgebraNode PadLeftWithNullsOnRightSide(JoinAlgebraNode node, RowBufferCreationMode rowBufferCreationMode) { ComputeScalarAlgebraNode computeScalarAlgebraNode = new ComputeScalarAlgebraNode(); computeScalarAlgebraNode.Input = node.Left; List<RowBufferEntry> outputList = new List<RowBufferEntry>(); outputList.AddRange(node.Left.OutputList); List<ComputedValueDefinition> definedValues = new List<ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Right.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); if (rowBufferCreationMode == RowBufferCreationMode.KeepExisting) { definedValue.Target = rowBufferEntry; } else { definedValue.Target = new RowBufferEntry(rowBufferEntry.DataType); } definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); definedValues.Add(definedValue); outputList.Add(definedValue.Target); } computeScalarAlgebraNode.DefinedValues = definedValues.ToArray(); computeScalarAlgebraNode.OutputList = outputList.ToArray(); return computeScalarAlgebraNode; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { base.VisitJoinAlgebraNode(node); if (node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { // TODO: Check if we could represent this join condition by an hash match operator JoinAlgebraNode leftOuterJoinNode = new JoinAlgebraNode(); leftOuterJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; leftOuterJoinNode.Predicate = (ExpressionNode)node.Predicate.Clone(); leftOuterJoinNode.Left = (AlgebraNode) node.Left.Clone(); leftOuterJoinNode.Right = (AlgebraNode) node.Right.Clone(); leftOuterJoinNode.OutputList = ArrayHelpers.Clone(node.OutputList); List<RowBufferEntry> swappedOutputList = new List<RowBufferEntry>(); swappedOutputList.AddRange(node.Right.OutputList); swappedOutputList.AddRange(node.Left.OutputList); JoinAlgebraNode leftAntiSemiJoinNode = new JoinAlgebraNode(); leftAntiSemiJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin; leftAntiSemiJoinNode.Predicate = (ExpressionNode) node.Predicate.Clone(); leftAntiSemiJoinNode.Left = (AlgebraNode) node.Right.Clone(); leftAntiSemiJoinNode.Right = (AlgebraNode) node.Left.Clone(); leftAntiSemiJoinNode.OutputList = swappedOutputList.ToArray(); List<ComputedValueDefinition> computeScalareDefinedValues = new List<ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Left.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rowBufferEntry; definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); computeScalareDefinedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarNode = new ComputeScalarAlgebraNode(); computeScalarNode.Input = leftAntiSemiJoinNode; computeScalarNode.DefinedValues = computeScalareDefinedValues.ToArray(); computeScalarNode.OutputList = swappedOutputList.ToArray(); List<UnitedValueDefinition> concatDefinedValues = new List<UnitedValueDefinition>(); for (int i = 0; i < node.OutputList.Length; i++) { RowBufferEntry rowBufferEntry = node.OutputList[i]; UnitedValueDefinition concatDefinedValue = new UnitedValueDefinition(); concatDefinedValue.Target = rowBufferEntry; concatDefinedValue.DependendEntries = new RowBufferEntry[] { node.OutputList[i], node.OutputList[i] }; concatDefinedValues.Add(concatDefinedValue); } ConcatAlgebraNode concatenationNode = new ConcatAlgebraNode(); concatenationNode.Inputs = new AlgebraNode[] {leftOuterJoinNode, computeScalarNode}; concatenationNode.DefinedValues = concatDefinedValues.ToArray(); concatenationNode.OutputList = swappedOutputList.ToArray(); return concatenationNode; } return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Reorder // // A LSJ (B LOJ C) ---> (A LOJ C) LSJ B (LOJ has no join condition and C produces at most one row) if (node.Op == JoinAlgebraNode.JoinOperator.LeftSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin) { JoinAlgebraNode rightChildJoin = node.Right as JoinAlgebraNode; if (rightChildJoin != null && rightChildJoin.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin && rightChildJoin.Predicate == null && AstUtil.WillProduceAtMostOneRow(rightChildJoin.Right)) { node.Right = rightChildJoin.Left; rightChildJoin.Left = node.Left; node.Left = rightChildJoin; return VisitAlgebraNode(node); } } node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // For easier handling we replace right operations by equivalent // left operations. if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin) { node.SwapSides(); return(VisitAlgebraNode(node)); } // Visit children bool semiJoinContext; semiJoinContext = (node.Op == JoinAlgebraNode.JoinOperator.RightSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin); _semiJoinContextFlagStack.Push(semiJoinContext); node.Left = VisitAlgebraNode(node.Left); _semiJoinContextFlagStack.Pop(); semiJoinContext = (node.Op == JoinAlgebraNode.JoinOperator.LeftSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin); _semiJoinContextFlagStack.Push(semiJoinContext); node.Right = VisitAlgebraNode(node.Right); _semiJoinContextFlagStack.Pop(); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { base.VisitJoinAlgebraNode(node); if (node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { // TODO: Check if we could represent this join condition by an hash match operator JoinAlgebraNode leftOuterJoinNode = new JoinAlgebraNode(); leftOuterJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; leftOuterJoinNode.Predicate = (ExpressionNode)node.Predicate.Clone(); leftOuterJoinNode.Left = (AlgebraNode)node.Left.Clone(); leftOuterJoinNode.Right = (AlgebraNode)node.Right.Clone(); leftOuterJoinNode.OutputList = ArrayHelpers.Clone(node.OutputList); List <RowBufferEntry> swappedOutputList = new List <RowBufferEntry>(); swappedOutputList.AddRange(node.Right.OutputList); swappedOutputList.AddRange(node.Left.OutputList); JoinAlgebraNode leftAntiSemiJoinNode = new JoinAlgebraNode(); leftAntiSemiJoinNode.Op = JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin; leftAntiSemiJoinNode.Predicate = (ExpressionNode)node.Predicate.Clone(); leftAntiSemiJoinNode.Left = (AlgebraNode)node.Right.Clone(); leftAntiSemiJoinNode.Right = (AlgebraNode)node.Left.Clone(); leftAntiSemiJoinNode.OutputList = swappedOutputList.ToArray(); List <ComputedValueDefinition> computeScalareDefinedValues = new List <ComputedValueDefinition>(); foreach (RowBufferEntry rowBufferEntry in node.Left.OutputList) { ComputedValueDefinition definedValue = new ComputedValueDefinition(); definedValue.Target = rowBufferEntry; definedValue.Expression = LiteralExpression.FromTypedNull(rowBufferEntry.DataType); computeScalareDefinedValues.Add(definedValue); } ComputeScalarAlgebraNode computeScalarNode = new ComputeScalarAlgebraNode(); computeScalarNode.Input = leftAntiSemiJoinNode; computeScalarNode.DefinedValues = computeScalareDefinedValues.ToArray(); computeScalarNode.OutputList = swappedOutputList.ToArray(); List <UnitedValueDefinition> concatDefinedValues = new List <UnitedValueDefinition>(); for (int i = 0; i < node.OutputList.Length; i++) { RowBufferEntry rowBufferEntry = node.OutputList[i]; UnitedValueDefinition concatDefinedValue = new UnitedValueDefinition(); concatDefinedValue.Target = rowBufferEntry; concatDefinedValue.DependendEntries = new RowBufferEntry[] { node.OutputList[i], node.OutputList[i] }; concatDefinedValues.Add(concatDefinedValue); } ConcatAlgebraNode concatenationNode = new ConcatAlgebraNode(); concatenationNode.Inputs = new AlgebraNode[] { leftOuterJoinNode, computeScalarNode }; concatenationNode.DefinedValues = concatDefinedValues.ToArray(); concatenationNode.OutputList = swappedOutputList.ToArray(); return(concatenationNode); } return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Reorder // // A LSJ (B LOJ C) ---> (A LOJ C) LSJ B (LOJ has no join condition and C produces at most one row) if (node.Op == JoinAlgebraNode.JoinOperator.LeftSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin) { JoinAlgebraNode rightChildJoin = node.Right as JoinAlgebraNode; if (rightChildJoin != null && rightChildJoin.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin && rightChildJoin.Predicate == null && AstUtil.WillProduceAtMostOneRow(rightChildJoin.Right)) { node.Right = rightChildJoin.Left; rightChildJoin.Left = node.Left; node.Left = rightChildJoin; return(VisitAlgebraNode(node)); } } node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { Visit(node.Left); Visit(node.Right); _definedValueEntries.Add(node.ProbeBufferEntry); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { Visit(node.Left); Visit(node.Right); _definedValueEntries.Add(node.ProbeBufferEntry); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { Visit(node.Left); Visit(node.Right); node.OuterReferences = AstUtil.GetOuterReferences(node); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { Visit(node.Left); Visit(node.Right); node.OuterReferences = AstUtil.GetOuterReferences(node); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { base.VisitJoinAlgebraNode(node); if (node.ProbeBufferEntry != null) NameEntry(node.ProbeBufferEntry, EXPRESSION_NAME_FMT_STR); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { base.VisitJoinAlgebraNode(node); if (node.ProbeBufferEntry != null) { NameEntry(node.ProbeBufferEntry, EXPRESSION_NAME_FMT_STR); } return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Get declared tables of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); // Analyze AND-parts of Condition if (node.Predicate != null) { List<ExpressionNode> leftAndParts = new List<ExpressionNode>(); List<ExpressionNode> rightAndParts = new List<ExpressionNode>(); List<ExpressionNode> remainingAndParts = new List<ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { // Check if we can push this AND-part down. if (AstUtil.AllowsLeftPushDown(node.Op) && AstUtil.ExpressionDoesNotReference(andPart, rightDefinedValues)) { leftAndParts.Add(andPart); } else if (AstUtil.AllowsRightPushDown(node.Op) && AstUtil.ExpressionDoesNotReference(andPart, leftDefinedValues)) { rightAndParts.Add(andPart); } else { remainingAndParts.Add(andPart); } } if (leftAndParts.Count > 0) { node.Left = GetFilterFromAndParts(leftAndParts, node.Left); } if (rightAndParts.Count > 0) { node.Right = GetFilterFromAndParts(rightAndParts, node.Right); } node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); } // Visit children node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Get declared tables of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); // Analyze AND-parts of Condition if (node.Predicate != null) { List <ExpressionNode> leftAndParts = new List <ExpressionNode>(); List <ExpressionNode> rightAndParts = new List <ExpressionNode>(); List <ExpressionNode> remainingAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { // Check if we can push this AND-part down. if (AstUtil.AllowsLeftPushDown(node.Op) && AstUtil.ExpressionDoesNotReference(andPart, rightDefinedValues)) { leftAndParts.Add(andPart); } else if (AstUtil.AllowsRightPushDown(node.Op) && AstUtil.ExpressionDoesNotReference(andPart, leftDefinedValues)) { rightAndParts.Add(andPart); } else { remainingAndParts.Add(andPart); } } if (leftAndParts.Count > 0) { node.Left = GetFilterFromAndParts(leftAndParts, node.Left); } if (rightAndParts.Count > 0) { node.Right = GetFilterFromAndParts(rightAndParts, node.Right); } node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); } // Visit children node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { ShowPlanElement leftElement = ConvertNode(node.Left); ShowPlanElement rightElement = ConvertNode(node.Right); PropertyListBuilder propertyListBuilder = new PropertyListBuilder(); AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOutputList, node.OutputList); propertyListBuilder.Write(Resources.ShowPlanKeyLogicalOperator, LogicalOperatorToString(node.Op)); AddStatistics(propertyListBuilder, node.StatisticsIterator); if (node.Predicate != null) { propertyListBuilder.Write(Resources.ShowPlanKeyPredicate, node.Predicate.GenerateSource()); } if (node.OuterReferences != null && node.OuterReferences.Length > 0) { AddRowBufferEntries(propertyListBuilder, Resources.ShowPlanGroupOuterReferences, node.OuterReferences); } if (node.ProbeBufferEntry != null) { WriteRowBufferEntry(propertyListBuilder, Resources.ShowPlanKeyProbeColumn, node.ProbeBufferEntry); } if (node.PassthruPredicate != null) { propertyListBuilder.Write(Resources.ShowPlanKeyPassthru, node.PassthruPredicate.GenerateSource()); } // We give a warning if a join has no predicate and no outer reference. // In this case the join would simply multiply the other side. // However, we supppress the warning if any side is known at produce at // most one row. if (node.Predicate == null && (node.OuterReferences == null || node.OuterReferences.Length == 0) && !AstUtil.WillProduceAtMostOneRow(node.Left) && !AstUtil.WillProduceAtMostOneRow(node.Right)) { propertyListBuilder.Write(Resources.ShowPlanKeyWarning, Resources.ShowPlanWarningNoJoinPredicate); } IList <ShowPlanProperty> properties = propertyListBuilder.ToList(); ShowPlanElement element = new ShowPlanElement(ShowPlanOperator.NestedLoops, properties, leftElement, rightElement); _currentElement = element; return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); RowBufferEntry[] outerReferences = AstUtil.GetOuterReferences(node); if (outerReferences != null && outerReferences.Length > 0) _outerReferences.Push(node.OuterReferences); node.Right = VisitAlgebraNode(node.Right); if (outerReferences != null && outerReferences.Length > 0) _outerReferences.Pop(); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { _xmlWriter.WriteStartElement("joinAlgebraNode"); _xmlWriter.WriteAttributeString("op", node.Op.ToString()); WriteRowBufferEntries("externalColumnDependencies", node.OuterReferences); WriteAstNode("leftNode", node.Left); WriteAstNode("rightNode", node.Right); WriteAstNode("joinCondition", node.Predicate); _xmlWriter.WriteEndElement(); return(node); }
private static bool SemiJoinDoesNotDependOn(JoinAlgebraNode.JoinOperator op, ExpressionNode part, RowBufferEntry[] leftDefinedValues, RowBufferEntry[] rightDefinedValues) { if (op == JoinAlgebraNode.JoinOperator.LeftSemiJoin || op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin) { return AstUtil.ExpressionDoesNotReference(part, rightDefinedValues); } if (op == JoinAlgebraNode.JoinOperator.RightSemiJoin || op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin) { return AstUtil.ExpressionDoesNotReference(part, leftDefinedValues); } return true; }
public override AstElement Clone(Dictionary <AstElement, AstElement> alreadyClonedElements) { JoinAlgebraNode result = new JoinAlgebraNode(); result.StatisticsIterator = StatisticsIterator; result.OutputList = ArrayHelpers.Clone(OutputList); result.Left = (AlgebraNode)_left.Clone(alreadyClonedElements); result.Right = (AlgebraNode)_right.Clone(alreadyClonedElements); result.Op = _op; if (_predicate != null) { result.Predicate = (ExpressionNode)_predicate.Clone(alreadyClonedElements); } result.OuterReferences = ArrayHelpers.Clone(_outerReferences); return(result); }
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 static RowBufferEntry[] GetOuterReferences(JoinAlgebraNode node) { RowBufferEntry[] leftDefinedValues = GetDefinedValueEntries(node.Left); RowBufferEntry[] rowBufferEntries = GetRowBufferEntryReferences(node.Right); List <RowBufferEntry> outerReferenceList = new List <RowBufferEntry>(); foreach (RowBufferEntry rightColumnDependency in rowBufferEntries) { if (ArrayHelpers.Contains(leftDefinedValues, rightColumnDependency)) { outerReferenceList.Add(rightColumnDependency); } } return(outerReferenceList.ToArray()); }
public virtual AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); if (node.Predicate != null) { node.Predicate = VisitExpression(node.Predicate); } if (node.PassthruPredicate != null) { node.PassthruPredicate = VisitExpression(node.PassthruPredicate); } return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); List <RowBufferEntry> outputList = new List <RowBufferEntry>(); outputList.AddRange(node.Left.OutputList); outputList.AddRange(node.Right.OutputList); if (node.ProbeBufferEntry != null) { outputList.Add(node.ProbeBufferEntry); } node.OutputList = outputList.ToArray(); return(node); }
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 override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { if (node.Op != JoinAlgebraNode.JoinOperator.InnerJoin) { _consistsOnlyOfInnerJoinsFiltersAndTables = false; return(node); } if (node.Predicate != null) { _filters.Add(node.Predicate); } Visit(node.Left); Visit(node.Right); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // A IJ (B J C) --> (A IJ B) J C node.Left = VisitAlgebraNode(node.Left); if (node.Op != JoinAlgebraNode.JoinOperator.InnerJoin) return node; JoinAlgebraNode rightSide = node.Right as JoinAlgebraNode; if (rightSide == null) return node; node.Right = rightSide.Left; rightSide.Left = node; return VisitAlgebraNode(rightSide); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); RowBufferEntry[] outerReferences = AstUtil.GetOuterReferences(node); if (outerReferences != null && outerReferences.Length > 0) { _outerReferences.Push(node.OuterReferences); } node.Right = VisitAlgebraNode(node.Right); if (outerReferences != null && outerReferences.Length > 0) { _outerReferences.Pop(); } return(node); }
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 override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // A IJ (B J C) --> (A IJ B) J C node.Left = VisitAlgebraNode(node.Left); if (node.Op != JoinAlgebraNode.JoinOperator.InnerJoin) { return(node); } JoinAlgebraNode rightSide = node.Right as JoinAlgebraNode; if (rightSide == null) { return(node); } node.Right = rightSide.Left; rightSide.Left = node; return(VisitAlgebraNode(rightSide)); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.OutputList = RemovedUnneededRowBufferColumns(node.OutputList); if (node.Predicate != null) { AddNeededRowBufferEntryReferences(node.Predicate); } if (node.PassthruPredicate != null) { AddNeededRowBufferEntryReferences(node.PassthruPredicate); } if (node.OuterReferences != null) { foreach (RowBufferEntry outerReference in node.OuterReferences) { AddNeededRowBufferEntry(outerReference); } } return(base.VisitJoinAlgebraNode(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 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); } }
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 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 AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Get declared tables of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); // Replace outer joins by left-/right-/inner joins if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { if (IsAnyNullRejected(leftDefinedValues)) { if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; else node.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; } } if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { if (IsAnyNullRejected(rightDefinedValues)) { if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; else node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; } } // After converting an outer join to an inner one we can // sometimes eliminate the whole join. if (node.Op == JoinAlgebraNode.JoinOperator.InnerJoin) { // TODO: There is a problem. If the constant scan defines values this does not work. Acutally, // this is currently no problem as the only way to create such a plan is using derived // tables and in this phase the child will be a ResultNode. if (node.Left is ConstantScanAlgebraNode) return VisitAlgebraNode(WrapWithFilter(node.Right, node.Predicate)); if (node.Right is ConstantScanAlgebraNode) return VisitAlgebraNode(WrapWithFilter(node.Left, node.Predicate)); } // Analyze AND-parts of Condition if (node.Predicate == null) { // TODO: This does not work as the children are not yet rearranged. if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) { bool hasOuterReferences = AstUtil.GetOuterReferences(node).Length == 0; if (!hasOuterReferences) { if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin && AstUtil.WillProduceAtLeastOneRow(node.Right) || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin && AstUtil.WillProduceAtLeastOneRow(node.Left)) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; return VisitAlgebraNode(node); } } } } else { foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { if (node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { // Check if we can derive from this AND-part that a table it depends on // is null-rejected. RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart); foreach (RowBufferEntry rowBufferEntry in rowBufferEntries) { if (AstUtil.ExpressionYieldsNullOrFalseIfRowBufferEntryNull(andPart, rowBufferEntry)) { if (ArrayHelpers.Contains(leftDefinedValues, rowBufferEntry) && node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin) { AddNullRejectedTable(rowBufferEntry); } else if (ArrayHelpers.Contains(rightDefinedValues, rowBufferEntry) && node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin) { AddNullRejectedTable(rowBufferEntry); } } } } } } // Visit children node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return node; }
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 static RowBufferEntry[] GetOuterReferences(JoinAlgebraNode node) { RowBufferEntry[] leftDefinedValues = GetDefinedValueEntries(node.Left); RowBufferEntry[] rowBufferEntries = GetRowBufferEntryReferences(node.Right); List<RowBufferEntry> outerReferenceList = new List<RowBufferEntry>(); foreach (RowBufferEntry rightColumnDependency in rowBufferEntries) { if (ArrayHelpers.Contains(leftDefinedValues, rightColumnDependency)) outerReferenceList.Add(rightColumnDependency); } return outerReferenceList.ToArray(); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); // Reorder (pull LOJ out of IJ) // // (A LOJ B) IJ C ---> (A IJ C) LOJ B (IJ does not depend on B) // (A ROJ B) IJ C ---> A ROJ (B IJ C) (IJ does not depend on A) if (node.Op == JoinAlgebraNode.JoinOperator.InnerJoin) { JoinAlgebraNode childJoin = node.Left as JoinAlgebraNode; if (childJoin != null && (childJoin.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || childJoin.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin)) { if (childJoin.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) { if (AstUtil.JoinDoesNotDependOn(node, childJoin.Right)) { node.Left = childJoin.Left; childJoin.Left = node; return(VisitAlgebraNode(childJoin)); } } else if (childJoin.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) { if (AstUtil.JoinDoesNotDependOn(node, childJoin.Left)) { node.Left = childJoin.Right; childJoin.Right = node; return(VisitAlgebraNode(childJoin)); } } } } //// Reorder (push LSJ) //// //// (A J B) LSJ C ---> (A LSJ C) J B (LSJ does not depend on B) //// (A J B) LSJ C ---> A J (B LSJ C) (LSJ does not depend on A) //if (node.Op == JoinAlgebraNode.JoinOperator.LeftSemiJoin || // node.Op == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin) //{ // JoinAlgebraNode childJoin = node.Left as JoinAlgebraNode; // if (childJoin != null) // { // if (AstUtil.JoinDoesNotDependOn(node, childJoin.Right)) // { // node.Left = childJoin.Left; // childJoin.Left = node; // return VisitAlgebraNode(childJoin); // } // if (AstUtil.JoinDoesNotDependOn(node, childJoin.Left)) // { // node.Left = childJoin.Right; // childJoin.Right = node; // return VisitAlgebraNode(childJoin); // } // } //} return(node); }
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 static bool AllowsRightPushDown(JoinAlgebraNode.JoinOperator joinOperator) { return joinOperator == JoinAlgebraNode.JoinOperator.InnerJoin || joinOperator == JoinAlgebraNode.JoinOperator.LeftOuterJoin || joinOperator == JoinAlgebraNode.JoinOperator.LeftSemiJoin || joinOperator == JoinAlgebraNode.JoinOperator.RightSemiJoin || joinOperator == JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin || joinOperator == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin; }
public virtual AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); if (node.Predicate != null) node.Predicate = VisitExpression(node.Predicate); if (node.PassthruPredicate != null) node.PassthruPredicate = VisitExpression(node.PassthruPredicate); return node; }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); List<RowBufferEntry> outputList = new List<RowBufferEntry>(); outputList.AddRange(node.Left.OutputList); outputList.AddRange(node.Right.OutputList); if (node.ProbeBufferEntry != null) outputList.Add(node.ProbeBufferEntry); node.OutputList = outputList.ToArray(); return node; }
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; }
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 void UpdatePredicateRowBufferReferences(NestedLoopsIterator nestedLoopsIterator, JoinAlgebraNode node) { BoundRowBufferEntrySet leftBoundRowBufferEntrySet = new BoundRowBufferEntrySet(nestedLoopsIterator.Left.RowBuffer, node.Left.OutputList); BoundRowBufferEntrySet rightBoundRowBufferEntrySet = new BoundRowBufferEntrySet(nestedLoopsIterator.Right.RowBuffer, node.Right.OutputList); if (node.Predicate != null) nestedLoopsIterator.Predicate = CreateRuntimeExpression(node.Predicate, leftBoundRowBufferEntrySet, rightBoundRowBufferEntrySet); if (node.PassthruPredicate != null) nestedLoopsIterator.PassthruPredicate = CreateRuntimeExpression(node.PassthruPredicate, leftBoundRowBufferEntrySet, rightBoundRowBufferEntrySet); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); // Get defined values of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); List<ExpressionNode> andPartsWithinJoin = new List<ExpressionNode>(); // Try to pull up AND-parts that contain outer references from a left sided filter and combine // them with the join predicate. // // NOTE: This is only possible if the join is not a LEFT OUTER or FULL OUTER JOIN since this // operation would change the join's semantic. if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { FilterAlgebraNode leftAsFilter = node.Left as FilterAlgebraNode; if (leftAsFilter != null) { List<ExpressionNode> remainingAndParts = new List<ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, leftAsFilter.Predicate)) { if (AndPartHasOuterReference(andPart, leftDefinedValues)) andPartsWithinJoin.Add(andPart); else remainingAndParts.Add(andPart); } leftAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (leftAsFilter.Predicate == null) node.Left = leftAsFilter.Input; } } // Try to pull up AND-parts that contain outer references from a right sided filter and combine // them with the join predicate. // // NOTE: This is only possible if the join is not a RIGHT OUTER or FULL OUTER JOIN since this // operation would change the join's semantic. if (node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { FilterAlgebraNode rightAsFilter = node.Right as FilterAlgebraNode; if (rightAsFilter != null) { List<ExpressionNode> remainingAndParts = new List<ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, rightAsFilter.Predicate)) { if (AndPartHasOuterReference(andPart, rightDefinedValues)) andPartsWithinJoin.Add(andPart); else remainingAndParts.Add(andPart); } rightAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (rightAsFilter.Predicate == null) node.Right = rightAsFilter.Input; } } // If we found any AND-parts that could be pulled up, merge them with the join predicate. if (andPartsWithinJoin.Count > 0) node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, node.Predicate, AstUtil.CombineConditions(LogicalOperator.And, andPartsWithinJoin)); // Now we try to extract AND-parts that contain outer references from the join predicate itself. // // NOTE: This is only possible if the node is not an OUTER JOIN. If the node is a SEMI JOIN the // operation is only legal if the AND-part does not reference any columns from the side that is // is used as filter criteria (i.e. for LSJ this is the right side, for RSJ this is the left // side). if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin && node.Predicate != null) { List<ExpressionNode> andPartsAboveJoin = new List<ExpressionNode>(); List<ExpressionNode> remainingAndParts = new List<ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { if (AndPartHasOuterReference(andPart, leftDefinedValues, rightDefinedValues) && SemiJoinDoesNotDependOn(node.Op, andPart, leftDefinedValues, rightDefinedValues)) andPartsAboveJoin.Add(andPart); else remainingAndParts.Add(andPart); } node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (andPartsAboveJoin.Count > 0) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andPartsAboveJoin); filterAlgebraNode.Input = node; return filterAlgebraNode; } } return node; }
public override AstElement Clone(Dictionary<AstElement, AstElement> alreadyClonedElements) { JoinAlgebraNode result = new JoinAlgebraNode(); result.StatisticsIterator = StatisticsIterator; result.OutputList = ArrayHelpers.Clone(OutputList); result.Left = (AlgebraNode)_left.Clone(alreadyClonedElements); result.Right = (AlgebraNode)_right.Clone(alreadyClonedElements); result.Op = _op; if (_predicate != null) result.Predicate = (ExpressionNode)_predicate.Clone(alreadyClonedElements); result.OuterReferences = ArrayHelpers.Clone(_outerReferences); return result; }
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); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); // Get defined values of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); List <ExpressionNode> andPartsWithinJoin = new List <ExpressionNode>(); // Try to pull up AND-parts that contain outer references from a left sided filter and combine // them with the join predicate. // // NOTE: This is only possible if the join is not a LEFT OUTER or FULL OUTER JOIN since this // operation would change the join's semantic. if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { FilterAlgebraNode leftAsFilter = node.Left as FilterAlgebraNode; if (leftAsFilter != null) { List <ExpressionNode> remainingAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, leftAsFilter.Predicate)) { if (AndPartHasOuterReference(andPart, leftDefinedValues)) { andPartsWithinJoin.Add(andPart); } else { remainingAndParts.Add(andPart); } } leftAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (leftAsFilter.Predicate == null) { node.Left = leftAsFilter.Input; } } } // Try to pull up AND-parts that contain outer references from a right sided filter and combine // them with the join predicate. // // NOTE: This is only possible if the join is not a RIGHT OUTER or FULL OUTER JOIN since this // operation would change the join's semantic. if (node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { FilterAlgebraNode rightAsFilter = node.Right as FilterAlgebraNode; if (rightAsFilter != null) { List <ExpressionNode> remainingAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, rightAsFilter.Predicate)) { if (AndPartHasOuterReference(andPart, rightDefinedValues)) { andPartsWithinJoin.Add(andPart); } else { remainingAndParts.Add(andPart); } } rightAsFilter.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (rightAsFilter.Predicate == null) { node.Right = rightAsFilter.Input; } } } // If we found any AND-parts that could be pulled up, merge them with the join predicate. if (andPartsWithinJoin.Count > 0) { node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, node.Predicate, AstUtil.CombineConditions(LogicalOperator.And, andPartsWithinJoin)); } // Now we try to extract AND-parts that contain outer references from the join predicate itself. // // NOTE: This is only possible if the node is not an OUTER JOIN. If the node is a SEMI JOIN the // operation is only legal if the AND-part does not reference any columns from the side that is // is used as filter criteria (i.e. for LSJ this is the right side, for RSJ this is the left // side). if (node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin && node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin && node.Predicate != null) { List <ExpressionNode> andPartsAboveJoin = new List <ExpressionNode>(); List <ExpressionNode> remainingAndParts = new List <ExpressionNode>(); foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { if (AndPartHasOuterReference(andPart, leftDefinedValues, rightDefinedValues) && SemiJoinDoesNotDependOn(node.Op, andPart, leftDefinedValues, rightDefinedValues)) { andPartsAboveJoin.Add(andPart); } else { remainingAndParts.Add(andPart); } } node.Predicate = AstUtil.CombineConditions(LogicalOperator.And, remainingAndParts); if (andPartsAboveJoin.Count > 0) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.And, andPartsAboveJoin); filterAlgebraNode.Input = node; return(filterAlgebraNode); } } return(node); }
private void PushOuterReferences(object[] rowBuffer, JoinAlgebraNode node) { if (node.OuterReferences != null && node.OuterReferences.Length > 0) { // Important: We cannot use node.OuterReferences as argument for BoundRowBufferEntrySet(). // The replacment strategy below will replace occurences to the entries by their index // within the array. Therefore we need an array with the same layout as the row buffer. RowBufferEntry[] outerReferences = new RowBufferEntry[node.Left.OutputList.Length]; for (int i = 0; i < outerReferences.Length; i++) { if (ArrayHelpers.Contains(node.OuterReferences, node.Left.OutputList[i])) outerReferences[i] = node.Left.OutputList[i]; } BoundRowBufferEntrySet bufferEntrySet = new BoundRowBufferEntrySet(rowBuffer, outerReferences); _outerReferenceStack.Push(bufferEntrySet); } }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { // Get declared tables of left and right RowBufferEntry[] leftDefinedValues = AstUtil.GetDefinedValueEntries(node.Left); RowBufferEntry[] rightDefinedValues = AstUtil.GetDefinedValueEntries(node.Right); // Replace outer joins by left-/right-/inner joins if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { if (IsAnyNullRejected(leftDefinedValues)) { if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; } else { node.Op = JoinAlgebraNode.JoinOperator.LeftOuterJoin; } } } if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.FullOuterJoin) { if (IsAnyNullRejected(rightDefinedValues)) { if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; } else { node.Op = JoinAlgebraNode.JoinOperator.RightOuterJoin; } } } // After converting an outer join to an inner one we can // sometimes eliminate the whole join. if (node.Op == JoinAlgebraNode.JoinOperator.InnerJoin) { // TODO: There is a problem. If the constant scan defines values this does not work. Acutally, // this is currently no problem as the only way to create such a plan is using derived // tables and in this phase the child will be a ResultNode. if (node.Left is ConstantScanAlgebraNode) { return(VisitAlgebraNode(WrapWithFilter(node.Right, node.Predicate))); } if (node.Right is ConstantScanAlgebraNode) { return(VisitAlgebraNode(WrapWithFilter(node.Left, node.Predicate))); } } // Analyze AND-parts of Condition if (node.Predicate == null) { // TODO: This does not work as the children are not yet rearranged. if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin) { bool hasOuterReferences = AstUtil.GetOuterReferences(node).Length == 0; if (!hasOuterReferences) { if (node.Op == JoinAlgebraNode.JoinOperator.LeftOuterJoin && AstUtil.WillProduceAtLeastOneRow(node.Right) || node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin && AstUtil.WillProduceAtLeastOneRow(node.Left)) { node.Op = JoinAlgebraNode.JoinOperator.InnerJoin; return(VisitAlgebraNode(node)); } } } } else { foreach (ExpressionNode andPart in AstUtil.SplitCondition(LogicalOperator.And, node.Predicate)) { if (node.Op != JoinAlgebraNode.JoinOperator.FullOuterJoin) { // Check if we can derive from this AND-part that a table it depends on // is null-rejected. RowBufferEntry[] rowBufferEntries = AstUtil.GetRowBufferEntryReferences(andPart); foreach (RowBufferEntry rowBufferEntry in rowBufferEntries) { if (AstUtil.ExpressionYieldsNullOrFalseIfRowBufferEntryNull(andPart, rowBufferEntry)) { if (ArrayHelpers.Contains(leftDefinedValues, rowBufferEntry) && node.Op != JoinAlgebraNode.JoinOperator.LeftOuterJoin) { AddNullRejectedTable(rowBufferEntry); } else if (ArrayHelpers.Contains(rightDefinedValues, rowBufferEntry) && node.Op != JoinAlgebraNode.JoinOperator.RightOuterJoin) { AddNullRejectedTable(rowBufferEntry); } } } } } } // Visit children node.Left = VisitAlgebraNode(node.Left); node.Right = VisitAlgebraNode(node.Right); return(node); }
public override AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { if (node.Op == JoinAlgebraNode.JoinOperator.RightOuterJoin || node.Op == JoinAlgebraNode.JoinOperator.RightAntiSemiJoin || node.Op == JoinAlgebraNode.JoinOperator.RightSemiJoin) { if (node.OuterReferences != null && node.OuterReferences.Length > 0) throw ExceptionBuilder.InternalError("Outer references should not be possible for {0} and are not supported.", node.Op); node.SwapSides(); } NestedLoopsIterator nestedLoopsIterator; switch (node.Op) { case JoinAlgebraNode.JoinOperator.InnerJoin: nestedLoopsIterator = new InnerNestedLoopsIterator(); break; case JoinAlgebraNode.JoinOperator.LeftOuterJoin: nestedLoopsIterator = new LeftOuterNestedLoopsIterator(); break; case JoinAlgebraNode.JoinOperator.LeftSemiJoin: if (node.ProbeBufferEntry == null) nestedLoopsIterator = new LeftSemiNestedLoopsIterator(); else { ProbedSemiJoinNestedLoopsIterator probedSemiJoinNestedLoopsIterator = new ProbedSemiJoinNestedLoopsIterator(); probedSemiJoinNestedLoopsIterator.ProbeOutput = GetDefinedValue(node.OutputList, node.ProbeBufferEntry); nestedLoopsIterator = probedSemiJoinNestedLoopsIterator; } break; case JoinAlgebraNode.JoinOperator.LeftAntiSemiJoin: if (node.ProbeBufferEntry == null) nestedLoopsIterator = new LeftAntiSemiNestedLoopsIterator(); else { ProbedAntiSemiJoinNestedLoopsIterator probedSemiJoinNestedLoopsIterator = new ProbedAntiSemiJoinNestedLoopsIterator(); probedSemiJoinNestedLoopsIterator.ProbeOutput = GetDefinedValue(node.OutputList, node.ProbeBufferEntry); nestedLoopsIterator = probedSemiJoinNestedLoopsIterator; } break; default: throw ExceptionBuilder.UnhandledCaseLabel(node.Op); } nestedLoopsIterator.RowBuffer = new object[node.OutputList.Length]; nestedLoopsIterator.Left = ConvertAlgebraNode(node.Left); nestedLoopsIterator.LeftOutput = GetIteratorOutput(0, node.Left.OutputList, node.OutputList); PushOuterReferences(nestedLoopsIterator.Left.RowBuffer, node); nestedLoopsIterator.Right = ConvertAlgebraNode(node.Right); nestedLoopsIterator.RightOutput = GetIteratorOutput(nestedLoopsIterator.LeftOutput.Length, node.Right.OutputList, node.OutputList); UpdatePredicateRowBufferReferences(nestedLoopsIterator, node); if (node.OuterReferences != null && node.OuterReferences.Length > 0) _outerReferenceStack.Pop(); SetLastIterator(node, nestedLoopsIterator); return node; }
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; } }
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 AlgebraNode VisitJoinAlgebraNode(JoinAlgebraNode node) { if (node.Op != JoinAlgebraNode.JoinOperator.InnerJoin) { _consistsOnlyOfInnerJoinsFiltersAndTables = false; return node; } if (node.Predicate != null) _filters.Add(node.Predicate); Visit(node.Left); Visit(node.Right); return node; }
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 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); }