commit 7749d7d3fabf468dbe2c5f397add9f8e31f59614
Author: Pavel Stehule <pavel.stehule@gooddata.com>
Date:   Wed Jul 8 14:24:55 2015 +0200

    initial

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 0683548..c4e56c8 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -742,6 +742,14 @@ static const SchemaQuery Query_for_list_of_matviews = {
 "   FROM pg_catalog.pg_tablesample_method "\
 "  WHERE substring(pg_catalog.quote_ident(tsmname),1,%d)='%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.
@@ -832,6 +840,8 @@ static PGresult *exec_query(const char *query);
 
 static void get_previous_words(int point, char **previous_words, int nwords);
 
+static char *get_vartype(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);
@@ -3548,20 +3558,6 @@ psql_completion(const char *text, int start, int end)
 
 			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
@@ -3571,10 +3567,31 @@ psql_completion(const char *text, int start, int end)
 		}
 		else
 		{
-			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);
+			}
+			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);
+			}
 		}
 	}
 
@@ -4636,6 +4653,42 @@ get_previous_words(int point, char **previous_words, int nwords)
 	}
 }
 
+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);
+
+	appendPQExpBuffer(&query_buffer,
+		"SELECT vartype FROM 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;
+}
+
 #ifdef NOT_USED
 
 /*
