`LOB.read(0)` gives unhelpful error message in thin mode
The following Python script:
import oracledb
db = oracledb.connect("user/pwd@db")
c = db.cursor()
c.execute("select to_clob('foo') from dual").fetchone()[0].read(0)
gives the following output:
Traceback (most recent call last):
File "/Users/walter/oracledb_bug.py", line 4, in <module>
c.execute("select to_clob('foo') from dual").fetchone()[0].read(0)
File "/Users/walter/pyvenvs/default/lib/python3.10/site-packages/oracledb/lob.py", line 116, in read
return self._impl.read(offset, amount)
File "src/oracledb/impl/thin/lob.pyx", line 140, in oracledb.thin_impl.ThinLobImpl.read
File "src/oracledb/impl/thin/protocol.pyx", line 294, in oracledb.thin_impl.Protocol._process_single_message
File "src/oracledb/impl/thin/protocol.pyx", line 295, in oracledb.thin_impl.Protocol._process_single_message
File "src/oracledb/impl/thin/protocol.pyx", line 288, in oracledb.thin_impl.Protocol._process_message
oracledb.exceptions.DatabaseError: ORA-03137: malformed TTC packet from client rejected: [kpolob:offset 0] [0] [0] [2] [] [] [] []
In thick mode I get:
Traceback (most recent call last):
File "/Users/walter/oracledb_bug.py", line 5, in <module>
c.execute("select to_clob('foo') from dual").fetchone()[0].read(0)
File "/Users/walter/pyvenvs/default/lib/python3.10/site-packages/oracledb/lob.py", line 116, in read
return self._impl.read(offset, amount)
File "src/oracledb/impl/thick/lob.pyx", line 168, in oracledb.thick_impl.ThickLobImpl.read
File "src/oracledb/impl/thick/utils.pyx", line 409, in oracledb.thick_impl._raise_from_odpi
File "src/oracledb/impl/thick/utils.pyx", line 399, in oracledb.thick_impl._raise_from_info
oracledb.exceptions.DatabaseError: ORA-24801: Unzulässiger Parameterwert in OCI-LOB-Funktion
which at least gives a hint at what the problem is.
import sys, platform, oracledb
print(f"{platform.platform()=}")
print(f"{sys.maxsize > 2**32=}")
print(f"{platform.python_version()=}")
print(f"{oracledb.__version__=}")
prints
platform.platform()='macOS-12.4-x86_64-i386-64bit'
sys.maxsize > 2**32=True
platform.python_version()='3.10.4'
oracledb.__version__='1.0.0'
The database is an Oracle XE.
select value from nls_database_parameters where parameter='NLS_RDBMS_VERSION';
returns 21.0.0.0.0.
If we adjust the code so that it returns an empty string instead of raising an exception, would you consider that preferable? I don't find the thick driver error to be all that helpful either! The other option is to create a more meaningful error -- but it seems unnecessary. Thoughts?
The most helpful would probably be:
ValueError: offset must be > 0
BTW, passing a negative values currently results in:
OverflowError: can't convert negative value to uint64_t
so 0 is the only values with this behavour.
The most elegant API would be support for slices for LOB objects, since slices clip out of bound values automatically.
So instead of lob.read(1, 100) I could do lob[:100] and instead of lob.read(lob.getsize()-100) I could do lob[-100:] (I'm assuming that the default value for the amount parameter is "until the rest of the LOB".
I've added error DPY-2030 to address this situation for both thin and thick. If you want to create a new enhancement request for supporting slices with LOBs, please go ahead; otherwise, I'll close this when 1.1 is released.
This enhancement has been implemented in python-oracledb 1.1.0 which was just released.