diff -cr 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-06 19:38:26.000000000 +0100 *************** *** 137,142 **** --- 137,143 ---- 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,155 **** --- 151,171 ---- 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 = (char**) 0; } 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,468 **** --- 479,494 ---- /* Forward declaration of functions */ + static char **get_empty_list(); + static char **_get_query_list(int is_schema_query, + const char *text, const char *query, + const char *completion_info); + 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 **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,760 **** 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); /* ALTER TABLE xxx RENAME yyy */ else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && --- 780,796 ---- else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && (pg_strcasecmp(prev_wd, "ALTER") == 0 || pg_strcasecmp(prev_wd, "RENAME") == 0)) ! { ! 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,767 **** --- 798,810 ---- 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,1461 **** 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); ! /* For the following, handle the case of a single table only for now */ /* Complete LOCK [TABLE] with "IN" */ --- 1497,1510 ---- else if (pg_strcasecmp(prev_wd, "LOCK") == 0 || (pg_strcasecmp(prev_wd, "TABLE") == 0 && pg_strcasecmp(prev2_wd, "LOCK") == 0)) ! { ! 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,1644 **** 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); /* Complete RESET SESSION with AUTHORIZATION */ else if (pg_strcasecmp(prev2_wd, "RESET") == 0 && pg_strcasecmp(prev_wd, "SESSION") == 0) --- 1687,1697 ---- else if (pg_strcasecmp(prev3_wd, "SET") == 0 && pg_strcasecmp(prev2_wd, "SESSION") == 0 && pg_strcasecmp(prev_wd, "AUTHORIZATION") == 0) ! { ! 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,2320 **** --- 2368,2437 ---- } + /* LIST HELPER FUNCTIONS */ + + static char** + get_empty_list() { + char** list = 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 /*