" (SELECT polrelid FROM pg_catalog.pg_policy "\
" WHERE pg_catalog.quote_ident(polname)='%s')"
+#define Query_for_enum \
+" SELECT name FROM ( "\
+" SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
+" FROM pg_catalog.pg_settings "\
+" WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
+" UNION ALL " \
+" 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 char *complete_from_files(const char *text, int state);
static char *pg_strdup_keyword_case(const char *s, const char *ref);
+static char *escape_string(const char *text);
static PGresult *exec_query(const char *query);
static void get_previous_words(int point, char **previous_words, int nwords);
+static char *get_guctype(const char *varname);
+
#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);
else if (pg_strcasecmp(prev3_wd, "SET") == 0 &&
(pg_strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0))
{
+ /* special cased code for individual GUCs */
if (pg_strcasecmp(prev2_wd, "DateStyle") == 0)
{
static const char *const my_list[] =
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
}
else
{
- static const char *const my_list[] =
- {"DEFAULT", NULL};
+ /* generic, type based, GUC support */
- COMPLETE_WITH_LIST(my_list);
+ char *guctype = get_guctype(prev2_wd);
+
+ if (guctype && strcmp(guctype, "enum") == 0)
+ {
+ char querybuf[1024];
+
+ snprintf(querybuf, 1024, Query_for_enum, prev2_wd);
+ COMPLETE_WITH_QUERY(querybuf);
+ }
+ else if (guctype && strcmp(guctype, "bool") == 0)
+ {
+ static const char *const my_list[] =
+ {"on", "off", "true", "false", "yes", "no", "1", "0", "DEFAULT", NULL};
+
+ COMPLETE_WITH_LIST(my_list);
+ }
+ else
+ {
+ static const char *const my_list[] =
+ {"DEFAULT", NULL};
+
+ COMPLETE_WITH_LIST(my_list);
+ }
+
+ if (guctype)
+ free(guctype);
}
}
result = NULL;
/* Set up suitably-escaped copies of textual inputs */
- e_text = pg_malloc(string_length * 2 + 1);
- PQescapeString(e_text, text, string_length);
+ e_text = escape_string(text);
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);
- }
+ e_info_charp = escape_string(completion_info_charp);
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);
- }
+ e_info_charp2 = escape_string(completion_info_charp2);
else
e_info_charp2 = NULL;
}
+/*
+ * escape_string - Escape argument for use as string literal.
+ *
+ * The returned value has to be freed.
+ */
+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;
+}
+
+
/*
* Execute a query and report any errors. This should be the preferred way of
* talking to the database in this file.
}
}
+/*
+ * Look up the type for the GUC variable with the passed name.
+ *
+ * Returns NULL if the variable is unknown. Otherwise the returned string,
+ * containing the type, has to be freed.
+ */
+static char *
+get_guctype(const char *varname)
+{
+ PQExpBufferData query_buffer;
+ char *e_varname;
+ PGresult *result;
+ char *guctype = NULL;
+
+ e_varname = escape_string(varname);
+
+ initPQExpBuffer(&query_buffer);
+ 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);
+
+ if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
+ guctype = pg_strdup(PQgetvalue(result, 0, 0));
+
+ PQclear(result);
+
+ return guctype;
+}
+
#ifdef NOT_USED
/*