Skip to content

Commit 3f2d616

Browse files
Nikita GlukhovCommitfest Bot
Nikita Glukhov
authored and
Commitfest Bot
committed
Enable String node as field accessors in generic subscripting
Now that we are allowing container generic subscripting to take dot notation in the list of indirections, and it is transformed as a String node. For jsonb, we want to represent field accessors as String nodes in refupperexprs for distinguishing from ordinary text subscripts which can be needed for correct EXPLAIN. Strings node is no longer a valid expression nodes, so added special handling for them in walkers in nodeFuncs etc.
1 parent 3c5017a commit 3f2d616

File tree

4 files changed

+121
-27
lines changed

4 files changed

+121
-27
lines changed

src/backend/executor/execExpr.c

+18-6
Original file line numberDiff line numberDiff line change
@@ -3336,9 +3336,15 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
33363336
{
33373337
sbsrefstate->upperprovided[i] = true;
33383338
/* Each subscript is evaluated into appropriate array entry */
3339-
ExecInitExprRec(e, state,
3340-
&sbsrefstate->upperindex[i],
3341-
&sbsrefstate->upperindexnull[i]);
3339+
if (IsA(e, String))
3340+
{
3341+
sbsrefstate->upperindex[i] = CStringGetTextDatum(strVal(e));
3342+
sbsrefstate->upperindexnull[i] = false;
3343+
}
3344+
else
3345+
ExecInitExprRec(e, state,
3346+
&sbsrefstate->upperindex[i],
3347+
&sbsrefstate->upperindexnull[i]);
33423348
}
33433349
i++;
33443350
}
@@ -3359,9 +3365,15 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
33593365
{
33603366
sbsrefstate->lowerprovided[i] = true;
33613367
/* Each subscript is evaluated into appropriate array entry */
3362-
ExecInitExprRec(e, state,
3363-
&sbsrefstate->lowerindex[i],
3364-
&sbsrefstate->lowerindexnull[i]);
3368+
if (IsA(e, String))
3369+
{
3370+
sbsrefstate->lowerindex[i] = CStringGetTextDatum(strVal(e));
3371+
sbsrefstate->lowerindexnull[i] = false;
3372+
}
3373+
else
3374+
ExecInitExprRec(e, state,
3375+
&sbsrefstate->lowerindex[i],
3376+
&sbsrefstate->lowerindexnull[i]);
33653377
}
33663378
i++;
33673379
}

src/backend/nodes/nodeFuncs.c

+64-9
Original file line numberDiff line numberDiff line change
@@ -2182,12 +2182,28 @@ expression_tree_walker_impl(Node *node,
21822182
case T_SubscriptingRef:
21832183
{
21842184
SubscriptingRef *sbsref = (SubscriptingRef *) node;
2185+
ListCell *lc;
2186+
2187+
/*
2188+
* Recurse directly for upper/lower container index lists,
2189+
* skipping String subscripts used for dot notation.
2190+
*/
2191+
foreach(lc, sbsref->refupperindexpr)
2192+
{
2193+
Node *expr = lfirst(lc);
2194+
2195+
if (expr && !IsA(expr, String) && WALK(expr))
2196+
return true;
2197+
}
2198+
2199+
foreach(lc, sbsref->reflowerindexpr)
2200+
{
2201+
Node *expr = lfirst(lc);
2202+
2203+
if (expr && !IsA(expr, String) && WALK(expr))
2204+
return true;
2205+
}
21852206

2186-
/* recurse directly for upper/lower container index lists */
2187-
if (LIST_WALK(sbsref->refupperindexpr))
2188-
return true;
2189-
if (LIST_WALK(sbsref->reflowerindexpr))
2190-
return true;
21912207
/* walker must see the refexpr and refassgnexpr, however */
21922208
if (WALK(sbsref->refexpr))
21932209
return true;
@@ -3082,12 +3098,51 @@ expression_tree_mutator_impl(Node *node,
30823098
{
30833099
SubscriptingRef *sbsref = (SubscriptingRef *) node;
30843100
SubscriptingRef *newnode;
3101+
ListCell *lc;
3102+
List *exprs = NIL;
30853103

30863104
FLATCOPY(newnode, sbsref, SubscriptingRef);
3087-
MUTATE(newnode->refupperindexpr, sbsref->refupperindexpr,
3088-
List *);
3089-
MUTATE(newnode->reflowerindexpr, sbsref->reflowerindexpr,
3090-
List *);
3105+
3106+
foreach(lc, sbsref->refupperindexpr)
3107+
{
3108+
Node *expr = lfirst(lc);
3109+
3110+
if (expr && IsA(expr, String))
3111+
{
3112+
String *str;
3113+
3114+
FLATCOPY(str, expr, String);
3115+
expr = (Node *) str;
3116+
}
3117+
else
3118+
expr = mutator(expr, context);
3119+
3120+
exprs = lappend(exprs, expr);
3121+
}
3122+
3123+
newnode->refupperindexpr = exprs;
3124+
3125+
exprs = NIL;
3126+
3127+
foreach(lc, sbsref->reflowerindexpr)
3128+
{
3129+
Node *expr = lfirst(lc);
3130+
3131+
if (expr && IsA(expr, String))
3132+
{
3133+
String *str;
3134+
3135+
FLATCOPY(str, expr, String);
3136+
expr = (Node *) str;
3137+
}
3138+
else
3139+
expr = mutator(expr, context);
3140+
3141+
exprs = lappend(exprs, expr);
3142+
}
3143+
3144+
newnode->reflowerindexpr = exprs;
3145+
30913146
MUTATE(newnode->refexpr, sbsref->refexpr,
30923147
Expr *);
30933148
MUTATE(newnode->refassgnexpr, sbsref->refassgnexpr,

src/backend/parser/parse_collate.c

+18-4
Original file line numberDiff line numberDiff line change
@@ -680,11 +680,25 @@ assign_collations_walker(Node *node, assign_collations_context *context)
680680
* contribute anything.)
681681
*/
682682
SubscriptingRef *sbsref = (SubscriptingRef *) node;
683+
ListCell *lc;
684+
685+
/* skip String subscripts used for dot notation */
686+
foreach(lc, sbsref->refupperindexpr)
687+
{
688+
Node *expr = lfirst(lc);
689+
690+
if (expr && !IsA(expr, String))
691+
assign_expr_collations(context->pstate, expr);
692+
}
693+
694+
foreach(lc, sbsref->reflowerindexpr)
695+
{
696+
Node *expr = lfirst(lc);
697+
698+
if (expr && !IsA(expr, String))
699+
assign_expr_collations(context->pstate, expr);
700+
}
683701

684-
assign_expr_collations(context->pstate,
685-
(Node *) sbsref->refupperindexpr);
686-
assign_expr_collations(context->pstate,
687-
(Node *) sbsref->reflowerindexpr);
688702
(void) assign_collations_walker((Node *) sbsref->refexpr,
689703
&loccontext);
690704
(void) assign_collations_walker((Node *) sbsref->refassgnexpr,

src/backend/utils/adt/ruleutils.c

+21-8
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "nodes/makefuncs.h"
4848
#include "nodes/nodeFuncs.h"
4949
#include "nodes/pathnodes.h"
50+
#include "nodes/subscripting.h"
5051
#include "optimizer/optimizer.h"
5152
#include "parser/parse_agg.h"
5253
#include "parser/parse_func.h"
@@ -12995,17 +12996,29 @@ printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
1299512996
lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */
1299612997
foreach(uplist_item, sbsref->refupperindexpr)
1299712998
{
12998-
appendStringInfoChar(buf, '[');
12999-
if (lowlist_item)
12999+
Node *up = (Node *) lfirst(uplist_item);
13000+
13001+
if (IsA(up, String))
13002+
{
13003+
appendStringInfoChar(buf, '.');
13004+
appendStringInfoString(buf, quote_identifier(strVal(up)));
13005+
}
13006+
else
1300013007
{
13008+
appendStringInfoChar(buf, '[');
13009+
if (lowlist_item)
13010+
{
13011+
/* If subexpression is NULL, get_rule_expr prints nothing */
13012+
get_rule_expr((Node *) lfirst(lowlist_item), context, false);
13013+
appendStringInfoChar(buf, ':');
13014+
}
1300113015
/* If subexpression is NULL, get_rule_expr prints nothing */
13002-
get_rule_expr((Node *) lfirst(lowlist_item), context, false);
13003-
appendStringInfoChar(buf, ':');
13004-
lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
13016+
get_rule_expr((Node *) lfirst(uplist_item), context, false);
13017+
appendStringInfoChar(buf, ']');
1300513018
}
13006-
/* If subexpression is NULL, get_rule_expr prints nothing */
13007-
get_rule_expr((Node *) lfirst(uplist_item), context, false);
13008-
appendStringInfoChar(buf, ']');
13019+
13020+
if (lowlist_item)
13021+
lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
1300913022
}
1301013023
}
1301113024

0 commit comments

Comments
 (0)