@@ -759,6 +759,15 @@ static const SchemaQuery Query_for_list_of_matviews = {
759759" (SELECT polrelid FROM pg_catalog.pg_policy "\
760760" WHERE pg_catalog.quote_ident(polname)='%s')"
761761
762+ #define Query_for_enum \
763+ " SELECT name FROM ( "\
764+ " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
765+ " FROM pg_catalog.pg_settings "\
766+ " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
767+ " UNION ALL " \
768+ " SELECT 'DEFAULT' ) ss "\
769+ " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
770+
762771/*
763772 * This is a list of all "things" in Pgsql, which can show up after CREATE or
764773 * DROP; and there is also a query to get a list of them.
@@ -845,10 +854,13 @@ static char **complete_from_variables(const char *text,
845854static char * complete_from_files (const char * text , int state );
846855
847856static char * pg_strdup_keyword_case (const char * s , const char * ref );
857+ static char * escape_string (const char * text );
848858static PGresult * exec_query (const char * query );
849859
850860static void get_previous_words (int point , char * * previous_words , int nwords );
851861
862+ static char * get_guctype (const char * varname );
863+
852864#ifdef NOT_USED
853865static char * quote_file_name (char * text , int match_type , char * quote_pointer );
854866static char * dequote_file_name (char * text , char quote_char );
@@ -3684,6 +3696,7 @@ psql_completion(const char *text, int start, int end)
36843696 else if (pg_strcasecmp (prev3_wd , "SET" ) == 0 &&
36853697 (pg_strcasecmp (prev_wd , "TO" ) == 0 || strcmp (prev_wd , "=" ) == 0 ))
36863698 {
3699+ /* special cased code for individual GUCs */
36873700 if (pg_strcasecmp (prev2_wd , "DateStyle" ) == 0 )
36883701 {
36893702 static const char * const my_list [] =
@@ -3694,20 +3707,6 @@ psql_completion(const char *text, int start, int end)
36943707
36953708 COMPLETE_WITH_LIST (my_list );
36963709 }
3697- else if (pg_strcasecmp (prev2_wd , "IntervalStyle" ) == 0 )
3698- {
3699- static const char * const my_list [] =
3700- {"postgres" , "postgres_verbose" , "sql_standard" , "iso_8601" , NULL };
3701-
3702- COMPLETE_WITH_LIST (my_list );
3703- }
3704- else if (pg_strcasecmp (prev2_wd , "GEQO" ) == 0 )
3705- {
3706- static const char * const my_list [] =
3707- {"ON" , "OFF" , "DEFAULT" , NULL };
3708-
3709- COMPLETE_WITH_LIST (my_list );
3710- }
37113710 else if (pg_strcasecmp (prev2_wd , "search_path" ) == 0 )
37123711 {
37133712 COMPLETE_WITH_QUERY (Query_for_list_of_schemas
@@ -3717,10 +3716,34 @@ psql_completion(const char *text, int start, int end)
37173716 }
37183717 else
37193718 {
3720- static const char * const my_list [] =
3721- {"DEFAULT" , NULL };
3719+ /* generic, type based, GUC support */
37223720
3723- COMPLETE_WITH_LIST (my_list );
3721+ char * guctype = get_guctype (prev2_wd );
3722+
3723+ if (guctype && strcmp (guctype , "enum" ) == 0 )
3724+ {
3725+ char querybuf [1024 ];
3726+
3727+ snprintf (querybuf , 1024 , Query_for_enum , prev2_wd );
3728+ COMPLETE_WITH_QUERY (querybuf );
3729+ }
3730+ else if (guctype && strcmp (guctype , "bool" ) == 0 )
3731+ {
3732+ static const char * const my_list [] =
3733+ {"on" , "off" , "true" , "false" , "yes" , "no" , "1" , "0" , "DEFAULT" , NULL };
3734+
3735+ COMPLETE_WITH_LIST (my_list );
3736+ }
3737+ else
3738+ {
3739+ static const char * const my_list [] =
3740+ {"DEFAULT" , NULL };
3741+
3742+ COMPLETE_WITH_LIST (my_list );
3743+ }
3744+
3745+ if (guctype )
3746+ free (guctype );
37243747 }
37253748 }
37263749
@@ -4263,30 +4286,15 @@ _complete_from_query(int is_schema_query, const char *text, int state)
42634286 result = NULL ;
42644287
42654288 /* Set up suitably-escaped copies of textual inputs */
4266- e_text = pg_malloc (string_length * 2 + 1 );
4267- PQescapeString (e_text , text , string_length );
4289+ e_text = escape_string (text );
42684290
42694291 if (completion_info_charp )
4270- {
4271- size_t charp_len ;
4272-
4273- charp_len = strlen (completion_info_charp );
4274- e_info_charp = pg_malloc (charp_len * 2 + 1 );
4275- PQescapeString (e_info_charp , completion_info_charp ,
4276- charp_len );
4277- }
4292+ e_info_charp = escape_string (completion_info_charp );
42784293 else
42794294 e_info_charp = NULL ;
42804295
42814296 if (completion_info_charp2 )
4282- {
4283- size_t charp_len ;
4284-
4285- charp_len = strlen (completion_info_charp2 );
4286- e_info_charp2 = pg_malloc (charp_len * 2 + 1 );
4287- PQescapeString (e_info_charp2 , completion_info_charp2 ,
4288- charp_len );
4289- }
4297+ e_info_charp2 = escape_string (completion_info_charp2 );
42904298 else
42914299 e_info_charp2 = NULL ;
42924300
@@ -4677,6 +4685,26 @@ pg_strdup_keyword_case(const char *s, const char *ref)
46774685}
46784686
46794687
4688+ /*
4689+ * escape_string - Escape argument for use as string literal.
4690+ *
4691+ * The returned value has to be freed.
4692+ */
4693+ static char *
4694+ escape_string (const char * text )
4695+ {
4696+ size_t text_length ;
4697+ char * result ;
4698+
4699+ text_length = strlen (text );
4700+
4701+ result = pg_malloc (text_length * 2 + 1 );
4702+ PQescapeStringConn (pset .db , result , text , text_length , NULL );
4703+
4704+ return result ;
4705+ }
4706+
4707+
46804708/*
46814709 * Execute a query and report any errors. This should be the preferred way of
46824710 * talking to the database in this file.
@@ -4790,6 +4818,40 @@ get_previous_words(int point, char **previous_words, int nwords)
47904818 }
47914819}
47924820
4821+ /*
4822+ * Look up the type for the GUC variable with the passed name.
4823+ *
4824+ * Returns NULL if the variable is unknown. Otherwise the returned string,
4825+ * containing the type, has to be freed.
4826+ */
4827+ static char *
4828+ get_guctype (const char * varname )
4829+ {
4830+ PQExpBufferData query_buffer ;
4831+ char * e_varname ;
4832+ PGresult * result ;
4833+ char * guctype = NULL ;
4834+
4835+ e_varname = escape_string (varname );
4836+
4837+ initPQExpBuffer (& query_buffer );
4838+ appendPQExpBuffer (& query_buffer ,
4839+ "SELECT vartype FROM pg_catalog.pg_settings "
4840+ "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')" ,
4841+ e_varname );
4842+
4843+ result = exec_query (query_buffer .data );
4844+ termPQExpBuffer (& query_buffer );
4845+ free (e_varname );
4846+
4847+ if (PQresultStatus (result ) == PGRES_TUPLES_OK && PQntuples (result ) > 0 )
4848+ guctype = pg_strdup (PQgetvalue (result , 0 , 0 ));
4849+
4850+ PQclear (result );
4851+
4852+ return guctype ;
4853+ }
4854+
47934855#ifdef NOT_USED
47944856
47954857/*
0 commit comments