Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ukVzx-003P8Z-EN for pgsql-hackers@arkaria.postgresql.org; Fri, 08 Aug 2025 22:55:41 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1ukVzv-00HHeU-F5 for pgsql-hackers@arkaria.postgresql.org; Fri, 08 Aug 2025 22:55:39 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ukVzu-00HHeM-Pa for pgsql-hackers@lists.postgresql.org; Fri, 08 Aug 2025 22:55:39 +0000 Received: from fout-a5-smtp.messagingengine.com ([103.168.172.148]) by makus.postgresql.org with smtp (Exim 4.96) (envelope-from ) id 1ukVzr-001T9Q-1D for pgsql-hackers@postgresql.org; Fri, 08 Aug 2025 22:55:37 +0000 Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailfout.phl.internal (Postfix) with ESMTP id 7ECCEEC0921; Fri, 8 Aug 2025 18:55:35 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Fri, 08 Aug 2025 18:55:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ilmari.org; h=cc :cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1754693735; x=1754780135; bh=zgtF0tl0Ip KfY8ENzFgbxZx68YmvKvDKtWsoump8RgA=; b=dbTZmoj1mfPkkZ4aU44WI3vP35 TKA7AmWXmS6BwBspDTkL8eNX8PScM7R8Aq/nsx/oAVMqtCNK7KUllp2i7qA4KVFe CQEMEfg3vlY2t1pLALY+EjAUhZPBzOWcP4k9vnWTMOELKhYyULypzSOoExQLjEXZ wA/75yVx1zAHfn1zEDjOisWNI2YjZFb7W2zTchuY3SbZFpS+ZSj/0tuvZ8EnckdH TQKBUCFNLLQLO9+gvqVvHG6ESkfSFqxzCuCKad38pK4lqy0BOKPZnYF9kErLneIT N1IW9gtwA7cB+1ukO2QUgo5Tp5X+PujtNKY8ENl5afJVT6IP9wDMxyO7f10g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1754693735; x=1754780135; bh=zgtF0tl0IpKfY8ENzFgbxZx68YmvKvDKtWs oump8RgA=; b=kdaVMpz+PU+UxZtUzeD0uc5pNMQ8scRTuwnP716p67rWyXXzLX+ TuhvSVAYZmKieeJJMNRaVTzm3CqGhgFbsJqv+OFYSVPXfM4UFSbFxOEjgCBaQaOw wJFZCKIdoHFvwkAJwZOvscWArJsSr8Xz0uogNh9aLzXN/Rq/SRhv1m5X4MHYCvKc v+aB0YBU48TdenVErbDwqLJYr0wryslH2Oz+CgV85EAShud/k9nqA2vrDPrHxBAJ HuXMzXFMNpItJ7KhD0u97YBz9vU+O9+Ay8p+Tq+x1snlvDIdLz/s9oPjUfRljJqg vyrRe5/T4lT8rrpUli4IMKjxjq+qRNqjcTA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdefgdduvdehtdejucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhephffvvefufhffjgfkfgggtgesmhdtreertderjeenucfhrhhomhepffgrghhfihhn nhcukfhlmhgrrhhiucforghnnhhsnohkvghruceoihhlmhgrrhhisehilhhmrghrihdroh hrgheqnecuggftrfgrthhtvghrnhepvddvhfehtdefkedugfetudefhefggfegjeeijeeh uefgteehgfegtdelgeetteejnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpe hmrghilhhfrhhomhepihhlmhgrrhhisehilhhmrghrihdrohhrghdpnhgspghrtghpthht ohepvddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepphhgshhqlhdqhhgrtghkvg hrshesphhoshhtghhrvghsqhhlrdhorhhgpdhrtghpthhtohepshhhihhnhigruddurdhk rghtohesghhmrghilhdrtghomh X-ME-Proxy: Feedback-ID: i1ff147bf:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 8 Aug 2025 18:55:34 -0400 (EDT) From: =?utf-8?Q?Dagfinn_Ilmari_Manns=C3=A5ker?= To: Shinya Kato Cc: pgsql-hackers@postgresql.org Subject: Re: Improve tab completion for various SET/RESET forms References: <87bjqwwtic.fsf@wibble.ilmari.org> <18691637-2af2-4a2f-9f12-8201c2a88206@eisentraut.org> <871prqwq19.fsf@wibble.ilmari.org> <87tt4lumqz.fsf@wibble.ilmari.org> <87seicgu1q.fsf@wibble.ilmari.org> Date: Fri, 08 Aug 2025 23:55:33 +0100 In-Reply-To: (Shinya Kato's message of "Fri, 8 Aug 2025 12:03:30 +0900") Message-ID: <87a549h196.fsf@wibble.ilmari.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Shinya Kato writes: > On Fri, Aug 1, 2025 at 2:16 AM Dagfinn Ilmari Mannsåker > wrote: >> >> Dagfinn Ilmari Mannsåker writes: >> >> > I just noticed that in addition to ALTER ROLE ... RESET being buggy, the >> > ALTER DATABASE ... RESET query doesn't schema-qualify the unnest() call. >> > Here's an updated patch series that fixes that too. The first two are >> > bug fixes to features new in 18 and should IMO be committed before >> > that's released. The rest can wait for 19. >> >> Now that Tomas has committed the two bugfixes, here's the rest of the >> patches rebased over that. > > Thank you for the patches. > > + else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny, "SET")) > + COMPLETE_WITH("SCHEMA"); > > In addition to SET SCHEMA, I think you should add tab completion for > SET WITHOUT OIDS. As Kirill pointed out, support for WITH OIDS was removed in v12. The SET WITHOUT OIDS syntax only remains as a no-op for backwards compatibility with existing SQL scripts, so there's no point in offering tab completion for it. > +#define Query_for_list_of_session_vars \ > +"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\ > +" WHERE context IN ('user', 'superuser') "\ > +" AND source = 'session' "\ > +" AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" > > I think the context IN ('user', 'superuser') condition is redundant > here. If a parameter's source is 'session', its context must be either > 'user' or 'superuser'. Therefore, the source = 'session' check alone > should be sufficient. Good point, updated in the attached v4 patches. - ilmari --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v4-0001-Add-tab-completion-for-ALTER-TABLE-.-ALTER-COLUMN.patch From 59d8c9c4874dadc8754f0dd7ea6d6dc67f3814ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= Date: Mon, 9 Jun 2025 20:39:15 +0100 Subject: [PATCH v4 1/4] Add tab completion for ALTER TABLE ... ALTER COLUMN ... RESET Unlike SET, it only takes parenthesised attribute options. --- src/bin/psql/tab-complete.in.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 1f2ca946fc5..176ae1284be 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -2913,9 +2913,13 @@ match_previous_words(int pattern_id, "STATISTICS", "STORAGE", /* a subset of ALTER SEQUENCE options */ "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE"); - /* ALTER TABLE ALTER [COLUMN] SET ( */ - else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") || - Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "(")) + /* ALTER TABLE ALTER [COLUMN] RESET */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "RESET") || + Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "RESET")) + COMPLETE_WITH("("); + /* ALTER TABLE ALTER [COLUMN] SET|RESET ( */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET|RESET", "(") || + Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET|RESET", "(")) COMPLETE_WITH("n_distinct", "n_distinct_inherited"); /* ALTER TABLE ALTER [COLUMN] SET COMPRESSION */ else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") || -- 2.50.1 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v4-0002-Add-tab-completion-for-ALTER-FOREIGN-TABLE-.-SET.patch From d34caaeb8409d58b5abaac825ed1c093bb5e7cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= Date: Mon, 9 Jun 2025 20:41:29 +0100 Subject: [PATCH v4 2/4] Add tab completion for ALTER FOREIGN TABLE ... SET The schema is the only thing that can be set for foreign tables. --- src/bin/psql/tab-complete.in.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 176ae1284be..d31f5780727 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -2435,6 +2435,10 @@ match_previous_words(int pattern_id, COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT"); + else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny, "SET")) + COMPLETE_WITH("SCHEMA"); + else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny, "SET", "SCHEMA")) + COMPLETE_WITH_QUERY(Query_for_list_of_schemas); /* ALTER INDEX */ else if (Matches("ALTER", "INDEX")) -- 2.50.1 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=v4-0003-Improve-tab-completion-for-RESET.patch From 9e3b600924c4118002fb36187fa268ba2ac37d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= Date: Fri, 8 Aug 2025 23:06:36 +0100 Subject: [PATCH v4 3/4] Improve tab completion for RESET Only complete variables that have been set in the current session, plus the keywords ALL, ROLE and SESSION (which will subsequently be completed with AUTHORIZATION). Because we're using Matches() insted of TailMatches(), we can also get rid of the guards against ALTER DATABASE|USER|ROLE ... RESET. --- src/bin/psql/tab-complete.in.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index d31f5780727..c4f50880965 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -1047,6 +1047,11 @@ static const SchemaQuery Query_for_trigger_of_table = { " WHERE context IN ('user', 'superuser') "\ " AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" +#define Query_for_list_of_session_vars \ +"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\ +" WHERE source = 'session' "\ +" AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" + #define Query_for_list_of_show_vars \ "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\ " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" @@ -5027,9 +5032,8 @@ match_previous_words(int pattern_id, /* SET, RESET, SHOW */ /* Complete with a variable name */ - else if (TailMatches("SET|RESET") && - !TailMatches("UPDATE", MatchAny, "SET") && - !TailMatches("ALTER", "DATABASE|USER|ROLE", MatchAny, "RESET")) + else if (TailMatches("SET") && + !TailMatches("UPDATE", MatchAny, "SET")) COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars, "CONSTRAINTS", "TRANSACTION", @@ -5037,6 +5041,12 @@ match_previous_words(int pattern_id, "ROLE", "TABLESPACE", "ALL"); + /* Complete with variables set in the current session */ + else if (Matches("RESET")) + COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_session_vars, + "ALL", + "ROLE", + "SESSION"); else if (Matches("SHOW")) COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_show_vars, "SESSION AUTHORIZATION", -- 2.50.1 --=-=-=--