CommitFest 7365 Review: Partial Indexes on System Catalogs

code-review · generated from canonical Markdown

Type
code-review
Source
postgresql-master
Slug
commitfest-7365-review
Tags
code-reviewcoveragepatch-reviewpostgresql
Updated
2026-10-05T18:54:19.117008+00:00
Verdict / Summaryneeds-review
Front matter
schema: review-report-v2
slug: commitfest-7365-review
source: postgresql-master
target: "CommitFest 7365: Partial indexes on system catalogs (uncommitted staged diff on master dfcf6fa7)"
base: dfcf6fa7749d1fc4660d03590f14dca7c855048c
head: dfcf6fa7749d1fc4660d03590f14dca7c855048c
diff_sha: 08e15b568004b821e8694150cf0662975324f350c3fe097b7c7e5315a5cc3a97
verdict: needs-review
blocker_counts:
  verified: 0
  unverified: 0
coverage_requirement: required
coverage_status: measured

CommitFest 7365 Review: Partial Indexes on System Catalogs

Verdict: needs-review

Blocker split: verified 0 / unverified 0. No blockers. One correctness MAJOR (misc_sanity test breakage, FIND-001) and one live-thread design objection MAJOR (FIND-002) drive the needs-review verdict per the deterministic rubric (correctness MAJOR + live objection => needs-review).

Patch Summary

This patch adds support for partial indexes on system catalogs with a restricted whitelist of predicate shapes that can be evaluated during catalog maintenance without building an EState:

The patch modifies:

Findings

FIND-001

— MAJOR (correctness): misc_sanity regression test breaks

Location: src/test/regress/expected/misc_sanity.out:97

Mechanism: The patch adds two new unique partial indexes on pg_constraint (pg_constraint_conrelid_conname_index OID 581, pg_constraint_contypid_conname_index OID 582). genbki.pl correctly suppresses pg_constraint constraint generation for partial unique indexes (the WHERE regex check at line 155), so these indexes have no backing pg_constraint entry. However, the existing misc_sanity regression test asserts that no system catalog unique index lacks a backing constraint ("There should be none"). The test's expected output was not updated.

Verification: verified by reproduction. Full make installcheck with an instrumented build: "1 of 240 tests failed" — misc_sanity.out.diff shows the 2 new unique partial indexes. Confirmed via SQL that both indexes have indisunique=true and no pg_constraint row with matching conindid. Applied the repair (updating expected output) to a scratch copy and re-ran misc_sanity: "All 1 tests passed."

Repair: Update src/test/regress/expected/misc_sanity.out to list the 2 new unique partial indexes as expected results. The test comment "(There should be none.)" should be updated to reflect that partial unique indexes intentionally lack backing constraints.

Repair validation: passed (apply-check + diff-check + targeted-test). The repair patch applies cleanly to HEAD; re-running misc_sanity with the updated expected output passes.

FIND-002

— MAJOR (correctness, cannot-verify): Live thread design objection

Location: src/backend/catalog/indexing.c:77 (overall design)

Mechanism: The patch's design approach is contested by two senior reviewers on pgsql-hackers thread 657827:

  • Tom Lane (2026-10-01): skeptical of the restricted whitelist — "we don't have partial indexes, just a hack with a small number of potential use-cases." Suggests pg_constraint is misdesigned and should be refactored via breakout catalogs instead.
  • Andres Freund (2026-10-01): questions whether the gain warrants the complexity, noting catcache negative-lookup caching may negate the benefit. Requests an actual benefiting index + syscache.

The patch author labels it "meant for experimentation, not for commit."

Verification: cannot-verify (design-acceptability objection, not a code defect). The thread is live with no resolution.

Repair: No code repair — this requires author response on pgsql-hackers addressing both reviewers' concerns, or a revised approach.

FIND-003

— MINOR (maintainability): Hardcoded operator OID

Location: src/backend/bootstrap/bootparse.y:128

Mechanism: op->opno = 608; uses a hardcoded operator OID literal for the oid <> operator instead of a named macro. The patch author explicitly acknowledges this: "dropping a hardcoded operator OID is still pending."

Verification: verified by static inspection. The cover letter lists this as pending work.

Repair: Replace literal 608 with a named constant (e.g., OID_NOT_EQUAL_OPERATOR). The exact macro name depends on project conventions; the illustrative example shows the intent.

Repair validation: partial (apply-check + diff-check + static-check). Full compile pending author confirmation of the canonical macro name.

COV-001

— MINOR (tests): Uncovered NullTest IS NOT NULL false-return path

Location: src/backend/catalog/indexing.c:164

Mechanism: Changed-code coverage identified an uncovered executable line: the NullTest IS NOT NULL false-return path in CatalogIndexPredSatisfied. When a partial catalog index has a column IS NOT NULL predicate and a catalog row is inserted where that column is NULL, line 164 (return false) should execute. The existing test only creates a contypid IS NOT NULL index on a NOT NULL column, so isnull is always false.

Verification: verified by coverage. gcov branch data for line 163 shows branch 0 (isnull true) taken 0%. Confirmed that pg_constraint.conbin is nullable and PK/UNIQUE/NOT NULL constraints have conbin=NULL. A test creating a conbin IS NOT NULL partial index + a PK table insert exercises this path.

Repair: Add a test section to catalog_partial_index.sql that creates a conbin IS NOT NULL partial index and creates a table with a PRIMARY KEY (inserting a pg_constraint row with conbin=NULL).

Repair validation: partial. Manual SQL execution confirmed the path is exercised; full pg_regress expected-output integration pending.

Verification Summary

FindingSeverityClassStatusMethod
FIND-001MAJORcorrectnessverifiedrepro
FIND-002MAJORcorrectnesscannot-verifystatic-check
FIND-003MINORmaintainabilityverifiedstatic-check
COV-001MINORtestsverifiedverified-by-coverage

Cannot-verify findings: FIND-002 is a design-acceptability objection (UNVERIFIED), not a code defect. It requires mailing-list resolution, not code verification.

Repair Validation Summary

FindingPatchValidationMethods
FIND-001provided (unified-diff)passedapply-check, diff-check, targeted-test
FIND-002waived (design-choice)waivedn/a
FIND-003provided (unified-diff)partialapply-check, diff-check, static-check
COV-001provided (unified-diff)partialapply-check, diff-check, targeted-test

FIND-001 repair is fully validated: the expected-output update applies to HEAD and the test passes with the updated output.

FIND-003 repair is partial: the structural change is correct but the exact macro name requires project-convention confirmation before compile validation.

COV-001 repair is partial: the test logic is verified by manual SQL execution but the full pg_regress expected-output integration is pending.

Changed-Code Coverage

Coverage requirement: required (4 changed instrumentable C/Y/L files)

Execution lane: host-disposable (passed)

Counter epoch: fresh (gcda reset before initdb; initdb captures bootstrap parser coverage; full installcheck captures runtime coverage)

Metrics

MetricCount
Changed executable lines83
Covered changed lines78
Compiler-uncovered changed lines5
Uncovered changed lines (semantic)5
Structural uncovered lines0
Changed branches36
Covered changed branches27
Uncovered branches9

Invariant: covered (78) + compiler-uncovered (5) = changed executable lines (83) ✓

Uncovered Lines

FileLineFunctionCoverabilityReason
indexing.c96catalog_pred_clause_supportedinfeasibleDefensive guard (neither OpExpr nor NullTest); enforced at creation
indexing.c144CatalogIndexPredSatisfiedinfeasibleDefensive elog(ERROR); enforced at creation
indexing.c164CatalogIndexPredSatisfiedcoverable-nowNullTest IS NOT NULL with NULL value; needs nullable-column test (COV-001)
bootparse.y118makeBootCatalogPredicateinfeasibleUnknown column error; requires malformed BKI
bootparse.y121makeBootCatalogPredicateinfeasibleNon-OID column error; requires malformed BKI

Uncovered Branches (9)

All 9 uncovered branches are defensive/infeasible except 1 coverable-now branch:

Non-instrumented Changes

Test Commands

configure --enable-debug --enable-cassert CFLAGS='-O0 -g'
make -j4 && make install
# Rebuild changed objects with coverage:
make -C src/backend/catalog indexing.o CFLAGS='-O0 -g --coverage -fprofile-arcs -ftest-coverage'
make -C src/backend/commands indexcmds.o CFLAGS='-O0 -g --coverage -fprofile-arcs -ftest-coverage'
make -C src/backend/bootstrap bootparse.o bootscanner.o CFLAGS='-O0 -g --coverage -fprofile-arcs -ftest-coverage'
# Relink backend with coverage:
make -C src/backend postgres CFLAGS='-O0 -g --coverage -fprofile-arcs -ftest-coverage'
# Fresh epoch: initdb captures bootstrap, installcheck captures runtime
initdb -N --no-locale -E UTF8
pg_ctl start
make -C src/test/regress installcheck

Coverage Evidence

Thread Reconciliation

Thread: pgsql-hackers #657827 "Partial indexes on system catalogs" (2026-10-01)

Status: reconciled (3 messages)

MessageSenderKindSummary
179089136170...@gmail.comManuel Reyes BravopatchInitial proof-of-concept; whitelist approach; acknowledges pending items
mvpdr22hi77...@7zh2ki5oeecmAndres FreundreviewSkeptical: benefit/complexity tradeoff; needs real benefiting syscache
1298334.1790896057@sss.pgh.pa.usTom LanereviewSkeptical: whitelist is a hack; suggests pg_constraint refactoring instead

Finding dispositions:

Aggregated Test Plan

  1. FIND-001 repair: Update misc_sanity.out expected output (verified passing)
  2. COV-001 repair: Add conbin IS NOT NULL + PK insert test to catalog_partial_index.sql
  3. Existing tests: catalog_partial_index (new test, passes), full installcheck (239/240 pass, 1 expected misc_sanity failure)

Residual Risk

Provenance