Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5787d50

Browse files
committed
Improve psql's tab completion to handle completing attribute names in cases
where the relation name was schema-qualified, for exampleUPDATE foo.bar SET <tab>Also support cases where the relation name was quoted unnecessarily,for exampleUPDATE "foo" SET <tab>Greg Sabino Mullane, slightly simplified by myself.
1 parent6fc9d42 commit5787d50

File tree

1 file changed

+102
-26
lines changed

1 file changed

+102
-26
lines changed

‎src/bin/psql/tab-complete.c

Lines changed: 102 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.169 2008/01/01 19:45:56 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.170 2008/03/29 19:19:14 tgl Exp $
77
*/
88

99
/*----------------------------------------------------------------------
@@ -53,6 +53,7 @@
5353
#include"pqexpbuffer.h"
5454
#include"common.h"
5555
#include"settings.h"
56+
#include"stringutils.h"
5657

5758
#ifdefHAVE_RL_FILENAME_COMPLETION_FUNCTION
5859
#definefilename_completion_function rl_filename_completion_function
@@ -124,29 +125,70 @@ static intcompletion_max_records;
124125
* Communication variables set by COMPLETE_WITH_FOO macros and then used by
125126
* the completion callback functions. Ugly but there is no better way.
126127
*/
127-
staticconstchar*completion_charp;/* to pass a string */
128+
staticconstchar*completion_charp;/* to pass a string */
128129
staticconstchar*const*completion_charpp;/* to pass a list of strings */
129130
staticconstchar*completion_info_charp;/* to pass a second string */
131+
staticconstchar*completion_info_charp2;/* to pass a third string */
130132
staticconstSchemaQuery*completion_squery;/* to pass a SchemaQuery */
131133

132-
/* A couple of macros to ease typing. You can use these to complete the given
133-
string with
134-
1) The results from a query you pass it. (Perhaps one of those below?)
135-
2) The results from a schema query you pass it.
136-
3) The items from a null-pointer-terminated list.
137-
4) A string constant
138-
5) The list of attributes to the given table.
139-
*/
134+
/*
135+
* A few macros to ease typing. You can use these to complete the given
136+
* string with
137+
* 1) The results from a query you pass it. (Perhaps one of those below?)
138+
* 2) The results from a schema query you pass it.
139+
* 3) The items from a null-pointer-terminated list.
140+
* 4) A string constant.
141+
* 5) The list of attributes of the given table (possibly schema-qualified).
142+
*/
140143
#defineCOMPLETE_WITH_QUERY(query) \
141-
do { completion_charp = query; matches = completion_matches(text, complete_from_query); } while(0)
144+
do { \
145+
completion_charp = query; \
146+
matches = completion_matches(text, complete_from_query); \
147+
} while (0)
148+
142149
#defineCOMPLETE_WITH_SCHEMA_QUERY(query,addon) \
143-
do { completion_squery = &(query); completion_charp = addon; matches = completion_matches(text, complete_from_schema_query); } while(0)
150+
do { \
151+
completion_squery = &(query); \
152+
completion_charp = addon; \
153+
matches = completion_matches(text, complete_from_schema_query); \
154+
} while (0)
155+
144156
#defineCOMPLETE_WITH_LIST(list) \
145-
do { completion_charpp = list; matches = completion_matches(text, complete_from_list); } while(0)
157+
do { \
158+
completion_charpp = list; \
159+
matches = completion_matches(text, complete_from_list); \
160+
} while (0)
161+
146162
#defineCOMPLETE_WITH_CONST(string) \
147-
do { completion_charp = string; matches = completion_matches(text, complete_from_const); } while(0)
148-
#defineCOMPLETE_WITH_ATTR(table,addon) \
149-
do {completion_charp = Query_for_list_of_attributes addon; completion_info_charp = table; matches = completion_matches(text, complete_from_query); } while(0)
163+
do { \
164+
completion_charp = string; \
165+
matches = completion_matches(text, complete_from_const); \
166+
} while (0)
167+
168+
#defineCOMPLETE_WITH_ATTR(relation,addon) \
169+
do { \
170+
char *_completion_schema; \
171+
char *_completion_table; \
172+
\
173+
_completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
174+
false, false, pset.encoding); \
175+
(void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
176+
false, false, pset.encoding); \
177+
_completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
178+
false, false, pset.encoding); \
179+
if (_completion_table == NULL) \
180+
{ \
181+
completion_charp = Query_for_list_of_attributes addon; \
182+
completion_info_charp = relation; \
183+
} \
184+
else \
185+
{ \
186+
completion_charp = Query_for_list_of_attributes_with_schema addon; \
187+
completion_info_charp = _completion_table; \
188+
completion_info_charp2 = _completion_schema; \
189+
} \
190+
matches = completion_matches(text, complete_from_query); \
191+
} while (0)
150192

151193
/*
152194
* Assembly instructions for schema queries
@@ -308,11 +350,12 @@ static const SchemaQuery Query_for_list_of_views = {
308350
/*
309351
* Queries to get lists of names of various kinds of things, possibly
310352
* restricted to names matching a partially entered name. In these queries,
311-
* %s will be replaced by the text entered so far (suitably escaped to
312-
* become a SQL literal string). %d will be replaced by the length of the
313-
* string (in unescaped form).A second %s, if present, will be replaced
314-
* by a suitably-escaped version of the string provided in
315-
* completion_info_charp.
353+
* the first %s will be replaced by the text entered so far (suitably escaped
354+
* to become a SQL literal string). %d will be replaced by the length of the
355+
* string (in unescaped form).A second and third %s, if present, will be
356+
* replaced by a suitably-escaped version of the string provided in
357+
* completion_info_charp. A fourth and fifth %s are similarly replaced by
358+
* completion_info_charp2.
316359
*
317360
* Beware that the allowed sequences of %s and %d are determined by
318361
* _complete_from_query().
@@ -325,9 +368,23 @@ static const SchemaQuery Query_for_list_of_views = {
325368
" AND a.attnum > 0 "\
326369
" AND NOT a.attisdropped "\
327370
" AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
328-
" AND pg_catalog.quote_ident(relname)='%s' "\
371+
" AND (pg_catalog.quote_ident(relname)='%s' "\
372+
" OR '\"' || relname || '\"'='%s') "\
329373
" AND pg_catalog.pg_table_is_visible(c.oid)"
330374

375+
#defineQuery_for_list_of_attributes_with_schema \
376+
"SELECT pg_catalog.quote_ident(attname) "\
377+
" FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
378+
" WHERE c.oid = a.attrelid "\
379+
" AND n.oid = c.relnamespace "\
380+
" AND a.attnum > 0 "\
381+
" AND NOT a.attisdropped "\
382+
" AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
383+
" AND (pg_catalog.quote_ident(relname)='%s' "\
384+
" OR '\"' || relname || '\"' ='%s') "\
385+
" AND (pg_catalog.quote_ident(nspname)='%s' "\
386+
" OR '\"' || nspname || '\"' ='%s') "
387+
331388
#defineQuery_for_list_of_template_databases \
332389
"SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
333390
" WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s' and datistemplate IS TRUE"
@@ -584,9 +641,10 @@ psql_completion(char *text, int start, int end)
584641
completion_charp=NULL;
585642
completion_charpp=NULL;
586643
completion_info_charp=NULL;
644+
completion_info_charp2=NULL;
587645

588646
/*
589-
* Scan the input line before our current position for the lastfour
647+
* Scan the input line before our current position for the lastfive
590648
* words. According to those we'll make some smart decisions on what the
591649
* user is probably intending to type. TODO: Use strtokx() to do this.
592650
*/
@@ -2225,8 +2283,9 @@ complete_from_schema_query(const char *text, int state)
22252283
The query can be one of two kinds:
22262284
- A simple query which must contain a %d and a %s, which will be replaced
22272285
by the string length of the text and the text itself. The query may also
2228-
have another %s in it, which will be replaced by the value of
2229-
completion_info_charp.
2286+
have up to four more %s in it; the first two such will be replaced by the
2287+
value of completion_info_charp, the next two by the value of
2288+
completion_info_charp2.
22302289
or:
22312290
- A schema query used for completion of both schema and relation names;
22322291
these are more complex and must contain in the following order:
@@ -2255,6 +2314,7 @@ _complete_from_query(int is_schema_query, const char *text, int state)
22552314
PQExpBufferDataquery_buffer;
22562315
char*e_text;
22572316
char*e_info_charp;
2317+
char*e_info_charp2;
22582318

22592319
list_index=0;
22602320
string_length=strlen(text);
@@ -2279,6 +2339,18 @@ _complete_from_query(int is_schema_query, const char *text, int state)
22792339
else
22802340
e_info_charp=NULL;
22812341

2342+
if (completion_info_charp2)
2343+
{
2344+
size_tcharp_len;
2345+
2346+
charp_len=strlen(completion_info_charp2);
2347+
e_info_charp2=pg_malloc(charp_len*2+1);
2348+
PQescapeString(e_info_charp2,completion_info_charp2,
2349+
charp_len);
2350+
}
2351+
else
2352+
e_info_charp2=NULL;
2353+
22822354
initPQExpBuffer(&query_buffer);
22832355

22842356
if (is_schema_query)
@@ -2374,7 +2446,9 @@ _complete_from_query(int is_schema_query, const char *text, int state)
23742446
{
23752447
/* completion_charp is an sprintf-style format string */
23762448
appendPQExpBuffer(&query_buffer,completion_charp,
2377-
string_length,e_text,e_info_charp);
2449+
string_length,e_text,
2450+
e_info_charp,e_info_charp,
2451+
e_info_charp2,e_info_charp2);
23782452
}
23792453

23802454
/* Limit the number of records in the result */
@@ -2387,6 +2461,8 @@ _complete_from_query(int is_schema_query, const char *text, int state)
23872461
free(e_text);
23882462
if (e_info_charp)
23892463
free(e_info_charp);
2464+
if (e_info_charp2)
2465+
free(e_info_charp2);
23902466
}
23912467

23922468
/* Find something that matches */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp