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

Commit 0e439b1

Browse files
author
Nikita Glukhov
committed
Add JSON_TABLE
1 parent f5208cd commit 0e439b1

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
@@ -2922,9 +2922,11 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
29222922
{
29232923
TableFunc *tablefunc = (TableFunc *) node;
29242924

2925+
APP_JUMB(tablefunc->functype);
29252926
JumbleExpr(jstate, tablefunc->docexpr);
29262927
JumbleExpr(jstate, tablefunc->rowexpr);
29272928
JumbleExpr(jstate, (Node *) tablefunc->colexprs);
2929+
JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
29282930
}
29292931
break;
29302932
case T_TableSampleClause:

src/backend/commands/explain.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2752,7 +2752,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
27522752
break;
27532753
case T_TableFuncScan:
27542754
Assert(rte->rtekind == RTE_TABLEFUNC);
2755-
objectname = "xmltable";
2755+
objectname = rte->tablefunc ?
2756+
rte->tablefunc->functype == TFT_XMLTABLE ?
2757+
"xmltable" : "json_table" : NULL;
27562758
objecttag = "Table Function Name";
27572759
break;
27582760
case T_ValuesScan:

src/backend/executor/execExpr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,7 @@ ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
20932093
var->var.cb_arg = var;
20942094
var->estate = ExecInitExpr(argexpr, parent);
20952095
var->econtext = NULL;
2096+
var->mcxt = NULL;
20962097
var->evaluated = false;
20972098
var->value = (Datum) 0;
20982099
var->isnull = true;

src/backend/executor/execExprInterp.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3645,7 +3645,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
36453645
/*
36463646
* Evaluate a expression substituting specified value in its CaseTestExpr nodes.
36473647
*/
3648-
static Datum
3648+
Datum
36493649
ExecEvalExprPassingCaseValue(ExprState *estate, ExprContext *econtext,
36503650
bool *isnull,
36513651
Datum caseval_datum, bool caseval_isnull)
@@ -3705,6 +3705,7 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
37053705

37063706
case JSON_BEHAVIOR_NULL:
37073707
case JSON_BEHAVIOR_UNKNOWN:
3708+
case JSON_BEHAVIOR_EMPTY:
37083709
*is_null = true;
37093710
return (Datum) 0;
37103711

@@ -3765,8 +3766,14 @@ EvalJsonPathVar(void *cxt, bool *isnull)
37653766

37663767
if (!ecxt->evaluated)
37673768
{
3769+
MemoryContext oldcxt = ecxt->mcxt ?
3770+
MemoryContextSwitchTo(ecxt->mcxt) : NULL;
3771+
37683772
ecxt->value = ExecEvalExpr(ecxt->estate, ecxt->econtext, &ecxt->isnull);
37693773
ecxt->evaluated = true;
3774+
3775+
if (oldcxt)
3776+
MemoryContextSwitchTo(oldcxt);
37703777
}
37713778

37723779
*isnull = ecxt->isnull;
@@ -4033,6 +4040,11 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
40334040
*op->resnull = false;
40344041
break;
40354042

4043+
case IS_JSON_TABLE:
4044+
res = item;
4045+
*op->resnull = false;
4046+
break;
4047+
40364048
default:
40374049
elog(ERROR, "unrecognized SQL/JSON expression op %d",
40384050
jexpr->op);
@@ -4053,6 +4065,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
40534065
}
40544066

40554067
if (jexpr->op != IS_JSON_EXISTS &&
4068+
jexpr->op != IS_JSON_TABLE &&
40564069
(!empty ? jexpr->op != IS_JSON_VALUE :
40574070
/* result is already coerced in DEFAULT behavior case */
40584071
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

@@ -2403,6 +2406,99 @@ _copyJsonArgument(const JsonArgument *from)
24032406
return newnode;
24042407
}
24052408

2409+
/*
2410+
* _copyJsonTable
2411+
*/
2412+
static JsonTable *
2413+
_copyJsonTable(const JsonTable *from)
2414+
{
2415+
JsonTable *newnode = makeNode(JsonTable);
2416+
2417+
COPY_NODE_FIELD(common);
2418+
COPY_NODE_FIELD(columns);
2419+
COPY_NODE_FIELD(plan);
2420+
COPY_NODE_FIELD(on_error);
2421+
COPY_NODE_FIELD(alias);
2422+
COPY_SCALAR_FIELD(location);
2423+
2424+
return newnode;
2425+
}
2426+
2427+
/*
2428+
* _copyJsonTableColumn
2429+
*/
2430+
static JsonTableColumn *
2431+
_copyJsonTableColumn(const JsonTableColumn *from)
2432+
{
2433+
JsonTableColumn *newnode = makeNode(JsonTableColumn);
2434+
2435+
COPY_SCALAR_FIELD(coltype);
2436+
COPY_STRING_FIELD(name);
2437+
COPY_NODE_FIELD(typename);
2438+
COPY_STRING_FIELD(pathspec);
2439+
COPY_STRING_FIELD(pathname);
2440+
COPY_SCALAR_FIELD(format);
2441+
COPY_SCALAR_FIELD(wrapper);
2442+
COPY_SCALAR_FIELD(omit_quotes);
2443+
COPY_NODE_FIELD(columns);
2444+
COPY_NODE_FIELD(on_empty);
2445+
COPY_NODE_FIELD(on_error);
2446+
COPY_SCALAR_FIELD(location);
2447+
2448+
return newnode;
2449+
}
2450+
2451+
/*
2452+
* _copyJsonTablePlan
2453+
*/
2454+
static JsonTablePlan *
2455+
_copyJsonTablePlan(const JsonTablePlan *from)
2456+
{
2457+
JsonTablePlan *newnode = makeNode(JsonTablePlan);
2458+
2459+
COPY_SCALAR_FIELD(plan_type);
2460+
COPY_SCALAR_FIELD(join_type);
2461+
COPY_STRING_FIELD(pathname);
2462+
COPY_NODE_FIELD(plan1);
2463+
COPY_NODE_FIELD(plan2);
2464+
COPY_SCALAR_FIELD(location);
2465+
2466+
return newnode;
2467+
}
2468+
2469+
/*
2470+
* _copyJsonTableParentNode
2471+
*/
2472+
static JsonTableParentNode *
2473+
_copyJsonTableParentNode(const JsonTableParentNode *from)
2474+
{
2475+
JsonTableParentNode *newnode = makeNode(JsonTableParentNode);
2476+
2477+
COPY_NODE_FIELD(path);
2478+
COPY_STRING_FIELD(name);
2479+
COPY_NODE_FIELD(child);
2480+
COPY_SCALAR_FIELD(outerJoin);
2481+
COPY_SCALAR_FIELD(colMin);
2482+
COPY_SCALAR_FIELD(colMax);
2483+
2484+
return newnode;
2485+
}
2486+
2487+
/*
2488+
* _copyJsonTableSiblingNode
2489+
*/
2490+
static JsonTableSiblingNode *
2491+
_copyJsonTableSiblingNode(const JsonTableSiblingNode *from)
2492+
{
2493+
JsonTableSiblingNode *newnode = makeNode(JsonTableSiblingNode);
2494+
2495+
COPY_NODE_FIELD(larg);
2496+
COPY_NODE_FIELD(rarg);
2497+
COPY_SCALAR_FIELD(cross);
2498+
2499+
return newnode;
2500+
}
2501+
24062502
/* ****************************************************************
24072503
* relation.h copy functions
24082504
*
@@ -5320,6 +5416,21 @@ copyObjectImpl(const void *from)
53205416
case T_JsonArgument:
53215417
retval = _copyJsonArgument(from);
53225418
break;
5419+
case T_JsonTable:
5420+
retval = _copyJsonTable(from);
5421+
break;
5422+
case T_JsonTableColumn:
5423+
retval = _copyJsonTableColumn(from);
5424+
break;
5425+
case T_JsonTablePlan:
5426+
retval = _copyJsonTablePlan(from);
5427+
break;
5428+
case T_JsonTableParentNode:
5429+
retval = _copyJsonTableParentNode(from);
5430+
break;
5431+
case T_JsonTableSiblingNode:
5432+
retval = _copyJsonTableSiblingNode(from);
5433+
break;
53235434

53245435
/*
53255436
* 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
{
@@ -3235,6 +3261,12 @@ equal(const void *a, const void *b)
32353261
case T_JsonExpr:
32363262
retval = _equalJsonExpr(a, b);
32373263
break;
3264+
case T_JsonTableParentNode:
3265+
retval = _equalJsonTableParentNode(a, b);
3266+
break;
3267+
case T_JsonTableSiblingNode:
3268+
retval = _equalJsonTableSiblingNode(a, b);
3269+
break;
32383270

32393271
/*
32403272
* RELATION NODES

src/backend/nodes/makefuncs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,25 @@ makeJsonBehavior(JsonBehaviorType type, Node *default_expr)
660660
return behavior;
661661
}
662662

663+
/*
664+
* makeJsonTableJoinedPlan -
665+
* creates a joined JsonTablePlan node
666+
*/
667+
Node *
668+
makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2,
669+
int location)
670+
{
671+
JsonTablePlan *n = makeNode(JsonTablePlan);
672+
673+
n->plan_type = JSTP_JOINED;
674+
n->join_type = type;
675+
n->plan1 = castNode(JsonTablePlan, plan1);
676+
n->plan2 = castNode(JsonTablePlan, plan2);
677+
n->location = location;
678+
679+
return (Node *) n;
680+
}
681+
663682
/*
664683
* makeJsonEncoding -
665684
* converts JSON encoding name to enum JsonEncoding

0 commit comments

Comments
 (0)