@@ -89,14 +89,35 @@ AddSubscriptExpressions(SubscriptingRef *sbsref, struct ParseState *pstate, A_In
8989 }
9090}
9191
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+
92113/*
93114 * DuckdbSubscriptTransform is called by the parser when a subscripting
94115 * operation is performed on a duckdb type that can be indexed by arbitrary
95116 * expressions. All this does is parse those expressions and make sure the
96117 * subscript returns an an duckdb.unresolved_type again.
97118 */
98119void
99- DuckdbSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
120+ DuckdbSubscriptTransform (SubscriptingRef *sbsref, List ** indirection, struct ParseState *pstate, bool is_slice,
100121 bool is_assignment, const char *type_name) {
101122 /*
102123 * 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
111132 elog (ERROR, " Assignment to %s is not supported" , type_name);
112133 }
113134
114- if (indirection == NIL) {
135+ if (* indirection == NIL) {
115136 elog (ERROR, " Subscripting %s with an empty subscript is not supported" , type_name);
116137 }
117138
118139 // 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+ }
121144 }
122145
123146 // Set the result type of the subscripting operation
124147 sbsref->refrestype = pgduckdb::DuckdbUnresolvedTypeOid ();
125148 sbsref->reftypmod = -1 ;
149+
150+ *indirection = list_delete_first_n (*indirection, list_length (sbsref->refupperindexpr ));
126151}
127152
128153/*
@@ -136,7 +161,7 @@ DuckdbSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct Pars
136161 * Currently this is used for duckdb.row and duckdb.struct types.
137162 */
138163void
139- DuckdbTextSubscriptTransform (SubscriptingRef *sbsref, List *indirection, struct ParseState *pstate, bool is_slice,
164+ DuckdbTextSubscriptTransform (SubscriptingRef *sbsref, List ** indirection, struct ParseState *pstate, bool is_slice,
140165 bool is_assignment, const char *type_name) {
141166 /*
142167 * We need to populate our cache for some of the code below. Normally this
@@ -151,33 +176,40 @@ DuckdbTextSubscriptTransform(SubscriptingRef *sbsref, List *indirection, struct
151176 elog (ERROR, " Assignment to %s is not supported" , type_name);
152177 }
153178
154- if (indirection == NIL) {
179+ if (* indirection == NIL) {
155180 elog (ERROR, " Subscripting %s with an empty subscript is not supported" , type_name);
156181 }
157182
158183 bool first = true ;
159184
160185 // 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));
168196 if (is_slice) {
169197 sbsref->reflowerindexpr = lappend (sbsref->reflowerindexpr , NULL );
170198 }
171199 first = false ;
172200 continue ;
173201 }
174202
175- AddSubscriptExpressions (sbsref, pstate, subscript, is_slice);
203+ if (!AddSubscriptExpressions (sbsref, pstate, subscript, is_slice)) {
204+ break ;
205+ }
176206 }
177207
178208 // Set the result type of the subscripting operation
179209 sbsref->refrestype = pgduckdb::DuckdbUnresolvedTypeOid ();
180210 sbsref->reftypmod = -1 ;
211+
212+ *indirection = list_delete_first_n (*indirection, list_length (sbsref->refupperindexpr ));
181213}
182214
183215static bool
@@ -229,8 +261,14 @@ DuckdbSubscriptExecSetup(const SubscriptingRef * /*sbsref*/, SubscriptingRefStat
229261}
230262
231263void
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,
233266 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
234272 DuckdbTextSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.row" );
235273}
236274
@@ -249,8 +287,14 @@ static SubscriptRoutines duckdb_row_subscript_routines = {
249287};
250288
251289void
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,
253295 bool is_slice, bool is_assignment) {
296+ List **indirection = &indirection_;
297+ #endif
254298 DuckdbSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.unresolved_type" );
255299}
256300
@@ -269,8 +313,14 @@ static SubscriptRoutines duckdb_unresolved_type_subscript_routines = {
269313};
270314
271315void
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,
273318 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
274324 DuckdbTextSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.struct" );
275325}
276326
@@ -289,8 +339,14 @@ static SubscriptRoutines duckdb_struct_subscript_routines = {
289339};
290340
291341void
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,
293347 bool is_assignment) {
348+ List **indirection = &indirection_;
349+ #endif
294350 DuckdbSubscriptTransform (sbsref, indirection, pstate, is_slice, is_assignment, " duckdb.map" );
295351}
296352
0 commit comments