diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 47a1a19688f..21a4a807d93 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1220,6 +1220,110 @@ ends_with(const char *s, char c)
 	return (length > 0 && s[length - 1] == c);
 }
 
+static bool
+CheckTailMatchesFor(int previous_words_count, char **previous_words, int narg, ...)
+{
+	va_list		args;
+
+	if (previous_words_count < narg)
+		return false;
+
+	va_start(args, narg);
+
+	for (int argno = 0; argno < narg; argno++)
+	{
+		const char *arg = va_arg(args, const char *);
+
+		if (!word_matches(arg, previous_words[narg - argno - 1]))
+		{
+			va_end(args);
+			return false;
+		}
+	}
+
+	va_end(args);
+
+	return true;
+}
+
+static bool
+CheckMatchesFor(int previous_words_count, char **previous_words, int narg, ...)
+{
+	va_list		args;
+
+	if (previous_words_count != narg)
+		return false;
+
+	va_start(args, narg);
+
+	for (int argno = 0; argno < narg; argno++)
+	{
+		const char *arg = va_arg(args, const char *);
+
+		if (!word_matches(arg, previous_words[narg - argno - 1]))
+		{
+			va_end(args);
+			return false;
+		}
+	}
+
+	va_end(args);
+
+	return true;
+}
+
+static bool
+CheckTailMatchesCSFor(int previous_words_count, char **previous_words, int narg, ...)
+{
+	va_list		args;
+
+	if (previous_words_count < narg)
+		return false;
+
+	va_start(args, narg);
+
+	for (int argno = 0; argno < narg; argno++)
+	{
+		const char *arg = va_arg(args, const char *);
+
+		if (!word_matches_cs(arg, previous_words[narg - argno - 1]))
+		{
+			va_end(args);
+			return false;
+		}
+	}
+
+	va_end(args);
+
+	return true;
+}
+
+static bool
+CheckHeadMatchesFor(int previous_words_count, char **previous_words, int narg, ...)
+{
+	va_list		args;
+
+	if (previous_words_count < narg)
+		return false;
+
+	va_start(args, narg);
+
+	for (int argno = 0; argno < narg; argno++)
+	{
+		const char *arg = va_arg(args, const char *);
+
+		if (!word_matches(arg, previous_words[previous_words_count - (argno + 1)]))
+		{
+			va_end(args);
+			return false;
+		}
+	}
+
+	va_end(args);
+
+	return true;
+}
+
 /*
  * The completion function.
  *
@@ -1260,149 +1364,23 @@ psql_completion(const char *text, int start, int end)
 #define prev8_wd  (previous_words[7])
 #define prev9_wd  (previous_words[8])
 
+		/* Macros for matching the last N words before point, case-insensitively. */
+#define TailMatches(...) CheckTailMatchesFor(previous_words_count, previous_words, PP_NARG(__VA_ARGS__), __VA_ARGS__)
+
 	/* Macros for matching the last N words before point, case-insensitively. */
-#define TailMatches1(p1) \
-	(previous_words_count >= 1 && \
-	 word_matches(p1, prev_wd))
-
-#define TailMatches2(p2, p1) \
-	(previous_words_count >= 2 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd))
-
-#define TailMatches3(p3, p2, p1) \
-	(previous_words_count >= 3 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd))
-
-#define TailMatches4(p4, p3, p2, p1) \
-	(previous_words_count >= 4 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd) && \
-	 word_matches(p4, prev4_wd))
-
-#define TailMatches5(p5, p4, p3, p2, p1) \
-	(previous_words_count >= 5 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd) && \
-	 word_matches(p4, prev4_wd) && \
-	 word_matches(p5, prev5_wd))
-
-#define TailMatches6(p6, p5, p4, p3, p2, p1) \
-	(previous_words_count >= 6 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd) && \
-	 word_matches(p4, prev4_wd) && \
-	 word_matches(p5, prev5_wd) && \
-	 word_matches(p6, prev6_wd))
-
-#define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
-	(previous_words_count >= 7 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd) && \
-	 word_matches(p4, prev4_wd) && \
-	 word_matches(p5, prev5_wd) && \
-	 word_matches(p6, prev6_wd) && \
-	 word_matches(p7, prev7_wd))
-
-#define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
-	(previous_words_count >= 8 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd) && \
-	 word_matches(p4, prev4_wd) && \
-	 word_matches(p5, prev5_wd) && \
-	 word_matches(p6, prev6_wd) && \
-	 word_matches(p7, prev7_wd) && \
-	 word_matches(p8, prev8_wd))
-
-#define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
-	(previous_words_count >= 9 && \
-	 word_matches(p1, prev_wd) && \
-	 word_matches(p2, prev2_wd) && \
-	 word_matches(p3, prev3_wd) && \
-	 word_matches(p4, prev4_wd) && \
-	 word_matches(p5, prev5_wd) && \
-	 word_matches(p6, prev6_wd) && \
-	 word_matches(p7, prev7_wd) && \
-	 word_matches(p8, prev8_wd) && \
-	 word_matches(p9, prev9_wd))
-
-	/* Macros for matching the last N words before point, case-sensitively. */
-#define TailMatchesCS1(p1) \
-	(previous_words_count >= 1 && \
-	 word_matches_cs(p1, prev_wd))
-#define TailMatchesCS2(p2, p1) \
-	(previous_words_count >= 2 && \
-	 word_matches_cs(p1, prev_wd) && \
-	 word_matches_cs(p2, prev2_wd))
-#define TailMatchesCS3(p3, p2, p1) \
-	(previous_words_count >= 3 && \
-	 word_matches_cs(p1, prev_wd) && \
-	 word_matches_cs(p2, prev2_wd) && \
-	 word_matches_cs(p3, prev3_wd))
-#define TailMatchesCS4(p4, p3, p2, p1) \
-	(previous_words_count >= 4 && \
-	 word_matches_cs(p1, prev_wd) && \
-	 word_matches_cs(p2, prev2_wd) && \
-	 word_matches_cs(p3, prev3_wd) && \
-	 word_matches_cs(p4, prev4_wd))
+#define TailMatchesCS(...) CheckTailMatchesCSFor(previous_words_count, previous_words, PP_NARG(__VA_ARGS__), __VA_ARGS__)
 
 	/*
 	 * Macros for matching N words beginning at the start of the line,
 	 * case-insensitively.
 	 */
-#define Matches1(p1) \
-	(previous_words_count == 1 && \
-	 TailMatches1(p1))
-#define Matches2(p1, p2) \
-	(previous_words_count == 2 && \
-	 TailMatches2(p1, p2))
-#define Matches3(p1, p2, p3) \
-	(previous_words_count == 3 && \
-	 TailMatches3(p1, p2, p3))
-#define Matches4(p1, p2, p3, p4) \
-	(previous_words_count == 4 && \
-	 TailMatches4(p1, p2, p3, p4))
-#define Matches5(p1, p2, p3, p4, p5) \
-	(previous_words_count == 5 && \
-	 TailMatches5(p1, p2, p3, p4, p5))
-#define Matches6(p1, p2, p3, p4, p5, p6) \
-	(previous_words_count == 6 && \
-	 TailMatches6(p1, p2, p3, p4, p5, p6))
-#define Matches7(p1, p2, p3, p4, p5, p6, p7) \
-	(previous_words_count == 7 && \
-	 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
-#define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
-	(previous_words_count == 8 && \
-	 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
-#define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
-	(previous_words_count == 9 && \
-	 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
+#define Matches(...) CheckMatchesFor(previous_words_count, previous_words, PP_NARG(__VA_ARGS__), __VA_ARGS__)
 
 	/*
 	 * Macros for matching N words at the start of the line, regardless of
 	 * what is after them, case-insensitively.
 	 */
-#define HeadMatches1(p1) \
-	(previous_words_count >= 1 && \
-	 word_matches(p1, previous_words[previous_words_count - 1]))
-
-#define HeadMatches2(p1, p2) \
-	(previous_words_count >= 2 && \
-	 word_matches(p1, previous_words[previous_words_count - 1]) && \
-	 word_matches(p2, previous_words[previous_words_count - 2]))
-
-#define HeadMatches3(p1, p2, p3) \
-	(previous_words_count >= 3 && \
-	 word_matches(p1, previous_words[previous_words_count - 1]) && \
-	 word_matches(p2, previous_words[previous_words_count - 2]) && \
-	 word_matches(p3, previous_words[previous_words_count - 3]))
+#define HeadMatches(...) CheckHeadMatchesFor(previous_words_count, previous_words, PP_NARG(__VA_ARGS__), __VA_ARGS__)
 
 	/* Known command-starting keywords. */
 	static const char *const sql_commands[] = {
@@ -1492,38 +1470,38 @@ psql_completion(const char *text, int start, int end)
 
 /* CREATE */
 	/* complete with something you can create */
-	else if (TailMatches1("CREATE"))
+	else if (TailMatches("CREATE"))
 		matches = completion_matches(text, create_command_generator);
 
 /* DROP, but not DROP embedded in other commands */
 	/* complete with something you can drop */
-	else if (Matches1("DROP"))
+	else if (Matches("DROP"))
 		matches = completion_matches(text, drop_command_generator);
 
 /* ALTER */
 
 	/* ALTER TABLE */
-	else if (Matches2("ALTER", "TABLE"))
+	else if (Matches("ALTER", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
 								   "UNION SELECT 'ALL IN TABLESPACE'");
 
 	/* ALTER something */
-	else if (Matches1("ALTER"))
+	else if (Matches("ALTER"))
 		matches = completion_matches(text, alter_command_generator);
 	/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
-	else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
+	else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny))
 		COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
 	/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
-	else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
+	else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 	/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
-	else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
+	else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
 		COMPLETE_WITH_CONST("SET TABLESPACE");
 	/* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
-	else if (Matches3("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
+	else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
 		COMPLETE_WITH_CONST("(");
 	/* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> (...) */
-	else if (Matches4("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny))
+	else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny))
 	{
 		if (ends_with(prev_wd, ')'))
 			COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
@@ -1531,107 +1509,107 @@ psql_completion(const char *text, int start, int end)
 			COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
 	}
 	/* ALTER PUBLICATION <name> */
-	else if (Matches3("ALTER", "PUBLICATION", MatchAny))
+	else if (Matches("ALTER", "PUBLICATION", MatchAny))
 		COMPLETE_WITH_LIST5("ADD TABLE", "DROP TABLE", "OWNER TO", "RENAME TO", "SET");
 	/* ALTER PUBLICATION <name> SET */
-	else if (Matches4("ALTER", "PUBLICATION", MatchAny, "SET"))
+	else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
 		COMPLETE_WITH_LIST2("(", "TABLE");
 	/* ALTER PUBLICATION <name> SET ( */
-	else if (HeadMatches3("ALTER", "PUBLICATION", MatchAny) && TailMatches2("SET", "("))
+	else if (HeadMatches("ALTER", "PUBLICATION", MatchAny) && TailMatches("SET", "("))
 		COMPLETE_WITH_CONST("publish");
 	/* ALTER SUBSCRIPTION <name> */
-	else if (Matches3("ALTER", "SUBSCRIPTION", MatchAny))
+	else if (Matches("ALTER", "SUBSCRIPTION", MatchAny))
 		COMPLETE_WITH_LIST7("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
 							"RENAME TO", "REFRESH PUBLICATION", "SET");
 	/* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
-	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
-			 TailMatches2("REFRESH", "PUBLICATION"))
+	else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
+			 TailMatches("REFRESH", "PUBLICATION"))
 		COMPLETE_WITH_CONST("WITH (");
 	/* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
-	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
-			 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
+	else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
+			 TailMatches("REFRESH", "PUBLICATION", "WITH", "("))
 		COMPLETE_WITH_CONST("copy_data");
 	/* ALTER SUBSCRIPTION <name> SET */
-	else if (Matches4("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
+	else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
 		COMPLETE_WITH_LIST2("(", "PUBLICATION");
 	/* ALTER SUBSCRIPTION <name> SET ( */
-	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "("))
+	else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "("))
 		COMPLETE_WITH_LIST2("slot_name", "synchronous_commit");
 	/* ALTER SUBSCRIPTION <name> SET PUBLICATION */
-	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "PUBLICATION"))
+	else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches("SET", "PUBLICATION"))
 	{
 		/* complete with nothing here as this refers to remote publications */
 	}
 	/* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> */
-	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
-			 TailMatches3("SET", "PUBLICATION", MatchAny))
+	else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
+			 TailMatches("SET", "PUBLICATION", MatchAny))
 		COMPLETE_WITH_CONST("WITH (");
 	/* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> WITH ( */
-	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
-			 TailMatches5("SET", "PUBLICATION", MatchAny, "WITH", "("))
+	else if (HeadMatches("ALTER", "SUBSCRIPTION", MatchAny) &&
+			 TailMatches("SET", "PUBLICATION", MatchAny, "WITH", "("))
 		COMPLETE_WITH_LIST2("copy_data", "refresh");
 	/* ALTER SCHEMA <name> */
-	else if (Matches3("ALTER", "SCHEMA", MatchAny))
+	else if (Matches("ALTER", "SCHEMA", MatchAny))
 		COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
 
 	/* ALTER COLLATION <name> */
-	else if (Matches3("ALTER", "COLLATION", MatchAny))
+	else if (Matches("ALTER", "COLLATION", MatchAny))
 		COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
 
 	/* ALTER CONVERSION <name> */
-	else if (Matches3("ALTER", "CONVERSION", MatchAny))
+	else if (Matches("ALTER", "CONVERSION", MatchAny))
 		COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
 
 	/* ALTER DATABASE <name> */
-	else if (Matches3("ALTER", "DATABASE", MatchAny))
+	else if (Matches("ALTER", "DATABASE", MatchAny))
 		COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
 							"IS_TEMPLATE", "ALLOW_CONNECTIONS",
 							"CONNECTION LIMIT");
 
 	/* ALTER DATABASE <name> SET TABLESPACE */
-	else if (Matches5("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
+	else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
 
 	/* ALTER EVENT TRIGGER */
-	else if (Matches3("ALTER", "EVENT", "TRIGGER"))
+	else if (Matches("ALTER", "EVENT", "TRIGGER"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
 
 	/* ALTER EVENT TRIGGER <name> */
-	else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
+	else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
 		COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
 
 	/* ALTER EVENT TRIGGER <name> ENABLE */
-	else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
+	else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
 		COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
 
 	/* ALTER EXTENSION <name> */
-	else if (Matches3("ALTER", "EXTENSION", MatchAny))
+	else if (Matches("ALTER", "EXTENSION", MatchAny))
 		COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
 
 	/* ALTER EXTENSION <name> UPDATE */
-	else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
+	else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
 	}
 
 	/* ALTER EXTENSION <name> UPDATE TO */
-	else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
+	else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
 	}
 
 	/* ALTER FOREIGN */
-	else if (Matches2("ALTER", "FOREIGN"))
+	else if (Matches("ALTER", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 
 	/* ALTER FOREIGN DATA WRAPPER <name> */
-	else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+	else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 		COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
 
 	/* ALTER FOREIGN TABLE <name> */
-	else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
+	else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
 	{
 		static const char *const list_ALTER_FOREIGN_TABLE[] =
 		{"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
@@ -1642,35 +1620,35 @@ psql_completion(const char *text, int start, int end)
 	}
 
 	/* ALTER INDEX */
-	else if (Matches2("ALTER", "INDEX"))
+	else if (Matches("ALTER", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
 								   "UNION SELECT 'ALL IN TABLESPACE'");
 	/* ALTER INDEX <name> */
-	else if (Matches3("ALTER", "INDEX", MatchAny))
+	else if (Matches("ALTER", "INDEX", MatchAny))
 		COMPLETE_WITH_LIST6("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
 							"RESET", "ATTACH PARTITION");
-	else if (Matches4("ALTER", "INDEX", MatchAny, "ATTACH"))
+	else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
 		COMPLETE_WITH_CONST("PARTITION");
-	else if (Matches5("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
+	else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
 	/* ALTER INDEX <name> ALTER COLUMN <colnum> */
-	else if (Matches6("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
+	else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
 		COMPLETE_WITH_CONST("SET STATISTICS");
 	/* ALTER INDEX <name> SET */
-	else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
+	else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
 		COMPLETE_WITH_LIST2("(", "TABLESPACE");
 	/* ALTER INDEX <name> RESET */
-	else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
+	else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
 		COMPLETE_WITH_CONST("(");
 	/* ALTER INDEX <foo> SET|RESET ( */
-	else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
+	else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
 		COMPLETE_WITH_LIST8("fillfactor", "recheck_on_update",
 							"vacuum_cleanup_index_scale_factor",	/* BTREE */
 							"fastupdate", "gin_pending_list_limit", /* GIN */
 							"buffering",	/* GiST */
 							"pages_per_range", "autosummarize"	/* BRIN */
 			);
-	else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
+	else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
 		COMPLETE_WITH_LIST8("fillfactor =", "recheck_on_update =",
 							"vacuum_cleanup_index_scale_factor =",	/* BTREE */
 							"fastupdate =", "gin_pending_list_limit =", /* GIN */
@@ -1679,21 +1657,21 @@ psql_completion(const char *text, int start, int end)
 			);
 
 	/* ALTER LANGUAGE <name> */
-	else if (Matches3("ALTER", "LANGUAGE", MatchAny))
+	else if (Matches("ALTER", "LANGUAGE", MatchAny))
 		COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
 
 	/* ALTER LARGE OBJECT <oid> */
-	else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
+	else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
 		COMPLETE_WITH_CONST("OWNER TO");
 
 	/* ALTER MATERIALIZED VIEW */
-	else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
+	else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
 								   "UNION SELECT 'ALL IN TABLESPACE'");
 
 	/* ALTER USER,ROLE <name> */
-	else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
-			 !TailMatches2("USER", "MAPPING"))
+	else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
+			 !TailMatches("USER", "MAPPING"))
 	{
 		static const char *const list_ALTERUSER[] =
 		{"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
@@ -1707,7 +1685,7 @@ psql_completion(const char *text, int start, int end)
 	}
 
 	/* ALTER USER,ROLE <name> WITH */
-	else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
+	else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
 	{
 		/* Similar to the above, but don't complete "WITH" again. */
 		static const char *const list_ALTERUSER_WITH[] =
@@ -1722,58 +1700,58 @@ psql_completion(const char *text, int start, int end)
 	}
 
 	/* ALTER DEFAULT PRIVILEGES */
-	else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
 		COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
 	/* ALTER DEFAULT PRIVILEGES FOR */
-	else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
 		COMPLETE_WITH_CONST("ROLE");
 	/* ALTER DEFAULT PRIVILEGES IN */
-	else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
 		COMPLETE_WITH_CONST("SCHEMA");
 	/* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
-	else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
 					  MatchAny))
 		COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
 	/* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
-	else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
 					  MatchAny))
 		COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
 	/* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
-	else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
 					  MatchAny, "FOR"))
 		COMPLETE_WITH_CONST("ROLE");
 	/* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
 	/* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
-	else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
+	else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
 					  MatchAny, "IN", "SCHEMA", MatchAny) ||
-			 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
+			 Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
 					  MatchAny, "FOR", "ROLE|USER", MatchAny))
 		COMPLETE_WITH_LIST2("GRANT", "REVOKE");
 	/* ALTER DOMAIN <name> */
-	else if (Matches3("ALTER", "DOMAIN", MatchAny))
+	else if (Matches("ALTER", "DOMAIN", MatchAny))
 		COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
 							"VALIDATE CONSTRAINT");
 	/* ALTER DOMAIN <sth> DROP */
-	else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
+	else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
 		COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
 	/* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
-	else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
+	else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
 	}
 	/* ALTER DOMAIN <sth> RENAME */
-	else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
+	else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
 		COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
 	/* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
-	else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
+	else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
 		COMPLETE_WITH_CONST("TO");
 
 	/* ALTER DOMAIN <sth> SET */
-	else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
+	else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
 		COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
 	/* ALTER SEQUENCE <name> */
-	else if (Matches3("ALTER", "SEQUENCE", MatchAny))
+	else if (Matches("ALTER", "SEQUENCE", MatchAny))
 	{
 		static const char *const list_ALTERSEQUENCE[] =
 		{"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
@@ -1782,79 +1760,79 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
 	}
 	/* ALTER SEQUENCE <name> NO */
-	else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
+	else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
 		COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
 	/* ALTER SERVER <name> */
-	else if (Matches3("ALTER", "SERVER", MatchAny))
+	else if (Matches("ALTER", "SERVER", MatchAny))
 		COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
 	/* ALTER SERVER <name> VERSION <version> */
-	else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
+	else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
 		COMPLETE_WITH_CONST("OPTIONS");
 	/* ALTER SYSTEM SET, RESET, RESET ALL */
-	else if (Matches2("ALTER", "SYSTEM"))
+	else if (Matches("ALTER", "SYSTEM"))
 		COMPLETE_WITH_LIST2("SET", "RESET");
-	else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
+	else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
-	else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
+	else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
 		COMPLETE_WITH_CONST("TO");
 	/* ALTER VIEW <name> */
-	else if (Matches3("ALTER", "VIEW", MatchAny))
+	else if (Matches("ALTER", "VIEW", MatchAny))
 		COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
 							"SET SCHEMA");
 	/* ALTER MATERIALIZED VIEW <name> */
-	else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
+	else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
 		COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
 							"SET SCHEMA");
 
 	/* ALTER POLICY <name> */
-	else if (Matches2("ALTER", "POLICY"))
+	else if (Matches("ALTER", "POLICY"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_policies);
 	/* ALTER POLICY <name> ON */
-	else if (Matches3("ALTER", "POLICY", MatchAny))
+	else if (Matches("ALTER", "POLICY", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 	/* ALTER POLICY <name> ON <table> */
-	else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
+	else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
 	}
 	/* ALTER POLICY <name> ON <table> - show options */
-	else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
+	else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
 	/* ALTER POLICY <name> ON <table> TO <role> */
-	else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
+	else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
 	/* ALTER POLICY <name> ON <table> USING ( */
-	else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
+	else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
 		COMPLETE_WITH_CONST("(");
 	/* ALTER POLICY <name> ON <table> WITH CHECK ( */
-	else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
+	else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
 		COMPLETE_WITH_CONST("(");
 
 	/* ALTER RULE <name>, add ON */
-	else if (Matches3("ALTER", "RULE", MatchAny))
+	else if (Matches("ALTER", "RULE", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 
 	/* If we have ALTER RULE <name> ON, then add the correct tablename */
-	else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
+	else if (Matches("ALTER", "RULE", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
 	}
 
 	/* ALTER RULE <name> ON <name> */
-	else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
+	else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_CONST("RENAME TO");
 
 	/* ALTER STATISTICS <name> */
-	else if (Matches3("ALTER", "STATISTICS", MatchAny))
+	else if (Matches("ALTER", "STATISTICS", MatchAny))
 		COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
 
 	/* ALTER TRIGGER <name>, add ON */
-	else if (Matches3("ALTER", "TRIGGER", MatchAny))
+	else if (Matches("ALTER", "TRIGGER", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 
-	else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
+	else if (Matches("ALTER", "TRIGGER", MatchAny, MatchAny))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
@@ -1863,17 +1841,17 @@ psql_completion(const char *text, int start, int end)
 	/*
 	 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
 	 */
-	else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
+	else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 
 	/* ALTER TRIGGER <name> ON <name> */
-	else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
+	else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_CONST("RENAME TO");
 
 	/*
 	 * If we detect ALTER TABLE <name>, suggest sub commands
 	 */
-	else if (Matches3("ALTER", "TABLE", MatchAny))
+	else if (Matches("ALTER", "TABLE", MatchAny))
 	{
 		static const char *const list_ALTER2[] =
 		{"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
@@ -1884,114 +1862,114 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST(list_ALTER2);
 	}
 	/* ALTER TABLE xxx ENABLE */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
 		COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
 							"TRIGGER");
-	else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
 		COMPLETE_WITH_LIST2("RULE", "TRIGGER");
-	else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_rule_of_table);
 	}
-	else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
 	{
 		completion_info_charp = prev4_wd;
 		COMPLETE_WITH_QUERY(Query_for_rule_of_table);
 	}
-	else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
 	}
-	else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
 	{
 		completion_info_charp = prev4_wd;
 		COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
 	}
 	/* ALTER TABLE xxx INHERIT */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	/* ALTER TABLE xxx NO INHERIT */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	/* ALTER TABLE xxx DISABLE */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
 		COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
-	else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_rule_of_table);
 	}
-	else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
 	}
 
 	/* ALTER TABLE xxx ALTER */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
 		COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
 
 	/* ALTER TABLE xxx RENAME */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
 		COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
-	else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
 		COMPLETE_WITH_ATTR(prev3_wd, "");
 
 	/* ALTER TABLE xxx RENAME yyy */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
+	else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
 		COMPLETE_WITH_CONST("TO");
 
 	/* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
-	else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
+	else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
 		COMPLETE_WITH_CONST("TO");
 
 	/* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
 		COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
 	/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
 		COMPLETE_WITH_ATTR(prev3_wd, "");
 
 	/*
 	 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
 	 * provide list of constraints
 	 */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
 	}
 	/* ALTER TABLE ALTER [COLUMN] <foo> */
-	else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
-			 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
+			 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
 		COMPLETE_WITH_LIST6("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
 	/* ALTER TABLE ALTER [COLUMN] <foo> SET */
-	else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
-			 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
+			 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
 		COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
 	/* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
-	else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
-			 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
+			 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
 		COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
 	/* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
-	else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
-			 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
+			 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
 		COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
 	/* ALTER TABLE ALTER [COLUMN] <foo> DROP */
-	else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
-			 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
+			 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
 		COMPLETE_WITH_LIST3("DEFAULT", "IDENTITY", "NOT NULL");
-	else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
 		COMPLETE_WITH_CONST("ON");
-	else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_index_of_table);
 	}
 	/* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
 		COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
 							"WITH", "WITHOUT");
 
@@ -1999,19 +1977,19 @@ psql_completion(const char *text, int start, int end)
 	 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
 	 * tablespaces
 	 */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
 	/* If we have ALTER TABLE <sth> SET WITH provide OIDS */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITH"))
 		COMPLETE_WITH_CONST("OIDS");
 	/* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
 		COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
 	/* ALTER TABLE <foo> RESET */
-	else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
 		COMPLETE_WITH_CONST("(");
 	/* ALTER TABLE <foo> SET|RESET ( */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
+	else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
 	{
 		static const char *const list_TABLEOPTIONS[] =
 		{
@@ -2050,146 +2028,146 @@ psql_completion(const char *text, int start, int end)
 
 		COMPLETE_WITH_LIST(list_TABLEOPTIONS);
 	}
-	else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
 	{
 		completion_info_charp = prev5_wd;
 		COMPLETE_WITH_QUERY(Query_for_index_of_table);
 	}
-	else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
 		COMPLETE_WITH_CONST("INDEX");
-	else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
 		COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
-	else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
 		COMPLETE_WITH_CONST("IDENTITY");
 
 	/*
 	 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
 	 * tables.
 	 */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	/* Limited completion support for partition bound specification */
-	else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
+	else if (TailMatches("ATTACH", "PARTITION", MatchAny))
 		COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
-	else if (TailMatches2("FOR", "VALUES"))
+	else if (TailMatches("FOR", "VALUES"))
 		COMPLETE_WITH_LIST3("FROM (", "IN (", "WITH (");
 
 	/*
 	 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
 	 * partitions of <foo>.
 	 */
-	else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
+	else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
 	{
 		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_partition_of_table);
 	}
 
 	/* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
-	else if (Matches3("ALTER", "TABLESPACE", MatchAny))
+	else if (Matches("ALTER", "TABLESPACE", MatchAny))
 		COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
 	/* ALTER TABLESPACE <foo> SET|RESET */
-	else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
+	else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
 		COMPLETE_WITH_CONST("(");
 	/* ALTER TABLESPACE <foo> SET|RESET ( */
-	else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
+	else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
 		COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
 							"effective_io_concurrency");
 
 	/* ALTER TEXT SEARCH */
-	else if (Matches3("ALTER", "TEXT", "SEARCH"))
+	else if (Matches("ALTER", "TEXT", "SEARCH"))
 		COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
-	else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
+	else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
 		COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
-	else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
+	else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
 		COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
-	else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
+	else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
 		COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
 							"DROP MAPPING FOR",
 							"OWNER TO", "RENAME TO", "SET SCHEMA");
 
 	/* complete ALTER TYPE <foo> with actions */
-	else if (Matches3("ALTER", "TYPE", MatchAny))
+	else if (Matches("ALTER", "TYPE", MatchAny))
 		COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
 							"DROP ATTRIBUTE",
 							"OWNER TO", "RENAME", "SET SCHEMA");
 	/* complete ALTER TYPE <foo> ADD with actions */
-	else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
+	else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
 		COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
 	/* ALTER TYPE <foo> RENAME	*/
-	else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
+	else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
 		COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
 	/* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
-	else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
+	else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
 		COMPLETE_WITH_CONST("TO");
 
 	/*
 	 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
 	 * of attributes
 	 */
-	else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
+	else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
 		COMPLETE_WITH_ATTR(prev3_wd, "");
 	/* ALTER TYPE ALTER ATTRIBUTE <foo> */
-	else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
+	else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
 		COMPLETE_WITH_CONST("TYPE");
 	/* complete ALTER GROUP <foo> */
-	else if (Matches3("ALTER", "GROUP", MatchAny))
+	else if (Matches("ALTER", "GROUP", MatchAny))
 		COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
 	/* complete ALTER GROUP <foo> ADD|DROP with USER */
-	else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
+	else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
 		COMPLETE_WITH_CONST("USER");
 	/* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
-	else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
+	else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 
 	/*
 	 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
 	 */
-	else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
+	else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
 		COMPLETE_WITH_ENUM_VALUE(prev3_wd);
 
 /* BEGIN */
-	else if (Matches1("BEGIN"))
+	else if (Matches("BEGIN"))
 		COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
 /* END, ABORT */
-	else if (Matches1("END|ABORT"))
+	else if (Matches("END|ABORT"))
 		COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
 /* COMMIT */
-	else if (Matches1("COMMIT"))
+	else if (Matches("COMMIT"))
 		COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
 /* RELEASE SAVEPOINT */
-	else if (Matches1("RELEASE"))
+	else if (Matches("RELEASE"))
 		COMPLETE_WITH_CONST("SAVEPOINT");
 /* ROLLBACK */
-	else if (Matches1("ROLLBACK"))
+	else if (Matches("ROLLBACK"))
 		COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
 /* CALL */
-	else if (Matches1("CALL"))
+	else if (Matches("CALL"))
 		COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
-	else if (Matches2("CALL", MatchAny))
+	else if (Matches("CALL", MatchAny))
 		COMPLETE_WITH_CONST("(");
 /* CLUSTER */
-	else if (Matches1("CLUSTER"))
+	else if (Matches("CLUSTER"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
-	else if (Matches2("CLUSTER", "VERBOSE"))
+	else if (Matches("CLUSTER", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
 	/* If we have CLUSTER <sth>, then add "USING" */
-	else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
+	else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
 		COMPLETE_WITH_CONST("USING");
 	/* If we have CLUSTER VERBOSE <sth>, then add "USING" */
-	else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
+	else if (Matches("CLUSTER", "VERBOSE", MatchAny))
 		COMPLETE_WITH_CONST("USING");
 	/* If we have CLUSTER <sth> USING, then add the index as well */
-	else if (Matches3("CLUSTER", MatchAny, "USING") ||
-			 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
+	else if (Matches("CLUSTER", MatchAny, "USING") ||
+			 Matches("CLUSTER", "VERBOSE", MatchAny, "USING"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_index_of_table);
 	}
 
 /* COMMENT */
-	else if (Matches1("COMMENT"))
+	else if (Matches("COMMENT"))
 		COMPLETE_WITH_CONST("ON");
-	else if (Matches2("COMMENT", "ON"))
+	else if (Matches("COMMENT", "ON"))
 	{
 		static const char *const list_COMMENT[] =
 		{"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
@@ -2204,28 +2182,28 @@ psql_completion(const char *text, int start, int end)
 
 		COMPLETE_WITH_LIST(list_COMMENT);
 	}
-	else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
+	else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
-	else if (Matches3("COMMENT", "ON", "FOREIGN"))
+	else if (Matches("COMMENT", "ON", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
-	else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
+	else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
 		COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
-	else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
+	else if (Matches("COMMENT", "ON", "CONSTRAINT"))
 		COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
-	else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
+	else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
 		COMPLETE_WITH_CONST("ON");
-	else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
+	else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
 	}
-	else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
+	else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
-	else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
+	else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
-	else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
-			 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
-			 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
+	else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
+			 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
+			 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
 		COMPLETE_WITH_CONST("IS");
 
 /* COPY */
@@ -2234,92 +2212,92 @@ psql_completion(const char *text, int start, int end)
 	 * If we have COPY, offer list of tables or "(" (Also cover the analogous
 	 * backslash command).
 	 */
-	else if (Matches1("COPY|\\copy"))
+	else if (Matches("COPY|\\copy"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
 								   " UNION ALL SELECT '('");
 	/* If we have COPY BINARY, complete with list of tables */
-	else if (Matches2("COPY", "BINARY"))
+	else if (Matches("COPY", "BINARY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 	/* If we have COPY (, complete it with legal commands */
-	else if (Matches2("COPY|\\copy", "("))
+	else if (Matches("COPY|\\copy", "("))
 		COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
 	/* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
-	else if (Matches2("COPY|\\copy", MatchAny) ||
-			 Matches3("COPY", "BINARY", MatchAny))
+	else if (Matches("COPY|\\copy", MatchAny) ||
+			 Matches("COPY", "BINARY", MatchAny))
 		COMPLETE_WITH_LIST2("FROM", "TO");
 	/* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
-	else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
-			 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
+	else if (Matches("COPY|\\copy", MatchAny, "FROM|TO") ||
+			 Matches("COPY", "BINARY", MatchAny, "FROM|TO"))
 	{
 		completion_charp = "";
 		matches = completion_matches(text, complete_from_files);
 	}
 
 	/* Handle COPY [BINARY] <sth> FROM|TO filename */
-	else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
-			 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
+	else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
+			 Matches("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
 		COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
 							"ENCODING");
 
 	/* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
-	else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
-			 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
+	else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
+			 Matches("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
 		COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
 							"FORCE NOT NULL");
 
 	/* CREATE ACCESS METHOD */
 	/* Complete "CREATE ACCESS METHOD <name>" */
-	else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
+	else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
 		COMPLETE_WITH_CONST("TYPE");
 	/* Complete "CREATE ACCESS METHOD <name> TYPE" */
-	else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
+	else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
 		COMPLETE_WITH_CONST("INDEX");
 	/* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
-	else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
+	else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
 		COMPLETE_WITH_CONST("HANDLER");
 
 	/* CREATE DATABASE */
-	else if (Matches3("CREATE", "DATABASE", MatchAny))
+	else if (Matches("CREATE", "DATABASE", MatchAny))
 		COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
 							"IS_TEMPLATE",
 							"ALLOW_CONNECTIONS", "CONNECTION LIMIT",
 							"LC_COLLATE", "LC_CTYPE");
 
-	else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
+	else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
 
 	/* CREATE EXTENSION */
 	/* Complete with available extensions rather than installed ones. */
-	else if (Matches2("CREATE", "EXTENSION"))
+	else if (Matches("CREATE", "EXTENSION"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
 	/* CREATE EXTENSION <name> */
-	else if (Matches3("CREATE", "EXTENSION", MatchAny))
+	else if (Matches("CREATE", "EXTENSION", MatchAny))
 		COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
 	/* CREATE EXTENSION <name> VERSION */
-	else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
+	else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
 	}
 
 	/* CREATE FOREIGN */
-	else if (Matches2("CREATE", "FOREIGN"))
+	else if (Matches("CREATE", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 
 	/* CREATE FOREIGN DATA WRAPPER */
-	else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+	else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 		COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
 
 	/* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
 	/* First off we complete CREATE UNIQUE with "INDEX" */
-	else if (TailMatches2("CREATE", "UNIQUE"))
+	else if (TailMatches("CREATE", "UNIQUE"))
 		COMPLETE_WITH_CONST("INDEX");
 
 	/*
 	 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
 	 * existing indexes
 	 */
-	else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
+	else if (TailMatches("CREATE|UNIQUE", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
 								   " UNION SELECT 'ON'"
 								   " UNION SELECT 'CONCURRENTLY'");
@@ -2328,294 +2306,294 @@ psql_completion(const char *text, int start, int end)
 	 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
 	 * that can indexes can be created on
 	 */
-	else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
-			 TailMatches2("INDEX|CONCURRENTLY", "ON"))
+	else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
+			 TailMatches("INDEX|CONCURRENTLY", "ON"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tpm, NULL);
 
 	/*
 	 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
 	 * indexes
 	 */
-	else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
+	else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
 								   " UNION SELECT 'ON'");
 	/* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
-	else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
-			 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
+	else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
+			 TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 
 	/*
 	 * Complete INDEX <name> ON <table> with a list of table columns (which
 	 * should really be in parens)
 	 */
-	else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
-			 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
+	else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
+			 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
 		COMPLETE_WITH_LIST2("(", "USING");
-	else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
-			 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
+	else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
+			 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
 		COMPLETE_WITH_ATTR(prev2_wd, "");
 	/* same if you put in USING */
-	else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
+	else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
 		COMPLETE_WITH_ATTR(prev4_wd, "");
 	/* Complete USING with an index method */
-	else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
-			 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
-			 TailMatches4("INDEX", "ON", MatchAny, "USING"))
+	else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
+			 TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
+			 TailMatches("INDEX", "ON", MatchAny, "USING"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
-	else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
-			 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
-			 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
+	else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
+			 !TailMatches("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
+			 !TailMatches("FOR", MatchAny, MatchAny, MatchAny))
 		COMPLETE_WITH_CONST("(");
 
 	/* CREATE POLICY */
 	/* Complete "CREATE POLICY <name> ON" */
-	else if (Matches3("CREATE", "POLICY", MatchAny))
+	else if (Matches("CREATE", "POLICY", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 	/* Complete "CREATE POLICY <name> ON <table>" */
-	else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 	/* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
-	else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
 	/* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
-	else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
 		COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
 
 	/*
 	 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
 	 * FOR|TO|USING|WITH CHECK
 	 */
-	else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
 		COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
 	/* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
-	else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
 		COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
 	/* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
-	else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
 		COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
 	/* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
-	else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
 		COMPLETE_WITH_LIST2("TO", "USING (");
 	/* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
-	else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
 		COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
 	/* Complete "CREATE POLICY <name> ON <table> TO <role>" */
-	else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
 	/* Complete "CREATE POLICY <name> ON <table> USING (" */
-	else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
 		COMPLETE_WITH_CONST("(");
 
 	/*
 	 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
 	 * ALL|SELECT|INSERT|UPDATE|DELETE
 	 */
-	else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
 		COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
 
 	/*
 	 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
 	 * INSERT TO|WITH CHECK"
 	 */
-	else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
 		COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
 
 	/*
 	 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
 	 * SELECT|DELETE TO|USING"
 	 */
-	else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
 		COMPLETE_WITH_LIST2("TO", "USING (");
 
 	/*
 	 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
 	 * ALL|UPDATE TO|USING|WITH CHECK
 	 */
-	else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
 		COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
 
 	/*
 	 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
 	 * <role>"
 	 */
-	else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
 
 	/*
 	 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
 	 * USING ("
 	 */
-	else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
+	else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
 		COMPLETE_WITH_CONST("(");
 
 
 /* CREATE PUBLICATION */
-	else if (Matches3("CREATE", "PUBLICATION", MatchAny))
+	else if (Matches("CREATE", "PUBLICATION", MatchAny))
 		COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
-	else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
+	else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
 		COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
 	/* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
-	else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
+	else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 	/* Complete "CREATE PUBLICATION <name> [...] WITH" */
-	else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
+	else if (HeadMatches("CREATE", "PUBLICATION") && TailMatches("WITH", "("))
 		COMPLETE_WITH_CONST("publish");
 
 /* CREATE RULE */
 	/* Complete "CREATE RULE <sth>" with "AS ON" */
-	else if (Matches3("CREATE", "RULE", MatchAny))
+	else if (Matches("CREATE", "RULE", MatchAny))
 		COMPLETE_WITH_CONST("AS ON");
 	/* Complete "CREATE RULE <sth> AS" with "ON" */
-	else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
+	else if (Matches("CREATE", "RULE", MatchAny, "AS"))
 		COMPLETE_WITH_CONST("ON");
 	/* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
-	else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
+	else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON"))
 		COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
 	/* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
-	else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
+	else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
 		COMPLETE_WITH_CONST("TO");
 	/* Complete "AS ON <sth> TO" with a table name */
-	else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
+	else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 
 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
-	else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
-			 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
+	else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
+			 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
 		COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
 							"CYCLE", "OWNED BY", "START WITH");
-	else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
-			 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
+	else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
+			 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
 		COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
 
 /* CREATE SERVER <name> */
-	else if (Matches3("CREATE", "SERVER", MatchAny))
+	else if (Matches("CREATE", "SERVER", MatchAny))
 		COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
 
 /* CREATE STATISTICS <name> */
-	else if (Matches3("CREATE", "STATISTICS", MatchAny))
+	else if (Matches("CREATE", "STATISTICS", MatchAny))
 		COMPLETE_WITH_LIST2("(", "ON");
-	else if (Matches4("CREATE", "STATISTICS", MatchAny, "("))
+	else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
 		COMPLETE_WITH_LIST2("ndistinct", "dependencies");
-	else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
+	else if (HeadMatches("CREATE", "STATISTICS", MatchAny) &&
 			 previous_words[0][0] == '(' &&
 			 previous_words[0][strlen(previous_words[0]) - 1] == ')')
 		COMPLETE_WITH_CONST("ON");
-	else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
-			 TailMatches1("FROM"))
+	else if (HeadMatches("CREATE", "STATISTICS", MatchAny) &&
+			 TailMatches("FROM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 
 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
 	/* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
-	else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
+	else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
 		COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
 	/* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
-	else if (TailMatches2("CREATE", "UNLOGGED"))
+	else if (TailMatches("CREATE", "UNLOGGED"))
 		COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
 	/* Complete PARTITION BY with RANGE ( or LIST ( or ... */
-	else if (TailMatches2("PARTITION", "BY"))
+	else if (TailMatches("PARTITION", "BY"))
 		COMPLETE_WITH_LIST3("RANGE (", "LIST (", "HASH (");
 	/* If we have xxx PARTITION OF, provide a list of partitioned tables */
-	else if (TailMatches2("PARTITION", "OF"))
+	else if (TailMatches("PARTITION", "OF"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
 	/* Limited completion support for partition bound specification */
-	else if (TailMatches3("PARTITION", "OF", MatchAny))
+	else if (TailMatches("PARTITION", "OF", MatchAny))
 		COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
 
 /* CREATE TABLESPACE */
-	else if (Matches3("CREATE", "TABLESPACE", MatchAny))
+	else if (Matches("CREATE", "TABLESPACE", MatchAny))
 		COMPLETE_WITH_LIST2("OWNER", "LOCATION");
 	/* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
-	else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
+	else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
 		COMPLETE_WITH_CONST("LOCATION");
 
 /* CREATE TEXT SEARCH */
-	else if (Matches3("CREATE", "TEXT", "SEARCH"))
+	else if (Matches("CREATE", "TEXT", "SEARCH"))
 		COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
-	else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
+	else if (Matches("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
 		COMPLETE_WITH_CONST("(");
 
 /* CREATE SUBSCRIPTION */
-	else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
+	else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
 		COMPLETE_WITH_CONST("CONNECTION");
-	else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
+	else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
 		COMPLETE_WITH_CONST("PUBLICATION");
-	else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
+	else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
 					  MatchAny, "PUBLICATION"))
 	{
 		/* complete with nothing here as this refers to remote publications */
 	}
-	else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("PUBLICATION", MatchAny))
+	else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("PUBLICATION", MatchAny))
 		COMPLETE_WITH_CONST("WITH (");
 	/* Complete "CREATE SUBSCRIPTION <name> ...  WITH ( <opt>" */
-	else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
+	else if (HeadMatches("CREATE", "SUBSCRIPTION") && TailMatches("WITH", "("))
 		COMPLETE_WITH_LIST6("copy_data", "connect", "create_slot", "enabled",
 							"slot_name", "synchronous_commit");
 
 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
 	/* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
-	else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
+	else if (TailMatches("CREATE", "TRIGGER", MatchAny))
 		COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
 	/* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
-	else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
+	else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
 		COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
 	/* complete CREATE TRIGGER <name> INSTEAD OF with an event */
-	else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
+	else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
 		COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
 	/* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
-	else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
-			 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
+	else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
+			 TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
 		COMPLETE_WITH_LIST2("ON", "OR");
 
 	/*
 	 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
 	 * tables
 	 */
-	else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
+	else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 	/* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
-	else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
+	else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("ON", MatchAny))
 		COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
 							"REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
-	else if (HeadMatches2("CREATE", "TRIGGER") &&
-			 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
+	else if (HeadMatches("CREATE", "TRIGGER") &&
+			 (TailMatches("DEFERRABLE") || TailMatches("INITIALLY", "IMMEDIATE|DEFERRED")))
 		COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("REFERENCING"))
 		COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("OLD|NEW", "TABLE"))
 		COMPLETE_WITH_CONST("AS");
-	else if (HeadMatches2("CREATE", "TRIGGER") &&
-			 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
-			  TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
+	else if (HeadMatches("CREATE", "TRIGGER") &&
+			 (TailMatches("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
+			  TailMatches("REFERENCING", "OLD", "TABLE", MatchAny)))
 		COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
-	else if (HeadMatches2("CREATE", "TRIGGER") &&
-			 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
-			  TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
+	else if (HeadMatches("CREATE", "TRIGGER") &&
+			 (TailMatches("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
+			  TailMatches("REFERENCING", "NEW", "TABLE", MatchAny)))
 		COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
-	else if (HeadMatches2("CREATE", "TRIGGER") &&
-			 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
-			  TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
-			  TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
-			  TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
+	else if (HeadMatches("CREATE", "TRIGGER") &&
+			 (TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
+			  TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
+			  TailMatches("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
+			  TailMatches("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
 		COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("FOR"))
 		COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("FOR", "EACH"))
 		COMPLETE_WITH_LIST2("ROW", "STATEMENT");
-	else if (HeadMatches2("CREATE", "TRIGGER") &&
-			 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
-			  TailMatches2("FOR", "ROW|STATEMENT")))
+	else if (HeadMatches("CREATE", "TRIGGER") &&
+			 (TailMatches("FOR", "EACH", "ROW|STATEMENT") ||
+			  TailMatches("FOR", "ROW|STATEMENT")))
 		COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
 	/* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("EXECUTE"))
 		COMPLETE_WITH_CONST("PROCEDURE");
-	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
+	else if (HeadMatches("CREATE", "TRIGGER") && TailMatches("EXECUTE", "PROCEDURE"))
 		COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
 
 /* CREATE ROLE,USER,GROUP <name> */
-	else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
-			 !TailMatches2("USER", "MAPPING"))
+	else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
+			 !TailMatches("USER", "MAPPING"))
 	{
 		static const char *const list_CREATEROLE[] =
 		{"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
@@ -2629,7 +2607,7 @@ psql_completion(const char *text, int start, int end)
 	}
 
 /* CREATE ROLE,USER,GROUP <name> WITH */
-	else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
+	else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
 	{
 		/* Similar to the above, but don't complete "WITH" again. */
 		static const char *const list_CREATEROLE_WITH[] =
@@ -2644,166 +2622,166 @@ psql_completion(const char *text, int start, int end)
 	}
 
 	/* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
-	else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
+	else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
 		COMPLETE_WITH_LIST2("GROUP", "ROLE");
 
 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
 	/* Complete CREATE VIEW <name> with AS */
-	else if (TailMatches3("CREATE", "VIEW", MatchAny))
+	else if (TailMatches("CREATE", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("AS");
 	/* Complete "CREATE VIEW <sth> AS with "SELECT" */
-	else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
+	else if (TailMatches("CREATE", "VIEW", MatchAny, "AS"))
 		COMPLETE_WITH_CONST("SELECT");
 
 /* CREATE MATERIALIZED VIEW */
-	else if (Matches2("CREATE", "MATERIALIZED"))
+	else if (Matches("CREATE", "MATERIALIZED"))
 		COMPLETE_WITH_CONST("VIEW");
 	/* Complete CREATE MATERIALIZED VIEW <name> with AS */
-	else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
+	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("AS");
 	/* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
-	else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
+	else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
 		COMPLETE_WITH_CONST("SELECT");
 
 /* CREATE EVENT TRIGGER */
-	else if (Matches2("CREATE", "EVENT"))
+	else if (Matches("CREATE", "EVENT"))
 		COMPLETE_WITH_CONST("TRIGGER");
 	/* Complete CREATE EVENT TRIGGER <name> with ON */
-	else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
+	else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 	/* Complete CREATE EVENT TRIGGER <name> ON with event_type */
-	else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
+	else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
 		COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
 
 /* DEALLOCATE */
-	else if (Matches1("DEALLOCATE"))
+	else if (Matches("DEALLOCATE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
 
 /* DECLARE */
-	else if (Matches2("DECLARE", MatchAny))
+	else if (Matches("DECLARE", MatchAny))
 		COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
 							"CURSOR");
-	else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
+	else if (HeadMatches("DECLARE") && TailMatches("CURSOR"))
 		COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
 
 /* DELETE --- can be inside EXPLAIN, RULE, etc */
 	/* ... despite which, only complete DELETE with FROM at start of line */
-	else if (Matches1("DELETE"))
+	else if (Matches("DELETE"))
 		COMPLETE_WITH_CONST("FROM");
 	/* Complete DELETE FROM with a list of tables */
-	else if (TailMatches2("DELETE", "FROM"))
+	else if (TailMatches("DELETE", "FROM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
 	/* Complete DELETE FROM <table> */
-	else if (TailMatches3("DELETE", "FROM", MatchAny))
+	else if (TailMatches("DELETE", "FROM", MatchAny))
 		COMPLETE_WITH_LIST2("USING", "WHERE");
 	/* XXX: implement tab completion for DELETE ... USING */
 
 /* DISCARD */
-	else if (Matches1("DISCARD"))
+	else if (Matches("DISCARD"))
 		COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
 
 /* DO */
-	else if (Matches1("DO"))
+	else if (Matches("DO"))
 		COMPLETE_WITH_CONST("LANGUAGE");
 
 /* DROP */
 	/* Complete DROP object with CASCADE / RESTRICT */
-	else if (Matches3("DROP",
+	else if (Matches("DROP",
 					  "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
 					  MatchAny) ||
-			 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
-			 (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
+			 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
+			 (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
 			  ends_with(prev_wd, ')')) ||
-			 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
-			 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
-			 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
-			 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
+			 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_LIST2("CASCADE", "RESTRICT");
 
 	/* help completing some of the variants */
-	else if (Matches3("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
+	else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
 		COMPLETE_WITH_CONST("(");
-	else if (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
+	else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
 		COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
-	else if (Matches2("DROP", "FOREIGN"))
+	else if (Matches("DROP", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 
 	/* DROP INDEX */
-	else if (Matches2("DROP", "INDEX"))
+	else if (Matches("DROP", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
 								   " UNION SELECT 'CONCURRENTLY'");
-	else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
+	else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
-	else if (Matches3("DROP", "INDEX", MatchAny))
+	else if (Matches("DROP", "INDEX", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
-	else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
+	else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
 
 	/* DROP MATERIALIZED VIEW */
-	else if (Matches2("DROP", "MATERIALIZED"))
+	else if (Matches("DROP", "MATERIALIZED"))
 		COMPLETE_WITH_CONST("VIEW");
-	else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
+	else if (Matches("DROP", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
 
 	/* DROP OWNED BY */
-	else if (Matches2("DROP", "OWNED"))
+	else if (Matches("DROP", "OWNED"))
 		COMPLETE_WITH_CONST("BY");
-	else if (Matches3("DROP", "OWNED", "BY"))
+	else if (Matches("DROP", "OWNED", "BY"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 
 	/* DROP TEXT SEARCH */
-	else if (Matches3("DROP", "TEXT", "SEARCH"))
+	else if (Matches("DROP", "TEXT", "SEARCH"))
 		COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
 
 	/* DROP TRIGGER */
-	else if (Matches3("DROP", "TRIGGER", MatchAny))
+	else if (Matches("DROP", "TRIGGER", MatchAny))
 		COMPLETE_WITH_CONST("ON");
-	else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
+	else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
 	}
-	else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
+	else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
 
 	/* DROP ACCESS METHOD */
-	else if (Matches2("DROP", "ACCESS"))
+	else if (Matches("DROP", "ACCESS"))
 		COMPLETE_WITH_CONST("METHOD");
-	else if (Matches3("DROP", "ACCESS", "METHOD"))
+	else if (Matches("DROP", "ACCESS", "METHOD"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
 
 	/* DROP EVENT TRIGGER */
-	else if (Matches2("DROP", "EVENT"))
+	else if (Matches("DROP", "EVENT"))
 		COMPLETE_WITH_CONST("TRIGGER");
-	else if (Matches3("DROP", "EVENT", "TRIGGER"))
+	else if (Matches("DROP", "EVENT", "TRIGGER"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
 
 	/* DROP POLICY <name>  */
-	else if (Matches2("DROP", "POLICY"))
+	else if (Matches("DROP", "POLICY"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_policies);
 	/* DROP POLICY <name> ON */
-	else if (Matches3("DROP", "POLICY", MatchAny))
+	else if (Matches("DROP", "POLICY", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 	/* DROP POLICY <name> ON <table> */
-	else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
+	else if (Matches("DROP", "POLICY", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
 	}
 
 	/* DROP RULE */
-	else if (Matches3("DROP", "RULE", MatchAny))
+	else if (Matches("DROP", "RULE", MatchAny))
 		COMPLETE_WITH_CONST("ON");
-	else if (Matches4("DROP", "RULE", MatchAny, "ON"))
+	else if (Matches("DROP", "RULE", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
 		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
 	}
-	else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
+	else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
 
 /* EXECUTE */
-	else if (Matches1("EXECUTE"))
+	else if (Matches("EXECUTE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
 
 /* EXPLAIN */
@@ -2811,22 +2789,22 @@ psql_completion(const char *text, int start, int end)
 	/*
 	 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
 	 */
-	else if (Matches1("EXPLAIN"))
+	else if (Matches("EXPLAIN"))
 		COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
 							"ANALYZE", "VERBOSE");
-	else if (Matches2("EXPLAIN", "ANALYZE"))
+	else if (Matches("EXPLAIN", "ANALYZE"))
 		COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
 							"VERBOSE");
-	else if (Matches2("EXPLAIN", "VERBOSE") ||
-			 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
+	else if (Matches("EXPLAIN", "VERBOSE") ||
+			 Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
 		COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
 
 /* FETCH && MOVE */
 	/* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
-	else if (Matches1("FETCH|MOVE"))
+	else if (Matches("FETCH|MOVE"))
 		COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
 	/* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
-	else if (Matches2("FETCH|MOVE", MatchAny))
+	else if (Matches("FETCH|MOVE", MatchAny))
 		COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
 
 	/*
@@ -2834,26 +2812,26 @@ psql_completion(const char *text, int start, int end)
 	 * but we may as well tab-complete both: perhaps some users prefer one
 	 * variant or the other.
 	 */
-	else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
+	else if (Matches("FETCH|MOVE", MatchAny, MatchAny))
 		COMPLETE_WITH_LIST2("FROM", "IN");
 
 /* FOREIGN DATA WRAPPER */
 	/* applies in ALTER/DROP FDW and in CREATE SERVER */
-	else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
-			 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
+	else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
+			 !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
 		COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
 	/* applies in CREATE SERVER */
-	else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
-			 HeadMatches2("CREATE", "SERVER"))
+	else if (TailMatches("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
+			 HeadMatches("CREATE", "SERVER"))
 		COMPLETE_WITH_CONST("OPTIONS");
 
 /* FOREIGN TABLE */
-	else if (TailMatches2("FOREIGN", "TABLE") &&
-			 !TailMatches3("CREATE", MatchAny, MatchAny))
+	else if (TailMatches("FOREIGN", "TABLE") &&
+			 !TailMatches("CREATE", MatchAny, MatchAny))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
 
 /* FOREIGN SERVER */
-	else if (TailMatches2("FOREIGN", "SERVER"))
+	else if (TailMatches("FOREIGN", "SERVER"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_servers);
 
 /*
@@ -2861,13 +2839,13 @@ psql_completion(const char *text, int start, int end)
  * ALTER DEFAULT PRIVILEGES, so use TailMatches
  */
 	/* Complete GRANT/REVOKE with a list of roles and privileges */
-	else if (TailMatches1("GRANT|REVOKE"))
+	else if (TailMatches("GRANT|REVOKE"))
 	{
 		/*
 		 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
 		 * privileges (can't grant roles)
 		 */
-		if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
+		if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
 			COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
 								 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
 								 "EXECUTE", "USAGE", "ALL");
@@ -2892,11 +2870,11 @@ psql_completion(const char *text, int start, int end)
 	 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
 	 * TO/FROM
 	 */
-	else if (TailMatches2("GRANT|REVOKE", MatchAny))
+	else if (TailMatches("GRANT|REVOKE", MatchAny))
 	{
-		if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
+		if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
 			COMPLETE_WITH_CONST("ON");
-		else if (TailMatches2("GRANT", MatchAny))
+		else if (TailMatches("GRANT", MatchAny))
 			COMPLETE_WITH_CONST("TO");
 		else
 			COMPLETE_WITH_CONST("FROM");
@@ -2913,13 +2891,13 @@ psql_completion(const char *text, int start, int end)
 	 * here will only work if the privilege list contains exactly one
 	 * privilege.
 	 */
-	else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON"))
 	{
 		/*
 		 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
 		 * objects supported.
 		 */
-		if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
+		if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
 			COMPLETE_WITH_LIST7("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
 		else
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
@@ -2943,13 +2921,13 @@ psql_completion(const char *text, int start, int end)
 									   " UNION SELECT 'TABLESPACE'"
 									   " UNION SELECT 'TYPE'");
 	}
-	else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL"))
 		COMPLETE_WITH_LIST5("FUNCTIONS IN SCHEMA",
 							"PROCEDURES IN SCHEMA",
 							"ROUTINES IN SCHEMA",
 							"SEQUENCES IN SCHEMA",
 							"TABLES IN SCHEMA");
-	else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
 
 	/*
@@ -2958,31 +2936,31 @@ psql_completion(const char *text, int start, int end)
 	 *
 	 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
 	 */
-	else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny))
 	{
-		if (TailMatches1("DATABASE"))
+		if (TailMatches("DATABASE"))
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
-		else if (TailMatches1("DOMAIN"))
+		else if (TailMatches("DOMAIN"))
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
-		else if (TailMatches1("FUNCTION"))
+		else if (TailMatches("FUNCTION"))
 			COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
-		else if (TailMatches1("LANGUAGE"))
+		else if (TailMatches("LANGUAGE"))
 			COMPLETE_WITH_QUERY(Query_for_list_of_languages);
-		else if (TailMatches1("PROCEDURE"))
+		else if (TailMatches("PROCEDURE"))
 			COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
-		else if (TailMatches1("ROUTINE"))
+		else if (TailMatches("ROUTINE"))
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
-		else if (TailMatches1("SCHEMA"))
+		else if (TailMatches("SCHEMA"))
 			COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
-		else if (TailMatches1("SEQUENCE"))
+		else if (TailMatches("SEQUENCE"))
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
-		else if (TailMatches1("TABLE"))
+		else if (TailMatches("TABLE"))
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
-		else if (TailMatches1("TABLESPACE"))
+		else if (TailMatches("TABLESPACE"))
 			COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
-		else if (TailMatches1("TYPE"))
+		else if (TailMatches("TYPE"))
 			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
-		else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
+		else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH_CONST("TO");
 		else
 			COMPLETE_WITH_CONST("FROM");
@@ -2992,111 +2970,111 @@ psql_completion(const char *text, int start, int end)
 	 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
 	 * CURRENT_USER, or SESSION_USER.
 	 */
-	else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
-			 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
+	else if ((HeadMatches("GRANT") && TailMatches("TO")) ||
+			 (HeadMatches("REVOKE") && TailMatches("FROM")))
 		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
 	/* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
-	else if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
+	else if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches("TO|FROM"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
 	/* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
-	else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
+	else if (HeadMatches("GRANT") && TailMatches("ON", MatchAny, MatchAny))
 		COMPLETE_WITH_CONST("TO");
-	else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
+	else if (HeadMatches("REVOKE") && TailMatches("ON", MatchAny, MatchAny))
 		COMPLETE_WITH_CONST("FROM");
 
 	/* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
-	else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
 	{
-		if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH_CONST("TO");
 		else
 			COMPLETE_WITH_CONST("FROM");
 	}
 
 	/* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
-	else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 	{
-		if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH_CONST("TO");
 		else
 			COMPLETE_WITH_CONST("FROM");
 	}
 
 	/* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
-	else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
+	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
 	{
-		if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH_CONST("TO");
 		else
 			COMPLETE_WITH_CONST("FROM");
 	}
 
 /* GROUP BY */
-	else if (TailMatches3("FROM", MatchAny, "GROUP"))
+	else if (TailMatches("FROM", MatchAny, "GROUP"))
 		COMPLETE_WITH_CONST("BY");
 
 /* IMPORT FOREIGN SCHEMA */
-	else if (Matches1("IMPORT"))
+	else if (Matches("IMPORT"))
 		COMPLETE_WITH_CONST("FOREIGN SCHEMA");
-	else if (Matches2("IMPORT", "FOREIGN"))
+	else if (Matches("IMPORT", "FOREIGN"))
 		COMPLETE_WITH_CONST("SCHEMA");
 
 /* INSERT --- can be inside EXPLAIN, RULE, etc */
 	/* Complete INSERT with "INTO" */
-	else if (TailMatches1("INSERT"))
+	else if (TailMatches("INSERT"))
 		COMPLETE_WITH_CONST("INTO");
 	/* Complete INSERT INTO with table names */
-	else if (TailMatches2("INSERT", "INTO"))
+	else if (TailMatches("INSERT", "INTO"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
 	/* Complete "INSERT INTO <table> (" with attribute names */
-	else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
+	else if (TailMatches("INSERT", "INTO", MatchAny, "("))
 		COMPLETE_WITH_ATTR(prev2_wd, "");
 
 	/*
 	 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
 	 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
 	 */
-	else if (TailMatches3("INSERT", "INTO", MatchAny))
+	else if (TailMatches("INSERT", "INTO", MatchAny))
 		COMPLETE_WITH_LIST6("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
 
 	/*
 	 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
 	 * "TABLE" or "OVERRIDING"
 	 */
-	else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
+	else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
 			 ends_with(prev_wd, ')'))
 		COMPLETE_WITH_LIST4("SELECT", "TABLE", "VALUES", "OVERRIDING");
 
 	/* Complete OVERRIDING */
-	else if (TailMatches1("OVERRIDING"))
+	else if (TailMatches("OVERRIDING"))
 		COMPLETE_WITH_LIST2("SYSTEM VALUE", "USER VALUE");
 
 	/* Complete after OVERRIDING clause */
-	else if (TailMatches3("OVERRIDING", MatchAny, "VALUE"))
+	else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
 		COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
 
 	/* Insert an open parenthesis after "VALUES" */
-	else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
+	else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
 		COMPLETE_WITH_CONST("(");
 
 /* LOCK */
 	/* Complete LOCK [TABLE] with a list of tables */
-	else if (Matches1("LOCK"))
+	else if (Matches("LOCK"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
 								   " UNION SELECT 'TABLE'");
-	else if (Matches2("LOCK", "TABLE"))
+	else if (Matches("LOCK", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
 	/* For the following, handle the case of a single table only for now */
 
 	/* Complete LOCK [TABLE] <table> with "IN" */
-	else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
-			 Matches3("LOCK", "TABLE", MatchAny))
+	else if (Matches("LOCK", MatchAnyExcept("TABLE")) ||
+			 Matches("LOCK", "TABLE", MatchAny))
 		COMPLETE_WITH_CONST("IN");
 
 	/* Complete LOCK [TABLE] <table> IN with a lock mode */
-	else if (Matches3("LOCK", MatchAny, "IN") ||
-			 Matches4("LOCK", "TABLE", MatchAny, "IN"))
+	else if (Matches("LOCK", MatchAny, "IN") ||
+			 Matches("LOCK", "TABLE", MatchAny, "IN"))
 		COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
 							"ROW SHARE MODE", "ROW EXCLUSIVE MODE",
 							"SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
@@ -3104,36 +3082,36 @@ psql_completion(const char *text, int start, int end)
 							"EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
 
 	/* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
-	else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
-			 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
+	else if (Matches("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
+			 Matches("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
 		COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
 
 	/* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
-	else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
-			 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
+	else if (Matches("LOCK", MatchAny, "IN", "SHARE") ||
+			 Matches("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
 		COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
 							"UPDATE EXCLUSIVE MODE");
 
 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
-	else if (TailMatches1("NOTIFY"))
+	else if (TailMatches("NOTIFY"))
 		COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s'");
 
 /* OPTIONS */
-	else if (TailMatches1("OPTIONS"))
+	else if (TailMatches("OPTIONS"))
 		COMPLETE_WITH_CONST("(");
 
 /* OWNER TO  - complete with available roles */
-	else if (TailMatches2("OWNER", "TO"))
+	else if (TailMatches("OWNER", "TO"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 
 /* ORDER BY */
-	else if (TailMatches3("FROM", MatchAny, "ORDER"))
+	else if (TailMatches("FROM", MatchAny, "ORDER"))
 		COMPLETE_WITH_CONST("BY");
-	else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
+	else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
 		COMPLETE_WITH_ATTR(prev3_wd, "");
 
 /* PREPARE xx AS */
-	else if (Matches3("PREPARE", MatchAny, "AS"))
+	else if (Matches("PREPARE", MatchAny, "AS"))
 		COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
 
 /*
@@ -3142,61 +3120,61 @@ psql_completion(const char *text, int start, int end)
  */
 
 /* REASSIGN OWNED BY xxx TO yyy */
-	else if (Matches1("REASSIGN"))
+	else if (Matches("REASSIGN"))
 		COMPLETE_WITH_CONST("OWNED BY");
-	else if (Matches2("REASSIGN", "OWNED"))
+	else if (Matches("REASSIGN", "OWNED"))
 		COMPLETE_WITH_CONST("BY");
-	else if (Matches3("REASSIGN", "OWNED", "BY"))
+	else if (Matches("REASSIGN", "OWNED", "BY"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
-	else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
+	else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
 		COMPLETE_WITH_CONST("TO");
-	else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
+	else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 
 /* REFRESH MATERIALIZED VIEW */
-	else if (Matches1("REFRESH"))
+	else if (Matches("REFRESH"))
 		COMPLETE_WITH_CONST("MATERIALIZED VIEW");
-	else if (Matches2("REFRESH", "MATERIALIZED"))
+	else if (Matches("REFRESH", "MATERIALIZED"))
 		COMPLETE_WITH_CONST("VIEW");
-	else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
 								   " UNION SELECT 'CONCURRENTLY'");
-	else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
-	else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("WITH");
-	else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
 		COMPLETE_WITH_CONST("WITH");
-	else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
 		COMPLETE_WITH_LIST2("NO DATA", "DATA");
-	else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
 		COMPLETE_WITH_LIST2("NO DATA", "DATA");
-	else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
 		COMPLETE_WITH_CONST("DATA");
-	else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
+	else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
 		COMPLETE_WITH_CONST("DATA");
 
 /* REINDEX */
-	else if (Matches1("REINDEX"))
+	else if (Matches("REINDEX"))
 		COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
-	else if (Matches2("REINDEX", "TABLE"))
+	else if (Matches("REINDEX", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
-	else if (Matches2("REINDEX", "INDEX"))
+	else if (Matches("REINDEX", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
-	else if (Matches2("REINDEX", "SCHEMA"))
+	else if (Matches("REINDEX", "SCHEMA"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
-	else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
+	else if (Matches("REINDEX", "SYSTEM|DATABASE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 
 /* SECURITY LABEL */
-	else if (Matches1("SECURITY"))
+	else if (Matches("SECURITY"))
 		COMPLETE_WITH_CONST("LABEL");
-	else if (Matches2("SECURITY", "LABEL"))
+	else if (Matches("SECURITY", "LABEL"))
 		COMPLETE_WITH_LIST2("ON", "FOR");
-	else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
+	else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
 		COMPLETE_WITH_CONST("ON");
-	else if (Matches3("SECURITY", "LABEL", "ON") ||
-			 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
+	else if (Matches("SECURITY", "LABEL", "ON") ||
+			 Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
 	{
 		static const char *const list_SECURITY_LABEL[] =
 		{"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
@@ -3206,7 +3184,7 @@ psql_completion(const char *text, int start, int end)
 
 		COMPLETE_WITH_LIST(list_SECURITY_LABEL);
 	}
-	else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
+	else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
 		COMPLETE_WITH_CONST("IS");
 
 /* SELECT */
@@ -3214,76 +3192,76 @@ psql_completion(const char *text, int start, int end)
 
 /* SET, RESET, SHOW */
 	/* Complete with a variable name */
-	else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
+	else if (TailMatches("SET|RESET") && !TailMatches("UPDATE", MatchAny, "SET"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
-	else if (Matches1("SHOW"))
+	else if (Matches("SHOW"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
 	/* Complete "SET TRANSACTION" */
-	else if (Matches2("SET", "TRANSACTION"))
+	else if (Matches("SET", "TRANSACTION"))
 		COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
-	else if (Matches2("BEGIN|START", "TRANSACTION") ||
-			 Matches2("BEGIN", "WORK") ||
-			 Matches1("BEGIN") ||
-			 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
+	else if (Matches("BEGIN|START", "TRANSACTION") ||
+			 Matches("BEGIN", "WORK") ||
+			 Matches("BEGIN") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
 		COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
-	else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
-			 Matches2("BEGIN", "NOT") ||
-			 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
+	else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
+			 Matches("BEGIN", "NOT") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
 		COMPLETE_WITH_CONST("DEFERRABLE");
-	else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
-			 Matches2("BEGIN", "ISOLATION") ||
-			 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
+	else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
+			 Matches("BEGIN", "ISOLATION") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
 		COMPLETE_WITH_CONST("LEVEL");
-	else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
-			 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
-			 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
+	else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
+			 Matches("BEGIN", "ISOLATION", "LEVEL") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
 		COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
-	else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
-			 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
-			 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
+	else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
+			 Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
 		COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
-	else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
-			 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
-			 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
+	else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
+			 Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
 		COMPLETE_WITH_CONST("READ");
-	else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
-			 Matches2("BEGIN", "READ") ||
-			 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
+	else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
+			 Matches("BEGIN", "READ") ||
+			 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
 		COMPLETE_WITH_LIST2("ONLY", "WRITE");
 	/* SET CONSTRAINTS */
-	else if (Matches2("SET", "CONSTRAINTS"))
+	else if (Matches("SET", "CONSTRAINTS"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
 	/* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
-	else if (Matches3("SET", "CONSTRAINTS", MatchAny))
+	else if (Matches("SET", "CONSTRAINTS", MatchAny))
 		COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
 	/* Complete SET ROLE */
-	else if (Matches2("SET", "ROLE"))
+	else if (Matches("SET", "ROLE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 	/* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
-	else if (Matches2("SET", "SESSION"))
+	else if (Matches("SET", "SESSION"))
 		COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
 	/* Complete SET SESSION AUTHORIZATION with username */
-	else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
+	else if (Matches("SET", "SESSION", "AUTHORIZATION"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
 	/* Complete RESET SESSION with AUTHORIZATION */
-	else if (Matches2("RESET", "SESSION"))
+	else if (Matches("RESET", "SESSION"))
 		COMPLETE_WITH_CONST("AUTHORIZATION");
 	/* Complete SET <var> with "TO" */
-	else if (Matches2("SET", MatchAny))
+	else if (Matches("SET", MatchAny))
 		COMPLETE_WITH_CONST("TO");
 
 	/*
 	 * Complete ALTER DATABASE|FUNCTION||PROCEDURE|ROLE|ROUTINE|USER ... SET
 	 * <name>
 	 */
-	else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
-			 TailMatches2("SET", MatchAny))
+	else if (HeadMatches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
+			 TailMatches("SET", MatchAny))
 		COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
 	/* Suggest possible variable values */
-	else if (TailMatches3("SET", MatchAny, "TO|="))
+	else if (TailMatches("SET", MatchAny, "TO|="))
 	{
 		/* special cased code for individual GUCs */
-		if (TailMatches2("DateStyle", "TO|="))
+		if (TailMatches("DateStyle", "TO|="))
 		{
 			static const char *const my_list[] =
 			{"ISO", "SQL", "Postgres", "German",
@@ -3293,7 +3271,7 @@ psql_completion(const char *text, int start, int end)
 
 			COMPLETE_WITH_LIST(my_list);
 		}
-		else if (TailMatches2("search_path", "TO|="))
+		else if (TailMatches("search_path", "TO|="))
 			COMPLETE_WITH_QUERY(Query_for_list_of_schemas
 								" AND nspname not like 'pg\\_toast%%' "
 								" AND nspname not like 'pg\\_temp%%' "
@@ -3322,83 +3300,83 @@ psql_completion(const char *text, int start, int end)
 	}
 
 /* START TRANSACTION */
-	else if (Matches1("START"))
+	else if (Matches("START"))
 		COMPLETE_WITH_CONST("TRANSACTION");
 
 /* TABLE, but not TABLE embedded in other commands */
-	else if (Matches1("TABLE"))
+	else if (Matches("TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
 
 /* TABLESAMPLE */
-	else if (TailMatches1("TABLESAMPLE"))
+	else if (TailMatches("TABLESAMPLE"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
-	else if (TailMatches2("TABLESAMPLE", MatchAny))
+	else if (TailMatches("TABLESAMPLE", MatchAny))
 		COMPLETE_WITH_CONST("(");
 
 /* TRUNCATE */
-	else if (Matches1("TRUNCATE"))
+	else if (Matches("TRUNCATE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 
 /* UNLISTEN */
-	else if (Matches1("UNLISTEN"))
+	else if (Matches("UNLISTEN"))
 		COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s' UNION SELECT '*'");
 
 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
 	/* If prev. word is UPDATE suggest a list of tables */
-	else if (TailMatches1("UPDATE"))
+	else if (TailMatches("UPDATE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
 	/* Complete UPDATE <table> with "SET" */
-	else if (TailMatches2("UPDATE", MatchAny))
+	else if (TailMatches("UPDATE", MatchAny))
 		COMPLETE_WITH_CONST("SET");
 	/* Complete UPDATE <table> SET with list of attributes */
-	else if (TailMatches3("UPDATE", MatchAny, "SET"))
+	else if (TailMatches("UPDATE", MatchAny, "SET"))
 		COMPLETE_WITH_ATTR(prev2_wd, "");
 	/* UPDATE <table> SET <attr> = */
-	else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
+	else if (TailMatches("UPDATE", MatchAny, "SET", MatchAny))
 		COMPLETE_WITH_CONST("=");
 
 /* USER MAPPING */
-	else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
+	else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
 		COMPLETE_WITH_CONST("FOR");
-	else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
+	else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles
 							" UNION SELECT 'CURRENT_USER'"
 							" UNION SELECT 'PUBLIC'"
 							" UNION SELECT 'USER'");
-	else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
+	else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
-	else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
+	else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
 		COMPLETE_WITH_CONST("SERVER");
-	else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
+	else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
 		COMPLETE_WITH_CONST("OPTIONS");
 
 /*
  * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
  * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
  */
-	else if (Matches1("VACUUM"))
+	else if (Matches("VACUUM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
 								   " UNION SELECT 'FULL'"
 								   " UNION SELECT 'FREEZE'"
 								   " UNION SELECT 'ANALYZE'"
 								   " UNION SELECT 'VERBOSE'");
-	else if (Matches2("VACUUM", "FULL|FREEZE"))
+	else if (Matches("VACUUM", "FULL|FREEZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
 								   " UNION SELECT 'ANALYZE'"
 								   " UNION SELECT 'VERBOSE'");
-	else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
+	else if (Matches("VACUUM", "FULL|FREEZE", "ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
 								   " UNION SELECT 'VERBOSE'");
-	else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
+	else if (Matches("VACUUM", "FULL|FREEZE", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
 								   " UNION SELECT 'ANALYZE'");
-	else if (Matches2("VACUUM", "VERBOSE"))
+	else if (Matches("VACUUM", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
 								   " UNION SELECT 'ANALYZE'");
-	else if (Matches2("VACUUM", "ANALYZE"))
+	else if (Matches("VACUUM", "ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
 								   " UNION SELECT 'VERBOSE'");
-	else if (HeadMatches1("VACUUM"))
+	else if (HeadMatches("VACUUM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
 
 /* WITH [RECURSIVE] */
@@ -3407,114 +3385,114 @@ psql_completion(const char *text, int start, int end)
 	 * Only match when WITH is the first word, as WITH may appear in many
 	 * other contexts.
 	 */
-	else if (Matches1("WITH"))
+	else if (Matches("WITH"))
 		COMPLETE_WITH_CONST("RECURSIVE");
 
 /* ANALYZE */
 	/* Complete with list of tables */
-	else if (Matches1("ANALYZE"))
+	else if (Matches("ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
 
 /* WHERE */
 	/* Simple case of the word before the where being the table name */
-	else if (TailMatches2(MatchAny, "WHERE"))
+	else if (TailMatches(MatchAny, "WHERE"))
 		COMPLETE_WITH_ATTR(prev2_wd, "");
 
 /* ... FROM ... */
 /* TODO: also include SRF ? */
-	else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
+	else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
 
 /* ... JOIN ... */
-	else if (TailMatches1("JOIN"))
+	else if (TailMatches("JOIN"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
 
 /* Backslash commands */
 /* TODO:  \dc \dd \dl */
-	else if (TailMatchesCS1("\\?"))
+	else if (TailMatchesCS("\\?"))
 		COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
-	else if (TailMatchesCS1("\\connect|\\c"))
+	else if (TailMatchesCS("\\connect|\\c"))
 	{
 		if (!recognized_connection_string(text))
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
 	}
-	else if (TailMatchesCS2("\\connect|\\c", MatchAny))
+	else if (TailMatchesCS("\\connect|\\c", MatchAny))
 	{
 		if (!recognized_connection_string(prev_wd))
 			COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 	}
-	else if (TailMatchesCS1("\\da*"))
+	else if (TailMatchesCS("\\da*"))
 		COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
-	else if (TailMatchesCS1("\\dA*"))
+	else if (TailMatchesCS("\\dA*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
-	else if (TailMatchesCS1("\\db*"))
+	else if (TailMatchesCS("\\db*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
-	else if (TailMatchesCS1("\\dD*"))
+	else if (TailMatchesCS("\\dD*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
-	else if (TailMatchesCS1("\\des*"))
+	else if (TailMatchesCS("\\des*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_servers);
-	else if (TailMatchesCS1("\\deu*"))
+	else if (TailMatchesCS("\\deu*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
-	else if (TailMatchesCS1("\\dew*"))
+	else if (TailMatchesCS("\\dew*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
-	else if (TailMatchesCS1("\\df*"))
+	else if (TailMatchesCS("\\df*"))
 		COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
 
-	else if (TailMatchesCS1("\\dFd*"))
+	else if (TailMatchesCS("\\dFd*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
-	else if (TailMatchesCS1("\\dFp*"))
+	else if (TailMatchesCS("\\dFp*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
-	else if (TailMatchesCS1("\\dFt*"))
+	else if (TailMatchesCS("\\dFt*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
 	/* must be at end of \dF alternatives: */
-	else if (TailMatchesCS1("\\dF*"))
+	else if (TailMatchesCS("\\dF*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
 
-	else if (TailMatchesCS1("\\di*"))
+	else if (TailMatchesCS("\\di*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
-	else if (TailMatchesCS1("\\dL*"))
+	else if (TailMatchesCS("\\dL*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_languages);
-	else if (TailMatchesCS1("\\dn*"))
+	else if (TailMatchesCS("\\dn*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
-	else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
+	else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
-	else if (TailMatchesCS1("\\ds*"))
+	else if (TailMatchesCS("\\ds*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
-	else if (TailMatchesCS1("\\dt*"))
+	else if (TailMatchesCS("\\dt*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
-	else if (TailMatchesCS1("\\dT*"))
+	else if (TailMatchesCS("\\dT*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
-	else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
+	else if (TailMatchesCS("\\du*") || TailMatchesCS("\\dg*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
-	else if (TailMatchesCS1("\\dv*"))
+	else if (TailMatchesCS("\\dv*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
-	else if (TailMatchesCS1("\\dx*"))
+	else if (TailMatchesCS("\\dx*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
-	else if (TailMatchesCS1("\\dm*"))
+	else if (TailMatchesCS("\\dm*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
-	else if (TailMatchesCS1("\\dE*"))
+	else if (TailMatchesCS("\\dE*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
-	else if (TailMatchesCS1("\\dy*"))
+	else if (TailMatchesCS("\\dy*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
 
 	/* must be at end of \d alternatives: */
-	else if (TailMatchesCS1("\\d*"))
+	else if (TailMatchesCS("\\d*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
 
-	else if (TailMatchesCS1("\\ef"))
+	else if (TailMatchesCS("\\ef"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
-	else if (TailMatchesCS1("\\ev"))
+	else if (TailMatchesCS("\\ev"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
 
-	else if (TailMatchesCS1("\\encoding"))
+	else if (TailMatchesCS("\\encoding"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
-	else if (TailMatchesCS1("\\h|\\help"))
+	else if (TailMatchesCS("\\h|\\help"))
 		COMPLETE_WITH_LIST(sql_commands);
-	else if (TailMatchesCS2("\\h|\\help", MatchAny))
+	else if (TailMatchesCS("\\h|\\help", MatchAny))
 	{
-		if (TailMatches1("DROP"))
+		if (TailMatches("DROP"))
 			matches = completion_matches(text, drop_command_generator);
-		else if (TailMatches1("ALTER"))
+		else if (TailMatches("ALTER"))
 			matches = completion_matches(text, alter_command_generator);
 
 		/*
@@ -3522,39 +3500,39 @@ psql_completion(const char *text, int start, int end)
 		 * repeated here
 		 */
 	}
-	else if (TailMatchesCS3("\\h|\\help", MatchAny, MatchAny))
+	else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
 	{
-		if (TailMatches2("CREATE|DROP", "ACCESS"))
+		if (TailMatches("CREATE|DROP", "ACCESS"))
 			COMPLETE_WITH_CONST("METHOD");
-		else if (TailMatches2("ALTER", "DEFAULT"))
+		else if (TailMatches("ALTER", "DEFAULT"))
 			COMPLETE_WITH_CONST("PRIVILEGES");
-		else if (TailMatches2("CREATE|ALTER|DROP", "EVENT"))
+		else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
 			COMPLETE_WITH_CONST("TRIGGER");
-		else if (TailMatches2("CREATE|ALTER|DROP", "FOREIGN"))
+		else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
 			COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
-		else if (TailMatches2("ALTER", "LARGE"))
+		else if (TailMatches("ALTER", "LARGE"))
 			COMPLETE_WITH_CONST("OBJECT");
-		else if (TailMatches2("CREATE|ALTER|DROP", "MATERIALIZED"))
+		else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
 			COMPLETE_WITH_CONST("VIEW");
-		else if (TailMatches2("CREATE|ALTER|DROP", "TEXT"))
+		else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
 			COMPLETE_WITH_CONST("SEARCH");
-		else if (TailMatches2("CREATE|ALTER|DROP", "USER"))
+		else if (TailMatches("CREATE|ALTER|DROP", "USER"))
 			COMPLETE_WITH_CONST("MAPPING FOR");
 	}
-	else if (TailMatchesCS4("\\h|\\help", MatchAny, MatchAny, MatchAny))
+	else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
 	{
-		if (TailMatches3("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
+		if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
 			COMPLETE_WITH_CONST("WRAPPER");
-		else if (TailMatches3("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
+		else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
 			COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
-		else if (TailMatches3("CREATE|ALTER|DROP", "USER", "MAPPING"))
+		else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
 			COMPLETE_WITH_CONST("FOR");
 	}
-	else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
+	else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_databases);
-	else if (TailMatchesCS1("\\password"))
+	else if (TailMatchesCS("\\password"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
-	else if (TailMatchesCS1("\\pset"))
+	else if (TailMatchesCS("\\pset"))
 	{
 		static const char *const my_list[] =
 		{"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
@@ -3565,9 +3543,9 @@ psql_completion(const char *text, int start, int end)
 
 		COMPLETE_WITH_LIST_CS(my_list);
 	}
-	else if (TailMatchesCS2("\\pset", MatchAny))
+	else if (TailMatchesCS("\\pset", MatchAny))
 	{
-		if (TailMatchesCS1("format"))
+		if (TailMatchesCS("format"))
 		{
 			static const char *const my_list[] =
 			{"unaligned", "aligned", "wrapped", "html", "asciidoc",
@@ -3575,46 +3553,46 @@ psql_completion(const char *text, int start, int end)
 
 			COMPLETE_WITH_LIST_CS(my_list);
 		}
-		else if (TailMatchesCS1("linestyle"))
+		else if (TailMatchesCS("linestyle"))
 			COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
-		else if (TailMatchesCS1("pager"))
+		else if (TailMatchesCS("pager"))
 			COMPLETE_WITH_LIST_CS3("on", "off", "always");
-		else if (TailMatchesCS1("unicode_border_linestyle|"
+		else if (TailMatchesCS("unicode_border_linestyle|"
 								"unicode_column_linestyle|"
 								"unicode_header_linestyle"))
 			COMPLETE_WITH_LIST_CS2("single", "double");
 	}
-	else if (TailMatchesCS1("\\unset"))
+	else if (TailMatchesCS("\\unset"))
 		matches = complete_from_variables(text, "", "", true);
-	else if (TailMatchesCS1("\\set"))
+	else if (TailMatchesCS("\\set"))
 		matches = complete_from_variables(text, "", "", false);
-	else if (TailMatchesCS2("\\set", MatchAny))
+	else if (TailMatchesCS("\\set", MatchAny))
 	{
-		if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
+		if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
 						   "SINGLELINE|SINGLESTEP"))
 			COMPLETE_WITH_LIST_CS2("on", "off");
-		else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
+		else if (TailMatchesCS("COMP_KEYWORD_CASE"))
 			COMPLETE_WITH_LIST_CS4("lower", "upper",
 								   "preserve-lower", "preserve-upper");
-		else if (TailMatchesCS1("ECHO"))
+		else if (TailMatchesCS("ECHO"))
 			COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
-		else if (TailMatchesCS1("ECHO_HIDDEN"))
+		else if (TailMatchesCS("ECHO_HIDDEN"))
 			COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
-		else if (TailMatchesCS1("HISTCONTROL"))
+		else if (TailMatchesCS("HISTCONTROL"))
 			COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
 								   "ignoreboth", "none");
-		else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
+		else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
 			COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
-		else if (TailMatchesCS1("SHOW_CONTEXT"))
+		else if (TailMatchesCS("SHOW_CONTEXT"))
 			COMPLETE_WITH_LIST_CS3("never", "errors", "always");
-		else if (TailMatchesCS1("VERBOSITY"))
+		else if (TailMatchesCS("VERBOSITY"))
 			COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
 	}
-	else if (TailMatchesCS1("\\sf*"))
+	else if (TailMatchesCS("\\sf*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
-	else if (TailMatchesCS1("\\sv*"))
+	else if (TailMatchesCS("\\sv*"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
-	else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
+	else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\i|\\include|"
 							"\\ir|\\include_relative|\\o|\\out|"
 							"\\s|\\w|\\write|\\lo_import"))
 	{
diff --git a/src/include/c.h b/src/include/c.h
index 901d7911980..23dd9a41358 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -224,6 +224,32 @@
 #define CppAsString2(x)			CppAsString(x)
 #define CppConcat(x, y)			x##y
 
+/*
+ * PP_NARG - return the number of arguments a vararg macro gets passed.
+ *
+ * Making C pretty by making it ugly again.
+ */
+#define PP_NARG(...) \
+	PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
+#define PP_NARG_(...) \
+	PP_ARG_N(__VA_ARGS__)
+#define PP_ARG_N( \
+	_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+	_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+	_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+	_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+	_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+	_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+	_61,_62,_63,  N, ...) N
+#define PP_RSEQ_N() \
+	63,62,61,60,                   \
+	59,58,57,56,55,54,53,52,51,50, \
+	49,48,47,46,45,44,43,42,41,40, \
+	39,38,37,36,35,34,33,32,31,30, \
+	29,28,27,26,25,24,23,22,21,20, \
+	19,18,17,16,15,14,13,12,11,10, \
+	9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
 /*
  * dummyret is used to set return values in macros that use ?: to make
  * assignments.  gcc wants these to be void, other compilers like char
