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

Commit eced0ca

Browse files
author
Nikita Glukhov
committed
Add JSON_TABLE
1 parent fc598ea commit eced0ca

29 files changed

+3721
-26
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

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

3006+
APP_JUMB(tablefunc->functype);
30063007
JumbleExpr(jstate, tablefunc->docexpr);
30073008
JumbleExpr(jstate, tablefunc->rowexpr);
30083009
JumbleExpr(jstate, (Node *) tablefunc->colexprs);
3010+
JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
30093011
}
30103012
break;
30113013
case T_TableSampleClause:

src/backend/commands/explain.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3097,7 +3097,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
30973097
break;
30983098
case T_TableFuncScan:
30993099
Assert(rte->rtekind == RTE_TABLEFUNC);
3100-
objectname = "xmltable";
3100+
objectname = rte->tablefunc ?
3101+
rte->tablefunc->functype == TFT_XMLTABLE ?
3102+
"xmltable" : "json_table" : NULL;
31013103
objecttag = "Table Function Name";
31023104
break;
31033105
case T_ValuesScan:

src/backend/executor/execExpr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2181,6 +2181,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
21812181
var->typmod = exprTypmod((Node *) argexpr);
21822182
var->estate = ExecInitExpr(argexpr, state->parent);
21832183
var->econtext = NULL;
2184+
var->mcxt = NULL;
21842185
var->evaluated = false;
21852186
var->value = (Datum) 0;
21862187
var->isnull = true;

src/backend/executor/execExprInterp.c

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

41884188
case JSON_BEHAVIOR_NULL:
41894189
case JSON_BEHAVIOR_UNKNOWN:
4190+
case JSON_BEHAVIOR_EMPTY:
41904191
*is_null = true;
41914192
return (Datum) 0;
41924193

@@ -4286,8 +4287,14 @@ EvalJsonPathVar(void *cxt, bool isJsonb, char *varName, int varNameLen,
42864287

42874288
if (!var->evaluated)
42884289
{
4290+
MemoryContext oldcxt = var->mcxt ?
4291+
MemoryContextSwitchTo(var->mcxt) : NULL;
4292+
42894293
var->value = ExecEvalExpr(var->estate, var->econtext, &var->isnull);
42904294
var->evaluated = true;
4295+
4296+
if (oldcxt)
4297+
MemoryContextSwitchTo(oldcxt);
42914298
}
42924299

42934300
if (var->isnull)
@@ -4584,6 +4591,10 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
45844591
return BoolGetDatum(res);
45854592
}
45864593

4594+
case IS_JSON_TABLE:
4595+
*resnull = false;
4596+
return item;
4597+
45874598
default:
45884599
elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
45894600
return (Datum) 0;

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"
@@ -162,8 +163,9 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
162163
scanstate->ss.ps.qual =
163164
ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
164165

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

168170
scanstate->perTableCxt =
169171
AllocSetContextCreate(CurrentMemoryContext,
@@ -384,14 +386,17 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
384386
routine->SetNamespace(tstate, ns_name, ns_uri);
385387
}
386388

387-
/* Install the row filter expression into the table builder context */
388-
value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
389-
if (isnull)
390-
ereport(ERROR,
391-
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
392-
errmsg("row filter expression must not be null")));
389+
if (routine->SetRowFilter)
390+
{
391+
/* Install the row filter expression into the table builder context */
392+
value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
393+
if (isnull)
394+
ereport(ERROR,
395+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
396+
errmsg("row filter expression must not be null")));
393397

394-
routine->SetRowFilter(tstate, TextDatumGetCString(value));
398+
routine->SetRowFilter(tstate, TextDatumGetCString(value));
399+
}
395400

396401
/*
397402
* 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
@@ -1302,6 +1302,7 @@ _copyTableFunc(const TableFunc *from)
13021302
{
13031303
TableFunc *newnode = makeNode(TableFunc);
13041304

1305+
COPY_SCALAR_FIELD(functype);
13051306
COPY_NODE_FIELD(ns_uris);
13061307
COPY_NODE_FIELD(ns_names);
13071308
COPY_NODE_FIELD(docexpr);
@@ -1312,7 +1313,9 @@ _copyTableFunc(const TableFunc *from)
13121313
COPY_NODE_FIELD(colcollations);
13131314
COPY_NODE_FIELD(colexprs);
13141315
COPY_NODE_FIELD(coldefexprs);
1316+
COPY_NODE_FIELD(colvalexprs);
13151317
COPY_BITMAPSET_FIELD(notnulls);
1318+
COPY_NODE_FIELD(plan);
13161319
COPY_SCALAR_FIELD(ordinalitycol);
13171320
COPY_LOCATION_FIELD(location);
13181321

@@ -2520,6 +2523,99 @@ _copyJsonArgument(const JsonArgument *from)
25202523
return newnode;
25212524
}
25222525

2526+
/*
2527+
* _copyJsonTable
2528+
*/
2529+
static JsonTable *
2530+
_copyJsonTable(const JsonTable *from)
2531+
{
2532+
JsonTable *newnode = makeNode(JsonTable);
2533+
2534+
COPY_NODE_FIELD(common);
2535+
COPY_NODE_FIELD(columns);
2536+
COPY_NODE_FIELD(plan);
2537+
COPY_NODE_FIELD(on_error);
2538+
COPY_NODE_FIELD(alias);
2539+
COPY_SCALAR_FIELD(location);
2540+
2541+
return newnode;
2542+
}
2543+
2544+
/*
2545+
* _copyJsonTableColumn
2546+
*/
2547+
static JsonTableColumn *
2548+
_copyJsonTableColumn(const JsonTableColumn *from)
2549+
{
2550+
JsonTableColumn *newnode = makeNode(JsonTableColumn);
2551+
2552+
COPY_SCALAR_FIELD(coltype);
2553+
COPY_STRING_FIELD(name);
2554+
COPY_NODE_FIELD(typeName);
2555+
COPY_STRING_FIELD(pathspec);
2556+
COPY_STRING_FIELD(pathname);
2557+
COPY_SCALAR_FIELD(format);
2558+
COPY_SCALAR_FIELD(wrapper);
2559+
COPY_SCALAR_FIELD(omit_quotes);
2560+
COPY_NODE_FIELD(columns);
2561+
COPY_NODE_FIELD(on_empty);
2562+
COPY_NODE_FIELD(on_error);
2563+
COPY_SCALAR_FIELD(location);
2564+
2565+
return newnode;
2566+
}
2567+
2568+
/*
2569+
* _copyJsonTablePlan
2570+
*/
2571+
static JsonTablePlan *
2572+
_copyJsonTablePlan(const JsonTablePlan *from)
2573+
{
2574+
JsonTablePlan *newnode = makeNode(JsonTablePlan);
2575+
2576+
COPY_SCALAR_FIELD(plan_type);
2577+
COPY_SCALAR_FIELD(join_type);
2578+
COPY_STRING_FIELD(pathname);
2579+
COPY_NODE_FIELD(plan1);
2580+
COPY_NODE_FIELD(plan2);
2581+
COPY_SCALAR_FIELD(location);
2582+
2583+
return newnode;
2584+
}
2585+
2586+
/*
2587+
* _copyJsonTableParentNode
2588+
*/
2589+
static JsonTableParentNode *
2590+
_copyJsonTableParentNode(const JsonTableParentNode *from)
2591+
{
2592+
JsonTableParentNode *newnode = makeNode(JsonTableParentNode);
2593+
2594+
COPY_NODE_FIELD(path);
2595+
COPY_STRING_FIELD(name);
2596+
COPY_NODE_FIELD(child);
2597+
COPY_SCALAR_FIELD(outerJoin);
2598+
COPY_SCALAR_FIELD(colMin);
2599+
COPY_SCALAR_FIELD(colMax);
2600+
2601+
return newnode;
2602+
}
2603+
2604+
/*
2605+
* _copyJsonTableSiblingNode
2606+
*/
2607+
static JsonTableSiblingNode *
2608+
_copyJsonTableSiblingNode(const JsonTableSiblingNode *from)
2609+
{
2610+
JsonTableSiblingNode *newnode = makeNode(JsonTableSiblingNode);
2611+
2612+
COPY_NODE_FIELD(larg);
2613+
COPY_NODE_FIELD(rarg);
2614+
COPY_SCALAR_FIELD(cross);
2615+
2616+
return newnode;
2617+
}
2618+
25232619
/* ****************************************************************
25242620
* pathnodes.h copy functions
25252621
*
@@ -5475,6 +5571,21 @@ copyObjectImpl(const void *from)
54755571
case T_JsonItemCoercions:
54765572
retval = _copyJsonItemCoercions(from);
54775573
break;
5574+
case T_JsonTable:
5575+
retval = _copyJsonTable(from);
5576+
break;
5577+
case T_JsonTableColumn:
5578+
retval = _copyJsonTableColumn(from);
5579+
break;
5580+
case T_JsonTablePlan:
5581+
retval = _copyJsonTablePlan(from);
5582+
break;
5583+
case T_JsonTableParentNode:
5584+
retval = _copyJsonTableParentNode(from);
5585+
break;
5586+
case T_JsonTableSiblingNode:
5587+
retval = _copyJsonTableSiblingNode(from);
5588+
break;
54785589

54795590
/*
54805591
* RELATION NODES

src/backend/nodes/equalfuncs.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ _equalRangeVar(const RangeVar *a, const RangeVar *b)
120120
static bool
121121
_equalTableFunc(const TableFunc *a, const TableFunc *b)
122122
{
123+
COMPARE_SCALAR_FIELD(functype);
123124
COMPARE_NODE_FIELD(ns_uris);
124125
COMPARE_NODE_FIELD(ns_names);
125126
COMPARE_NODE_FIELD(docexpr);
@@ -130,13 +131,38 @@ _equalTableFunc(const TableFunc *a, const TableFunc *b)
130131
COMPARE_NODE_FIELD(colcollations);
131132
COMPARE_NODE_FIELD(colexprs);
132133
COMPARE_NODE_FIELD(coldefexprs);
134+
COMPARE_NODE_FIELD(colvalexprs);
133135
COMPARE_BITMAPSET_FIELD(notnulls);
136+
COMPARE_NODE_FIELD(plan);
134137
COMPARE_SCALAR_FIELD(ordinalitycol);
135138
COMPARE_LOCATION_FIELD(location);
136139

137140
return true;
138141
}
139142

143+
static bool
144+
_equalJsonTableParentNode(const JsonTableParentNode *a, const JsonTableParentNode *b)
145+
{
146+
COMPARE_NODE_FIELD(path);
147+
COMPARE_STRING_FIELD(name);
148+
COMPARE_NODE_FIELD(child);
149+
COMPARE_SCALAR_FIELD(outerJoin);
150+
COMPARE_SCALAR_FIELD(colMin);
151+
COMPARE_SCALAR_FIELD(colMax);
152+
153+
return true;
154+
}
155+
156+
static bool
157+
_equalJsonTableSiblingNode(const JsonTableSiblingNode *a, const JsonTableSiblingNode *b)
158+
{
159+
COMPARE_NODE_FIELD(larg);
160+
COMPARE_NODE_FIELD(rarg);
161+
COMPARE_SCALAR_FIELD(cross);
162+
163+
return true;
164+
}
165+
140166
static bool
141167
_equalIntoClause(const IntoClause *a, const IntoClause *b)
142168
{
@@ -3301,6 +3327,12 @@ equal(const void *a, const void *b)
33013327
case T_JsonItemCoercions:
33023328
retval = _equalJsonItemCoercions(a, b);
33033329
break;
3330+
case T_JsonTableParentNode:
3331+
retval = _equalJsonTableParentNode(a, b);
3332+
break;
3333+
case T_JsonTableSiblingNode:
3334+
retval = _equalJsonTableSiblingNode(a, b);
3335+
break;
33043336

33053337
/*
33063338
* RELATION NODES

src/backend/nodes/makefuncs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,25 @@ makeJsonBehavior(JsonBehaviorType type, Node *default_expr)
794794
return behavior;
795795
}
796796

797+
/*
798+
* makeJsonTableJoinedPlan -
799+
* creates a joined JsonTablePlan node
800+
*/
801+
Node *
802+
makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2,
803+
int location)
804+
{
805+
JsonTablePlan *n = makeNode(JsonTablePlan);
806+
807+
n->plan_type = JSTP_JOINED;
808+
n->join_type = type;
809+
n->plan1 = castNode(JsonTablePlan, plan1);
810+
n->plan2 = castNode(JsonTablePlan, plan2);
811+
n->location = location;
812+
813+
return (Node *) n;
814+
}
815+
797816
/*
798817
* makeJsonEncoding -
799818
* 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
@@ -2309,6 +2309,8 @@ expression_tree_walker(Node *node,
23092309
return true;
23102310
if (walker(tf->coldefexprs, context))
23112311
return true;
2312+
if (walker(tf->colvalexprs, context))
2313+
return true;
23122314
}
23132315
break;
23142316
case T_JsonValueExpr:
@@ -3211,6 +3213,7 @@ expression_tree_mutator(Node *node,
32113213
MUTATE(newnode->rowexpr, tf->rowexpr, Node *);
32123214
MUTATE(newnode->colexprs, tf->colexprs, List *);
32133215
MUTATE(newnode->coldefexprs, tf->coldefexprs, List *);
3216+
MUTATE(newnode->colvalexprs, tf->colvalexprs, List *);
32143217
return (Node *) newnode;
32153218
}
32163219
break;
@@ -4033,6 +4036,30 @@ raw_expression_tree_walker(Node *node,
40334036
return true;
40344037
}
40354038
break;
4039+
case T_JsonTable:
4040+
{
4041+
JsonTable *jt = (JsonTable *) node;
4042+
4043+
if (walker(jt->common, context))
4044+
return true;
4045+
if (walker(jt->columns, context))
4046+
return true;
4047+
}
4048+
break;
4049+
case T_JsonTableColumn:
4050+
{
4051+
JsonTableColumn *jtc = (JsonTableColumn *) node;
4052+
4053+
if (walker(jtc->typeName, context))
4054+
return true;
4055+
if (walker(jtc->on_empty, context))
4056+
return true;
4057+
if (walker(jtc->on_error, context))
4058+
return true;
4059+
if (jtc->coltype == JTC_NESTED && walker(jtc->columns, context))
4060+
return true;
4061+
}
4062+
break;
40364063
default:
40374064
elog(ERROR, "unrecognized node type: %d",
40384065
(int) nodeTag(node));

0 commit comments

Comments
 (0)