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

Commit 1b6366f

Browse files
author
Nikita Glukhov
committed
Add JSON_TABLE
1 parent 3e7aef8 commit 1b6366f

29 files changed

+3706
-25
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

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

2927+
APP_JUMB(tablefunc->functype);
29272928
JumbleExpr(jstate, tablefunc->docexpr);
29282929
JumbleExpr(jstate, tablefunc->rowexpr);
29292930
JumbleExpr(jstate, (Node *) tablefunc->colexprs);
2931+
JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
29302932
}
29312933
break;
29322934
case T_TableSampleClause:

src/backend/commands/explain.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2925,7 +2925,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
29252925
break;
29262926
case T_TableFuncScan:
29272927
Assert(rte->rtekind == RTE_TABLEFUNC);
2928-
objectname = "xmltable";
2928+
objectname = rte->tablefunc ?
2929+
rte->tablefunc->functype == TFT_XMLTABLE ?
2930+
"xmltable" : "json_table" : NULL;
29292931
objecttag = "Table Function Name";
29302932
break;
29312933
case T_ValuesScan:

src/backend/executor/execExpr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,6 +2191,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
21912191
var->var.cb_arg = var;
21922192
var->estate = ExecInitExpr(argexpr, state->parent);
21932193
var->econtext = NULL;
2194+
var->mcxt = NULL;
21942195
var->evaluated = false;
21952196
var->value = (Datum) 0;
21962197
var->isnull = true;

src/backend/executor/execExprInterp.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4170,6 +4170,7 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
41704170

41714171
case JSON_BEHAVIOR_NULL:
41724172
case JSON_BEHAVIOR_UNKNOWN:
4173+
case JSON_BEHAVIOR_EMPTY:
41734174
*is_null = true;
41744175
return (Datum) 0;
41754176

@@ -4235,8 +4236,14 @@ EvalJsonPathVar(void *cxt, bool *isnull)
42354236

42364237
if (!ecxt->evaluated)
42374238
{
4239+
MemoryContext oldcxt = ecxt->mcxt ?
4240+
MemoryContextSwitchTo(ecxt->mcxt) : NULL;
4241+
42384242
ecxt->value = ExecEvalExpr(ecxt->estate, ecxt->econtext, &ecxt->isnull);
42394243
ecxt->evaluated = true;
4244+
4245+
if (oldcxt)
4246+
MemoryContextSwitchTo(oldcxt);
42404247
}
42414248

42424249
*isnull = ecxt->isnull;
@@ -4426,6 +4433,11 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44264433
*resnull = false;
44274434
break;
44284435

4436+
case IS_JSON_TABLE:
4437+
res = item;
4438+
*resnull = false;
4439+
break;
4440+
44294441
default:
44304442
elog(ERROR, "unrecognized SQL/JSON expression op %d",
44314443
jexpr->op);
@@ -4446,6 +4458,7 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44464458
}
44474459

44484460
if (jexpr->op != IS_JSON_EXISTS &&
4461+
jexpr->op != IS_JSON_TABLE &&
44494462
(!empty ? jexpr->op != IS_JSON_VALUE :
44504463
/* result is already coerced in DEFAULT behavior case */
44514464
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"
@@ -161,8 +162,9 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
161162
scanstate->ss.ps.qual =
162163
ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
163164

164-
/* Only XMLTABLE is supported currently */
165-
scanstate->routine = &XmlTableRoutine;
165+
/* Only XMLTABLE and JSON_TABLE are supported currently */
166+
scanstate->routine =
167+
tf->functype == TFT_XMLTABLE ? &XmlTableRoutine : &JsonbTableRoutine;
166168

167169
scanstate->perValueCxt =
168170
AllocSetContextCreate(CurrentMemoryContext,
@@ -365,14 +367,17 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
365367
routine->SetNamespace(tstate, ns_name, ns_uri);
366368
}
367369

368-
/* Install the row filter expression into the table builder context */
369-
value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
370-
if (isnull)
371-
ereport(ERROR,
372-
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
373-
errmsg("row filter expression must not be null")));
370+
if (routine->SetRowFilter)
371+
{
372+
/* Install the row filter expression into the table builder context */
373+
value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
374+
if (isnull)
375+
ereport(ERROR,
376+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
377+
errmsg("row filter expression must not be null")));
374378

375-
routine->SetRowFilter(tstate, TextDatumGetCString(value));
379+
routine->SetRowFilter(tstate, TextDatumGetCString(value));
380+
}
376381

377382
/*
378383
* 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
@@ -1288,6 +1288,7 @@ _copyTableFunc(const TableFunc *from)
12881288
{
12891289
TableFunc *newnode = makeNode(TableFunc);
12901290

1291+
COPY_SCALAR_FIELD(functype);
12911292
COPY_NODE_FIELD(ns_uris);
12921293
COPY_NODE_FIELD(ns_names);
12931294
COPY_NODE_FIELD(docexpr);
@@ -1298,7 +1299,9 @@ _copyTableFunc(const TableFunc *from)
12981299
COPY_NODE_FIELD(colcollations);
12991300
COPY_NODE_FIELD(colexprs);
13001301
COPY_NODE_FIELD(coldefexprs);
1302+
COPY_NODE_FIELD(colvalexprs);
13011303
COPY_BITMAPSET_FIELD(notnulls);
1304+
COPY_NODE_FIELD(plan);
13021305
COPY_SCALAR_FIELD(ordinalitycol);
13031306
COPY_LOCATION_FIELD(location);
13041307

@@ -2505,6 +2508,99 @@ _copyJsonArgument(const JsonArgument *from)
25052508
return newnode;
25062509
}
25072510

2511+
/*
2512+
* _copyJsonTable
2513+
*/
2514+
static JsonTable *
2515+
_copyJsonTable(const JsonTable *from)
2516+
{
2517+
JsonTable *newnode = makeNode(JsonTable);
2518+
2519+
COPY_NODE_FIELD(common);
2520+
COPY_NODE_FIELD(columns);
2521+
COPY_NODE_FIELD(plan);
2522+
COPY_NODE_FIELD(on_error);
2523+
COPY_NODE_FIELD(alias);
2524+
COPY_SCALAR_FIELD(location);
2525+
2526+
return newnode;
2527+
}
2528+
2529+
/*
2530+
* _copyJsonTableColumn
2531+
*/
2532+
static JsonTableColumn *
2533+
_copyJsonTableColumn(const JsonTableColumn *from)
2534+
{
2535+
JsonTableColumn *newnode = makeNode(JsonTableColumn);
2536+
2537+
COPY_SCALAR_FIELD(coltype);
2538+
COPY_STRING_FIELD(name);
2539+
COPY_NODE_FIELD(typename);
2540+
COPY_STRING_FIELD(pathspec);
2541+
COPY_STRING_FIELD(pathname);
2542+
COPY_SCALAR_FIELD(format);
2543+
COPY_SCALAR_FIELD(wrapper);
2544+
COPY_SCALAR_FIELD(omit_quotes);
2545+
COPY_NODE_FIELD(columns);
2546+
COPY_NODE_FIELD(on_empty);
2547+
COPY_NODE_FIELD(on_error);
2548+
COPY_SCALAR_FIELD(location);
2549+
2550+
return newnode;
2551+
}
2552+
2553+
/*
2554+
* _copyJsonTablePlan
2555+
*/
2556+
static JsonTablePlan *
2557+
_copyJsonTablePlan(const JsonTablePlan *from)
2558+
{
2559+
JsonTablePlan *newnode = makeNode(JsonTablePlan);
2560+
2561+
COPY_SCALAR_FIELD(plan_type);
2562+
COPY_SCALAR_FIELD(join_type);
2563+
COPY_STRING_FIELD(pathname);
2564+
COPY_NODE_FIELD(plan1);
2565+
COPY_NODE_FIELD(plan2);
2566+
COPY_SCALAR_FIELD(location);
2567+
2568+
return newnode;
2569+
}
2570+
2571+
/*
2572+
* _copyJsonTableParentNode
2573+
*/
2574+
static JsonTableParentNode *
2575+
_copyJsonTableParentNode(const JsonTableParentNode *from)
2576+
{
2577+
JsonTableParentNode *newnode = makeNode(JsonTableParentNode);
2578+
2579+
COPY_NODE_FIELD(path);
2580+
COPY_STRING_FIELD(name);
2581+
COPY_NODE_FIELD(child);
2582+
COPY_SCALAR_FIELD(outerJoin);
2583+
COPY_SCALAR_FIELD(colMin);
2584+
COPY_SCALAR_FIELD(colMax);
2585+
2586+
return newnode;
2587+
}
2588+
2589+
/*
2590+
* _copyJsonTableSiblingNode
2591+
*/
2592+
static JsonTableSiblingNode *
2593+
_copyJsonTableSiblingNode(const JsonTableSiblingNode *from)
2594+
{
2595+
JsonTableSiblingNode *newnode = makeNode(JsonTableSiblingNode);
2596+
2597+
COPY_NODE_FIELD(larg);
2598+
COPY_NODE_FIELD(rarg);
2599+
COPY_SCALAR_FIELD(cross);
2600+
2601+
return newnode;
2602+
}
2603+
25082604
/* ****************************************************************
25092605
* relation.h copy functions
25102606
*
@@ -5446,6 +5542,21 @@ copyObjectImpl(const void *from)
54465542
case T_JsonItemCoercions:
54475543
retval = _copyJsonItemCoercions(from);
54485544
break;
5545+
case T_JsonTable:
5546+
retval = _copyJsonTable(from);
5547+
break;
5548+
case T_JsonTableColumn:
5549+
retval = _copyJsonTableColumn(from);
5550+
break;
5551+
case T_JsonTablePlan:
5552+
retval = _copyJsonTablePlan(from);
5553+
break;
5554+
case T_JsonTableParentNode:
5555+
retval = _copyJsonTableParentNode(from);
5556+
break;
5557+
case T_JsonTableSiblingNode:
5558+
retval = _copyJsonTableSiblingNode(from);
5559+
break;
54495560

54505561
/*
54515562
* 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
{
@@ -3286,6 +3312,12 @@ equal(const void *a, const void *b)
32863312
case T_JsonItemCoercions:
32873313
retval = _equalJsonItemCoercions(a, b);
32883314
break;
3315+
case T_JsonTableParentNode:
3316+
retval = _equalJsonTableParentNode(a, b);
3317+
break;
3318+
case T_JsonTableSiblingNode:
3319+
retval = _equalJsonTableSiblingNode(a, b);
3320+
break;
32893321

32903322
/*
32913323
* 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

src/backend/nodes/nodeFuncs.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,6 +2291,8 @@ expression_tree_walker(Node *node,
22912291
return true;
22922292
if (walker(tf->coldefexprs, context))
22932293
return true;
2294+
if (walker(tf->colvalexprs, context))
2295+
return true;
22942296
}
22952297
break;
22962298
case T_JsonValueExpr:
@@ -3172,6 +3174,7 @@ expression_tree_mutator(Node *node,
31723174
MUTATE(newnode->rowexpr, tf->rowexpr, Node *);
31733175
MUTATE(newnode->colexprs, tf->colexprs, List *);
31743176
MUTATE(newnode->coldefexprs, tf->coldefexprs, List *);
3177+
MUTATE(newnode->colvalexprs, tf->colvalexprs, List *);
31753178
return (Node *) newnode;
31763179
}
31773180
break;
@@ -3993,6 +3996,30 @@ raw_expression_tree_walker(Node *node,
39933996
return true;
39943997
}
39953998
break;
3999+
case T_JsonTable:
4000+
{
4001+
JsonTable *jt = (JsonTable *) node;
4002+
4003+
if (walker(jt->common, context))
4004+
return true;
4005+
if (walker(jt->columns, context))
4006+
return true;
4007+
}
4008+
break;
4009+
case T_JsonTableColumn:
4010+
{
4011+
JsonTableColumn *jtc = (JsonTableColumn *) node;
4012+
4013+
if (walker(jtc->typename, context))
4014+
return true;
4015+
if (walker(jtc->on_empty, context))
4016+
return true;
4017+
if (walker(jtc->on_error, context))
4018+
return true;
4019+
if (jtc->coltype == JTC_NESTED && walker(jtc->columns, context))
4020+
return true;
4021+
}
4022+
break;
39964023
default:
39974024
elog(ERROR, "unrecognized node type: %d",
39984025
(int) nodeTag(node));

0 commit comments

Comments
 (0)