@@ -59,6 +59,111 @@ TargetEntry *transform_cypher_item(cypher_parsestate *cpstate, Node *node,
59
59
colname , resjunk );
60
60
}
61
61
62
+ /*
63
+ * expandNSItemAttrs -
64
+ * Workhorse for "*" expansion: produce a list of targetentries
65
+ * for the attributes of the nsitem
66
+ *
67
+ * pstate->p_next_resno determines the resnos assigned to the TLEs.
68
+ * The referenced columns are marked as requiring SELECT access.
69
+ */
70
+ List *
71
+ expand_NS_Item_Attrs (ParseState * pstate , ParseNamespaceItem * nsitem ,
72
+ int sublevels_up , int location )
73
+ {
74
+ RangeTblEntry * rte = nsitem -> p_rte ;
75
+ List * names ,
76
+ * vars ;
77
+ ListCell * name ,
78
+ * var ;
79
+ List * te_list = NIL ;
80
+
81
+ vars = expandNSItemVars (nsitem , sublevels_up , location , & names );
82
+
83
+ /*
84
+ * Require read access to the table. This is normally redundant with the
85
+ * markVarForSelectPriv calls below, but not if the table has zero
86
+ * columns. We need not do anything if the nsitem is for a join: its
87
+ * component tables will have been marked ACL_SELECT when they were added
88
+ * to the rangetable. (This step changes things only for the target
89
+ * relation of UPDATE/DELETE, which cannot be under a join.)
90
+ */
91
+ if (rte -> rtekind == RTE_RELATION )
92
+ rte -> requiredPerms |= ACL_SELECT ;
93
+
94
+ forboth (name , names , var , vars )
95
+ {
96
+ char * label = strVal (lfirst (name ));
97
+ Var * varnode = (Var * ) lfirst (var );
98
+ TargetEntry * te ;
99
+ if (strlen (label ) < 2 || (strlen (label ) >= 2 && label [0 ] == '_' && label [1 ] == '_' )) {
100
+ te = makeTargetEntry ((Expr * ) varnode ,
101
+ (AttrNumber ) pstate -> p_next_resno ++ ,
102
+ label ,
103
+ false);
104
+ te_list = lappend (te_list , te );
105
+
106
+ /* Require read access to each column */
107
+ markVarForSelectPriv (pstate , varnode );
108
+ }
109
+ }
110
+
111
+ Assert (name == NULL && var == NULL ); /* lists not the same length? */
112
+
113
+ return te_list ;
114
+ }
115
+
116
+ /*
117
+ * ExpandAllTables()
118
+ * Transforms '*' (in the target list) into a list of targetlist entries.
119
+ *
120
+ * tlist entries are generated for each relation visible for unqualified
121
+ * column name access. We do not consider qualified-name-only entries because
122
+ * that would include input tables of aliasless JOINs, NEW/OLD pseudo-entries,
123
+ * etc.
124
+ *
125
+ * The referenced relations/columns are marked as requiring SELECT access.
126
+ */
127
+ static List *
128
+ Expand_All_Tables (ParseState * pstate , int location )
129
+ {
130
+ List * target = NIL ;
131
+ bool found_table = false;
132
+ ListCell * l ;
133
+
134
+ foreach (l , pstate -> p_namespace )
135
+ {
136
+ ParseNamespaceItem * nsitem = (ParseNamespaceItem * ) lfirst (l );
137
+
138
+ /* Ignore table-only items */
139
+ if (!nsitem -> p_cols_visible )
140
+ continue ;
141
+ /* Should not have any lateral-only items when parsing targetlist */
142
+ Assert (!nsitem -> p_lateral_only );
143
+ /* Remember we found a p_cols_visible item */
144
+ found_table = true;
145
+
146
+ target = list_concat (target ,
147
+ expand_NS_Item_Attrs (pstate ,
148
+ nsitem ,
149
+ 0 ,
150
+ location ));
151
+ }
152
+
153
+ /*
154
+ * Check for "SELECT *;". We do it this way, rather than checking for
155
+ * target == NIL, because we want to allow SELECT * FROM a zero_column
156
+ * table.
157
+ */
158
+ if (!found_table )
159
+ ereport (ERROR ,
160
+ (errcode (ERRCODE_SYNTAX_ERROR ),
161
+ errmsg ("SELECT * with no tables specified is not valid" ),
162
+ parser_errposition (pstate , location )));
163
+
164
+ return target ;
165
+ }
166
+
62
167
// see transformTargetList()
63
168
List * transform_cypher_item_list (cypher_parsestate * cpstate , List * item_list ,
64
169
List * * groupClause , ParseExprKind expr_kind )
@@ -77,8 +182,8 @@ List *transform_cypher_item_list(cypher_parsestate *cpstate, List *item_list,
77
182
ResTarget * item = lfirst (li );
78
183
TargetEntry * te ;
79
184
80
- cpstate -> prop_node = NULL ;
81
- cpstate -> prop_name = NULL ;
185
+ cpstate -> prop_node = NULL ;
186
+ cpstate -> prop_name = NULL ;
82
187
83
188
if (expand_star ) {
84
189
if (IsA (item -> val , ColumnRef )) {
@@ -93,14 +198,16 @@ List *transform_cypher_item_list(cypher_parsestate *cpstate, List *item_list,
93
198
errmsg ("Invalid number of fields for *" ),
94
199
parser_errposition (pstate , cref -> location )));
95
200
96
- target_list = list_concat (target_list , ExpandAllTables (pstate , cref -> location ));
201
+ target_list = list_concat (target_list , Expand_All_Tables (pstate , cref -> location ));
97
202
continue ;
98
203
}
99
204
}
100
205
}
101
206
/* clear the exprHasAgg flag to check transform for an aggregate */
102
207
cpstate -> exprHasAgg = false;
103
208
209
+ // if (item->name[0] == '_' && item->name[1] == '_')
210
+ // continue;
104
211
/* transform the item */
105
212
te = transform_cypher_item (cpstate , item -> val , NULL , expr_kind , item -> name , false);
106
213
0 commit comments