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

Commit a4d4fa2

Browse files
author
Nikita Glukhov
committed
Allow variable jsonpath specifications in JSON_TABLE
1 parent 2a13e6c commit a4d4fa2

File tree

5 files changed

+42
-9
lines changed

5 files changed

+42
-9
lines changed

src/backend/parser/gram.y

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
845845
*/
846846
%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
847847
%nonassoc ERROR_P EMPTY_P DEFAULT ABSENT /* JSON error/empty behavior */
848-
%nonassoc FALSE_P KEEP OMIT PASSING TRUE_P UNKNOWN
848+
%nonassoc COLUMNS FALSE_P KEEP OMIT PASSING TRUE_P UNKNOWN
849849
%nonassoc IDENT GENERATED NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING CUBE ROLLUP
850850
%left Op OPERATOR /* multi-character ops and user-defined operators */
851851
%left '+' '-'
@@ -14739,7 +14739,7 @@ json_table_error_clause_opt:
1473914739
;
1474014740

1474114741
json_table_column_path_specification_clause_opt:
14742-
PATH json_path_specification { $$ = $2; }
14742+
PATH Sconst { $$ = $2; }
1474314743
| /* EMPTY */ %prec json_table_column { $$ = NULL; }
1474414744
;
1474514745

@@ -14771,7 +14771,7 @@ json_table_formatted_column_definition:
1477114771
;
1477214772

1477314773
json_table_nested_columns:
14774-
NESTED path_opt json_path_specification
14774+
NESTED path_opt Sconst
1477514775
json_as_path_name_clause_opt
1477614776
json_table_columns_clause
1477714777
{

src/backend/parser/parse_clause.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,18 @@ transformRangeTableSample(ParseState *pstate, RangeTableSample *rts)
10591059
return tablesample;
10601060
}
10611061

1062+
static Node *
1063+
makeStringConst(char *str, int location)
1064+
{
1065+
A_Const *n = makeNode(A_Const);
1066+
1067+
n->val.type = T_String;
1068+
n->val.val.str = str;
1069+
n->location = location;
1070+
1071+
return (Node *)n;
1072+
}
1073+
10621074
/*
10631075
* getRTEForSpecialRelationTypes
10641076
*
@@ -1102,6 +1114,7 @@ transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
11021114
JsonValueExpr *jvexpr = makeNode(JsonValueExpr);
11031115
JsonCommon *common = makeNode(JsonCommon);
11041116
JsonOutput *output = makeNode(JsonOutput);
1117+
JsonPathSpec pathspec;
11051118

11061119
jfexpr->op = jtc->coltype == JTC_REGULAR ? IS_JSON_VALUE : IS_JSON_QUERY;
11071120
jfexpr->common = common;
@@ -1122,7 +1135,7 @@ transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
11221135
common->passing = passingArgs;
11231136

11241137
if (jtc->pathspec)
1125-
common->pathspec = jtc->pathspec;
1138+
pathspec = jtc->pathspec;
11261139
else
11271140
{
11281141
/* Construct default path as '$."column_name"' */
@@ -1133,9 +1146,11 @@ transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
11331146
appendStringInfoString(&path, "$.");
11341147
escape_json(&path, jtc->name);
11351148

1136-
common->pathspec = path.data;
1149+
pathspec = path.data;
11371150
}
11381151

1152+
common->pathspec = makeStringConst(pathspec, -1);
1153+
11391154
jvexpr->expr = (Expr *) contextItemExpr;
11401155
jvexpr->format.type = JS_FORMAT_DEFAULT;
11411156
jvexpr->format.encoding = JS_ENC_DEFAULT;
@@ -1629,6 +1644,7 @@ transformJsonTable(ParseState *pstate, JsonTable *jt)
16291644
JsonCommon *jscommon;
16301645
JsonTablePlan *plan = jt->plan;
16311646
char *rootPathName = jt->common->pathname;
1647+
char *rootPath;
16321648
bool is_lateral;
16331649

16341650
cxt.table = jt;
@@ -1658,7 +1674,7 @@ transformJsonTable(ParseState *pstate, JsonTable *jt)
16581674
}
16591675

16601676
jscommon = copyObject(jt->common);
1661-
jscommon->pathspec = pstrdup("$");
1677+
jscommon->pathspec = makeStringConst(pstrdup("$"), -1);
16621678

16631679
jfe->op = IS_JSON_TABLE;
16641680
jfe->common = jscommon;
@@ -1682,10 +1698,19 @@ transformJsonTable(ParseState *pstate, JsonTable *jt)
16821698

16831699
cxt.contextItemTypid = exprType(tf->docexpr);
16841700

1701+
if (!IsA(jt->common->pathspec, A_Const) ||
1702+
castNode(A_Const, jt->common->pathspec)->val.type != T_String)
1703+
ereport(ERROR,
1704+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1705+
errmsg("only string constants supported in JSON_TABLE path specification"),
1706+
parser_errposition(pstate,
1707+
exprLocation(jt->common->pathspec))));
1708+
1709+
rootPath = castNode(A_Const, jt->common->pathspec)->val.val.str;
1710+
16851711
tf->plan = (Node *) transformJsonTableColumns(pstate, &cxt, plan,
16861712
jt->columns,
1687-
jt->common->pathspec,
1688-
&rootPathName,
1713+
rootPath, &rootPathName,
16891714
jt->common->location);
16901715

16911716
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
@@ -10124,7 +10124,8 @@ get_json_table_columns(TableFunc *tf, JsonTableParentNode *node,
1012410124
" FORMAT JSONB" : " FORMAT JSON");
1012510125

1012610126
appendStringInfoString(buf, " PATH ");
10127-
get_const_expr(colexpr->path_spec, context, -1);
10127+
10128+
get_json_path_spec(colexpr->path_spec, context, showimplicit);
1012810129

1012910130
if (colexpr->wrapper == JSW_CONDITIONAL)
1013010131
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
@@ -1832,3 +1832,8 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
18321832
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
18331833
ERROR: bad jsonpath representation
18341834
DETAIL: syntax error, unexpected IDENT_P at or near " "
1835+
-- Should fail (not supported)
1836+
SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));
1837+
ERROR: only string constants supported in JSON_TABLE path specification
1838+
LINE 1: SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || '...
1839+
^

src/test/regress/sql/jsonb_sqljson.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,3 +835,5 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
835835
SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
836836
-- Should fail (invalid path)
837837
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
838+
-- Should fail (not supported)
839+
SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));

0 commit comments

Comments
 (0)