SELECT on BLOB or CLOB columns no longer requires raw byte interpretation. The 72-byte server-side locator is wrapped in a typed BlobLocator or ClobLocator (frozen dataclass) so the column is recognizable as "server-side reference, not actual bytes". Wire-protocol findings: * Smart-LOB columns DON'T appear with their nominal type codes (102/101) in SQ_DESCRIBE. They surface as UDTFIXED (41) with extended_id 10 (BLOB) or 11 (CLOB) and encoded_length=72 (locator size). * Retrieving the actual bytes requires SQ_FPROUTINE (103) RPC to invoke ifx_lo_open, plus SQ_LODATA (97) for chunked transfer, plus another SQ_FPROUTINE for ifx_lo_close. That's a Phase 10 lift — roughly 2x the protocol surface of Phase 8. Server config needed (added to Phase 7 setup): * sbspace: onspaces -c -S sbspace1 ... * default sbspace: onmode -wm SBSPACENAME=sbspace1 What ships in Phase 9: * informix_db.BlobLocator(raw: bytes) — 72-byte frozen wrapper * informix_db.ClobLocator(raw: bytes) — distinct type, same shape * Row decoder branch in _resultset.parse_tuple_payload * Wire constants SQ_LODATA=97, SQ_FPROUTINE=103, SQ_FPARAM=104 Tests: * 11 unit tests in test_blob_locator_unit.py (no Informix needed) — construction, immutability, equality, hash, repr safety, size validation. * 4 integration tests in test_smart_lob.py — fixture seeds via JDBC reference client (smart-LOB writes also need deferred protocols). * RefBlob.java helper in tests/reference/ for seeding via JDBC. Total: 64 unit + 111 integration = 175 tests. Locator design note: __repr__ omits the raw bytes (they're opaque to the client). Same-bytes locators of different families compare unequal — BlobLocator(x) != ClobLocator(x) — to avoid silent type confusion.
23 lines
875 B
Java
23 lines
875 B
Java
package tests.reference;
|
|
import java.sql.*;
|
|
public class RefBlobTest {
|
|
public static void main(String[] args) throws Exception {
|
|
String table = args[0], payload = args[1];
|
|
Class.forName("com.informix.jdbc.IfxDriver");
|
|
try (Connection c = DriverManager.getConnection(
|
|
"jdbc:informix-sqli://127.0.0.1:9088/testdb:INFORMIXSERVER=informix",
|
|
"informix", "in4mix")) {
|
|
c.setAutoCommit(true);
|
|
try (Statement s = c.createStatement()) {
|
|
s.execute("CREATE TABLE " + table + " (id INT, data BLOB)");
|
|
}
|
|
try (PreparedStatement ps = c.prepareStatement(
|
|
"INSERT INTO " + table + " VALUES (?, ?)")) {
|
|
ps.setInt(1, 1);
|
|
ps.setBytes(2, payload.getBytes());
|
|
ps.executeUpdate();
|
|
}
|
|
}
|
|
}
|
|
}
|