# pgtest wire-protocol conformance report - SecantusDB (Python server) 0.6.0b12 - corpus + runner: cockroachdb/cockroach @ `e3bff5d92ac1` (`pkg/sql/pgwire/testdata/pgtest`, run by `pkg/testutils/pgtest` verbatim) - generated: 2026-08-19 18:13 UTC **49/66 files pass** (12 expected divergences, 0 unexpected failures, 5 skipped). | file | result | |---|---| | `aborted_txn` | pass | | `array` | pass | | `as_of_system_time` | skip | | `batch_stmt` | pass | | `bind_and_resolve` | pass | | `box2d` | expected divergence | | `char` | expected divergence | | `citext` | pass | | `collated_string` | pass | | `copy` | pass | | `copy_file_upload` | pass | | `data_type_size` | pass | | `decimal` | pass | | `enum` | pass | | `errors` | pass | | `execute` | pass | | `float` | pass | | `implicit_txn` | pass | | `inet` | pass | | `int2vector` | expected divergence | | `int_size` | pass | | `json` | pass | | `json_array` | pass | | `jsonpath` | expected divergence | | `large_input` | pass | | `ltree` | pass | | `multiple_active_portals` | expected divergence | | `multiple_active_portals/bind_to_an_existing_active_portal` | pass | | `multiple_active_portals/different_portals_bind_to_the_same_statement` | pass | | `multiple_active_portals/drop_table_when_there_are_dependent_active_portals` | pass | | `multiple_active_portals/more_complicated_stmts` | pass | | `multiple_active_portals/not_in_explicit_transaction` | pass | | `multiple_active_portals/not_supported_statements` | pass | | `multiple_active_portals/query_timeout` | expected divergence | | `multiple_active_portals/select_from_individual_resources` | pass | | `multiple_active_portals/select_from_same_table` | pass | | `notice` | pass | | `oid` | pass | | `param_status` | pass | | `parameter_description` | pass | | `pgjdbc` | pass | | `pgjdbc/158771` | pass | | `pgvector` | expected divergence | | `portals` | expected divergence | | `portals_crbugs` | skip | | `prepare` | pass | | `prepared_stmt_invalidation` | pass | | `procedure` | expected divergence | | `read_committed` | skip | | `row_description` | expected divergence | | `schema_changes_implicit_txn` | pass | | `schema_changes_implicit_txn/autocommit_for_bind` | pass | | `schema_changes_implicit_txn/triggers` | pass | | `set` | pass | | `set_transaction` | skip | | `show_commit_timestamp` | skip | | `simple` | pass | | `spatial` | expected divergence | | `statement_hints_pausable_portal` | pass | | `timezone` | pass | | `tuple` | pass | | `typing` | expected divergence | | `unknown` | pass | | `update_limit` | pass | | `varbit` | pass | | `void` | pass | ## Expected divergences - `box2d` — PostGIS BOX2D — an extension type outside SecantusDB's core-PostgreSQL SQL scope. The ``::BOX2D`` cast falls through to a text passthrough, so the binary result is the text form rather than PostGIS's four-float8 box encoding. Out of scope, like GEOMETRY (see ``spatial``). - `char` — char:250 pins TableOID=105 — crdb's deterministic descriptor id, with no ignore_table_oids directive on that stanza. Real PostgreSQL reports its own pg_class oid there too (installation-specific), so the stanza can't pass against any non-crdb server. Everything else in the file is green (oid-18 "char": casts, columns, params, 1-char truncation, NULL for empty/zero-byte, binary format). - `int2vector` — int2vector:26 expects indoption={2} for a plain primary key — crdb's NULLS-FIRST pkey representation. Real PostgreSQL reports 0 (ASC, NULLS LAST), and so do we; matching crdb's 2 would corrupt SQLAlchemy index reflection. The BINARY int2vector encoding the stanza actually regression-tests (int2 array elements, elemoid 21 — crdb #111907 shipped int8 once) is implemented and correct. - `jsonpath` — jsonpath:36/:76 expect crdb's BINARY jsonpath form — version byte + the SINGLE-QUOTED text ('$' -> 01272427). Real PostgreSQL's jsonpath_send emits the version byte + the canonical text WITHOUT outer quotes (0124), which is what we send. Everything else in the file is green (oid 4072, canonical $."abc" text, 42601 on an empty path, jsonb_path_query). - `multiple_active_portals` — A CockroachDB pausable-portal test. Two of its subtests can't pass against a non-crdb server: (1) `query_timeout` expects a portal paged MaxRows:1 to emit N DataRows and THEN a 57014 statement-timeout on the next pull — that incremental behaviour needs LAZY per-row portal evaluation, but SecantusDB materialises a portal's result eagerly (statement_timeout IS enforced for simple / single-statement queries, just not row-by-row across a paged portal); (2) `interleave_with_unpausable_portal` pins crdb's `0A000 unimplemented: the statement for a pausable portal must be a read-only SELECT` error (with a go.crdb.dev hint) for interleaving a non-read-only portal — real PostgreSQL interleaves those fine and emits no such error. Every other subtest passes (select_from_individual_resources, select_from_same_table, bind_to_an_existing_active_portal, not_in_explicit_transaction, drop_table_when_there_are_dependent_active_portals, different_portals_bind_to_the_same_statement, more_complicated_stmts, not_supported_statements). - `multiple_active_portals/query_timeout` — Expects a portal paged MaxRows:1 to emit several DataRows and then a 57014 statement-timeout on the next pull — needs LAZY per-row portal evaluation; SecantusDB materialises a portal's result eagerly, so statement_timeout (which IS enforced for simple / single-statement queries) can't page a portal row-by-row against the deadline. - `pgvector` — The pgvector VECTOR type — an extension outside SecantusDB's core-PostgreSQL SQL scope. A ``VECTOR`` column is rejected with a faithful 0A000 (unsupported column type), which is correct emulation of a server without the extension installed, but the corpus expects a working vector type. - `portals` — portals:1182 compares the CHECK-violation MESSAGE with keepErrMessage and pins crdb's wording ('failed to satisfy CHECK constraint (a > 1.0:::FLOAT8)'). We emit real PostgreSQL's ('new row for relation "t" violates check constraint "t_a_check"'), which is what psycopg/pgjdbc users parse — matching crdb would be a fidelity REGRESSION. Everything up to :1182 passes (1182 of 1550 lines, including PortalSuspended-on-exact-MaxRows and per-Execute row counts). NOTE: the stanzas after :1182 are therefore NOT exercised — they cover 34000 'unknown portal' (already implemented, slice 21) and 42P03 'cursor "p" already exists as portal' (NOT implemented). See tasks/backlog.md. - `procedure` — procedure:68 pins the NoticeResponse's SOURCE-LOCATION fields to crdb's own Go internals — File="builtins.go", Routine="func401" — with no crdb_only marker. Those fields name the server's own source file and function, so they are unmatchable by any other implementation: real PostgreSQL 14 emits Routine=exec_stmt_raise, File=pl_exec.c (probed), and SecantusDB leaves them empty rather than fabricate a C source location it does not have. Everything the stanza actually regression-tests works: CREATE PROCEDURE ... LANGUAGE plpgsql, CALL p(), and the three RAISE NOTICE messages (foo / bar / baz) arriving in order with SQLSTATE 00000, followed by CommandComplete CALL. - `row_description` — row_description:376 sends `SELECT 'foo'::STRING, 'bar'::STRING(2)` with NO crdb_only marker and expects crdb's STRING aliases (text/25 and varchar/1043 typmod 6, truncating 'bar' to 'ba'). Real PostgreSQL 14 rejects both casts outright — `ERROR: 42704 type "string" does not exist` (probed) — so the stanza can't pass against any non-crdb server, and matching crdb's varchar(2) truncation would diverge from PG. Everything before :376 is green: base-column identity across a JOIN and through a VIEW, char(n) blank padding on the wire, and attnum stability across ALTER COLUMN TYPE. - `spatial` — PostGIS GEOMETRY/GEOGRAPHY — an extension type outside SecantusDB's core-PostgreSQL SQL scope (the surrogate models MongoDB, not PostGIS). A GEOMETRY value can't round-trip its EWKB binary form; an untyped binary GEOMETRY parameter now surfaces a faithful 22P03 rather than a generic internal error, but the type itself is not implemented. - `typing` — typing's two non-crdb stanzas both use keepErrMessage and pin crdb's wording for a mixed-type comparison: 22023 'unsupported comparison operator: = ' (and = ). Real PostgreSQL 14 raises 42883 'operator does not exist: character varying = uuid' (probed), which is what we now emit — matching crdb would be a fidelity REGRESSION, same as the portals file. The behaviour the stanzas actually regression-test (a DECLARED parameter type making the comparison unresolvable AT PARSE, rather than a predicate that silently matches nothing) is implemented and correct.