Hi
2015-09-02 15:23 GMT+02:00 Andres Freund <[email protected]>:
> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers