]> granicus.if.org Git - postgresql/blob - src/bin/psql/tab-complete.c
Use PQescapeString to ensure that tab-completion queries are not messed
[postgresql] / src / bin / psql / tab-complete.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
5  *
6  * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.86 2003/10/14 22:47:12 tgl Exp $
7  */
8
9 /*----------------------------------------------------------------------
10  * This file implements a somewhat more sophisticated readline "TAB
11  * completion" in psql. It is not intended to be AI, to replace
12  * learning SQL, or to relieve you from thinking about what you're
13  * doing. Also it does not always give you all the syntactically legal
14  * completions, only those that are the most common or the ones that
15  * the programmer felt most like implementing.
16  *
17  * CAVEAT: Tab completion causes queries to be sent to the backend.
18  * The number tuples returned gets limited, in most default
19  * installations to 101, but if you still don't like this prospect,
20  * you can turn off tab completion in your ~/.inputrc (or else
21  * ${INPUTRC}) file so:
22  *
23  *       $if psql
24  *       set disable-completion on
25  *       $endif
26  *
27  * See `man 3 readline' or `info readline' for the full details. Also,
28  * hence the
29  *
30  * BUGS:
31  *
32  * - If you split your queries across lines, this whole things gets
33  *       confused. (To fix this, one would have to read psql's query
34  *       buffer rather than readline's line buffer, which would require
35  *       some major revisions of things.)
36  *
37  * - Table or attribute names with spaces in it may confuse it.
38  *
39  * - Quotes, parenthesis, and other funny characters are not handled
40  *       all that gracefully.
41  *----------------------------------------------------------------------
42  */
43
44 #include "postgres_fe.h"
45 #include "tab-complete.h"
46
47 #include "input.h"
48
49 /* If we don't have this, we might as well forget about the whole thing: */
50 #ifdef USE_READLINE
51
52 #include <ctype.h>
53 #ifdef USE_ASSERT_CHECKING
54 #include <assert.h>
55 #endif
56
57 #include "libpq-fe.h"
58
59 #include "common.h"
60 #include "settings.h"
61
62 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
63 #define filename_completion_function rl_filename_completion_function
64 #else
65 /* missing in some header files */
66 extern char *filename_completion_function();
67 #endif
68
69 #ifdef HAVE_RL_COMPLETION_MATCHES
70 #define completion_matches rl_completion_matches
71 #endif
72
73 #define BUF_SIZE 2048
74 #define ERROR_QUERY_TOO_LONG    /* empty */
75
76
77 /* Forward declaration of functions */
78 static char **psql_completion(char *text, int start, int end);
79 static char *create_command_generator(const char *text, int state);
80 static char *complete_from_query(const char *text, int state);
81 static char *complete_from_schema_query(const char *text, int state);
82 static char *_complete_from_query(int is_schema_query,
83                                          const char *text, int state);
84 static char *complete_from_const(const char *text, int state);
85 static char *complete_from_list(const char *text, int state);
86
87 static PGresult *exec_query(char *query);
88
89 static char *previous_word(int point, int skip);
90
91 #if 0
92 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
93 static char *dequote_file_name(char *text, char quote_char);
94 #endif
95
96 /* These variables are used to pass information into the completion functions.
97    Realizing that this is the cardinal sin of programming, I don't see a better
98    way. */
99 static char     *completion_charp;              /* if you need to pass a string */
100 static char     **completion_charpp;    /* if you need to pass a list of strings */
101 static char *completion_info_charp;             /* if you need to pass another
102                                                                                  * string */
103
104 /* Store how many records from a database query we want to return at most
105 (implemented via SELECT ... LIMIT xx). */
106 static int      completion_max_records;
107
108
109 /* Initialize the readline library for our purposes. */
110 void
111 initialize_readline(void)
112 {
113         rl_readline_name = pset.progname;
114         rl_attempted_completion_function = (void *) psql_completion;
115
116         rl_basic_word_break_characters = "\t\n@$><=;|&{( ";
117
118         completion_max_records = 100;
119
120         /*
121          * There is a variable rl_completion_query_items for this but
122          * apparently it's not defined everywhere.
123          */
124 }
125
126
127 /*
128  * Queries to get lists of names of various kinds of things, possibly
129  * restricted to names matching a partially entered name.  In these queries,
130  * %s will be replaced by the text entered so far (suitably escaped to
131  * become a SQL literal string).  %d will be replaced by the length of the
132  * string (in unescaped form).  Beware that the allowed sequences of %s and
133  * %d are determined by _complete_from_query().
134  */
135
136 #define Query_for_list_of_aggregates \
137 " SELECT DISTINCT proname " \
138 "   FROM pg_catalog.pg_proc" \
139 "  WHERE proisagg " \
140 "    AND substr(proname,1,%d)='%s'" \
141 "        UNION" \
142 " SELECT nspname || '.' AS relname" \
143 "   FROM pg_catalog.pg_namespace" \
144 "  WHERE substr(nspname,1,%d)='%s'" \
145 "        UNION" \
146 " SELECT DISTINCT nspname || '.' || proname AS relname" \
147 "   FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n" \
148 "  WHERE proisagg  " \
149 "    AND substr(nspname || '.' || proname,1,%d)='%s'" \
150 "    AND pronamespace = n.oid" \
151 "    AND ('%s' ~ '^.*\\\\.' "\
152 "     OR (SELECT TRUE "\
153 "           FROM pg_catalog.pg_namespace "\
154 "          WHERE substr(nspname,1,%d)='%s' "\
155 "         HAVING COUNT(nspname)=1))"
156
157 #define Query_for_list_of_attributes \
158 "SELECT a.attname FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
159 " WHERE c.oid = a.attrelid "\
160 "   AND a.attnum > 0 "\
161 "   AND NOT a.attisdropped "\
162 "   AND substr(a.attname,1,%d)='%s' "\
163 "   AND c.relname='%s' "\
164 "   AND pg_catalog.pg_table_is_visible(c.oid)"
165
166 #define Query_for_list_of_databases \
167 "SELECT datname FROM pg_catalog.pg_database "\
168 " WHERE substr(datname,1,%d)='%s'"
169
170 #define Query_for_list_of_datatypes \
171 " SELECT pg_catalog.format_type(t.oid, NULL) "\
172 "   FROM pg_catalog.pg_type t "\
173 "  WHERE (t.typrelid = 0 "\
174 "     OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "\
175 "    AND t.typname !~ '^_' "\
176 "    AND substr(pg_catalog.format_type(t.oid, NULL),1,%d)='%s' "\
177 "        UNION "\
178 " SELECT nspname || '.' AS relname "\
179 "   FROM pg_catalog.pg_namespace "\
180 "  WHERE substr(nspname,1,%d)='%s' "\
181 "        UNION "\
182 " SELECT nspname || '.' || pg_catalog.format_type(t.oid, NULL) AS relname "\
183 "   FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
184 "  WHERE(t.typrelid = 0 "\
185 "     OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "\
186 "    AND t.typname !~ '^_' "\
187 "    AND substr(nspname || '.' || pg_catalog.format_type(t.oid, NULL),1,%d)='%s' "\
188 "    AND typnamespace = n.oid "\
189 "    AND ('%s' ~ '^.*\\\\.' "\
190 "     OR (SELECT TRUE "\
191 "           FROM pg_catalog.pg_namespace "\
192 "          WHERE substr(nspname,1,%d)='%s' "\
193 "         HAVING COUNT(nspname)=1))"
194
195 #define Query_for_list_of_domains \
196 " SELECT typname "\
197 "   FROM pg_catalog.pg_type t "\
198 "  WHERE typtype = 'd' "\
199 "    AND substr(typname,1,%d)='%s' "\
200 "        UNION" \
201 " SELECT nspname || '.' "\
202 "   FROM pg_catalog.pg_namespace "\
203 "  WHERE substr(nspname,1,%d)='%s' "\
204 "        UNION "\
205 " SELECT nspname || '.' || pg_catalog.format_type(t.oid, NULL) "\
206 "   FROM pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
207 "  WHERE typtype = 'd' "\
208 "    AND substr(nspname || '.' || typname,1,%d)='%s' "\
209 "    AND typnamespace = n.oid "\
210 "    AND ('%s' ~ '^.*\\\\.' "\
211 "     OR (SELECT TRUE "\
212 "           FROM pg_catalog.pg_namespace "\
213 "          WHERE substr(nspname,1,%d)='%s' "\
214 "         HAVING COUNT(nspname)=1))"
215
216 #define Query_for_list_of_encodings \
217 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
218 "   FROM pg_catalog.pg_conversion "\
219 "  WHERE substr(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
220
221 #define Query_for_list_of_functions \
222 " SELECT DISTINCT proname || '()' "\
223 "   FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
224 "  WHERE substr(proname,1,%d)='%s'"\
225 "    AND pg_catalog.pg_function_is_visible(p.oid) "\
226 "    AND pronamespace = n.oid "\
227 "        UNION "\
228 " SELECT nspname || '.' "\
229 "   FROM pg_catalog.pg_namespace "\
230 "  WHERE substr(nspname,1,%d)='%s' "\
231 "        UNION "\
232 " SELECT nspname || '.' || proname "\
233 "   FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
234 "  WHERE substr(nspname || '.' || proname,1,%d)='%s' "\
235 "    AND pronamespace = n.oid "\
236 "    AND ('%s' ~ '^.*\\\\.' "\
237 "     OR (SELECT TRUE "\
238 "           FROM pg_catalog.pg_namespace "\
239 "          WHERE substr(nspname,1,%d)='%s' "\
240 "         HAVING COUNT(nspname)=1))"
241
242 #define Query_for_list_of_indexes \
243 " SELECT relname "\
244 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
245 "  WHERE relkind='i' "\
246 "    AND substr(relname,1,%d)='%s' "\
247 "    AND pg_catalog.pg_table_is_visible(c.oid) "\
248 "    AND relnamespace = n.oid "\
249 "    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "\
250 "        UNION "\
251 " SELECT nspname || '.' "\
252 "   FROM pg_catalog.pg_namespace "\
253 "  WHERE substr(nspname,1,%d)='%s' "\
254 "        UNION "\
255 " SELECT nspname || '.' || relname "\
256 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
257 "  WHERE relkind='i' "\
258 "    AND substr(nspname || '.' || relname,1,%d)='%s' "\
259 "    AND relnamespace = n.oid "\
260 "    AND ('%s' ~ '^.*\\\\.' "\
261 "     OR (SELECT TRUE "\
262 "           FROM pg_catalog.pg_namespace "\
263 "          WHERE substr(nspname,1,%d)='%s' "\
264 "         HAVING COUNT(nspname)=1))"
265
266
267 #define Query_for_list_of_languages \
268 "SELECT lanname "\
269 "  FROM pg_language "\
270 " WHERE lanname != 'internal' "\
271 "   AND substr(lanname,1,%d)='%s' "
272
273 #define Query_for_list_of_schemas \
274 "SELECT nspname FROM pg_catalog.pg_namespace "\
275 " WHERE substr(nspname,1,%d)='%s'"
276
277 #define Query_for_list_of_sequences \
278 " SELECT relname "\
279 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
280 "  WHERE relkind='S' "\
281 "    AND substr(relname,1,%d)='%s' "\
282 "    AND pg_catalog.pg_table_is_visible(c.oid) "\
283 "    AND relnamespace = n.oid "\
284 "    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "\
285 "        UNION "\
286 " SELECT nspname || '.' "\
287 "   FROM pg_catalog.pg_namespace "\
288 "  WHERE substr(nspname,1,%d)='%s' "\
289 "        UNION "\
290 " SELECT nspname || '.' || relname "\
291 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
292 "  WHERE relkind='S' "\
293 "    AND substr(nspname || '.' || relname,1,%d)='%s' "\
294 "    AND relnamespace = n.oid "\
295 "    AND ('%s' ~ '^.*\\\\.' "\
296 "     OR (SELECT TRUE "\
297 "           FROM pg_catalog.pg_namespace "\
298 "          WHERE substr(nspname,1,%d)='%s' "\
299 "         HAVING COUNT(nspname)=1))"
300
301 #define Query_for_list_of_system_relations \
302 "SELECT c.relname FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
303 " WHERE (c.relkind='r' OR c.relkind='v' OR c.relkind='s' OR c.relkind='S') "\
304 "   AND substr(c.relname,1,%d)='%s' "\
305 "   AND pg_catalog.pg_table_is_visible(c.oid)"\
306 "   AND relnamespace = n.oid "\
307 "   AND n.nspname = 'pg_catalog'"
308
309 #define Query_for_list_of_tables \
310 " SELECT relname "\
311 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
312 "  WHERE relkind='r' "\
313 "    AND substr(relname,1,%d)='%s' "\
314 "    AND pg_catalog.pg_table_is_visible(c.oid) "\
315 "    AND relnamespace = n.oid "\
316 "    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "\
317 "        UNION "\
318 " SELECT nspname || '.' "\
319 "   FROM pg_catalog.pg_namespace "\
320 "  WHERE substr(nspname  || '.',1,%d)='%s' "\
321 "        UNION "\
322 " SELECT nspname || '.' || relname "\
323 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
324 "  WHERE relkind='r' "\
325 "    AND substr(nspname || '.' || relname,1,%d)='%s' "\
326 "    AND relnamespace = n.oid "\
327 "    AND ('%s' ~ '^.*\\\\.' "\
328 "     OR (SELECT TRUE "\
329 "           FROM pg_catalog.pg_namespace n1 "\
330 "          WHERE substr(nspname ||'.',1,%d)='%s' "\
331 "         HAVING COUNT(nspname)=1))"
332
333 #define Query_for_list_of_tisv \
334 " SELECT relname "\
335 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
336 "  WHERE (relkind='r' OR relkind='i' OR relkind='S' OR relkind='v') "\
337 "    AND substr(relname,1,%d)='%s' "\
338 "    AND pg_catalog.pg_table_is_visible(c.oid) "\
339 "    AND relnamespace = n.oid "\
340 "    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "\
341 "        UNION "\
342 " SELECT nspname || '.' "\
343 "   FROM pg_catalog.pg_namespace "\
344 "  WHERE substr(nspname,1,%d)='%s' "\
345 "        UNION "\
346 " SELECT nspname || '.' || relname "\
347 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
348 "  WHERE (relkind='r' OR relkind='i' OR relkind='S' OR relkind='v') "\
349 "    AND substr(nspname || '.' || relname,1,%d)='%s' "\
350 "    AND relnamespace = n.oid "\
351 "    AND ('%s' ~ '^.*\\\\.' "\
352 "     OR (SELECT TRUE "\
353 "           FROM pg_catalog.pg_namespace "\
354 "          WHERE substr(nspname,1,%d)='%s' "\
355 "         HAVING COUNT(nspname)=1))"
356
357 #define Query_for_list_of_tsv \
358 " SELECT relname "\
359 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
360 "  WHERE (relkind='r' OR relkind='S' OR relkind='v') "\
361 "    AND substr(relname,1,%d)='%s' "\
362 "    AND pg_catalog.pg_table_is_visible(c.oid) "\
363 "    AND relnamespace = n.oid "\
364 "    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "\
365 "        UNION "\
366 " SELECT nspname || '.' "\
367 "   FROM pg_catalog.pg_namespace "\
368 "  WHERE substr(nspname,1,%d)='%s' "\
369 "        UNION "\
370 " SELECT nspname || '.' || relname "\
371 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
372 "  WHERE (relkind='r' OR relkind='S' OR relkind='v') "\
373 "    AND substr(nspname || '.' || relname,1,%d)='%s' "\
374 "    AND relnamespace = n.oid "\
375 "    AND ('%s' ~ '^.*\\\\.' "\
376 "     OR (SELECT TRUE "\
377 "           FROM pg_catalog.pg_namespace "\
378 "          WHERE substr(nspname,1,%d)='%s' "\
379 "         HAVING COUNT(nspname)=1))"
380
381 #define Query_for_list_of_views \
382 " SELECT relname "\
383 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
384 "  WHERE relkind='v'"\
385 "    AND substr(relname,1,%d)='%s' "\
386 "    AND pg_catalog.pg_table_is_visible(c.oid) "\
387 "    AND relnamespace = n.oid "\
388 "    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "\
389 "        UNION "\
390 " SELECT nspname || '.' "\
391 "   FROM pg_catalog.pg_namespace "\
392 "  WHERE substr(nspname,1,%d)='%s' "\
393 "        UNION "\
394 " SELECT nspname || '.' || relname "\
395 "   FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
396 "  WHERE relkind='v' "\
397 "    AND substr(nspname || '.' || relname,1,%d)='%s' "\
398 "    AND relnamespace = n.oid "\
399 "    AND ('%s' ~ '^.*\\\\.' "\
400 "     OR (SELECT TRUE "\
401 "           FROM pg_catalog.pg_namespace "\
402 "          WHERE substr(nspname,1,%d)='%s' "\
403 "         HAVING COUNT(nspname)=1))"
404
405 #define Query_for_list_of_users \
406 " SELECT usename "\
407 "   FROM pg_catalog.pg_user "\
408 "  WHERE substr(usename,1,%d)='%s'"
409
410 /* the silly-looking length condition is just to eat up the current word */
411 #define Query_for_table_owning_index \
412 "SELECT c1.relname "\
413 "  FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
414 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
415 "       and (%d = length('%s'))"\
416 "       and c2.relname='%s'"\
417 "       and pg_catalog.pg_table_is_visible(c2.oid)"
418
419 /* This is a list of all "things" in Pgsql, which can show up after CREATE or
420    DROP; and there is also a query to get a list of them.
421 */
422
423 #define WITH_SCHEMA 1
424 #define NO_SCHEMA 0
425
426 typedef struct
427 {
428         char       *name;
429         int                     with_schema;
430         char       *query;
431 } pgsql_thing_t;
432
433 pgsql_thing_t words_after_create[] = {
434         {"AGGREGATE", WITH_SCHEMA, Query_for_list_of_aggregates},
435         {"CAST", NO_SCHEMA, NULL},      /* Casts have complex structures for
436                                                                  * namees, so skip it */
437         {"CONVERSION", NO_SCHEMA, "SELECT conname FROM pg_catalog.pg_conversion WHERE substr(conname,1,%d)='%s'"},
438         {"DATABASE", NO_SCHEMA, Query_for_list_of_databases},
439         {"DOMAIN", WITH_SCHEMA, Query_for_list_of_domains},
440         {"FUNCTION", WITH_SCHEMA, Query_for_list_of_functions},
441         {"GROUP", NO_SCHEMA, "SELECT groname FROM pg_catalog.pg_group WHERE substr(groname,1,%d)='%s'"},
442         {"LANGUAGE", NO_SCHEMA, Query_for_list_of_languages},
443         {"INDEX", WITH_SCHEMA, Query_for_list_of_indexes},
444         {"OPERATOR", NO_SCHEMA, NULL},          /* Querying for this is probably
445                                                                                  * not such a good idea. */
446         {"RULE", NO_SCHEMA, "SELECT rulename FROM pg_catalog.pg_rules WHERE substr(rulename,1,%d)='%s'"},
447         {"SCHEMA", NO_SCHEMA, Query_for_list_of_schemas},
448         {"SEQUENCE", WITH_SCHEMA, Query_for_list_of_sequences},
449         {"TABLE", WITH_SCHEMA, Query_for_list_of_tables},
450         {"TEMP", NO_SCHEMA, NULL},      /* for CREATE TEMP TABLE ... */
451         {"TRIGGER", NO_SCHEMA, "SELECT tgname FROM pg_catalog.pg_trigger WHERE substr(tgname,1,%d)='%s'"},
452         {"TYPE", WITH_SCHEMA, Query_for_list_of_datatypes},
453         {"UNIQUE", NO_SCHEMA, NULL},    /* for CREATE UNIQUE INDEX ... */
454         {"USER", NO_SCHEMA, Query_for_list_of_users},
455         {"VIEW", WITH_SCHEMA, Query_for_list_of_views},
456         {NULL, NO_SCHEMA, NULL}         /* end of list */
457 };
458
459
460 /* A couple of macros to ease typing. You can use these to complete the given
461    string with
462    1) The results from a query you pass it. (Perhaps one of those above?)
463    2) The results from a schema query you pass it.
464    3) The items from a null-pointer-terminated list.
465    4) A string constant
466    5) The list of attributes to the given table.
467 */
468 #define COMPLETE_WITH_QUERY(query) \
469 do { completion_charp = query; matches = completion_matches(text, complete_from_query); } while(0)
470 #define COMPLETE_WITH_SCHEMA_QUERY(query) \
471 do { completion_charp = query; matches = completion_matches(text, complete_from_schema_query); } while(0)
472 #define COMPLETE_WITH_LIST(list) \
473 do { completion_charpp = list; matches = completion_matches(text, complete_from_list); } while(0)
474 #define COMPLETE_WITH_CONST(string) \
475 do { completion_charp = string; matches = completion_matches(text, complete_from_const); } while(0)
476 #define COMPLETE_WITH_ATTR(table) \
477 do {completion_charp = Query_for_list_of_attributes; completion_info_charp = table; matches = completion_matches(text, complete_from_query); } while(0)
478
479
480 /* The completion function. Acc. to readline spec this gets passed the text
481    entered to far and its start and end in the readline buffer. The return value
482    is some partially obscure list format that can be generated by the readline
483    libraries completion_matches() function, so we don't have to worry about it.
484 */
485 static char **
486 psql_completion(char *text, int start, int end)
487 {
488         /* This is the variable we'll return. */
489         char      **matches = NULL;
490
491         /* These are going to contain some scannage of the input line. */
492         char       *prev_wd,
493                            *prev2_wd,
494                            *prev3_wd,
495                            *prev4_wd;
496
497         static char *sql_commands[] = {
498                 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
499                 "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE", "DROP", "EXECUTE",
500                 "EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY",
501                 "PREPARE", "REINDEX", "RESET", "REVOKE", "ROLLBACK", "SELECT", "SET", "SHOW",
502                 "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", NULL
503         };
504
505         static char *pgsql_variables[] = {
506                 /* these SET arguments are known in gram.y */
507                 "CONSTRAINTS",
508                 "NAMES",
509                 "SESSION",
510                 "TRANSACTION",
511
512                 /*
513                  * the rest should match USERSET and possibly SUSET entries in
514                  * backend/utils/misc/guc.c.
515                  */
516                 "add_missing_from",
517                 "australian_timezones",
518                 "client_encoding",
519                 "client_min_messages",
520                 "commit_delay",
521                 "commit_siblings",
522                 "cpu_index_tuple_cost",
523                 "cpu_operator_cost",
524                 "cpu_tuple_cost",
525                 "DateStyle",
526                 "deadlock_timeout",
527                 "debug_pretty_print",
528                 "debug_print_parse",
529                 "debug_print_plan",
530                 "debug_print_rewritten",
531                 "default_statistics_target",
532                 "default_transaction_isolation",
533                 "default_transaction_read_only",
534                 "dynamic_library_path",
535                 "effective_cache_size",
536                 "enable_hashagg",
537                 "enable_hashjoin",
538                 "enable_indexscan",
539                 "enable_mergejoin",
540                 "enable_nestloop",
541                 "enable_seqscan",
542                 "enable_sort",
543                 "enable_tidscan",
544                 "explain_pretty_print",
545                 "extra_float_digits",
546                 "from_collapse_limit",
547                 "fsync",
548                 "geqo",
549                 "geqo_effort",
550                 "geqo_generations",
551                 "geqo_pool_size",
552                 "geqo_selection_bias",
553                 "geqo_threshold",
554                 "join_collapse_limit",
555                 "krb_server_keyfile",
556                 "lc_messages",
557                 "lc_monetary",
558                 "lc_numeric",
559                 "lc_time",
560                 "log_duration",
561                 "log_error_verbosity",
562                 "log_executor_stats",
563                 "log_min_duration_statement",
564                 "log_min_error_statement",
565                 "log_min_messages",
566                 "log_parser_stats",
567                 "log_planner_stats",
568                 "log_statement",
569                 "log_statement_stats",
570                 "max_connections",
571                 "max_expr_depth",
572                 "max_files_per_process",
573                 "max_fsm_pages",
574                 "max_fsm_relations",
575                 "max_locks_per_transaction",
576                 "password_encryption",
577                 "port",
578                 "random_page_cost",
579                 "regex_flavor",
580                 "search_path",
581                 "shared_buffers",
582                 "seed",
583                 "server_encoding",
584                 "sort_mem",
585                 "sql_inheritance",
586                 "ssl",
587                 "statement_timeout",
588                 "stats_block_level",
589                 "stats_command_string",
590                 "stats_reset_on_server_start",
591                 "stats_row_level",
592                 "stats_start_collector",
593                 "superuser_reserved_connections",
594                 "syslog",
595                 "syslog_facility",
596                 "syslog_ident",
597                 "tcpip_socket",
598                 "TimeZone",
599                 "trace_notify",
600                 "transform_null_equals",
601                 "unix_socket_directory",
602                 "unix_socket_group",
603                 "unix_socket_permissions",
604                 "vacuum_mem",
605                 "wal_buffers",
606                 "wal_debug",
607                 "wal_sync_method",
608                 NULL
609         };
610
611         static char *backslash_commands[] = {
612                 "\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",
613                 "\\d", "\\da", "\\dc", "\\dC", "\\dd", "\\dD", "\\df", "\\di",
614                 "\\dl", "\\dn", "\\do", "\\dp", "\\ds", "\\dS", "\\dt", "\\dT",
615                 "\\dv", "\\du",
616                 "\\e", "\\echo", "\\encoding",
617                 "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
618                 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
619                 "\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
620                 "\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
621         };
622
623         (void) end;                                     /* not used */
624
625 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
626         rl_completion_append_character = ' ';
627 #endif
628
629         /* Clear a few things. */
630         completion_charp = NULL;
631         completion_charpp = NULL;
632         completion_info_charp = NULL;
633
634         /*
635          * Scan the input line before our current position for the last four
636          * words. According to those we'll make some smart decisions on what
637          * the user is probably intending to type. TODO: Use strtokx() to do
638          * this.
639          */
640         prev_wd = previous_word(start, 0);
641         prev2_wd = previous_word(start, 1);
642         prev3_wd = previous_word(start, 2);
643         prev4_wd = previous_word(start, 3);
644
645         /* If a backslash command was started, continue */
646         if (text[0] == '\\')
647                 COMPLETE_WITH_LIST(backslash_commands);
648
649         /* If no previous word, suggest one of the basic sql commands */
650         else if (!prev_wd)
651                 COMPLETE_WITH_LIST(sql_commands);
652
653 /* CREATE or DROP but not ALTER TABLE sth DROP */
654         /* complete with something you can create or drop */
655         else if (strcasecmp(prev_wd, "CREATE") == 0 ||
656                          (strcasecmp(prev_wd, "DROP") == 0 &&
657                           strcasecmp(prev3_wd, "TABLE") != 0))
658                 matches = completion_matches(text, create_command_generator);
659
660 /* ALTER */
661
662         /*
663          * complete with what you can alter (TABLE, GROUP, USER, ...) unless
664          * we're in ALTER TABLE sth ALTER
665          */
666         else if (strcasecmp(prev_wd, "ALTER") == 0 &&
667                          strcasecmp(prev3_wd, "TABLE") != 0)
668         {
669                 char       *list_ALTER[] = {"DATABASE", "GROUP", "SCHEMA", "TABLE",
670                 "TRIGGER", "USER", NULL};
671
672                 COMPLETE_WITH_LIST(list_ALTER);
673         }
674
675         /* ALTER DATABASE <name> */
676         else if (strcasecmp(prev3_wd, "ALTER") == 0 &&
677                          strcasecmp(prev2_wd, "DATABASE") == 0)
678         {
679                 char       *list_ALTERDATABASE[] = {"RESET", "SET", NULL};
680
681                 COMPLETE_WITH_LIST(list_ALTERDATABASE);
682         }
683         /* ALTER TRIGGER <name>, add ON */
684         else if (strcasecmp(prev3_wd, "ALTER") == 0 &&
685                          strcasecmp(prev2_wd, "TRIGGER") == 0)
686                 COMPLETE_WITH_CONST("ON");
687
688         /*
689          * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
690          */
691         else if (strcasecmp(prev4_wd, "ALTER") == 0 &&
692                          strcasecmp(prev3_wd, "TRIGGER") == 0 &&
693                          strcasecmp(prev_wd, "ON") == 0)
694                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
695
696         /*
697          * If we detect ALTER TABLE <name>, suggest either ADD, DROP, ALTER,
698          * RENAME, or OWNER
699          */
700         else if (strcasecmp(prev3_wd, "ALTER") == 0 &&
701                          strcasecmp(prev2_wd, "TABLE") == 0)
702         {
703                 char       *list_ALTER2[] = {"ADD", "ALTER", "DROP", "RENAME",
704                 "OWNER TO", NULL};
705
706                 COMPLETE_WITH_LIST(list_ALTER2);
707         }
708         /* If we have TABLE <sth> ALTER|RENAME, provide list of columns */
709         else if (strcasecmp(prev3_wd, "TABLE") == 0 &&
710                          (strcasecmp(prev_wd, "ALTER") == 0 ||
711                           strcasecmp(prev_wd, "RENAME") == 0))
712                 COMPLETE_WITH_ATTR(prev2_wd);
713
714         /* If we have TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
715         else if (strcasecmp(prev3_wd, "TABLE") == 0 &&
716                          strcasecmp(prev_wd, "DROP") == 0)
717         {
718                 char       *list_TABLEDROP[] = {"COLUMN", "CONSTRAINT", NULL};
719
720                 COMPLETE_WITH_LIST(list_TABLEDROP);
721         }
722         /* If we have TABLE <sth> DROP COLUMN, provide list of columns */
723         else if (strcasecmp(prev4_wd, "TABLE") == 0 &&
724                          strcasecmp(prev2_wd, "DROP") == 0 &&
725                          strcasecmp(prev_wd, "COLUMN") == 0)
726                 COMPLETE_WITH_ATTR(prev3_wd);
727
728         /* complete ALTER GROUP <foo> with ADD or DROP */
729         else if (strcasecmp(prev3_wd, "ALTER") == 0 &&
730                          strcasecmp(prev2_wd, "GROUP") == 0)
731         {
732                 char       *list_ALTERGROUP[] = {"ADD", "DROP", NULL};
733
734                 COMPLETE_WITH_LIST(list_ALTERGROUP);
735         }
736         /* complete ALTER GROUP <foo> ADD|DROP with USER */
737         else if (strcasecmp(prev4_wd, "ALTER") == 0 &&
738                          strcasecmp(prev3_wd, "GROUP") == 0 &&
739                          (strcasecmp(prev_wd, "ADD") == 0 ||
740                           strcasecmp(prev_wd, "DROP") == 0))
741                 COMPLETE_WITH_CONST("USER");
742         /* complete {ALTER} GROUP <foo> ADD|DROP USER with a user name */
743         else if (strcasecmp(prev4_wd, "GROUP") == 0 &&
744                          (strcasecmp(prev2_wd, "ADD") == 0 ||
745                           strcasecmp(prev2_wd, "DROP") == 0) &&
746                          strcasecmp(prev_wd, "USER") == 0)
747                 COMPLETE_WITH_QUERY(Query_for_list_of_users);
748
749 /* ANALYZE */
750         /* If the previous word is ANALYZE, produce list of tables. */
751         else if (strcasecmp(prev_wd, "ANALYZE") == 0)
752                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
753         /* If we have ANALYZE <table>, complete with semicolon. */
754         else if (strcasecmp(prev2_wd, "ANALYZE") == 0)
755                 COMPLETE_WITH_CONST(";");
756
757 /* CLUSTER */
758         /* If the previous word is CLUSTER, produce list of indexes. */
759         else if (strcasecmp(prev_wd, "CLUSTER") == 0)
760                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
761         /* If we have CLUSTER <sth>, then add "ON" */
762         else if (strcasecmp(prev2_wd, "CLUSTER") == 0)
763                 COMPLETE_WITH_CONST("ON");
764
765         /*
766          * If we have CLUSTER <sth> ON, then add the correct tablename as
767          * well.
768          */
769         else if (strcasecmp(prev3_wd, "CLUSTER") == 0 &&
770                          strcasecmp(prev_wd, "ON") == 0)
771         {
772                 completion_info_charp = prev2_wd;
773                 COMPLETE_WITH_QUERY(Query_for_table_owning_index);
774         }
775
776 /* COMMENT */
777         else if (strcasecmp(prev_wd, "COMMENT") == 0)
778                 COMPLETE_WITH_CONST("ON");
779         else if (strcasecmp(prev2_wd, "COMMENT") == 0 &&
780                          strcasecmp(prev_wd, "ON") == 0)
781         {
782                 char       *list_COMMENT[] =
783                 {"DATABASE", "INDEX", "RULE", "SCHEMA", "SEQUENCE", "TABLE",
784                         "TYPE", "VIEW", "COLUMN", "AGGREGATE", "FUNCTION", "OPERATOR",
785                 "TRIGGER", "CONSTRAINT", "DOMAIN", NULL};
786
787                 COMPLETE_WITH_LIST(list_COMMENT);
788         }
789         else if (strcasecmp(prev4_wd, "COMMENT") == 0 &&
790                          strcasecmp(prev3_wd, "ON") == 0)
791                 COMPLETE_WITH_CONST("IS");
792
793 /* COPY */
794
795         /*
796          * If we have COPY [BINARY] (which you'd have to type yourself), offer
797          * list of tables (Also cover the analogous backslash command)
798          */
799         else if (strcasecmp(prev_wd, "COPY") == 0 ||
800                          strcasecmp(prev_wd, "\\copy") == 0 ||
801                          (strcasecmp(prev2_wd, "COPY") == 0 &&
802                           strcasecmp(prev_wd, "BINARY") == 0))
803                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
804         /* If we have COPY|BINARY <sth>, complete it with "TO" or "FROM" */
805         else if (strcasecmp(prev2_wd, "COPY") == 0 ||
806                          strcasecmp(prev2_wd, "\\copy") == 0 ||
807                          strcasecmp(prev2_wd, "BINARY") == 0)
808         {
809                 char       *list_FROMTO[] = {"FROM", "TO", NULL};
810
811                 COMPLETE_WITH_LIST(list_FROMTO);
812         }
813
814 /* CREATE INDEX */
815         /* First off we complete CREATE UNIQUE with "INDEX" */
816         else if (strcasecmp(prev2_wd, "CREATE") == 0 &&
817                          strcasecmp(prev_wd, "UNIQUE") == 0)
818                 COMPLETE_WITH_CONST("INDEX");
819         /* If we have CREATE|UNIQUE INDEX <sth>, then add "ON" */
820         else if (strcasecmp(prev2_wd, "INDEX") == 0 &&
821                          (strcasecmp(prev3_wd, "CREATE") == 0 ||
822                           strcasecmp(prev3_wd, "UNIQUE") == 0))
823                 COMPLETE_WITH_CONST("ON");
824         /* Complete ... INDEX <name> ON with a list of tables  */
825         else if (strcasecmp(prev3_wd, "INDEX") == 0 &&
826                          strcasecmp(prev_wd, "ON") == 0)
827                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
828
829         /*
830          * Complete INDEX <name> ON <table> with a list of table columns
831          * (which should really be in parens)
832          */
833         else if (strcasecmp(prev4_wd, "INDEX") == 0 &&
834                          strcasecmp(prev2_wd, "ON") == 0)
835                 COMPLETE_WITH_ATTR(prev_wd);
836         /* same if you put in USING */
837         else if (strcasecmp(prev4_wd, "ON") == 0 &&
838                          strcasecmp(prev2_wd, "USING") == 0)
839                 COMPLETE_WITH_ATTR(prev3_wd);
840         /* Complete USING with an index method */
841         else if (strcasecmp(prev_wd, "USING") == 0)
842         {
843                 char       *index_mth[] = {"BTREE", "RTREE", "HASH", "GIST", NULL};
844
845                 COMPLETE_WITH_LIST(index_mth);
846         }
847
848 /* CREATE RULE */
849         /* Complete "CREATE RULE <sth>" with "AS" */
850         else if (strcasecmp(prev3_wd, "CREATE") == 0 &&
851                          strcasecmp(prev2_wd, "RULE") == 0)
852                 COMPLETE_WITH_CONST("AS");
853         /* Complete "CREATE RULE <sth> AS with "ON" */
854         else if (strcasecmp(prev4_wd, "CREATE") == 0 &&
855                          strcasecmp(prev3_wd, "RULE") == 0 &&
856                          strcasecmp(prev_wd, "AS") == 0)
857                 COMPLETE_WITH_CONST("ON");
858         /* Complete "RULE * AS ON" with SELECT|UPDATE|DELETE|INSERT */
859         else if (strcasecmp(prev4_wd, "RULE") == 0 &&
860                          strcasecmp(prev2_wd, "AS") == 0 &&
861                          strcasecmp(prev_wd, "ON") == 0)
862         {
863                 char       *rule_events[] = {"SELECT", "UPDATE", "INSERT",
864                 "DELETE", NULL};
865
866                 COMPLETE_WITH_LIST(rule_events);
867         }
868         /* Complete "AS ON <sth with a 'T' :)>" with a "TO" */
869         else if (strcasecmp(prev3_wd, "AS") == 0 &&
870                          strcasecmp(prev2_wd, "ON") == 0 &&
871                          (toupper((unsigned char) prev_wd[4]) == 'T' ||
872                           toupper((unsigned char) prev_wd[5]) == 'T'))
873                 COMPLETE_WITH_CONST("TO");
874         /* Complete "AS ON <sth> TO" with a table name */
875         else if (strcasecmp(prev4_wd, "AS") == 0 &&
876                          strcasecmp(prev3_wd, "ON") == 0 &&
877                          strcasecmp(prev_wd, "TO") == 0)
878                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
879
880 /* CREATE TABLE */
881         /* Complete CREATE TEMP with "TABLE" */
882         else if (strcasecmp(prev2_wd, "CREATE") == 0 &&
883                          strcasecmp(prev_wd, "TEMP") == 0)
884                 COMPLETE_WITH_CONST("TABLE");
885
886 /* CREATE TRIGGER */
887         /* is on the agenda . . . */
888
889 /* CREATE VIEW */
890         /* Complete "CREATE VIEW <name>" with "AS" */
891         else if (strcasecmp(prev3_wd, "CREATE") == 0 &&
892                          strcasecmp(prev2_wd, "VIEW") == 0)
893                 COMPLETE_WITH_CONST("AS");
894         /* Complete "CREATE VIEW <sth> AS with "SELECT" */
895         else if (strcasecmp(prev4_wd, "CREATE") == 0 &&
896                          strcasecmp(prev3_wd, "VIEW") == 0 &&
897                          strcasecmp(prev_wd, "AS") == 0)
898                 COMPLETE_WITH_CONST("SELECT");
899
900 /* DELETE */
901
902         /*
903          * Complete DELETE with FROM (only if the word before that is not "ON"
904          * (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT)
905          */
906         else if (strcasecmp(prev_wd, "DELETE") == 0 &&
907                          !(strcasecmp(prev2_wd, "ON") == 0 ||
908                            strcasecmp(prev2_wd, "GRANT") == 0 ||
909                            strcasecmp(prev2_wd, "BEFORE") == 0 ||
910                            strcasecmp(prev2_wd, "AFTER") == 0))
911                 COMPLETE_WITH_CONST("FROM");
912         /* Complete DELETE FROM with a list of tables */
913         else if (strcasecmp(prev2_wd, "DELETE") == 0 &&
914                          strcasecmp(prev_wd, "FROM") == 0)
915                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
916         /* Complete DELETE FROM <table> with "WHERE" (perhaps a safe idea?) */
917         else if (strcasecmp(prev3_wd, "DELETE") == 0 &&
918                          strcasecmp(prev2_wd, "FROM") == 0)
919                 COMPLETE_WITH_CONST("WHERE");
920
921 /* EXPLAIN */
922
923         /*
924          * Complete EXPLAIN [VERBOSE] (which you'd have to type yourself) with
925          * the list of SQL commands
926          */
927         else if (strcasecmp(prev_wd, "EXPLAIN") == 0 ||
928                          (strcasecmp(prev2_wd, "EXPLAIN") == 0 &&
929                           strcasecmp(prev_wd, "VERBOSE") == 0))
930                 COMPLETE_WITH_LIST(sql_commands);
931
932 /* FETCH && MOVE */
933         /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
934         else if (strcasecmp(prev_wd, "FETCH") == 0 ||
935                          strcasecmp(prev_wd, "MOVE") == 0)
936         {
937                 char       *list_FETCH1[] = {"FORWARD", "BACKWARD", "RELATIVE", NULL};
938
939                 COMPLETE_WITH_LIST(list_FETCH1);
940         }
941         /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
942         else if (strcasecmp(prev2_wd, "FETCH") == 0 ||
943                          strcasecmp(prev2_wd, "MOVE") == 0)
944         {
945                 char       *list_FETCH2[] = {"ALL", "NEXT", "PRIOR", NULL};
946
947                 COMPLETE_WITH_LIST(list_FETCH2);
948         }
949
950         /*
951          * Complete FETCH <sth1> <sth2> with "FROM" or "TO". (Is there a
952          * difference? If not, remove one.)
953          */
954         else if (strcasecmp(prev3_wd, "FETCH") == 0 ||
955                          strcasecmp(prev3_wd, "MOVE") == 0)
956         {
957                 char       *list_FROMTO[] = {"FROM", "TO", NULL};
958
959                 COMPLETE_WITH_LIST(list_FROMTO);
960         }
961
962 /* GRANT && REVOKE*/
963         /* Complete GRANT/REVOKE with a list of privileges */
964         else if (strcasecmp(prev_wd, "GRANT") == 0 ||
965                          strcasecmp(prev_wd, "REVOKE") == 0)
966         {
967                 char       *list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL};
968
969                 COMPLETE_WITH_LIST(list_privileg);
970         }
971         /* Complete GRANT/REVOKE <sth> with "ON" */
972         else if (strcasecmp(prev2_wd, "GRANT") == 0 ||
973                          strcasecmp(prev2_wd, "REVOKE") == 0)
974                 COMPLETE_WITH_CONST("ON");
975
976         /*
977          * Complete GRANT/REVOKE <sth> ON with a list of tables, views,
978          * sequences, and indexes
979          *
980          * keywords DATABASE, FUNCTION, LANGUAGE, SCHEMA added to query result
981          * via UNION; seems to work intuitively
982          *
983          * Note: GRANT/REVOKE can get quite complex; tab-completion as
984          * implemented here will only work if the privilege list contains
985          * exactly one privilege
986          */
987         else if ((strcasecmp(prev3_wd, "GRANT") == 0 ||
988                           strcasecmp(prev3_wd, "REVOKE") == 0) &&
989                          strcasecmp(prev_wd, "ON") == 0)
990                 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
991                                                         " WHERE relkind in ('r','S','v')  "
992                                                         "   AND substr(relname,1,%d)='%s' "
993                                                   "   AND pg_catalog.pg_table_is_visible(c.oid) "
994                                                         "   AND relnamespace = n.oid "
995                                         "   AND n.nspname NOT IN ('pg_catalog', 'pg_toast') "
996                                                         " UNION "
997                                                         "SELECT 'DATABASE' AS relname "
998                                                         " UNION "
999                                                         "SELECT 'FUNCTION' AS relname "
1000                                                         " UNION "
1001                                                         "SELECT 'LANGUAGE' AS relname "
1002                                                         " UNION "
1003                                                         "SELECT 'SCHEMA' AS relname ");
1004
1005         /* Complete "GRANT/REVOKE * ON * " with "TO" */
1006         else if ((strcasecmp(prev4_wd, "GRANT") == 0 ||
1007                           strcasecmp(prev4_wd, "REVOKE") == 0) &&
1008                          strcasecmp(prev2_wd, "ON") == 0)
1009         {
1010                 if (strcasecmp(prev_wd, "DATABASE") == 0)
1011                         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1012                 else if (strcasecmp(prev_wd, "FUNCTION") == 0)
1013                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
1014                 else if (strcasecmp(prev_wd, "LANGUAGE") == 0)
1015                         COMPLETE_WITH_QUERY(Query_for_list_of_languages);
1016                 else if (strcasecmp(prev_wd, "SCHEMA") == 0)
1017                         COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
1018                 else
1019                         COMPLETE_WITH_CONST("TO");
1020         }
1021
1022         /*
1023          * TODO: to complete with user name we need prev5_wd -- wait for a
1024          * more general solution there same for GRANT <sth> ON { DATABASE |
1025          * FUNCTION | LANGUAGE | SCHEMA } xxx TO
1026          */
1027
1028 /* INSERT */
1029         /* Complete INSERT with "INTO" */
1030         else if (strcasecmp(prev_wd, "INSERT") == 0)
1031                 COMPLETE_WITH_CONST("INTO");
1032         /* Complete INSERT INTO with table names */
1033         else if (strcasecmp(prev2_wd, "INSERT") == 0 &&
1034                          strcasecmp(prev_wd, "INTO") == 0)
1035                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1036         /* Complete "INSERT INTO <table> (" with attribute names */
1037         else if (rl_line_buffer[start - 1] == '(' &&
1038                          strcasecmp(prev3_wd, "INSERT") == 0 &&
1039                          strcasecmp(prev2_wd, "INTO") == 0)
1040                 COMPLETE_WITH_ATTR(prev_wd);
1041
1042         /*
1043          * Complete INSERT INTO <table> with "VALUES" or "SELECT" or "DEFAULT
1044          * VALUES"
1045          */
1046         else if (strcasecmp(prev3_wd, "INSERT") == 0 &&
1047                          strcasecmp(prev2_wd, "INTO") == 0)
1048         {
1049                 char       *list_INSERT[] = {"DEFAULT VALUES", "SELECT", "VALUES", NULL};
1050
1051                 COMPLETE_WITH_LIST(list_INSERT);
1052         }
1053         /* Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" */
1054         else if (strcasecmp(prev4_wd, "INSERT") == 0 &&
1055                          strcasecmp(prev3_wd, "INTO") == 0 &&
1056                          prev_wd[strlen(prev_wd) - 1] == ')')
1057         {
1058                 char       *list_INSERT[] = {"SELECT", "VALUES", NULL};
1059
1060                 COMPLETE_WITH_LIST(list_INSERT);
1061         }
1062
1063         /* Insert an open parenthesis after "VALUES" */
1064         else if (strcasecmp(prev_wd, "VALUES") == 0 &&
1065                          strcasecmp(prev2_wd, "DEFAULT") != 0)
1066                 COMPLETE_WITH_CONST("(");
1067
1068 /* LOCK */
1069         /* Complete LOCK [TABLE] with a list of tables */
1070         else if (strcasecmp(prev_wd, "LOCK") == 0 ||
1071                          (strcasecmp(prev_wd, "TABLE") == 0 &&
1072                           strcasecmp(prev2_wd, "LOCK") == 0))
1073                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1074
1075         /* For the following, handle the case of a single table only for now */
1076
1077         /* Complete LOCK [TABLE] <table> with "IN" */
1078         else if ((strcasecmp(prev2_wd, "LOCK") == 0 &&
1079                           strcasecmp(prev_wd, "TABLE")) ||
1080                          (strcasecmp(prev2_wd, "TABLE") == 0 &&
1081                           strcasecmp(prev3_wd, "LOCK") == 0))
1082                 COMPLETE_WITH_CONST("IN");
1083
1084         /* Complete LOCK [TABLE] <table> IN with a lock mode */
1085         else if (strcasecmp(prev_wd, "IN") == 0 &&
1086                          (strcasecmp(prev3_wd, "LOCK") == 0 ||
1087                           (strcasecmp(prev3_wd, "TABLE") == 0 &&
1088                            strcasecmp(prev4_wd, "LOCK") == 0)))
1089         {
1090                 char       *lock_modes[] = {"ACCESS SHARE MODE",
1091                         "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
1092                         "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
1093                         "SHARE ROW EXCLUSIVE MODE",
1094                 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE", NULL};
1095
1096                 COMPLETE_WITH_LIST(lock_modes);
1097         }
1098
1099 /* NOTIFY */
1100         else if (strcasecmp(prev_wd, "NOTIFY") == 0)
1101                 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_listener WHERE substr(relname,1,%d)='%s'");
1102
1103 /* REINDEX */
1104         else if (strcasecmp(prev_wd, "REINDEX") == 0)
1105         {
1106                 char       *list_REINDEX[] = {"TABLE", "DATABASE", "INDEX", NULL};
1107
1108                 COMPLETE_WITH_LIST(list_REINDEX);
1109         }
1110         else if (strcasecmp(prev2_wd, "REINDEX") == 0)
1111         {
1112                 if (strcasecmp(prev_wd, "TABLE") == 0)
1113                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1114                 else if (strcasecmp(prev_wd, "DATABASE") == 0)
1115                         COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1116                 else if (strcasecmp(prev_wd, "INDEX") == 0)
1117                         COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
1118         }
1119
1120 /* SELECT */
1121         /* naah . . . */
1122
1123 /* SET, RESET, SHOW */
1124         /* Complete with a variable name */
1125         else if ((strcasecmp(prev_wd, "SET") == 0 &&
1126                           strcasecmp(prev3_wd, "UPDATE") != 0) ||
1127                          strcasecmp(prev_wd, "RESET") == 0 ||
1128                          strcasecmp(prev_wd, "SHOW") == 0)
1129                 COMPLETE_WITH_LIST(pgsql_variables);
1130         /* Complete "SET TRANSACTION" */
1131         else if ((strcasecmp(prev2_wd, "SET") == 0 &&
1132                           strcasecmp(prev_wd, "TRANSACTION") == 0) ||
1133                          (strcasecmp(prev4_wd, "SESSION") == 0 &&
1134                           strcasecmp(prev3_wd, "CHARACTERISTICS") == 0 &&
1135                           strcasecmp(prev2_wd, "AS") == 0 &&
1136                           strcasecmp(prev_wd, "TRANSACTION") == 0))
1137         {
1138                 char       *my_list[] = {"ISOLATION", "READ", NULL};
1139
1140                 COMPLETE_WITH_LIST(my_list);
1141         }
1142         else if (strcasecmp(prev3_wd, "SET") == 0 &&
1143                          strcasecmp(prev2_wd, "TRANSACTION") == 0 &&
1144                          strcasecmp(prev_wd, "ISOLATION") == 0)
1145                 COMPLETE_WITH_CONST("LEVEL");
1146         else if ((strcasecmp(prev4_wd, "SET") == 0 ||
1147                           strcasecmp(prev4_wd, "AS") == 0) &&
1148                          strcasecmp(prev3_wd, "TRANSACTION") == 0 &&
1149                          strcasecmp(prev2_wd, "ISOLATION") == 0 &&
1150                          strcasecmp(prev_wd, "LEVEL") == 0)
1151         {
1152                 char       *my_list[] = {"READ", "SERIALIZABLE", NULL};
1153
1154                 COMPLETE_WITH_LIST(my_list);
1155         }
1156         else if (strcasecmp(prev4_wd, "TRANSACTION") == 0 &&
1157                          strcasecmp(prev3_wd, "ISOLATION") == 0 &&
1158                          strcasecmp(prev2_wd, "LEVEL") == 0 &&
1159                          strcasecmp(prev_wd, "READ") == 0)
1160                 COMPLETE_WITH_CONST("COMMITTED");
1161         else if ((strcasecmp(prev3_wd, "SET") == 0 ||
1162                           strcasecmp(prev3_wd, "AS") == 0) &&
1163                          strcasecmp(prev2_wd, "TRANSACTION") == 0 &&
1164                          strcasecmp(prev_wd, "READ") == 0)
1165         {
1166                 char       *my_list[] = {"ONLY", "WRITE", NULL};
1167
1168                 COMPLETE_WITH_LIST(my_list);
1169         }
1170         /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
1171         else if (strcasecmp(prev3_wd, "SET") == 0 &&
1172                          strcasecmp(prev2_wd, "CONSTRAINTS") == 0)
1173         {
1174                 char       *constraint_list[] = {"DEFERRED", "IMMEDIATE", NULL};
1175
1176                 COMPLETE_WITH_LIST(constraint_list);
1177         }
1178         /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
1179         else if (strcasecmp(prev2_wd, "SET") == 0 &&
1180                          strcasecmp(prev_wd, "SESSION") == 0)
1181         {
1182                 char       *my_list[] = {"AUTHORIZATION",
1183                         "CHARACTERISTICS AS TRANSACTION",
1184                 NULL};
1185
1186                 COMPLETE_WITH_LIST(my_list);
1187         }
1188         /* Complete SET SESSION AUTHORIZATION with username */
1189         else if (strcasecmp(prev3_wd, "SET") == 0
1190                          && strcasecmp(prev2_wd, "SESSION") == 0
1191                          && strcasecmp(prev_wd, "AUTHORIZATION") == 0)
1192                 COMPLETE_WITH_QUERY(Query_for_list_of_users);
1193         /* Complete SET <var> with "TO" */
1194         else if (strcasecmp(prev2_wd, "SET") == 0 &&
1195                          strcasecmp(prev4_wd, "UPDATE") != 0)
1196                 COMPLETE_WITH_CONST("TO");
1197         /* Suggest possible variable values */
1198         else if (strcasecmp(prev3_wd, "SET") == 0 &&
1199                    (strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0))
1200         {
1201                 if (strcasecmp(prev2_wd, "DateStyle") == 0)
1202                 {
1203                         char       *my_list[] = {"ISO", "SQL", "Postgres", "German",
1204                                 "YMD", "DMY", "MDY",
1205                                 "US", "European", "NonEuropean",
1206                         "DEFAULT", NULL};
1207
1208                         COMPLETE_WITH_LIST(my_list);
1209                 }
1210                 else if (strcasecmp(prev2_wd, "GEQO") == 0)
1211                 {
1212                         char       *my_list[] = {"ON", "OFF", "DEFAULT", NULL};
1213
1214                         COMPLETE_WITH_LIST(my_list);
1215                 }
1216                 else
1217                 {
1218                         char       *my_list[] = {"DEFAULT", NULL};
1219
1220                         COMPLETE_WITH_LIST(my_list);
1221                 }
1222         }
1223
1224 /* TRUNCATE */
1225         else if (strcasecmp(prev_wd, "TRUNCATE") == 0)
1226                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1227
1228 /* UNLISTEN */
1229         else if (strcasecmp(prev_wd, "UNLISTEN") == 0)
1230                 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_listener WHERE substr(relname,1,%d)='%s' UNION SELECT '*'::name");
1231
1232 /* UPDATE */
1233         /* If prev. word is UPDATE suggest a list of tables */
1234         else if (strcasecmp(prev_wd, "UPDATE") == 0)
1235                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1236         /* Complete UPDATE <table> with "SET" */
1237         else if (strcasecmp(prev2_wd, "UPDATE") == 0)
1238                 COMPLETE_WITH_CONST("SET");
1239
1240         /*
1241          * If the previous word is SET (and it wasn't caught above as the
1242          * _first_ word) the word before it was (hopefully) a table name and
1243          * we'll now make a list of attributes.
1244          */
1245         else if (strcasecmp(prev_wd, "SET") == 0)
1246                 COMPLETE_WITH_ATTR(prev2_wd);
1247
1248 /* VACUUM */
1249         else if (strcasecmp(prev_wd, "VACUUM") == 0)
1250                 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class WHERE relkind='r' and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid) UNION SELECT 'FULL'::name UNION SELECT 'ANALYZE'::name");
1251         else if (strcasecmp(prev2_wd, "VACUUM") == 0 &&
1252                          (strcasecmp(prev_wd, "FULL") == 0 ||
1253                           strcasecmp(prev_wd, "ANALYZE") == 0))
1254                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1255
1256 /* WHERE */
1257         /* Simple case of the word before the where being the table name */
1258         else if (strcasecmp(prev_wd, "WHERE") == 0)
1259                 COMPLETE_WITH_ATTR(prev2_wd);
1260
1261 /* ... FROM ... */
1262 /* TODO: also include SRF ? */
1263         else if (strcasecmp(prev_wd, "FROM") == 0)
1264                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv);
1265
1266
1267 /* Backslash commands */
1268 /* TODO:  \dc \dd \dl */
1269         else if (strcmp(prev_wd, "\\connect") == 0 || strcmp(prev_wd, "\\c") == 0)
1270                 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1271         else if (strcmp(prev_wd, "\\d") == 0 || strcmp(prev_wd, "\\d+") == 0)
1272                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tisv);
1273         else if (strcmp(prev_wd, "\\da") == 0)
1274                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates);
1275         else if (strcmp(prev_wd, "\\dD") == 0)
1276                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
1277         else if (strcmp(prev_wd, "\\df") == 0 || strcmp(prev_wd, "\\df+") == 0)
1278                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
1279         else if (strcmp(prev_wd, "\\di") == 0 || strcmp(prev_wd, "\\di+") == 0)
1280                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
1281         else if (strcmp(prev_wd, "\\dn") == 0)
1282                 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
1283         else if (strcmp(prev_wd, "\\dp") == 0 || strcmp(prev_wd, "\\z") == 0)
1284                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv);
1285         else if (strcmp(prev_wd, "\\ds") == 0 || strcmp(prev_wd, "\\ds+") == 0)
1286                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
1287         else if (strcmp(prev_wd, "\\dS") == 0 || strcmp(prev_wd, "\\dS+") == 0)
1288                 COMPLETE_WITH_QUERY(Query_for_list_of_system_relations);
1289         else if (strcmp(prev_wd, "\\dt") == 0 || strcmp(prev_wd, "\\dt+") == 0)
1290                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
1291         else if (strcmp(prev_wd, "\\dT") == 0 || strcmp(prev_wd, "\\dT+") == 0)
1292                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
1293         else if (strcmp(prev_wd, "\\du") == 0)
1294                 COMPLETE_WITH_QUERY(Query_for_list_of_users);
1295         else if (strcmp(prev_wd, "\\dv") == 0 || strcmp(prev_wd, "\\dv+") == 0)
1296                 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
1297         else if (strcmp(prev_wd, "\\encoding") == 0)
1298                 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
1299         else if (strcmp(prev_wd, "\\h") == 0 || strcmp(prev_wd, "\\help") == 0)
1300                 COMPLETE_WITH_LIST(sql_commands);
1301         else if (strcmp(prev_wd, "\\pset") == 0)
1302         {
1303                 char       *my_list[] = {"format", "border", "expanded",
1304                         "null", "fieldsep", "tuples_only", "title", "tableattr", "pager",
1305                 "recordsep", NULL};
1306
1307                 COMPLETE_WITH_LIST(my_list);
1308         }
1309         else if (strcmp(prev_wd, "\\cd") == 0 ||
1310                  strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
1311                          strcmp(prev_wd, "\\g") == 0 ||
1312                          strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 ||
1313                   strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 ||
1314                          strcmp(prev_wd, "\\s") == 0 ||
1315                    strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0
1316                 )
1317                 matches = completion_matches(text, filename_completion_function);
1318
1319
1320         /*
1321          * Finally, we look through the list of "things", such as TABLE, INDEX
1322          * and check if that was the previous word. If so, execute the query
1323          * to get a list of them.
1324          */
1325         else
1326         {
1327                 int                     i;
1328
1329                 for (i = 0; words_after_create[i].name; i++)
1330                         if (strcasecmp(prev_wd, words_after_create[i].name) == 0)
1331                         {
1332                                 if (words_after_create[i].with_schema == WITH_SCHEMA)
1333                                         COMPLETE_WITH_SCHEMA_QUERY(words_after_create[i].query);
1334                                 else
1335                                         COMPLETE_WITH_QUERY(words_after_create[i].query);
1336                                 break;
1337                         }
1338         }
1339
1340
1341         /*
1342          * If we still don't have anything to match we have to fabricate some
1343          * sort of default list. If we were to just return NULL, readline
1344          * automatically attempts filename completion, and that's usually no
1345          * good.
1346          */
1347         if (matches == NULL)
1348         {
1349                 COMPLETE_WITH_CONST("");
1350 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1351                 rl_completion_append_character = '\0';
1352 #endif
1353         }
1354
1355
1356         /* free storage */
1357         free(prev_wd);
1358         free(prev2_wd);
1359         free(prev3_wd);
1360         free(prev4_wd);
1361
1362         /* Return our Grand List O' Matches */
1363         return matches;
1364 }
1365
1366
1367
1368 /* GENERATOR FUNCTIONS
1369
1370    These functions do all the actual work of completing the input. They get
1371    passed the text so far and the count how many times they have been called so
1372    far with the same text.
1373    If you read the above carefully, you'll see that these don't get called
1374    directly but through the readline interface.
1375    The return value is expected to be the full completion of the text, going
1376    through a list each time, or NULL if there are no more matches. The string
1377    will be free()'d be readline, so you must run it through strdup() or
1378    something of that sort.
1379 */
1380
1381 /* This one gives you one from a list of things you can put after CREATE or DROP
1382    as defined above.
1383 */
1384 static char *
1385 create_command_generator(const char *text, int state)
1386 {
1387         static int      list_index,
1388                                 string_length;
1389         char       *name;
1390
1391         /* If this is the first time for this completion, init some values */
1392         if (state == 0)
1393         {
1394                 list_index = 0;
1395                 string_length = strlen(text);
1396         }
1397
1398         /* find something that matches */
1399         while ((name = words_after_create[list_index++].name))
1400                 if (strncasecmp(name, text, string_length) == 0)
1401                         return xstrdup(name);
1402
1403         /* if nothing matches, return NULL */
1404         return NULL;
1405 }
1406
1407
1408 /* The following two functions are wrappers for _complete_from_query */
1409
1410 static char *
1411 complete_from_query(const char *text, int state)
1412 {
1413         return _complete_from_query(0, text, state);
1414 }
1415
1416 static char *
1417 complete_from_schema_query(const char *text, int state)
1418 {
1419         return _complete_from_query(1, text, state);
1420 }
1421
1422
1423 /* This creates a list of matching things, according to a query pointed to
1424    by completion_charp.
1425    The query can be one of two kinds:
1426    - A simple query which must contain a %d and a %s, which will be replaced
1427    by the string length of the text and the text itself. The query may also
1428    have another %s in it, which will be replaced by the value of
1429    completion_info_charp.
1430          or:
1431    - A schema query used for completion of both schema and relation names;
1432    these are more complex and must contain in the following order:
1433          %d %s %d %s %d %s %s %d %s
1434    where %d is the string length of the text and %s the text itself.
1435
1436    It is assumed that strings should be escaped to become SQL literals
1437    (that is, what is in the query is actually ... '%s' ...)
1438
1439    See top of file for examples of both kinds of query.
1440 */
1441
1442 static char *
1443 _complete_from_query(int is_schema_query, const char *text, int state)
1444 {
1445         static int      list_index,
1446                                 string_length;
1447         static PGresult *result = NULL;
1448
1449         /*
1450          * If this is the first time for this completion, we fetch a list of
1451          * our "things" from the backend.
1452          */
1453         if (state == 0)
1454         {
1455                 char            query_buffer[BUF_SIZE];
1456                 char       *e_text;
1457                 char       *e_info_charp;
1458
1459                 list_index = 0;
1460                 string_length = strlen(text);
1461
1462                 /* Free any prior result */
1463                 PQclear(result);
1464                 result = NULL;
1465
1466                 /* Need to have a query */
1467                 if (completion_charp == NULL)
1468                         return NULL;
1469
1470                 /* Set up suitably-escaped copies of textual inputs */
1471                 if (text)
1472                 {
1473                         e_text = (char *) malloc(strlen(text) * 2 + 1);
1474                         if (!e_text)
1475                                 return NULL;
1476                         PQescapeString(e_text, text, strlen(text));
1477                 }
1478                 else
1479                         e_text = NULL;
1480
1481                 if (completion_info_charp)
1482                 {
1483                         e_info_charp = (char *)
1484                                 malloc(strlen(completion_info_charp) * 2 + 1);
1485                         if (!e_info_charp)
1486                         {
1487                                 if (e_text)
1488                                         free(e_text);
1489                                 return NULL;
1490                         }
1491                         PQescapeString(e_info_charp, completion_info_charp,
1492                                                    strlen(completion_info_charp));
1493                 }
1494                 else
1495                         e_info_charp = NULL;
1496
1497                 if (is_schema_query)
1498                 {
1499                         if (snprintf(query_buffer, BUF_SIZE, completion_charp,
1500                                                  string_length, e_text,
1501                                                  string_length, e_text,
1502                                                  string_length, e_text,
1503                                                  e_text,
1504                                                  string_length, e_text,
1505                                                  string_length, e_text) == -1)
1506                                 ERROR_QUERY_TOO_LONG;
1507                         else
1508                                 result = exec_query(query_buffer);
1509                 }
1510                 else
1511                 {
1512                         if (snprintf(query_buffer, BUF_SIZE, completion_charp,
1513                                                  string_length, e_text, e_info_charp) == -1)
1514                                 ERROR_QUERY_TOO_LONG;
1515                         else
1516                                 result = exec_query(query_buffer);
1517                 }
1518
1519                 if (e_text)
1520                         free(e_text);
1521                 if (e_info_charp)
1522                         free(e_info_charp);
1523         }
1524
1525         /* Find something that matches */
1526         if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
1527         {
1528                 const char *item;
1529
1530                 while (list_index < PQntuples(result) &&
1531                            (item = PQgetvalue(result, list_index++, 0)))
1532                         if (strncasecmp(text, item, string_length) == 0)
1533                                 return xstrdup(item);
1534         }
1535
1536         /* If nothing matches, free the db structure and return null */
1537         PQclear(result);
1538         result = NULL;
1539         return NULL;
1540 }
1541
1542
1543 /* This function returns in order one of a fixed, NULL pointer terminated list
1544    of strings (if matching). This can be used if there are only a fixed number
1545    SQL words that can appear at certain spot.
1546 */
1547 static char *
1548 complete_from_list(const char *text, int state)
1549 {
1550         static int      string_length,
1551                                 list_index,
1552                                 matches;
1553         static bool casesensitive;
1554         char       *item;
1555
1556         /* need to have a list */
1557 #ifdef USE_ASSERT_CHECKING
1558         assert(completion_charpp);
1559 #endif
1560
1561         /* Initialization */
1562         if (state == 0)
1563         {
1564                 list_index = 0;
1565                 string_length = strlen(text);
1566                 casesensitive = true;
1567                 matches = 0;
1568         }
1569
1570         while ((item = completion_charpp[list_index++]))
1571         {
1572                 /* First pass is case sensitive */
1573                 if (casesensitive && strncmp(text, item, string_length) == 0)
1574                 {
1575                         matches++;
1576                         return xstrdup(item);
1577                 }
1578
1579                 /* Second pass is case insensitive, don't bother counting matches */
1580                 if (!casesensitive && strncasecmp(text, item, string_length) == 0)
1581                         return xstrdup(item);
1582         }
1583
1584         /*
1585          * No matches found. If we're not case insensitive already, lets
1586          * switch to being case insensitive and try again
1587          */
1588         if (casesensitive && matches == 0)
1589         {
1590                 casesensitive = false;
1591                 list_index = 0;
1592                 state++;
1593                 return (complete_from_list(text, state));
1594         }
1595
1596         /* If no more matches, return null. */
1597         return NULL;
1598 }
1599
1600
1601 /* This function returns one fixed string the first time even if it doesn't
1602    match what's there, and nothing the second time. This should be used if there
1603    is only one possibility that can appear at a certain spot, so misspellings
1604    will be overwritten.
1605    The string to be passed must be in completion_charp.
1606 */
1607 static char *
1608 complete_from_const(const char *text, int state)
1609 {
1610         (void) text;                            /* We don't care about what was entered
1611                                                                  * already. */
1612
1613 #ifdef USE_ASSERT_CHECKING
1614         assert(completion_charp);
1615 #endif
1616         if (state == 0)
1617                 return xstrdup(completion_charp);
1618         else
1619                 return NULL;
1620 }
1621
1622
1623
1624 /* HELPER FUNCTIONS */
1625
1626
1627 /* Execute a query and report any errors. This should be the preferred way of
1628    talking to the database in this file.
1629    Note that the query passed in here must not have a semicolon at the end
1630    because we need to append LIMIT xxx.
1631 */
1632 static PGresult *
1633 exec_query(char *query)
1634 {
1635         PGresult   *result;
1636         char            query_buffer[BUF_SIZE];
1637
1638         if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
1639                 return NULL;
1640 #ifdef USE_ASSERT_CHECKING
1641         assert(query[strlen(query) - 1] != ';');
1642 #endif
1643
1644         if (snprintf(query_buffer, BUF_SIZE, "%s LIMIT %d;",
1645                                  query, completion_max_records) == -1)
1646         {
1647                 ERROR_QUERY_TOO_LONG;
1648                 return NULL;
1649         }
1650
1651         result = PQexec(pset.db, query);
1652
1653         if (result != NULL && PQresultStatus(result) != PGRES_TUPLES_OK)
1654         {
1655 #if 0
1656                 psql_error("tab completion: %s failed - %s\n",
1657                                    query, PQresStatus(PQresultStatus(result)));
1658 #endif
1659                 PQclear(result);
1660                 result = NULL;
1661         }
1662
1663         return result;
1664 }
1665
1666
1667
1668 /* Return the word (space delimited) before point. Set skip > 0 to skip that
1669    many words; e.g. skip=1 finds the word before the previous one.
1670 */
1671 static char *
1672 previous_word(int point, int skip)
1673 {
1674         int                     i,
1675                                 start = 0,
1676                                 end = -1,
1677                                 inquotes = 0;
1678         char       *s;
1679
1680         while (skip-- >= 0)
1681         {
1682                 /* first we look for a space before the current word */
1683                 for (i = point; i >= 0; i--)
1684                         if (rl_line_buffer[i] == ' ')
1685                                 break;
1686
1687                 /* now find the first non-space which then constitutes the end */
1688                 for (; i >= 0; i--)
1689                         if (rl_line_buffer[i] != ' ')
1690                         {
1691                                 end = i;
1692                                 break;
1693                         }
1694
1695                 /*
1696                  * If no end found we return null, because there is no word before
1697                  * the point
1698                  */
1699                 if (end == -1)
1700                         return NULL;
1701
1702                 /*
1703                  * Otherwise we now look for the start. The start is either the
1704                  * last character before any space going backwards from the end,
1705                  * or it's simply character 0
1706                  */
1707                 for (start = end; start > 0; start--)
1708                 {
1709                         if (rl_line_buffer[start] == '"')
1710                                 inquotes = !inquotes;
1711                         if ((rl_line_buffer[start - 1] == ' ') && inquotes == 0)
1712                                 break;
1713                 }
1714
1715                 point = start;
1716         }
1717
1718         /* make a copy */
1719         s = (char *) malloc(end - start + 2);
1720         if (!s)
1721         {
1722                 psql_error("out of memory\n");
1723                 if (!pset.cur_cmd_interactive)
1724                         exit(EXIT_FAILURE);
1725                 else
1726                         return NULL;
1727         }
1728
1729         strncpy(s, &rl_line_buffer[start], end - start + 1);
1730         s[end - start + 1] = '\0';
1731
1732         return s;
1733 }
1734
1735
1736
1737 #if 0
1738
1739 /*
1740  * Surround a string with single quotes. This works for both SQL and
1741  * psql internal. Currently disable because it is reported not to
1742  * cooperate with certain versions of readline.
1743  */
1744 static char *
1745 quote_file_name(char *text, int match_type, char *quote_pointer)
1746 {
1747         char       *s;
1748         size_t          length;
1749
1750         (void) quote_pointer;           /* not used */
1751
1752         length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
1753         s = malloc(length);
1754         s[0] = '\'';
1755         strcpy(s + 1, text);
1756         if (match_type == SINGLE_MATCH)
1757                 s[length - 2] = '\'';
1758         s[length - 1] = '\0';
1759         return s;
1760 }
1761
1762
1763
1764 static char *
1765 dequote_file_name(char *text, char quote_char)
1766 {
1767         char       *s;
1768         size_t          length;
1769
1770         if (!quote_char)
1771                 return xstrdup(text);
1772
1773         length = strlen(text);
1774         s = malloc(length - 2 + 1);
1775         strncpy(s, text +1, length - 2);
1776         s[length] = '\0';
1777
1778         return s;
1779 }
1780 #endif   /* 0 */
1781
1782 #endif   /* USE_READLINE */