Thin mode: an outputtypehandler redefining a CLOB as DB_TYPE_LONG misreads the reply when the statement is cached
Chưa có ai nhận issue này.
- #635 của @lemenkov — đã đóng, không merge
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- python
- Lĩnh vực
- backend-api-design, database
Hướng nghiên cứu
Start with MessageWithData._preprocess_query() in src/oracledb/impl/thin/messages/base.pyx and compare its output type handler change handling with _process_error_info() for ORA-00932. The report says a linked pull request contains a fix, so review that change and the related cursor and LOB tests: tests/cursor, tests/data_types/test_1500_lobs.py, test_1600_longs.py, and test_2500_lobs_async.py. Done means cached statements return the expected CLOB or LONG values across the reported query orders and pass those tests.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Version: python-oracledb 26.1.0, and also the current main (26.2.0b1, commit 27132e11, 2026-11-12), thin mode, Python 3.14, Linux.
Database: Oracle Database 23ai Free (23.26), 21c XE and 18c XE. It reproduces the same way on all three.
What happens
A query runs once without a type handler. The same SQL then runs on a new cursor whose outputtypehandler returns cursor.var(oracledb.DB_TYPE_LONG, ...) for the CLOB column. That second fetch misreads the reply, and the error depends on the columns around the CLOB:
| query (plain first, then with the handler) | default statement cache | stmtcachesize=0 |
|---|---|---|
SELECT TO_CLOB('lob text') FROM dual |
DPY-5000: internal error: unknown protocol message type 40 |
ok |
SELECT TO_CLOB('lob text'), DATE '2026-11-04' FROM dual |
ValueError: year must be in 1..9999, not -10062 |
ok |
SELECT DATE '2026-11-04', TO_CLOB('lob text') FROM dual |
DPY-5000 |
ok |
SELECT TO_CLOB('lob text'), 1.5 FROM dual |
DPY-5015: encoded number data too long (40 bytes) |
ok |
SELECT TO_CLOB('lob text'), 'abc' FROM dual |
UnicodeDecodeError |
ok |
If the handler is there on the first execute of the SQL, or the statement cache is off, every case returns the expected row.
Reproducer
import oracledb
DSN = "host:1521/service" # any 12c+ database; queries DUAL only
def clob_as_long(cursor, metadata):
if metadata.type_code is oracledb.DB_TYPE_CLOB:
return cursor.var(oracledb.DB_TYPE_LONG, arraysize=cursor.arraysize)
return None
sql = "SELECT TO_CLOB('lob text') FROM dual"
for cache in (20, 0):
conn = oracledb.connect(user="...", password="...", dsn=DSN, stmtcachesize=cache)
conn.cursor().execute(sql).fetchone() # 1. plain: LOB locator
cur = conn.cursor()
cur.outputtypehandler = clob_as_long # 2. same SQL, now as LONG
try:
cur.execute(sql)
print(cache, "ok", cur.fetchone())
except Exception as exc:
print(cache, "fails:", type(exc).__name__, exc)
conn.close()
Output:
20 fails: InternalError DPY-5000: internal error: unknown protocol message type 40 ...
0 ok ('lob text',)
Expected
('lob text',) in both cases, as with the cache off.
The reverse order is wrong too, silently: run the SQL first with the CLOB→LONG handler, then on a new cursor without a handler (or with a handler that leaves the CLOB alone), and the CLOB column comes back as str instead of a LOB.
Cause
In MessageWithData._preprocess_query() (src/oracledb/impl/thin/messages/base.pyx), when the output type handler differs from the one used for the statement's last fetch, the fetch variables are rebuilt for the new handler, but _requires_define isn't set. The statement is cached, so no new describe arrives either, and the database keeps returning the LOB columns in the form the last define asked for. The client then decodes them in the form the new fetch variables expect.
Setting _requires_define there isn't enough. On a cached cursor it sends a define without an execute, and the fetch fails with ORA-01002. The fix in the attached PR clears the cursor instead, as _process_error_info() already does for ORA-00932, but only when the statement has LOB columns (_no_prefetch). The statement is then parsed, described and defined again, and the fetch variables come from the new describe. With the fix, all 15 combinations (3 orders × 5 queries) pass on 23ai, 21c and 18c, and tests/cursor, tests/data_types/test_1500_lobs.py, test_1600_longs.py and test_2500_lobs_async.py pass against 23ai (597 passed, 8 skipped).
- Ngôn ngữ chính
- Python
- Star
- 458
- Fork
- 123
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của oracle/python-oracledb
-
DPY-3040 on AR8MSWIN1256 (charset id 560) when reading DbObject string attributes in Thin modeĐang mởbug
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 57/100
oracle/python-oracledb#636 · 1 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 55/100
oracle/python-oracledb#633 ·
-
Thin mode: segfault when a cached query is executed again after its first execute failed with ORA-01438Có thể đã có người làm @jhchong0405 đã nhận 3 ngày trước. Đang mở
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 38/100
oracle/python-oracledb#631 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
oracle/python-oracledb#630 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 15/100
oracle/python-oracledb#629 ·
Tất cả issue của oracle/python-oracledb
Issue tương tự
-
SslLibrary crashes with unhandled OSError: port/proto not found on non-standard SSL portsCó thể đã có người làm @himanchalkaushale đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
OWASP/Nettacker#1884 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
A-connection-core C-enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
aws-samples/sample-per-model-bedrock#869 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Spec: say that included_antigen_sources gates LENS labels; do not merge it into antigen kindsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
fzn0x/watchtower#17 ·