System.Data.FunctionNode.EvalFunction C# (CSharp) Method

EvalFunction() private method

private EvalFunction ( FunctionId id, object argumentValues, DataRow row, DataRowVersion version ) : object
id FunctionId
argumentValues object
row DataRow
version DataRowVersion
return object
        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);
                            }
                            return SqlConvert.ChangeType2(argumentValues[0], mytype, type, FormatProvider);
                        }

                        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);
            }
        }