diff --git a/docs/UPSTREAM.md b/docs/UPSTREAM.md index d393754..0ae7b5e 100644 --- a/docs/UPSTREAM.md +++ b/docs/UPSTREAM.md @@ -12,6 +12,8 @@ before it is filed. | Date | Project | Report | What it is | Status | |---|---|---|---|---| +| 2026-09-21 | ArcadeDB | [ArcadeData/arcadedb#8090](https://github.com/ArcadeData/arcadedb/issues/8090) (opened by the maintainer from the case-study exchange, credited to this project) | A `DATETIME_MICROS` (also `DATETIME`, `DATETIME_NANOS`) literal written with a space separator *and* a fraction — `'2024-02-29 13:45:10.123456'`, the form psqlodbc renders a bound `SQL_TYPE_TIMESTAMP` parameter in — is accepted by `INSERT` and stored as NULL, with no error and nothing logged at the default level. The space alone parses and the fraction alone parses; the two together fail every parser `Type.convert()` tries, and its blanket `catch (Exception)` logs at `FINE` and returns null, so the same construct turns *any* unparseable value for *any* target type into NULL. Recorded here as a documented behaviour since 2026-08-28 (`tests/compat/README.md`); the maintainer reproduced it on main, wrote the root cause and a two-part fix into the issue, and labelled it critical. Reproduced from here on 26.9.1 on 2026-09-21, text and binary result formats and through psqlodbc. | open | +| 2026-08-28 | ArcadeDB | [ArcadeData/arcadedb#6674](https://github.com/ArcadeData/arcadedb/issues/6674) (reported by an ArcadeDB contributor on 2026-08-24, not from this project; listed because this tracker carried the symptom as "documented, not yet reported" until 2026-09-21) | A NULL in a `BOOLEAN` column arrived over the wire as `false` with a non-NULL indicator: the text serializer wrote `"0"` for a NULL, the binary path wrote the `-1` sentinel, so text and binary disagreed. Observed here on `arcadedata/arcadedb:latest` = 26.8.1; the matrix entry masked it with `not_null=("bo",)`. | **fixed** the day it was reported, shipped in 26.9.1 (2026-09-03). Retested here on 26.9.1 on 2026-09-21: NULL round-trips on the text and binary paths and through psqlodbc; the matrix entry's `not_null` flag is removed and the all-NULL row check covers the column again. | | 2026-09-17 | ArcadeDB | [ArcadeData/arcadedb#7815](https://github.com/ArcadeData/arcadedb/pull/7815) | PostgreSQL wire, simple query protocol: `BEGIN`, `COMMIT`, `ROLLBACK` and the savepoint statements are answered with a zero-field `RowDescription` before the `CommandComplete`, so libpq reports `PGRES_TUPLES_OK` instead of `PGRES_COMMAND_OK`; `psql` prints an empty table after `BEGIN` and the Arrow PostgreSQL ADBC driver, whose DB-API starts with autocommit off, fails `[libpq] Failed to begin transaction:`. psqlodbc ignores the status, so adbcBridge was never affected. Sent as a fix with a wire-level test | **fixed on main** — our fix PR was merged by the maintainer on 2026-09-17, the day it was opened (merge `7ed83075`); found on `26.10.1-SNAPSHOT` while re-checking #7188; the new test fails before the fix, and the maintainer re-ran the PostgreSQL module's integration suite on it (244 tests, 0 failures) and extended the fix so a prefixed `{sql}BEGIN` gets its command tag too. That savepoint statements are accepted without being implemented is tracked separately as [ArcadeData/arcadedb#7846](https://github.com/ArcadeData/arcadedb/issues/7846). Expected in 26.10.1 | | 2026-09-17 | DuckDB ODBC | [duckdb/duckdb-odbc#524](https://github.com/duckdb/duckdb-odbc/pull/524) | Parameter arrays on 1.5.5 and on main: with `SQL_ATTR_PARAMSET_SIZE` above 1, every fixed-length parameter receives set 0's value in every row under `SQL_SUCCESS` with the right processed count; only character and binary parameters step (the fixed-length branches read from the start of the bound buffer). Sent as a fix: each set reads its own element, with a test over six types and a NULL set | **merged 2026-09-17** (ours) — approved ("Thanks for the PR! Looks good to me.") and merged by a DuckDB maintainer the day it was opened (merge `1e065eaf`), green on Linux, macOS and Windows on both architectures; reproduced on the 1.5.5 release and on main, verified on a build of the fix, where the driver's whole test suite passes. Ships in the first duckdb-odbc release after v1.5.5.0; adbcBridge keeps binding row by row for DuckDB until then | | 2026-09-17 | DuckDB ODBC | [duckdb/duckdb-odbc#523](https://github.com/duckdb/duckdb-odbc/pull/523) | `SQLGetInfo(SQL_DBMS_VER)` on 1.5.5: under unixODBC the process segfaults (the driver's internal `SQLAllocHandle` call binds to the driver manager, fails, and the error path frees an uninitialized handle); linked directly it returns `SQL_SUCCESS`, the right length and an empty string (read into one buffer, returned from another). Sent as a fix: the version comes straight from the engine, with a test against `pragma_version()` | **merged 2026-09-17** (ours) — approved ("Thanks for the PR! It looks good to me.") and merged by a DuckDB maintainer the day it was opened, green on Linux, macOS and Windows; reproduced on the 1.5.5 release and verified on a build of the fix, where the driver's whole test suite passes. Ships in the first duckdb-odbc release after v1.5.5.0 | @@ -73,7 +75,6 @@ time allows, and a reproduction contributed by anyone is welcome. | DuckDB ODBC 1.5.5 (Linux) | (`SQLGetInfo(SQL_DBMS_VER)` segfault and the parameter-array defect: both sent upstream as fixes and both merged on 2026-09-17, see duckdb/duckdb-odbc#523 and #524 above.) A fetch writes the full 2048-row vector into bound buffers whatever the rowset size. adbcBridge binds row by row and fetches 2048-row rowsets there. | `COMPATIBILITY.md`, `tests/compat/README.md` | | RisingWave 3.0 | A server-side statement name is not released when the client closes the statement, so psqlodbc's `_PLAN0x` names collide on the second prepare of an allocate/prepare/execute/free loop (`XX000 Duplicated statement name`). adbcBridge sets `UseServerSidePrepare=0` there. | `COMPATIBILITY.md` | | OceanBase CE 4.4.2 | A server-side prepared execute in which a parameter arrives as `MYSQL_TYPE_NULL` (what MySQL Connector/ODBC sends for a NULL before a value has fixed the type) is refused with `Object type error` (4001); MySQL accepts the same sequence. | `COMPATIBILITY.md` | -| ArcadeDB 26.9 (PostgreSQL wire) | A `DATETIME_MICROS` literal written with a space separator and a fraction (`'2024-02-29 13:45:10.123456'`, the form psqlodbc renders a bound timestamp in) is stored as NULL under `SQL_SUCCESS`; a NULL `BOOLEAN` arrives over the wire as `false` with a non-NULL indicator. | `tests/compat/README.md` | | `alexbrainman/odbc` (Go, Windows) | Access violation inside `api.SQLGetDiagRec` on the first driver diagnostic, on every server but SQLite. | `bench/LANGUAGE_BENCHMARKS-windows.md` | | psqlodbc 18.x | Sends `SHOW DateStyle` at connect, which YDB's PostgreSQL layer rejects; 16.x does not. (Arguably YDB's to implement.) | `COMPATIBILITY.md`, macOS and Windows columns | | Firebird ODBC 3.0.1 / 3.5.0-rc1 | No macOS build; Firebird 5's sample security database ships with no SYSDBA and bootstrapping one needs an administrator. | `COMPATIBILITY.md` | diff --git a/tests/compat/README.md b/tests/compat/README.md index c34ae68..7584cdf 100644 --- a/tests/compat/README.md +++ b/tests/compat/README.md @@ -3505,8 +3505,13 @@ that path, since every other driver answers the enumeration. * **`BoolsAsChar=0`** in the connection string. Without it psqlodbc reports every `BOOLEAN` as a `VARCHAR(5)` holding `"1"`/`"0"` instead of `SQL_BIT`. Same setting, same reason, as the `questdb` entry. -* **`not_null=("bo",)`.** With `BoolsAsChar=0` a boolean property has no NULL state on - the wire: row 2's `bo` goes in as `NULL` and reads back `False`. +* **NULL booleans, fixed upstream.** On 26.8.1 a NULL `BOOLEAN` property came back over + the wire as `false` with a non-NULL indicator (the text serializer wrote `"0"` for a + NULL; [ArcadeData/arcadedb#6674](https://github.com/ArcadeData/arcadedb/issues/6674), + reported by an ArcadeDB contributor, fixed 2026-08-24, shipped in 26.9.1). The entry + carried `not_null=("bo",)` for it until 2026-09-21, when a retest on 26.9.1 showed row + 2's `bo` reading back `NULL` on the text and binary paths and through psqlodbc; the + flag is gone and the all-NULL row check covers `bo` again. * **`decimal_type="decimal128(28, 3)"`.** ArcadeDB reports no declared precision for a `DECIMAL` property, so psqlodbc falls back to its own maximum (28) with the scale of the values in the result set — as it does for RisingWave's unqualified `NUMERIC`. @@ -3514,7 +3519,12 @@ that path, since every other driver answers the enumeration. `DATETIME_MICROS` property is stored as `NULL`, silently; `'2024-02-29T13:45:10.123456'` round-trips to the microsecond. (A bound `SQL_TYPE_TIMESTAMP` parameter goes as the space form, so it hits the same silent NULL — - a reason to write timestamps as ISO text against this server.) + a reason to write timestamps as ISO text against this server.) Reproduced on 26.9.1 + on 2026-09-21: the space alone parses and the fraction alone parses, the two together + fail to parse and a blanket handler in the type converter turns the value into NULL + under a successful `INSERT`. Tracked as + [ArcadeData/arcadedb#8090](https://github.com/ArcadeData/arcadedb/issues/8090), opened + by the maintainer with the root cause and a reproducer. * **No binary transport.** A bound `bytea` parameter is refused by the protocol layer outright (`Error on parsing bind message: Type with code 0 not supported for deserializing`), and a `BINARY` property fed a string hands the string straight back. diff --git a/tests/compat/test_matrix.py b/tests/compat/test_matrix.py index 622737e..a939503 100644 --- a/tests/compat/test_matrix.py +++ b/tests/compat/test_matrix.py @@ -1358,9 +1358,11 @@ def tdengine_setup(n=20000, chunk=1000, base=1709210000000000): # falls back to its own maximum (28) with the scale of the values in the result # set -- as it does for RisingWave's unqualified NUMERIC. decimal_type="decimal128(28, 3)", - # A BOOLEAN property has no NULL state on the wire: row 2's `bo` was inserted as - # NULL and reads back false, as QuestDB's and Access's booleans do. - not_null=("bo",), + # Until 26.9.1 a NULL BOOLEAN came back as false over the wire (the text + # serializer wrote "0" for a NULL; ArcadeData/arcadedb#6674, fixed 2026-08-24) and + # this entry carried not_null=("bo",) for it. Retested on 26.9.1 on 2026-09-21: + # row 2's `bo` reads back NULL on the text and binary paths and through psqlodbc, + # so the flag is gone and the all-NULL row check covers `bo` again. # ArcadeDB is a graph database as much as a document one, which nothing in the # standard workload touches, so the `extra` steps build a small graph through the # ODBC path and traverse it: three vertices, two edges, then one- and two-hop