diff -ur cvs/pgsql/src/bin/psql/tab-complete.c cvs.build/pgsql/src/bin/psql/tab-complete.c --- cvs/pgsql/src/bin/psql/tab-complete.c 2005-12-23 16:58:19.000000000 +0100 +++ cvs.build/pgsql/src/bin/psql/tab-complete.c 2006-01-08 13:06:15.000000000 +0100 @@ -137,6 +137,7 @@ 3) The items from a null-pointer-terminated list. 4) A string constant 5) The list of attributes to the given table. + 6) A list that can contain several of the above (malloc'ed list). */ #define COMPLETE_WITH_QUERY(query) \ do { completion_charp = query; matches = completion_matches(text, complete_from_query); } while(0) @@ -150,6 +151,21 @@ do {completion_charp = Query_for_list_of_attributes; completion_info_charp = table; matches = completion_matches(text, complete_from_query); } while(0) /* + * Keep the "malloced" keyword in all the names such that we remember that + * memory got allocated here. COMPLETE_WITH_MALLOCED_LIST frees this memory. + */ +#define COMPLETE_WITH_MALLOCED_LIST(list) \ + do { COMPLETE_WITH_LIST((const char **) list); free(list); list = NULL; } while(0) +#define MALLOCED_LIST_ADD_ITEM(list, item) \ + ((list) = list_add_item((list), (item))) +#define GET_MALLOCED_LIST_WITH_ATTR(table) \ + (get_query_list(text, Query_for_list_of_attributes, (table))) +#define GET_MALLOCED_LIST_WITH_QUERY(query) \ + (get_query_list(text, (query), NULL)) +#define GET_MALLOCED_LIST_WITH_SCHEMA_QUERY(query,addon) \ + (get_schema_query_list(text, &(query), addon)) + +/* * Assembly instructions for schema queries */ @@ -463,6 +479,16 @@ /* Forward declaration of functions */ +static char **get_empty_list(void); +static char **get_query_list(const char *text, const char *query, + const char *completion_info); +static char **get_schema_query_list(const char *text, const SchemaQuery* squery, + const char *completion_info); +static char **_get_query_list(int is_schema_query, + const char *text, const char *query, + const char *completion_info); +static char **list_add_item(char **list, char *item); + static char **psql_completion(char *text, int start, int end); static char *create_command_generator(const char *text, int state); static char *complete_from_query(const char *text, int state); @@ -754,7 +780,17 @@ else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && (pg_strcasecmp(prev_wd, "ALTER") == 0 || pg_strcasecmp(prev_wd, "RENAME") == 0)) - COMPLETE_WITH_ATTR(prev2_wd); + { + char **list = GET_MALLOCED_LIST_WITH_ATTR(prev2_wd); + MALLOCED_LIST_ADD_ITEM(list, "COLUMN"); + COMPLETE_WITH_MALLOCED_LIST(list); + } + /* If we have TABLE ALTER COLUMN|RENAME COLUMN, provide list of columns */ + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "COLUMN") == 0 && + (pg_strcasecmp(prev2_wd, "ALTER") == 0 || + pg_strcasecmp(prev2_wd, "RENAME") == 0)) + COMPLETE_WITH_ATTR(prev3_wd); /* ALTER TABLE xxx RENAME yyy */ else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && @@ -762,6 +798,13 @@ pg_strcasecmp(prev_wd, "TO") != 0) COMPLETE_WITH_CONST("TO"); + /* ALTER TABLE xxx RENAME COLUMN yyy */ + else if (pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "RENAME") == 0 && + pg_strcasecmp(prev2_wd, "COLUMN") == 0 && + pg_strcasecmp(prev_wd, "TO") != 0) + COMPLETE_WITH_CONST("TO"); + /* If we have TABLE DROP, provide COLUMN or CONSTRAINT */ else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && pg_strcasecmp(prev_wd, "DROP") == 0) @@ -1454,8 +1497,14 @@ else if (pg_strcasecmp(prev_wd, "LOCK") == 0 || (pg_strcasecmp(prev_wd, "TABLE") == 0 && pg_strcasecmp(prev2_wd, "LOCK") == 0)) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); - + { + char **list = GET_MALLOCED_LIST_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + /* if we have only seen LOCK but not LOCK TABLE so far, offer + * the TABLE keyword as well */ + if (pg_strcasecmp(prev_wd, "LOCK") == 0) + MALLOCED_LIST_ADD_ITEM(list, "TABLE"); + COMPLETE_WITH_MALLOCED_LIST(list); + } /* For the following, handle the case of a single table only for now */ /* Complete LOCK [TABLE] with "IN" */ @@ -1638,7 +1687,11 @@ else if (pg_strcasecmp(prev3_wd, "SET") == 0 && pg_strcasecmp(prev2_wd, "SESSION") == 0 && pg_strcasecmp(prev_wd, "AUTHORIZATION") == 0) - COMPLETE_WITH_QUERY(Query_for_list_of_roles); + { + char **list = GET_MALLOCED_LIST_WITH_QUERY(Query_for_list_of_roles); + MALLOCED_LIST_ADD_ITEM(list, "DEFAULT"); + COMPLETE_WITH_MALLOCED_LIST(list); + } /* Complete RESET SESSION with AUTHORIZATION */ else if (pg_strcasecmp(prev2_wd, "RESET") == 0 && pg_strcasecmp(prev_wd, "SESSION") == 0) @@ -2315,6 +2368,71 @@ } +/* LIST HELPER FUNCTIONS */ + +static char ** +get_empty_list(void) +{ + char **list = (char **) malloc(sizeof(char *)); + list[0] = NULL; + return list; +} + +/* the following two functions are wrappers for _get_query_list */ +static char ** +get_schema_query_list(const char *text, + const SchemaQuery *squery, + const char *addon) +{ + completion_squery = squery; + return _get_query_list(1, text, addon, NULL); +} + +static char ** +get_query_list(const char *text, + const char *query, + const char *completion_info) +{ + return _get_query_list(0, text, query, completion_info); +} + +static char ** +_get_query_list(int is_schema_query, + const char *text, + const char *query, + const char *completion_info) +{ + char **list = get_empty_list(); + char *entry; + int state = 0; + + completion_charp = query; + completion_info_charp = completion_info; + + do { + if (is_schema_query) + entry = complete_from_schema_query(text, state++); + else + entry = complete_from_query(text, state++); + list = list_add_item(list, entry); + } while (entry); + + return list; +} + +static char ** +list_add_item(char **list, char *item) +{ + int size = 0; + while (list[size]) + size++; + list = realloc(list, sizeof(char *) * (size + 1 + 1)); + list[size] = item; + list[size+1] = NULL; + return list; +} + + #if 0 /*