@@ -2933,11 +2933,72 @@ get_select_query_def(Query *query, deparse_context *context,
2933
2933
context -> windowTList = save_windowtlist ;
2934
2934
}
2935
2935
2936
+ /*
2937
+ * Detect whether query looks like SELECT ... FROM VALUES();
2938
+ * if so, return the VALUES RTE. Otherwise return NULL.
2939
+ */
2940
+ static RangeTblEntry *
2941
+ get_simple_values_rte (Query * query )
2942
+ {
2943
+ RangeTblEntry * result = NULL ;
2944
+ ListCell * lc ;
2945
+
2946
+ /*
2947
+ * We want to return TRUE even if the Query also contains OLD or NEW rule
2948
+ * RTEs. So the idea is to scan the rtable and see if there is only one
2949
+ * inFromCl RTE that is a VALUES RTE.
2950
+ */
2951
+ foreach (lc , query -> rtable )
2952
+ {
2953
+ RangeTblEntry * rte = (RangeTblEntry * ) lfirst (lc );
2954
+
2955
+ if (rte -> rtekind == RTE_VALUES && rte -> inFromCl )
2956
+ {
2957
+ if (result )
2958
+ return NULL ; /* multiple VALUES (probably not possible) */
2959
+ result = rte ;
2960
+ }
2961
+ else if (rte -> rtekind == RTE_RELATION && !rte -> inFromCl )
2962
+ continue ; /* ignore rule entries */
2963
+ else
2964
+ return NULL ; /* something else -> not simple VALUES */
2965
+ }
2966
+
2967
+ /*
2968
+ * We don't need to check the targetlist in any great detail, because
2969
+ * parser/analyze.c will never generate a "bare" VALUES RTE --- they only
2970
+ * appear inside auto-generated sub-queries with very restricted
2971
+ * structure. However, DefineView might have modified the tlist by
2972
+ * injecting new column aliases; so compare tlist resnames against the
2973
+ * RTE's names to detect that.
2974
+ */
2975
+ if (result )
2976
+ {
2977
+ ListCell * lcn ;
2978
+
2979
+ if (list_length (query -> targetList ) != list_length (result -> eref -> colnames ))
2980
+ return NULL ; /* this probably cannot happen */
2981
+ forboth (lc , query -> targetList , lcn , result -> eref -> colnames )
2982
+ {
2983
+ TargetEntry * tle = (TargetEntry * ) lfirst (lc );
2984
+ char * cname = strVal (lfirst (lcn ));
2985
+
2986
+ if (tle -> resjunk )
2987
+ return NULL ; /* this probably cannot happen */
2988
+ if (tle -> resname == NULL || strcmp (tle -> resname , cname ) != 0 )
2989
+ return NULL ; /* column name has been changed */
2990
+ }
2991
+ }
2992
+
2993
+ return result ;
2994
+ }
2995
+
2936
2996
static void
2937
2997
get_basic_select_query (Query * query , deparse_context * context ,
2938
2998
TupleDesc resultDesc )
2939
2999
{
2940
3000
StringInfo buf = context -> buf ;
3001
+ RangeTblEntry * values_rte ;
2941
3002
char * sep ;
2942
3003
ListCell * l ;
2943
3004
@@ -2950,23 +3011,13 @@ get_basic_select_query(Query *query, deparse_context *context,
2950
3011
/*
2951
3012
* If the query looks like SELECT * FROM (VALUES ...), then print just the
2952
3013
* VALUES part. This reverses what transformValuesClause() did at parse
2953
- * time. If the jointree contains just a single VALUES RTE, we assume
2954
- * this case applies (without looking at the targetlist...)
3014
+ * time.
2955
3015
*/
2956
- if (list_length (query -> jointree -> fromlist ) == 1 )
3016
+ values_rte = get_simple_values_rte (query );
3017
+ if (values_rte )
2957
3018
{
2958
- RangeTblRef * rtr = (RangeTblRef * ) linitial (query -> jointree -> fromlist );
2959
-
2960
- if (IsA (rtr , RangeTblRef ))
2961
- {
2962
- RangeTblEntry * rte = rt_fetch (rtr -> rtindex , query -> rtable );
2963
-
2964
- if (rte -> rtekind == RTE_VALUES )
2965
- {
2966
- get_values_def (rte -> values_lists , context );
2967
- return ;
2968
- }
2969
- }
3019
+ get_values_def (values_rte -> values_lists , context );
3020
+ return ;
2970
3021
}
2971
3022
2972
3023
/*
@@ -6681,7 +6732,9 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
6681
6732
break ;
6682
6733
case RTE_VALUES :
6683
6734
/* Values list RTE */
6735
+ appendStringInfoChar (buf , '(' );
6684
6736
get_values_def (rte -> values_lists , context );
6737
+ appendStringInfoChar (buf , ')' );
6685
6738
break ;
6686
6739
case RTE_CTE :
6687
6740
appendStringInfoString (buf , quote_identifier (rte -> ctename ));
@@ -6721,6 +6774,13 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
6721
6774
quote_identifier (rte -> eref -> aliasname ));
6722
6775
gavealias = true;
6723
6776
}
6777
+ else if (rte -> rtekind == RTE_VALUES )
6778
+ {
6779
+ /* Alias is syntactically required for VALUES */
6780
+ appendStringInfo (buf , " %s" ,
6781
+ quote_identifier (rte -> eref -> aliasname ));
6782
+ gavealias = true;
6783
+ }
6724
6784
6725
6785
if (rte -> rtekind == RTE_FUNCTION )
6726
6786
{
0 commit comments