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

Reply via email to