public void PushBinary(BinaryOperator binaryOperator) { ExpressionNode rightExpressionNode = _expressionStack.Pop(); ExpressionNode leftExpressionNode = _expressionStack.Pop(); BinaryExpression binaryExpression = new BinaryExpression(binaryOperator, leftExpressionNode, rightExpressionNode); _expressionStack.Push(binaryExpression); }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { if (expression.Op == BinaryOperator.LogicalOr) { // Special handling for logical OR: // For logical OR both arguments must be NULL to yield false/null. Visit(expression.Left); bool leftIsNullOrFalse = _lastExpressionsYieldsNullOrFalse; Visit(expression.Right); _lastExpressionsYieldsNullOrFalse = leftIsNullOrFalse && _lastExpressionsYieldsNullOrFalse; } else { // In all other cases we know the result will be false/null if // any operand is null. Visit(expression.Left); bool leftIsNullOrFalse = _lastExpressionsYieldsNullOrFalse; Visit(expression.Right); _lastExpressionsYieldsNullOrFalse = leftIsNullOrFalse || _lastExpressionsYieldsNullOrFalse; } return expression; }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { base.VisitBinaryExpression(expression); ConstantExpression leftConstant = expression.Left as ConstantExpression; ConstantExpression rightConstant = expression.Right as ConstantExpression; if (leftConstant != null && rightConstant != null) { // Both operands are constants, compute the result and return a constant node. try { return LiteralExpression.FromTypedValue(expression.GetValue(), expression.ExpressionType); } catch (RuntimeException ex) { _errorReporter.CannotFoldConstants(ex); } } else if ((leftConstant != null || rightConstant != null) && (expression.Op == BinaryOperator.LogicalAnd || expression.Op == BinaryOperator.LogicalOr)) { // We have a boolean AND or OR expression where one operand is a constant. Check if we // already know the result. if (expression.Op == BinaryOperator.LogicalAnd) { // Check if one operand is false if (leftConstant != null && !leftConstant.IsNullValue && !leftConstant.AsBoolean || rightConstant != null && !rightConstant.IsNullValue && !rightConstant.AsBoolean) return LiteralExpression.FromBoolean(false); } else { // Check if one operand is true if (leftConstant != null && !leftConstant.IsNullValue && leftConstant.AsBoolean || rightConstant != null && !rightConstant.IsNullValue && rightConstant.AsBoolean) return LiteralExpression.FromBoolean(true); } // We don't know the result but we can throw away the and/or expression // by replacing it with the unknown part. if (leftConstant != null && !leftConstant.IsNullValue) return expression.Right; else if (rightConstant != null && !rightConstant.IsNullValue) return expression.Left; return expression; } // If we getting here we return the orginal one. return expression; }
public override AstElement Clone(Dictionary<AstElement, AstElement> alreadyClonedElements) { BinaryExpression result = new BinaryExpression(); result.Op = _op; result.Left = (ExpressionNode) _left.Clone(alreadyClonedElements); result.Right = (ExpressionNode) _right.Clone(alreadyClonedElements); result.OperatorMethod = OperatorMethod; return result; }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { base.VisitBinaryExpression(expression); Type leftType = expression.Left.ExpressionType; Type rightType = expression.Right.ExpressionType; if (leftType == null || rightType == null) { expression.OperatorMethod = null; } else if (expression.Op == BinaryOperator.LogicalAnd ||expression.Op == BinaryOperator.LogicalOr) { // If an operand of this expression is of type NULL the whole expression would be of type // NULL (because any operator containing NULL will yield NULL). But Boolean conditions // are an exception to this rule. This is why there is no operator method in the builtin operators // that calculculates OR or AND. Instead, there is custom IL emitted for these operators. // // This expression will never use the operator method. The binder will return a placeholder. if (expression.Left.ExpressionType != typeof(bool) && expression.Left.ExpressionType != typeof(DBNull) || expression.Right.ExpressionType != typeof(bool) && expression.Right.ExpressionType != typeof(DBNull)) { // We only accept Boolean and NULL datatypes as argument to OR and AND. _errorReporter.CannotApplyOperator(expression.Op, expression.Left.ExpressionType, expression.Right.ExpressionType); } expression.OperatorMethod = _binder.BindOperator(expression.Op, typeof(bool), typeof(bool)); } else { expression.OperatorMethod = _binder.BindOperator(expression.Op, leftType, rightType); if (expression.OperatorMethod == null) { _errorReporter.CannotApplyOperator(expression.Op, leftType, rightType); } else { // Convert operands if necessary ParameterInfo[] opMethodParams = expression.OperatorMethod.GetParameters(); expression.Left = _binder.ConvertExpressionIfRequired(expression.Left, opMethodParams[0].ParameterType); expression.Right = _binder.ConvertExpressionIfRequired(expression.Right, opMethodParams[1].ParameterType); } } return expression; }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { if (expression.Op == BinaryOperator.LogicalAnd) { return base.VisitBinaryExpression(expression); } else if (expression.Op == BinaryOperator.Equal) { RowBufferEntry[] leftRowBufferEntries = AstUtil.GetRowBufferEntryReferences(expression.Left); RowBufferEntry[] rightRowBufferEntries = AstUtil.GetRowBufferEntryReferences(expression.Right); if (leftRowBufferEntries.Length == 1 && rightRowBufferEntries.Length == 1) { RowBufferEntry leftRowBufferEntry = leftRowBufferEntries[0]; RowBufferEntry rightRowBufferEntry = rightRowBufferEntries[0]; bool leftIsOuter = IsOuterReference(leftRowBufferEntry); bool rightIsOuter = IsOuterReference(rightRowBufferEntry); if (leftRowBufferEntry != rightRowBufferEntry && leftIsOuter ^ rightIsOuter) { // Both expressions depend on extactly one row buffer entry but // they are not refering to the same row buffer entry and // only one is an outer reference. SpoolExpression spoolExpression = new SpoolExpression(); if (leftIsOuter) { spoolExpression.IndexExpression = expression.Right; spoolExpression.ProbeExpression = expression.Left; } else { spoolExpression.IndexExpression = expression.Left; spoolExpression.ProbeExpression = expression.Right; } _spoolExpressions.Add(spoolExpression); return LiteralExpression.FromBoolean(true); } } } return expression; }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { // Emit left operand bool parenthesesNedded = NeedParentheses(expression.Left, expression.Op.Precedence, false); if (parenthesesNedded) _writer.Write("("); Visit(expression.Left); if (parenthesesNedded) _writer.Write(")"); // Emit operator _writer.Write(" "); _writer.Write(expression.Op.TokenText); _writer.Write(" "); // Emit right operand parenthesesNedded = NeedParentheses(expression.Right, expression.Op.Precedence, true); if (parenthesesNedded) _writer.Write("("); Visit(expression.Right); if (parenthesesNedded) _writer.Write(")"); return expression; }
private ExpressionNode ParseSubExpression(ExpressionNode left, int precedence) { if (left == null) { // No left operand, so we parse one and take care about leading unary operators if (_token.Info.UnaryOperator != null) { UnaryOperator op = _token.Info.UnaryOperator; NextToken(); ExpressionNode expr = ParseSubExpression(null, op.Precedence); left = new UnaryExpression(op, expr); } else { left = ParseSimpleExpression(); } } while (_token.Id != TokenId.Eof) { // Special handling for NOT BETWEEN, NOT IN, NOT LIKE, NOT SIMILAR TO, and NOT SOUNDSLIKE. bool negated = false; if (_token.Id == TokenId.NOT) { if (_lookahead.Id == TokenId.BETWEEN || _lookahead.Id == TokenId.IN || _lookahead.Id == TokenId.LIKE || _lookahead.Id == TokenId.SIMILAR || _lookahead.Id == TokenId.SOUNDSLIKE) { NextToken(); negated = true; } } // Special handling for the only ternary operator BETWEEN if (_token.Id == TokenId.BETWEEN) { NextToken(); ExpressionNode lowerBound = ParseSubExpression(null, Operator.BETWEEN_PRECEDENCE); Match(TokenId.AND); ExpressionNode upperBound = ParseSubExpression(null, Operator.BETWEEN_PRECEDENCE); left = new BetweenExpression(left, lowerBound, upperBound); } else { // If there is no binary operator we are finished if (_token.Info.BinaryOperator == null) break; BinaryOperator binaryOp = _token.Info.BinaryOperator; // Precedence is lower, parse it later if (binaryOp.Precedence < precedence) break; // Precedence is equal, but operator ist not right associative, parse it later if (binaryOp.Precedence == precedence && !binaryOp.IsRightAssociative) break; // Precedence is higher NextToken(); // Special handling for SIMILAR TO if (binaryOp == BinaryOperator.SimilarTo) Match(TokenId.TO); if (binaryOp == BinaryOperator.In) { // Special handling for IN InExpression inExpression = new InExpression(); inExpression.Left = left; inExpression.RightExpressions = ParseSimpleQueryExpressionList(); left = inExpression; } else if (_token.Id == TokenId.ANY || _token.Id == TokenId.SOME || _token.Id == TokenId.ALL) { // Special handling for ANY (SOME) and ALL if (binaryOp != BinaryOperator.Equal && binaryOp != BinaryOperator.NotEqual && binaryOp != BinaryOperator.Less && binaryOp != BinaryOperator.LessOrEqual && binaryOp != BinaryOperator.Greater && binaryOp != BinaryOperator.GreaterOrEqual) { _errorReporter.InvalidOperatorForAllAny(_token.Range, binaryOp); } AllAnySubselect allAnySubselect = new AllAnySubselect(); allAnySubselect.Left = left; allAnySubselect.Op = binaryOp; allAnySubselect.Type = (_token.Id == TokenId.ALL) ? AllAnySubselect.AllAnyType.All : AllAnySubselect.AllAnyType.Any; NextToken(); Match(TokenId.LeftParentheses); allAnySubselect.Query = ParseQuery(); Match(TokenId.RightParentheses); left = allAnySubselect; } else { left = new BinaryExpression(binaryOp, left, ParseSubExpression(null, binaryOp.Precedence)); } } // Special handling for negated expressions (see above) if (negated) left = new UnaryExpression(UnaryOperator.LogicalNot, left); } return left; }
public override ExpressionNode VisitBetweenExpression(BetweenExpression expression) { // First visit all expressions base.VisitBetweenExpression(expression); // Since a BETWEEN expression can be expressed using an AND expression and two // <= binary operator nodes we convert them to simplify the join and optimization engine. BinaryExpression lowerBound = new BinaryExpression(BinaryOperator.LessOrEqual, expression.LowerBound, expression.Expression); BinaryExpression upperBound = new BinaryExpression(BinaryOperator.LessOrEqual, expression.Expression, expression.UpperBound); BinaryExpression and = new BinaryExpression(BinaryOperator.LogicalAnd, lowerBound, upperBound); // Make sure we also resolve the result. return VisitExpression(and); }
public override ExpressionNode VisitCaseExpression(CaseExpression expression) { // Replace simple CASE by searched CASE, i.e. // // replace // // CASE InputExpr // WHEN Expr1 THEN ThenExpr1 ... // WHEN ExprN THEN ThenExprN // [ELSE ElseExpr] // END // // by // // CASE // WHEN InputExpr = Expr1 THEN ThenExpr1 ... // WHEN InputExpr = ExprN THEN ThenExprN // [ELSE ElseExpr] // END if (expression.InputExpression != null) { for (int i = 0; i < expression.WhenExpressions.Length; i++) { BinaryExpression binaryExpression = new BinaryExpression(); binaryExpression.Op = BinaryOperator.Equal; binaryExpression.Left = (ExpressionNode) expression.InputExpression.Clone(); binaryExpression.Right = expression.WhenExpressions[i]; expression.WhenExpressions[i] = binaryExpression; } expression.InputExpression = null; } return base.VisitCaseExpression(expression); }
public override ExpressionNode VisitInExpression(InExpression expression) { // First visit right expressions base.VisitInExpression(expression); // Check if the IN expression should have been expr = ANY (suquery) if (expression.RightExpressions.Length == 1) { SingleRowSubselect firstElemenAsSubselect = expression.RightExpressions[0] as SingleRowSubselect; if (firstElemenAsSubselect != null) { AllAnySubselect result = new AllAnySubselect(); result.Type = AllAnySubselect.AllAnyType.Any; result.Left = expression.Left; result.Op = BinaryOperator.Equal; result.Query = firstElemenAsSubselect.Query; return result; } } // IN-expressions can be written as a chain of OR and = expressions: // // leftExpr IN (rightExpr1 , ... , rightExprN) // // (leftExpr = rightExpr1) OR (...) OR (leftExpr = rightExprN) ExpressionNode resultNode = null; foreach (ExpressionNode rightExpression in expression.RightExpressions) { ExpressionNode clonedLeft = (ExpressionNode) expression.Left.Clone(); BinaryExpression comparisionNode = new BinaryExpression(BinaryOperator.Equal, clonedLeft, rightExpression); if (resultNode == null) resultNode = comparisionNode; else { BinaryExpression orNode = new BinaryExpression(BinaryOperator.LogicalOr, resultNode, comparisionNode); resultNode = orNode; } } // Visit resulting expression. return VisitExpression(resultNode); }
public virtual ExpressionNode VisitBinaryExpression(BinaryExpression expression) { expression.Left = VisitExpression(expression.Left); expression.Right = VisitExpression(expression.Right); return expression; }
public ExpressionNode ToExpression() { BinaryOperator op; switch (_op) { case JoinOperator.Equal: op = BinaryOperator.Equal; break; case JoinOperator.Less: op = BinaryOperator.Less; break; case JoinOperator.LessOrEqual: op = BinaryOperator.LessOrEqual; break; case JoinOperator.Greater: op = BinaryOperator.Greater; break; case JoinOperator.GreaterOrEqual: op = BinaryOperator.GreaterOrEqual; break; default: throw ExceptionBuilder.UnhandledCaseLabel(_op); } // HACK: Here we need to create a fully resolved binary expression node // Using the code (Binder.BindOperator) is NOT the way it should be... Binder binder = new Binder(ExceptionErrorProvider.Instance); BinaryExpression binaryExpression = new BinaryExpression(op, _leftExpression, _rightExpression); binaryExpression.OperatorMethod = binder.BindOperator(op, _leftExpression.ExpressionType, _rightExpression.ExpressionType); return binaryExpression; }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { bool isConjuctionOrDisjunction = expression.Op == BinaryOperator.LogicalAnd || expression.Op == BinaryOperator.LogicalOr; if (!isConjuctionOrDisjunction) { EmitCall(expression.OperatorMethod, null, expression.Left, expression.Right); } else { // He expression is a logical OR or a logical AND. In this case we have to pay // special attention to NULL values and short circuit evaluation. // Normally, a binary expression will yield NULL if any of the operands is NULL // (as in function calls). // // For conjuctions and disjunctions this is not true. Sometimes these boolean // operators will return TRUE or FALSE though an operand was null. The following // truth table must hold: // // AND | F | T | N OR | F | T | N // ----+---+---+-- ---+---+---+-- // F | F | F | F F | F | T | N // T | F | T | N T | T | T | T // N | F | N | N N | N | T | N // // In short, these exceptions exist: // // NULL AND FALSE ---> FALSE // FALSE AND NULL ---> FALSE // // NULL OR TRUE ---> TRUE // TRUE OR NULL ---> TRUE // // In addition we want to support short circuit evaluation. int left = DeclareLocal(); int right = DeclareLocal(); Label finish = _ilEmitContext.ILGenerator.DefineLabel(); if (expression.Op == BinaryOperator.LogicalAnd) { // Peseudo code: // // object left = expression.Left.Evaluate(); // // if (left != null && (bool)left == false) // return false; // else // { // object right = expression.Right.Evaluate(); // // if (right != null && (bool)right == false) // return false; // // if (rigth == null || left == null) // return null; // // return (bool)left & (bool)right; // } Label checkRightSide = _ilEmitContext.ILGenerator.DefineLabel(); Label checkAnyNull = _ilEmitContext.ILGenerator.DefineLabel(); Label returnNull = _ilEmitContext.ILGenerator.DefineLabel(); Label checkBothTrue = _ilEmitContext.ILGenerator.DefineLabel(); VisitExpression(expression.Left); _ilEmitContext.ILGenerator.Emit(OpCodes.Stloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, checkRightSide); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Brtrue, checkRightSide); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldc_I4_0); _ilEmitContext.ILGenerator.Emit(OpCodes.Box, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); _ilEmitContext.ILGenerator.MarkLabel(checkRightSide); VisitExpression(expression.Right); _ilEmitContext.ILGenerator.Emit(OpCodes.Stloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, checkAnyNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Brtrue, checkAnyNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldc_I4_0); _ilEmitContext.ILGenerator.Emit(OpCodes.Box, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); _ilEmitContext.ILGenerator.MarkLabel(checkAnyNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, returnNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Brtrue, checkBothTrue); _ilEmitContext.ILGenerator.MarkLabel(returnNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldnull); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); _ilEmitContext.ILGenerator.MarkLabel(checkBothTrue); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.And); _ilEmitContext.ILGenerator.Emit(OpCodes.Box, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); } else { // Peseudo code: // // object left = expression.Left.Evaluate(); // // if (left != null && (bool)left == true) // return true; // else // { // object right = expression.Right.Evaluate(); // // if (right != null && (bool)right == true) // return true; // // if (rigth == null || left == null) // return null; // // return (bool)left | (bool)right; // } Label checkRightSide = _ilEmitContext.ILGenerator.DefineLabel(); Label checkAnyNull = _ilEmitContext.ILGenerator.DefineLabel(); Label returnNull = _ilEmitContext.ILGenerator.DefineLabel(); Label checkAnyTrue = _ilEmitContext.ILGenerator.DefineLabel(); VisitExpression(expression.Left); _ilEmitContext.ILGenerator.Emit(OpCodes.Stloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, checkRightSide); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, checkRightSide); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldc_I4_1); _ilEmitContext.ILGenerator.Emit(OpCodes.Box, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); _ilEmitContext.ILGenerator.MarkLabel(checkRightSide); VisitExpression(expression.Right); _ilEmitContext.ILGenerator.Emit(OpCodes.Stloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, checkAnyNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, checkAnyNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldc_I4_1); _ilEmitContext.ILGenerator.Emit(OpCodes.Box, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); _ilEmitContext.ILGenerator.MarkLabel(checkAnyNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Brfalse, returnNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Brtrue, checkAnyTrue); _ilEmitContext.ILGenerator.MarkLabel(returnNull); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldnull); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); _ilEmitContext.ILGenerator.MarkLabel(checkAnyTrue); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, left); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Ldloc, right); _ilEmitContext.ILGenerator.Emit(OpCodes.Unbox_Any, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Or); _ilEmitContext.ILGenerator.Emit(OpCodes.Box, typeof(Boolean)); _ilEmitContext.ILGenerator.Emit(OpCodes.Br, finish); } _ilEmitContext.ILGenerator.MarkLabel(finish); } return expression; }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { if (expression.Op == BinaryOperator.LogicalAnd) { return base.VisitBinaryExpression(expression); } else if (expression.Op == BinaryOperator.Equal) { RowBufferEntry[] leftRowBufferEntries = AstUtil.GetRowBufferEntryReferences(expression.Left); RowBufferEntry[] rightRowBufferEntries = AstUtil.GetRowBufferEntryReferences(expression.Right); if (leftRowBufferEntries.Length == 1 && rightRowBufferEntries.Length == 1) { RowBufferEntry leftRowBufferEntry = leftRowBufferEntries[0]; RowBufferEntry rightRowBufferEntry = rightRowBufferEntries[0]; if (leftRowBufferEntry != rightRowBufferEntry) { // Both expressions depend on extactly one row buffer entry but // they are not refering to the same row buffer entry. bool leftDependsOnLeft= ArrayHelpers.Contains(_leftDefinedEntries, leftRowBufferEntry); bool rightDependsOnRight = ArrayHelpers.Contains(_rightDefinedEntries, rightRowBufferEntry); bool leftDependsOnRight = ArrayHelpers.Contains(_rightDefinedEntries, leftRowBufferEntry); bool rightDependsOnLeft = ArrayHelpers.Contains(_leftDefinedEntries, rightRowBufferEntry); if (leftDependsOnRight && rightDependsOnLeft) { ExpressionNode oldLeft = expression.Left; expression.Left = expression.Right; expression.Right = oldLeft; leftDependsOnLeft = true; rightDependsOnRight = true; } if (leftDependsOnLeft && rightDependsOnRight) { _equalPredicates.Add(expression); return LiteralExpression.FromBoolean(true); } } } } return expression; }
private static bool VisitBinaryExpression(BinaryExpression node1, BinaryExpression node2) { return node2 != null && node1.Op == node2.Op && Visit(node1.Left, node2.Left) && Visit(node1.Right, node2.Right); }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { if (expression.Op != BinaryOperator.LogicalAnd && expression.Op != BinaryOperator.LogicalOr) return base.VisitBinaryExpression(expression); if (expression.Op == BinaryOperator.LogicalAnd) { // AND expression.Left = VisitExpression(expression.Left); expression.Right = VisitExpression(expression.Right); return expression; } else { // OR AlgebraNode input = GetAndResetLastNode(); _probingEnabledStack.Push(false); List<ExpressionNode> scalarOrParts = new List<ExpressionNode>(); List<AlgebraNode> algebrizedOrParts = new List<AlgebraNode>(); foreach (ExpressionNode orPart in AstUtil.SplitCondition(LogicalOperator.Or, expression)) { if (!AstUtil.ContainsSubselect(orPart)) { scalarOrParts.Add(orPart); } else { ExpressionNode replacedOrPart = VisitExpression(orPart); FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Input = GetAndResetLastNode(); filterAlgebraNode.Predicate = replacedOrPart; algebrizedOrParts.Add(filterAlgebraNode); } } if (scalarOrParts.Count > 0) { FilterAlgebraNode filterAlgebraNode = new FilterAlgebraNode(); filterAlgebraNode.Predicate = AstUtil.CombineConditions(LogicalOperator.Or, scalarOrParts); filterAlgebraNode.Input = CreateConstantScan(); algebrizedOrParts.Insert(0, filterAlgebraNode); } _probingEnabledStack.Pop(); ConcatAlgebraNode concat = new ConcatAlgebraNode(); concat.DefinedValues = new UnitedValueDefinition[0]; concat.Inputs = algebrizedOrParts.ToArray(); RowBufferEntry probeColumn = CreateProbeColumn(); JoinAlgebraNode leftSemiJoinBetweenInputAndConcat = new JoinAlgebraNode(); leftSemiJoinBetweenInputAndConcat.Op = JoinAlgebraNode.JoinOperator.LeftSemiJoin; leftSemiJoinBetweenInputAndConcat.PassthruPredicate = CurrentPassthruPredicate; leftSemiJoinBetweenInputAndConcat.ProbeBufferEntry = probeColumn; leftSemiJoinBetweenInputAndConcat.Left = input; leftSemiJoinBetweenInputAndConcat.Right = concat; SetLastAlgebraNode(leftSemiJoinBetweenInputAndConcat); return CreateProbeColumnRef(probeColumn); } }
public override ExpressionNode VisitBinaryExpression(BinaryExpression expression) { _xmlWriter.WriteStartElement("binaryExpression"); _xmlWriter.WriteAttributeString("operator", expression.Op.TokenText); WriteTypeAttribute(expression.ExpressionType); Visit(expression.Left); Visit(expression.Right); _xmlWriter.WriteEndElement(); return expression; }