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

Commit 1e19395

Browse files
author
Commitfest Bot
committed
[CF 5214] v11 - SQL:2023 JSON simplified accessor support
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5214 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAK98qZ1nz6ZZhQqTOCNwRguZE5GsBLW5BQT_k=s7AA6gc2CN_g@mail.gmail.com Author(s): Alexandra Wang
2 parents 03c53a7 + c191ba0 commit 1e19395

File tree

27 files changed

+1567
-202
lines changed

27 files changed

+1567
-202
lines changed

contrib/hstore/hstore_subs.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
*/
4141
static void
4242
hstore_subscript_transform(SubscriptingRef *sbsref,
43-
List *indirection,
43+
List **indirection,
4444
ParseState *pstate,
4545
bool isSlice,
4646
bool isAssignment)
@@ -49,15 +49,15 @@ hstore_subscript_transform(SubscriptingRef *sbsref,
4949
Node *subexpr;
5050

5151
/* We support only single-subscript, non-slice cases */
52-
if (isSlice || list_length(indirection) != 1)
52+
if (isSlice || list_length(*indirection) != 1)
5353
ereport(ERROR,
5454
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5555
errmsg("hstore allows only one subscript"),
5656
parser_errposition(pstate,
57-
exprLocation((Node *) indirection))));
57+
exprLocation((Node *) *indirection))));
5858

5959
/* Transform the subscript expression to type text */
60-
ai = linitial_node(A_Indices, indirection);
60+
ai = linitial_node(A_Indices, *indirection);
6161
Assert(ai->uidx != NULL && ai->lidx == NULL && !ai->is_slice);
6262

6363
subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
@@ -81,6 +81,8 @@ hstore_subscript_transform(SubscriptingRef *sbsref,
8181
/* Determine the result type of the subscripting operation; always text */
8282
sbsref->refrestype = TEXTOID;
8383
sbsref->reftypmod = -1;
84+
85+
*indirection = NIL;
8486
}
8587

8688
/*

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/gram.y

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
687687
*/
688688
%token <str> IDENT UIDENT FCONST SCONST USCONST BCONST XCONST Op
689689
%token <ival> ICONST PARAM
690-
%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER
690+
%token TYPECAST DOT_DOT COLON_EQUALS EQUALS_GREATER DOUBLE_ASTERISK
691691
%token LESS_EQUALS GREATER_EQUALS NOT_EQUALS
692692

693693
/*
@@ -16971,6 +16971,13 @@ indirection_el:
1697116971
{
1697216972
$$ = (Node *) makeNode(A_Star);
1697316973
}
16974+
| '.' DOUBLE_ASTERISK
16975+
{
16976+
ereport(ERROR,
16977+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
16978+
errmsg("arbitrary depth wild card in simple json accessor not supported"),
16979+
parser_errposition(@2)));
16980+
}
1697416981
| '[' a_expr ']'
1697516982
{
1697616983
A_Indices *ai = makeNode(A_Indices);
@@ -19000,6 +19007,7 @@ check_func_name(List *names, core_yyscan_t yyscanner)
1900019007
static List *
1900119008
check_indirection(List *indirection, core_yyscan_t yyscanner)
1900219009
{
19010+
#if 0
1900319011
ListCell *l;
1900419012

1900519013
foreach(l, indirection)
@@ -19010,6 +19018,7 @@ check_indirection(List *indirection, core_yyscan_t yyscanner)
1901019018
parser_yyerror("improper use of \"*\"");
1901119019
}
1901219020
}
19021+
#endif
1901319022
return indirection;
1901419023
}
1901519024

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/parser/parse_expr.c

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
7474
static Node *transformWholeRowRef(ParseState *pstate,
7575
ParseNamespaceItem *nsitem,
7676
int sublevels_up, int location);
77-
static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
7877
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
7978
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
8079
static Node *transformJsonObjectConstructor(ParseState *pstate,
@@ -158,7 +157,7 @@ transformExprRecurse(ParseState *pstate, Node *expr)
158157
break;
159158

160159
case T_A_Indirection:
161-
result = transformIndirection(pstate, (A_Indirection *) expr);
160+
result = transformIndirection(pstate, (A_Indirection *) expr, NULL);
162161
break;
163162

164163
case T_A_ArrayExpr:
@@ -432,8 +431,9 @@ unknown_attribute(ParseState *pstate, Node *relref, const char *attname,
432431
}
433432
}
434433

435-
static Node *
436-
transformIndirection(ParseState *pstate, A_Indirection *ind)
434+
Node *
435+
transformIndirection(ParseState *pstate, A_Indirection *ind,
436+
bool *trailing_star_expansion)
437437
{
438438
Node *last_srf = pstate->p_last_srf;
439439
Node *result = transformExprRecurse(pstate, ind->arg);
@@ -442,8 +442,9 @@ transformIndirection(ParseState *pstate, A_Indirection *ind)
442442
ListCell *i;
443443

444444
/*
445-
* We have to split any field-selection operations apart from
446-
* subscripting. Adjacent A_Indices nodes have to be treated as a single
445+
* Combine field names and subscripts into a single indirection list, as
446+
* some subscripting containers, such as jsonb, support field access using
447+
* dot notation. Adjacent A_Indices nodes have to be treated as a single
447448
* multidimensional subscript operation.
448449
*/
449450
foreach(i, ind->indirection)
@@ -453,48 +454,80 @@ transformIndirection(ParseState *pstate, A_Indirection *ind)
453454
if (IsA(n, A_Indices))
454455
subscripts = lappend(subscripts, n);
455456
else if (IsA(n, A_Star))
457+
subscripts = lappend(subscripts, n);
458+
else
456459
{
457-
ereport(ERROR,
458-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
459-
errmsg("row expansion via \"*\" is not supported here"),
460-
parser_errposition(pstate, location)));
460+
Assert(IsA(n, String));
461+
subscripts = lappend(subscripts, n);
461462
}
462-
else
463+
}
464+
465+
while (subscripts)
466+
{
467+
/* try processing container subscripts first */
468+
Node *newresult = (Node *)
469+
transformContainerSubscripts(pstate,
470+
result,
471+
exprType(result),
472+
exprTypmod(result),
473+
&subscripts,
474+
false,
475+
true);
476+
477+
if (!newresult)
463478
{
464-
Node *newresult;
479+
/*
480+
* generic subscripting failed; falling back to function call or
481+
* field selection for a composite type.
482+
*/
483+
Node *n;
465484

466-
Assert(IsA(n, String));
485+
Assert(subscripts);
486+
487+
n = linitial(subscripts);
488+
489+
if (IsA(n, A_Star))
490+
{
491+
/* Success, if trailing star expansion is allowed */
492+
if (trailing_star_expansion && list_length(subscripts) == 1)
493+
{
494+
*trailing_star_expansion = true;
495+
return result;
496+
}
467497

468-
/* process subscripts before this field selection */
469-
if (subscripts)
470-
result = (Node *) transformContainerSubscripts(pstate,
471-
result,
472-
exprType(result),
473-
exprTypmod(result),
474-
subscripts,
475-
false);
476-
subscripts = NIL;
498+
ereport(ERROR,
499+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
500+
errmsg("row expansion via \"*\" is not supported here"),
501+
parser_errposition(pstate, location)));
502+
}
503+
else if (!IsA(n, String))
504+
ereport(ERROR,
505+
(errcode(ERRCODE_DATATYPE_MISMATCH),
506+
errmsg("cannot subscript type %s because it does not support subscripting",
507+
format_type_be(exprType(result))),
508+
parser_errposition(pstate, exprLocation(result))));
477509

510+
/* try to find function for field selection */
478511
newresult = ParseFuncOrColumn(pstate,
479512
list_make1(n),
480513
list_make1(result),
481514
last_srf,
482515
NULL,
483516
false,
484517
location);
485-
if (newresult == NULL)
518+
519+
if (!newresult)
486520
unknown_attribute(pstate, result, strVal(n), location);
487-
result = newresult;
521+
522+
/* consume field select */
523+
subscripts = list_delete_first(subscripts);
488524
}
525+
526+
result = newresult;
489527
}
490-
/* process trailing subscripts, if any */
491-
if (subscripts)
492-
result = (Node *) transformContainerSubscripts(pstate,
493-
result,
494-
exprType(result),
495-
exprTypmod(result),
496-
subscripts,
497-
false);
528+
529+
if (trailing_star_expansion)
530+
*trailing_star_expansion = false;
498531

499532
return result;
500533
}

0 commit comments

Comments
 (0)