public override AstNode Visit(AstNode node) { if (!(node is ExpressionNode)) { // Non-expressions are visited as usual. return(base.Visit(node)); } // First, we only visit expressions that contain a subquery. // // For correct handling of ProbeColumn we to decect whether probing // is required or not. Probing is only needed if the existance subquery // appears in an expression that is not a logical AND or logical OR (or // an existence subquery itself). if (AstUtil.ContainsSubselect(node)) { BinaryExpression binaryExpression = node as BinaryExpression; bool isLogicalLink = binaryExpression != null && (binaryExpression.Op == BinaryOperator.LogicalAnd || binaryExpression.Op == BinaryOperator.LogicalOr); bool isExistenceSubquery = node.NodeType == AstNodeType.AllAnySubselect || node.NodeType == AstNodeType.ExistsSubselect; bool requiresProbing = !isLogicalLink && !isExistenceSubquery; if (requiresProbing) { _probingEnabledStack.Push(true); } AstNode resultExpression = base.Visit(node); if (requiresProbing) { _probingEnabledStack.Pop(); } return(resultExpression); } // Don't visit expressions that do not contain suqueries. 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 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)); } }