@@ -142,6 +142,7 @@ static bool completion_case_sensitive;/* completion is case sensitive */
142142 * 3) The items from a null-pointer-terminated list.
143143 * 4) A string constant.
144144 * 5) The list of attributes of the given table (possibly schema-qualified).
145+ * 6/ The list of arguments to the given function (possibly schema-qualified).
145146 */
146147#define COMPLETE_WITH_QUERY (query ) \
147148do { \
@@ -202,6 +203,31 @@ do { \
202203matches = completion_matches(text, complete_from_query); \
203204} while (0)
204205
206+ #define COMPLETE_WITH_FUNCTION_ARG (function ) \
207+ do { \
208+ char *_completion_schema; \
209+ char *_completion_function; \
210+ \
211+ _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
212+ false, false, pset.encoding); \
213+ (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
214+ false, false, pset.encoding); \
215+ _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
216+ false, false, pset.encoding); \
217+ if (_completion_function == NULL) \
218+ { \
219+ completion_charp = Query_for_list_of_arguments; \
220+ completion_info_charp = function; \
221+ } \
222+ else \
223+ { \
224+ completion_charp = Query_for_list_of_arguments_with_schema; \
225+ completion_info_charp = _completion_function; \
226+ completion_info_charp2 = _completion_schema; \
227+ } \
228+ matches = completion_matches(text, complete_from_query); \
229+ } while (0)
230+
205231/*
206232 * Assembly instructions for schema queries
207233 */
@@ -598,10 +624,25 @@ static const SchemaQuery Query_for_list_of_views = {
598624" FROM pg_catalog.pg_am "\
599625" WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
600626
627+ /* the silly-looking length condition is just to eat up the current word */
601628#define Query_for_list_of_arguments \
602- " SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
603- " FROM pg_catalog.pg_proc "\
604- " WHERE proname='%s'"
629+ "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
630+ " FROM pg_catalog.pg_proc "\
631+ " WHERE (%d = pg_catalog.length('%s'))"\
632+ " AND (pg_catalog.quote_ident(proname)='%s'"\
633+ " OR '\"' || proname || '\"'='%s') "\
634+ " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
635+
636+ /* the silly-looking length condition is just to eat up the current word */
637+ #define Query_for_list_of_arguments_with_schema \
638+ "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
639+ " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
640+ " WHERE (%d = pg_catalog.length('%s'))"\
641+ " AND n.oid = p.pronamespace "\
642+ " AND (pg_catalog.quote_ident(proname)='%s' "\
643+ " OR '\"' || proname || '\"' ='%s') "\
644+ " AND (pg_catalog.quote_ident(nspname)='%s' "\
645+ " OR '\"' || nspname || '\"' ='%s') "
605646
606647#define Query_for_list_of_extensions \
607648" SELECT pg_catalog.quote_ident(extname) "\
@@ -863,13 +904,7 @@ psql_completion(char *text, int start, int end)
863904COMPLETE_WITH_LIST (list_ALTERAGG );
864905}
865906else
866- {
867- char * tmp_buf = malloc (strlen (Query_for_list_of_arguments )+ strlen (prev2_wd ));
868-
869- sprintf (tmp_buf ,Query_for_list_of_arguments ,prev2_wd );
870- COMPLETE_WITH_QUERY (tmp_buf );
871- free (tmp_buf );
872- }
907+ COMPLETE_WITH_FUNCTION_ARG (prev2_wd );
873908}
874909
875910/* ALTER SCHEMA <name> */
@@ -2186,13 +2221,7 @@ psql_completion(char *text, int start, int end)
21862221 (pg_strcasecmp (prev3_wd ,"AGGREGATE" )== 0 ||
21872222pg_strcasecmp (prev3_wd ,"FUNCTION" )== 0 )&&
21882223pg_strcasecmp (prev_wd ,"(" )== 0 )
2189- {
2190- char * tmp_buf = malloc (strlen (Query_for_list_of_arguments )+ strlen (prev2_wd ));
2191-
2192- sprintf (tmp_buf ,Query_for_list_of_arguments ,prev2_wd );
2193- COMPLETE_WITH_QUERY (tmp_buf );
2194- free (tmp_buf );
2195- }
2224+ COMPLETE_WITH_FUNCTION_ARG (prev2_wd );
21962225/* DROP OWNED BY */
21972226else if (pg_strcasecmp (prev2_wd ,"DROP" )== 0 &&
21982227pg_strcasecmp (prev_wd ,"OWNED" )== 0 )