private object EvalUnaryOp(int op, object vl) { object value = DBNull.Value; if (DataExpression.IsUnknown(vl)) { return(DBNull.Value); } StorageType storageType; switch (op) { case Operators.Noop: return(vl); case Operators.UnaryPlus: storageType = DataStorage.GetStorageType(vl.GetType()); if (ExpressionNode.IsNumericSql(storageType)) { return(vl); } throw ExprException.TypeMismatch(ToString()); case Operators.Negative: // the have to be better way for doing this.. storageType = DataStorage.GetStorageType(vl.GetType()); if (ExpressionNode.IsNumericSql(storageType)) { switch (storageType) { case StorageType.Byte: value = -(byte)vl; break; case StorageType.Int16: value = -(short)vl; break; case StorageType.Int32: value = -(int)vl; break; case StorageType.Int64: value = -(long)vl; break; case StorageType.Single: value = -(float)vl; break; case StorageType.Double: value = -(double)vl; break; case StorageType.Decimal: value = -(decimal)vl; break; case StorageType.SqlDecimal: value = -(SqlDecimal)vl; break; case StorageType.SqlDouble: value = -(SqlDouble)vl; break; case StorageType.SqlSingle: value = -(SqlSingle)vl; break; case StorageType.SqlMoney: value = -(SqlMoney)vl; break; case StorageType.SqlInt64: value = -(SqlInt64)vl; break; case StorageType.SqlInt32: value = -(SqlInt32)vl; break; case StorageType.SqlInt16: value = -(SqlInt16)vl; break; default: Debug.Fail("Missing a type conversion"); value = DBNull.Value; break; } return(value); } throw ExprException.TypeMismatch(ToString()); case Operators.Not: if (vl is SqlBoolean) { if (((SqlBoolean)vl).IsFalse) { return(SqlBoolean.True); } else if (((SqlBoolean)vl).IsTrue) { return(SqlBoolean.False); } throw ExprException.UnsupportedOperator(op); // or should the result of not SQLNull be SqlNull ? } else { if (DataExpression.ToBoolean(vl) != false) { return(false); } return(true); } default: throw ExprException.UnsupportedOperator(op); } }
/// <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; }
private object EvalUnaryOp(int op, object vl) { object value = DBNull.Value; if (DataExpression.IsUnknown(vl)) { return(DBNull.Value); } switch (op) { case Operators.Noop: return(vl); case Operators.UnaryPlus: if (ExpressionNode.IsNumeric(vl.GetType())) { return(vl); } throw ExprException.TypeMismatch(this.ToString()); case Operators.Negative: // the have to be better way for doing this.. if (ExpressionNode.IsNumeric(vl.GetType())) { if (vl is byte) { value = -(Byte)vl; } else if (vl is Int16) { value = -(Int16)vl; } else if (vl is Int32) { value = -(Int32)vl; } else if (vl is Int64) { value = -(Int64)vl; } else if (vl is Single) { value = -(Single)vl; } else if (vl is Double) { value = -(Double)vl; } else if (vl is Decimal) { value = -(Decimal)vl; } else { Debug.Assert(false, "Missing a type conversion " + vl.GetType().FullName); value = DBNull.Value; } return(value); } throw ExprException.TypeMismatch(this.ToString()); case Operators.Not: if (DataExpression.ToBoolean(vl) != false) { return(false); } return(true); default: throw ExprException.UnsupportedOperator(op); } }
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 object EvalUnaryOp(int op, object vl) { if (!DataExpression.IsUnknown(vl)) { switch (op) { case 0: return(vl); case 1: { StorageType storageType = DataStorage.GetStorageType(vl.GetType()); if (!ExpressionNode.IsNumericSql(storageType)) { throw ExprException.TypeMismatch(this.ToString()); } switch (storageType) { case StorageType.Byte: return((int)-((byte)vl)); case StorageType.Int16: return((int)-((short)vl)); case StorageType.Int32: return(-((int)vl)); case StorageType.Int64: return(-((long)vl)); case StorageType.Single: return(-((float)vl)); case StorageType.Double: return(-((double)vl)); case StorageType.Decimal: return(-((decimal)vl)); case StorageType.SqlDecimal: return(-((SqlDecimal)vl)); case StorageType.SqlDouble: return(-((SqlDouble)vl)); case StorageType.SqlInt16: return(-((SqlInt16)vl)); case StorageType.SqlInt32: return(-((SqlInt32)vl)); case StorageType.SqlInt64: return(-((SqlInt64)vl)); case StorageType.SqlMoney: return(-((SqlMoney)vl)); case StorageType.SqlSingle: return(-((SqlSingle)vl)); } break; } case 2: if (!ExpressionNode.IsNumericSql(DataStorage.GetStorageType(vl.GetType()))) { throw ExprException.TypeMismatch(this.ToString()); } return(vl); case 3: { if (!(vl is SqlBoolean)) { if (DataExpression.ToBoolean(vl)) { return(false); } return(true); } SqlBoolean flag2 = (SqlBoolean)vl; if (!flag2.IsFalse) { SqlBoolean flag = (SqlBoolean)vl; if (!flag.IsTrue) { throw ExprException.UnsupportedOperator(op); } return(SqlBoolean.False); } return(SqlBoolean.True); } default: throw ExprException.UnsupportedOperator(op); } } return(DBNull.Value); }