--- tab-complete.in.c.orig	2024-07-13 12:12:49.659229840 -0400
+++ tab-complete.in.c	2024-07-13 12:28:07.394700992 -0400
@@ -1304,6 +1304,47 @@ static const pgsql_thing_t words_after_c
 	{NULL}						/* end of list */
 };
 
+/*
+ * The tcpatterns[] table provides the initial pattern-match rule for each
+ * switch case in match_previous_words().  The contents of the table
+ * are constructed by gen_tabcomplete.pl.
+ */
+
+/* Basic match rules appearing in tcpatterns[].kind */
+enum TCPatternKind
+{
+	Match,
+	MatchCS,
+	HeadMatch,
+	HeadMatchCS,
+	TailMatch,
+	TailMatchCS,
+};
+
+/* Things besides string literals that can appear in tcpatterns[].words */
+#define MatchAny  NULL
+#define MatchAnyExcept(pattern)  ("!" pattern)
+#define MatchAnyN ""
+
+/* One entry in tcpatterns[] */
+typedef struct
+{
+	int			id;				/* case label used in match_previous_words */
+	enum TCPatternKind kind;	/* match kind, see above */
+	int			nwords;			/* length of words[] array */
+	const char *const *words;	/* array of match words */
+} TCPattern;
+
+/* Macro emitted by gen_tabcomplete.pl to fill a tcpatterns[] entry */
+#define TCPAT(id, kind, ...) \
+	{ (id), (kind), VA_ARGS_NARGS(__VA_ARGS__), \
+	  (const char * const []) { __VA_ARGS__ } }
+
+static const TCPattern tcpatterns[] =
+{
+	/* Insert tab-completion pattern data here. */
+};
+
 /* Storage parameters for CREATE TABLE and ALTER TABLE */
 static const char *const table_storage_parameters[] = {
 	"autovacuum_analyze_scale_factor",
@@ -1469,10 +1510,6 @@ initialize_readline(void)
  * just be written directly in patterns.)  There is also MatchAnyN, but that
  * is supported only in Matches/MatchesCS and is not handled here.
  */
-#define MatchAny  NULL
-#define MatchAnyExcept(pattern)  ("!" pattern)
-#define MatchAnyN ""
-
 static bool
 word_matches(const char *pattern,
 			 const char *word,
@@ -2071,9 +2108,10 @@ match_previous_words(const char *text, i
 	/* ALTER PUBLICATION <name> ADD */
 	else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
 		COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
-	else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") ||
-			 (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
-			  ends_with(prev_wd, ',')))
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
+	else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
+			 ends_with(prev_wd, ','))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
 
 	/*
@@ -2539,8 +2577,7 @@ match_previous_words(const char *text, i
 	}
 	/* ALTER TABLE xxx ADD [COLUMN] yyy */
 	else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
-			 (Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAny) &&
-			  !Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN")))
+			 Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAnyExcept("COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN")))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
 	/* ALTER TABLE xxx ADD CONSTRAINT yyy */
 	else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
@@ -3941,13 +3978,14 @@ match_previous_words(const char *text, i
 					 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
 					 MatchAny) ||
 			 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
-			 (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
-			  ends_with(prev_wd, ')')) ||
 			 Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
 			 Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
 			 Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
 			 Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
 		COMPLETE_WITH("CASCADE", "RESTRICT");
+	else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
+			 ends_with(prev_wd, ')'))
+		COMPLETE_WITH("CASCADE", "RESTRICT");
 
 	/* help completing some of the variants */
 	else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
