diff options
author | Andrew Dunstan <andrew@dunslane.net> | 2022-04-04 15:36:03 -0400 |
---|---|---|
committer | Andrew Dunstan <andrew@dunslane.net> | 2022-04-04 16:03:47 -0400 |
commit | 4e34747c88a03ede6e9d731727815e37273d4bc9 (patch) | |
tree | c7318a224b908c5dbaba3198324c90ec5429c3a5 /src/backend/parser/parse_expr.c | |
parent | c42a6fc41dc22b42e5417224440c02893996afb4 (diff) | |
download | postgresql-4e34747c88a03ede6e9d731727815e37273d4bc9.tar.gz postgresql-4e34747c88a03ede6e9d731727815e37273d4bc9.zip |
JSON_TABLE
This feature allows jsonb data to be treated as a table and thus used in
a FROM clause like other tabular data. Data can be selected from the
jsonb using jsonpath expressions, and hoisted out of nested structures
in the jsonb to form multiple rows, more or less like an outer join.
Nikita Glukhov
Reviewers have included (in no particular order) Andres Freund, Alexander
Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zhihong Yu (whose
name I previously misspelled), Himanshu Upadhyaya, Daniel Gustafsson,
Justin Pryzby.
Discussion: https://postgr.es/m/7e2cb85d-24cf-4abb-30a5-1a33715959bd@postgrespro.ru
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r-- | src/backend/parser/parse_expr.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 911f355460b..b6a2482f23a 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -4093,7 +4093,7 @@ transformJsonExprCommon(ParseState *pstate, JsonFuncExpr *func) Node *pathspec; JsonFormatType format; - if (func->common->pathname) + if (func->common->pathname && func->op != JSON_TABLE_OP) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("JSON_TABLE path name is not allowed here"), @@ -4131,14 +4131,19 @@ transformJsonExprCommon(ParseState *pstate, JsonFuncExpr *func) transformJsonPassingArgs(pstate, format, func->common->passing, &jsexpr->passing_values, &jsexpr->passing_names); - if (func->op != JSON_EXISTS_OP) + if (func->op != JSON_EXISTS_OP && func->op != JSON_TABLE_OP) jsexpr->on_empty = transformJsonBehavior(pstate, func->on_empty, JSON_BEHAVIOR_NULL); - jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, - func->op == JSON_EXISTS_OP ? - JSON_BEHAVIOR_FALSE : - JSON_BEHAVIOR_NULL); + if (func->op == JSON_EXISTS_OP) + jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, + JSON_BEHAVIOR_FALSE); + else if (func->op == JSON_TABLE_OP) + jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, + JSON_BEHAVIOR_EMPTY); + else + jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, + JSON_BEHAVIOR_NULL); return jsexpr; } @@ -4439,6 +4444,21 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) jsexpr->result_coercion->expr = NULL; } break; + + case JSON_TABLE_OP: + jsexpr->returning = makeNode(JsonReturning); + jsexpr->returning->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); + jsexpr->returning->typid = exprType(contextItemExpr); + jsexpr->returning->typmod = -1; + + if (jsexpr->returning->typid != JSONBOID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("JSON_TABLE() is not yet implemented for json type"), + errhint("Try casting the argument to jsonb"), + parser_errposition(pstate, func->location))); + + break; } if (exprType(contextItemExpr) != JSONBOID) |