A timestamp that stores NULL and says it worked, and a boolean note that went stale
Two behaviours sat in this project's ArcadeDB compatibility notes since 2026-08-28, written
down but never filed: a timestamp form that silently stored NULL, and a NULL BOOLEAN that
read back as false. Both have now been settled, and in opposite directions. One turned out
to be worse than the note said and is a critical issue in ArcadeDB's own tracker. The other
had already been fixed before the note was ever published, which is the more useful lesson.
The timestamp: success, and no value
A DATETIME_MICROS property fed the string '2024-02-29 13:45:10.123456' stores NULL. The
INSERT reports success. Nothing in the result says a value was dropped.
Either half of that literal on its own is fine:
literal='2024-02-29T13:45:10.123456' stored=2024-02-29T13:45:10.123456
literal='2024-02-29 13:45:10.123456' stored=>>> NULL <<<
literal='2024-02-29 13:45:10' stored=2024-02-29T13:45:10
The T separator round-trips to the microsecond, and the space separator without a fraction
round-trips too. Only the combination fails, and the combination is exactly what psqlodbc
renders a bound SQL_TYPE_TIMESTAMP parameter as. So an application that binds a timestamp
parameter — the ordinary thing to do — writes nothing and is told it wrote something.
ArcadeDB filed this themselves on 2026-09-21 as
ArcadeData/arcadedb#8090, labelled
severity:critical, after this project's notes were shared with them. Their issue names the
cause, which our note could not: a blanket catch in Type.convert() logs the parse failure
at FINE and returns null, and the insert carries on. It affects every PostgreSQL-wire
client that binds a timestamp against a sub-second-precision property, not just this driver.
The literal is not the only way in. Binding the value as a parameter — the ordinary thing an application does, and the reason the form appears at all — loses it the same way, through psqlodbc and out the other side as Arrow:
INSERT INTO RetestT SET lbl = ?, ts = ? with datetime(2024, 2, 29, 13, 45, 10, 123456)
DATETIME_MICROS column as Arrow:
bound-param -> None <- value lost server-side
Confirmed on the same 26.9.1 image on 2026-09-21. The INSERT succeeds, SQLExecute returns
SQL_SUCCESS, and the column is empty. Nothing between the application and the storage engine
has a way to notice.
Until it is fixed, the way through is to write timestamps as ISO text with the T, which is
what the compatibility entry for ArcadeDB says and what its parameter settings do.
The boolean: a note that aged badly
The second note said a NULL BOOLEAN had no NULL state over the wire: row 2's bo went in as
NULL and read back as False, so the compatibility entry marks that column not_null.
That was observed on 2026-08-28 against arcadedata/arcadedb:latest, which was 26.8.1 at the
time. It is not true any more, and it had already stopped being true before we wrote it up: a
project contributor filed the same behaviour as
#6674 on 2026-08-24 and closed it the
same day, and the fix shipped in 26.9.1 on 2026-09-03.
A retest on 2026-09-21 against the official 26.9.1 image (arcadedata/arcadedb:26.9.1),
through the route the compatibility entry actually describes — psqlodbc 16 with
BoolsAsChar=0, then adbcBridge into Arrow:
BOOLEAN column as Arrow:
schema: bool
true-row -> True
false-row -> False
null-row -> None <- SQL NULL
absent-row -> None <- SQL NULL
A NULL property and an absent property both arrive as SQL NULL, and true/false arrive
intact. The behaviour is correct.
What that is worth saying out loud
A compatibility matrix is a set of claims with dates on them, and a claim about a fast-moving database is perishable. This one went stale in nine days, between the observation and the write-up, and the only reason it was caught is that the project read the note and pushed back on it rather than accepting it.
Two habits come out of that, and both are now in this project's routine. Every quirk carries the version it was seen on, so a reader can tell what a cell is actually about. And a quirk that is documented but not filed gets re-tested against the current release before it is repeated anywhere, because "documented, not reported" is exactly where a fixed bug goes to live on.
The ArcadeDB compatibility entry keeps its not_null flag for the boolean column for now,
because the matrix row still records 26.9; it moves when the row is re-measured on 26.9.1.
Where these are tracked
- Timestamp: ArcadeData/arcadedb#8090,
open,
severity:critical, filed by the project on 2026-09-21. - Boolean: ArcadeData/arcadedb#6674, closed 2026-08-24 by a project contributor, shipped in 26.9.1, retested here on 2026-09-21.
Both rows are in this project's upstream record, and the ArcadeDB entry with its settings is on the ArcadeDB page.