Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b2f50f1

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 a2ca4db commit b2f50f1

File tree

4 files changed

+121
-27
lines changed

4 files changed

+121
-27
lines changed

src/backend/executor/execExpr.c

Lines changed: 18 additions & 6 deletions
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

Lines changed: 64 additions & 9 deletions
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

Lines changed: 18 additions & 4 deletions
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

Lines changed: 21 additions & 8 deletions
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"
@@ -13005,17 +13006,29 @@ printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
1300513006
lowlist_item = list_head(sbsref->reflowerindexpr); /* could be NULL */
1300613007
foreach(uplist_item, sbsref->refupperindexpr)
1300713008
{
13008-
appendStringInfoChar(buf, '[');
13009-
if (lowlist_item)
13009+
Node *up = (Node *) lfirst(uplist_item);
13010+
13011+
if (IsA(up, String))
13012+
{
13013+
appendStringInfoChar(buf, '.');
13014+
appendStringInfoString(buf, quote_identifier(strVal(up)));
13015+
}
13016+
else
1301013017
{
13018+
appendStringInfoChar(buf, '[');
13019+
if (lowlist_item)
13020+
{
13021+
/* If subexpression is NULL, get_rule_expr prints nothing */
13022+
get_rule_expr((Node *) lfirst(lowlist_item), context, false);
13023+
appendStringInfoChar(buf, ':');
13024+
}
1301113025
/* If subexpression is NULL, get_rule_expr prints nothing */
13012-
get_rule_expr((Node *) lfirst(lowlist_item), context, false);
13013-
appendStringInfoChar(buf, ':');
13014-
lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
13026+
get_rule_expr((Node *) lfirst(uplist_item), context, false);
13027+
appendStringInfoChar(buf, ']');
1301513028
}
13016-
/* If subexpression is NULL, get_rule_expr prints nothing */
13017-
get_rule_expr((Node *) lfirst(uplist_item), context, false);
13018-
appendStringInfoChar(buf, ']');
13029+
13030+
if (lowlist_item)
13031+
lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item);
1301913032
}
1302013033
}
1302113034

0 commit comments

Comments
 (0)