dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.66k stars 4.58k forks source link

[System.Data.Odbc] GetSchemaTable fails with OverflowException for x64 ODBC driver #40654

Open MaceWindu opened 3 years ago

MaceWindu commented 3 years ago

Description

Calling OdbcDataReader.GetSchemaTable for reader that contains blob column fails with OverflowException in 64-bit process.

Used driver: "HDBODBC" (SAP HANA ODBC driver) Column types: BLOB, CLOB, NCLOB, TEXT

Configuration

OS: Windows Bitness: 64-bit process Framework: any

Regression?

Not regression, but bug. Also fails for .net framework.

Other information

System.OverflowException
  HResult=0x80131516
  Message=Arithmetic operation resulted in an overflow.
  Source=System.Data.Odbc
  StackTrace:
   at System.Data.Odbc.SQLLEN.op_Implicit(SQLLEN value)

image image

ghost commented 3 years ago

Tagging subscribers to this area: @roji, @ajcvickers See info in area-owners.md if you want to be subscribed.

roji commented 3 years ago

@MaceWindu thanks for filing this. The team is now busy with stabilizing .NET 5.0 - we are unlikely to get around to this issue before the release. We'll definitely take a look at this at that point.

I'm completely unfamiliar with SAP HANA ODBC driver. To help us reproduce and effectively fix this, is there any way to submit a code sample that reproduces the error? If not, is it possible to reproduce this with another, more accessible ODBC driver (e.g. for SQL Server)?

bucweat commented 10 months ago

Hi,

Seeing similar issue with DuckDB.

Code reference for code mentioned below: https://github.com/dotnet/runtime/blob/a2818c5728833ffc1988eb24b6648dc09554d19d/src/libraries/System.Data.Odbc/src/System/Data/Odbc/OdbcDataReader.cs#L2049

BTW I'm actually running .Net framework 4.8.1. The code is slightly different (from debugging symbols):

array[i].scale = (byte)(int)GetColAttribute(i, (ODBC32.SQL_DESC)5, ODBC32.SQL_COLUMN.SCALE, ODBC32.HANDLER.IGNORE);

When the driver is setting SQL_COLUMN_SCALE DuckDB is passing a Int32 value of -1. The System.Data.Odbc.SQLLEN _value returned from GetColAttribute() is 0x00000000ffffffff. There is a (byte)(int) cast before setting array[i].scale, but at least in my case that cast is not working and results in System.OverflowException.

I've yet to find a definitive source for what SQL_COLUMN_SCALE should be, however, I do believe that DuckDB should not be returning -1 given it is going into a variable of type byte.

meiaestro commented 3 months ago

We are getting the same error when trying to get column schema information for a SAP HANA database table:

Stacktrace: at System.IntPtr.ToInt32() at System.Data.Odbc.SQLLEN.op_Implicit(SQLLEN value) at System.Data.Odbc.OdbcDataReader.BuildMetaDataInfo() at System.Data.Odbc.OdbcDataReader.GetSchemaTable() at System.Data.Common.DbDataReaderExtensions.GetColumnSchemaCompatibility(DbDataReader reader) at System.Data.Common.DbDataReader.GetColumnSchemaAsync(CancellationToken cancellationToken) --- End of stack trace from previous location ---

It appears that the column causing the overflow exception is of type NCLOB with length int32.max = 2147483647.

For us a working workaround is to avoid 'GetColumnSchemaAsync' and calling 'GetName' and 'GetFieldType' for every column instead.