@@ -89,14 +89,35 @@ AddSubscriptExpressions(SubscriptingRef *sbsref, struct ParseState *pstate, A_In
89
89
}
90
90
}
91
91
92
+ bool
93
+ AddSubscriptExpressions (SubscriptingRef *sbsref, struct ParseState *pstate, Node *subscript, bool is_slice) {
94
+ if (IsA (subscript, A_Indices)) {
95
+ // If the subscript is an A_Indices node, we can add the expressions directly
96
+ AddSubscriptExpressions (sbsref, pstate, castNode (A_Indices, subscript), is_slice);
97
+ return true ;
98
+ }
99
+
100
+ if (IsA (subscript, String)) {
101
+ sbsref->refupperindexpr = lappend (sbsref->refupperindexpr , subscript);
102
+ return true ;
103
+ }
104
+
105
+ if (IsA (subscript, A_Star)) {
106
+ sbsref->refupperindexpr = lappend (sbsref->refupperindexpr , NULL );
107
+ return true ;
108
+ }
109
+
110
+ return false ;
111
+ }
112
+
92
113
/*
93
114
* DuckdbSubscriptTransform is called by the parser when a subscripting
94
115
* operation is performed on a duckdb type that can be indexed by arbitrary
95
116
* expressions. All this does is parse those expressions and make sure the
96
117
* subscript returns an an duckdb.unresolved_type again.
97
118
*/
98
119
void
99
- DuckdbSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
120
+ DuckdbSubscriptTransform (SubscriptingRef *sbsref, List ** indirection, struct ParseState *pstate, bool is_slice,
100
121
bool is_assignment, const char *type_name) {
101
122
/*
102
123
* We need to populate our cache for some of the code below. Normally this
@@ -111,18 +132,22 @@ DuckdbSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct Pars
111
132
elog (ERROR, " Assignment to %s is not supported" , type_name);
112
133
}
113
134
114
- if (indirection == NIL) {
135
+ if (* indirection == NIL) {
115
136
elog (ERROR, " Subscripting %s with an empty subscript is not supported" , type_name);
116
137
}
117
138
118
139
// Transform each subscript expression
119
- foreach_node (A_Indices, subscript, indirection) {
120
- AddSubscriptExpressions (sbsref, pstate, subscript, is_slice);
140
+ foreach_ptr (Node, subscript, *indirection) {
141
+ if (!AddSubscriptExpressions (sbsref, pstate, subscript, is_slice)) {
142
+ break ;
143
+ }
121
144
}
122
145
123
146
// Set the result type of the subscripting operation
124
147
sbsref->refrestype = pgduckdb::DuckdbUnresolvedTypeOid ();
125
148
sbsref->reftypmod = -1 ;
149
+
150
+ *indirection = list_delete_first_n (*indirection, list_length (sbsref->refupperindexpr ));
126
151
}
127
152
128
153
/*
@@ -136,7 +161,7 @@ DuckdbSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct Pars
136
161
* Currently this is used for duckdb.row and duckdb.struct types.
137
162
*/
138
163
void
139
- DuckdbTextSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
164
+ DuckdbTextSubscriptTransform (SubscriptingRef *sbsref, List ** indirection, struct ParseState *pstate, bool is_slice,
140
165
bool is_assignment, const char *type_name) {
141
166
/*
142
167
* We need to populate our cache for some of the code below. Normally this
@@ -151,33 +176,40 @@ DuckdbTextSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct
151
176
elog (ERROR, " Assignment to %s is not supported" , type_name);
152
177
}
153
178
154
- if (indirection == NIL) {
179
+ if (* indirection == NIL) {
155
180
elog (ERROR, " Subscripting %s with an empty subscript is not supported" , type_name);
156
181
}
157
182
158
183
bool first = true ;
159
184
160
185
// Transform each subscript expression
161
- foreach_node (A_Indices, subscript, indirection) {
162
- /* The first subscript needs to be a TEXT constant, since it should be
163
- * a column reference. But the subscripts after that can be anything,
164
- * DuckDB should interpret those. */
165
- if (first) {
166
- sbsref->refupperindexpr =
167
- lappend (sbsref->refupperindexpr , CoerceSubscriptToText (pstate, subscript, type_name));
186
+ foreach_ptr (Node, subscript, *indirection) {
187
+ /*
188
+ * If the first subscript is an index expression then it needs to be
189
+ * coerced to text, since it should be a column reference. But the
190
+ * subscripts after that can be anything, DuckDB should interpret
191
+ * those.
192
+ */
193
+ if (first && IsA (subscript, A_Indices)) {
194
+ sbsref->refupperindexpr = lappend (sbsref->refupperindexpr ,
195
+ CoerceSubscriptToText (pstate, castNode (A_Indices, subscript), type_name));
168
196
if (is_slice) {
169
197
sbsref->reflowerindexpr = lappend (sbsref->reflowerindexpr , NULL );
170
198
}
171
199
first = false ;
172
200
continue ;
173
201
}
174
202
175
- AddSubscriptExpressions (sbsref, pstate, subscript, is_slice);
203
+ if (!AddSubscriptExpressions (sbsref, pstate, subscript, is_slice)) {
204
+ break ;
205
+ }
176
206
}
177
207
178
208
// Set the result type of the subscripting operation
179
209
sbsref->refrestype = pgduckdb::DuckdbUnresolvedTypeOid ();
180
210
sbsref->reftypmod = -1 ;
211
+
212
+ *indirection = list_delete_first_n (*indirection, list_length (sbsref->refupperindexpr ));
181
213
}
182
214
183
215
static bool
@@ -229,8 +261,14 @@ DuckdbSubscriptExecSetup(const SubscriptingRef * /*sbsref*/, SubscriptingRefStat
229
261
}
230
262
231
263
void
232
- DuckdbRowSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
264
+ #if PG_VERSION_NUM >= 180000
265
+ DuckdbRowSubscriptTransform (SubscriptingRef *sbsref, List **indirection, struct ParseState *pstate, bool is_slice,
233
266
bool is_assignment) {
267
+ #else
268
+ DuckdbRowSubscriptTransform (SubscriptingRef *sbsref, List *indirection_, struct ParseState *pstate, bool is_slice,
269
+ bool is_assignment) {
270
+ List **indirection = &indirection_;
271
+ #endif
234
272
DuckdbTextSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.row" );
235
273
}
236
274
@@ -249,8 +287,14 @@ static SubscriptRoutines duckdb_row_subscript_routines = {
249
287
};
250
288
251
289
void
252
- DuckdbUnresolvedTypeSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate,
290
+ #if PG_VERSION_NUM >= 180000
291
+ DuckdbUnresolvedTypeSubscriptTransform (SubscriptingRef *sbsref, List **indirection, struct ParseState *pstate,
292
+ bool is_slice, bool is_assignment) {
293
+ #else
294
+ DuckdbUnresolvedTypeSubscriptTransform (SubscriptingRef *sbsref, List *indirection_, struct ParseState *pstate,
253
295
bool is_slice, bool is_assignment) {
296
+ List **indirection = &indirection_;
297
+ #endif
254
298
DuckdbSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.unresolved_type" );
255
299
}
256
300
@@ -269,8 +313,14 @@ static SubscriptRoutines duckdb_unresolved_type_subscript_routines = {
269
313
};
270
314
271
315
void
272
- DuckdbStructSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
316
+ #if PG_VERSION_NUM >= 180000
317
+ DuckdbStructSubscriptTransform (SubscriptingRef *sbsref, List **indirection, struct ParseState *pstate, bool is_slice,
273
318
bool is_assignment) {
319
+ #else
320
+ DuckdbStructSubscriptTransform (SubscriptingRef *sbsref, List *indirection_, struct ParseState *pstate, bool is_slice,
321
+ bool is_assignment) {
322
+ List **indirection = &indirection_;
323
+ #endif
274
324
DuckdbTextSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.struct" );
275
325
}
276
326
@@ -289,8 +339,14 @@ static SubscriptRoutines duckdb_struct_subscript_routines = {
289
339
};
290
340
291
341
void
292
- DuckdbMapSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
342
+ #if PG_VERSION_NUM >= 180000
343
+ DuckdbMapSubscriptTransform (SubscriptingRef *sbsref, List **indirection, struct ParseState *pstate, bool is_slice,
344
+ bool is_assignment) {
345
+ #else
346
+ DuckdbMapSubscriptTransform (SubscriptingRef *sbsref, List *indirection_, struct ParseState *pstate, bool is_slice,
293
347
bool is_assignment) {
348
+ List **indirection = &indirection_;
349
+ #endif
294
350
DuckdbSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.map" );
295
351
}
296
352
0 commit comments