8000 Json v9 by l-wang · Pull Request #3 · l-wang/postgres · GitHub
[go: up one dir, main page]

Skip to content

Json v9 #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions contrib/hstore/hstore_subs.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
*/
static void
hstore_subscript_transform(SubscriptingRef *sbsref,
List *indirection,
List **indirection,
ParseState *pstate,
bool isSlice,
bool isAssignment)
Expand All @@ -49,15 +49,15 @@ hstore_subscript_transform(SubscriptingRef *sbsref,
Node *subexpr;

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

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

subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
Expand All @@ -81,6 +81,8 @@ hstore_subscript_transform(SubscriptingRef *sbsref,
/* Determine the result type of the subscripting operation; always text */
sbsref->refrestype = TEXTOID;
sbsref->reftypmod = -1;

*indirection = NIL;
}

/*
Expand Down
24 changes: 18 additions & 6 deletions src/backend/executor/execExpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3328,9 +3328,15 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
{
sbsrefstate->upperprovided[i] = true;
/* Each subscript is evaluated into appropriate array entry */
ExecInitExprRec(e, state,
&sbsrefstate->upperindex[i],
&sbsrefstate->upperindexnull[i]);
if (IsA(e, String))
{
sbsrefstate->upperindex[i] = CStringGetTextDatum(strVal(e));
sbsrefstate->upperindexnull[i] = false;
}
else
ExecInitExprRec(e, state,
&sbsrefstate->upperindex[i],
&sbsrefstate->upperindexnull[i]);
}
i++;
}
Expand All @@ -3351,9 +3357,15 @@ ExecInitSubscriptingRef(ExprEvalStep *scratch, SubscriptingRef *sbsref,
{
sbsrefstate->lowerprovided[i] = true;
/* Each subscript is evaluated into appropriate array entry */
ExecInitExprRec(e, state,
&sbsrefstate->lowerindex[i],
&sbsrefstate->lowerindexnull[i]);
if (IsA(e, String))
{
sbsrefstate->lowerindex[i] = CStringGetTextDatum(strVal(e));
sbsrefstate->lowerindexnull[i] = false;
}
else
ExecInitExprRec(e, state,
&sbsrefstate->lowerindex[i],
&sbsrefstate->lowerindexnull[i]);
}
i++;
}
Expand Down
73 changes: 64 additions & 9 deletions src/backend/nodes/nodeFuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2182,12 +2182,28 @@ expression_tree_walker_impl(Node *node,
case T_SubscriptingRef:
{
SubscriptingRef *sbsref = (SubscriptingRef *) node;
ListCell *lc;

/*
* Recurse directly for upper/lower container index lists,
* skipping String subscripts used for dot notation.
*/
foreach(lc, sbsref->refupperindexpr)
{
Node *expr = lfirst(lc);

if (expr && !IsA(expr, String) && WALK(expr))
return true;
}

foreach(lc, sbsref->reflowerindexpr)
{
Node *expr = lfirst(lc);

if (expr && !IsA(expr, String) && WALK(expr))
return true;
}

/* recurse directly for upper/lower container index lists */
if (LIST_WALK(sbsref->refupperindexpr))
return true;
if (LIST_WALK(sbsref->reflowerindexpr))
return true;
/* walker must see the refexpr and refassgnexpr, however */
if (WALK(sbsref->refexpr))
return true;
Expand Down Expand Up @@ -3082,12 +3098,51 @@ expression_tree_mutator_impl(Node *node,
{
SubscriptingRef *sbsref = (SubscriptingRef *) node;
SubscriptingRef *newnode;
ListCell *lc;
List *exprs = NIL;

FLATCOPY(newnode, sbsref, SubscriptingRef);
MUTATE(newnode->refupperindexpr, sbsref->refupperindexpr,
List *);
MUTATE(newnode->reflowerindexpr, sbsref->reflowerindexpr,
List *);

foreach(lc, sbsref->refupperindexpr)
{
Node *expr = lfirst(lc);

if (expr && IsA(expr, String))
{
String *str;

FLATCOPY(str, expr, String);
expr = (Node *) str;
}
else
expr = mutator(expr, context);

exprs = lappend(exprs, expr);
}

newnode->refupperindexpr = exprs;

exprs = NIL;

foreach(lc, sbsref->reflowerindexpr)
{
Node *expr = lfirst(lc);

if (expr && IsA(expr, String))
{
String *str;

FLATCOPY(str, expr, String);
expr = (Node *) str;
}
else
expr = mutator(expr, context);

exprs = lappend(exprs, expr);
}

newnode->reflowerindexpr = exprs;

MUTATE(newnode->refexpr, sbsref->refexpr,
Expr *);
MUTATE(newnode->refassgnexpr, sbsref->refassgnexpr,
Expand Down
2 changes: 2 additions & 0 deletions src/backend/parser/gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -18968,6 +18968,7 @@ check_func_name(List *names, core_yyscan_t yyscanner)
static List *
check_indirection(List *indirection, core_yyscan_t yyscanner)
{
#if 0
ListCell *l;

foreach(l, indirection)
Expand All @@ -18978,6 +18979,7 @@ check_indirection(List *indirection, core_yyscan_t yyscanner)
parser_yyerror("improper use of \"*\"");
}
}
#endif
return indirection;
}

Expand Down
22 changes: 18 additions & 4 deletions src/backend/parser/parse_collate.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,11 +680,25 @@ assign_collations_walker(Node *node, assign_collations_context *context)
* contribute anything.)
*/
SubscriptingRef *sbsref = (SubscriptingRef *) node;
ListCell *lc;

/* skip String subscripts used for dot notation */
foreach(lc, sbsref->refupperindexpr)
{
Node *expr = lfirst(lc);

if (expr && !IsA(expr, String))
assign_expr_collations(context->pstate, expr);
}

foreach(lc, sbsref->reflowerindexpr)
{
Node *expr = lfirst(lc);

if (expr && !IsA(expr, String))
assign_expr_collations(context->pstate, expr);
}

assign_expr_collations(context->pstate,
(Node *) sbsref->refupperindexpr);
assign_expr_collations(context->pstate,
(Node *) sbsref->reflowerindexpr);
(void) assign_collations_walker((Node *) sbsref->refexpr,
&loccontext);
(void) assign_collations_walker((Node *) sbsref->refassgnexpr,
Expand Down
97 changes: 65 additions & 32 deletions src/backend/parser/parse_expr.c
4FEB
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformWholeRowRef(ParseState *pstate,
ParseNamespaceItem *nsitem,
int sublevels_up, int location);
static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
static Node *transformJsonObjectConstructor(ParseState *pstate,
Expand Down Expand Up @@ -158,7 +157,7 @@ transformExprRecurse(ParseState *pstate, Node *expr)
break;

case T_A_Indirection:
result = transformIndirection(pstate, (A_Indirection *) expr);
result = transformIndirection(pstate, (A_Indirection *) expr, NULL);
break;

case T_A_ArrayExpr:
Expand Down Expand Up @@ -432,8 +431,9 @@ unknown_attribute(ParseState *pstate, Node *relref, const char *attname,
}
}

static Node *
transformIndirection(ParseState *pstate, A_Indirection *ind)
Node *
transformIndirection(ParseState *pstate, A_Indirection *ind,
bool *trailing_star_expansion)
{
Node *last_srf = pstate->p_last_srf;
Node *result = transformExprRecurse(pstate, ind->arg);
Expand All< D54 /tool-tip> @@ -442,8 +442,9 @@ transformIndirection(ParseState *pstate, A_Indirection *ind)
ListCell *i;

/*
* We have to split any field-selection operations apart from
* subscripting. Adjacent A_Indices nodes have to be treated as a single
* Combine field names and subscripts into a single indirection list, as
* some subscripting containers, such as jsonb, support field access using
* dot notation. Adjacent A_Indices nodes have to be treated as a single
* multidimensional subscript operation.
*/
foreach(i, ind->indirection)
Expand All @@ -453,48 +454,80 @@ transformIndirection(ParseState *pstate, A_Indirection *ind)
if (IsA(n, A_Indices))
subscripts = lappend(subscripts, n);
else if (IsA(n, A_Star))
subscripts = lappend(subscripts, n);
else
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row expansion via \"*\" is not supported here"),
parser_errposition(pstate, location)));
Assert(IsA(n, String));
subscripts = lappend(subscripts, n);
}
else
}

while (subscripts)
{
/* try processing container subscripts first */
Node *newresult = (Node *)
transformContainerSubscripts(pstate,
result,
exprType(result),
exprTypmod(result),
&subscripts,
false,
true);

if (!newresult)
{
Node *newresult;
/*
* generic subscripting failed; falling back to function call or
* field selection for a composite type.
*/
Node *n;

Assert(IsA(n, String));
Assert(subscripts);

n = linitial(subscripts);

if (IsA(n, A_Star))
{
/* Success, if trailing star expansion is allowed */
if (trailing_star_expansion && list_length(subscripts) == 1)
{
*trailing_star_expansion = true;
return result;
}

/* process subscripts before this field selection */
if (subscripts)
result = (Node *) transformContainerSubscripts(pstate,
result,
exprType(result),
exprTypmod(result),
subscripts,
false);
subscripts = NIL;
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("row expansion via \"*\" is not supported here"),
parser_errposition(pstate, location)));
}
else if (!IsA(n, String))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot subscript type %s because it does not support subscripting",
format_type_be(exprType(result))),
parser_errposition(pstate, exprLocation(result))));

/* try to find function for field selection */
newresult = ParseFuncOrColumn(pstate,
list_make1(n),
list_make1(result),
last_srf,
NULL,
false,
location);
if (newresult == NULL)

if (!newresult)
unknown_attribute(pstate, result, strVal(n), location);
result = newresult;

/* consume field select */
subscripts = list_delete_first(subscripts);
}

result = newresult;
}
/* process trailing subscripts, if any */
if (subscripts)
result = (Node *) transformContainerSubscripts(pstate,
result,
exprType(result),
exprTypmod(result),
subscripts,
false);

if (trailing_star_expansion)
*trailing_star_expansion = false;

return result;
}
Expand Down
Loading
0