public TreeNode BuildNode(BinaryNode<int> node) { TreeNode n = new TreeNode() { Text = node.Value.ToString() }; if (node.LeftNode != null) n.Nodes.Add(BuildNode(node.LeftNode)); if (node.RightNode != null) n.Nodes.Add(BuildNode(node.RightNode)); return n; }
/// <summary> /// Builds expression tree for higher-precedence operator to be used as left /// operand of current operator. May cause errors - always do ErrorCheck() upin return. /// </summary> private void BuildExpression(int pri) { ExpressionNode expr = null; Debug.Assert(pri > Operators.priStart && pri <= Operators.priMax, "Invalid priority value"); /* For all operators of higher or same precedence (we are always * left-associative) */ while (true) { Debug.Assert(_topOperator > 0, "Empty operator stack!!"); OperatorInfo opInfo = _ops[_topOperator - 1]; if (opInfo._priority < pri) { goto end_loop; } Debug.Assert(opInfo._priority >= pri, "Invalid prioriry value"); _topOperator--; ExpressionNode nodeLeft; ExpressionNode nodeRight; switch (opInfo._type) { case Nodes.Binop: { // get right, left operands. Bind them. nodeRight = NodePop(); nodeLeft = NodePop(); /* This is the place to do type and other checks */ switch (opInfo._op) { case Operators.Between: case Operators.BetweenAnd: case Operators.BitwiseAnd: case Operators.BitwiseOr: case Operators.BitwiseXor: case Operators.BitwiseNot: throw ExprException.UnsupportedOperator(opInfo._op); case Operators.Is: case Operators.Or: case Operators.And: case Operators.EqualTo: case Operators.NotEqual: case Operators.Like: case Operators.LessThen: case Operators.LessOrEqual: case Operators.GreaterThen: case Operators.GreaterOrEqual: case Operators.In: break; default: Debug.Assert(opInfo._op == Operators.Plus || opInfo._op == Operators.Minus || opInfo._op == Operators.Multiply || opInfo._op == Operators.Divide || opInfo._op == Operators.Modulo, "Invalud Binary operation"); break; } Debug.Assert(nodeLeft != null, "Invalid left operand"); Debug.Assert(nodeRight != null, "Invalid right operand"); if (opInfo._op == Operators.Like) { expr = new LikeNode(_table, opInfo._op, nodeLeft, nodeRight); } else { expr = new BinaryNode(_table, opInfo._op, nodeLeft, nodeRight); } break; } case Nodes.Unop: /* Unary operator: Pop and bind right op. */ nodeLeft = null; nodeRight = NodePop(); /* Check for special cases */ switch (opInfo._op) { case Operators.Not: break; case Operators.BitwiseNot: throw ExprException.UnsupportedOperator(opInfo._op); case Operators.Negative: break; } Debug.Assert(nodeLeft == null, "Invalid left operand"); Debug.Assert(nodeRight != null, "Invalid right operand"); expr = new UnaryNode(_table, opInfo._op, nodeRight); break; case Nodes.Zop: /* Intrinsic constant: just create node. */ expr = new ZeroOpNode(opInfo._op); break; default: Debug.Fail("Unhandled operator type"); goto end_loop; } Debug.Assert(expr != null, "Failed to create expression"); NodePush(expr); // countinue while loop; } end_loop: ; }
private void BuildExpression(int pri) { OperatorInfo info; ExpressionNode node = null; Label_0002: info = this.ops[this.topOperator - 1]; if (info.priority >= pri) { ExpressionNode node2; ExpressionNode node3; this.topOperator--; switch (info.type) { case Nodes.Unop: node3 = null; node2 = this.NodePop(); switch (info.op) { case 0x19: throw ExprException.UnsupportedOperator(info.op); } node = new UnaryNode(this._table, info.op, node2); goto Label_016C; case Nodes.UnopSpec: case Nodes.BinopSpec: return; case Nodes.Binop: node2 = this.NodePop(); node3 = this.NodePop(); switch (info.op) { case 4: case 6: case 0x16: case 0x17: case 0x18: case 0x19: throw ExprException.UnsupportedOperator(info.op); } if (info.op == 14) { node = new LikeNode(this._table, info.op, node3, node2); } else { node = new BinaryNode(this._table, info.op, node3, node2); } goto Label_016C; case Nodes.Zop: node = new ZeroOpNode(info.op); goto Label_016C; } } return; Label_016C: this.NodePush(node); goto Label_0002; }
// Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions private void AnalyzeExpression(BinaryNode expr) { if (_linearExpression == _expression) return; if (expr._op == Operators.Or) { _linearExpression = _expression; return; } else if (expr._op == Operators.And) { bool isLeft = false, isRight = false; if (expr._left is BinaryNode) { AnalyzeExpression((BinaryNode)expr._left); if (_linearExpression == _expression) return; isLeft = true; } else { UnaryNode unaryNode = expr._left as UnaryNode; if (unaryNode != null) { while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode._right; } if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode._right)); if (_linearExpression == _expression) { return; } isLeft = true; } } } if (expr._right is BinaryNode) { AnalyzeExpression((BinaryNode)expr._right); if (_linearExpression == _expression) return; isRight = true; } else { UnaryNode unaryNode = expr._right as UnaryNode; if (unaryNode != null) { while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode._right; } if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode._right)); if (_linearExpression == _expression) { return; } isRight = true; } } } if (isLeft && isRight) return; ExpressionNode e = isLeft ? expr._right : expr._left; _linearExpression = (_linearExpression == null ? e : new BinaryNode(_table, Operators.And, e, _linearExpression)); return; } else if (IsSupportedOperator(expr._op)) { if (expr._left is NameNode && expr._right is ConstNode) { ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(_table, Operators.And, expr, canColumn.expr)); if (expr._op == Operators.EqualTo) { canColumn.equalsOperator = true; } _candidatesForBinarySearch = true; return; } else if (expr._right is NameNode && expr._left is ConstNode) { ExpressionNode temp = expr._left; expr._left = expr._right; expr._right = temp; switch (expr._op) { case Operators.GreaterThen: expr._op = Operators.LessThen; break; case Operators.LessThen: expr._op = Operators.GreaterThen; break; case Operators.GreaterOrEqual: expr._op = Operators.LessOrEqual; break; case Operators.LessOrEqual: expr._op = Operators.GreaterOrEqual; break; default: break; } ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(_table, Operators.And, expr, canColumn.expr)); if (expr._op == Operators.EqualTo) { canColumn.equalsOperator = true; } _candidatesForBinarySearch = true; return; } } _linearExpression = (_linearExpression == null ? expr : new BinaryNode(_table, Operators.And, expr, _linearExpression)); return; }
private int Eval(BinaryNode expr, DataRow row, DataRowVersion version) { if (expr._op == Operators.And) { int lResult = Eval((BinaryNode)expr._left, row, version); if (lResult != 0) { return(lResult); } int rResult = Eval((BinaryNode)expr._right, row, version); if (rResult != 0) { return(rResult); } return(0); } long c = 0; object vLeft = expr._left.Eval(row, version); if (expr._op != Operators.Is && expr._op != Operators.IsNot) { object vRight = expr._right.Eval(row, version); bool isLConst = (expr._left is ConstNode); bool isRConst = (expr._right is ConstNode); if ((vLeft == DBNull.Value) || (expr._left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft))) { return(-1); } if ((vRight == DBNull.Value) || (expr._right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight))) { return(1); } StorageType leftType = DataStorage.GetStorageType(vLeft.GetType()); if (StorageType.Char == leftType) { if ((isRConst) || (!expr._right.IsSqlColumn)) { vRight = Convert.ToChar(vRight, _table.FormatProvider); } else { vRight = SqlConvert.ChangeType2(vRight, StorageType.Char, typeof(char), _table.FormatProvider); } } StorageType rightType = DataStorage.GetStorageType(vRight.GetType()); StorageType resultType; if (expr._left.IsSqlColumn || expr._right.IsSqlColumn) { resultType = expr.ResultSqlType(leftType, rightType, isLConst, isRConst, expr._op); } else { resultType = expr.ResultType(leftType, rightType, isLConst, isRConst, expr._op); } if (StorageType.Empty == resultType) { expr.SetTypeMismatchError(expr._op, vLeft.GetType(), vRight.GetType()); } // if comparing a Guid column value against a string literal // use InvariantCulture instead of DataTable.Locale because in the Danish related cultures // sorting a Guid as a string has different results than in Invariant and English related cultures. // This fix is restricted to DataTable.Select("GuidColumn = 'string literal'") types of queries NameNode namedNode = null; System.Globalization.CompareInfo comparer = ((isLConst && !isRConst && (leftType == StorageType.String) && (rightType == StorageType.Guid) && (null != (namedNode = expr._right as NameNode)) && (namedNode._column.DataType == typeof(Guid))) || (isRConst && !isLConst && (rightType == StorageType.String) && (leftType == StorageType.Guid) && (null != (namedNode = expr._left as NameNode)) && (namedNode._column.DataType == typeof(Guid)))) ? System.Globalization.CultureInfo.InvariantCulture.CompareInfo : null; c = expr.BinaryCompare(vLeft, vRight, resultType, expr._op, comparer); } switch (expr._op) { case Operators.EqualTo: c = (c == 0 ? 0 : c < 0 ? -1 : 1); break; case Operators.GreaterThen: c = (c > 0 ? 0 : -1); break; case Operators.LessThen: c = (c < 0 ? 0 : 1); break; case Operators.GreaterOrEqual: c = (c >= 0 ? 0 : -1); break; case Operators.LessOrEqual: c = (c <= 0 ? 0 : 1); break; case Operators.Is: c = (vLeft == DBNull.Value ? 0 : -1); break; case Operators.IsNot: c = (vLeft != DBNull.Value ? 0 : 1); break; default: Debug.Assert(true, "Unsupported Binary Search Operator!"); break; } return((int)c); }
// Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions private void AnalyzeExpression(BinaryNode expr) { if (_linearExpression == _expression) { return; } if (expr._op == Operators.Or) { _linearExpression = _expression; return; } else if (expr._op == Operators.And) { bool isLeft = false, isRight = false; if (expr._left is BinaryNode) { AnalyzeExpression((BinaryNode)expr._left); if (_linearExpression == _expression) { return; } isLeft = true; } else { UnaryNode unaryNode = expr._left as UnaryNode; if (unaryNode != null) { while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode._right; } if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode._right)); if (_linearExpression == _expression) { return; } isLeft = true; } } } if (expr._right is BinaryNode) { AnalyzeExpression((BinaryNode)expr._right); if (_linearExpression == _expression) { return; } isRight = true; } else { UnaryNode unaryNode = expr._right as UnaryNode; if (unaryNode != null) { while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode._right; } if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode._right)); if (_linearExpression == _expression) { return; } isRight = true; } } } if (isLeft && isRight) { return; } ExpressionNode e = isLeft ? expr._right : expr._left; _linearExpression = (_linearExpression == null ? e : new BinaryNode(_table, Operators.And, e, _linearExpression)); return; } else if (IsSupportedOperator(expr._op)) { if (expr._left is NameNode && expr._right is ConstNode) { ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(_table, Operators.And, expr, canColumn.expr)); if (expr._op == Operators.EqualTo) { canColumn.equalsOperator = true; } _candidatesForBinarySearch = true; return; } else if (expr._right is NameNode && expr._left is ConstNode) { ExpressionNode temp = expr._left; expr._left = expr._right; expr._right = temp; switch (expr._op) { case Operators.GreaterThen: expr._op = Operators.LessThen; break; case Operators.LessThen: expr._op = Operators.GreaterThen; break; case Operators.GreaterOrEqual: expr._op = Operators.LessOrEqual; break; case Operators.LessOrEqual: expr._op = Operators.GreaterOrEqual; break; default: break; } ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(_table, Operators.And, expr, canColumn.expr)); if (expr._op == Operators.EqualTo) { canColumn.equalsOperator = true; } _candidatesForBinarySearch = true; return; } } _linearExpression = (_linearExpression == null ? expr : new BinaryNode(_table, Operators.And, expr, _linearExpression)); return; }
private object EvalBinaryOp(int op, ExpressionNode left, ExpressionNode right, DataRow row, DataRowVersion version, int[] recordNos) { object vLeft; object vRight; bool isLConst, isRConst; Type result; /* * special case for OR and AND operators: we don't want to evaluate * both right and left operands, because we can shortcut : * for OR operator If one of the operands is true the result is true * for AND operator If one of rhe operands is flase the result is false * CONSIDER : in the shortcut case do we want to type-check the other operand? */ if (op != Operators.Or && op != Operators.And && op != Operators.In && op != Operators.Is && op != Operators.IsNot) { vLeft = BinaryNode.Eval(left, row, version, recordNos); vRight = BinaryNode.Eval(right, row, version, recordNos); isLConst = (left is ConstNode); isRConst = (right is ConstNode); // special case of handling NULLS, currently only OR operator can work with NULLS if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } result = ResultType(vLeft.GetType(), vRight.GetType(), isLConst, isRConst, op); if (result == null) { SetTypeMismatchError(op, vLeft.GetType(), vRight.GetType()); } #if DEBUG if (CompModSwitches.BinaryNode.TraceVerbose) { Debug.WriteLine("Result of the operator: " + result.Name); } #endif } else { vLeft = vRight = DBNull.Value; result = null; } object value = DBNull.Value; bool typeMismatch = false; try { switch (op) { case Operators.Plus: if (result == typeof(Byte)) { value = Convert.ToByte(Convert.ToByte(vLeft) + Convert.ToByte(vRight)); } else if (result == typeof(SByte)) { value = Convert.ToSByte(Convert.ToSByte(vLeft) + Convert.ToSByte(vRight)); } else if (result == typeof(Int16)) { value = Convert.ToInt16(Convert.ToInt16(vLeft) + Convert.ToInt16(vRight)); } else if (result == typeof(UInt16)) { value = Convert.ToUInt16(Convert.ToUInt16(vLeft) + Convert.ToUInt16(vRight)); } else if (result == typeof(Int32)) { Int32 a = Convert.ToInt32(vLeft); Int32 b = Convert.ToInt32(vRight); checked { value = a + b; } } else if (result == typeof(UInt32)) { UInt32 a = Convert.ToUInt32(vLeft); UInt32 b = Convert.ToUInt32(vRight); checked { value = a + b; } } else if (result == typeof(UInt64)) { UInt64 a = Convert.ToUInt64(vLeft); UInt64 b = Convert.ToUInt64(vRight); checked { value = a + b; } } else if (result == typeof(Int64)) { Int64 a = Convert.ToInt64(vLeft); Int64 b = Convert.ToInt64(vRight); checked { value = a + b; } } else if (result == typeof(Decimal)) { Decimal a = Convert.ToDecimal(vLeft); Decimal b = Convert.ToDecimal(vRight); checked { value = a + b; } } else if (result == typeof(Single)) { Single a = Convert.ToSingle(vLeft); Single b = Convert.ToSingle(vRight); checked { value = a + b; } } else if (result == typeof(double)) { Double a = Convert.ToDouble(vLeft); Double b = Convert.ToDouble(vRight); checked { value = a + b; } } else if (result == typeof(string) || result == typeof(char)) { value = Convert.ToString(vLeft) + Convert.ToString(vRight); } else if (result == typeof(DateTime)) { // one of the operands should be a DateTime, and an other a TimeSpan if (vLeft is TimeSpan && vRight is DateTime) { value = (DateTime)vRight + (TimeSpan)vLeft; } else if (vLeft is DateTime && vRight is TimeSpan) { value = (DateTime)vLeft + (TimeSpan)vRight; } else { typeMismatch = true; } } else if (result == typeof(TimeSpan)) { value = (TimeSpan)vLeft + (TimeSpan)vRight; } else { typeMismatch = true; } break; case Operators.Minus: if (result == typeof(Byte)) { value = Convert.ToByte(Convert.ToByte(vLeft) - Convert.ToByte(vRight)); } else if (result == typeof(SByte)) { value = Convert.ToSByte(Convert.ToSByte(vLeft) - Convert.ToSByte(vRight)); } else if (result == typeof(Int16)) { value = Convert.ToInt16(Convert.ToInt16(vLeft) - Convert.ToInt16(vRight)); } else if (result == typeof(UInt16)) { value = Convert.ToUInt16(Convert.ToUInt16(vLeft) - Convert.ToUInt16(vRight)); } else if (result == typeof(Int32)) { Int32 a = Convert.ToInt32(vLeft); Int32 b = Convert.ToInt32(vRight); checked { value = a - b; } } else if (result == typeof(UInt32)) { UInt32 a = Convert.ToUInt32(vLeft); UInt32 b = Convert.ToUInt32(vRight); checked { value = a - b; } } else if (result == typeof(Int64)) { Int64 a = Convert.ToInt64(vLeft); Int64 b = Convert.ToInt64(vRight); checked { value = a - b; } } else if (result == typeof(UInt64)) { UInt64 a = Convert.ToUInt64(vLeft); UInt64 b = Convert.ToUInt64(vRight); checked { value = a - b; } } else if (result == typeof(Decimal)) { Decimal a = Convert.ToDecimal(vLeft); Decimal b = Convert.ToDecimal(vRight); checked { value = a - b; } } else if (result == typeof(Single)) { Single a = Convert.ToSingle(vLeft); Single b = Convert.ToSingle(vRight); checked { value = a - b; } } else if (result == typeof(double)) { Double a = Convert.ToDouble(vLeft); Double b = Convert.ToDouble(vRight); checked { value = a - b; } } else if (result == typeof(DateTime)) { value = (DateTime)vLeft - (TimeSpan)vRight; } else if (result == typeof(TimeSpan)) { if (vLeft is DateTime) { value = (DateTime)vLeft - (DateTime)vRight; } else { value = (TimeSpan)vLeft - (TimeSpan)vRight; } } else { typeMismatch = true; } break; case Operators.Multiply: if (result == typeof(Byte)) { value = Convert.ToByte(Convert.ToByte(vLeft) * Convert.ToByte(vRight)); } else if (result == typeof(SByte)) { value = Convert.ToSByte(Convert.ToSByte(vLeft) * Convert.ToSByte(vRight)); } else if (result == typeof(Int16)) { value = Convert.ToInt16(Convert.ToInt16(vLeft) * Convert.ToInt16(vRight)); } else if (result == typeof(UInt16)) { value = Convert.ToUInt16(Convert.ToUInt16(vLeft) * Convert.ToUInt16(vRight)); } else if (result == typeof(Int32)) { Int32 a = Convert.ToInt32(vLeft); Int32 b = Convert.ToInt32(vRight); checked { value = a * b; } } else if (result == typeof(UInt32)) { UInt32 a = Convert.ToUInt32(vLeft); UInt32 b = Convert.ToUInt32(vRight); checked { value = a * b; } } else if (result == typeof(Int64)) { Int64 a = Convert.ToInt64(vLeft); Int64 b = Convert.ToInt64(vRight); checked { value = a * b; } } else if (result == typeof(UInt64)) { UInt64 a = Convert.ToUInt64(vLeft); UInt64 b = Convert.ToUInt64(vRight); checked { value = a * b; } } else if (result == typeof(Decimal)) { Decimal a = Convert.ToDecimal(vLeft); Decimal b = Convert.ToDecimal(vRight); checked { value = a * b; } } else if (result == typeof(Single)) { Single a = Convert.ToSingle(vLeft); Single b = Convert.ToSingle(vRight); checked { value = a * b; } } else if (result == typeof(double)) { Double a = Convert.ToDouble(vLeft); Double b = Convert.ToDouble(vRight); checked { value = a * b; } } else { typeMismatch = true; } break; case Operators.Divide: if (result == typeof(Byte)) { value = Convert.ToByte(Convert.ToByte(vLeft) / Convert.ToByte(vRight)); } else if (result == typeof(SByte)) { value = Convert.ToSByte(Convert.ToSByte(vLeft) / Convert.ToSByte(vRight)); } else if (result == typeof(Int16)) { value = Convert.ToInt16(Convert.ToInt16(vLeft) / Convert.ToInt16(vRight)); } else if (result == typeof(UInt16)) { value = Convert.ToUInt16(Convert.ToUInt16(vLeft) / Convert.ToUInt16(vRight)); } else if (result == typeof(Int32)) { Int32 a = Convert.ToInt32(vLeft); Int32 b = Convert.ToInt32(vRight); checked { value = a / b; } } else if (result == typeof(UInt32)) { UInt32 a = Convert.ToUInt32(vLeft); UInt32 b = Convert.ToUInt32(vRight); checked { value = a / b; } } else if (result == typeof(UInt64)) { UInt64 a = Convert.ToUInt64(vLeft); UInt64 b = Convert.ToUInt64(vRight); checked { value = a / b; } } else if (result == typeof(Int64)) { Int64 a = Convert.ToInt64(vLeft); Int64 b = Convert.ToInt64(vRight); checked { value = a / b; } } else if (result == typeof(Decimal)) { Decimal a = Convert.ToDecimal(vLeft); Decimal b = Convert.ToDecimal(vRight); checked { value = a / b; } } else if (result == typeof(Single)) { Single a = Convert.ToSingle(vLeft); Single b = Convert.ToSingle(vRight); checked { value = a / b; } } else if (result == typeof(double)) { Double a = Convert.ToDouble(vLeft); Double b = Convert.ToDouble(vRight); checked { value = a / b; } } else { typeMismatch = true; } break; case Operators.EqualTo: if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } return(0 == Compare(vLeft, vRight, result, Operators.EqualTo)); case Operators.GreaterThen: if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } return(0 < Compare(vLeft, vRight, result, op)); case Operators.LessThen: if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } return(0 > Compare(vLeft, vRight, result, op)); case Operators.GreaterOrEqual: if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } return(0 <= Compare(vLeft, vRight, result, op)); case Operators.LessOrEqual: if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } return(0 >= Compare(vLeft, vRight, result, op)); case Operators.NotEqual: if ((vLeft == DBNull.Value) || (vRight == DBNull.Value)) { return(DBNull.Value); } return(0 != Compare(vLeft, vRight, result, op)); case Operators.Is: vLeft = BinaryNode.Eval(left, row, version, recordNos); if (vLeft == DBNull.Value) { return(true); } return(false); case Operators.IsNot: vLeft = BinaryNode.Eval(left, row, version, recordNos); if (vLeft == DBNull.Value) { return(false); } return(true); case Operators.And: /* * special case evaluating of the AND operator: we don't want to evaluate * both right and left operands, because we can shortcut : * If one of the operands is flase the result is false * CONSIDER : in the shortcut case do we want to type-check the other operand? */ vLeft = BinaryNode.Eval(left, row, version, recordNos); if (vLeft == DBNull.Value) { return(DBNull.Value); } if (!(vLeft is bool)) { vRight = BinaryNode.Eval(right, row, version, recordNos); typeMismatch = true; break; } if ((bool)vLeft == false) { value = false; break; } vRight = BinaryNode.Eval(right, row, version, recordNos); if (vRight == DBNull.Value) { return(DBNull.Value); } if (!(vRight is bool)) { typeMismatch = true; break; } value = (bool)vRight; break; case Operators.Or: /* * special case evaluating the OR operator: we don't want to evaluate * both right and left operands, because we can shortcut : * If one of the operands is true the result is true * CONSIDER : in the shortcut case do we want to type-check the other operand? */ vLeft = BinaryNode.Eval(left, row, version, recordNos); if (vLeft != DBNull.Value) { if (!(vLeft is bool)) { vRight = BinaryNode.Eval(right, row, version, recordNos); typeMismatch = true; break; } if ((bool)vLeft == true) { value = true; break; } } vRight = BinaryNode.Eval(right, row, version, recordNos); if (vRight == DBNull.Value) { return(vLeft); } if (vLeft == DBNull.Value) { return(vRight); } if (!(vRight is bool)) { typeMismatch = true; break; } value = (bool)vRight; break; case Operators.Modulo: if (ExpressionNode.IsInteger(result)) { if (result == typeof(UInt64)) { value = Convert.ToUInt64(vLeft) % Convert.ToUInt64(vRight); } else { value = Convert.ToInt64(vLeft) % Convert.ToInt64(vRight); value = Convert.ChangeType(value, result); } } else { typeMismatch = true; } break; case Operators.In: /* * special case evaluating of the IN operator: the right have to be IN function node */ #if DEBUG if (CompModSwitches.BinaryNode.TraceVerbose) { Debug.WriteLine("Evaluating IN operator.."); } #endif if (!(right is FunctionNode)) { // this is more like an Assert: should never happens, so we do not care about "nice" Exseptions throw ExprException.InWithoutParentheses(); } vLeft = BinaryNode.Eval(left, row, version, recordNos); if (vLeft == DBNull.Value) { return(DBNull.Value); } /* validate IN parameters : must all be constant expressions */ value = false; FunctionNode into = (FunctionNode)right; for (int i = 0; i < into.argumentCount; i++) { vRight = into.arguments[i].Eval(); #if DEBUG if (CompModSwitches.BinaryNode.TraceVerbose) { Debug.WriteLine("Evaluate IN parameter " + into.arguments[i].ToString() + " = " + vRight.ToString()); } #endif if (vRight == DBNull.Value) { continue; } Debug.Assert((vLeft != DBNull.Value) && (vRight != DBNull.Value), "Imposible.."); result = vLeft.GetType(); if (0 == Compare(vLeft, vRight, result, Operators.EqualTo)) { value = true; break; } } break; default: #if DEBUG if (CompModSwitches.BinaryNode.TraceVerbose) { Debug.WriteLine("NYI : " + Operators.ToString(op)); } #endif throw ExprException.UnsupportedOperator(op); } } catch (OverflowException) { throw ExprException.Overflow(result); } if (typeMismatch) { SetTypeMismatchError(op, vLeft.GetType(), vRight.GetType()); } return(value); }
private int Eval(BinaryNode expr, DataRow row, DataRowVersion version) { if (expr.op == Operators.And) { int lResult = Eval((BinaryNode)expr.left,row,version); if (lResult != 0) return lResult; int rResult = Eval((BinaryNode)expr.right,row,version); if (rResult != 0) return rResult; return 0; } long c = 0; object vLeft = expr.left.Eval(row, version); if (expr.op != Operators.Is && expr.op != Operators.IsNot) { object vRight = expr.right.Eval(row, version); bool isLConst = (expr.left is ConstNode); bool isRConst = (expr.right is ConstNode); if ((vLeft == DBNull.Value)||(expr.left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft))) return -1; if ((vRight == DBNull.Value)||(expr.right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight))) return 1; StorageType leftType = DataStorage.GetStorageType(vLeft.GetType()); if (StorageType.Char == leftType) { if ((isRConst)||(!expr.right.IsSqlColumn)) vRight = Convert.ToChar(vRight, table.FormatProvider); else vRight = SqlConvert.ChangeType2(vRight, StorageType.Char, typeof(char), table.FormatProvider); } StorageType rightType = DataStorage.GetStorageType(vRight.GetType()); StorageType resultType; if (expr.left.IsSqlColumn || expr.right.IsSqlColumn) { resultType = expr.ResultSqlType(leftType, rightType, isLConst, isRConst, expr.op); } else { resultType = expr.ResultType(leftType, rightType, isLConst, isRConst, expr.op); } if (StorageType.Empty == resultType) { expr.SetTypeMismatchError(expr.op, vLeft.GetType(), vRight.GetType()); } // if comparing a Guid column value against a string literal // use InvariantCulture instead of DataTable.Locale because in the Danish related cultures // sorting a Guid as a string has different results than in Invariant and English related cultures. // This fix is restricted to DataTable.Select("GuidColumn = 'string literal'") types of queries NameNode namedNode = null; System.Globalization.CompareInfo comparer = ((isLConst && !isRConst && (leftType == StorageType.String) && (rightType == StorageType.Guid) && (null != (namedNode = expr.right as NameNode)) && (namedNode.column.DataType == typeof(Guid))) || (isRConst && !isLConst && (rightType == StorageType.String) && (leftType == StorageType.Guid) && (null != (namedNode = expr.left as NameNode)) && (namedNode.column.DataType == typeof(Guid)))) ? System.Globalization.CultureInfo.InvariantCulture.CompareInfo : null; c = expr.BinaryCompare(vLeft, vRight, resultType, expr.op, comparer); } switch(expr.op) { case Operators.EqualTo: c = (c == 0 ? 0 : c < 0 ? -1 : 1); break; case Operators.GreaterThen: c = (c > 0 ? 0 : -1); break; case Operators.LessThen: c = (c < 0 ? 0 : 1); break; case Operators.GreaterOrEqual: c = (c >= 0 ? 0 : -1); break; case Operators.LessOrEqual: c = (c <= 0 ? 0 : 1); break; case Operators.Is: c = (vLeft == DBNull.Value ? 0 : -1); break; case Operators.IsNot: c = (vLeft != DBNull.Value ? 0 : 1); break; default: Debug.Assert(true, "Unsupported Binary Search Operator!"); break; } return (int)c; }
// haroona : Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions private void AnalyzeExpression(BinaryNode expr) { if (this.linearExpression == this.expression) { return; } if (expr.op == Operators.Or) { this.linearExpression = this.expression; return; } else if (expr.op == Operators.And) { bool isLeft = false, isRight = false; if (expr.left is BinaryNode) { AnalyzeExpression((BinaryNode)expr.left); if (this.linearExpression == this.expression) { return; } isLeft = true; } else if (expr.left is UnaryNode && ((UnaryNode)(expr.left)).op == Operators.Noop && ((UnaryNode)(expr.left)).right is BinaryNode) { AnalyzeExpression((BinaryNode)((UnaryNode)(expr.left)).right); if (this.linearExpression == this.expression) { return; } isLeft = true; } if (expr.right is BinaryNode) { AnalyzeExpression((BinaryNode)expr.right); if (this.linearExpression == this.expression) { return; } isRight = true; } else if (expr.right is UnaryNode && ((UnaryNode)(expr.right)).op == Operators.Noop && ((UnaryNode)(expr.right)).right is BinaryNode) { AnalyzeExpression((BinaryNode)((UnaryNode)(expr.right)).right); if (this.linearExpression == this.expression) { return; } isRight = true; } if (isLeft && isRight) { return; } ExpressionNode e = isLeft ? expr.right : expr.left; this.linearExpression = (this.linearExpression == null ? e : new BinaryNode(Operators.And, e, this.linearExpression)); return; } else if (IsSupportedOperator(expr.op)) { if (expr.left is NameNode && expr.right is ConstNode) { ColumnInfo canColumn = (ColumnInfo)candidateColumns[((NameNode)(expr.left)).column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(Operators.And, expr, canColumn.expr)); if (expr.op == Operators.EqualTo) { canColumn.equalsOperator = true; } candidatesForBinarySearch = true; return; } else if (expr.right is NameNode && expr.left is ConstNode) { ExpressionNode temp = expr.left; expr.left = expr.right; expr.right = temp; switch (expr.op) { case Operators.GreaterThen: expr.op = Operators.LessThen; break; case Operators.LessThen: expr.op = Operators.GreaterThen; break; case Operators.GreaterOrEqual: expr.op = Operators.LessOrEqual; break; case Operators.LessOrEqual: expr.op = Operators.GreaterOrEqual; break; default: break; } ColumnInfo canColumn = (ColumnInfo)candidateColumns[((NameNode)(expr.left)).column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(Operators.And, expr, canColumn.expr)); if (expr.op == Operators.EqualTo) { canColumn.equalsOperator = true; } candidatesForBinarySearch = true; return; } } this.linearExpression = (this.linearExpression == null ? expr : new BinaryNode(Operators.And, expr, this.linearExpression)); return; }
private void AnalyzeExpression(BinaryNode expr) { if (this.linearExpression != this.expression) { if (expr.op == 0x1b) { this.linearExpression = this.expression; } else if (expr.op == 0x1a) { bool flag = false; bool flag2 = false; if (expr.left is BinaryNode) { this.AnalyzeExpression((BinaryNode) expr.left); if (this.linearExpression == this.expression) { return; } flag = true; } else { UnaryNode left = expr.left as UnaryNode; if (left != null) { while (((left.op == 0) && (left.right is UnaryNode)) && (((UnaryNode) left.right).op == 0)) { left = (UnaryNode) left.right; } if ((left.op == 0) && (left.right is BinaryNode)) { this.AnalyzeExpression((BinaryNode) left.right); if (this.linearExpression == this.expression) { return; } flag = true; } } } if (expr.right is BinaryNode) { this.AnalyzeExpression((BinaryNode) expr.right); if (this.linearExpression == this.expression) { return; } flag2 = true; } else { UnaryNode right = expr.right as UnaryNode; if (right != null) { while (((right.op == 0) && (right.right is UnaryNode)) && (((UnaryNode) right.right).op == 0)) { right = (UnaryNode) right.right; } if ((right.op == 0) && (right.right is BinaryNode)) { this.AnalyzeExpression((BinaryNode) right.right); if (this.linearExpression == this.expression) { return; } flag2 = true; } } } if (!flag || !flag2) { ExpressionNode node3 = flag ? expr.right : expr.left; this.linearExpression = (this.linearExpression == null) ? node3 : new BinaryNode(this.table, 0x1a, node3, this.linearExpression); } } else { if (this.IsSupportedOperator(expr.op)) { if ((expr.left is NameNode) && (expr.right is ConstNode)) { ColumnInfo info2 = this.candidateColumns[((NameNode) expr.left).column.Ordinal]; info2.expr = (info2.expr == null) ? expr : new BinaryNode(this.table, 0x1a, expr, info2.expr); if (expr.op == 7) { info2.equalsOperator = true; } this.candidatesForBinarySearch = true; return; } if ((expr.right is NameNode) && (expr.left is ConstNode)) { ExpressionNode node4 = expr.left; expr.left = expr.right; expr.right = node4; switch (expr.op) { case 8: expr.op = 9; break; case 9: expr.op = 8; break; case 10: expr.op = 11; break; case 11: expr.op = 10; break; } ColumnInfo info = this.candidateColumns[((NameNode) expr.left).column.Ordinal]; info.expr = (info.expr == null) ? expr : new BinaryNode(this.table, 0x1a, expr, info.expr); if (expr.op == 7) { info.equalsOperator = true; } this.candidatesForBinarySearch = true; return; } } this.linearExpression = (this.linearExpression == null) ? expr : new BinaryNode(this.table, 0x1a, expr, this.linearExpression); } } }
private int Eval(BinaryNode expr, DataRow row, DataRowVersion version) { if (expr.op == 0x1a) { int num4 = this.Eval((BinaryNode) expr.left, row, version); if (num4 != 0) { return num4; } int num3 = this.Eval((BinaryNode) expr.right, row, version); if (num3 != 0) { return num3; } return 0; } long num = 0L; object obj3 = expr.left.Eval(row, version); if ((expr.op != 13) && (expr.op != 0x27)) { StorageType type; object obj2 = expr.right.Eval(row, version); bool lc = expr.left is ConstNode; bool rc = expr.right is ConstNode; if ((obj3 == DBNull.Value) || (expr.left.IsSqlColumn && DataStorage.IsObjectSqlNull(obj3))) { return -1; } if ((obj2 == DBNull.Value) || (expr.right.IsSqlColumn && DataStorage.IsObjectSqlNull(obj2))) { return 1; } StorageType storageType = DataStorage.GetStorageType(obj3.GetType()); if (StorageType.Char == storageType) { if (rc || !expr.right.IsSqlColumn) { obj2 = Convert.ToChar(obj2, this.table.FormatProvider); } else { obj2 = SqlConvert.ChangeType2(obj2, StorageType.Char, typeof(char), this.table.FormatProvider); } } StorageType right = DataStorage.GetStorageType(obj2.GetType()); if (expr.left.IsSqlColumn || expr.right.IsSqlColumn) { type = expr.ResultSqlType(storageType, right, lc, rc, expr.op); } else { type = expr.ResultType(storageType, right, lc, rc, expr.op); } if (type == StorageType.Empty) { expr.SetTypeMismatchError(expr.op, obj3.GetType(), obj2.GetType()); } num = expr.BinaryCompare(obj3, obj2, type, expr.op); } switch (expr.op) { case 7: num = (num == 0L) ? ((long) 0) : ((num < 0L) ? ((long) (-1)) : ((long) 1)); break; case 8: num = (num > 0L) ? ((long) 0) : ((long) (-1)); break; case 9: num = (num < 0L) ? ((long) 0) : ((long) 1); break; case 10: num = (num >= 0L) ? ((long) 0) : ((long) (-1)); break; case 11: num = (num <= 0L) ? ((long) 0) : ((long) 1); break; case 13: num = (obj3 == DBNull.Value) ? ((long) 0) : ((long) (-1)); break; case 0x27: num = (obj3 != DBNull.Value) ? ((long) 0) : ((long) 1); break; } return (int) num; }
private void AnalyzeExpression(BinaryNode expr) { if (this.linearExpression != this.expression) { if (expr.op == 0x1b) { this.linearExpression = this.expression; } else if (expr.op == 0x1a) { bool flag = false; bool flag2 = false; if (expr.left is BinaryNode) { this.AnalyzeExpression((BinaryNode)expr.left); if (this.linearExpression == this.expression) { return; } flag = true; } else { UnaryNode left = expr.left as UnaryNode; if (left != null) { while (((left.op == 0) && (left.right is UnaryNode)) && (((UnaryNode)left.right).op == 0)) { left = (UnaryNode)left.right; } if ((left.op == 0) && (left.right is BinaryNode)) { this.AnalyzeExpression((BinaryNode)left.right); if (this.linearExpression == this.expression) { return; } flag = true; } } } if (expr.right is BinaryNode) { this.AnalyzeExpression((BinaryNode)expr.right); if (this.linearExpression == this.expression) { return; } flag2 = true; } else { UnaryNode right = expr.right as UnaryNode; if (right != null) { while (((right.op == 0) && (right.right is UnaryNode)) && (((UnaryNode)right.right).op == 0)) { right = (UnaryNode)right.right; } if ((right.op == 0) && (right.right is BinaryNode)) { this.AnalyzeExpression((BinaryNode)right.right); if (this.linearExpression == this.expression) { return; } flag2 = true; } } } if (!flag || !flag2) { ExpressionNode node3 = flag ? expr.right : expr.left; this.linearExpression = (this.linearExpression == null) ? node3 : new BinaryNode(this.table, 0x1a, node3, this.linearExpression); } } else { if (this.IsSupportedOperator(expr.op)) { if ((expr.left is NameNode) && (expr.right is ConstNode)) { ColumnInfo info2 = this.candidateColumns[((NameNode)expr.left).column.Ordinal]; info2.expr = (info2.expr == null) ? expr : new BinaryNode(this.table, 0x1a, expr, info2.expr); if (expr.op == 7) { info2.equalsOperator = true; } this.candidatesForBinarySearch = true; return; } if ((expr.right is NameNode) && (expr.left is ConstNode)) { ExpressionNode node4 = expr.left; expr.left = expr.right; expr.right = node4; switch (expr.op) { case 8: expr.op = 9; break; case 9: expr.op = 8; break; case 10: expr.op = 11; break; case 11: expr.op = 10; break; } ColumnInfo info = this.candidateColumns[((NameNode)expr.left).column.Ordinal]; info.expr = (info.expr == null) ? expr : new BinaryNode(this.table, 0x1a, expr, info.expr); if (expr.op == 7) { info.equalsOperator = true; } this.candidatesForBinarySearch = true; return; } } this.linearExpression = (this.linearExpression == null) ? expr : new BinaryNode(this.table, 0x1a, expr, this.linearExpression); } } }
private int Eval(BinaryNode expr, DataRow row, DataRowVersion version) { if (expr.op == 0x1a) { int num4 = this.Eval((BinaryNode)expr.left, row, version); if (num4 != 0) { return(num4); } int num3 = this.Eval((BinaryNode)expr.right, row, version); if (num3 != 0) { return(num3); } return(0); } long num = 0L; object obj3 = expr.left.Eval(row, version); if ((expr.op != 13) && (expr.op != 0x27)) { StorageType type; object obj2 = expr.right.Eval(row, version); bool lc = expr.left is ConstNode; bool rc = expr.right is ConstNode; if ((obj3 == DBNull.Value) || (expr.left.IsSqlColumn && DataStorage.IsObjectSqlNull(obj3))) { return(-1); } if ((obj2 == DBNull.Value) || (expr.right.IsSqlColumn && DataStorage.IsObjectSqlNull(obj2))) { return(1); } StorageType storageType = DataStorage.GetStorageType(obj3.GetType()); if (StorageType.Char == storageType) { if (rc || !expr.right.IsSqlColumn) { obj2 = Convert.ToChar(obj2, this.table.FormatProvider); } else { obj2 = SqlConvert.ChangeType2(obj2, StorageType.Char, typeof(char), this.table.FormatProvider); } } StorageType right = DataStorage.GetStorageType(obj2.GetType()); if (expr.left.IsSqlColumn || expr.right.IsSqlColumn) { type = expr.ResultSqlType(storageType, right, lc, rc, expr.op); } else { type = expr.ResultType(storageType, right, lc, rc, expr.op); } if (type == StorageType.Empty) { expr.SetTypeMismatchError(expr.op, obj3.GetType(), obj2.GetType()); } num = expr.BinaryCompare(obj3, obj2, type, expr.op); } switch (expr.op) { case 7: num = (num == 0L) ? ((long)0) : ((num < 0L) ? ((long)(-1)) : ((long)1)); break; case 8: num = (num > 0L) ? ((long)0) : ((long)(-1)); break; case 9: num = (num < 0L) ? ((long)0) : ((long)1); break; case 10: num = (num >= 0L) ? ((long)0) : ((long)(-1)); break; case 11: num = (num <= 0L) ? ((long)0) : ((long)1); break; case 13: num = (obj3 == DBNull.Value) ? ((long)0) : ((long)(-1)); break; case 0x27: num = (obj3 != DBNull.Value) ? ((long)0) : ((long)1); break; } return((int)num); }
// Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions private void AnalyzeExpression(BinaryNode expr) { Debug.Assert(_candidateColumns != null); if (_linearExpression == _expression) { return; } if (expr._op == Operators.Or) { _linearExpression = _expression; return; } else if (expr._op == Operators.And) { bool isLeft = false, isRight = false; if (expr._left is BinaryNode) { AnalyzeExpression((BinaryNode)expr._left); if (_linearExpression == _expression) { return; } isLeft = true; } else { UnaryNode?unaryNode = expr._left as UnaryNode; if (unaryNode != null) { while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode._right; } if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode._right)); if (_linearExpression == _expression) { return; } isLeft = true; } } } if (expr._right is BinaryNode) { AnalyzeExpression((BinaryNode)expr._right); if (_linearExpression == _expression) { return; } isRight = true; } else { UnaryNode?unaryNode = expr._right as UnaryNode; if (unaryNode != null) { while (unaryNode._op == Operators.Noop && unaryNode._right is UnaryNode && ((UnaryNode)unaryNode._right)._op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode._right; } if (unaryNode._op == Operators.Noop && unaryNode._right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode._right)); if (_linearExpression == _expression) { return; } isRight = true; } } } if (isLeft && isRight) { return; } ExpressionNode e = isLeft ? expr._right : expr._left; _linearExpression = (_linearExpression == null ? e : new BinaryNode(_table, Operators.And, e, _linearExpression)); return; } else if (IsSupportedOperator(expr._op)) { if (expr._left is NameNode && expr._right is ConstNode) { ColumnInfo canColumn = _candidateColumns[((NameNode)(expr._left))._column !.Ordinal];
private int Eval(BinaryNode expr, DataRow row, DataRowVersion version) { if (expr.op == Operators.And) { int lResult = Eval((BinaryNode)expr.left, row, version); if (lResult != 0) { return(lResult); } int rResult = Eval((BinaryNode)expr.right, row, version); if (rResult != 0) { return(rResult); } return(0); } long c = 0; object vLeft = expr.left.Eval(row, version); if (expr.op != Operators.Is && expr.op != Operators.IsNot) { object vRight = expr.right.Eval(row, version); bool isLConst = (expr.left is ConstNode); bool isRConst = (expr.right is ConstNode); if (vLeft == DBNull.Value) { return(-1); } if (vRight == DBNull.Value) { return(1); } if (vLeft.GetType() == typeof(char)) { vRight = Convert.ToChar(vRight); } Type result = expr.ResultType(vLeft.GetType(), vRight.GetType(), isLConst, isRConst, expr.op); if (result == null) { expr.SetTypeMismatchError(expr.op, vLeft.GetType(), vRight.GetType()); } c = expr.Compare(vLeft, vRight, result, expr.op); } switch (expr.op) { case Operators.EqualTo: c = (c == 0 ? 0 : c < 0 ? -1 : 1); break; case Operators.GreaterThen: c = (c > 0 ? 0 : -1); break; case Operators.LessThen: c = (c < 0 ? 0 : 1); break; case Operators.GreaterOrEqual: c = (c >= 0 ? 0 : -1); break; case Operators.LessOrEqual: c = (c <= 0 ? 0 : 1); break; case Operators.Is: c = (vLeft == DBNull.Value ? 0 : -1); break; case Operators.IsNot: c = (vLeft != DBNull.Value ? 0 : 1); break; default: Debug.Assert(true, "Unsupported Binary Search Operator!"); break; } return((int)c); }
/// <devdoc> /// Builds expression tree for higher-precedence operator to be used as left /// operand of current operator. May cause errors - always do ErrorCheck() upin return. /// </devdoc> private void BuildExpression(int pri) { ExpressionNode expr = null; Debug.Assert(pri > Operators.priStart && pri <= Operators.priMax, "Invalid priority value"); /* For all operators of higher or same precedence (we are always left-associative) */ while (true) { Debug.Assert(topOperator > 0, "Empty operator stack!!"); OperatorInfo opInfo = ops[topOperator - 1]; if (opInfo.priority < pri) goto end_loop; Debug.Assert(opInfo.priority >= pri, "Invalid prioriry value"); topOperator--; ExpressionNode nodeLeft; ExpressionNode nodeRight; switch (opInfo.type) { case Nodes.Binop: { // get right, left operands. Bind them. nodeRight = NodePop(); nodeLeft = NodePop(); /* This is the place to do type and other checks */ switch (opInfo.op) { case Operators.Between: case Operators.BetweenAnd: case Operators.BitwiseAnd: case Operators.BitwiseOr: case Operators.BitwiseXor: case Operators.BitwiseNot: throw ExprException.UnsupportedOperator(opInfo.op); case Operators.Is: // case Operators.Or: case Operators.And: case Operators.EqualTo: case Operators.NotEqual: case Operators.Like: case Operators.LessThen: case Operators.LessOrEqual: case Operators.GreaterThen: case Operators.GreaterOrEqual: case Operators.In: break; default: Debug.Assert(opInfo.op == Operators.Plus || opInfo.op == Operators.Minus || opInfo.op == Operators.Multiply || opInfo.op == Operators.Divide || opInfo.op == Operators.Modulo, "Invalud Binary operation"); break; } Debug.Assert(nodeLeft != null, "Invalid left operand"); Debug.Assert(nodeRight != null, "Invalid right operand"); if (opInfo.op == Operators.Like) { expr = new LikeNode(_table, opInfo.op, nodeLeft, nodeRight); } else { expr = new BinaryNode(_table, opInfo.op, nodeLeft, nodeRight); } break; } case Nodes.Unop: /* Unary operator: Pop and bind right op. */ nodeLeft = null; nodeRight = NodePop(); /* Check for special cases */ switch (opInfo.op) { case Operators.Not: break; case Operators.BitwiseNot: throw ExprException.UnsupportedOperator(opInfo.op); case Operators.Negative: break; } Debug.Assert(nodeLeft == null, "Invalid left operand"); Debug.Assert(nodeRight != null, "Invalid right operand"); expr = new UnaryNode(_table, opInfo.op, nodeRight); break; case Nodes.Zop: /* Intrinsic constant: just create node. */ expr = new ZeroOpNode(opInfo.op); break; default: Debug.Assert(false, "Unhandled operator type"); goto end_loop; } Debug.Assert(expr != null, "Failed to create expression"); NodePush(expr); // countinue while loop; } end_loop: ; }
// Microsoft : Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions private void AnalyzeExpression(BinaryNode expr) { if (this.linearExpression == this.expression) { return; } if (expr.op == Operators.Or) { this.linearExpression = this.expression; return; } else if (expr.op == Operators.And) { bool isLeft = false, isRight = false; if (expr.left is BinaryNode) { AnalyzeExpression((BinaryNode)expr.left); if (this.linearExpression == this.expression) { return; } isLeft = true; } else { UnaryNode unaryNode = expr.left as UnaryNode; if (unaryNode != null) { while (unaryNode.op == Operators.Noop && unaryNode.right is UnaryNode && ((UnaryNode)unaryNode.right).op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode.right; } if (unaryNode.op == Operators.Noop && unaryNode.right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode.right)); if (this.linearExpression == this.expression) { return; } isLeft = true; } } } if (expr.right is BinaryNode) { AnalyzeExpression((BinaryNode)expr.right); if (this.linearExpression == this.expression) { return; } isRight = true; } else { UnaryNode unaryNode = expr.right as UnaryNode; if (unaryNode != null) { while (unaryNode.op == Operators.Noop && unaryNode.right is UnaryNode && ((UnaryNode)unaryNode.right).op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode.right; } if (unaryNode.op == Operators.Noop && unaryNode.right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode.right)); if (this.linearExpression == this.expression) { return; } // SQLBU 497534: DataTable.Select() returns incorrect results with multiple statements depending '(' and ')' // from copy paste error fixing SQLBU 342141 isRight = true; } } } if (isLeft && isRight) { return; } ExpressionNode e = isLeft ? expr.right : expr.left; this.linearExpression = (this.linearExpression == null ? e : new BinaryNode(table, Operators.And, e, this.linearExpression)); return; } else if (IsSupportedOperator(expr.op)) { if (expr.left is NameNode && expr.right is ConstNode) { ColumnInfo canColumn = (ColumnInfo)candidateColumns[((NameNode)(expr.left)).column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(table, Operators.And, expr, canColumn.expr)); if (expr.op == Operators.EqualTo) { canColumn.equalsOperator = true; } candidatesForBinarySearch = true; return; } else if (expr.right is NameNode && expr.left is ConstNode) { ExpressionNode temp = expr.left; expr.left = expr.right; expr.right = temp; switch (expr.op) { case Operators.GreaterThen: expr.op = Operators.LessThen; break; case Operators.LessThen: expr.op = Operators.GreaterThen; break; case Operators.GreaterOrEqual: expr.op = Operators.LessOrEqual; break; case Operators.LessOrEqual: expr.op = Operators.GreaterOrEqual; break; default: break; } ColumnInfo canColumn = (ColumnInfo)candidateColumns[((NameNode)(expr.left)).column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(table, Operators.And, expr, canColumn.expr)); if (expr.op == Operators.EqualTo) { canColumn.equalsOperator = true; } candidatesForBinarySearch = true; return; } } this.linearExpression = (this.linearExpression == null ? expr : new BinaryNode(table, Operators.And, expr, this.linearExpression)); return; }
// [....] : Gathers all linear expressions in to this.linearExpression and all binary expressions in to their respective candidate columns expressions private void AnalyzeExpression(BinaryNode expr) { if (this.linearExpression == this.expression) return; if (expr.op == Operators.Or) { this.linearExpression = this.expression; return; } else if (expr.op == Operators.And) { bool isLeft=false, isRight=false; if (expr.left is BinaryNode) { AnalyzeExpression((BinaryNode)expr.left); if (this.linearExpression == this.expression) return; isLeft = true; } else { UnaryNode unaryNode = expr.left as UnaryNode; if (unaryNode != null) { while (unaryNode.op == Operators.Noop && unaryNode.right is UnaryNode && ((UnaryNode)unaryNode.right).op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode.right; } if (unaryNode.op == Operators.Noop && unaryNode.right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode.right)); if (this.linearExpression == this.expression) { return; } isLeft = true; } } } if (expr.right is BinaryNode) { AnalyzeExpression((BinaryNode)expr.right); if (this.linearExpression == this.expression) return; isRight = true; } else { UnaryNode unaryNode = expr.right as UnaryNode; if (unaryNode != null) { while (unaryNode.op == Operators.Noop && unaryNode.right is UnaryNode && ((UnaryNode)unaryNode.right).op == Operators.Noop) { unaryNode = (UnaryNode)unaryNode.right; } if (unaryNode.op == Operators.Noop && unaryNode.right is BinaryNode) { AnalyzeExpression((BinaryNode)(unaryNode.right)); if (this.linearExpression == this.expression) { return; } // SQLBU 497534: DataTable.Select() returns incorrect results with multiple statements depending '(' and ')' // from copy paste error fixing SQLBU 342141 isRight = true; } } } if (isLeft && isRight) return; ExpressionNode e = isLeft ? expr.right : expr.left; this.linearExpression = (this.linearExpression == null ? e : new BinaryNode(table, Operators.And, e, this.linearExpression)); return; } else if (IsSupportedOperator(expr.op)) { if (expr.left is NameNode && expr.right is ConstNode) { ColumnInfo canColumn = (ColumnInfo)candidateColumns[((NameNode)(expr.left)).column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(table, Operators.And, expr, canColumn.expr)); if (expr.op == Operators.EqualTo) { canColumn.equalsOperator = true; } candidatesForBinarySearch = true; return; } else if (expr.right is NameNode && expr.left is ConstNode) { ExpressionNode temp = expr.left; expr.left = expr.right; expr.right = temp; switch(expr.op) { case Operators.GreaterThen: expr.op = Operators.LessThen; break; case Operators.LessThen: expr.op = Operators.GreaterThen; break; case Operators.GreaterOrEqual: expr.op = Operators.LessOrEqual; break; case Operators.LessOrEqual: expr.op = Operators.GreaterOrEqual; break; default : break; } ColumnInfo canColumn = (ColumnInfo)candidateColumns[((NameNode)(expr.left)).column.Ordinal]; canColumn.expr = (canColumn.expr == null ? expr : new BinaryNode(table, Operators.And, expr, canColumn.expr)); if (expr.op == Operators.EqualTo) { canColumn.equalsOperator = true; } candidatesForBinarySearch = true; return; } } this.linearExpression = (this.linearExpression == null ? expr : new BinaryNode(table, Operators.And, expr, this.linearExpression)); return; }