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

Commit 828b0c8

Browse files
author
Nikita Glukhov
committed
Add JSON_TABLE
1 parent 077dd7f commit 828b0c8

31 files changed

+2381
-32
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

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

3230+
APP_JUMB(tablefunc->functype);
32303231
JumbleExpr(jstate, tablefunc->docexpr);
32313232
JumbleExpr(jstate, tablefunc->rowexpr);
32323233
JumbleExpr(jstate, (Node *) tablefunc->colexprs);
3234+
JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
32333235
}
32343236
break;
32353237
case T_TableSampleClause:

src/backend/commands/explain.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3575,7 +3575,9 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
35753575
break;
35763576
case T_TableFuncScan:
35773577
Assert(rte->rtekind == RTE_TABLEFUNC);
3578-
objectname = "xmltable";
3578+
objectname = rte->tablefunc ?
3579+
rte->tablefunc->functype == TFT_XMLTABLE ?
3580+
"xmltable" : "json_table" : NULL;
35793581
objecttag = "Table Function Name";
35803582
break;
35813583
case T_ValuesScan:

src/backend/executor/execExpr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,6 +2315,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
23152315
var->typmod = exprTypmod((Node *) argexpr);
23162316
var->estate = ExecInitExpr(argexpr, state->parent);
23172317
var->econtext = NULL;
2318+
var->mcxt = NULL;
23182319
var->evaluated = false;
23192320
var->value = (Datum) 0;
23202321
var->isnull = true;

src/backend/executor/execExprInterp.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,6 +4536,7 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
45364536

45374537
case JSON_BEHAVIOR_NULL:
45384538
case JSON_BEHAVIOR_UNKNOWN:
4539+
case JSON_BEHAVIOR_EMPTY:
45394540
*is_null = true;
45404541
return (Datum) 0;
45414542

@@ -4628,8 +4629,14 @@ EvalJsonPathVar(void *cxt, char *varName, int varNameLen,
46284629

46294630
if (!var->evaluated)
46304631
{
4632+
MemoryContext oldcxt = var->mcxt ?
4633+
MemoryContextSwitchTo(var->mcxt) : NULL;
4634+
46314635
var->value = ExecEvalExpr(var->estate, var->econtext, &var->isnull);
46324636
var->evaluated = true;
4637+
4638+
if (oldcxt)
4639+
MemoryContextSwitchTo(oldcxt);
46334640
}
46344641

46354642
if (var->isnull)
@@ -4772,6 +4779,7 @@ ExecEvalJsonExprSubtrans(JsonFunc func, ExprEvalStep *op,
47724779
PG_CATCH();
47734780
{
47744781
ErrorData *edata;
4782+
int ecategory;
47754783

47764784
/* Save error info in oldcontext */
47774785
MemoryContextSwitchTo(oldcontext);
@@ -4783,8 +4791,10 @@ ExecEvalJsonExprSubtrans(JsonFunc func, ExprEvalStep *op,
47834791
MemoryContextSwitchTo(oldcontext);
47844792
CurrentResourceOwner = oldowner;
47854793

4786-
if (ERRCODE_TO_CATEGORY(edata->sqlerrcode) !=
4787-
ERRCODE_DATA_EXCEPTION)
4794+
ecategory = ERRCODE_TO_CATEGORY(edata->sqlerrcode);
4795+
4796+
if (ecategory != ERRCODE_DATA_EXCEPTION &&
4797+
ecategory != ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION) /* domain errors */
47884798
ReThrowError(edata);
47894799

47904800
res = (Datum) 0;
@@ -4913,6 +4923,10 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
49134923
break;
49144924
}
49154925

4926+
case IS_JSON_TABLE:
4927+
*resnull = false;
4928+
return item;
4929+
49164930
default:
49174931
elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
49184932
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 "miscadmin.h"
2929
#include "nodes/execnodes.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->perTableCxt =
168170
AllocSetContextCreate(CurrentMemoryContext,
@@ -381,14 +383,17 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
381383
routine->SetNamespace(tstate, ns_name, ns_uri);
382384
}
383385

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

391-
routine->SetRowFilter(tstate, TextDatumGetCString(value));
395+
routine->SetRowFilter(tstate, TextDatumGetCString(value));
396+
}
392397

393398
/*
394399
* Install the column filter expressions into the table builder context.

src/backend/nodes/copyfuncs.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,7 @@ _copyTableFunc(const TableFunc *from)
13491349
{
13501350
TableFunc *newnode = makeNode(TableFunc);
13511351

1352+
COPY_SCALAR_FIELD(functype);
13521353
COPY_NODE_FIELD(ns_uris);
13531354
COPY_NODE_FIELD(ns_names);
13541355
COPY_NODE_FIELD(docexpr);
@@ -1359,7 +1360,9 @@ _copyTableFunc(const TableFunc *from)
13591360
COPY_NODE_FIELD(colcollations);
13601361
COPY_NODE_FIELD(colexprs);
13611362
COPY_NODE_FIELD(coldefexprs);
1363+
COPY_NODE_FIELD(colvalexprs);
13621364
COPY_BITMAPSET_FIELD(notnulls);
1365+
COPY_NODE_FIELD(plan);
13631366
COPY_SCALAR_FIELD(ordinalitycol);
13641367
COPY_LOCATION_FIELD(location);
13651368

@@ -2615,6 +2618,76 @@ _copyJsonArgument(const JsonArgument *from)
26152618
return newnode;
26162619
}
26172620

2621+
/*
2622+
* _copyJsonTable
2623+
*/
2624+
static JsonTable *
2625+
_copyJsonTable(const JsonTable *from)
2626+
{
2627+
JsonTable *newnode = makeNode(JsonTable);
2628+
2629+
COPY_NODE_FIELD(common);
2630+
COPY_NODE_FIELD(columns);
2631+
COPY_NODE_FIELD(on_error);
2632+
COPY_NODE_FIELD(alias);
2633+
COPY_SCALAR_FIELD(location);
2634+
2635+
return newnode;
2636+
}
2637+
2638+
/*
2639+
* _copyJsonTableColumn
2640+
*/
2641+
static JsonTableColumn *
2642+
_copyJsonTableColumn(const JsonTableColumn *from)
2643+
{
2644+
JsonTableColumn *newnode = makeNode(JsonTableColumn);
2645+
2646+
COPY_SCALAR_FIELD(coltype);
2647+
COPY_STRING_FIELD(name);
2648+
COPY_NODE_FIELD(typeName);
2649+
COPY_STRING_FIELD(pathspec);
2650+
COPY_SCALAR_FIELD(format);
2651+
COPY_SCALAR_FIELD(wrapper);
2652+
COPY_SCALAR_FIELD(omit_quotes);
2653+
COPY_NODE_FIELD(columns);
2654+
COPY_NODE_FIELD(on_empty);
2655+
COPY_NODE_FIELD(on_error);
2656+
COPY_SCALAR_FIELD(location);
2657+
2658+
return newnode;
2659+
}
2660+
2661+
/*
2662+
* _copyJsonTableParentNode
2663+
*/
2664+
static JsonTableParentNode *
2665+
_copyJsonTableParentNode(const JsonTableParentNode *from)
2666+
{
2667+
JsonTableParentNode *newnode = makeNode(JsonTableParentNode);
2668+
2669+
COPY_NODE_FIELD(path);
2670+
COPY_NODE_FIELD(child);
2671+
COPY_SCALAR_FIELD(colMin);
2672+
COPY_SCALAR_FIELD(colMax);
2673+
2674+
return newnode;
2675+
}
2676+
2677+
/*
2678+
* _copyJsonTableSiblingNode
2679+
*/
2680+
static JsonTableSiblingNode *
2681+
_copyJsonTableSiblingNode(const JsonTableSiblingNode *from)
2682+
{
2683+
JsonTableSiblingNode *newnode = makeNode(JsonTableSiblingNode);
2684+
2685+
COPY_NODE_FIELD(larg);
2686+
COPY_NODE_FIELD(rarg);
2687+
2688+
return newnode;
2689+
}
2690+
26182691
/* ****************************************************************
26192692
* pathnodes.h copy functions
26202693
*
@@ -5578,6 +5651,18 @@ copyObjectImpl(const void *from)
55785651
case T_JsonItemCoercions:
55795652
retval = _copyJsonItemCoercions(from);
55805653
break;
5654+
case T_JsonTable:
5655+
retval = _copyJsonTable(from);
5656+
break;
5657+
case T_JsonTableColumn:
5658+
retval = _copyJsonTableColumn(from);
5659+
break;
5660+
case T_JsonTableParentNode:
5661+
retval = _copyJsonTableParentNode(from);
5662+
break;
5663+
case T_JsonTableSiblingNode:
5664+
retval = _copyJsonTableSiblingNode(from);
5665+
break;
55815666

55825667
/*
55835668
* RELATION NODES

src/backend/nodes/equalfuncs.c

Lines changed: 29 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,35 @@ _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_NODE_FIELD(child);
148+
COMPARE_SCALAR_FIELD(colMin);
149+
COMPARE_SCALAR_FIELD(colMax);
150+
151+
return true;
152+
}
153+
154+
static bool
155+
_equalJsonTableSiblingNode(const JsonTableSiblingNode *a, const JsonTableSiblingNode *b)
156+
{
157+
COMPARE_NODE_FIELD(larg);
158+
COMPARE_NODE_FIELD(rarg);
159+
160+
return true;
161+
}
162+
140163
static bool
141164
_equalIntoClause(const IntoClause *a, const IntoClause *b)
142165
{
@@ -3479,6 +3502,12 @@ equal(const void *a, const void *b)
34793502
case T_JsonItemCoercions:
34803503
retval = _equalJsonItemCoercions(a, b);
34813504
break;
3505+
case T_JsonTableParentNode:
3506+
retval = _equalJsonTableParentNode(a, b);
3507+
break;
3508+
case T_JsonTableSiblingNode:
3509+
retval = _equalJsonTableSiblingNode(a, b);
3510+
break;
34823511

34833512
/*
34843513
* RELATION NODES

src/backend/nodes/nodeFuncs.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,6 +2352,8 @@ expression_tree_walker(Node *node,
23522352
return true;
23532353
if (walker(tf->coldefexprs, context))
23542354
return true;
2355+
if (walker(tf->colvalexprs, context))
2356+
return true;
23552357
}
23562358
break;
23572359
case T_JsonValueExpr:
@@ -3347,6 +3349,7 @@ expression_tree_mutator(Node *node,
33473349
MUTATE(newnode->rowexpr, tf->rowexpr, Node *);
33483350
MUTATE(newnode->colexprs, tf->colexprs, List *);
33493351
MUTATE(newnode->coldefexprs, tf->coldefexprs, List *);
3352+
MUTATE(newnode->colvalexprs, tf->colvalexprs, List *);
33503353
return (Node *) newnode;
33513354
}
33523355
break;
@@ -4291,6 +4294,30 @@ raw_expression_tree_walker(Node *node,
42914294
return true;
42924295
}
42934296
break;
4297+
case T_JsonTable:
4298+
{
4299+
JsonTable *jt = (JsonTable *) node;
4300+
4301+
if (walker(jt->common, context))
4302+
return true;
4303+
if (walker(jt->columns, context))
4304+
return true;
4305+
}
4306+
break;
4307+
case T_JsonTableColumn:
4308+
{
4309+
JsonTableColumn *jtc = (JsonTableColumn *) node;
4310+
4311+
if (walker(jtc->typeName, context))
4312+
return true;
4313+
if (walker(jtc->on_empty, context))
4314+
return true;
4315+
if (walker(jtc->on_error, context))
4316+
return true;
4317+
if (jtc->coltype == JTC_NESTED && walker(jtc->columns, context))
4318+
return true;
4319+
}
4320+
break;
42944321
default:
42954322
elog(ERROR, "unrecognized node type: %d",
42964323
(int) nodeTag(node));

0 commit comments

Comments
 (0)