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

Commit 3f08b9f

Browse files
author
Nikita Glukhov
committed
JSON_TABLE
1 parent 0e6b8b8 commit 3f08b9f

30 files changed

+3748
-27
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
@@ -3021,7 +3021,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
30213021
break;
30223022
case T_TableFuncScan:
30233023
Assert(rte->rtekind == RTE_TABLEFUNC);
3024-
objectname = "xmltable";
3024+
objectname = rte->tablefunc ?
3025+
rte->tablefunc->functype == TFT_XMLTABLE ?
3026+
"xmltable" : "json_table" : NULL;
30253027
objecttag = "Table Function Name";
30263028
break;
30273029
case T_ValuesScan:

src/backend/executor/execExpr.c

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

src/backend/executor/execExprInterp.c

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

41754175
case JSON_BEHAVIOR_NULL:
41764176
case JSON_BEHAVIOR_UNKNOWN:
4177+
case JSON_BEHAVIOR_EMPTY:
41774178
*is_null = true;
41784179
return (Datum) 0;
41794180

@@ -4239,8 +4240,14 @@ EvalJsonPathVar(void *cxt, bool *isnull)
42394240

42404241
if (!ecxt->evaluated)
42414242
{
4243+
MemoryContext oldcxt = ecxt->mcxt ?
4244+
MemoryContextSwitchTo(ecxt->mcxt) : NULL;
4245+
42424246
ecxt->value = ExecEvalExpr(ecxt->estate, ecxt->econtext, &ecxt->isnull);
42434247
ecxt->evaluated = true;
4248+
4249+
if (oldcxt)
4250+
MemoryContextSwitchTo(oldcxt);
42444251
}
42454252

42464253
*isnull = ecxt->isnull;
@@ -4447,6 +4454,10 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44474454
return BoolGetDatum((isjsonb ? JsonbPathExists : JsonPathExists)
44484455
(item, path, op->d.jsonexpr.args));
44494456

4457+
case IS_JSON_TABLE:
4458+
*resnull = false;
4459+
return item;
4460+
44504461
default:
44514462
elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
44524463
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
@@ -1297,6 +1297,7 @@ _copyTableFunc(const TableFunc *from)
12971297
{
12981298
TableFunc *newnode = makeNode(TableFunc);
12991299

1300+
COPY_SCALAR_FIELD(functype);
13001301
COPY_NODE_FIELD(ns_uris);
13011302
COPY_NODE_FIELD(ns_names);
13021303
COPY_NODE_FIELD(docexpr);
@@ -1307,7 +1308,9 @@ _copyTableFunc(const TableFunc *from)
13071308
COPY_NODE_FIELD(colcollations);
13081309
COPY_NODE_FIELD(colexprs);
13091310
COPY_NODE_FIELD(coldefexprs);
1311+
COPY_NODE_FIELD(colvalexprs);
13101312
COPY_BITMAPSET_FIELD(notnulls);
1313+
COPY_NODE_FIELD(plan);
13111314
COPY_SCALAR_FIELD(ordinalitycol);
13121315
COPY_LOCATION_FIELD(location);
13131316

@@ -2514,6 +2517,99 @@ _copyJsonArgument(const JsonArgument *from)
25142517
return newnode;
25152518
}
25162519

2520+
/*
2521+
* _copyJsonTable
2522+
*/
2523+
static JsonTable *
2524+
_copyJsonTable(const JsonTable *from)
2525+
{
2526+
JsonTable *newnode = makeNode(JsonTable);
2527+
2528+
COPY_NODE_FIELD(common);
2529+
COPY_NODE_FIELD(columns);
2530+
COPY_NODE_FIELD(plan);
2531+
COPY_NODE_FIELD(on_error);
2532+
COPY_NODE_FIELD(alias);
2533+
COPY_SCALAR_FIELD(location);
2534+
2535+
return newnode;
2536+
}
2537+
2538+
/*
2539+
* _copyJsonTableColumn
2540+
*/
2541+
static JsonTableColumn *
2542+
_copyJsonTableColumn(const JsonTableColumn *from)
2543+
{
2544+
JsonTableColumn *newnode = makeNode(JsonTableColumn);
2545+
2546+
COPY_SCALAR_FIELD(coltype);
2547+
COPY_STRING_FIELD(name);
2548+
COPY_NODE_FIELD(typeName);
2549+
COPY_STRING_FIELD(pathspec);
2550+
COPY_STRING_FIELD(pathname);
2551+
COPY_SCALAR_FIELD(format);
2552+
COPY_SCALAR_FIELD(wrapper);
2553+
COPY_SCALAR_FIELD(omit_quotes);
2554+
COPY_NODE_FIELD(columns);
2555+
COPY_NODE_FIELD(on_empty);
2556+
COPY_NODE_FIELD(on_error);
2557+
COPY_SCALAR_FIELD(location);
2558+
2559+
return newnode;
2560+
}
2561+
2562+
/*
2563+
* _copyJsonTablePlan
2564+
*/
2565+
static JsonTablePlan *
2566+
_copyJsonTablePlan(const JsonTablePlan *from)
2567+
{
2568+
JsonTablePlan *newnode = makeNode(JsonTablePlan);
2569+
2570+
COPY_SCALAR_FIELD(plan_type);
2571+
COPY_SCALAR_FIELD(join_type);
2572+
COPY_STRING_FIELD(pathname);
2573+
COPY_NODE_FIELD(plan1);
2574+
COPY_NODE_FIELD(plan2);
2575+
COPY_SCALAR_FIELD(location);
2576+
2577+
return newnode;
2578+
}
2579+
2580+
/*
2581+
* _copyJsonTableParentNode
2582+
*/
2583+
static JsonTableParentNode *
2584+
_copyJsonTableParentNode(const JsonTableParentNode *from)
2585+
{
2586+
JsonTableParentNode *newnode = makeNode(JsonTableParentNode);
2587+
2588+
COPY_NODE_FIELD(path);
2589+
COPY_STRING_FIELD(name);
2590+
COPY_NODE_FIELD(child);
2591+
COPY_SCALAR_FIELD(outerJoin);
2592+
COPY_SCALAR_FIELD(colMin);
2593+
COPY_SCALAR_FIELD(colMax);
2594+
2595+
return newnode;
2596+
}
2597+
2598+
/*
2599+
* _copyJsonTableSiblingNode
2600+
*/
2601+
static JsonTableSiblingNode *
2602+
_copyJsonTableSiblingNode(const JsonTableSiblingNode *from)
2603+
{
2604+
JsonTableSiblingNode *newnode = makeNode(JsonTableSiblingNode);
2605+
2606+
COPY_NODE_FIELD(larg);
2607+
COPY_NODE_FIELD(rarg);
2608+
COPY_SCALAR_FIELD(cross);
2609+
2610+
return newnode;
2611+
}
2612+
25172613
/* ****************************************************************
25182614
* relation.h copy functions
25192615
*
@@ -5459,6 +5555,21 @@ copyObjectImpl(const void *from)
54595555
case T_JsonItemCoercions:
54605556
retval = _copyJsonItemCoercions(from);
54615557
break;
5558+
case T_JsonTable:
5559+
retval = _copyJsonTable(from);
5560+
break;
5561+
case T_JsonTableColumn:
5562+
retval = _copyJsonTableColumn(from);
5563+
break;
5564+
case T_JsonTablePlan:
5565+
retval = _copyJsonTablePlan(from);
5566+
break;
5567+
case T_JsonTableParentNode:
5568+
retval = _copyJsonTableParentNode(from);
5569+
break;
5570+
case T_JsonTableSiblingNode:
5571+
retval = _copyJsonTableSiblingNode(from);
5572+
break;
54625573

54635574
/*
54645575
* 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
@@ -659,6 +659,25 @@ makeJsonBehavior(JsonBehaviorType type, Node *default_expr)
659659
return behavior;
660660
}
661661

662+
/*
663+
* makeJsonTableJoinedPlan -
664+
* creates a joined JsonTablePlan node
665+
*/
666+
Node *
667+
makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2,
668+
int location)
669+
{
670+
JsonTablePlan *n = makeNode(JsonTablePlan);
671+
672+
n->plan_type = JSTP_JOINED;
673+
n->join_type = type;
674+
n->plan1 = castNode(JsonTablePlan, plan1);
675+
n->plan2 = castNode(JsonTablePlan, plan2);
676+
n->location = location;
677+
678+
return (Node *) n;
679+
}
680+
662681
/*
663682
* makeJsonEncoding -
664683
* 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)