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

Commit 13410cc

Browse files
author
Nikita Glukhov
committed
Add json support for JSON_TABLE
1 parent 1696acc commit 13410cc

File tree

6 files changed

+1613
-31
lines changed

6 files changed

+1613
-31
lines changed

src/backend/executor/nodeTableFuncscan.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
#include "postgres.h"
2424

2525
#include "nodes/execnodes.h"
26+
#include "catalog/pg_type.h"
2627
#include "executor/executor.h"
2728
#include "executor/nodeTableFuncscan.h"
2829
#include "executor/tablefunc.h"
2930
#include "miscadmin.h"
31+
#include "nodes/nodeFuncs.h"
3032
#include "utils/builtins.h"
3133
#include "utils/jsonpath.h"
3234
#include "utils/lsyscache.h"
@@ -165,7 +167,8 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
165167

166168
/* Only XMLTABLE and JSON_TABLE are supported currently */
167169
scanstate->routine =
168-
tf->functype == TFT_XMLTABLE ? &XmlTableRoutine : &JsonbTableRoutine;
170+
tf->functype == TFT_XMLTABLE ? &XmlTableRoutine :
171+
exprType(tf->docexpr) == JSONBOID ? &JsonbTableRoutine : &JsonTableRoutine;
169172

170173
scanstate->perTableCxt =
171174
AllocSetContextCreate(CurrentMemoryContext,

src/backend/parser/parse_expr.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4824,12 +4824,6 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
48244824
jsexpr->returning.typid = exprType(contextItemExpr);
48254825
jsexpr->returning.typmod = -1;
48264826

4827-
if (jsexpr->returning.typid != JSONBOID)
4828-
ereport(ERROR,
4829-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4830-
errmsg("JSON_TABLE() is not yet implemented for json type"),
4831-
parser_errposition(pstate, func->location)));
4832-
48334827
break;
48344828
}
48354829

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ typedef struct JsonTableContext
261261
} *colexprs;
262262
JsonTableScanState root;
263263
bool empty;
264+
bool isJsonb;
264265
} JsonTableContext;
265266

266267
/* strict/lax flags is decomposed into four [un]wrap/error flags */
@@ -434,7 +435,7 @@ static void popJsonItem(JsonItemStack *stack);
434435

435436
static JsonTableJoinState *JsonTableInitPlanState(JsonTableContext *cxt,
436437
Node *plan, JsonTableScanState *parent);
437-
static bool JsonTableNextRow(JsonTableScanState *scan);
438+
static bool JsonTableNextRow(JsonTableScanState *scan, bool isJsonb);
438439

439440

440441
/****************** User interface to JsonPath executor ********************/
@@ -3748,11 +3749,11 @@ JsonTableInitPlanState(JsonTableContext *cxt, Node *plan,
37483749
}
37493750

37503751
/*
3751-
* JsonTableInitOpaque
3752+
* JsonxTableInitOpaque
37523753
* Fill in TableFuncScanState->opaque for JsonTable processor
37533754
*/
37543755
static void
3755-
JsonTableInitOpaque(TableFuncScanState *state, int natts)
3756+
JsonxTableInitOpaque(TableFuncScanState *state, int natts, bool isJsonb)
37563757
{
37573758
JsonTableContext *cxt;
37583759
PlanState *ps = &state->ss.ps;
@@ -3766,6 +3767,7 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
37663767

37673768
cxt = palloc0(sizeof(JsonTableContext));
37683769
cxt->magic = JSON_TABLE_CONTEXT_MAGIC;
3770+
cxt->isJsonb = isJsonb;
37693771

37703772
if (list_length(ci->passing.values) > 0)
37713773
{
@@ -3816,6 +3818,18 @@ JsonTableInitOpaque(TableFuncScanState *state, int natts)
38163818
state->opaque = cxt;
38173819
}
38183820

3821+
static void
3822+
JsonbTableInitOpaque(TableFuncScanState *state, int natts)
3823+
{
3824+
JsonxTableInitOpaque(state, natts, true);
3825+
}
3826+
3827+
static void
3828+
JsonTableInitOpaque(TableFuncScanState *state, int natts)
3829+
{
3830+
JsonxTableInitOpaque(state, natts, false);
3831+
}
3832+
38193833
/* Reset scan iterator to the beginning of the item list */
38203834
static void
38213835
JsonTableRescan(JsonTableScanState *scan)
@@ -3829,19 +3843,19 @@ JsonTableRescan(JsonTableScanState *scan)
38293843

38303844
/* Reset context item of a scan, execute JSON path and reset a scan */
38313845
static void
3832-
JsonTableResetContextItem(JsonTableScanState *scan, Datum item)
3846+
JsonTableResetContextItem(JsonTableScanState *scan, Datum item, bool isJsonb)
38333847
{
38343848
MemoryContext oldcxt;
38353849
JsonPathExecResult res;
3836-
Jsonx *js = (Jsonx *) DatumGetJsonbP(item);
3850+
Jsonx *js = DatumGetJsonxP(item, isJsonb);
38373851

38383852
JsonValueListClear(&scan->found);
38393853

38403854
MemoryContextResetOnly(scan->mcxt);
38413855

38423856
oldcxt = MemoryContextSwitchTo(scan->mcxt);
38433857

3844-
res = executeJsonPath(scan->path, scan->args, EvalJsonPathVar, js, true,
3858+
res = executeJsonPath(scan->path, scan->args, EvalJsonPathVar, js, isJsonb,
38453859
scan->errorOnError, &scan->found);
38463860

38473861
MemoryContextSwitchTo(oldcxt);
@@ -3864,7 +3878,7 @@ JsonTableSetDocument(TableFuncScanState *state, Datum value)
38643878
{
38653879
JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableSetDocument");
38663880

3867-
JsonTableResetContextItem(&cxt->root, value);
3881+
JsonTableResetContextItem(&cxt->root, value, cxt->isJsonb);
38683882
}
38693883

38703884
/* Recursively reset scan and its child nodes */
@@ -3891,15 +3905,15 @@ JsonTableRescanRecursive(JsonTableJoinState *state)
38913905
* Returned false at the end of a scan, true otherwise.
38923906
*/
38933907
static bool
3894-
JsonTableNextJoinRow(JsonTableJoinState *state)
3908+
JsonTableNextJoinRow(JsonTableJoinState *state, bool isJsonb)
38953909
{
38963910
if (!state->is_join)
3897-
return JsonTableNextRow(&state->u.scan);
3911+
return JsonTableNextRow(&state->u.scan, isJsonb);
38983912

38993913
if (state->u.join.advanceRight)
39003914
{
39013915
/* fetch next inner row */
3902-
if (JsonTableNextJoinRow(state->u.join.right))
3916+
if (JsonTableNextJoinRow(state->u.join.right, isJsonb))
39033917
return true;
39043918

39053919
/* inner rows are exhausted */
@@ -3912,7 +3926,7 @@ JsonTableNextJoinRow(JsonTableJoinState *state)
39123926
while (!state->u.join.advanceRight)
39133927
{
39143928
/* fetch next outer row */
3915-
bool left = JsonTableNextJoinRow(state->u.join.left);
3929+
bool left = JsonTableNextJoinRow(state->u.join.left, isJsonb);
39163930

39173931
if (state->u.join.cross)
39183932
{
@@ -3921,14 +3935,14 @@ JsonTableNextJoinRow(JsonTableJoinState *state)
39213935

39223936
JsonTableRescanRecursive(state->u.join.right);
39233937

3924-
if (!JsonTableNextJoinRow(state->u.join.right))
3938+
if (!JsonTableNextJoinRow(state->u.join.right, isJsonb))
39253939
continue; /* next outer row */
39263940

39273941
state->u.join.advanceRight = true; /* next inner row */
39283942
}
39293943
else if (!left)
39303944
{
3931-
if (!JsonTableNextJoinRow(state->u.join.right))
3945+
if (!JsonTableNextJoinRow(state->u.join.right, isJsonb))
39323946
return false; /* end of scan */
39333947

39343948
state->u.join.advanceRight = true; /* next inner row */
@@ -3966,20 +3980,20 @@ JsonTableJoinReset(JsonTableJoinState *state)
39663980
* Returned false at the end of a scan, true otherwise.
39673981
*/
39683982
static bool
3969-
JsonTableNextRow(JsonTableScanState *scan)
3983+
JsonTableNextRow(JsonTableScanState *scan, bool isJsonb)
39703984
{
39713985
/* reset context item if requested */
39723986
if (scan->reset)
39733987
{
39743988
Assert(!scan->parent->currentIsNull);
3975-
JsonTableResetContextItem(scan, scan->parent->current);
3989+
JsonTableResetContextItem(scan, scan->parent->current, isJsonb);
39763990
scan->reset = false;
39773991
}
39783992

39793993
if (scan->advanceNested)
39803994
{
39813995
/* fetch next nested row */
3982-
scan->advanceNested = JsonTableNextJoinRow(scan->nested);
3996+
scan->advanceNested = JsonTableNextJoinRow(scan->nested, isJsonb);
39833997

39843998
if (scan->advanceNested)
39853999
return true;
@@ -4000,7 +4014,7 @@ JsonTableNextRow(JsonTableScanState *scan)
40004014

40014015
/* set current row item */
40024016
oldcxt = MemoryContextSwitchTo(scan->mcxt);
4003-
scan->current = JsonbPGetDatum(JsonItemToJsonb(jbv));
4017+
scan->current = JsonItemToJsonxDatum(jbv, isJsonb);
40044018
scan->currentIsNull = false;
40054019
MemoryContextSwitchTo(oldcxt);
40064020

@@ -4011,7 +4025,7 @@ JsonTableNextRow(JsonTableScanState *scan)
40114025

40124026
JsonTableJoinReset(scan->nested);
40134027

4014-
scan->advanceNested = JsonTableNextJoinRow(scan->nested);
4028+
scan->advanceNested = JsonTableNextJoinRow(scan->nested, isJsonb);
40154029

40164030
if (scan->advanceNested || scan->outerJoin)
40174031
break;
@@ -4035,7 +4049,7 @@ JsonTableFetchRow(TableFuncScanState *state)
40354049
if (cxt->empty)
40364050
return false;
40374051

4038-
return JsonTableNextRow(&cxt->root);
4052+
return JsonTableNextRow(&cxt->root, cxt->isJsonb);
40394053
}
40404054

40414055
/*
@@ -4088,6 +4102,18 @@ JsonTableDestroyOpaque(TableFuncScanState *state)
40884102
}
40894103

40904104
const TableFuncRoutine JsonbTableRoutine =
4105+
{
4106+
JsonbTableInitOpaque,
4107+
JsonTableSetDocument,
4108+
NULL,
4109+
NULL,
4110+
NULL,
4111+
JsonTableFetchRow,
4112+
JsonTableGetValue,
4113+
JsonTableDestroyOpaque
4114+
};
4115+
4116+
const TableFuncRoutine JsonTableRoutine =
40914117
{
40924118
JsonTableInitOpaque,
40934119
JsonTableSetDocument,

src/include/utils/jsonpath.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ extern JsonItem *JsonPathValue(Datum jb, JsonPath *jp, bool *empty,
352352
extern int EvalJsonPathVar(void *vars, bool isJsonb, char *varName,
353353
int varNameLen, JsonItem *val, JsonbValue *baseObject);
354354

355+
extern const TableFuncRoutine JsonTableRoutine;
355356
extern const TableFuncRoutine JsonbTableRoutine;
356357

357358
#endif

0 commit comments

Comments
 (0)