From de75fe8f6d9bf90ac8fa78c89f5f9119900c94c9 Mon Sep 17 00:00:00 2001 From: Baji Shaik Date: Mon, 19 Oct 2026 19:35:45 -0500 Subject: [PATCH] psql: Add tab completion for ALTER TABLE ALTER CONSTRAINT After ALTER TABLE t ALTER CONSTRAINT c, psql now offers DEFERRABLE, NOT DEFERRABLE, ENFORCED, NOT ENFORCED, INITIALLY DEFERRED, INITIALLY IMMEDIATE, INHERIT, and NO INHERIT. Previously, selecting the constraint name was a dead end with no further suggestions. Also add the follow-up completions for NOT, NO, and INITIALLY, so that choosing one of those words and pressing tab again offers the matching second word, instead of a second dead end. Likewise, DEFERRABLE is itself followed by INITIALLY DEFERRED and INITIALLY IMMEDIATE, which is how deferrable constraints are most often written, matching the existing pattern used for e.g. ALTER STATISTICS ... SET. The INITIALLY rule itself is extended to also match after DEFERRABLE INITIALLY, since typing DEFERRABLE first and then INITIALLY is one of the orders ALTER CONSTRAINT accepts. NOT DEFERRABLE only offers INITIALLY IMMEDIATE, not INITIALLY DEFERRED: the grammar rejects a constraint declared both NOT DEFERRABLE and INITIALLY DEFERRED ("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), so offering it there would suggest something that's always a syntax error. --- src/bin/psql/tab-complete.in.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index f86684edc08..d4ed6218655 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -2934,6 +2934,32 @@ match_previous_words(int pattern_id, set_completion_reference(prev3_wd); COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table); } + /* ALTER TABLE ALTER CONSTRAINT options */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny)) + COMPLETE_WITH("DEFERRABLE", "NOT DEFERRABLE", "ENFORCED", "NOT ENFORCED", + "INITIALLY DEFERRED", "INITIALLY IMMEDIATE", + "INHERIT", "NO INHERIT"); + /* ALTER TABLE ALTER CONSTRAINT NOT */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny, "NOT")) + COMPLETE_WITH("DEFERRABLE", "ENFORCED"); + /* ALTER TABLE ALTER CONSTRAINT DEFERRABLE */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny, "DEFERRABLE")) + COMPLETE_WITH("INITIALLY DEFERRED", "INITIALLY IMMEDIATE"); + /* + * ALTER TABLE ALTER CONSTRAINT NOT DEFERRABLE + * + * Only INITIALLY IMMEDIATE is valid here: a constraint declared NOT + * DEFERRABLE cannot also be INITIALLY DEFERRED. + */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny, "NOT", "DEFERRABLE")) + COMPLETE_WITH("INITIALLY IMMEDIATE"); + /* ALTER TABLE ALTER CONSTRAINT NO */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny, "NO")) + COMPLETE_WITH("INHERIT"); + /* ALTER TABLE ALTER CONSTRAINT [DEFERRABLE] INITIALLY */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny, "INITIALLY") || + Matches("ALTER", "TABLE", MatchAny, "ALTER", "CONSTRAINT", MatchAny, "DEFERRABLE", "INITIALLY")) + COMPLETE_WITH("DEFERRED", "IMMEDIATE"); /* ALTER TABLE VALIDATE CONSTRAINT */ else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT")) { -- 2.54.0 (Apple Git-157)