private object EvalBinaryOp(int op, ExpressionNode left, ExpressionNode right, DataRow row, DataRowVersion version, int[] recordNos)
{
object vLeft;
object vRight;
StorageType resultType;
/*
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);
Type typeofLeft = vLeft.GetType();
Type typeofRight = vRight.GetType();
StorageType leftStorage = DataStorage.GetStorageType(typeofLeft);
StorageType rightStorage = DataStorage.GetStorageType(typeofRight);
bool leftIsSqlType = DataStorage.IsSqlType(leftStorage);
bool rightIsSqlType = DataStorage.IsSqlType(rightStorage);
// special case of handling NULLS, currently only OR operator can work with NULLS
if (leftIsSqlType && DataStorage.IsObjectSqlNull(vLeft))
{
return vLeft;
}
else if (rightIsSqlType && DataStorage.IsObjectSqlNull(vRight))
{
return vRight;
}
else if ((vLeft == DBNull.Value) || (vRight == DBNull.Value))
{
return DBNull.Value;
}
if (leftIsSqlType || rightIsSqlType)
{
resultType = ResultSqlType(leftStorage, rightStorage, (left is ConstNode), (right is ConstNode), op);
}
else
{
resultType = ResultType(leftStorage, rightStorage, (left is ConstNode), (right is ConstNode), op);
}
if (StorageType.Empty == resultType)
{
SetTypeMismatchError(op, typeofLeft, typeofRight);
}
}
else
{
vLeft = vRight = DBNull.Value;
resultType = StorageType.Empty; // shouldnt we make it boolean?
}
object value = DBNull.Value;
bool typeMismatch = false;
try
{
switch (op)
{
case Operators.Plus:
switch (resultType)
{
case StorageType.Byte:
{
value = Convert.ToByte((Convert.ToByte(vLeft, FormatProvider) + Convert.ToByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SByte:
{
value = Convert.ToSByte((Convert.ToSByte(vLeft, FormatProvider) + Convert.ToSByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int16:
{
value = Convert.ToInt16((Convert.ToInt16(vLeft, FormatProvider) + Convert.ToInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.UInt16:
{
value = Convert.ToUInt16((Convert.ToUInt16(vLeft, FormatProvider) + Convert.ToUInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int32:
{
checked { value = Convert.ToInt32(vLeft, FormatProvider) + Convert.ToInt32(vRight, FormatProvider); }
break;
}
case StorageType.UInt32:
{
checked { value = Convert.ToUInt32(vLeft, FormatProvider) + Convert.ToUInt32(vRight, FormatProvider); }
break;
}
case StorageType.UInt64:
{
checked { value = Convert.ToUInt64(vLeft, FormatProvider) + Convert.ToUInt64(vRight, FormatProvider); }
break;
}
case StorageType.Int64:
{
checked { value = Convert.ToInt64(vLeft, FormatProvider) + Convert.ToInt64(vRight, FormatProvider); }
break;
}
case StorageType.Decimal:
{
checked { value = Convert.ToDecimal(vLeft, FormatProvider) + Convert.ToDecimal(vRight, FormatProvider); }
break;
}
case StorageType.Single:
{
checked { value = Convert.ToSingle(vLeft, FormatProvider) + Convert.ToSingle(vRight, FormatProvider); }
break;
}
case StorageType.Double:
{
checked { value = Convert.ToDouble(vLeft, FormatProvider) + Convert.ToDouble(vRight, FormatProvider); }
break;
}
case StorageType.String:
case StorageType.Char:
{
value = Convert.ToString(vLeft, FormatProvider) + Convert.ToString(vRight, FormatProvider);
break;
}
case StorageType.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;
}
break;
}
case StorageType.TimeSpan:
{
value = (TimeSpan)vLeft + (TimeSpan)vRight;
break;
}
case StorageType.SqlInt16:
{
value = (SqlConvert.ConvertToSqlInt16(vLeft) + SqlConvert.ConvertToSqlInt16(vRight));
break;
}
case StorageType.SqlInt32:
{
value = (SqlConvert.ConvertToSqlInt32(vLeft) + SqlConvert.ConvertToSqlInt32(vRight));
break;
}
case StorageType.SqlInt64:
{
value = (SqlConvert.ConvertToSqlInt64(vLeft) + SqlConvert.ConvertToSqlInt64(vRight));
break;
}
case StorageType.SqlDouble:
{
value = (SqlConvert.ConvertToSqlDouble(vLeft) + SqlConvert.ConvertToSqlDouble(vRight));
break;
}
case StorageType.SqlSingle:
{
value = (SqlConvert.ConvertToSqlSingle(vLeft) + SqlConvert.ConvertToSqlSingle(vRight));
break;
}
case StorageType.SqlDecimal:
{
value = (SqlConvert.ConvertToSqlDecimal(vLeft) + SqlConvert.ConvertToSqlDecimal(vRight));
break;
}
case StorageType.SqlMoney:
{
value = (SqlConvert.ConvertToSqlMoney(vLeft) + SqlConvert.ConvertToSqlMoney(vRight));
break;
}
case StorageType.SqlByte:
{
value = (SqlConvert.ConvertToSqlByte(vLeft) + SqlConvert.ConvertToSqlByte(vRight));
break;
}
case StorageType.SqlString:
{
value = (SqlConvert.ConvertToSqlString(vLeft) + SqlConvert.ConvertToSqlString(vRight));
break;
}
case StorageType.SqlDateTime:
{
if (vLeft is TimeSpan && vRight is SqlDateTime)
{
SqlDateTime rValue = SqlConvert.ConvertToSqlDateTime(vRight);
value = SqlConvert.ConvertToSqlDateTime((DateTime)rValue.Value + (TimeSpan)vLeft);
}
else if (vLeft is SqlDateTime && vRight is TimeSpan)
{
SqlDateTime lValue = SqlConvert.ConvertToSqlDateTime(vLeft);
value = SqlConvert.ConvertToSqlDateTime((DateTime)lValue.Value + (TimeSpan)vRight);
}
else
{
typeMismatch = true;
}
break;
}
default:
{
typeMismatch = true;
break;
}
}
break; // Operators.Plus
case Operators.Minus:
switch (resultType)
{
case StorageType.Byte:
{
value = Convert.ToByte((Convert.ToByte(vLeft, FormatProvider) - Convert.ToByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SqlByte:
{
value = (SqlConvert.ConvertToSqlByte(vLeft) - SqlConvert.ConvertToSqlByte(vRight));
break;
}
case StorageType.SByte:
{
value = Convert.ToSByte((Convert.ToSByte(vLeft, FormatProvider) - Convert.ToSByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int16:
{
value = Convert.ToInt16((Convert.ToInt16(vLeft, FormatProvider) - Convert.ToInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SqlInt16:
{
value = (SqlConvert.ConvertToSqlInt16(vLeft) - SqlConvert.ConvertToSqlInt16(vRight));
break;
}
case StorageType.UInt16:
{
value = Convert.ToUInt16((Convert.ToUInt16(vLeft, FormatProvider) - Convert.ToUInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int32:
{
checked { value = Convert.ToInt32(vLeft, FormatProvider) - Convert.ToInt32(vRight, FormatProvider); }
break;
}
case StorageType.SqlInt32:
{
value = (SqlConvert.ConvertToSqlInt32(vLeft) - SqlConvert.ConvertToSqlInt32(vRight));
break;
}
case StorageType.UInt32:
{
checked { value = Convert.ToUInt32(vLeft, FormatProvider) - Convert.ToUInt32(vRight, FormatProvider); }
break;
}
case StorageType.Int64:
{
checked { value = Convert.ToInt64(vLeft, FormatProvider) - Convert.ToInt64(vRight, FormatProvider); }
break;
}
case StorageType.SqlInt64:
{
value = (SqlConvert.ConvertToSqlInt64(vLeft) - SqlConvert.ConvertToSqlInt64(vRight));
break;
}
case StorageType.UInt64:
{
checked { value = Convert.ToUInt64(vLeft, FormatProvider) - Convert.ToUInt64(vRight, FormatProvider); }
break;
}
case StorageType.Decimal:
{
checked { value = Convert.ToDecimal(vLeft, FormatProvider) - Convert.ToDecimal(vRight, FormatProvider); }
break;
}
case StorageType.SqlDecimal:
{
value = (SqlConvert.ConvertToSqlDecimal(vLeft) - SqlConvert.ConvertToSqlDecimal(vRight));
break;
}
case StorageType.Single:
{
checked { value = Convert.ToSingle(vLeft, FormatProvider) - Convert.ToSingle(vRight, FormatProvider); }
break;
}
case StorageType.SqlSingle:
{
value = (SqlConvert.ConvertToSqlSingle(vLeft) - SqlConvert.ConvertToSqlSingle(vRight));
break;
}
case StorageType.Double:
{
checked { value = Convert.ToDouble(vLeft, FormatProvider) - Convert.ToDouble(vRight, FormatProvider); }
break;
}
case StorageType.SqlDouble:
{
value = (SqlConvert.ConvertToSqlDouble(vLeft) - SqlConvert.ConvertToSqlDouble(vRight));
break;
}
case StorageType.SqlMoney:
{
value = (SqlConvert.ConvertToSqlMoney(vLeft) - SqlConvert.ConvertToSqlMoney(vRight));
break;
}
case StorageType.DateTime:
{
value = (DateTime)vLeft - (TimeSpan)vRight;
break;
}
case StorageType.TimeSpan:
{
if (vLeft is DateTime)
{
value = (DateTime)vLeft - (DateTime)vRight;
}
else
value = (TimeSpan)vLeft - (TimeSpan)vRight;
break;
}
case StorageType.SqlDateTime:
{
if (vLeft is TimeSpan && vRight is SqlDateTime)
{
SqlDateTime rValue = SqlConvert.ConvertToSqlDateTime(vRight);
value = SqlConvert.ConvertToSqlDateTime((DateTime)rValue.Value - (TimeSpan)vLeft);
}
else if (vLeft is SqlDateTime && vRight is TimeSpan)
{
SqlDateTime lValue = SqlConvert.ConvertToSqlDateTime(vLeft);
value = SqlConvert.ConvertToSqlDateTime((DateTime)lValue.Value - (TimeSpan)vRight);
}
else
{
typeMismatch = true;
}
break;
}
default:
{
typeMismatch = true;
break;
}
}
break; // Operators.Minus
case Operators.Multiply:
switch (resultType)
{
case StorageType.Byte:
{
value = Convert.ToByte((Convert.ToByte(vLeft, FormatProvider) * Convert.ToByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SqlByte:
{
value = (SqlConvert.ConvertToSqlByte(vLeft) * SqlConvert.ConvertToSqlByte(vRight));
break;
}
case StorageType.SByte:
{
value = Convert.ToSByte((Convert.ToSByte(vLeft, FormatProvider) * Convert.ToSByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int16:
{
value = Convert.ToInt16((Convert.ToInt16(vLeft, FormatProvider) * Convert.ToInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SqlInt16:
{
value = (SqlConvert.ConvertToSqlInt16(vLeft) * SqlConvert.ConvertToSqlInt16(vRight));
break;
}
case StorageType.UInt16:
{
value = Convert.ToUInt16((Convert.ToUInt16(vLeft, FormatProvider) * Convert.ToUInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int32:
{
checked { value = Convert.ToInt32(vLeft, FormatProvider) * Convert.ToInt32(vRight, FormatProvider); }
break;
}
case StorageType.SqlInt32:
{
value = (SqlConvert.ConvertToSqlInt32(vLeft) * SqlConvert.ConvertToSqlInt32(vRight));
break;
}
case StorageType.UInt32:
{
checked { value = Convert.ToUInt32(vLeft, FormatProvider) * Convert.ToUInt32(vRight, FormatProvider); }
break;
}
case StorageType.Int64:
{
checked { value = Convert.ToInt64(vLeft, FormatProvider) * Convert.ToInt64(vRight, FormatProvider); }
break;
}
case StorageType.SqlInt64:
{
value = (SqlConvert.ConvertToSqlInt64(vLeft) * SqlConvert.ConvertToSqlInt64(vRight));
break;
}
case StorageType.UInt64:
{
checked { value = Convert.ToUInt64(vLeft, FormatProvider) * Convert.ToUInt64(vRight, FormatProvider); }
break;
}
case StorageType.Decimal:
{
checked { value = Convert.ToDecimal(vLeft, FormatProvider) * Convert.ToDecimal(vRight, FormatProvider); }
break;
}
case StorageType.SqlDecimal:
{
value = (SqlConvert.ConvertToSqlDecimal(vLeft) * SqlConvert.ConvertToSqlDecimal(vRight));
break;
}
case StorageType.Single:
{
checked { value = Convert.ToSingle(vLeft, FormatProvider) * Convert.ToSingle(vRight, FormatProvider); }
break;
}
case StorageType.SqlSingle:
{
value = (SqlConvert.ConvertToSqlSingle(vLeft) * SqlConvert.ConvertToSqlSingle(vRight));
break;
}
case StorageType.SqlMoney:
{
value = (SqlConvert.ConvertToSqlMoney(vLeft) * SqlConvert.ConvertToSqlMoney(vRight));
break;
}
case StorageType.Double:
{
checked { value = Convert.ToDouble(vLeft, FormatProvider) * Convert.ToDouble(vRight, FormatProvider); }
break;
}
case StorageType.SqlDouble:
{
value = (SqlConvert.ConvertToSqlDouble(vLeft) * SqlConvert.ConvertToSqlDouble(vRight));
break;
}
default:
{
typeMismatch = true;
break;
}
}
break; // Operators.Multiply
case Operators.Divide:
switch (resultType)
{
case StorageType.Byte:
{
value = Convert.ToByte((Convert.ToByte(vLeft, FormatProvider) / Convert.ToByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SqlByte:
{
value = (SqlConvert.ConvertToSqlByte(vLeft) / SqlConvert.ConvertToSqlByte(vRight));
break;
}
case StorageType.SByte:
{
value = Convert.ToSByte((Convert.ToSByte(vLeft, FormatProvider) / Convert.ToSByte(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int16:
{
value = Convert.ToInt16((Convert.ToInt16(vLeft, FormatProvider) / Convert.ToInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.SqlInt16:
{
value = (SqlConvert.ConvertToSqlInt16(vLeft) / SqlConvert.ConvertToSqlInt16(vRight));
break;
}
case StorageType.UInt16:
{
value = Convert.ToUInt16((Convert.ToUInt16(vLeft, FormatProvider) / Convert.ToUInt16(vRight, FormatProvider)), FormatProvider);
break;
}
case StorageType.Int32:
{
checked { value = Convert.ToInt32(vLeft, FormatProvider) / Convert.ToInt32(vRight, FormatProvider); }
break;
}
case StorageType.SqlInt32:
{
value = (SqlConvert.ConvertToSqlInt32(vLeft) / SqlConvert.ConvertToSqlInt32(vRight));
break;
}
case StorageType.UInt32:
{
checked { value = Convert.ToUInt32(vLeft, FormatProvider) / Convert.ToUInt32(vRight, FormatProvider); }
break;
}
case StorageType.UInt64:
{
checked { value = Convert.ToUInt64(vLeft, FormatProvider) / Convert.ToUInt64(vRight, FormatProvider); }
break;
}
case StorageType.Int64:
{
checked { value = Convert.ToInt64(vLeft, FormatProvider) / Convert.ToInt64(vRight, FormatProvider); }
break;
}
case StorageType.SqlInt64:
{
value = (SqlConvert.ConvertToSqlInt64(vLeft) / SqlConvert.ConvertToSqlInt64(vRight));
break;
}
case StorageType.Decimal:
{
checked { value = Convert.ToDecimal(vLeft, FormatProvider) / Convert.ToDecimal(vRight, FormatProvider); }
break;
}
case StorageType.SqlDecimal:
{
value = (SqlConvert.ConvertToSqlDecimal(vLeft) / SqlConvert.ConvertToSqlDecimal(vRight));
break;
}
case StorageType.Single:
{
checked { value = Convert.ToSingle(vLeft, FormatProvider) / Convert.ToSingle(vRight, FormatProvider); }
break;
}
case StorageType.SqlSingle:
{
value = (SqlConvert.ConvertToSqlSingle(vLeft) / SqlConvert.ConvertToSqlSingle(vRight));
break;
}
case StorageType.SqlMoney:
{
value = (SqlConvert.ConvertToSqlMoney(vLeft) / SqlConvert.ConvertToSqlMoney(vRight));
break;
}
case StorageType.Double:
{
double b = Convert.ToDouble(vRight, FormatProvider);
checked { value = Convert.ToDouble(vLeft, FormatProvider) / b; }
break;
}
case StorageType.SqlDouble:
{
value = (SqlConvert.ConvertToSqlDouble(vLeft) / SqlConvert.ConvertToSqlDouble(vRight));
break;
}
default:
{
typeMismatch = true;
break;
}
}
break; // Operators.Divide
case Operators.EqualTo:
if ((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)) ||
(vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
return DBNull.Value;
return (0 == BinaryCompare(vLeft, vRight, resultType, Operators.EqualTo));
case Operators.GreaterThen:
if ((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)) ||
(vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
return DBNull.Value;
return (0 < BinaryCompare(vLeft, vRight, resultType, op));
case Operators.LessThen:
if ((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)) ||
(vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
return DBNull.Value;
return (0 > BinaryCompare(vLeft, vRight, resultType, op));
case Operators.GreaterOrEqual:
if ((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)) ||
(vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
return DBNull.Value;
return (0 <= BinaryCompare(vLeft, vRight, resultType, op));
case Operators.LessOrEqual:
if (((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft))) ||
((vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight))))
return DBNull.Value;
return (0 >= BinaryCompare(vLeft, vRight, resultType, op));
case Operators.NotEqual:
if (((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft))) ||
((vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight))))
return DBNull.Value;
return (0 != BinaryCompare(vLeft, vRight, resultType, op));
case Operators.Is:
vLeft = BinaryNode.Eval(left, row, version, recordNos);
if ((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)))
{
return true;
}
return false;
case Operators.IsNot:
vLeft = BinaryNode.Eval(left, row, version, recordNos);
if ((vLeft == DBNull.Value) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)))
{
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) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)))
return DBNull.Value;
if ((!(vLeft is bool)) && (!(vLeft is SqlBoolean)))
{
vRight = BinaryNode.Eval(right, row, version, recordNos);
typeMismatch = true;
break;
}
if (vLeft is bool)
{
if ((bool)vLeft == false)
{
value = false;
break;
}
}
else
{
if (((SqlBoolean)vLeft).IsFalse)
{
value = false;
break;
}
}
vRight = BinaryNode.Eval(right, row, version, recordNos);
if ((vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
return DBNull.Value;
if ((!(vRight is bool)) && (!(vRight is SqlBoolean)))
{
typeMismatch = true;
break;
}
if (vRight is bool)
{
value = (bool)vRight;
break;
}
else
{
value = ((SqlBoolean)vRight).IsTrue;
}
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) && (!DataStorage.IsObjectSqlNull(vLeft)))
{
if ((!(vLeft is bool)) && (!(vLeft is SqlBoolean)))
{
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) || (DataStorage.IsObjectSqlNull(vRight)))
return vLeft;
if ((vLeft == DBNull.Value) || (DataStorage.IsObjectSqlNull(vLeft)))
return vRight;
if ((!(vRight is bool)) && (!(vRight is SqlBoolean)))
{
typeMismatch = true;
break;
}
value = (vRight is bool) ? ((bool)vRight) : (((SqlBoolean)vRight).IsTrue);
break;
/* for M3, use original code , in below, and make sure to have two different code path; increases perf
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.IsIntegerSql(resultType))
{
if (resultType == StorageType.UInt64)
{
value = Convert.ToUInt64(vLeft, FormatProvider) % Convert.ToUInt64(vRight, FormatProvider);
}
else if (DataStorage.IsSqlType(resultType))
{
SqlInt64 res = (SqlConvert.ConvertToSqlInt64(vLeft) % SqlConvert.ConvertToSqlInt64(vRight));
if (resultType == StorageType.SqlInt32)
{
value = res.ToSqlInt32();
}
else if (resultType == StorageType.SqlInt16)
{
value = res.ToSqlInt16();
}
else if (resultType == StorageType.SqlByte)
{
value = res.ToSqlByte();
}
else
{
value = res;
}
}
else
{
value = Convert.ToInt64(vLeft, FormatProvider) % Convert.ToInt64(vRight, FormatProvider);
value = Convert.ChangeType(value, DataStorage.GetTypeStorage(resultType), FormatProvider);
}
}
else
{
typeMismatch = true;
}
break;
case Operators.In:
/*
special case evaluating of the IN operator: the right have to be IN function node
*/
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) || (left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)))
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 ((vRight == DBNull.Value) || (right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
continue;
Debug.Assert((!DataStorage.IsObjectNull(vLeft)) && (!DataStorage.IsObjectNull(vRight)), "Imposible..");
resultType = DataStorage.GetStorageType(vLeft.GetType());
if (0 == BinaryCompare(vLeft, vRight, resultType, Operators.EqualTo))
{
value = true;
break;
}
}
break;
default:
throw ExprException.UnsupportedOperator(op);
}
}
catch (OverflowException)
{
throw ExprException.Overflow(DataStorage.GetTypeStorage(resultType));
}
if (typeMismatch)
{
SetTypeMismatchError(op, vLeft.GetType(), vRight.GetType());
}
return value;
}