IsInteger() static private method

static private IsInteger ( StorageType type ) : bool
type StorageType
return bool
示例#1
0
        private object EvalFunction(FunctionId id, object[] argumentValues, DataRow row, DataRowVersion version)
        {
            StorageType storageType;

            switch (id)
            {
            case FunctionId.Abs:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));

                storageType = DataStorage.GetStorageType(argumentValues[0].GetType());
                if (ExpressionNode.IsInteger(storageType))
                {
                    return(Math.Abs((long)argumentValues[0]));
                }
                if (ExpressionNode.IsNumeric(storageType))
                {
                    return(Math.Abs((double)argumentValues[0]));
                }

                throw ExprException.ArgumentTypeInteger(s_funcs[_info]._name, 1);

            case FunctionId.cBool:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));

                storageType = DataStorage.GetStorageType(argumentValues[0].GetType());
                return(storageType switch
                {
                    StorageType.Boolean => (bool)argumentValues[0],
                    StorageType.Int32 => ((int)argumentValues[0] != 0),
                    StorageType.Double => ((double)argumentValues[0] != 0.0),
                    StorageType.String => bool.Parse((string)argumentValues[0]),
                    _ => throw ExprException.DatatypeConvertion(argumentValues[0].GetType(), typeof(bool)),
                });
示例#2
0
        internal static bool ToBoolean(object value, bool strict)
        {
            if (IsUnknown(value))
            {
                return(false);
            }
            if (value is bool)
            {
                return((bool)value);
            }
            if (value is string)
            {
                try {
                    return(Boolean.Parse((string)value));
                }
                catch (Exception) {
                    // CONSIDER: keep the original exception, add it to the error text
                    throw ExprException.DatavalueConvertion(value, typeof(bool));
                }
            }
            if (!strict)
            {
                // convert whole numeric values to boolean:
                if (ExpressionNode.IsInteger(value.GetType()))
                {
                    return((Int64)value != 0);
                }
            }

            throw ExprException.DatavalueConvertion(value, typeof(bool));
        }
示例#3
0
        internal override object Eval(DataRow row, DataRowVersion version)
        {
            Debug.Assert(_info < s_funcs.Length && _info >= 0, "Invalid function info.");

            object[] argumentValues = new object[_argumentCount];

            Debug.Assert(_argumentCount == s_funcs[_info]._argumentCount || s_funcs[_info]._isVariantArgumentList, "Invalid argument argumentCount.");

            // special case of the Convert function
            if (s_funcs[_info]._id == FunctionId.Convert)
            {
                if (_argumentCount != 2)
                {
                    throw ExprException.FunctionArgumentCount(_name);
                }

                argumentValues[0] = _arguments[0].Eval(row, version);
                argumentValues[1] = GetDataType(_arguments[1]);
            }
            else if (s_funcs[_info]._id != FunctionId.Iif)
            { // We do not want to evaluate arguments of IIF, we will already do it in EvalFunction/ second point: we may go to div by 0
                for (int i = 0; i < _argumentCount; i++)
                {
                    argumentValues[i] = _arguments[i].Eval(row, version);

                    if (s_funcs[_info]._isValidateArguments)
                    {
                        if ((argumentValues[i] == DBNull.Value) || (typeof(object) == s_funcs[_info]._parameters[i]))
                        {
                            // currently all supported functions with IsValidateArguments set to true
                            // NOTE: for IIF and ISNULL IsValidateArguments set to false
                            return(DBNull.Value);
                        }

                        if (argumentValues[i].GetType() != s_funcs[_info]._parameters[i])
                        {
                            // We are allowing conversions in one very specific case: int, int64,...'nice' numeric to numeric..

                            if (s_funcs[_info]._parameters[i] == typeof(int) && ExpressionNode.IsInteger(DataStorage.GetStorageType(argumentValues[i].GetType())))
                            {
                                argumentValues[i] = Convert.ToInt32(argumentValues[i], FormatProvider);
                            }
                            else if ((s_funcs[_info]._id == FunctionId.Trim) || (s_funcs[_info]._id == FunctionId.Substring) || (s_funcs[_info]._id == FunctionId.Len))
                            {
                                if ((typeof(string) != (argumentValues[i].GetType())) && (typeof(SqlString) != (argumentValues[i].GetType())))
                                {
                                    throw ExprException.ArgumentType(s_funcs[_info]._name, i + 1, s_funcs[_info]._parameters[i]);
                                }
                            }
                            else
                            {
                                throw ExprException.ArgumentType(s_funcs[_info]._name, i + 1, s_funcs[_info]._parameters[i]);
                            }
                        }
                    }
                }
            }
            return(EvalFunction(s_funcs[_info]._id, argumentValues, row, version));
        }
示例#4
0
 internal override object Eval(DataRow row, DataRowVersion version)
 {
     object[] argumentValues = new object[this.argumentCount];
     if (funcs[this.info].id == FunctionId.Convert)
     {
         if (this.argumentCount != 2)
         {
             throw ExprException.FunctionArgumentCount(this.name);
         }
         argumentValues[0] = this.arguments[0].Eval(row, version);
         argumentValues[1] = this.GetDataType(this.arguments[1]);
     }
     else if (funcs[this.info].id != FunctionId.Iif)
     {
         for (int i = 0; i < this.argumentCount; i++)
         {
             argumentValues[i] = this.arguments[i].Eval(row, version);
             if (funcs[this.info].IsValidateArguments)
             {
                 if ((argumentValues[i] == DBNull.Value) || (typeof(object) == funcs[this.info].parameters[i]))
                 {
                     return(DBNull.Value);
                 }
                 if (argumentValues[i].GetType() != funcs[this.info].parameters[i])
                 {
                     if ((funcs[this.info].parameters[i] == typeof(int)) && ExpressionNode.IsInteger(DataStorage.GetStorageType(argumentValues[i].GetType())))
                     {
                         argumentValues[i] = Convert.ToInt32(argumentValues[i], base.FormatProvider);
                     }
                     else
                     {
                         if (((funcs[this.info].id != FunctionId.Trim) && (funcs[this.info].id != FunctionId.Substring)) && (funcs[this.info].id != FunctionId.Len))
                         {
                             throw ExprException.ArgumentType(funcs[this.info].name, i + 1, funcs[this.info].parameters[i]);
                         }
                         if ((typeof(string) != argumentValues[i].GetType()) && (typeof(SqlString) != argumentValues[i].GetType()))
                         {
                             throw ExprException.ArgumentType(funcs[this.info].name, i + 1, funcs[this.info].parameters[i]);
                         }
                     }
                 }
             }
         }
     }
     return(this.EvalFunction(funcs[this.info].id, argumentValues, row, version));
 }
示例#5
0
        private object EvalFunction(FunctionId id, object[] argumentValues, DataRow row, DataRowVersion version)
        {
            StorageType storageType;

            switch (id)
            {
            case FunctionId.Abs:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));

                storageType = DataStorage.GetStorageType(argumentValues[0].GetType());
                if (ExpressionNode.IsInteger(storageType))
                {
                    return(Math.Abs((long)argumentValues[0]));
                }
                if (ExpressionNode.IsNumeric(storageType))
                {
                    return(Math.Abs((double)argumentValues[0]));
                }

                throw ExprException.ArgumentTypeInteger(s_funcs[_info]._name, 1);

            case FunctionId.cBool:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));

                storageType = DataStorage.GetStorageType(argumentValues[0].GetType());
                switch (storageType)
                {
                case StorageType.Boolean:
                    return((bool)argumentValues[0]);

                case StorageType.Int32:
                    return((int)argumentValues[0] != 0);

                case StorageType.Double:
                    return((double)argumentValues[0] != 0.0);

                case StorageType.String:
                    return(bool.Parse((string)argumentValues[0]));

                default:
                    throw ExprException.DatatypeConvertion(argumentValues[0].GetType(), typeof(bool));
                }

            case FunctionId.cInt:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));
                return(Convert.ToInt32(argumentValues[0], FormatProvider));

            case FunctionId.cDate:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));
                return(Convert.ToDateTime(argumentValues[0], FormatProvider));

            case FunctionId.cDbl:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));
                return(Convert.ToDouble(argumentValues[0], FormatProvider));

            case FunctionId.cStr:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));
                return(Convert.ToString(argumentValues[0], FormatProvider));

            case FunctionId.Charindex:
                Debug.Assert(_argumentCount == 2, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));

                Debug.Assert(argumentValues[0] is string, "Invalid argument type for " + s_funcs[_info]._name);
                Debug.Assert(argumentValues[1] is string, "Invalid argument type for " + s_funcs[_info]._name);

                if (DataStorage.IsObjectNull(argumentValues[0]) || DataStorage.IsObjectNull(argumentValues[1]))
                {
                    return(DBNull.Value);
                }

                if (argumentValues[0] is SqlString)
                {
                    argumentValues[0] = ((SqlString)argumentValues[0]).Value;
                }

                if (argumentValues[1] is SqlString)
                {
                    argumentValues[1] = ((SqlString)argumentValues[1]).Value;
                }

                return(((string)argumentValues[1]).IndexOf((string)argumentValues[0], StringComparison.Ordinal));

            case FunctionId.Iif:
                Debug.Assert(_argumentCount == 3, "Invalid argument argumentCount: " + _argumentCount.ToString(FormatProvider));

                object first = _arguments[0].Eval(row, version);

                if (DataExpression.ToBoolean(first) != false)
                {
                    return(_arguments[1].Eval(row, version));
                }
                else
                {
                    return(_arguments[2].Eval(row, version));
                }

            case FunctionId.In:
                // we never evaluate IN directly: IN as a binary operator, so evaluation of this should be in
                // BinaryNode class
                throw ExprException.NYI(s_funcs[_info]._name);

            case FunctionId.IsNull:
                Debug.Assert(_argumentCount == 2, "Invalid argument argumentCount: ");

                if (DataStorage.IsObjectNull(argumentValues[0]))
                {
                    return(argumentValues[1]);
                }
                else
                {
                    return(argumentValues[0]);
                }

            case FunctionId.Len:
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));
                Debug.Assert((argumentValues[0] is string) || (argumentValues[0] is SqlString), "Invalid argument type for " + s_funcs[_info]._name);

                if (argumentValues[0] is SqlString)
                {
                    if (((SqlString)argumentValues[0]).IsNull)
                    {
                        return(DBNull.Value);
                    }
                    else
                    {
                        argumentValues[0] = ((SqlString)argumentValues[0]).Value;
                    }
                }

                return(((string)argumentValues[0]).Length);


            case FunctionId.Substring:
                Debug.Assert(_argumentCount == 3, "Invalid argument argumentCount: " + _argumentCount.ToString(FormatProvider));
                Debug.Assert((argumentValues[0] is string) || (argumentValues[0] is SqlString), "Invalid first argument " + argumentValues[0].GetType().FullName + " in " + s_funcs[_info]._name);
                Debug.Assert(argumentValues[1] is int, "Invalid second argument " + argumentValues[1].GetType().FullName + " in " + s_funcs[_info]._name);
                Debug.Assert(argumentValues[2] is int, "Invalid third argument " + argumentValues[2].GetType().FullName + " in " + s_funcs[_info]._name);

                // work around the differences in .NET and VBA implementation of the Substring function
                // 1. The <index> Argument is 0-based in .NET, and 1-based in VBA
                // 2. If the <Length> argument is longer then the string length .NET throws an ArgumentException
                //    but our users still want to get a result.

                int start = (int)argumentValues[1] - 1;

                int length = (int)argumentValues[2];

                if (start < 0)
                {
                    throw ExprException.FunctionArgumentOutOfRange("index", "Substring");
                }

                if (length < 0)
                {
                    throw ExprException.FunctionArgumentOutOfRange("length", "Substring");
                }

                if (length == 0)
                {
                    return(string.Empty);
                }

                if (argumentValues[0] is SqlString)
                {
                    argumentValues[0] = ((SqlString)argumentValues[0]).Value;
                }

                int src_length = ((string)argumentValues[0]).Length;

                if (start > src_length)
                {
                    return(DBNull.Value);
                }

                if (start + length > src_length)
                {
                    length = src_length - start;
                }

                return(((string)argumentValues[0]).Substring(start, length));

            case FunctionId.Trim:
            {
                Debug.Assert(_argumentCount == 1, "Invalid argument argumentCount for " + s_funcs[_info]._name + " : " + _argumentCount.ToString(FormatProvider));
                Debug.Assert((argumentValues[0] is string) || (argumentValues[0] is SqlString), "Invalid argument type for " + s_funcs[_info]._name);

                if (DataStorage.IsObjectNull(argumentValues[0]))
                {
                    return(DBNull.Value);
                }

                if (argumentValues[0] is SqlString)
                {
                    argumentValues[0] = ((SqlString)argumentValues[0]).Value;
                }

                return(((string)argumentValues[0]).Trim());
            }

            case FunctionId.Convert:
                if (_argumentCount != 2)
                {
                    throw ExprException.FunctionArgumentCount(_name);
                }

                if (argumentValues[0] == DBNull.Value)
                {
                    return(DBNull.Value);
                }

                Type        type   = (Type)argumentValues[1];
                StorageType mytype = DataStorage.GetStorageType(type);
                storageType = DataStorage.GetStorageType(argumentValues[0].GetType());

                if (mytype == StorageType.DateTimeOffset)
                {
                    if (storageType == StorageType.String)
                    {
                        return(SqlConvert.ConvertStringToDateTimeOffset((string)argumentValues[0], FormatProvider));
                    }
                }

                if (StorageType.Object != mytype)
                {
                    if ((mytype == StorageType.Guid) && (storageType == StorageType.String))
                    {
                        return(new Guid((string)argumentValues[0]));
                    }

                    if (ExpressionNode.IsFloatSql(storageType) && ExpressionNode.IsIntegerSql(mytype))
                    {
                        if (StorageType.Single == storageType)
                        {
                            return(SqlConvert.ChangeType2((float)SqlConvert.ChangeType2(argumentValues[0], StorageType.Single, typeof(float), FormatProvider), mytype, type, FormatProvider));
                        }
                        else if (StorageType.Double == storageType)
                        {
                            return(SqlConvert.ChangeType2((double)SqlConvert.ChangeType2(argumentValues[0], StorageType.Double, typeof(double), FormatProvider), mytype, type, FormatProvider));
                        }
                        else if (StorageType.Decimal == storageType)
                        {
                            return(SqlConvert.ChangeType2((decimal)SqlConvert.ChangeType2(argumentValues[0], StorageType.Decimal, typeof(decimal), FormatProvider), mytype, type, FormatProvider));
                        }
                    }

                    // The Convert function can be called lazily, outside of a previous Serialization Guard scope.
                    // If there was a type limiter scope on the stack at the time this Convert function was created,
                    // we must manually re-enter the Serialization Guard scope.

                    DeserializationToken deserializationToken = (_capturedLimiter != null) ? SerializationInfo.StartDeserialization() : default;
                    using (deserializationToken)
                    {
                        return(SqlConvert.ChangeType2(argumentValues[0], mytype, type, FormatProvider));
                    }
                }

                return(argumentValues[0]);

            case FunctionId.DateTimeOffset:
                if (argumentValues[0] == DBNull.Value || argumentValues[1] == DBNull.Value || argumentValues[2] == DBNull.Value)
                {
                    return(DBNull.Value);
                }
                switch (((DateTime)argumentValues[0]).Kind)
                {
                case DateTimeKind.Utc:
                    if ((int)argumentValues[1] != 0 && (int)argumentValues[2] != 0)
                    {
                        throw ExprException.MismatchKindandTimeSpan();
                    }
                    break;

                case DateTimeKind.Local:
                    if (DateTimeOffset.Now.Offset.Hours != (int)argumentValues[1] && DateTimeOffset.Now.Offset.Minutes != (int)argumentValues[2])
                    {
                        throw ExprException.MismatchKindandTimeSpan();
                    }
                    break;

                case DateTimeKind.Unspecified: break;
                }
                if ((int)argumentValues[1] < -14 || (int)argumentValues[1] > 14)
                {
                    throw ExprException.InvalidHoursArgument();
                }
                if ((int)argumentValues[2] < -59 || (int)argumentValues[2] > 59)
                {
                    throw ExprException.InvalidMinutesArgument();
                }
                // range should be within -14 hours and  +14 hours
                if ((int)argumentValues[1] == 14 && (int)argumentValues[2] > 0)
                {
                    throw ExprException.InvalidTimeZoneRange();
                }
                if ((int)argumentValues[1] == -14 && (int)argumentValues[2] < 0)
                {
                    throw ExprException.InvalidTimeZoneRange();
                }

                return(new DateTimeOffset((DateTime)argumentValues[0], new TimeSpan((int)argumentValues[1], (int)argumentValues[2], 0)));

            default:
                throw ExprException.UndefinedFunction(s_funcs[_info]._name);
            }
        }
        private object EvalFunction(FunctionId id, object[] argumentValues, DataRow row, DataRowVersion version)
        {
#if DEBUG
            if (CompModSwitches.FunctionNode.TraceVerbose)
            {
                Debug.WriteLine("calculate " + this.ToString());
            }
#endif

            switch (id)
            {
            case FunctionId.Abs:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());

                if (ExpressionNode.IsInteger(argumentValues[0].GetType()))
                {
                    return(Math.Abs((Int64)argumentValues[0]));
                }
                if (ExpressionNode.IsNumeric(argumentValues[0].GetType()))
                {
                    return(Math.Abs((double)argumentValues[0]));
                }

                throw ExprException.ArgumentTypeInteger(funcs[info].name, 1);

            case FunctionId.cBool:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());

                if (argumentValues[0] is bool)
                {
                    return((bool)argumentValues[0]);
                }

                if (argumentValues[0] is int)
                {
                    return((int)argumentValues[0] != 0);
                }

                if (argumentValues[0] is double)
                {
                    return((double)argumentValues[0] != 0.0);
                }

                if (argumentValues[0] is string)
                {
                    return(Boolean.Parse((string)argumentValues[0]));
                }

                throw ExprException.DatatypeConvertion(argumentValues[0].GetType(), typeof(bool));

            case FunctionId.cInt:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());
                return(Convert.ToInt32(argumentValues[0]));

            case FunctionId.cDate:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());
#if DEBUG
                if (CompModSwitches.FunctionNode.TraceVerbose)
                {
                    Debug.WriteLine("Convert " + Convert.ToString(argumentValues[0]) + " of " + argumentValues[0].GetType().Name + " to datetime");
                }
#endif
                return(Convert.ToDateTime(argumentValues[0]));

            case FunctionId.cDbl:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());
                return(Convert.ToDouble(argumentValues[0]));

            case FunctionId.cStr:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());
                return(Convert.ToString(argumentValues[0]));

            case FunctionId.Charindex:
                Debug.Assert(argumentCount == 2, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());

                Debug.Assert(argumentValues[0] is string, "Invalid argument type for " + funcs[info].name);
                Debug.Assert(argumentValues[1] is string, "Invalid argument type for " + funcs[info].name);

                if ((argumentValues[0] == DBNull.Value) || (argumentValues[1] == DBNull.Value))
                {
                    return(DBNull.Value);
                }

                return(((string)argumentValues[1]).IndexOf((string)argumentValues[0]));

            case FunctionId.Iif:
                Debug.Assert(argumentCount == 3, "Invalid argument argumentCount: " + argumentCount.ToString());

                object first = this.arguments[0].Eval(row, version);

                if (DataExpression.ToBoolean(first) != false)
                {
                    return(this.arguments[1].Eval(row, version));
                }
                else
                {
                    return(this.arguments[2].Eval(row, version));
                }

            case FunctionId.In:
                // we never evaluate IN directly: IN as a binary operator, so evaluation of this should be in
                // BinaryNode class
                throw ExprException.NYI(funcs[info].name);

            case FunctionId.IsNull:
                Debug.Assert(argumentCount == 2, "Invalid argument argumentCount: ");

                if ((argumentValues[0]) == DBNull.Value)
                {
                    return(argumentValues[1]);
                }
                else
                {
                    return(argumentValues[0]);
                }

            case FunctionId.Len:
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());
                Debug.Assert(argumentValues[0] is string, "Invalid argument type for " + funcs[info].name);

                return(((string)argumentValues[0]).Length);


            case FunctionId.Substring:
                Debug.Assert(argumentCount == 3, "Invalid argument argumentCount: " + argumentCount.ToString());
                Debug.Assert(argumentValues[0] is string, "Invalid first argument " + argumentValues[0].GetType().FullName + " in " + funcs[info].name);
                Debug.Assert(argumentValues[1] is int, "Invalid second argument " + argumentValues[1].GetType().FullName + " in " + funcs[info].name);
                Debug.Assert(argumentValues[2] is int, "Invalid third argument " + argumentValues[2].GetType().FullName + " in " + funcs[info].name);

                // work around the differences in COM+ and VBA implementation of the Substring function
                // 1. The <index> Argument is 0-based in COM+, and 1-based in VBA
                // 2. If the <Length> argument is longer then the string length COM+ throws an ArgumentException
                //    but our users still want to get a result.

                int start = (int)argumentValues[1] - 1;

                int length = (int)argumentValues[2];

                if (start < 0)
                {
                    throw ExprException.FunctionArgumentOutOfRange("index", "Substring");
                }

                if (length < 0)
                {
                    throw ExprException.FunctionArgumentOutOfRange("length", "Substring");
                }

                if (length == 0)
                {
                    return("");
                }

                int src_length = ((string)argumentValues[0]).Length;

                if (start > src_length)
                {
                    return(DBNull.Value);
                }

                if (start + length > src_length)
                {
                    length = src_length - start;
                }

                return(((string)argumentValues[0]).Substring(start, length));

            case FunctionId.Trim:
            {
                Debug.Assert(argumentCount == 1, "Invalid argument argumentCount for " + funcs[info].name + " : " + argumentCount.ToString());
                Debug.Assert(argumentValues[0] is string, "Invalid argument type for " + funcs[info].name);

                if (argumentValues[0] == DBNull.Value)
                {
                    return(DBNull.Value);
                }

                return(((string)argumentValues[0]).Trim());
            }

            case FunctionId.Convert:
                if (argumentCount != 2)
                {
                    throw ExprException.FunctionArgumentCount(this.name);
                }

                if (argumentValues[0] == DBNull.Value)
                {
                    return(DBNull.Value);
                }

                Type type   = (Type)argumentValues[1];
                Type _oType = argumentValues[0].GetType();

                if (type != typeof(object))
                {
                    if ((type == typeof(Guid)) && (_oType == typeof(String)))
                    {
                        return(new Guid((string)argumentValues[0]));
                    }

                    if (ExpressionNode.IsFloat(_oType) && ExpressionNode.IsInteger(type))
                    {
                        if (_oType == typeof(Single))
                        {
                            return(Convert.ChangeType((Single)Convert.ChangeType(argumentValues[0], typeof(Single)), type));
                        }
                        else if (_oType == typeof(double))
                        {
                            return(Convert.ChangeType((double)Convert.ChangeType(argumentValues[0], typeof(double)), type));
                        }
                        else
                        {
                            return(Convert.ChangeType((decimal)Convert.ChangeType(argumentValues[0], typeof(decimal)), type));
                        }
                    }
                    return(Convert.ChangeType(argumentValues[0], type));
                }
                return(argumentValues[0]);

            default:
                throw ExprException.UndefinedFunction(funcs[info].name);
            }
        }
        internal override object Eval(DataRow row, DataRowVersion version)
        {
            Debug.Assert(info < funcs.Length && info >= 0, "Invalid function info.");

            object[] argumentValues = new object[this.argumentCount];

            Debug.Assert(this.argumentCount == funcs[info].argumentCount || funcs[info].IsVariantArgumentList, "Invalid argument argumentCount.");

            // special case of the Convert function
            if (funcs[info].id == FunctionId.Convert)
            {
                if (argumentCount != 2)
                {
                    throw ExprException.FunctionArgumentCount(this.name);
                }

                argumentValues[0] = this.arguments[0].Eval(row, version);
                argumentValues[1] = GetDataType(this.arguments[1]);
            }
            else
            {
                for (int i = 0; i < this.argumentCount; i++)
                {
                    argumentValues[i] = this.arguments[i].Eval(row, version);

                    if (funcs[info].IsValidateArguments)
                    {
#if DEBUG
                        if (CompModSwitches.FunctionNode.TraceVerbose)
                        {
                            Debug.WriteLine("Validate arguments for " + funcs[info].name);
                        }
#endif
                        if ((argumentValues[i] == DBNull.Value) || (typeof(object) == funcs[info].parameters[i]))
                        {
#if DEBUG
                            if (CompModSwitches.FunctionNode.TraceVerbose)
                            {
                                Debug.WriteLine("argument " + (i + 1).ToString() + " is empty");
                            }
#endif

                            // currently all supported functions with IsValidateArguments set to true
                            // NOTE: for IIF and ISNULL IsValidateArguments set to false
                            return(DBNull.Value);
                        }

                        if (argumentValues[i].GetType() != funcs[info].parameters[i])
                        {
#if DEBUG
                            if (CompModSwitches.FunctionNode.TraceVerbose)
                            {
                                Debug.WriteLine("change argumnet " + argumentValues[i].ToString() + " to " + funcs[info].parameters[i].ToString());
                            }
#endif
                            // We are allowing conversions in one very specific case: int, int64,...'nice' numeric to numeric..

                            if (funcs[info].parameters[i] == typeof(int) && ExpressionNode.IsInteger(argumentValues[i].GetType()))
                            {
                                argumentValues[i] = Convert.ToInt32(argumentValues[i]);
                            }
                            else
                            {
                                throw ExprException.ArgumentType(funcs[info].name, i + 1, funcs[info].parameters[i]);
                            }
                        }
                    }
                }
            }
            return(EvalFunction(funcs[info].id, argumentValues, row, version));
        }
示例#8
0
        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);
        }
示例#9
0
        internal long Compare(object vLeft, object vRight, Type type, int op)
        {
            //Debug.WriteLine("Compare '" + vLeft.ToString() + "' to '" + vRight.ToString() + "' , type " + type.ToString());
            long result       = 0;
            bool typeMismatch = false;

            try {
                if (type == typeof(UInt64))
                {
                    Decimal dec = Convert.ToDecimal(vLeft) - Convert.ToDecimal(vRight);
                    if (dec == 0)
                    {
                        result = 0;
                    }
                    else if (dec > 0)
                    {
                        result = 1;
                    }
                    else
                    {
                        result = -1;
                    }
                }
                else if (type == typeof(char))
                {
                    result = Convert.ToInt32(vLeft) - Convert.ToInt32(Convert.ToChar(vRight));
                }
                else if (ExpressionNode.IsInteger(type))
                {
                    Int64 a = Convert.ToInt64(vLeft);
                    Int64 b = Convert.ToInt64(vRight);
                    checked { result = a - b; }
                }
                else if (type == typeof(Decimal))
                {
                    Decimal a = Convert.ToDecimal(vLeft);
                    Decimal b = Convert.ToDecimal(vRight);
                    result = Decimal.Compare(a, b);
                }
                else if (type == typeof(double))
                {
                    Double a = Convert.ToDouble(vLeft);
                    Double b = Convert.ToDouble(vRight);
                    double d;
                    checked { d = a - b; }
                    if (d == 0)
                    {
                        result = 0;
                    }
                    else if (d > 0)
                    {
                        result = 1;
                    }
                    else
                    {
                        result = -1;
                    }
                }
                else if (type == typeof(Single))
                {
                    Single a = Convert.ToSingle(vLeft);
                    Single b = Convert.ToSingle(vRight);
                    Single d;
                    checked { d = a - b; }
                    if (d == 0)
                    {
                        result = 0;
                    }
                    else if (d > 0)
                    {
                        result = 1;
                    }
                    else
                    {
                        result = -1;
                    }
                }
                else if (type == typeof(DateTime))
                {
                    //Debug.WriteLine("Compare '" + vLeft.ToString() + "' to '" + vRight.ToString() + "'");
                    result = DateTime.Compare(Convert.ToDateTime(vLeft), Convert.ToDateTime(vRight));
                    //Debug.WriteLine("result = " + result.ToString());
                }
                else if (type == typeof(string))
                {
                    //Debug.WriteLine("Compare '" + vLeft.ToString() + "' to '" + vRight.ToString() + "'");
                    result = table.Compare(Convert.ToString(vLeft), Convert.ToString(vRight), CompareOptions.None);
                    //Debug.WriteLine("result = " + result.ToString());
                }
                else if (type == typeof(Guid))
                {
                    //Debug.WriteLine("Compare '" + vLeft.ToString() + "' to '" + vRight.ToString() + "'");
                    result = ((Guid)vLeft).CompareTo((Guid)vRight);
                    //Debug.WriteLine("result = " + result.ToString());
                }
                else if (type == typeof(bool))
                {
                    if (op == Operators.EqualTo || op == Operators.NotEqual)
                    {
                        object bLeft  = DataExpression.ToBoolean(vLeft);
                        object bRight = DataExpression.ToBoolean(vRight);
                        result = Convert.ToInt32(bLeft) - Convert.ToInt32(bRight);
                    }
                    else
                    {
                        typeMismatch = true;
                    }
                }
                else
                {
                    typeMismatch = true;
                }
            }
            catch {
                SetTypeMismatchError(op, vLeft.GetType(), vRight.GetType());
            }

            if (typeMismatch)
            {
                SetTypeMismatchError(op, vLeft.GetType(), vRight.GetType());
            }

            return(result);
        }
示例#10
0
        private object EvalFunction(FunctionId id, object[] argumentValues, DataRow row, DataRowVersion version)
        {
            StorageType type;

            switch (id)
            {
            case FunctionId.Charindex:
                if (!DataStorage.IsObjectNull(argumentValues[0]) && !DataStorage.IsObjectNull(argumentValues[1]))
                {
                    if (argumentValues[0] is SqlString)
                    {
                        SqlString str6 = (SqlString)argumentValues[0];
                        argumentValues[0] = str6.Value;
                    }
                    if (argumentValues[1] is SqlString)
                    {
                        SqlString str5 = (SqlString)argumentValues[1];
                        argumentValues[1] = str5.Value;
                    }
                    return(((string)argumentValues[1]).IndexOf((string)argumentValues[0], StringComparison.Ordinal));
                }
                return(DBNull.Value);

            case FunctionId.Len:
            {
                if (!(argumentValues[0] is SqlString))
                {
                    goto Label_02D4;
                }
                SqlString str4 = (SqlString)argumentValues[0];
                if (!str4.IsNull)
                {
                    SqlString str3 = (SqlString)argumentValues[0];
                    argumentValues[0] = str3.Value;
                    goto Label_02D4;
                }
                return(DBNull.Value);
            }

            case FunctionId.Substring:
            {
                int startIndex = ((int)argumentValues[1]) - 1;
                int length     = (int)argumentValues[2];
                if (startIndex < 0)
                {
                    throw ExprException.FunctionArgumentOutOfRange("index", "Substring");
                }
                if (length < 0)
                {
                    throw ExprException.FunctionArgumentOutOfRange("length", "Substring");
                }
                if (length == 0)
                {
                    return("");
                }
                if (argumentValues[0] is SqlString)
                {
                    SqlString str2 = (SqlString)argumentValues[0];
                    argumentValues[0] = str2.Value;
                }
                int num3 = ((string)argumentValues[0]).Length;
                if (startIndex > num3)
                {
                    return(DBNull.Value);
                }
                if ((startIndex + length) > num3)
                {
                    length = num3 - startIndex;
                }
                return(((string)argumentValues[0]).Substring(startIndex, length));
            }

            case FunctionId.IsNull:
                if (!DataStorage.IsObjectNull(argumentValues[0]))
                {
                    return(argumentValues[0]);
                }
                return(argumentValues[1]);

            case FunctionId.Iif:
                if (!DataExpression.ToBoolean(this.arguments[0].Eval(row, version)))
                {
                    return(this.arguments[2].Eval(row, version));
                }
                return(this.arguments[1].Eval(row, version));

            case FunctionId.Convert:
            {
                if (this.argumentCount != 2)
                {
                    throw ExprException.FunctionArgumentCount(this.name);
                }
                if (argumentValues[0] == DBNull.Value)
                {
                    return(DBNull.Value);
                }
                Type        dataType    = (Type)argumentValues[1];
                StorageType storageType = DataStorage.GetStorageType(dataType);
                type = DataStorage.GetStorageType(argumentValues[0].GetType());
                if ((storageType == StorageType.DateTimeOffset) && (type == StorageType.String))
                {
                    return(SqlConvert.ConvertStringToDateTimeOffset((string)argumentValues[0], base.FormatProvider));
                }
                if (StorageType.Object == storageType)
                {
                    return(argumentValues[0]);
                }
                if ((storageType == StorageType.Guid) && (type == StorageType.String))
                {
                    return(new Guid((string)argumentValues[0]));
                }
                if (ExpressionNode.IsFloatSql(type) && ExpressionNode.IsIntegerSql(storageType))
                {
                    if (StorageType.Single == type)
                    {
                        return(SqlConvert.ChangeType2((float)SqlConvert.ChangeType2(argumentValues[0], StorageType.Single, typeof(float), base.FormatProvider), storageType, dataType, base.FormatProvider));
                    }
                    if (StorageType.Double == type)
                    {
                        return(SqlConvert.ChangeType2((double)SqlConvert.ChangeType2(argumentValues[0], StorageType.Double, typeof(double), base.FormatProvider), storageType, dataType, base.FormatProvider));
                    }
                    if (StorageType.Decimal == type)
                    {
                        return(SqlConvert.ChangeType2((decimal)SqlConvert.ChangeType2(argumentValues[0], StorageType.Decimal, typeof(decimal), base.FormatProvider), storageType, dataType, base.FormatProvider));
                    }
                }
                return(SqlConvert.ChangeType2(argumentValues[0], storageType, dataType, base.FormatProvider));
            }

            case FunctionId.cInt:
                return(Convert.ToInt32(argumentValues[0], base.FormatProvider));

            case FunctionId.cBool:
            {
                StorageType type4 = DataStorage.GetStorageType(argumentValues[0].GetType());
                if (type4 > StorageType.Int32)
                {
                    switch (type4)
                    {
                    case StorageType.Double:
                        return(!(((double)argumentValues[0]) == 0.0));

                    case StorageType.String:
                        return(bool.Parse((string)argumentValues[0]));
                    }
                    break;
                }
                switch (type4)
                {
                case StorageType.Boolean:
                    return((bool)argumentValues[0]);

                case StorageType.Int32:
                    return(((int)argumentValues[0]) != 0);
                }
                break;
            }

            case FunctionId.cDate:
                return(Convert.ToDateTime(argumentValues[0], base.FormatProvider));

            case FunctionId.cDbl:
                return(Convert.ToDouble(argumentValues[0], base.FormatProvider));

            case FunctionId.cStr:
                return(Convert.ToString(argumentValues[0], base.FormatProvider));

            case FunctionId.Abs:
                type = DataStorage.GetStorageType(argumentValues[0].GetType());
                if (!ExpressionNode.IsInteger(type))
                {
                    if (!ExpressionNode.IsNumeric(type))
                    {
                        throw ExprException.ArgumentTypeInteger(funcs[this.info].name, 1);
                    }
                    return(Math.Abs((double)argumentValues[0]));
                }
                return(Math.Abs((long)argumentValues[0]));

            case FunctionId.In:
                throw ExprException.NYI(funcs[this.info].name);

            case FunctionId.Trim:
                if (!DataStorage.IsObjectNull(argumentValues[0]))
                {
                    if (argumentValues[0] is SqlString)
                    {
                        SqlString str = (SqlString)argumentValues[0];
                        argumentValues[0] = str.Value;
                    }
                    return(((string)argumentValues[0]).Trim());
                }
                return(DBNull.Value);

            case FunctionId.DateTimeOffset:
                if (((argumentValues[0] != DBNull.Value) && (argumentValues[1] != DBNull.Value)) && (argumentValues[2] != DBNull.Value))
                {
                    DateTime time = (DateTime)argumentValues[0];
                    switch (time.Kind)
                    {
                    case DateTimeKind.Utc:
                        if ((((int)argumentValues[1]) != 0) && (((int)argumentValues[2]) != 0))
                        {
                            throw ExprException.MismatchKindandTimeSpan();
                        }
                        break;

                    case DateTimeKind.Local:
                        if ((DateTimeOffset.Now.Offset.Hours != ((int)argumentValues[1])) && (DateTimeOffset.Now.Offset.Minutes != ((int)argumentValues[2])))
                        {
                            throw ExprException.MismatchKindandTimeSpan();
                        }
                        break;
                    }
                    if ((((int)argumentValues[1]) < -14) || (((int)argumentValues[1]) > 14))
                    {
                        throw ExprException.InvalidHoursArgument();
                    }
                    if ((((int)argumentValues[2]) < -59) || (((int)argumentValues[2]) > 0x3b))
                    {
                        throw ExprException.InvalidMinutesArgument();
                    }
                    if ((((int)argumentValues[1]) == 14) && (((int)argumentValues[2]) > 0))
                    {
                        throw ExprException.InvalidTimeZoneRange();
                    }
                    if ((((int)argumentValues[1]) == -14) && (((int)argumentValues[2]) < 0))
                    {
                        throw ExprException.InvalidTimeZoneRange();
                    }
                    return(new DateTimeOffset((DateTime)argumentValues[0], new TimeSpan((int)argumentValues[1], (int)argumentValues[2], 0)));
                }
                return(DBNull.Value);

            default:
                throw ExprException.UndefinedFunction(funcs[this.info].name);
            }
            throw ExprException.DatatypeConvertion(argumentValues[0].GetType(), typeof(bool));
Label_02D4:
            return(((string)argumentValues[0]).Length);
        }