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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy