3
3
*
4
4
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
5
5
*
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 $
7
7
*/
8
8
9
9
/*----------------------------------------------------------------------
53
53
#include "pqexpbuffer.h"
54
54
#include "common.h"
55
55
#include "settings.h"
56
+ #include "stringutils.h"
56
57
57
58
#ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
58
59
#define filename_completion_function rl_filename_completion_function
@@ -124,29 +125,70 @@ static int completion_max_records;
124
125
* Communication variables set by COMPLETE_WITH_FOO macros and then used by
125
126
* the completion callback functions. Ugly but there is no better way.
126
127
*/
127
- static const char * completion_charp ; /* to pass a string */
128
+ static const char * completion_charp ; /* to pass a string */
128
129
static const char * const * completion_charpp ; /* to pass a list of strings */
129
130
static const char * completion_info_charp ; /* to pass a second string */
131
+ static const char * completion_info_charp2 ; /* to pass a third string */
130
132
static const SchemaQuery * completion_squery ; /* to pass a SchemaQuery */
131
133
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
+ */
140
143
#define COMPLETE_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
+
142
149
#define COMPLETE_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
+
144
156
#define COMPLETE_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
+
146
162
#define COMPLETE_WITH_CONST (string ) \
147
- do { completion_charp = string; matches = completion_matches(text, complete_from_const); } while(0)
148
- #define COMPLETE_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
+ #define COMPLETE_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)
150
192
151
193
/*
152
194
* Assembly instructions for schema queries
@@ -308,11 +350,12 @@ static const SchemaQuery Query_for_list_of_views = {
308
350
/*
309
351
* Queries to get lists of names of various kinds of things, possibly
310
352
* 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.
316
359
*
317
360
* Beware that the allowed sequences of %s and %d are determined by
318
361
* _complete_from_query().
@@ -325,9 +368,23 @@ static const SchemaQuery Query_for_list_of_views = {
325
368
" AND a.attnum > 0 "\
326
369
" AND NOT a.attisdropped "\
327
370
" 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') "\
329
373
" AND pg_catalog.pg_table_is_visible(c.oid)"
330
374
375
+ #define Query_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
+
331
388
#define Query_for_list_of_template_databases \
332
389
"SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
333
390
" 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)
584
641
completion_charp = NULL ;
585
642
completion_charpp = NULL ;
586
643
completion_info_charp = NULL ;
644
+ completion_info_charp2 = NULL ;
587
645
588
646
/*
589
- * Scan the input line before our current position for the last four
647
+ * Scan the input line before our current position for the last five
590
648
* words. According to those we'll make some smart decisions on what the
591
649
* user is probably intending to type. TODO: Use strtokx() to do this.
592
650
*/
@@ -2225,8 +2283,9 @@ complete_from_schema_query(const char *text, int state)
2225
2283
The query can be one of two kinds:
2226
2284
- A simple query which must contain a %d and a %s, which will be replaced
2227
2285
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.
2230
2289
or:
2231
2290
- A schema query used for completion of both schema and relation names;
2232
2291
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)
2255
2314
PQExpBufferData query_buffer ;
2256
2315
char * e_text ;
2257
2316
char * e_info_charp ;
2317
+ char * e_info_charp2 ;
2258
2318
2259
2319
list_index = 0 ;
2260
2320
string_length = strlen (text );
@@ -2279,6 +2339,18 @@ _complete_from_query(int is_schema_query, const char *text, int state)
2279
2339
else
2280
2340
e_info_charp = NULL ;
2281
2341
2342
+ if (completion_info_charp2 )
2343
+ {
2344
+ size_t charp_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
+
2282
2354
initPQExpBuffer (& query_buffer );
2283
2355
2284
2356
if (is_schema_query )
@@ -2374,7 +2446,9 @@ _complete_from_query(int is_schema_query, const char *text, int state)
2374
2446
{
2375
2447
/* completion_charp is an sprintf-style format string */
2376
2448
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 );
2378
2452
}
2379
2453
2380
2454
/* Limit the number of records in the result */
@@ -2387,6 +2461,8 @@ _complete_from_query(int is_schema_query, const char *text, int state)
2387
2461
free (e_text );
2388
2462
if (e_info_charp )
2389
2463
free (e_info_charp );
2464
+ if (e_info_charp2 )
2465
+ free (e_info_charp2 );
2390
2466
}
2391
2467
2392
2468
/* Find something that matches */
0 commit comments