aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execExprInterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execExprInterp.c')
-rw-r--r--src/backend/executor/execExprInterp.c743
1 files changed, 0 insertions, 743 deletions
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 636794ca6f1..9b9bbf00a97 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -57,31 +57,22 @@
#include "postgres.h"
#include "access/heaptoast.h"
-#include "access/xact.h"
-#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/sequence.h"
#include "executor/execExpr.h"
#include "executor/nodeSubplan.h"
#include "funcapi.h"
#include "miscadmin.h"
-#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
-#include "parser/parse_expr.h"
#include "pgstat.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datum.h"
#include "utils/expandedrecord.h"
-#include "utils/json.h"
-#include "utils/jsonb.h"
-#include "utils/jsonfuncs.h"
-#include "utils/jsonpath.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
-#include "utils/resowner.h"
#include "utils/timestamp.h"
#include "utils/typcache.h"
#include "utils/xml.h"
@@ -488,9 +479,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
&&CASE_EEOP_GROUPING_FUNC,
&&CASE_EEOP_WINDOW_FUNC,
&&CASE_EEOP_SUBPLAN,
- &&CASE_EEOP_JSON_CONSTRUCTOR,
- &&CASE_EEOP_IS_JSON,
- &&CASE_EEOP_JSONEXPR,
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
&&CASE_EEOP_AGG_DESERIALIZE,
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
@@ -1824,27 +1812,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
/* too complex for an inline implementation */
ExecEvalAggOrderedTransTuple(state, op, econtext);
- EEO_NEXT();
- }
-
- EEO_CASE(EEOP_JSON_CONSTRUCTOR)
- {
- /* too complex for an inline implementation */
- ExecEvalJsonConstructor(state, op, econtext);
- EEO_NEXT();
- }
-
- EEO_CASE(EEOP_IS_JSON)
- {
- /* too complex for an inline implementation */
- ExecEvalJsonIsPredicate(state, op);
- EEO_NEXT();
- }
- EEO_CASE(EEOP_JSONEXPR)
- {
- /* too complex for an inline implementation */
- ExecEvalJson(state, op, econtext);
EEO_NEXT();
}
@@ -3972,91 +3940,6 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
}
}
-void
-ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op)
-{
- JsonIsPredicate *pred = op->d.is_json.pred;
- Datum js = *op->resvalue;
- Oid exprtype;
- bool res;
-
- if (*op->resnull)
- {
- *op->resvalue = BoolGetDatum(false);
- return;
- }
-
- exprtype = exprType(pred->expr);
-
- if (exprtype == TEXTOID || exprtype == JSONOID)
- {
- text *json = DatumGetTextP(js);
-
- if (pred->item_type == JS_TYPE_ANY)
- res = true;
- else
- {
- switch (json_get_first_token(json, false))
- {
- case JSON_TOKEN_OBJECT_START:
- res = pred->item_type == JS_TYPE_OBJECT;
- break;
- case JSON_TOKEN_ARRAY_START:
- res = pred->item_type == JS_TYPE_ARRAY;
- break;
- case JSON_TOKEN_STRING:
- case JSON_TOKEN_NUMBER:
- case JSON_TOKEN_TRUE:
- case JSON_TOKEN_FALSE:
- case JSON_TOKEN_NULL:
- res = pred->item_type == JS_TYPE_SCALAR;
- break;
- default:
- res = false;
- break;
- }
- }
-
- /*
- * Do full parsing pass only for uniqueness check or for JSON text
- * validation.
- */
- if (res && (pred->unique_keys || exprtype == TEXTOID))
- res = json_validate(json, pred->unique_keys, false);
- }
- else if (exprtype == JSONBOID)
- {
- if (pred->item_type == JS_TYPE_ANY)
- res = true;
- else
- {
- Jsonb *jb = DatumGetJsonbP(js);
-
- switch (pred->item_type)
- {
- case JS_TYPE_OBJECT:
- res = JB_ROOT_IS_OBJECT(jb);
- break;
- case JS_TYPE_ARRAY:
- res = JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb);
- break;
- case JS_TYPE_SCALAR:
- res = JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb);
- break;
- default:
- res = false;
- break;
- }
- }
-
- /* Key uniqueness check is redundant for jsonb */
- }
- else
- res = false;
-
- *op->resvalue = BoolGetDatum(res);
-}
-
/*
* ExecEvalGroupingFunc
*
@@ -4619,629 +4502,3 @@ ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans,
MemoryContextSwitchTo(oldContext);
}
-
-/*
- * Evaluate a JSON constructor expression.
- */
-void
-ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
- ExprContext *econtext)
-{
- Datum res;
- JsonConstructorExprState *jcstate = op->d.json_constructor.jcstate;
- JsonConstructorExpr *ctor = jcstate->constructor;
- bool is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
- bool isnull = false;
-
- if (ctor->type == JSCTOR_JSON_ARRAY)
- res = (is_jsonb ?
- jsonb_build_array_worker :
- json_build_array_worker) (jcstate->nargs,
- jcstate->arg_values,
- jcstate->arg_nulls,
- jcstate->arg_types,
- ctor->absent_on_null);
- else if (ctor->type == JSCTOR_JSON_OBJECT)
- res = (is_jsonb ?
- jsonb_build_object_worker :
- json_build_object_worker) (jcstate->nargs,
- jcstate->arg_values,
- jcstate->arg_nulls,
- jcstate->arg_types,
- ctor->absent_on_null,
- ctor->unique);
- else if (ctor->type == JSCTOR_JSON_SCALAR)
- {
- if (jcstate->arg_nulls[0])
- {
- res = (Datum) 0;
- isnull = true;
- }
- else
- {
- Datum value = jcstate->arg_values[0];
- int category = jcstate->arg_type_cache[0].category;
- Oid outfuncid = jcstate->arg_type_cache[0].outfuncid;
-
- if (is_jsonb)
- res = to_jsonb_worker(value, category, outfuncid);
- else
- res = to_json_worker(value, category, outfuncid);
- }
- }
- else if (ctor->type == JSCTOR_JSON_PARSE)
- {
- if (jcstate->arg_nulls[0])
- {
- res = (Datum) 0;
- isnull = true;
- }
- else
- {
- Datum value = jcstate->arg_values[0];
- text *js = DatumGetTextP(value);
-
- if (is_jsonb)
- res = jsonb_from_text(js, true);
- else
- {
- (void) json_validate(js, true, true);
- res = value;
- }
- }
- }
- else
- {
- res = (Datum) 0;
- elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type);
- }
-
- *op->resvalue = res;
- *op->resnull = isnull;
-}
-
-/*
- * Evaluate a JSON error/empty behavior result.
- */
-static Datum
-ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
- ExprState *default_estate, bool *is_null)
-{
- *is_null = false;
-
- switch (behavior->btype)
- {
- case JSON_BEHAVIOR_EMPTY_ARRAY:
- return JsonbPGetDatum(JsonbMakeEmptyArray());
-
- case JSON_BEHAVIOR_EMPTY_OBJECT:
- return JsonbPGetDatum(JsonbMakeEmptyObject());
-
- case JSON_BEHAVIOR_TRUE:
- return BoolGetDatum(true);
-
- case JSON_BEHAVIOR_FALSE:
- return BoolGetDatum(false);
-
- case JSON_BEHAVIOR_NULL:
- case JSON_BEHAVIOR_UNKNOWN:
- case JSON_BEHAVIOR_EMPTY:
- *is_null = true;
- return (Datum) 0;
-
- case JSON_BEHAVIOR_DEFAULT:
- return ExecEvalExpr(default_estate, econtext, is_null);
-
- default:
- elog(ERROR, "unrecognized SQL/JSON behavior %d", behavior->btype);
- return (Datum) 0;
- }
-}
-
-/*
- * Evaluate a coercion of a JSON item to the target type.
- */
-static Datum
-ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
- Datum res, bool *isNull, void *p, bool *error)
-{
- ExprState *estate = p;
- JsonExprState *jsestate;
-
- if (estate) /* coerce using specified expression */
- return ExecEvalExpr(estate, econtext, isNull);
-
- jsestate = op->d.jsonexpr.jsestate;
-
- if (jsestate->jsexpr->op != JSON_EXISTS_OP)
- {
- JsonCoercion *coercion = jsestate->jsexpr->result_coercion;
- JsonExpr *jexpr = jsestate->jsexpr;
- Jsonb *jb = *isNull ? NULL : DatumGetJsonbP(res);
-
- if ((coercion && coercion->via_io) ||
- (jexpr->omit_quotes && !*isNull &&
- JB_ROOT_IS_SCALAR(jb)))
- {
- /* strip quotes and call typinput function */
- char *str = *isNull ? NULL : JsonbUnquote(jb);
-
- return InputFunctionCall(&jsestate->input.func, str,
- jsestate->input.typioparam,
- jexpr->returning->typmod);
- }
- else if (coercion && coercion->via_populate)
- return json_populate_type(res, JSONBOID,
- jexpr->returning->typid,
- jexpr->returning->typmod,
- &jsestate->cache,
- econtext->ecxt_per_query_memory,
- isNull);
- }
-
- if (jsestate->result_expr)
- {
- jsestate->res_expr->value = res;
- jsestate->res_expr->isnull = *isNull;
-
- res = ExecEvalExpr(jsestate->result_expr, econtext, isNull);
- }
-
- return res;
-}
-
-/*
- * Evaluate a JSON path variable caching computed value.
- */
-int
-EvalJsonPathVar(void *cxt, char *varName, int varNameLen,
- JsonbValue *val, JsonbValue *baseObject)
-{
- JsonPathVariableEvalContext *var = NULL;
- List *vars = cxt;
- ListCell *lc;
- int id = 1;
-
- if (!varName)
- return list_length(vars);
-
- foreach(lc, vars)
- {
- var = lfirst(lc);
-
- if (!strncmp(var->name, varName, varNameLen))
- break;
-
- var = NULL;
- id++;
- }
-
- if (!var)
- return -1;
-
- if (!var->evaluated)
- {
- MemoryContext oldcxt = var->mcxt ?
- MemoryContextSwitchTo(var->mcxt) : NULL;
-
- var->value = ExecEvalExpr(var->estate, var->econtext, &var->isnull);
- var->evaluated = true;
-
- if (oldcxt)
- MemoryContextSwitchTo(oldcxt);
- }
-
- if (var->isnull)
- {
- val->type = jbvNull;
- return 0;
- }
-
- JsonItemFromDatum(var->value, var->typid, var->typmod, val);
-
- *baseObject = *val;
- return id;
-}
-
-/*
- * Prepare SQL/JSON item coercion to the output type. Returned a datum of the
- * corresponding SQL type and a pointer to the coercion state.
- */
-Datum
-ExecPrepareJsonItemCoercion(JsonbValue *item,
- JsonReturning *returning,
- struct JsonCoercionsState *coercions,
- struct JsonCoercionState **pcoercion)
-{
- struct JsonCoercionState *coercion;
- Datum res;
- JsonbValue buf;
-
- if (item->type == jbvBinary &&
- JsonContainerIsScalar(item->val.binary.data))
- {
- bool res PG_USED_FOR_ASSERTS_ONLY;
-
- res = JsonbExtractScalar(item->val.binary.data, &buf);
- item = &buf;
- Assert(res);
- }
-
- /* get coercion state reference and datum of the corresponding SQL type */
- switch (item->type)
- {
- case jbvNull:
- coercion = &coercions->null;
- res = (Datum) 0;
- break;
-
- case jbvString:
- coercion = &coercions->string;
- res = PointerGetDatum(cstring_to_text_with_len(item->val.string.val,
- item->val.string.len));
- break;
-
- case jbvNumeric:
- coercion = &coercions->numeric;
- res = NumericGetDatum(item->val.numeric);
- break;
-
- case jbvBool:
- coercion = &coercions->boolean;
- res = BoolGetDatum(item->val.boolean);
- break;
-
- case jbvDatetime:
- res = item->val.datetime.value;
- switch (item->val.datetime.typid)
- {
- case DATEOID:
- coercion = &coercions->date;
- break;
- case TIMEOID:
- coercion = &coercions->time;
- break;
- case TIMETZOID:
- coercion = &coercions->timetz;
- break;
- case TIMESTAMPOID:
- coercion = &coercions->timestamp;
- break;
- case TIMESTAMPTZOID:
- coercion = &coercions->timestamptz;
- break;
- default:
- elog(ERROR, "unexpected jsonb datetime type oid %u",
- item->val.datetime.typid);
- return (Datum) 0;
- }
- break;
-
- case jbvArray:
- case jbvObject:
- case jbvBinary:
- coercion = &coercions->composite;
- res = JsonbPGetDatum(JsonbValueToJsonb(item));
- break;
-
- default:
- elog(ERROR, "unexpected jsonb value type %d", item->type);
- return (Datum) 0;
- }
-
- *pcoercion = coercion;
-
- return res;
-}
-
-typedef Datum (*JsonFunc) (ExprEvalStep *op, ExprContext *econtext,
- Datum item, bool *resnull, void *p, bool *error);
-
-static Datum
-ExecEvalJsonExprSubtrans(JsonFunc func, ExprEvalStep *op,
- ExprContext *econtext,
- Datum res, bool *resnull,
- void *p, bool *error, bool subtrans)
-{
- MemoryContext oldcontext;
- ResourceOwner oldowner;
-
- if (!subtrans)
- /* No need to use subtransactions. */
- return func(op, econtext, res, resnull, p, error);
-
- /*
- * We should catch exceptions of category ERRCODE_DATA_EXCEPTION and
- * execute the corresponding ON ERROR behavior then.
- */
- oldcontext = CurrentMemoryContext;
- oldowner = CurrentResourceOwner;
-
- Assert(error);
-
- BeginInternalSubTransaction(NULL);
- /* Want to execute expressions inside function's memory context */
- MemoryContextSwitchTo(oldcontext);
-
- PG_TRY();
- {
- res = func(op, econtext, res, resnull, p, error);
-
- /* Commit the inner transaction, return to outer xact context */
- ReleaseCurrentSubTransaction();
- MemoryContextSwitchTo(oldcontext);
- CurrentResourceOwner = oldowner;
- }
- PG_CATCH();
- {
- ErrorData *edata;
- int ecategory;
-
- /* Save error info in oldcontext */
- MemoryContextSwitchTo(oldcontext);
- edata = CopyErrorData();
- FlushErrorState();
-
- /* Abort the inner transaction */
- RollbackAndReleaseCurrentSubTransaction();
- MemoryContextSwitchTo(oldcontext);
- CurrentResourceOwner = oldowner;
-
- ecategory = ERRCODE_TO_CATEGORY(edata->sqlerrcode);
-
- if (ecategory != ERRCODE_DATA_EXCEPTION && /* jsonpath and other data
- * errors */
- ecategory != ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION) /* domain errors */
- ReThrowError(edata);
-
- res = (Datum) 0;
- *error = true;
- }
- PG_END_TRY();
-
- return res;
-}
-
-
-typedef struct
-{
- JsonPath *path;
- bool *error;
- bool coercionInSubtrans;
-} ExecEvalJsonExprContext;
-
-static Datum
-ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
- Datum item, bool *resnull, void *pcxt,
- bool *error)
-{
- ExecEvalJsonExprContext *cxt = pcxt;
- JsonPath *path = cxt->path;
- JsonExprState *jsestate = op->d.jsonexpr.jsestate;
- JsonExpr *jexpr = jsestate->jsexpr;
- ExprState *estate = NULL;
- bool empty = false;
- Datum res = (Datum) 0;
-
- switch (jexpr->op)
- {
- case JSON_QUERY_OP:
- res = JsonPathQuery(item, path, jexpr->wrapper, &empty, error,
- jsestate->args);
- if (error && *error)
- {
- *resnull = true;
- return (Datum) 0;
- }
- *resnull = !DatumGetPointer(res);
- break;
-
- case JSON_VALUE_OP:
- {
- struct JsonCoercionState *jcstate;
- JsonbValue *jbv = JsonPathValue(item, path, &empty, error,
- jsestate->args);
-
- if (error && *error)
- return (Datum) 0;
-
- if (!jbv) /* NULL or empty */
- break;
-
- Assert(!empty);
-
- *resnull = false;
-
- /* coerce scalar item to the output type */
- if (jexpr->returning->typid == JSONOID ||
- jexpr->returning->typid == JSONBOID)
- {
- /* Use result coercion from json[b] to the output type */
- res = JsonbPGetDatum(JsonbValueToJsonb(jbv));
- break;
- }
-
- /* Use coercion from SQL/JSON item type to the output type */
- res = ExecPrepareJsonItemCoercion(jbv,
- jsestate->jsexpr->returning,
- &jsestate->coercions,
- &jcstate);
-
- if (jcstate->coercion &&
- (jcstate->coercion->via_io ||
- jcstate->coercion->via_populate))
- {
- if (error)
- {
- *error = true;
- return (Datum) 0;
- }
-
- /*
- * Coercion via I/O means here that the cast to the target
- * type simply does not exist.
- */
- ereport(ERROR,
- (errcode(ERRCODE_SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE),
- errmsg("SQL/JSON item cannot be cast to target type")));
- }
- else if (!jcstate->estate)
- return res; /* no coercion */
-
- /* coerce using specific expression */
- estate = jcstate->estate;
- jsestate->coercion_expr->value = res;
- jsestate->coercion_expr->isnull = *resnull;
- break;
- }
-
- case JSON_EXISTS_OP:
- {
- bool exists = JsonPathExists(item, path,
- jsestate->args,
- error);
-
- *resnull = error && *error;
- res = BoolGetDatum(exists);
-
- if (!jsestate->result_expr)
- return res;
-
- /* coerce using result expression */
- estate = jsestate->result_expr;
- jsestate->res_expr->value = res;
- jsestate->res_expr->isnull = *resnull;
- break;
- }
-
- case JSON_TABLE_OP:
- *resnull = false;
- return item;
-
- default:
- elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
- return (Datum) 0;
- }
-
- if (empty)
- {
- Assert(jexpr->on_empty); /* it is not JSON_EXISTS */
-
- if (jexpr->on_empty->btype == JSON_BEHAVIOR_ERROR)
- {
- if (error)
- {
- *error = true;
- return (Datum) 0;
- }
-
- ereport(ERROR,
- (errcode(ERRCODE_NO_SQL_JSON_ITEM),
- errmsg("no SQL/JSON item")));
- }
-
- if (jexpr->on_empty->btype == JSON_BEHAVIOR_DEFAULT)
-
- /*
- * Execute DEFAULT expression as a coercion expression, because
- * its result is already coerced to the target type.
- */
- estate = jsestate->default_on_empty;
- else
- /* Execute ON EMPTY behavior */
- res = ExecEvalJsonBehavior(econtext, jexpr->on_empty,
- jsestate->default_on_empty,
- resnull);
- }
-
- return ExecEvalJsonExprSubtrans(ExecEvalJsonExprCoercion, op, econtext,
- res, resnull, estate, error,
- cxt->coercionInSubtrans);
-}
-
-bool
-ExecEvalJsonNeedsSubTransaction(JsonExpr *jsexpr,
- struct JsonCoercionsState *coercions)
-{
- if (jsexpr->on_error->btype == JSON_BEHAVIOR_ERROR)
- return false;
-
- if (jsexpr->op == JSON_EXISTS_OP && !jsexpr->result_coercion)
- return false;
-
- if (!coercions)
- return true;
-
- return false;
-}
-
-/* ----------------------------------------------------------------
- * ExecEvalJson
- * ----------------------------------------------------------------
- */
-void
-ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
-{
- ExecEvalJsonExprContext cxt;
- JsonExprState *jsestate = op->d.jsonexpr.jsestate;
- JsonExpr *jexpr = jsestate->jsexpr;
- Datum item;
- Datum res = (Datum) 0;
- JsonPath *path;
- ListCell *lc;
- bool error = false;
- bool needSubtrans;
- bool throwErrors = jexpr->on_error->btype == JSON_BEHAVIOR_ERROR;
-
- *op->resnull = true; /* until we get a result */
- *op->resvalue = (Datum) 0;
-
- if (jsestate->formatted_expr->isnull || jsestate->pathspec->isnull)
- {
- /* execute domain checks for NULLs */
- (void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
- NULL, NULL);
-
- Assert(*op->resnull);
- return;
- }
-
- item = jsestate->formatted_expr->value;
- path = DatumGetJsonPathP(jsestate->pathspec->value);
-
- /* reset JSON path variable contexts */
- foreach(lc, jsestate->args)
- {
- JsonPathVariableEvalContext *var = lfirst(lc);
-
- var->econtext = econtext;
- var->evaluated = false;
- }
-
- needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &jsestate->coercions);
-
- cxt.path = path;
- cxt.error = throwErrors ? NULL : &error;
- cxt.coercionInSubtrans = !needSubtrans && !throwErrors;
- Assert(!needSubtrans || cxt.error);
-
- res = ExecEvalJsonExprSubtrans(ExecEvalJsonExpr, op, econtext, item,
- op->resnull, &cxt, cxt.error,
- needSubtrans);
-
- if (error)
- {
- /* Execute ON ERROR behavior */
- res = ExecEvalJsonBehavior(econtext, jexpr->on_error,
- jsestate->default_on_error,
- op->resnull);
-
- /* result is already coerced in DEFAULT behavior case */
- if (jexpr->on_error->btype != JSON_BEHAVIOR_DEFAULT)
- res = ExecEvalJsonExprCoercion(op, econtext, res,
- op->resnull,
- NULL, NULL);
- }
-
- *op->resvalue = res;
-}