Describe the bug
If you use Dolphin ODBC to access a DB table that uses varchar(max)or varbinary(max) you'll get a walkback as Dolphin is trying to copy the entry's column data from a 0 length ByteArray.
To Reproduce
Steps to reproduce the behaviour:
Open a Dolphin ODBC connection to a database that has a table that has varbinary(max) and/or varchar(max) columns.
Try and retrieve data from the column(s) in that table and get a walkback like the following:
2024-05-26T21:27:08.7755494+01:00: Unhandled exception - a BoundsError('Index 2274981 is out of bounds')
ByteArray(Object)>>errorSubscriptBounds:
ByteArray(Object)>>_primitiveError:at:
ByteArray(Object)>>basicAt:
ByteArray>>replaceBytesOf:from:to:startingAt:
ByteArray>>replaceFrom:to:with:startingAt:
ByteArray(ArrayedCollection)>>copyFrom:to:
DBField>>getByteArray
DBField>>value
[] in DBRowBuffer>>objects
[] in SequenceableCollection>>collect:
Array(SequenceableCollection)>>uncheckedFrom:to:keysAndValuesDo:
Array(SequenceableCollection)>>keysAndValuesDo:
Array(SequenceableCollection)>>collect:
DBBoundBuffer(DBRowBuffer)>>objects
DBRow>>initializeFromBuffer:
DBRow class>>fromBuffer:
DBBoundBuffer(DBRowBuffer)>>asObject
DBForwardOnlyResultSet(DBResultSet)>>from:keysAndValuesDo:
DBForwardOnlyResultSet(DBResultSet)>>keysAndValuesDo:
DBForwardOnlyResultSet(SequenceableCollection)>>do:
DBForwardOnlyResultSet(DBResultSet)>>collect:
OdbcDbDataService>>collectResultsFrom:for:using:
[] in OdbcDbDataService(DbDataService)>>getEntitiesFromDb:for:creator:
Expected behaviour
I would expect the data to be successfully copied as it is for varchar(n) and/or varbinary(n) columns.
Screenshots
The problem (IMHO) is that in DBField>>initializeForColumn: the column attributes for the varbinary(max) column are as follows:
So a 0 length ByteArray is allocated to hold the data when it is fetched from the table. As the DB reports the length of that particular entry as being 2274981 bytes you get the walkback when DBField>>getByteArray is called .
I don't know an awful lot about the inner details of SQL/ODBC but my assumption is that the 0 length for the SQL_VARBINARY attribute means max i.e. up to 2GB.
Please complete the following information):
OS: Windows 10
Dolphin: v7.1.24
Additional context
Given that none of my uses need more than around 4MB per varbinary/varchar entries I made it so that a 16MB buffer is allocated for varbinary(max) and varchar(max) columns, but all that has done is to "kick the can down the road" for a more general solution, given that these columns can in theory hold 2GB per entry.
I made the following changes to my Dolphin core image to hack me past the problem:
Describe the bug If you use Dolphin ODBC to access a DB table that uses varchar(max) or varbinary(max) you'll get a walkback as Dolphin is trying to copy the entry's column data from a 0 length ByteArray.
To Reproduce Steps to reproduce the behaviour:
2024-05-26T21:27:08.7755494+01:00: Unhandled exception - a BoundsError('Index 2274981 is out of bounds')
ByteArray(Object)>>errorSubscriptBounds: ByteArray(Object)>>_primitiveError:at: ByteArray(Object)>>basicAt: ByteArray>>replaceBytesOf:from:to:startingAt: ByteArray>>replaceFrom:to:with:startingAt: ByteArray(ArrayedCollection)>>copyFrom:to: DBField>>getByteArray DBField>>value [] in DBRowBuffer>>objects [] in SequenceableCollection>>collect: Array(SequenceableCollection)>>uncheckedFrom:to:keysAndValuesDo: Array(SequenceableCollection)>>keysAndValuesDo: Array(SequenceableCollection)>>collect: DBBoundBuffer(DBRowBuffer)>>objects DBRow>>initializeFromBuffer: DBRow class>>fromBuffer: DBBoundBuffer(DBRowBuffer)>>asObject DBForwardOnlyResultSet(DBResultSet)>>from:keysAndValuesDo: DBForwardOnlyResultSet(DBResultSet)>>keysAndValuesDo: DBForwardOnlyResultSet(SequenceableCollection)>>do: DBForwardOnlyResultSet(DBResultSet)>>collect: OdbcDbDataService>>collectResultsFrom:for:using: [] in OdbcDbDataService(DbDataService)>>getEntitiesFromDb:for:creator:
Expected behaviour I would expect the data to be successfully copied as it is for varchar(n) and/or varbinary(n) columns.
Screenshots The problem (IMHO) is that in
DBField>>initializeForColumn:
the column attributes for the varbinary(max) column are as follows:So a 0 length ByteArray is allocated to hold the data when it is fetched from the table. As the DB reports the length of that particular entry as being 2274981 bytes you get the walkback when
DBField>>getByteArray
is called .I don't know an awful lot about the inner details of SQL/ODBC but my assumption is that the 0 length for the SQL_VARBINARY attribute means max i.e. up to 2GB.
Please complete the following information):
Additional context Given that none of my uses need more than around 4MB per varbinary/varchar entries I made it so that a 16MB buffer is allocated for varbinary(max) and varchar(max) columns, but all that has done is to "kick the can down the road" for a more general solution, given that these columns can in theory hold 2GB per entry.
I made the following changes to my Dolphin core image to hack me past the problem: