internal override void Bind(DataTable table, ArrayList list) { this.Check(); // special case for the Convert function bind only the first argument: // the second argument should be a COM+ data Type stored as a name node, replace it with constant. if (funcs[info].id == FunctionId.Convert) { if (argumentCount != 2) { throw ExprException.FunctionArgumentCount(this.name); } arguments[0].Bind(table, list); if (arguments[1].GetType() == typeof(NameNode)) { NameNode type = (NameNode)arguments[1]; arguments[1] = new ConstNode(ValueType.Str, type.name); } arguments[1].Bind(table, list); } else { for (int i = 0; i < argumentCount; i++) { arguments[i].Bind(table, list); } } }
internal override void Bind(DataTable table, List <DataColumn> list) { BindTable(table); Check(); // special case for the Convert function bind only the first argument: // the second argument should be a Type stored as a name node, replace it with constant. if (s_funcs[_info]._id == FunctionId.Convert) { if (_argumentCount != 2) { throw ExprException.FunctionArgumentCount(_name); } _arguments[0].Bind(table, list); if (_arguments[1].GetType() == typeof(NameNode)) { NameNode type = (NameNode)_arguments[1]; _arguments[1] = new ConstNode(table, ValueType.Str, type._name); } _arguments[1].Bind(table, list); } else { for (int i = 0; i < _argumentCount; i++) { _arguments[i].Bind(table, list); } } }
internal override void Bind(DataTable table, List <DataColumn> list) { base.BindTable(table); this.Check(); if (funcs[this.info].id == FunctionId.Convert) { if (this.argumentCount != 2) { throw ExprException.FunctionArgumentCount(this.name); } this.arguments[0].Bind(table, list); if (this.arguments[1].GetType() == typeof(NameNode)) { NameNode node = (NameNode)this.arguments[1]; this.arguments[1] = new ConstNode(table, System.Data.ValueType.Str, node.name); } this.arguments[1].Bind(table, list); } else { for (int i = 0; i < this.argumentCount; i++) { this.arguments[i].Bind(table, list); } } }
internal void Check() { Function f = s_funcs[_info]; if (_info < 0) { throw ExprException.UndefinedFunction(_name); } if (s_funcs[_info]._isVariantArgumentList) { // for finctions with variabls argument list argumentCount is a minimal number of arguments if (_argumentCount < s_funcs[_info]._argumentCount) { // Special case for the IN operator if (s_funcs[_info]._id == FunctionId.In) { throw ExprException.InWithoutList(); } throw ExprException.FunctionArgumentCount(_name); } } else { if (_argumentCount != s_funcs[_info]._argumentCount) { throw ExprException.FunctionArgumentCount(_name); } } }
internal void Check() { Function f = funcs[info]; if (this.info < 0) { throw ExprException.UndefinedFunction(this.name); } if (funcs[info].IsVariantArgumentList) { // for finctions with variabls argument list argumentCount is a minimal number of arguments if (argumentCount < funcs[info].argumentCount) { // Special case for the IN operator if (funcs[this.info].id == FunctionId.In) { throw ExprException.InWithoutList(); } throw ExprException.FunctionArgumentCount(this.name); } } else { if (argumentCount != funcs[info].argumentCount) { throw ExprException.FunctionArgumentCount(this.name); } } }
internal virtual void AddArgument(ExpressionNode argument) { #if DEBUG if (CompModSwitches.FunctionNode.TraceVerbose) { Debug.WriteLine("Add argument " + argument.ToString()); } #endif Debug.Assert(info >= 0, String.Format(Res.GetString(Res.Expr_UndefinedFunction), this.name)); if (!funcs[info].IsVariantArgumentList && argumentCount >= funcs[info].argumentCount) { throw ExprException.FunctionArgumentCount(this.name); } if (arguments == null) { arguments = new ExpressionNode[initialCapacity]; } else if (argumentCount == arguments.Length) { ExpressionNode[] bigger = new ExpressionNode[argumentCount * 2]; System.Array.Copy(arguments, 0, bigger, 0, argumentCount); arguments = bigger; } arguments[argumentCount++] = argument; #if DEBUG if (CompModSwitches.FunctionNode.TraceVerbose) { Debug.WriteLine("Append argument " + argument.ToString() + " to function " + funcs[info].name); } #endif }
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)); }
internal override void Bind(DataTable table, List <DataColumn> list) { BindTable(table); Check(); // special case for the Convert function bind only the first argument: // the second argument should be a Type stored as a name node, replace it with constant. if (s_funcs[_info]._id == FunctionId.Convert) { if (_argumentCount != 2) { throw ExprException.FunctionArgumentCount(_name); } _arguments ![0].Bind(table, list);
internal virtual void Check() { #if DEBUG if (CompModSwitches.FunctionNode.TraceVerbose) { Debug.WriteLine("Check function: " + this.name); } #endif Function f = funcs[info]; #if DEBUG if (CompModSwitches.FunctionNode.TraceVerbose) { Debug.WriteLine("id = " + ((int)f.id).ToString()); } if (CompModSwitches.FunctionNode.TraceVerbose) { Debug.WriteLine(", arguments = " + this.argumentCount.ToString()); } #endif if (this.info < 0) { throw ExprException.UndefinedFunction(this.name); } if (funcs[info].IsVariantArgumentList) { // for finctions with variabls argument list argumentCount is a minimal number of arguments if (argumentCount < funcs[info].argumentCount) { // Special case for the IN operator if (funcs[this.info].id == FunctionId.In) { throw ExprException.InWithoutList(); } throw ExprException.FunctionArgumentCount(this.name); } } else { if (argumentCount != funcs[info].argumentCount) { throw ExprException.FunctionArgumentCount(this.name); } } }
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)); }
internal void AddArgument(ExpressionNode argument) { if (!funcs[this.info].IsVariantArgumentList && (this.argumentCount >= funcs[this.info].argumentCount)) { throw ExprException.FunctionArgumentCount(this.name); } if (this.arguments == null) { this.arguments = new ExpressionNode[1]; } else if (this.argumentCount == this.arguments.Length) { ExpressionNode[] destinationArray = new ExpressionNode[this.argumentCount * 2]; Array.Copy(this.arguments, 0, destinationArray, 0, this.argumentCount); this.arguments = destinationArray; } this.arguments[this.argumentCount++] = argument; }
internal void AddArgument(ExpressionNode argument) { if (!s_funcs[_info]._isVariantArgumentList && _argumentCount >= s_funcs[_info]._argumentCount) { throw ExprException.FunctionArgumentCount(_name); } if (_arguments == null) { _arguments = new ExpressionNode[initialCapacity]; } else if (_argumentCount == _arguments.Length) { ExpressionNode[] bigger = new ExpressionNode[_argumentCount * 2]; Array.Copy(_arguments, bigger, _argumentCount); _arguments = bigger; } _arguments[_argumentCount++] = argument; }
internal void AddArgument(ExpressionNode argument) { if (!funcs[info].IsVariantArgumentList && argumentCount >= funcs[info].argumentCount) { throw ExprException.FunctionArgumentCount(this.name); } if (arguments == null) { arguments = new ExpressionNode[initialCapacity]; } else if (argumentCount == arguments.Length) { ExpressionNode[] bigger = new ExpressionNode[argumentCount * 2]; System.Array.Copy(arguments, 0, bigger, 0, argumentCount); arguments = bigger; } arguments[argumentCount++] = argument; }
internal void Check() { Function function1 = funcs[this.info]; if (this.info < 0) { throw ExprException.UndefinedFunction(this.name); } if (funcs[this.info].IsVariantArgumentList) { if (this.argumentCount < funcs[this.info].argumentCount) { if (funcs[this.info].id == FunctionId.In) { throw ExprException.InWithoutList(); } throw ExprException.FunctionArgumentCount(this.name); } } else if (this.argumentCount != funcs[this.info].argumentCount) { throw ExprException.FunctionArgumentCount(this.name); } }
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); } }
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)); }
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); } }
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); }