ibm_db_dbi.Binary returns a memoryview. Passing such values to Cursor.executemany:
- for a
BLOB column, stores the text of the object's repr (<memory at 0x7f...>) instead of the bytes, with no error;
- for
VARBINARY(n) and CHAR(n) FOR BIT DATA columns, fails with SQL0302N (value out of range), even when every value fits.
Single-row Cursor.execute with the same memoryview values stores the correct bytes. Passing bytes to executemany also works.
Reproduction
import ibm_db_dbi
conn = ibm_db_dbi.connect("DATABASE=...;HOSTNAME=...;PORT=...;PROTOCOL=TCPIP;UID=...;PWD=...;", "", "")
cur = conn.cursor()
cur.execute("CREATE TABLE PRB (ID INT, VB VARBINARY(8), BL BLOB(1K))")
rows = [(1, ibm_db_dbi.Binary(b"\x01\x02")), (2, ibm_db_dbi.Binary(b"\x03\x04"))]
cur.executemany("INSERT INTO PRB (ID, BL) VALUES (?, ?)", rows)
conn.commit()
cur.execute("SELECT ID, HEX(CAST(BL AS VARBINARY(64))) FROM PRB ORDER BY ID")
print(cur.fetchall())
# ibm_db 3.3.0: [(1, '3C6D656D6F7279206174203078...3E'), (2, '3C6D656D6F7279...3E')] -> "<memory at 0x...>"
# ibm_db 3.2.3: the same text, UTF-16 encoded
cur.executemany("INSERT INTO PRB (ID, VB) VALUES (?, ?)", rows)
# SQL0302N The value of a host variable in the EXECUTE or OPEN statement is out of range for its corresponding use.
Expected: the bytes 0102 and 0304 stored in both cases, as with execute or with bytes values.
Environment
- ibm_db 3.3.0 and 3.2.3 (bundled clidriver), Python 3.11, Linux x86_64
- Db2 LUW 11.5.9.0 (Community Edition container)
SQLAlchemy binds binary values through dbapi.Binary, so any SQLAlchemy executemany of LargeBinary/BLOB values is affected. A dialect-side workaround (bind bytes) is proposed in ibmdb/python-ibmdbsa#205.
ibm_db_dbi.Binaryreturns amemoryview. Passing such values toCursor.executemany:BLOBcolumn, stores the text of the object's repr (<memory at 0x7f...>) instead of the bytes, with no error;VARBINARY(n)andCHAR(n) FOR BIT DATAcolumns, fails withSQL0302N(value out of range), even when every value fits.Single-row
Cursor.executewith the samememoryviewvalues stores the correct bytes. Passingbytestoexecutemanyalso works.Reproduction
Expected: the bytes
0102and0304stored in both cases, as withexecuteor withbytesvalues.Environment
SQLAlchemy binds binary values through
dbapi.Binary, so any SQLAlchemyexecutemanyofLargeBinary/BLOBvalues is affected. A dialect-side workaround (bindbytes) is proposed in ibmdb/python-ibmdbsa#205.