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

Commit 1696acc

Browse files
author
Nikita Glukhov
committed
Allow variable jsonpath specifications in JSON_TABLE
1 parent eced0ca commit 1696acc

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

src/backend/parser/parse_clause.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,18 @@ transformRangeTableSample(ParseState *pstate, RangeTableSample *rts)
10291029
return tablesample;
10301030
}
10311031

1032+
static Node *
1033+
makeStringConst(char *str, int location)
1034+
{
1035+
A_Const *n = makeNode(A_Const);
1036+
1037+
n->val.type = T_String;
1038+
n->val.val.str = str;
1039+
n->location = location;
1040+
1041+
return (Node *)n;
1042+
}
1043+
10321044
/*
10331045
* getRTEForSpecialRelationTypes
10341046
*
@@ -1072,6 +1084,7 @@ transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
10721084
JsonValueExpr *jvexpr = makeNode(JsonValueExpr);
10731085
JsonCommon *common = makeNode(JsonCommon);
10741086
JsonOutput *output = makeNode(JsonOutput);
1087+
JsonPathSpec pathspec;
10751088

10761089
jfexpr->op = jtc->coltype == JTC_REGULAR ? IS_JSON_VALUE : IS_JSON_QUERY;
10771090
jfexpr->common = common;
@@ -1092,7 +1105,7 @@ transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
10921105
common->passing = passingArgs;
10931106

10941107
if (jtc->pathspec)
1095-
common->pathspec = jtc->pathspec;
1108+
pathspec = jtc->pathspec;
10961109
else
10971110
{
10981111
/* Construct default path as '$."column_name"' */
@@ -1103,9 +1116,11 @@ transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
11031116
appendStringInfoString(&path, "$.");
11041117
escape_json(&path, jtc->name);
11051118

1106-
common->pathspec = path.data;
1119+
pathspec = path.data;
11071120
}
11081121

1122+
common->pathspec = makeStringConst(pathspec, -1);
1123+
11091124
jvexpr->expr = (Expr *) contextItemExpr;
11101125
jvexpr->format.type = JS_FORMAT_DEFAULT;
11111126
jvexpr->format.encoding = JS_ENC_DEFAULT;
@@ -1606,6 +1621,7 @@ transformJsonTable(ParseState *pstate, JsonTable *jt)
16061621
JsonCommon *jscommon;
16071622
JsonTablePlan *plan = jt->plan;
16081623
char *rootPathName = jt->common->pathname;
1624+
char *rootPath;
16091625
bool is_lateral;
16101626

16111627
cxt.table = jt;
@@ -1637,7 +1653,7 @@ transformJsonTable(ParseState *pstate, JsonTable *jt)
16371653
#endif
16381654

16391655
jscommon = copyObject(jt->common);
1640-
jscommon->pathspec = pstrdup("$");
1656+
jscommon->pathspec = makeStringConst(pstrdup("$"), -1);
16411657

16421658
jfe->op = IS_JSON_TABLE;
16431659
jfe->common = jscommon;
@@ -1661,10 +1677,19 @@ transformJsonTable(ParseState *pstate, JsonTable *jt)
16611677

16621678
cxt.contextItemTypid = exprType(tf->docexpr);
16631679

1680+
if (!IsA(jt->common->pathspec, A_Const) ||
1681+
castNode(A_Const, jt->common->pathspec)->val.type != T_String)
1682+
ereport(ERROR,
1683+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1684+
errmsg("only string constants supported in JSON_TABLE path specification"),
1685+
parser_errposition(pstate,
1686+
exprLocation(jt->common->pathspec))));
1687+
1688+
rootPath = castNode(A_Const, jt->common->pathspec)->val.val.str;
1689+
16641690
tf->plan = (Node *) transformJsonTableColumns(pstate, &cxt, plan,
16651691
jt->columns,
1666-
jt->common->pathspec,
1667-
&rootPathName,
1692+
rootPath, &rootPathName,
16681693
jt->common->location);
16691694

16701695
tf->ordinalitycol = -1; /* undefine ordinality column number */

src/backend/utils/adt/ruleutils.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10360,7 +10360,8 @@ get_json_table_columns(TableFunc *tf, JsonTableParentNode *node,
1036010360
" FORMAT JSONB" : " FORMAT JSON");
1036110361

1036210362
appendStringInfoString(buf, " PATH ");
10363-
get_const_expr(colexpr->path_spec, context, -1);
10363+
10364+
get_json_path_spec(colexpr->path_spec, context, showimplicit);
1036410365

1036510366
if (colexpr->wrapper == JSW_CONDITIONAL)
1036610367
appendStringInfo(buf, " WITH CONDITIONAL WRAPPER");

src/test/regress/expected/jsonb_sqljson.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,6 +1895,11 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
18951895
-- Should fail (invalid path)
18961896
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
18971897
ERROR: syntax error, unexpected IDENT_P at or near "error" of jsonpath input
1898+
-- Should fail (not supported)
1899+
SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));
1900+
ERROR: only string constants supported in JSON_TABLE path specification
1901+
LINE 1: SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || '...
1902+
^
18981903
-- Test parallel JSON_VALUE()
18991904
CREATE TABLE test_parallel_jsonb_value AS
19001905
SELECT i::text::jsonb AS js

src/test/regress/sql/jsonb_sqljson.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,8 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
861861
SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
862862
-- Should fail (invalid path)
863863
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
864+
-- Should fail (not supported)
865+
SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));
864866

865867
-- Test parallel JSON_VALUE()
866868
CREATE TABLE test_parallel_jsonb_value AS
@@ -876,4 +878,3 @@ SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value
876878
EXPLAIN (COSTS OFF)
877879
SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
878880
SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
879-

0 commit comments

Comments
 (0)