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) { 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); }
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); } }