summaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execExpr.c11
-rw-r--r--src/backend/executor/execExprInterp.c2
-rw-r--r--src/backend/executor/nodeTableFuncscan.c41
3 files changed, 39 insertions, 15 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index bc5feb0115a..79087cc6d63 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2436,7 +2436,16 @@ ExecInitExprRec(Expr *node, ExprState *state,
{
JsonExpr *jsexpr = castNode(JsonExpr, node);
- ExecInitJsonExpr(jsexpr, state, resv, resnull, &scratch);
+ /*
+ * No need to initialize a full JsonExprState For
+ * JSON_TABLE(), because the upstream caller tfuncFetchRows()
+ * is only interested in the value of formatted_expr.
+ */
+ if (jsexpr->op == JSON_TABLE_OP)
+ ExecInitExprRec((Expr *) jsexpr->formatted_expr, state,
+ resv, resnull);
+ else
+ ExecInitJsonExpr(jsexpr, state, resv, resnull, &scratch);
break;
}
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 24a3990a30a..41af28cb1eb 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4370,6 +4370,8 @@ ExecEvalJsonExprPath(ExprState *state, ExprEvalStep *op,
break;
}
+ /* JSON_TABLE_OP can't happen here */
+
default:
elog(ERROR, "unrecognized SQL/JSON expression op %d",
(int) jsexpr->op);
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index 72ca34a2287..f483221bb8e 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -28,6 +28,7 @@
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "utils/builtins.h"
+#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/xml.h"
@@ -161,8 +162,9 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
scanstate->ss.ps.qual =
ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
- /* Only XMLTABLE is supported currently */
- scanstate->routine = &XmlTableRoutine;
+ /* Only XMLTABLE and JSON_TABLE are supported currently */
+ scanstate->routine =
+ tf->functype == TFT_XMLTABLE ? &XmlTableRoutine : &JsonbTableRoutine;
scanstate->perTableCxt =
AllocSetContextCreate(CurrentMemoryContext,
@@ -182,6 +184,10 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
ExecInitExprList(tf->colexprs, (PlanState *) scanstate);
scanstate->coldefexprs =
ExecInitExprList(tf->coldefexprs, (PlanState *) scanstate);
+ scanstate->colvalexprs =
+ ExecInitExprList(tf->colvalexprs, (PlanState *) scanstate);
+ scanstate->passingvalexprs =
+ ExecInitExprList(tf->passingvalexprs, (PlanState *) scanstate);
scanstate->notnulls = tf->notnulls;
@@ -274,11 +280,12 @@ tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext)
/*
* Each call to fetch a new set of rows - of which there may be very many
- * if XMLTABLE is being used in a lateral join - will allocate a possibly
- * substantial amount of memory, so we cannot use the per-query context
- * here. perTableCxt now serves the same function as "argcontext" does in
- * FunctionScan - a place to store per-one-call (i.e. one result table)
- * lifetime data (as opposed to per-query or per-result-tuple).
+ * if XMLTABLE or JSON_TABLE is being used in a lateral join - will
+ * allocate a possibly substantial amount of memory, so we cannot use the
+ * per-query context here. perTableCxt now serves the same function as
+ * "argcontext" does in FunctionScan - a place to store per-one-call (i.e.
+ * one result table) lifetime data (as opposed to per-query or
+ * per-result-tuple).
*/
MemoryContextSwitchTo(tstate->perTableCxt);
@@ -369,14 +376,20 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
routine->SetNamespace(tstate, ns_name, ns_uri);
}
- /* Install the row filter expression into the table builder context */
- value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
- if (isnull)
- ereport(ERROR,
- (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
- errmsg("row filter expression must not be null")));
+ /*
+ * Install the row filter expression, if any, into the table builder
+ * context.
+ */
+ if (routine->SetRowFilter)
+ {
+ value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
+ if (isnull)
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("row filter expression must not be null")));
- routine->SetRowFilter(tstate, TextDatumGetCString(value));
+ routine->SetRowFilter(tstate, TextDatumGetCString(value));
+ }
/*
* Install the column filter expressions into the table builder context.