← All notes

Notes · 2026-09-06

ArcadeDB fixed the pg_type bootstrap within a day, verified on the merged build

The native PostgreSQL ADBC driver could not connect to ArcadeDB; a probe comment became a diagnosed issue, a fix and a merge within a day. Verified.

The native-driver probe of 2026-09-05 found that the Apache Arrow PostgreSQL ADBC driver (1.12.0) could not open a connection to ArcadeDB's PostgreSQL-protocol plugin at all. This note records what happened next, because it happened fast, and because the first verification needed a correction.

Timeline

When (UTC) What
2026-09-05 21:19 Follow-up comment on ArcadeDB's discussion thread with the probe result: Expected 5 or 6 columns from type resolver pg_type query but got 0
22:11 ArcadeDB's maintainer opened #7178 with the diagnosis
22:33 Fix PR #7179 opened, with tests
22:44 Verified on the PR's CI image: the driver connects (see the correction below)
22:47 Maintainer filed #7180 for what the driver hits next
2026-09-06 02:48 PR merged; #7178 closed
03:05 Verified again on the merged code, this time with the fixture types present

What was wrong

The driver bootstraps its type resolver with three queries before it hands back a connection, and it checks the shape of each answer: zero rows are fine, zero columns are fatal. The third query selects oid, typname, typreceive, typbasetype, typrelid, typarray from pg_catalog.pg_type with a WHERE clause of inequalities, a parenthesised OR and a ::TEXT cast. ArcadeDB's emulated pg_type knew neither typreceive nor typsend, and its WHERE parser accepted a single equality only, so the whole projection was declined and the answer had no columns. The fix teaches the emulation those columns, with PostgreSQL's real receive and send function names (the driver selects a column's decoder by that name), and registers pg_type as a query family of its own so the filter is evaluated.

What the merged build does now

Same seven-step probe, native driver, fixture types created first:

Step Driver defaults With adbc.postgresql.use_copy=false
connect passes passes
SELECT 1 stops: COPY (…) TO STDOUT (FORMAT binary) is not ArcadeDB SQL passes
GetTableSchema empty schema empty schema
GetObjects lists both types lists both types
read the fixture table stops at COPY passes; @rid, @type, @cat as strings, the five properties as int64, string, double, date32 and bool

So the fix does exactly what #7178 says, and with one driver option the native driver now runs the read workload against ArcadeDB end to end apart from the schema lookup. adbcBridge over psqlodbc passes all seven steps before and after, as it did in the original probe.

What is left, and where it is tracked

Both items are in #7180 with the driver's exact statements:

  • Binary COPY … TO STDOUT. The driver's default read path. A feature in its own right on ArcadeDB's side; the use_copy=false option is the working route today, as it is on CockroachDB and openGauss.
  • GetTableSchema. The driver's statement joins pg_class, pg_attribute and pg_type with cls.oid = $1::regclass::oid; ArcadeDB has no regclass cast, so the statement is answered with zero rows. The same join filtered by relname returns the five properties.

The maintainer says the fix ships in ArcadeDB 26.10.1, the October release, and is in the 26.10.1-SNAPSHOT build now. The ArcadeDB row in the probe note and in the matrix will say "connects" once 26.10.1 is out.

A correction to the first verification

The first verification, on the PR's CI image, reported two further stops that were not ArcadeDB's: GetObjects returning no tables and SELECT * FROM "adbc_big" failing with "type not found". Both came from the probe's own order of operations. It runs the native driver before the ODBC pass, and the ODBC pass is what creates the fixture types, so on a freshly started image the native run saw a database with nothing in it. With the types present, GetObjects lists everything and quoted identifiers work. The correction was posted on the PR and on #7180 the same evening, and the probe is now run twice on a fresh server so the second pass measures a populated database.

Trying it

docker run -d -p 5432:5432 \
  -e JAVA_OPTS="-Darcadedb.server.rootPassword=… -Darcadedb.server.defaultDatabases=adbc[adbc:adbc] \
     -Darcadedb.server.plugins=Postgres:com.arcadedb.postgres.PostgresProtocolPlugin" \
  arcadedata/arcadedb:latest
import adbc_driver_postgresql.dbapi as pg
from adbc_driver_postgresql import StatementOptions
conn = pg.connect("postgresql://root:…@127.0.0.1:5432/adbc", autocommit=True)
cur = conn.cursor()
cur.adbc_statement.set_options(**{StatementOptions.USE_COPY.value: "false"})
cur.execute("SELECT * FROM adbc_big")
print(cur.fetch_arrow_table())

Until 26.10.1 is out, that needs the 26.10.1-SNAPSHOT build. The ODBC route works on the released 26.9.1 today:

import adbcbridge
conn = adbcbridge.connect(uri="Driver=psqlodbcw.so;Server=127.0.0.1;Port=5432;Database=adbc;Uid=root;Pwd=…;BoolsAsChar=0;")