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