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

Commit 47c9ac9

Browse files
author
Nikita Glukhov
committed
Add JSON_TABLE
1 parent 6081f03 commit 47c9ac9

29 files changed

+3725
-105
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,9 +2947,11 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
29472947
{
29482948
TableFunc *tablefunc = (TableFunc *) node;
29492949

2950+
APP_JUMB(tablefunc->functype);
29502951
JumbleExpr(jstate, tablefunc->docexpr);
29512952
JumbleExpr(jstate, tablefunc->rowexpr);
29522953
JumbleExpr(jstate, (Node *) tablefunc->colexprs);
2954+
JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
29532955
}
29542956
break;
29552957
case T_TableSampleClause:

src/backend/commands/explain.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2707,7 +2707,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
27072707
break;
27082708
case T_TableFuncScan:
27092709
Assert(rte->rtekind == RTE_TABLEFUNC);
2710-
objectname = "xmltable";
2710+
objectname = rte->tablefunc ?
2711+
rte->tablefunc->functype == TFT_XMLTABLE ?
2712+
"xmltable" : "json_table" : NULL;
27112713
objecttag = "Table Function Name";
27122714
break;
27132715
case T_ValuesScan:

src/backend/executor/execExpr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,7 @@ ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
20862086
var->var.cb_arg = var;
20872087
var->estate = ExecInitExpr(argexpr, parent);
20882088
var->econtext = NULL;
2089+
var->mcxt = NULL;
20892090
var->evaluated = false;
20902091
var->value = (Datum) 0;
20912092
var->isnull = true;

src/backend/executor/execExprInterp.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3596,7 +3596,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
35963596
/*
35973597
* Evaluate a expression substituting specified value in its CaseTestExpr nodes.
35983598
*/
3599-
static Datum
3599+
Datum
36003600
ExecEvalExprPassingCaseValue(ExprState *estate, ExprContext *econtext,
36013601
bool *isnull,
36023602
Datum caseval_datum, bool caseval_isnull)
@@ -3656,6 +3656,7 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
36563656

36573657
case JSON_BEHAVIOR_NULL:
36583658
case JSON_BEHAVIOR_UNKNOWN:
3659+
case JSON_BEHAVIOR_EMPTY:
36593660
*is_null = true;
36603661
return (Datum) 0;
36613662

@@ -3716,8 +3717,14 @@ EvalJsonPathVar(void *cxt, bool *isnull)
37163717

37173718
if (!ecxt->evaluated)
37183719
{
3720+
MemoryContext oldcxt = ecxt->mcxt ?
3721+
MemoryContextSwitchTo(ecxt->mcxt) : NULL;
3722+
37193723
ecxt->value = ExecEvalExpr(ecxt->estate, ecxt->econtext, &ecxt->isnull);
37203724
ecxt->evaluated = true;
3725+
3726+
if (oldcxt)
3727+
MemoryContextSwitchTo(oldcxt);
37213728
}
37223729

37233730
*isnull = ecxt->isnull;
@@ -3984,6 +3991,11 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
39843991
*op->resnull = false;
39853992
break;
39863993

3994+
case IS_JSON_TABLE:
3995+
res = item;
3996+
*op->resnull = false;
3997+
break;
3998+
39873999
default:
39884000
elog(ERROR, "unrecognized SQL/JSON expression op %d",
39894001
jexpr->op);
@@ -4004,6 +4016,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
40044016
}
40054017

40064018
if (jexpr->op != IS_JSON_EXISTS &&
4019+
jexpr->op != IS_JSON_TABLE &&
40074020
(!empty ? jexpr->op != IS_JSON_VALUE :
40084021
/* result is already coerced in DEFAULT behavior case */
40094022
jexpr->on_empty.btype != JSON_BEHAVIOR_DEFAULT))

src/backend/executor/nodeTableFuncscan.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "executor/tablefunc.h"
2929
#include "miscadmin.h"
3030
#include "utils/builtins.h"
31+
#include "utils/jsonpath.h"
3132
#include "utils/lsyscache.h"
3233
#include "utils/memutils.h"
3334
#include "utils/xml.h"
@@ -167,8 +168,9 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
167168
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
168169
ExecAssignScanProjectionInfo(&scanstate->ss);
169170

170-
/* Only XMLTABLE is supported currently */
171-
scanstate->routine = &XmlTableRoutine;
171+
/* Only XMLTABLE and JSON_TABLE are supported currently */
172+
scanstate->routine =
173+
tf->functype == TFT_XMLTABLE ? &XmlTableRoutine : &JsonbTableRoutine;
172174

173175
scanstate->perValueCxt =
174176
AllocSetContextCreate(CurrentMemoryContext,
@@ -371,14 +373,17 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
371373
routine->SetNamespace(tstate, ns_name, ns_uri);
372374
}
373375

374-
/* Install the row filter expression into the table builder context */
375-
value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
376-
if (isnull)
377-
ereport(ERROR,
378-
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
379-
errmsg("row filter expression must not be null")));
376+
if (routine->SetRowFilter)
377+
{
378+
/* Install the row filter expression into the table builder context */
379+
value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
380+
if (isnull)
381+
ereport(ERROR,
382+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
383+
errmsg("row filter expression must not be null")));
380384

381-
routine->SetRowFilter(tstate, TextDatumGetCString(value));
385+
routine->SetRowFilter(tstate, TextDatumGetCString(value));
386+
}
382387

383388
/*
384389
* Install the column filter expressions into the table builder context.

src/backend/nodes/copyfuncs.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,7 @@ _copyTableFunc(const TableFunc *from)
12241224
{
12251225
TableFunc *newnode = makeNode(TableFunc);
12261226

1227+
COPY_SCALAR_FIELD(functype);
12271228
COPY_NODE_FIELD(ns_uris);
12281229
COPY_NODE_FIELD(ns_names);
12291230
COPY_NODE_FIELD(docexpr);
@@ -1234,7 +1235,9 @@ _copyTableFunc(const TableFunc *from)
12341235
COPY_NODE_FIELD(colcollations);
12351236
COPY_NODE_FIELD(colexprs);
12361237
COPY_NODE_FIELD(coldefexprs);
1238+
COPY_NODE_FIELD(colvalexprs);
12371239
COPY_BITMAPSET_FIELD(notnulls);
1240+
COPY_NODE_FIELD(plan);
12381241
COPY_SCALAR_FIELD(ordinalitycol);
12391242
COPY_LOCATION_FIELD(location);
12401243

@@ -2404,6 +2407,99 @@ _copyJsonArgument(const JsonArgument *from)
24042407
return newnode;
24052408
}
24062409

2410+
/*
2411+
* _copyJsonTable
2412+
*/
2413+
static JsonTable *
2414+
_copyJsonTable(const JsonTable *from)
2415+
{
2416+
JsonTable *newnode = makeNode(JsonTable);
2417+
2418+
COPY_NODE_FIELD(common);
2419+
COPY_NODE_FIELD(columns);
2420+
COPY_NODE_FIELD(plan);
2421+
COPY_NODE_FIELD(on_error);
2422+
COPY_NODE_FIELD(alias);
2423+
COPY_SCALAR_FIELD(location);
2424+
2425+
return newnode;
2426+
}
2427+
2428+
/*
2429+
* _copyJsonTableColumn
2430+
*/
2431+
static JsonTableColumn *
2432+
_copyJsonTableColumn(const JsonTableColumn *from)
2433+
{
2434+
JsonTableColumn *newnode = makeNode(JsonTableColumn);
2435+
2436+
COPY_SCALAR_FIELD(coltype);
2437+
COPY_STRING_FIELD(name);
2438+
COPY_NODE_FIELD(typename);
2439+
COPY_STRING_FIELD(pathspec);
2440+
COPY_STRING_FIELD(pathname);
2441+
COPY_SCALAR_FIELD(format);
2442+
COPY_SCALAR_FIELD(wrapper);
2443+
COPY_SCALAR_FIELD(omit_quotes);
2444+
COPY_NODE_FIELD(columns);
2445+
COPY_NODE_FIELD(on_empty);
2446+
COPY_NODE_FIELD(on_error);
2447+
COPY_SCALAR_FIELD(location);
2448+
2449+
return newnode;
2450+
}
2451+
2452+
/*
2453+
* _copyJsonTablePlan
2454+
*/
2455+
static JsonTablePlan *
2456+
_copyJsonTablePlan(const JsonTablePlan *from)
2457+
{
2458+
JsonTablePlan *newnode = makeNode(JsonTablePlan);
2459+
2460+
COPY_SCALAR_FIELD(plan_type);
2461+
COPY_SCALAR_FIELD(join_type);
2462+
COPY_STRING_FIELD(pathname);
2463+
COPY_NODE_FIELD(plan1);
2464+
COPY_NODE_FIELD(plan2);
2465+
COPY_SCALAR_FIELD(location);
2466+
2467+
return newnode;
2468+
}
2469+
2470+
/*
2471+
* _copyJsonTableParentNode
2472+
*/
2473+
static JsonTableParentNode *
2474+
_copyJsonTableParentNode(const JsonTableParentNode *from)
2475+
{
2476+
JsonTableParentNode *newnode = makeNode(JsonTableParentNode);
2477+
2478+
COPY_NODE_FIELD(path);
2479+
COPY_STRING_FIELD(name);
2480+
COPY_NODE_FIELD(child);
2481+
COPY_SCALAR_FIELD(outerJoin);
2482+
COPY_SCALAR_FIELD(colMin);
2483+
COPY_SCALAR_FIELD(colMax);
2484+
2485+
return newnode;
2486+
}
2487+
2488+
/*
2489+
* _copyJsonTableSiblingNode
2490+
*/
2491+
static JsonTableSiblingNode *
2492+
_copyJsonTableSiblingNode(const JsonTableSiblingNode *from)
2493+
{
2494+
JsonTableSiblingNode *newnode = makeNode(JsonTableSiblingNode);
2495+
2496+
COPY_NODE_FIELD(larg);
2497+
COPY_NODE_FIELD(rarg);
2498+
COPY_SCALAR_FIELD(cross);
2499+
2500+
return newnode;
2501+
}
2502+
24072503
/* ****************************************************************
24082504
* relation.h copy functions
24092505
*
@@ -5304,6 +5400,21 @@ copyObjectImpl(const void *from)
53045400
case T_JsonArgument:
53055401
retval = _copyJsonArgument(from);
53065402
break;
5403+
case T_JsonTable:
5404+
retval = _copyJsonTable(from);
5405+
break;
5406+
case T_JsonTableColumn:
5407+
retval = _copyJsonTableColumn(from);
5408+
break;
5409+
case T_JsonTablePlan:
5410+
retval = _copyJsonTablePlan(from);
5411+
break;
5412+
case T_JsonTableParentNode:
5413+
retval = _copyJsonTableParentNode(from);
5414+
break;
5415+
case T_JsonTableSiblingNode:
5416+
retval = _copyJsonTableSiblingNode(from);
5417+
break;
53075418

53085419
/*
53095420
* RELATION NODES

src/backend/nodes/equalfuncs.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ _equalRangeVar(const RangeVar *a, const RangeVar *b)
119119
static bool
120120
_equalTableFunc(const TableFunc *a, const TableFunc *b)
121121
{
122+
COMPARE_SCALAR_FIELD(functype);
122123
COMPARE_NODE_FIELD(ns_uris);
123124
COMPARE_NODE_FIELD(ns_names);
124125
COMPARE_NODE_FIELD(docexpr);
@@ -129,13 +130,38 @@ _equalTableFunc(const TableFunc *a, const TableFunc *b)
129130
COMPARE_NODE_FIELD(colcollations);
130131
COMPARE_NODE_FIELD(colexprs);
131132
COMPARE_NODE_FIELD(coldefexprs);
133+
COMPARE_NODE_FIELD(colvalexprs);
132134
COMPARE_BITMAPSET_FIELD(notnulls);
135+
COMPARE_NODE_FIELD(plan);
133136
COMPARE_SCALAR_FIELD(ordinalitycol);
134137
COMPARE_LOCATION_FIELD(location);
135138

136139
return true;
137140
}
138141

142+
static bool
143+
_equalJsonTableParentNode(const JsonTableParentNode *a, const JsonTableParentNode *b)
144+
{
145+
COMPARE_NODE_FIELD(path);
146+
COMPARE_STRING_FIELD(name);
147+
COMPARE_NODE_FIELD(child);
148+
COMPARE_SCALAR_FIELD(outerJoin);
149+
COMPARE_SCALAR_FIELD(colMin);
150+
COMPARE_SCALAR_FIELD(colMax);
151+
152+
return true;
153+
}
154+
155+
static bool
156+
_equalJsonTableSiblingNode(const JsonTableSiblingNode *a, const JsonTableSiblingNode *b)
157+
{
158+
COMPARE_NODE_FIELD(larg);
159+
COMPARE_NODE_FIELD(rarg);
160+
COMPARE_SCALAR_FIELD(cross);
161+
162+
return true;
163+
}
164+
139165
static bool
140166
_equalIntoClause(const IntoClause *a, const IntoClause *b)
141167
{
@@ -3223,6 +3249,12 @@ equal(const void *a, const void *b)
32233249
case T_JsonExpr:
32243250
retval = _equalJsonExpr(a, b);
32253251
break;
3252+
case T_JsonTableParentNode:
3253+
retval = _equalJsonTableParentNode(a, b);
3254+
break;
3255+
case T_JsonTableSiblingNode:
3256+
retval = _equalJsonTableSiblingNode(a, b);
3257+
break;
32263258

32273259
/*
32283260
* RELATION NODES

src/backend/nodes/makefuncs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,25 @@ makeJsonBehavior(JsonBehaviorType type, Node *default_expr)
643643
return behavior;
644644
}
645645

646+
/*
647+
* makeJsonTableJoinedPlan -
648+
* creates a joined JsonTablePlan node
649+
*/
650+
Node *
651+
makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2,
652+
int location)
653+
{
654+
JsonTablePlan *n = makeNode(JsonTablePlan);
655+
656+
n->plan_type = JSTP_JOINED;
657+
n->join_type = type;
658+
n->plan1 = castNode(JsonTablePlan, plan1);
659+
n->plan2 = castNode(JsonTablePlan, plan2);
660+
n->location = location;
661+
662+
return (Node *) n;
663+
}
664+
646665
/*
647666
* makeJsonEncoding -
648667
* converts JSON encoding name to enum JsonEncoding

0 commit comments

Comments
 (0)