Skip to content

Missing tests: 87 confirmed behaviours no shell or pytest arm exercises (#1339 audit) #1341

Open

Description

@jdatcmd

Missing tests: 87 confirmed behaviours no test exercises

The owner asked the pytest audit (#1339) to also look for missing tests, for old and new features. This issue holds what it found.

How the list was made

  • Searching: at main a30faeb, eight searchers each built an inventory a different way and grepped test/*.sh and test/pytest/*.py for each item:
    • every SQL function and catalog;
    • every setting;
    • every user-reachable error path in the C and SQL;
    • documented claims in docs/;
    • CHANGELOG entries for alpha3 to alpha5;
    • shell/pytest twin parity;
    • the alpha5 time-series features and how they interact;
    • core access-method behaviour.
  • Verifying: two independent skeptics then searched for an existing test covering each reported gap, trying to refute it. A gap is listed only if neither found one. That kept 87 of the 104 reported.
  • Reading this list: a skeptic reads code; it doesn't run it. So treat each item as "no test found", not "untested for certain". Each fix starts with a red arm, in both twins, that a named mutation of the product must redden.

By severity: high 31, medium 43, low 13. By search: core-am 18, twin-parity 15, error-paths 14, docs-claims 12, time-series-alpha5 11, sql-objects 9, gucs 7, changelog-features 1.

High (31)

  • docs/limitations.md promises that ON CONFLICT DO NOTHING 'works' and that DO UPDATE raises the row-locking error. Neither is tested. For any table wi… (core-am; docs/limitations.md:655-656; src/columnar_tableam.c:2141-2154 (COLUMNAR_UNSUPPO…)
    Arm to add: Add to fk_referencing.sh, the suite for row-locking consequences, plus a new pytest twin. Setup: c (id int PRIMARY KEY, v text) USING pgcolumnar; heap mirror h; insert (1,'a'),(2,'b') into both. Arm 'ON CONFLICT DO NOTHING inserts the new key and skips the conflict': INSERT VALUES (2,'x'),(3,'c') ON CONFLICT DO NOTHING. Expect success, rows {1,2,3}, v of id 2 still 'b', same a…
  • The AM takes no SSI predicate locks: there is no PredicateLockRelation or PredicateLockTID call on scans and no CheckForSerializableConflictOut. A SE… (core-am; src/*.c: grep -n 'PredicateLock\|CheckForSerializableConflict' returns nothing;…)
    Arm to add: New pair test/serializable.sh and test/pytest/test_serializable.py, with a heap control. Setup: doctors (id int, on_call bool) USING pgcolumnar with rows (1,t) and (2,t). Steps: 1. s1: BEGIN ISOLATION LEVEL SERIALIZABLE; SELECT count(*) FROM doctors WHERE on_call. 2. s2: the same. 3. s1: UPDATE doctors SET on_call=false WHERE id=1. 4. s2: UPDATE doctors SET on_call=false WHERE…
  • A SQL TRUNCATE that rolls back, at transaction level or to a savepoint, must restore every row. set_new_filelocator deletes the old storage's catalog… (core-am; src/columnar_tableam.c:1236-1285 (pgcolumnar_delete_storage_tree and PgColumnar…)
    Arm to add: Add to truncate_cleanup.sh plus a new pytest twin, with a heap mirror and an index on id. Arm 'a rolled-back TRUNCATE restores every row': BEGIN; TRUNCATE t; INSERT 10 rows; ROLLBACK. Expect set hash = heap, an index point lookup returns the row, and pgcolumnar.storage still resolves. Arm 'a TRUNCATE rolled back to a savepoint keeps the parent's rows': BEGIN; INSERT 3000 rows;…
  • CREATE INDEX builds from an MVCC snapshot, so a row deleted after an older REPEATABLE READ snapshot started is left out of the new index. Heap includ… (core-am; src/columnar_tableam.c:2466-2475 (serial build: snapshot = GetActiveSnapshot() …)
    Arm to add: New isolation spec test/isolation/specs/index_build_vs_old_snapshot.spec. Mirror it as an arm in a new pair test/index_build_snapshot.sh and test/pytest/test_index_build_snapshot.py. Steps: 1. Create t (id int) USING pgcolumnar with ids 1..10000 and no index. Create heap mirror h. 2. s1: BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT count(*) FROM t. 3. s2: DELETE FROM t WHERE …
  • An inner statement's ExecutorEnd flushes the OUTER statement's buffered rows and delete marks while an inner subtransaction (a plpgsql EXCEPTION bloc… (core-am; src/columnar_tableam.c:2777-2784 (pgcolumnar_executor_end calls PgColumnarFlush…)
    Arm to add: New pair test/subxact_flush.sh and test/pytest/test_subxact_flush.py. Setup: t (id int) USING pgcolumnar; heap mirror th; side table s (id int) USING pgcolumnar; function f(i) that runs BEGIN INSERT INTO s VALUES (i); PERFORM 1/0; EXCEPTION WHEN division_by_zero THEN NULL; END; RETURN i. Arm 'outer insert survives an aborted inner block': INSERT INTO t SELECT f(g) FROM generat…
  • An uncommitted DELETE (or key-changing UPDATE) of unique key k in T1 races an INSERT of k in T2, then T1 rolls back. Heap makes T2 wait on T1 through… (core-am; src/columnar_tableam.c:1942-1994 (pgcolumnar_index_fetch_tuple: dirty snapshot,…)
    Arm to add: Add to unique_conc.sh plus a new pytest twin (two connections). Run each case on a heap control too. Arm 'an insert of a key whose delete is uncommitted does not commit a duplicate when the delete rolls back': 1. u (k int UNIQUE) USING pgcolumnar; INSERT (5). 2. s1: BEGIN; DELETE FROM u WHERE k=5. 3. s2: INSERT INTO u VALUES (5). Do not wait for it. 4. s1: ROLLBACK. 5. Expect …
  • INSERT ... ON CONFLICT DO NOTHING 'works' on a columnar table, and ON CONFLICT DO UPDATE raises 'columnar: row locking is not supported yet'. (docs-claims; docs/limitations.md:655-656; the speculative-insert callbacks raise COLUMNAR_UN…)
    Arm to add: Add to a suite with unique indexes (e.g. test/unique_conc.sh, with a matching arm in its pytest twin when created). CREATE TABLE oc (k int PRIMARY KEY, v int) USING pgcolumnar; INSERT INTO oc VALUES (1,1). Arm 1: INSERT INTO oc VALUES (1,9) ON CONFLICT DO NOTHING succeeds, and count is 1 with v = 1. Arm 2: INSERT INTO oc VALUES (2,2) ON CONFLICT DO NOTHING succeeds and count b…
  • The four REST functions (iceberg_rest_table_location, iceberg_rest_scan, iceberg_rest_namespaces, iceberg_rest_tables) and a scan of the pgcolumnar_i… (docs-claims; docs/sql-reference.md:1159 and :1281; gates at src/columnar_iceberg_rest.c:676,…)
    Arm to add: Shell (test/server_file_privilege.sh, no pytest twin yet): add these rows to entry_points: "iceberg_rest_table_location|read|SELECT pgcolumnar.iceberg_rest_table_location('http://127.0.0.1:1','db','t')", the matching rows for iceberg_rest_scan (with AS t(id bigint)), iceberg_rest_namespaces and iceberg_rest_tables, and "iceberg_fdw_scan|read|SELECT * FROM ift" over CREATE SERV…
  • With the server form, a non-superuser role that has no USER MAPPING token is refused (28000) before any request. Only a superuser may set credentials… (docs-claims; docs/sql-reference.md:1143-1149 and :1183-1184; src/columnar_iceberg_rest.c:141…)
    Arm to add: Shell (test/iceberg_rest_server.sh, no pytest twin yet): create role ice_r with LOGIN, schema USAGE and pg_read_server_files, with no mapping on server cat, and start the server with PGCOLUMNAR_ICEBERG_REST_TOKEN set to the valid token. (1) As ice_r, iceberg_rest_table_location('cat','db','events') gives 28000, and the fixture request log shows no new loadTable request. (2) As…
  • pgcolumnar.expire deletes rows and must refuse a role that does not own the table ('you must own the table'). (docs-claims; docs/how-to.md:296; src/columnar_vacuum.c:2368 (PgColumnarRequireTableOwnerByOi…)
    Arm to add: Both twins of native_ownership: add "expire('n')" to OWNER_ONLY and to the refused calls. First, as the owner, run set_options('n', ttl_column => 'ts', ttl_interval => '1 day') on a table with a timestamptz column and aged rows, so a missing gate would really delete. Arm 'non-owner refused: expire' expects SQLSTATE 42501 (pytest: expect.sqlstate) and then checks count(*) FROM …
  • parallel_copy requires INSERT on the target, and parallel_export_parquet requires SELECT on the target. Each check is separate from the server-file r… (docs-claims; docs/sql-reference.md:749 (INSERT) and :823 (SELECT); src/columnar_parallel_cop…)
    Arm to add: Shell (test/import_export_privilege.sh, no pytest twin yet): reuse the attacker role, which holds schema USAGE, EXECUTE and both server-file roles and has no table grant. Add 'parallel_copy refuses a caller with no INSERT on the target' (SELECT pgcolumnar.parallel_copy('target', '', 2); expect 'permission denied for table', with count(*) of the target un…
  • pgcolumnar.expire refuses a ttl_column that is not date, timestamp or timestamptz (42804) and a ttl_column that no longer exists (42703). set_options… (error-paths; src/columnar_vacuum.c:2403-2410 (undefined column), src/columnar_vacuum.c:2471-…)
    Arm to add: In ttl_expire.sh and test_ttl_expire.py: (a) create ttl_int (k int, ts int) USING pgcolumnar with several row groups, including negative and small values. Call set_options(ttl_column => 'ts', ttl_interval => '1 day'), which must be accepted. Then SELECT pgcolumnar.expire('ttl_int') -> 42804, and count(*) is unchanged. (b) On a timestamptz fixture with a declared retention, run…
  • pg_read_server_files gate in icefdwBeginForeignScan (42501 'must be superuser or a member of the pg_read_server_files role to read an Iceberg table')… (error-paths; src/columnar_iceberg_fdw.c:1388 (executor gate); src/columnar_iceberg_fdw.c Get…)
    Arm to add: In iceberg_fdw.sh and test_iceberg_fdw.py, create role ice_nofile NOSUPERUSER LOGIN and GRANT SELECT ON the existing Iceberg foreign table. Arm A: SELECT count(*) as ice_nofile -> SQLSTATE 42501. Add a premise that the same query as superuser returns the fixture's row count. Mutation: delete the has_privs_of_role block at iceberg_fdw.c:1388; the arm then returns the count. Arm…
  • A non-superuser must not borrow the server's ambient PGCOLUMNAR_ICEBERG_REST_TOKEN when it has no token mapping. That is the 28000 'iceberg: no beare… (error-paths; src/columnar_iceberg_rest.c:203-215 (rest_resolve_server ambient check); src/co…)
    Arm to add: In iceberg_rest_server.sh and a new pytest twin, after pg_restart_env sets a valid PGCOLUMNAR_ICEBERG_REST_TOKEN (line 223), create role rc NOSUPERUSER. GRANT pg_read_server_files, USAGE ON SCHEMA pgcolumnar and USAGE ON FOREIGN SERVER cat TO rc. Give rc no mapping. Arm 1: as rc, SELECT pgcolumnar.iceberg_rest_table_location('cat','db','events') -> 28000. Control: the same cal…
  • pgcolumnar.enable_row_update_lock: no test sets or reads it, so the documented off branch never runs and nothing proves the setting gates the lock. T… (gucs; src/columnar_tableam.c:4400; src/columnar_row_lock.c:246; docs/configuration.md…)
    Arm to add: Shell, in update_conc.sh: open session A with BEGIN; UPDATE t_col SET v=v+1 WHERE id=1; and hold it with pg_sleep, using the PSQL_BG pattern from advisory_lock_class.sh. From the control session, read pg_locks WHERE locktype='advisory' AND objsubid=104 (PGCOLUMNAR_LOCKCLASS_ROW_IDENTITY) AND pid=. Arm 'row update takes a row-identity lock when on' expects count >= 1. Repeat…
  • pgcolumnar.row_lock_buckets: no test sets or reads it. Two documented promises are untested. (a) It is fixed at server start (PGC_POSTMASTER), becaus… (gucs; src/columnar_tableam.c:4414 (PGC_POSTMASTER at :4429); src/columnar_row_lock.c:…)
    Arm to add: Shell, in update_conc.sh: (1) Arm 'row_lock_buckets cannot be changed per session' runs SET pgcolumnar.row_lock_buckets = 1 and expects SQLSTATE 55P02. (2) Arm 'a bulk UPDATE holds at most row_lock_buckets row locks': load 200000 rows with stripe_row_limit large. In one session run BEGIN; UPDATE t SET v=v+1; then, still inside the transaction, count pg_locks WHERE pid=pg_bac…
  • pgcolumnar.rollup_source_groups(regclass) and pgcolumnar.rollup_source_retired(regclass) are SECURITY DEFINER, and PUBLIC keeps EXECUTE (no REVOKE). … (sql-objects; pgcolumnar--1.0-alpha5.sql:2427-2460 (no REVOKE for either; compare :814-821 an…)
    Arm to add: Add to rollup.sh, next to the ru_a/ru_b block (line ~393), and to the matching arm in test_rollup.py (rp_other block, ~465). As ru_b, which has no SELECT on public.own_src: SELECT count(*) FROM pgcolumnar.rollup_source_groups('public.own_src') and the same for rollup_source_retired. Expect 42501|42501. Pair it with a premise that ru_a, the owner, gets a non-error count fro…
  • pgcolumnar.rollup and pgcolumnar.rollup_group grant INSERT, UPDATE and DELETE to PUBLIC. They rely on a USING-only RLS policy, which also serves as t… (sql-objects; pgcolumnar--1.0-alpha5.sql:2405-2413)
    Arm to add: Add to both twins. As ru_b, run INSERT INTO pgcolumnar.rollup_group VALUES ('public.own_r'::regclass, 999999, 1, 0, now(), now(), false) and expect 42501. As ru_b, run UPDATE pgcolumnar.rollup SET source_storage = 0 WHERE rollup = 'public.own_r'::regclass and DELETE FROM pgcolumnar.rollup_group WHERE rollup = 'public.own_r'::regclass. Then as ru_a, own_r's catalog rows a…
  • An ALTER COLUMN TYPE that PostgreSQL performs without a rewrite but which changes the value order. int4 to oid is a binary-coercible cast, and it reo… (time-series-alpha5; src/columnar_tableam.c pgcolumnar_collations_before / pgcolumnar_forget_changed…)
    Arm to add: New arms in collation_change.sh and test_collation_change.py, with heap as the oracle in the same shape as the existing ones. Setup: 1. Create columnar oc and heap oh: (k int, c int), 3 row groups of 1000 rows each, every group holding both negative and positive c. 2. Run ALTER TABLE ... ALTER COLUMN c TYPE oid on both. Premise: pg_relation_filenode('oc') is unchanged, so …
  • **create_rollup on a source column with a non-default collation (text min/max, or a text group_by key). create_rollup builds each partials column as %…** (time-series-alpha5; pgcolumnar--1.0-alpha4--1.0-alpha5.sql:1352-1355 (min/max column built from cty…) *Arm to add:* Both twins. Setup: 1. CREATE TABLE ct (ts timestamptz, dev text COLLATE "C", s text COLLATE "C") USING pgcolumnar, with stripe_row_limit 1000. Explicit "C" differs from the default collation OID 100, so the arm does not depend on the server locale. 2. Insert 3000 rows, with dev and s mixing upper and lower case. 3. create_rollup('r_ct','ct','ts','1 hour',ORIGIN,'{dev}','{co…
  • The SECURITY DEFINER helpers rollup_source_groups(source) and rollup_source_retired(source). They read pgcolumnar.row_group, delete_vector and retire… (time-series-alpha5; pgcolumnar--1.0-alpha4--1.0-alpha5.sql:1237-1271)
    Arm to add: Both twins: rollup.sh privilege block and test_rollup.py. Setup: 1. Create role ru_b with USAGE on schema pgcolumnar and no SELECT on own_src. 2. Grant ru_b EXECUTE on both helpers explicitly, so that only the plpgsql guard can refuse. This copies entry_point_privilege's lesson about layered guards. Check these calls as ru_b: - `SELECT * FROM pgcolumnar.rollup_source_groups('p…
  • Write-side row-level security on pgcolumnar.rollup and pgcolumnar.rollup_group. Both tables GRANT SELECT, INSERT, UPDATE and DELETE TO PUBLIC, and th… (time-series-alpha5; pgcolumnar--1.0-alpha4--1.0-alpha5.sql:1215-1223 (RLS and grants), 1659-1695 (r…)
    Arm to add: Both twins: rollup.sh as_role block and test_rollup.py as_role. As ru_b, against ru_a's own_r: 1. INSERT INTO pgcolumnar.rollup_group VALUES ('public.own_r'::regclass, 999999, 1, 0, NULL, NULL, false): expect 42501 (a new row violates the row-level security policy). 2. UPDATE pgcolumnar.rollup SET source_storage = 0 WHERE rollup = 'public.own_r'::regclass: expect it to rep…
  • Two sessions insert the same key concurrently. The second inserter must block and then get unique_violation (23505), leaving exactly one row. The buc… (twin-parity; test/unique_conc.sh:382 (1b post-fix: blocked inserter got a unique_violation),…)
    Arm to add: In both twins: create a pgcolumnar table with a UNIQUE index on k. s1: BEGIN; INSERT k=1. s2 (thread): INSERT k=1, which must block. Assert this with a pg_locks wait on s2's pid before s1 COMMITs. After the commit, expect.sqlstate(err,'23505','1b post-fix: blocked inserter got a unique_violation') and expect.num(count,1,'1b post-fix: exactly one row with key 1'). Also check th…
  • Two transactions UPDATE or DELETE the same row. The losing writer must get serialization_failure (40001) and no duplicate row may survive (lost-updat… (twin-parity; test/update_conc.sh:324-333 (uu/RC columnar keeps a single row (no duplicate); …)
    Arm to add: pytest test_update_conc.py, using two psycopg connections at READ COMMITTED on a pgcolumnar table holding one row k=1. s1: BEGIN; UPDATE t SET v=v+1 WHERE k=1. s2 (in a thread): UPDATE t SET v=v+10 WHERE k=1, which blocks. s1 COMMIT. Expect: expect.sqlstate(s2_err, '40001', 'uu/RC columnar loser gets serialization_failure') and expect.num(count(*) WHERE k=1, 1, 'uu/RC columnar…
  • Crash recovery and corruption detection: - recovery.sh: committed columnar rows survive an immediate stop and redo. - native_backend_crash.sh: a back… (twin-parity; test/recovery.sh:80 (s1 recovery ran / s1 col count / s2 col count unchanged); …)
    Arm to add: pytest recovery: insert N rows into a pgcolumnar table and commit. Stop the cluster with pg_ctl -m immediate (pgc_cluster has Cluster.stop/start; give it an immediate-mode stop for this test). Start it and expect.num(count(*), N, 's1 col count'). Run the same against a heap mirror as the oracle. Corruption: overwrite column_chunk.byte_length for one chunk through the catalog a…
  • Catalog-driven sweep: every relation-taking C entry point has a decided privilege bar. An unprivileged caller holding EXECUTE gets 42501 from the C c… (twin-parity; test/entry_point_privilege.sh:274 (no relation-taking C entry point is still un…)
    Arm to add: pytest twin: query pg_proc for pgcolumnar functions with proargtypes[0]='regclass'::regtype and prolang = C. For each function, as a role holding EXECUTE but no SELECT on a fixture table, call it and expect.sqlstate(err,'42501',f'{fn} refuses an unprivileged caller with 42501'), parametrized on the name. Add a premise that the owner's call succeeds. Add a coverage arm: the set…
  • Import and export functions must not bypass grants or row-level security. import_export_privilege.sh: import_parquet/import_arrow refuse INSERT into … (twin-parity; test/import_export_privilege.sh:99; test/rls_direct_storage.sh:113 and the foll…)
    Arm to add: Extend the UNDER_POLICY parametrize idiom into a new test_rls_direct_storage.py: export_parquet, export_arrow, parallel_export_parquet, import_parquet, import_arrow and parallel_copy each give expect.sqlstate(err,'42501',name) for a role holding SELECT/INSERT and EXECUTE but restricted by a policy. Then os.path.exists(outfile) must be False ('no export file was written for the…
  • Maintenance and debug entry points check ownership BEFORE taking a lock, and refuse non-owners. vacuum_lock_privilege.sh: vacuum, vacuum_sorted, clus… (twin-parity; test/vacuum_lock_privilege.sh:77; test/vm_privilege.sh:115; test/debug_hook_pri…)
    Arm to add: Lock ordering: s1 holds ACCESS SHARE on t in an open transaction. As a non-owner with EXECUTE, call pgcolumnar.vacuum('t') with lock_timeout='200ms'. Expect expect.sqlstate(err,'42501','vacuum refuses a non-owner before taking the exclusive lock'), not 55P03. Parametrize the same arm over vacuum_sorted, cluster, add_projection, drop_projection, recluster. vm_privilege: an unpr…
  • After the twin rule, fixes for backend aborts and catalog leaks landed with shell arms only: - A partitioned columnar table aborts the backend in four entry points: PgColumnarIsColumnarRelation tests relam and never relkind #1259 (a267bb1): a partitioned parent with relam=pgcol… (twin-parity; test/inheritance.sh:151-159; test/parquet_import.sh:243; test/phase5.sh:326; te…)
    Arm to add: Both twins, PG17+ only (the shell arm skips below 17, fix: import_parquet segfaults on a partitioned columnar parent (#1263) #1264): CREATE TABLE pp (a int) PARTITION BY RANGE (a) USING pgcolumnar, plus one leaf. - get_storage_id('pp') and add_projection('pp','p1',ARRAY['a']) each raise a refusal. - Afterwards SELECT 1 on the same connection succeeds ('and the cluster is still up after it'). - import_parquet into pp is refused, and a HEAP target …
  • Userinfo in a caller-written URL is refused (22023) on every path: read_parquet http and s3:// bucket authority, gs://, the s3 read and write paths, … (twin-parity; test/objstore_userinfo.sh:65 (read_parquet refuses userinfo (22023, the parse g…)
    Arm to add: New test_objstore_userinfo.py, parametrized over (func, url): read_parquet('http://u:p@127.0.0.1:1/x.parquet'), read_parquet('s3://u:p@mybucket/x.parquet'), export_parquet('t','s3://u:p@mybucket/o.parquet'), export_arrow(...). Each gives expect.sqlstate(err,'22023',name) and expect.contains(msg,'userinfo',...). Add controls: 's3://mybucket/x.parquet' reaches the endpoint deman…
  • Object-store hardening has no twin: - objstore_crlf.sh: a CR/LF in a URL path or a REST catalog_uri is rejected before any request is sent, so reques… (twin-parity; test/objstore_crlf.sh:30; test/objstore_allowlist.sh:85; test/objstore_credenti…)
    Arm to add: Allow-list: with objstore_allowed_endpoints unset, read_parquet('http://127.0.0.1:/x.parquet') gives expect.sqlstate(err,'42501','default: an http read is refused 42501'), and the message names the GUC. Credentials: CREATE SERVER ... OPTIONS (secret_access_key 'x') gives 'HV00D'. A non-superuser ALTER USER MAPPING ... credentials_required 'false' gives '42501'. CRLF: rea…

Medium (43)

  • A statement must not see rows it wrote itself, even after it flushes stripes mid-way: INSERT INTO t SELECT FROM t, and UPDATE of every row of a table bigger than stripe_… (core-am; phase3.sh:193-196 (the weak check); columnar_tableam.c:605-613 (a sca…)
  • No megabyte-scale values. The largest tested value is 70 KB (parallel_copy.sh:149), then 12 KB (differential.sh:74) and about 3.2 KB (native_toasted_write.sh:27). Also u… (core-am; src/columnar_tableam.c:1355-1359 (no toast table; values are stored i…)
  • At wal_level=minimal, a table created or truncated in the same transaction skips WAL, because the storage code branches on RelationNeedsWAL, and depends on the pending s… (core-am; src/columnar_storage.c:104/112 (metapage log_newpage, unconditional) …)
  • Encoder and zone-map coverage for types missing from the differential matrix: - fixed-width pass-by-reference of unusual lengths: timetz (12), macaddr (6), macaddr8 (8, … (core-am; src/columnar_encoding.c:295-305 and 2584-2604 (fixed-width paths keye…)
  • Maintenance functions that roll back or crash part-way: compact_rewrite, recluster, compact and pgcolumnar.vacuum inside a transaction that rolls back, and an immediate … (core-am; src/columnar_vacuum.c (rewrite_one_group ~346, pgcolumnar_recluster_o…)
  • REINDEX is documented as the way stale index entries are reclaimed, but nothing runs it. CREATE INDEX CONCURRENTLY and REINDEX CONCURRENTLY reach index_validate_scan, wh… (core-am; docs/limitations.md:777-781; src/columnar_tableam.c:2547-2552 (COLUMN…)
  • Two partition shapes are untested. First, an UPDATE that moves a row between columnar partitions (row movement: delete in one partition, insert in another), alone and ra… (core-am; src/columnar_tableam.c pgcolumnar_tuple_delete and tuple_update (chan…)
  • RLS on the query paths: custom scan, vectorized and grouped aggregates, covering projection scan, index-only scan, parallel scan. Also leakproof ordering: no non-leakpro… (core-am; src/columnar_customscan.c:1375 (plan qual from clauses); 3071/3180/33…)
  • Rolling back to a savepoint, or failing a statement, after the statement has already flushed stripes mid-way. Three things are untested: - what a sequential scan and a v… (core-am; src/columnar_tableam.c:2741-2752 (subxact abort); src/columnar_write_…)
  • Beyond the same-session cases in prepared_writes, these are untested: - what other sessions see while a transaction is prepared; - unique-key and row-update locks carrie… (core-am; src/columnar_tableam.c:2666-2700 (PRE_PREPARE/PREPARE flush and reset))
  • The settings in configuration.md have the documented defaults and contexts. enable_end_truncation needs superuser to set. row_lock_buckets is fixed at server start. The … (docs-claims; docs/configuration.md:6-11, :77 (enable_end_truncation superuser), :1…)
  • expire refuses a retention column that is not date, timestamp or timestamptz (42804). It treats a half declaration (ttl_column without ttl_interval, or the reverse) as n… (docs-claims; docs/sql-reference.md:252-254 and :294-296; docs/how-to.md:295-298; s…)
  • CREATE INDEX CONCURRENTLY is not supported on a columnar table (refused through the concurrent validate path). (docs-claims; docs/limitations.md:781-782; src/columnar_tableam.c:2547-2552 (COLUMN…)
  • A read uses the scanning user's mapping first, then a PUBLIC mapping. (docs-claims; docs/sql-reference.md:1386-1391; src/columnar_parquet_reader.c around…)
  • create_rollup refuses a ts_column that is not timestamptz (22023). (docs-claims; docs/sql-reference.md:650; pgcolumnar--1.0-alpha5.sql:2498-2503)
  • import_arrow refuses dictionary-encoded files (0A000) and compressed record-batch bodies (0A000). The existing dictionary arm uses a text column and expect_error, which … (error-paths; src/columnar_arrow.c:2403-2407 (DictionaryBatch), src/columnar_arrow.…)
  • A date32 or date64 value outside PostgreSQL's date range is refused with 22008 'Arrow date value out of range for type date'. The time and timestamp siblings are tested,… (error-paths; src/columnar_arrow.c:1879-1883)
  • iceberg_data_files refuses a data manifest whose entries are delete files or have status=2 (DELETED). Only the manifest-level refusal (content=1 in the manifest list) is… (error-paths; src/columnar_iceberg.c:786-795)
  • The grouped vector aggregate's sum(float8) and sum(real) must raise 'value out of range: overflow' (22003) when two finite inputs add to infinity, as core's float8pl and… (error-paths; src/columnar_vector.c:3198-3220 (called at 3330-3334))
  • An unlogged columnar table is refused (0A000 'unlogged columnar tables are not supported'). docs/limitations.md:658 says CREATE TABLE refuses an unlogged columnar table.… (error-paths; src/columnar_tableam.c:1236-1239; docs/limitations.md:658)
  • The pg_read_server_files gate on iceberg_rest_table_location, iceberg_rest_scan, iceberg_rest_namespaces and iceberg_rest_tables (42501 '... to read a REST catalog'). Th… (error-paths; src/columnar_iceberg_rest.c:676, 711, 762, 835)
  • A parquet FDW user mapping that carries only half a credential (access_key_id without secret_access_key, or the reverse) is refused with 28000 'carries only half a crede… (error-paths; src/columnar_parquet_reader.c:4789-4796)
  • pqfdwGetForeignRelSize stat()s the file only when the caller has pg_read_server_files (Server-file privilege model has drifted: docs claim superuser, two functions require only a role, and the boundary test covers neither #330). An unprivileged planner gets the flat default estimate and cannot probe whe… (error-paths; src/columnar_parquet_reader.c:4385-4397)
  • pgcolumnar.bulk_parallel_writer can be set by any user (PGC_USERSET), and its description promises 'Safe even if set by hand: the skip fires only when the storage row is… (gucs; src/columnar_tableam.c:4232-4245; guard at src/columnar_metadata.c:21…)
  • The UPDATE/DELETE row-identity lock (class 104) is never checked for being unreachable from SQL. advisory_lock_class.sh covers only the locks an INSERT takes, which are … (gucs; src/columnar_row_lock.c:270-276 (SET_LOCKTAG_ADVISORY(..., PGCOLUMNAR…)
  • pgcolumnar.enable_end_truncation is superuser-only (PGC_SUSET), and docs/configuration.md:88 says 'Requires superuser to set'. No test shows that a non-superuser is refu… (gucs; src/columnar_tableam.c:4157-4166 (PGC_SUSET at :4163); docs/configura…)
  • pgcolumnar.analyze(rel, columns) refuses a named column that does not exist: 'column "%" does not exist in %'. The body says a silent no-op here is the failure that look… (sql-objects; pgcolumnar--1.0-alpha5.sql:1549-1565)
  • The partition_create_ahead refusals before any DDL: (a) '% is partitioned on %, not on a timestamp' (55000), (b) '% is not RANGE-partitioned on one column' (55000), (c) … (sql-objects; pgcolumnar--1.0-alpha5.sql:2080-2097)
  • create_rollup's refusal of a ts_column that is not timestamptz: 'column "%" of % is not a timestamptz column' (22023). Without it, a timestamp column would be bucketed… (sql-objects; pgcolumnar--1.0-alpha5.sql:2498-2504)
  • set_options refuses an unknown compression name: 'unknown columnar compression "%"'. The C reader maps an unrecognised name to -1 and falls back to the instance default … (sql-objects; pgcolumnar--1.0-alpha5.sql:532-555)
  • tier_partition refuses a server that does not exist: 'server "%" does not exist' (42704). Without this branch, the ELSIF compares NULL <> 'pgcolumnar_parquet', which is … (sql-objects; pgcolumnar--1.0-alpha5.sql:2934-2941)
  • How a rollup interacts with the maintenance daemon. how-to.md:646-648 promises: 'When pgcolumnar.expire, or the maintenance daemon, drops old rows of the source, the rol… (time-series-alpha5; src/columnar_autovacuum.c:238-282 (av_expire_one), 499-501; pgcolumna…)
  • how-to.md:333-337 documents that for a date or timestamp retention column, 'The daemon uses the server's TimeZone setting'. A session's zone, or a database-level ALTER … (time-series-alpha5; docs/how-to.md:333-337; src/columnar_vacuum.c pgcolumnar_expire TIMES…`)
  • Whether a rollup survives pg_dump and pg_restore. Only pgcolumnar.options and pgcolumnar.projection_declaration are registered with pg_extension_config_dump, and pgcolum… (time-series-alpha5; pgcolumnar--1.0-alpha5.sql:104, 133 (the only pg_extension_config_dum…)
  • The window in which the alpha5 library runs against alpha4 SQL, between make install plus restart and ALTER EXTENSION UPDATE (docs/installation.md steps 1-3). PgColumnar… (time-series-alpha5; src/columnar_metadata.c:2019-2032 (retired_group deleted unconditiona…)
  • What happens to a rollup when its source is removed or replaced. The rollup catalog stores source regclass with no pg_depend entry and no drop hook (grep -n rollup sr… (time-series-alpha5; pgcolumnar--1.0-alpha4--1.0-alpha5.sql:1186-1201 (catalog, no depende…`)
  • tier_partition, partition_create_ahead and the statements partition_drop_plan returns all run as the caller (none is SECURITY DEFINER). No test ever calls them as a non-… (time-series-alpha5; pgcolumnar--1.0-alpha4--1.0-alpha5.sql:811 (partition_create_ahead), …)
  • docs/configuration.md documents two settings that no test in either harness exercises: - pgcolumnar.enable_row_update_lock: 'Off restores the prior behavior'. - pgcolumn… (twin-parity; docs/configuration.md:114-115; src/columnar_row_lock.c:72-73, :246, :…)
  • Shell arms added after 2026-09-09 with no pytest counterpart: - native_recluster: 'unique still enforced, by SQLSTATE 23505 and not by any failure'. - alter_am_cleanup: … (twin-parity; test/native_recluster.sh:91; test/alter_am_cleanup.sh:235; test/nativ…)
  • Two problems with the runtime filter twins: - The shell's 'fact-qual conjunction equals heap' arm (a key qual k>100 plus a non-key qual alongside the runtime interval, l… (twin-parity; test/native_join_runtime_filter.sh:295-298 (fact-qual conjunction equ…)
  • These suites have no twin: - fk_referencing.sh: a foreign key referencing a columnar table is refused, the error says why, no table is left behind, and ALTER ADD CONSTRA… (twin-parity; test/fk_referencing.sh:54; test/truncate_cleanup.sh:58; test/native_d…)
  • These suites have no twin: - pg_dump_roundtrip.sh: projections and options survive dump and restore, and a dropped projection is not resurrected. - pg_upgrade.sh: rows a… (twin-parity; test/pg_dump_roundtrip.sh:87; test/pg_upgrade.sh:171; test/replicatio…)
  • 225 recording shell suites have no pytest twin, and no list declares them. COMPLETE + INCOMPLETE are checked only against pairs that already exist on disk with the same … (twin-parity; test/pytest/test_compare_to_bash.py:88-170 (COMPLETE/INCOMPLETE), :14…)

Low (13)

  • The changelog promises that expire, compact_rewrite, VACUUM and recluster each recompute the column extent before commit, so the extent is never narrower than the data. (changelog-features; CHANGELOG.md:39-53; src/columnar_metadata.c:1058-1065 (one mark in Pg…)
  • ALTER TABLE forms that scan existing rows through the AM: SET NOT NULL, ADD PRIMARY KEY on populated data, ADD CONSTRAINT ... CHECK NOT VALID followed by VALIDATE CONSTR… (core-am; src/columnar_tableam.c:597-613 (the scan begin used by ATRewriteTable…)
  • Refusals with no test: - CREATE UNLOGGED TABLE ... USING pgcolumnar and ALTER TABLE ... SET UNLOGGED (documented); - ALTER TABLE ... SET TABLESPACE (refused in code, und… (core-am; src/columnar_tableam.c:1236-1239 (unlogged), 2301-2304 (relation_copy…)
  • pgcolumnar.row_tid refuses a row number below 1 (22003). partition_drop_plan refuses a NULL cutoff (22023) in both overloads. (docs-claims; docs/sql-reference.md:672 and :640; src/columnar_storage.c:684-688; p…)
  • compact_rewrite's max_groups caps how many row groups one call rewrites, and the function returns that number. (docs-claims; docs/sql-reference.md:275-277; docs/how-to.md:284; src/columnar_vacuu…)
  • A projection sorted on a type with no btree ordering (json, point) is refused with 0A000 'cannot sort projection on column of type'. add_projection does not check this, … (error-paths; src/columnar_write_state.c:3581-3586)
  • create_rollup refuses a ts_column that is not timestamptz (22023 'is not a timestamptz column'). Every refusal at creation is tested except this one. rollup.sh:134 check… (error-paths; pgcolumnar--1.0-alpha5.sql:2498-2502)
  • partition_create_ahead refuses width <= 0 or ahead < 0 (22023), a parent that is not RANGE-partitioned on one column (55000), and a key that is not a timestamp (55000). … (error-paths; pgcolumnar--1.0-alpha5.sql:2080-2096)
  • No test ever sets pgcolumnar.compression_level away from its default of 3. The session value is copied into every write state and backfill (columnar_write_state.c:681, :… (gucs; src/columnar_tableam.c:3936-3944; src/columnar_write_state.c:681,3699)
  • pgcolumnar.tier_fault_after has a check hook that refuses any value other than a step name, 'so a typo cannot leave a test believing it injected a fault it did not'. No … (gucs; src/columnar_tableam.c:3847-3856 (pgcolumnar_check_tier_fault_after),…)
  • partition_drop_plan(parent, cutoff) refuses a NULL cutoff: 'cutoff must not be NULL' (22023), in both the timestamptz and timestamp overloads. Without it, upper_bound <… (sql-objects; pgcolumnar--1.0-alpha5.sql:2306-2308, 2335-2337`)
  • Three remaining create_rollup and rebase_rollup refusals have no arm: 'group_by column "%" does not exist' (22023), '% of a % column cannot be folded' (sum or avg over a… (sql-objects; pgcolumnar--1.0-alpha5.sql:2535-2538, 2559-2565, 2859-2862)
  • The month and year width path. With no existing partition, the start is date_trunc('month', now()), or localtimestamp for a timestamp key, and each next bound is lo + … (time-series-alpha5; pgcolumnar--1.0-alpha4--1.0-alpha5.sql:888-893 and 937-942 (month bra…)

Each item's full search evidence and suggested arm is in the audit's JSON file. I'll attach the relevant part to each PR. Claim an item here before starting.

Activity

  1. OffgridwithJD commented on Oct 13, 2026

    @OffgridwithJD
    Collaborator

    Claiming the items in my features (partition lifecycle and tiering), as one batch:

    • partition_create_ahead refusals before any DDL: a key that is not a timestamp, a parent not RANGE-partitioned on one column, width <= 0 and ahead < 0. These are the two entries at sql-objects and error-paths.
    • partition_drop_plan refuses a NULL cutoff, in both overloads (the docs-claims and sql-objects entries; I'm leaving row_tid to its owner).
    • tier_partition refuses a server that does not exist (42704).
    • pgcolumnar.tier_fault_after's check hook refuses a value that is not a step name.
    • The month and year width path of partition_create_ahead.

    Each one is red first, in both twins, under a mutation that removes the branch it tests. The tier/partition "run as the caller" item (time-series-alpha5) is a larger design question, so I'm leaving it open for now.

  2. OffgridwithJD commented on Oct 14, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd, claiming a second batch, in features I built (rollups) and next to my ttl work. Each item is red first, in both twins, under a named mutation.

    Rollups, privilege and refusals:

    • rollup_source_groups and rollup_source_retired: SECURITY DEFINER with PUBLIC EXECUTE. First I'll probe whether a role with no SELECT on the source can read through them. If it can, that's a fix plus its arm, not just an arm. (High, the sql-objects and time-series entries.)
    • Write-side RLS on pgcolumnar.rollup and pgcolumnar.rollup_group: another role's INSERT, UPDATE and DELETE. (High, both entries.)
    • create_rollup on a source column with a non-default collation. (High.)
    • create_rollup refusing a ts_column that is not timestamptz (22023), and the three remaining create_rollup and rebase_rollup refusals. (Medium and low.)

    expire:

    • A non-owner is refused (42501) on a table with a real declared retention, with the row count unchanged. (High.)
    • A retention column that is not date or a timestamp (42804), one that no longer exists (42703), and the half-declaration behaviour. (High and medium.)

    I'm leaving the rollup lifecycle items (dump/restore, source dropped, the daemon) for after this batch.

  3. jdatcmd commented on Oct 14, 2026

    @jdatcmd
    CollaboratorAuthor

    Claiming (jdatcmd): the core-am and settings items, in this order, red first, both twins. The plan with proof criteria is on #1283.

    1. ON CONFLICT DO NOTHING / DO UPDATE;
    2. TRUNCATE rollback;
    3. the subtransaction ExecutorEnd flush;
    4. the unique race after an uncommitted DELETE rolls back;
    5. CREATE INDEX under an older RR snapshot;
    6. enable_row_update_lock / row_lock_buckets;
    7. SSI: an anomaly test first, then an owner decision.
  4. added a commit that references this issue on Oct 14, 2026
  5. OffgridwithJD commented on Oct 14, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd, progress on my half of #1341.

    PRs open:

    In progress, red first:

    • import_arrow's dictionary refusal, asserted by SQLSTATE and message rather than by any error, plus a compressed-body arm.
    • A Parquet user mapping holding half a credential, refused with 28000 before any request.

    Handed to you: the Iceberg and REST privilege items (see #1283).

    Still claimed by me:

    • create_rollup on a non-default collation;
    • expire's half declaration;
    • the remaining object-store and import twin-parity items.
  6. 335 remaining items

  7. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd My open chain, each stacked on the one above, in merge order:

    order PR what review
    1 #1450 item 66: the upgrade window's missing-table error names ALTER EXTENSION UPDATE approved
    2 #1452 fk_referencing twin: a referenced table may still be set to a row store needs review
    3 #1453 truncate_cleanup twin; the shell needed no change needs review
    4 #1454 native_dml twin: the min/max arm can now see a zone-map answer that ignores deletes needs review
    5 #1455 native_dict_underfill twin: a crash can no longer pass the survival arm needs review
    6 #1456 native_decode_gating twin: the counters can now see a double count and a deleted row, and the fixture no longer depends on the gating it tests needs review
    7 #1457 native_decode_gate_width twin: the unshipped settings are proven absent by SQLSTATE needs review

    That covers all four native_d* suites without a twin, so the question in my last comment is moot.

    Each PR has red-first by mutation in both twins, five-major runs, and a ledger seed checked against the gate. Each restates on its parent's numbers, so merged in order they need no restate, unless main moves underneath them. I'll hold off stacking more until you've had a pass at these. #1451 goes after them, as you asked.

    🤖 Generated with Claude Code

  8. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    Correction to the table above: #1452 through #1456 are already approved, thanks. Only #1457 is new.

    🤖 Generated with Claude Code

  9. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd I went past my "hold off": the user asked me to continue with the two-cluster suites. Two more are on top of #1457, in merge order:

    order PR what review
    8 #1458 pg_dump_roundtrip twin: the index arm takes the index, and the sort_by arm checks the order approved, thanks
    9 #1461 pg_upgrade twin: the shell's index arm passed with c_id dropped, because the planner took the columnar scan with no post-upgrade stats new

    #1461 adds no ledger rows, since pg_upgrade.sh records nothing, so it costs your #1459 restate nothing. Its twin needs a second major in PGC_UPGRADE_FROM_PG_CONFIG. In the matrix it declines and is listed for 15–19 in expected_unrunnable.txt. I ran it on 15→16, 16→17, 17→18 and 18→19, 16/16 each.

    I also approved #1459 and #1460, both reproduced on my own build.

    🤖 Generated with Claude Code

  10. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd Status, and one question.

    Item 129 is complete on my side: pg_dump_roundtrip (#1458), pg_upgrade (#1461) and replication (#1463), the last two approved, thanks. #1461's root fix is in 70c186ee.

    Item 70: #1465 twins native_recluster. Its index arm couldn't see recluster's visibility-map clear: with PgColumnarVMClearForRowRange removed, the old shell was 12/12 green, because no VM bit was ever set. A VACUUM first and an index-only count make that 81409 for 40960. It's stacked on #1463. alter_am_cleanup is next, on top of it.

    Question: item 70's text is cut off after test/native_recluster.sh:91; test/alter_am_cleanup.sh:235; test/nativ…. Do you know which suite the third one is? If not, I'll pick the native_* suites without a twin whose shell arms postdate 2026-09-09.

    Items 23, 24 and 25 (the unique_conc, update_conc, recovery, native_backend_crash and corruption twins) are on main (#1438 … #1446), and item 29 is #1448. Their boxes could be ticked.

    🤖 Generated with Claude Code

  11. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd My chain, for when you're ready to merge it. Each PR is stacked on the one before it, so merged in order they need no restate. All are approved except #1469, which is new.

    order PR what
    1 #1450 item 66: the upgrade window's missing-table hint
    2–7 #1452 #1453 #1454 #1455 #1456 #1457 fk_referencing, truncate_cleanup, native_dml, native_dict_underfill, native_decode_gating, native_decode_gate_width
    8–10 #1458 #1461 #1463 pg_dump_roundtrip, pg_upgrade, replication (item 129)
    11–13 #1465 #1467 #1468 native_recluster, alter_am_cleanup, native_reclaim (item 70)
    14 #1469 native_repack: "the supported alternative" must reclaim

    Merging #1450 through #1468 now would let me stop stacking. Every new twin otherwise sits on top of 15 open PRs, and a restate grows with it.

    #1451 and #1459 go after the chain, as you planned. Nothing in the chain touches their files except the budget census, which #1459 already says it will restate.

    🤖 Generated with Claude Code

  12. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd #1470 landed under my chain, so I've restated all 18 branches onto main db561684 and force-pushed them with a lease on each old SHA. Every one of them is MERGEABLE again, and the approvals held.

    How I checked it:

    The PR bodies still quote their pre-restate census, one higher on never. The commits and files are right.

    PR new head
    #1450 7ac79e58
    #1452 4ee6e1fd
    #1453 50a8c31f
    #1454 091f9826
    #1455 2548d989
    #1456 fb1f6e23
    #1457 0cb4e37a
    #1458 1da9bbfe
    #1461 d70e5d6f
    #1463 3f27e479
    #1465 1ef6ec67
    #1467 62c80a43
    #1468 ffa62b2c
    #1469 ef24df80
    #1471 9f3548ac
    #1472 93654fb5
    #1473 d1221247
    #1474 46db3790

    The merge order is unchanged: #1450 first, then up the stack.

    🤖 Generated with Claude Code

  13. OffgridwithJD commented on Oct 16, 2026

    @OffgridwithJD
    Collaborator

    @jdatcmd A correction to my restate note above. The restate dropped two edits to test_compare_to_bash.py: the loop-reader guard's file list, which #1468 and #1469 extend with native_reclaim and native_repack. My replay tool restates only that file's COMPLETE list. So the six top branches failed test_the_loop_reader_invents_nothing_in_this_corpus. The guards caught it on the next PR.

    I've re-replayed and re-pushed those six, and then ran the full no-cluster guard set (438 passed) at all 18 tips, not only the top. The census at each tip still equals its tsv, and the code is unchanged.

    PR head now
    #1468 8c74c45c
    #1469 0692d956
    #1471 abc7c8da
    #1472 79eb5cce
    #1473 80af30a5
    #1474 5b031586

    #1450 through #1467 keep the heads in my previous comment. A new PR, #1476 (native_parquet_schema), sits on top.

    🤖 Generated with Claude Code

  14. jdatcmd commented on Oct 16, 2026

    @jdatcmd
    CollaboratorAuthor

    @OffgridwithJD, a proposed split of the 10 open boxes, to resolve this issue, by each box's first words. Correct anything.

    Mine:

    Yours, continuing your item-74 twin work:

    If you've already started any of mine, say so and I'll drop it.

  15. jdatcmd commented on Oct 16, 2026

    @jdatcmd
    CollaboratorAuthor

    @OffgridwithJD, a heads-up for your next twin PR. #1509 adds test/pytest/unported_suites.txt (168 stems) and a guard that holds it both ways. Once it lands, a PR that adds test_<stem>.py must also remove that stem's line from the file. The guard names the stem if you forget. One stem per line, so two ports don't conflict there.

  16. jdatcmd commented on Oct 16, 2026

    @jdatcmd
    CollaboratorAuthor

    Ticked two boxes:

    In review:

    About the "Shell arms added after 2026-09-09" box: its text is truncated in the issue itself. The two arms it names (native_recluster's 23505, alter_am_cleanup's DROP EXTENSION) have their pytest counterparts, and both suites are COMPLETE. The rest of what it lists is, I believe, the INCOMPLETE entries (native_skip, now #1510; native_agg, native_format, large_values, range_pruning, iceberg_data_files, native_upgrade_converge). I'm porting those next.

  17. jdatcmd commented on Oct 16, 2026

    @jdatcmd
    CollaboratorAuthor

    Ticked "Two problems with the runtime filter twins". #1512 fixed both, checked on main at d3b237ec:

    • The fact-qual conjunction arm now has a pytest counterpart: "fact-qual conjunction equals heap" and "fact-qual plan has coordinator" are in test_native_join_runtime_filter.py.
    • The stem mismatch: the twin is now test_native_join_runtime_filter.py. Its stem is in COMPLETE and not in unported_suites.txt. The four arms named missing by literal name are all present, as are the "plan has coordinator" names. test_compare_to_bash.py passes 41/41 on a clean checkout of main, which grades every COMPLETE stem to zero missing names.
  18. jdatcmd commented on Oct 16, 2026

    @jdatcmd
    CollaboratorAuthor

    Reopened: closed by accident. Merging #1509 closed this tracker, because its body began "Fixes #1341's entry …". GitHub reads "Fixes #1341" as a closing keyword and ignores the possessive. 7 boxes are still open. I reopened #1339 earlier today for the same reason, and I now grep each PR body for closing keywords before merging.

  19. jdatcmd commented on Oct 17, 2026

    @jdatcmd
    CollaboratorAuthor

    Progress on the box "Shell arms added after 2026-09-09 with no pytest counterpart" (mine), by its INCOMPLETE suites:

    Suite State
    range_pruning merged in #1529, with a follow-up on collation choice in #1532
    native_format #1531, in review
    iceberg_data_files #1533, in review
    large_values already grades with nothing missing. It stays INCOMPLETE on purpose: its opt-in over-1-GB arm has no SKIP verdict in the pytest layer.
    native_upgrade_converge not started. It stages install scripts into each major's share/extension with a backup and restore, so the pytest twin needs that surgery done safely. I'll take it after the queue above clears.

    Shell defects found and fixed while porting:

    🤖 Generated with Claude Code

  20. jdatcmd commented on Oct 17, 2026

    @jdatcmd
    CollaboratorAuthor

    Gap found in #1531's review: no arm catches the fetch path's format-check cache reset.

    PgColumnarDiscardFetchCache (columnar_reader.c) resets columnarFetchFmtOk. With that line removed, both twins of native_format stay green on PG17, measured on daffef31.

    Why: each reading in both twins now starts a new backend, as the shell's psql per statement does. A per-session cache never carries from one reading to the next.

    What an arm would need: in one session, fetch a row from a table stamped 1. Then change the stamp to 3, discard the cache the way the server does, and fetch again. The second fetch must be refused with 0A000.

    Not started. It needs its own .sh and pytest pair.

    🤖 Generated with Claude Code

  21. jdatcmd commented on Oct 17, 2026

    @jdatcmd
    CollaboratorAuthor

    Follow-ups from the reviews of #1531 and #1533. These are non-blocking. Each needs a change to both twins.

    iceberg_data_files: the 42501 arm reads only the SQLSTATE.

    • A schema denial is also 42501. With the gate off and the twin's GRANT USAGE ON SCHEMA removed, the arm passed on "permission denied for schema pgcolumnar" (measured by OffgridwithJD).
    • So the arm reaches the gate only while that grant stays in the fixture.
    • Fix: add a premise has_schema_privilege('icedf_unpriv', 'pgcolumnar', 'USAGE'), or match the message for pg_read_server_files.
    • Also drop the GRANT EXECUTE. PUBLIC already holds EXECUTE, so it does nothing.

    native_format: tidying in the twin.

    • FETCH_GUCS is dead now that the RESET is gone.
    • The _refusal docstring says a WARNING "is a failed reading". In fact psycopg does not raise a WARNING, so it reads as ("ok", ""). The arm still goes red, but for a different reason.
    • _four_paths joins the readings into one string, so a query_error() in any position after the first reads as a text mismatch, not a VacuityError.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions