Skip to content

Commit 02b8048

Browse files
committed
psql: improve tab-complete's handling of variant SQL names.
This patch improves tab completion's ability to deal with valid variant spellings of SQL identifiers. Notably: * Unquoted upper-case identifiers are now downcased as the backend would do, allowing them to be completed correctly. * Tab completion can now match identifiers that are quoted even though they don't need to be; for example "f<TAB> now completes to "foo" if that's the only available name. Previously, only names that require quotes would be offered. * Schema-qualified identifiers are now supported where SQL syntax allows it; many lesser-used completion rules neglected this. * Completion operations that refer back to some previously-typed name (for example, to complete names of columns belonging to a previously-mentioned table) now allow variant spellings of the previous name too. In addition, performance of tab completion queries has been improved for databases containing many objects, although you'd only be likely to notice with a heavily-loaded server. Authors of future tab-completion patches should note that this commit changes many details about how tab completion queries must be written: * Tab completion queries now deal in raw object names; do not use quote_ident(). * The name-matching restriction in a query must now be written as "outputcol LIKE '%s'", not "substring(outputcol,1,%d)='%s'". * The SchemaQuery mechanism has been extended so that it can handle queries that refer back to a previous name. Most completion queries that do that should be converted to SchemaQuery form. Only consider using a literal query if the previous name can never be schema-qualified. Don't use a literal query if the name-to-be-completed can validly be schema-qualified, either. * Use set_completion_reference() to specify which word is the previous name to consider, for either a SchemaQuery or a literal query. * If you want to offer some keywords in addition to a query result (for example, offer COLUMN in addition to column names after "ALTER TABLE t RENAME"), do not use the old hack of tacking the keywords on with UNION. Instead use the new QUERY_PLUS macros to write such keywords separately from the query proper. The "addon" macro arguments that used to be used for this purpose are gone. * If your query returns something that's not a SQL identifier (such as an attribute number or enum label), use the new QUERY_VERBATIM macros to prevent the result from incorrectly getting double-quoted. You may still need to use quote_literal in such a query, too. Tom Lane and Haiying Tang Discussion: https://postgr.es/m/a63cbd45e3884cf9b3961c2a6a95dcb7@G08CNEXMBPEKD05.g08.fujitsu.local
1 parent b3d7d6e commit 02b8048

File tree

3 files changed

+1613
-949
lines changed

3 files changed

+1613
-949
lines changed

doc/src/sgml/ref/psql-ref.sgml

+51-15
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,9 @@ EOF
318318
<term><option>--no-readline</option></term>
319319
<listitem>
320320
<para>
321-
Do not use <application>Readline</application> for line editing and do
322-
not use the command history.
323-
This can be useful to turn off tab expansion when cutting and pasting.
321+
Do not use <application>Readline</application> for line editing and
322+
do not use the command history (see
323+
<xref linkend="app-psql-readline"/> below).
324324
</para>
325325
</listitem>
326326
</varlistentry>
@@ -4562,21 +4562,47 @@ testdb=&gt; \set PROMPT1 '%[%033[1;33;40m%]%n@%/%R%[%033[0m%]%# '
45624562

45634563
</refsect3>
45644564

4565-
<refsect3>
4565+
<refsect3 id="app-psql-readline">
45664566
<title>Command-Line Editing</title>
45674567

4568+
<indexterm>
4569+
<primary>Readline</primary>
4570+
<secondary>in psql</secondary>
4571+
</indexterm>
4572+
<indexterm>
4573+
<primary>libedit</primary>
4574+
<secondary>in psql</secondary>
4575+
</indexterm>
4576+
4577+
<para>
4578+
<application>psql</application> uses
4579+
the <application>Readline</application>
4580+
or <application>libedit</application> library, if available, for
4581+
convenient line editing and retrieval. The command history is
4582+
automatically saved when <application>psql</application> exits and is
4583+
reloaded when <application>psql</application> starts up. Type
4584+
up-arrow or control-P to retrieve previous lines.
4585+
</para>
4586+
4587+
<para>
4588+
You can also use tab completion to fill in partially-typed keywords
4589+
and SQL object names in many (by no means all) contexts. For example,
4590+
at the start of a command, typing <literal>ins</literal> and pressing
4591+
TAB will fill in <literal>insert into </literal>. Then, typing a few
4592+
characters of a table or schema name and pressing TAB will fill in the
4593+
unfinished name, or offer a menu of possible completions when there's
4594+
more than one. (Depending on the library in use, you may need to
4595+
press TAB more than once to get a menu.)
4596+
</para>
4597+
45684598
<para>
4569-
<application>psql</application> supports the <application>Readline</application>
4570-
library for convenient line editing and retrieval. The command
4571-
history is automatically saved when <application>psql</application>
4572-
exits and is reloaded when
4573-
<application>psql</application> starts up. Tab-completion is also
4574-
supported, although the completion logic makes no claim to be an
4575-
<acronym>SQL</acronym> parser. The queries generated by tab-completion
4576-
can also interfere with other SQL commands, e.g., <literal>SET
4577-
TRANSACTION ISOLATION LEVEL</literal>.
4578-
If for some reason you do not like the tab completion, you
4579-
can turn it off by putting this in a file named
4599+
Tab completion for SQL object names requires sending queries to the
4600+
server to find possible matches. In some contexts this can interfere
4601+
with other operations. For example, after <command>BEGIN</command>
4602+
it will be too late to issue <command>SET TRANSACTION ISOLATION
4603+
LEVEL</command> if a tab-completion query is issued in between.
4604+
If you do not want tab completion at all, you
4605+
can turn it off permanently by putting this in a file named
45804606
<filename>.inputrc</filename> in your home directory:
45814607
<programlisting>
45824608
$if psql
@@ -4587,6 +4613,16 @@ $endif
45874613
<application>Readline</application> feature. Read its documentation
45884614
for further details.)
45894615
</para>
4616+
4617+
<para>
4618+
The <option>-n</option> (<option>--no-readline</option>) command line
4619+
option can also be useful to disable use
4620+
of <application>Readline</application> for a single run
4621+
of <application>psql</application>. This prevents tab completion,
4622+
use or recording of command line history, and editing of multi-line
4623+
commands. It is particularly useful when you need to copy-and-paste
4624+
text that contains TAB characters.
4625+
</para>
45904626
</refsect3>
45914627
</refsect2>
45924628
</refsect1>

src/bin/psql/t/010_tab_completion.pl

+94-2
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@
4040

4141
# set up a few database objects
4242
$node->safe_psql('postgres',
43-
"CREATE TABLE tab1 (f1 int, f2 text);\n"
43+
"CREATE TABLE tab1 (f1 int primary key, f2 text);\n"
4444
. "CREATE TABLE mytab123 (f1 int, f2 text);\n"
4545
. "CREATE TABLE mytab246 (f1 int, f2 text);\n"
46-
. "CREATE TYPE enum1 AS ENUM ('foo', 'bar', 'baz');\n");
46+
. "CREATE TABLE \"mixedName\" (f1 int, f2 text);\n"
47+
. "CREATE TYPE enum1 AS ENUM ('foo', 'bar', 'baz', 'BLACK');\n");
4748

4849
# Developers would not appreciate this test adding a bunch of junk to
4950
# their ~/.psql_history, so be sure to redirect history into a temp file.
@@ -176,13 +177,87 @@ sub clear_line
176177

177178
clear_query();
178179

180+
# check handling of quoted names
181+
check_completion(
182+
"select * from \"my\t",
183+
qr/select \* from "my\a?tab/,
184+
"complete \"my<tab> to \"mytab when there are multiple choices");
185+
186+
check_completion(
187+
"\t\t",
188+
qr/"mytab123" +"mytab246"/,
189+
"offer multiple quoted table choices");
190+
191+
check_completion("2\t", qr/246" /,
192+
"finish completion of one of multiple quoted table choices");
193+
194+
clear_query();
195+
196+
# check handling of mixed-case names
197+
check_completion(
198+
"select * from \"mi\t",
199+
qr/"mixedName"/,
200+
"complete a mixed-case name");
201+
202+
clear_query();
203+
204+
# check case folding
205+
check_completion(
206+
"select * from TAB\t",
207+
qr/tab1 /,
208+
"automatically fold case");
209+
210+
clear_query();
211+
179212
# check case-sensitive keyword replacement
180213
# note: various versions of readline/libedit handle backspacing
181214
# differently, so just check that the replacement comes out correctly
182215
check_completion("\\DRD\t", qr/drds /, "complete \\DRD<tab> to \\drds");
183216

184217
clear_query();
185218

219+
# check completion of a schema-qualified name
220+
check_completion(
221+
"select * from pub\t",
222+
qr/public\./,
223+
"complete schema when relevant");
224+
225+
check_completion(
226+
"tab\t",
227+
qr/tab1 /,
228+
"complete schema-qualified name");
229+
230+
clear_query();
231+
232+
check_completion(
233+
"select * from PUBLIC.t\t",
234+
qr/public\.tab1 /,
235+
"automatically fold case in schema-qualified name");
236+
237+
clear_query();
238+
239+
# check interpretation of referenced names
240+
check_completion(
241+
"alter table tab1 drop constraint \t",
242+
qr/tab1_pkey /,
243+
"complete index name for referenced table");
244+
245+
clear_query();
246+
247+
check_completion(
248+
"alter table TAB1 drop constraint \t",
249+
qr/tab1_pkey /,
250+
"complete index name for referenced table, with downcasing");
251+
252+
clear_query();
253+
254+
check_completion(
255+
"alter table public.\"tab1\" drop constraint \t",
256+
qr/tab1_pkey /,
257+
"complete index name for referenced table, with schema and quoting");
258+
259+
clear_query();
260+
186261
# check filename completion
187262
check_completion(
188263
"\\lo_import tmp_check/some\t",
@@ -234,6 +309,23 @@ sub clear_line
234309

235310
clear_line();
236311

312+
# enum labels are case sensitive, so this should complete BLACK immediately
313+
check_completion(
314+
"ALTER TYPE enum1 RENAME VALUE 'B\t",
315+
qr|BLACK|,
316+
"enum labels are case sensitive");
317+
318+
clear_line();
319+
320+
# check completion of a keyword offered in addition to object names
321+
# (that code path currently doesn't preserve case of what's typed)
322+
check_completion(
323+
"comment on constraint foo on dom\t",
324+
qr|DOMAIN|,
325+
"offer keyword in addition to query result");
326+
327+
clear_query();
328+
237329
# send psql an explicit \q to shut it down, else pty won't close properly
238330
$timer->start(5);
239331
$in .= "\\q\n";

0 commit comments

Comments
 (0)