FirebirdSQL / NETProvider

Firebird ADO.NET Data Provider
https://www.firebirdsql.org/en/net-provider/
Other
159 stars 65 forks source link

DbDataReader.GetIntXX throws "Unable to cast object of type 'System.Numerics.BigInteger' to type 'System.IConvertible'" #1073

Closed hazzik closed 1 year ago

hazzik commented 2 years ago

When upgrading from Firebird3 to Firebird4 I've found that in certain scenarios the DbDataReader's GetByte, GetInt16, GetInt32, GetInt64 throw "Unable to cast object of type 'System.Numerics.BigInteger' to type 'System.IConvertible'" when resulting column type is INT128.

The reason being that, in our case, the definition of SUMs return type has changed from

Result typeReturns a result of the same numeric data type as the input expression.

To:

The result type of SUM depends on the input type:

input type
result type
FLOAT, DOUBLE PRECISION DOUBLE PRECISION
SMALLINT, INTEGER BIGINT
BIGINT, INT128 INT128
DECIMAL/NUMERIC(p, n) with p < 10 DECIMAL/NUMERIC(18, n)
DECIMAL/NUMERIC(p, n) with p >= 10 DECIMAL/NUMERIC(38, n)

Expected behavior: exception should be thrown only when value is too big to fit into the requested type.

The culprit is Convert.ToXXX in this (and similar) code block:

https://github.com/FirebirdSQL/NETProvider/blob/ebd58c427de8fcdc3c5b08541a450dc09831e023/src/FirebirdSql.Data.FirebirdClient/Common/DbValue.cs#L200-L203

Code to reproduce:

var cmd = connection.CreateCommand();
cmd.CommandText = "select sum(cast(1 as bigint)) from RDB$DATABASE";
var r = cmd.ExecuteReader();
r.Read();
var v = r.GetInt64(0);

Full stack trace:

System.InvalidCastException : Unable to cast object of type 'System.Numerics.BigInteger' to type 'System.IConvertible'.
   at System.Convert.ToInt64(Object value, IFormatProvider provider)
   at FirebirdSql.Data.Common.DbValue.GetInt64()
   at FirebirdSql.Data.FirebirdClient.FbDataReader.GetInt64(Int32 i)
cincuranet commented 1 year ago

Thanks. Good catch. The fix will land momentarily.

cincuranet commented 1 year ago

Fixed via 2197f7a1.