Hi 2015-09-02 15:23 GMT+02:00 Andres Freund <and...@anarazel.de>:
> Hi, > > On 2015-07-08 14:50:37 +0200, Pavel Stehule wrote: > > - static const char *const my_list[] = > > - {"DEFAULT", NULL}; > > + /* fallback for GUC settings */ > > > > - COMPLETE_WITH_LIST(my_list); > > + char *vartype = get_vartype(prev2_wd); > > + > > + if (strcmp(vartype, "enum") == 0) > > + { > > + char querybuf[1024]; > > + > > + snprintf(querybuf, 1024, Query_for_enum, > prev2_wd); > > + COMPLETE_WITH_QUERY(querybuf); > > + } > > Won't that mean that enum variables don't complete to default anymore? > no, it does #define Query_for_enum \ " SELECT name FROM ( "\ " SELECT unnest(enumvals) AS name "\ " FROM pg_catalog.pg_settings "\ " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\ " UNION SELECT 'DEFAULT' ) ss "\ **************** " WHERE pg_catalog.substring(name,1,%%d)='%%s'" > > > +static char * > > +get_vartype(const char *varname) > > +{ > > + PQExpBufferData query_buffer; > > + char *e_varname; > > + PGresult *result; > > + int string_length; > > + static char resbuf[10]; > > + > > + initPQExpBuffer(&query_buffer); > > + > > + string_length = strlen(varname); > > + e_varname = pg_malloc(string_length * 2 + 1); > > + PQescapeString(e_varname, varname, string_length); > > Independent of this patch, we really shouldn't do this in several places > :( > fixed > > > + appendPQExpBuffer(&query_buffer, > > + "SELECT vartype FROM pg_settings WHERE > pg_catalog.lower(name) = pg_catalog.lower('%s')", > > + e_varname); > > Missing pg_catalog for pg_settings. > fixed > > Greetings, > > Andres Freund > I am sending new version Regards Pavel
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c new file mode 100644 index 816deda..61216e1 *** a/src/bin/psql/tab-complete.c --- b/src/bin/psql/tab-complete.c *************** static const SchemaQuery Query_for_list_ *** 757,762 **** --- 757,770 ---- " (SELECT polrelid FROM pg_catalog.pg_policy "\ " WHERE pg_catalog.quote_ident(polname)='%s')" + #define Query_for_enum \ + " SELECT name FROM ( "\ + " SELECT unnest(enumvals) AS name "\ + " FROM pg_catalog.pg_settings "\ + " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\ + " UNION SELECT 'DEFAULT' ) ss "\ + " WHERE pg_catalog.substring(name,1,%%d)='%%s'" + /* * This is a list of all "things" in Pgsql, which can show up after CREATE or * DROP; and there is also a query to get a list of them. *************** static PGresult *exec_query(const char * *** 847,852 **** --- 855,863 ---- static void get_previous_words(int point, char **previous_words, int nwords); + static char *get_vartype(const char *varname); + static char *escape_string(const char *text); + #ifdef NOT_USED static char *quote_file_name(char *text, int match_type, char *quote_pointer); static char *dequote_file_name(char *text, char quote_char); *************** psql_completion(const char *text, int st *** 3604,3623 **** COMPLETE_WITH_LIST(my_list); } - else if (pg_strcasecmp(prev2_wd, "IntervalStyle") == 0) - { - static const char *const my_list[] = - {"postgres", "postgres_verbose", "sql_standard", "iso_8601", NULL}; - - COMPLETE_WITH_LIST(my_list); - } - else if (pg_strcasecmp(prev2_wd, "GEQO") == 0) - { - static const char *const my_list[] = - {"ON", "OFF", "DEFAULT", NULL}; - - COMPLETE_WITH_LIST(my_list); - } else if (pg_strcasecmp(prev2_wd, "search_path") == 0) { COMPLETE_WITH_QUERY(Query_for_list_of_schemas --- 3615,3620 ---- *************** psql_completion(const char *text, int st *** 3627,3636 **** } else { ! static const char *const my_list[] = ! {"DEFAULT", NULL}; ! COMPLETE_WITH_LIST(my_list); } } --- 3624,3654 ---- } else { ! /* fallback for GUC settings */ ! char *vartype = get_vartype(prev2_wd); ! ! if (strcmp(vartype, "enum") == 0) ! { ! char querybuf[1024]; ! ! snprintf(querybuf, 1024, Query_for_enum, prev2_wd); ! COMPLETE_WITH_QUERY(querybuf); ! } ! else if (strcmp(vartype, "bool") == 0) ! { ! static const char *const my_list[] = ! {"ON", "OFF", "DEFAULT", NULL}; ! ! COMPLETE_WITH_LIST(my_list); ! } ! else ! { ! static const char *const my_list[] = ! {"DEFAULT", NULL}; ! ! COMPLETE_WITH_LIST(my_list); ! } } } *************** _complete_from_query(int is_schema_query *** 4166,4195 **** result = NULL; /* Set up suitably-escaped copies of textual inputs */ ! e_text = pg_malloc(string_length * 2 + 1); ! PQescapeString(e_text, text, string_length); if (completion_info_charp) ! { ! size_t charp_len; ! ! charp_len = strlen(completion_info_charp); ! e_info_charp = pg_malloc(charp_len * 2 + 1); ! PQescapeString(e_info_charp, completion_info_charp, ! charp_len); ! } else e_info_charp = NULL; if (completion_info_charp2) ! { ! size_t charp_len; ! ! charp_len = strlen(completion_info_charp2); ! e_info_charp2 = pg_malloc(charp_len * 2 + 1); ! PQescapeString(e_info_charp2, completion_info_charp2, ! charp_len); ! } else e_info_charp2 = NULL; --- 4184,4198 ---- result = NULL; /* Set up suitably-escaped copies of textual inputs */ ! e_text = escape_string(text); if (completion_info_charp) ! e_info_charp = escape_string(completion_info_charp); else e_info_charp = NULL; if (completion_info_charp2) ! e_info_charp2 = escape_string(completion_info_charp2); else e_info_charp2 = NULL; *************** get_previous_words(int point, char **pre *** 4692,4697 **** --- 4695,4758 ---- } } + /* + * Returns name of type of any configuration variable. + * + * Note: There are few differences between type system used by pg_settings + * and internal type system. Isn't possible to return OID based type, but + * text name is good enough for our purpouse. + */ + static char * + get_vartype(const char *varname) + { + PQExpBufferData query_buffer; + char *e_varname; + PGresult *result; + static char resbuf[10]; + + initPQExpBuffer(&query_buffer); + + e_varname = escape_string(varname); + + appendPQExpBuffer(&query_buffer, + "SELECT vartype FROM pg_catalog.pg_settings " + "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')", + e_varname); + + result = exec_query(query_buffer.data); + termPQExpBuffer(&query_buffer); + free(e_varname); + + resbuf[0] = '\0'; + + if (PQresultStatus(result) == PGRES_TUPLES_OK) + { + if (PQntuples(result) > 0) + strncpy(resbuf, PQgetvalue(result, 0, 0), 10); + } + + PQclear(result); + + return resbuf; + } + + /* + * escape_string - ensure correct sanitization of entered string + */ + static char * + escape_string(const char *text) + { + size_t text_length; + char *result; + + text_length = strlen(text); + + result = pg_malloc(text_length * 2 + 1); + PQescapeStringConn(pset.db, result, text, text_length, NULL); + + return result; + } + #ifdef NOT_USED /* *************** dequote_file_name(char *text, char quote *** 4732,4737 **** --- 4793,4800 ---- return s; } + + #endif /* NOT_USED */ #endif /* USE_READLINE */
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers