System.Data.BinaryNode.EvalBinaryOp C# (CSharp) Method

EvalBinaryOp() private method

private EvalBinaryOp ( int op, ExpressionNode left, ExpressionNode right, DataRow row, DataRowVersion version, int recordNos ) : object
op int
left ExpressionNode
right ExpressionNode
row DataRow
version DataRowVersion
recordNos int
return object
        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;
        }