CommitFest 7374 Review: psql tab-completion fix for GRANT/REVOKE CREATE
report · generated from canonical Markdown
report
postgresql-master
commitfest-7374-review2026-10-02T00:37:13.208524+00:00
Front matter
schema: review-report-v2 target: CommitFest 7374 - psql: avoid CREATE command completion after GRANT/REVOKE CREATE base: 1378aa13430e264a990a18597e9d8fdae740927e head: 1378aa13430e264a990a18597e9d8fdae740927e verdict: ready-for-committer (test follow-up required) blocker_counts: verified: 0 unverified: 0 diff_blob_sha: e743f35cc349805a6c5aa7560d4786b38be9e4fa model: glm-5.2:cloud
CommitFest 7374 Review: psql tab-completion fix for GRANT/REVOKE CREATE
Summary
Patch: [PATCH] psql: avoid CREATE command completion after GRANT/REVOKE CREATE Author: Haruna Miwa (miwa@sraoss.co.jp) Date: 2026-10-01 Thread-ID: OSOP286MB78539E88C47403451BFFF140F18A2@OSOP286MB7853.JPNP286.PROD.OUTLOOK.COM
The patch adds an exclusion condition to the generic CREATE tab-completion rule in src/bin/psql/tab-complete.in.c so that GRANT CREATE and REVOKE CREATE (no longer trigger the create_command_generator, which offers irrelevant object types like ACCESS METHOD, AGGREGATE, DATABASE, etc. Instead, the privilege completion path fires and correctly offers ON.
Verdict: ready-for-committer (test follow-up required)
The implementation is correct, minimal, and well-scoped. No correctness, security, performance, or maintainability issues were found. One test-gap finding (COV-1, MAJOR, class=tests) requires a follow-up test patch to guard the new exclusion branch. The proposed test patch has been validated with a two-run gate (passes on patched code, fails on unpatched code).
Patch Diff
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -2186,7 +2186,9 @@ match_previous_words(int pattern_id,
/* CREATE */
/* complete with something you can create */
- else if (TailMatches("CREATE"))
+ else if (TailMatches("CREATE") &&
+ /* exclude cases of GRANT/REVOKE CREATE */
+ !TailMatches("GRANT|REVOKE", "CREATE"))
{
/* only some object types can be created as part of CREATE SCHEMA */
if (HeadMatches("CREATE", "SCHEMA"))Review Findings
No test coverage for new GRANT/REVOKE CREATE exclusion (MAJOR, tests)
Location: src/bin/psql/tab-complete.in.c:2189 Severity: MAJOR Class: tests Verification status: verified (by coverage)
Mechanism: The patch adds !TailMatches("GRANT|REVOKE", "CREATE") as a new AND condition to the CREATE completion rule at line 2189. Fresh-epoch gcov branch coverage (measured at HEAD with only the implementation patch applied) shows:
- Line 2189-2191: executed 1 time (by the existing
CREATE TY\ttest) - Branch 1 (fallthrough, condition true → enters create body): taken 100%
- Branch 2 (condition false → exclusion triggers): taken 0%
The GRANT/REVOKE CREATE exclusion path is never exercised by any existing test. The TAP test 010_tab_completion.pl does not test GRANT or REVOKE completions at all.
Failure risk: Without a test, a future refactor could remove the exclusion and reintroduce irrelevant create_command_generator suggestions after GRANT CREATE / REVOKE CREATE with no test failure.
Repair: Add two check_completion calls to src/bin/psql/t/010_tab_completion.pl verifying that GRANT CREATE\t and REVOKE CREATE\t produce qr/ON / (the privilege completion path) instead of the create_command_generator object list.
Suggested code (exact postimage)
check_completion( "GRANT CREATE \t", qr/ON /, "GRANT CREATE offers ON, not create_command_generator"); clear_query(); check_completion( "REVOKE CREATE \t", qr/ON /, "REVOKE CREATE offers ON, not create_command_generator"); clear_query();
Repair patch (HEAD-bound unified diff, sha256: b8bf19b15003051f94128c51e33dfd43d17f6c6322e9b88d8c016dd3a032bf89)
diff --git a/src/bin/psql/t/010_tab_completion.pl b/src/bin/psql/t/010_tab_completion.pl
--- a/src/bin/psql/t/010_tab_completion.pl
+++ b/src/bin/psql/t/010_tab_completion.pl
@@ -409,6 +409,24 @@ check_completion(
clear_query();
+# check that generic CREATE completion is not offered after GRANT/REVOKE
+# CREATE. On the unpatched code, GRANT CREATE<tab> offers object types
+# from create_command_generator (ACCESS METHOD, AGGREGATE, ...). After
+# the fix, only the privilege completion path fires and offers ON.
+check_completion(
+ "GRANT CREATE \t",
+ qr/ON /,
+ "GRANT CREATE offers ON, not create_command_generator");
+
+clear_query();
+
+check_completion(
+ "REVOKE CREATE \t",
+ qr/ON /,
+ "REVOKE CREATE offers ON, not create_command_generator");
+
+clear_query();
+
# check no-completions code path
check_completion("blarg \t\t", qr//, "check completion failure path");Repair Validation Summary
| Method | Result | Evidence |
|---|---|---|
| apply-check | passed | git apply succeeds on HEAD 1378aa13430 |
| diff-check | passed | Unified diff is well-formed with correct ---/+++ markers |
| targeted-test | passed | Patched: 93/93 tests pass (2 new tests ok 86, ok 88) |
| two-run | passed | Unpatched: test times out (query_until qr/ON / never matches because unpatched offers ACCESS METHOD, AGGREGATE, ...); Patched: all pass |
Verification Summary
Static verification
- gen_tabcomplete.pl compatibility: The
&&AND pattern is supported by
gen_tabcomplete.pl (line 236-251). The first clause TailMatches("CREATE") becomes a switch case label; the remainder !TailMatches("GRANT|REVOKE", "CREATE") is emitted as the if guard. Verified by building tab-complete.c and inspecting the output: case 1: followed by
word_matchesOR syntax:TailMatches("GRANT|REVOKE", "CREATE")uses
| as the OR separator, which is handled by word_matches() (line 1577). The pattern matches when the last 2 words are [GRANT or REVOKE, CREATE].
- Indentation: The continuation line uses
\t\t\t(3 tabs + 1 space),
consistent with existing multi-line conditions at line 3584.
- No security issues: The patch only affects psql client-side tab-completion.
No server-side changes, no privilege escalation, no injection risk.
- No correctness issues: The exclusion correctly prevents
create_command_generator from firing after GRANT CREATE / REVOKE CREATE, allowing the privilege completion path at line 4610 (TailMatches("GRANT|REVOKE", MatchAny)) to offer ON.
Runtime verification
- Build: Full PostgreSQL build with
--with-readline --with-icusucceeds. - Existing tests:
make -C src/bin/psql check PROVE_TESTS=t/010_tab_completion.pl
passes all 89 tests with the implementation patch applied (no regression).
- Behavioral confirmation: Interactive psql diagnostic confirms:
- Unpatched:
GRANT CREATE\t→ACCESS METHOD,AGGREGATE,CAST, ... (wrong) - Patched:
GRANT CREATE\t→ON(correct privilege completion) CREATE TY\t→CREATE TYPE(no regression on normal CREATE completion)
Changed-Code Coverage
Coverage requirement: required (changed instrumentable implementation in src/bin/psql/tab-complete.in.c)
Counter epoch: fresh (gcda files deleted before test run, disposable build)
Execution lane: host-disposable
| Lane | Status | Evidence |
|---|---|---|
| nested-sandbox | blocked | Coverage LDFLAGS cause libpq-refs-stamp failure (gcov exit@GLIBC) |
| host-disposable | passed | Full build with -fprofile-arcs -ftest-coverage, 89 tests pass, gcov data collected |
Test commands
make -C src/bin/psql check PROVE_TESTS=t/010_tab_completion.pl
Raw metrics (without test patch)
| Metric | Value |
|---|---|
| Changed executable lines | 2 |
| Covered changed lines | 2 |
| Compiler-uncovered changed lines | 0 |
| Uncovered changed lines | 0 |
| Structural uncovered changed lines | 0 |
| Changed branches | 1 |
| Covered changed branches | 0 |
Uncovered branches
Branch at src/bin/psql/tab-complete.in.c:2189 (branch_id=2, count=0)
else if (TailMatches("CREATE") &&
/* exclude cases of GRANT/REVOKE CREATE */
!TailMatches("GRANT|REVOKE", "CREATE"))- Coverability: coverable-now
- Reason: The GRANT/REVOKE CREATE exclusion branch (condition false, skip
create_command_generator body) is never exercised. No existing test sends GRANT CREATE or REVOKE CREATE to psql tab-completion. Trivially coverable by a TAP test typing GRANT CREATE<TAB> and verifying ON is offered.
- Test example:
check_completion("GRANT CREATE \t", qr/ON /, "GRANT CREATE offers ON, not create_command_generator"); - Vehicle: tap
- Oracle:
qr/ON / - Baseline (unpatched): offers
ACCESS METHOD,AGGREGATE, ... — test times out - Patched: offers
ON— test passes
Touched functions
| Function | File | Lines | Entered | Whole-function lines | Whole-function branches |
|---|---|---|---|---|---|
match_previous_words | src/bin/psql/tab-complete.in.c | 2171-5745 | yes | 665/2452 | 427/1595 |
Coverage with proposed test patch
When the proposed test patch is applied, branch 2 at line 2189 is taken 67% (2 out of 3 times), confirming the test covers the exclusion. All 93 tests pass.
Non-instrumented changes
None. The only changed file is src/bin/psql/tab-complete.in.c (C implementation).
pgsql-hackers Thread Ledger
Status: no-thread-found
Reconstruction methods: pgsql-hackers mail search (BM25)
Summary: Searched the pgsql-hackers inbox for the patch subject. Found exactly one message: OSOP286MB78539E88C47403451BFFF140F18A2@OSOP286MB7853.JPNP286.PROD.OUTLOOK.COM (2026-10-01, Haruna Miwa, [PATCH] psql: avoid CREATE command completion after GRANT/REVOKE CREATE). This is the initial patch submission with no replies or review responses. No prior thread discussion of this specific issue was found.
Finding links:
| Finding | Disposition | Rationale |
|---|---|---|
| COV-1 | new | Test gap newly identified by this review; no prior reviewer raised it |
Aggregated Test Plan
- Existing:
t/010_tab_completion.pl— 89 tests covering basic completions,
GUCs, psql variables, CREATE/DROP/PUBLICATION completions.
- Proposed (COV-1 repair): Add
GRANT CREATE\t→ONand
REVOKE CREATE\t → ON tests to t/010_tab_completion.pl.
Residual Risk
Low. The patch is a 2-line change to psql client-side tab-completion logic with no server-side impact. The only residual risk is the untested exclusion branch, which is addressed by the proposed test patch (COV-1).
Provenance
- Model: glm-5.2:cloud
- Review seats: pg-patch-reviewer (static), pg-security-reviewer (static),
pg-test-author (test proposal), pg-finding-verifier (repair validation), pg-change-coverage-reviewer (coverage analysis)
- Validator:
validate_review_artifact.py(passed, exit 0)