expression eval: Fix EEOP_JSON_CONSTRUCTOR and EEOP_JSONEXPR size.
authorAndres Freund <[email protected]>
Fri, 17 Jun 2022 01:33:42 +0000 (18:33 -0700)
committerAndres Freund <[email protected]>
Tue, 5 Jul 2022 18:25:08 +0000 (11:25 -0700)
The new expression step types increased the size of ExprEvalStep by ~4 for all
types of expression steps, slowing down expression evaluation noticeably. Move
them out of line.

There's other issues with these expression steps, but addressing them is
largely independent of this aspect.

Author: Andres Freund <[email protected]>
Reviewed-By: Andrew Dunstan <[email protected]>
Discussion: https://postgr.es/m/20220616233130[email protected]
Backpatch: 15-

src/backend/executor/execExpr.c
src/backend/executor/execExprInterp.c
src/include/executor/execExpr.h
src/tools/pgindent/typedefs.list

index 2831e7978b57ece7eaf41f20ca155f43eae5fb4a..1f65daf203594295ee5450fd281e976be44be0a5 100644 (file)
@@ -2470,32 +2470,38 @@ ExecInitExprRec(Expr *node, ExprState *state,
                }
                else
                {
+                   JsonConstructorExprState *jcstate;
+
+                   jcstate = palloc0(sizeof(JsonConstructorExprState));
+
                    scratch.opcode = EEOP_JSON_CONSTRUCTOR;
-                   scratch.d.json_constructor.constructor = ctor;
-                   scratch.d.json_constructor.arg_values = palloc(sizeof(Datum) * nargs);
-                   scratch.d.json_constructor.arg_nulls = palloc(sizeof(bool) * nargs);
-                   scratch.d.json_constructor.arg_types = palloc(sizeof(Oid) * nargs);
-                   scratch.d.json_constructor.nargs = nargs;
+                   scratch.d.json_constructor.jcstate = jcstate;
+
+                   jcstate->constructor = ctor;
+                   jcstate->arg_values = palloc(sizeof(Datum) * nargs);
+                   jcstate->arg_nulls = palloc(sizeof(bool) * nargs);
+                   jcstate->arg_types = palloc(sizeof(Oid) * nargs);
+                   jcstate->nargs = nargs;
 
                    foreach(lc, args)
                    {
                        Expr       *arg = (Expr *) lfirst(lc);
 
-                       scratch.d.json_constructor.arg_types[argno] = exprType((Node *) arg);
+                       jcstate->arg_types[argno] = exprType((Node *) arg);
 
                        if (IsA(arg, Const))
                        {
                            /* Don't evaluate const arguments every round */
                            Const      *con = (Const *) arg;
 
-                           scratch.d.json_constructor.arg_values[argno] = con->constvalue;
-                           scratch.d.json_constructor.arg_nulls[argno] = con->constisnull;
+                           jcstate->arg_values[argno] = con->constvalue;
+                           jcstate->arg_nulls[argno] = con->constisnull;
                        }
                        else
                        {
                            ExecInitExprRec(arg, state,
-                                           &scratch.d.json_constructor.arg_values[argno],
-                                           &scratch.d.json_constructor.arg_nulls[argno]);
+                                           &jcstate->arg_values[argno],
+                                           &jcstate->arg_nulls[argno]);
                        }
                        argno++;
                    }
@@ -2506,14 +2512,14 @@ ExecInitExprRec(Expr *node, ExprState *state,
                        bool        is_jsonb =
                        ctor->returning->format->format_type == JS_FORMAT_JSONB;
 
-                       scratch.d.json_constructor.arg_type_cache =
-                           palloc(sizeof(*scratch.d.json_constructor.arg_type_cache) * nargs);
+                       jcstate->arg_type_cache =
+                           palloc(sizeof(*jcstate->arg_type_cache) * nargs);
 
                        for (int i = 0; i < nargs; i++)
                        {
                            int         category;
                            Oid         outfuncid;
-                           Oid         typid = scratch.d.json_constructor.arg_types[i];
+                           Oid         typid = jcstate->arg_types[i];
 
                            if (is_jsonb)
                            {
@@ -2532,8 +2538,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
                                category = (int) jscat;
                            }
 
-                           scratch.d.json_constructor.arg_type_cache[i].outfuncid = outfuncid;
-                           scratch.d.json_constructor.arg_type_cache[i].category = category;
+                           jcstate->arg_type_cache[i].outfuncid = outfuncid;
+                           jcstate->arg_type_cache[i].category = category;
                        }
                    }
 
@@ -2572,41 +2578,44 @@ ExecInitExprRec(Expr *node, ExprState *state,
        case T_JsonExpr:
            {
                JsonExpr   *jexpr = castNode(JsonExpr, node);
+               JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
                ListCell   *argexprlc;
                ListCell   *argnamelc;
 
                scratch.opcode = EEOP_JSONEXPR;
-               scratch.d.jsonexpr.jsexpr = jexpr;
+               scratch.d.jsonexpr.jsestate = jsestate;
+
+               jsestate->jsexpr = jexpr;
 
-               scratch.d.jsonexpr.formatted_expr =
-                   palloc(sizeof(*scratch.d.jsonexpr.formatted_expr));
+               jsestate->formatted_expr =
+                   palloc(sizeof(*jsestate->formatted_expr));
 
                ExecInitExprRec((Expr *) jexpr->formatted_expr, state,
-                               &scratch.d.jsonexpr.formatted_expr->value,
-                               &scratch.d.jsonexpr.formatted_expr->isnull);
+                               &jsestate->formatted_expr->value,
+                               &jsestate->formatted_expr->isnull);
 
-               scratch.d.jsonexpr.pathspec =
-                   palloc(sizeof(*scratch.d.jsonexpr.pathspec));
+               jsestate->pathspec =
+                   palloc(sizeof(*jsestate->pathspec));
 
                ExecInitExprRec((Expr *) jexpr->path_spec, state,
-                               &scratch.d.jsonexpr.pathspec->value,
-                               &scratch.d.jsonexpr.pathspec->isnull);
+                               &jsestate->pathspec->value,
+                               &jsestate->pathspec->isnull);
 
-               scratch.d.jsonexpr.res_expr =
-                   palloc(sizeof(*scratch.d.jsonexpr.res_expr));
+               jsestate->res_expr =
+                   palloc(sizeof(*jsestate->res_expr));
 
-               scratch.d.jsonexpr.result_expr = jexpr->result_coercion
+               jsestate->result_expr = jexpr->result_coercion
                    ? ExecInitExprWithCaseValue((Expr *) jexpr->result_coercion->expr,
                                                state->parent,
-                                               &scratch.d.jsonexpr.res_expr->value,
-                                               &scratch.d.jsonexpr.res_expr->isnull)
+                                               &jsestate->res_expr->value,
+                                               &jsestate->res_expr->isnull)
                    : NULL;
 
-               scratch.d.jsonexpr.default_on_empty = !jexpr->on_empty ? NULL :
+               jsestate->default_on_empty = !jexpr->on_empty ? NULL :
                    ExecInitExpr((Expr *) jexpr->on_empty->default_expr,
                                 state->parent);
 
-               scratch.d.jsonexpr.default_on_error =
+               jsestate->default_on_error =
                    ExecInitExpr((Expr *) jexpr->on_error->default_expr,
                                 state->parent);
 
@@ -2617,11 +2626,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
                    /* lookup the result type's input function */
                    getTypeInputInfo(jexpr->returning->typid, &typinput,
-                                    &scratch.d.jsonexpr.input.typioparam);
-                   fmgr_info(typinput, &scratch.d.jsonexpr.input.func);
+                                    &jsestate->input.typioparam);
+                   fmgr_info(typinput, &jsestate->input.func);
                }
 
-               scratch.d.jsonexpr.args = NIL;
+               jsestate->args = NIL;
 
                forboth(argexprlc, jexpr->passing_values,
                        argnamelc, jexpr->passing_names)
@@ -2640,11 +2649,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
                    var->value = (Datum) 0;
                    var->isnull = true;
 
-                   scratch.d.jsonexpr.args =
-                       lappend(scratch.d.jsonexpr.args, var);
+                   jsestate->args =
+                       lappend(jsestate->args, var);
                }
 
-               scratch.d.jsonexpr.cache = NULL;
+               jsestate->cache = NULL;
 
                if (jexpr->coercions)
                {
@@ -2653,13 +2662,13 @@ ExecInitExprRec(Expr *node, ExprState *state,
                    Datum      *caseval;
                    bool       *casenull;
 
-                   scratch.d.jsonexpr.coercion_expr =
-                       palloc(sizeof(*scratch.d.jsonexpr.coercion_expr));
+                   jsestate->coercion_expr =
+                       palloc(sizeof(*jsestate->coercion_expr));
 
-                   caseval = &scratch.d.jsonexpr.coercion_expr->value;
-                   casenull = &scratch.d.jsonexpr.coercion_expr->isnull;
+                   caseval = &jsestate->coercion_expr->value;
+                   casenull = &jsestate->coercion_expr->isnull;
 
-                   for (cstate = &scratch.d.jsonexpr.coercions.null,
+                   for (cstate = &jsestate->coercions.null,
                         coercion = &jexpr->coercions->null;
                         coercion <= &jexpr->coercions->composite;
                         coercion++, cstate++)
index eaec697bb38ab0afb9beb728d435f678953e1727..80c5e04dd5fb2f6b6486975b77eb6f95f6694352 100644 (file)
@@ -4510,39 +4510,40 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
                        ExprContext *econtext)
 {
    Datum       res;
-   JsonConstructorExpr *ctor = op->d.json_constructor.constructor;
+   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) (op->d.json_constructor.nargs,
-                                        op->d.json_constructor.arg_values,
-                                        op->d.json_constructor.arg_nulls,
-                                        op->d.json_constructor.arg_types,
-                                        op->d.json_constructor.constructor->absent_on_null);
+              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) (op->d.json_constructor.nargs,
-                                         op->d.json_constructor.arg_values,
-                                         op->d.json_constructor.arg_nulls,
-                                         op->d.json_constructor.arg_types,
-                                         op->d.json_constructor.constructor->absent_on_null,
-                                         op->d.json_constructor.constructor->unique);
+              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 (op->d.json_constructor.arg_nulls[0])
+       if (jcstate->arg_nulls[0])
        {
            res = (Datum) 0;
            isnull = true;
        }
        else
        {
-           Datum       value = op->d.json_constructor.arg_values[0];
-           int         category = op->d.json_constructor.arg_type_cache[0].category;
-           Oid         outfuncid = op->d.json_constructor.arg_type_cache[0].outfuncid;
+           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);
@@ -4552,14 +4553,14 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
    }
    else if (ctor->type == JSCTOR_JSON_PARSE)
    {
-       if (op->d.json_constructor.arg_nulls[0])
+       if (jcstate->arg_nulls[0])
        {
            res = (Datum) 0;
            isnull = true;
        }
        else
        {
-           Datum       value = op->d.json_constructor.arg_values[0];
+           Datum       value = jcstate->arg_values[0];
            text       *js = DatumGetTextP(value);
 
            if (is_jsonb)
@@ -4627,14 +4628,17 @@ 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);
 
-   if (op->d.jsonexpr.jsexpr->op != JSON_EXISTS_OP)
+   jsestate = op->d.jsonexpr.jsestate;
+
+   if (jsestate->jsexpr->op != JSON_EXISTS_OP)
    {
-       JsonCoercion *coercion = op->d.jsonexpr.jsexpr->result_coercion;
-       JsonExpr   *jexpr = op->d.jsonexpr.jsexpr;
+       JsonCoercion *coercion = jsestate->jsexpr->result_coercion;
+       JsonExpr   *jexpr = jsestate->jsexpr;
        Jsonb      *jb = *isNull ? NULL : DatumGetJsonbP(res);
 
        if ((coercion && coercion->via_io) ||
@@ -4644,25 +4648,25 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
            /* strip quotes and call typinput function */
            char       *str = *isNull ? NULL : JsonbUnquote(jb);
 
-           return InputFunctionCall(&op->d.jsonexpr.input.func, str,
-                                    op->d.jsonexpr.input.typioparam,
+           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,
-                                     &op->d.jsonexpr.cache,
+                                     &jsestate->cache,
                                      econtext->ecxt_per_query_memory,
                                      isNull);
    }
 
-   if (op->d.jsonexpr.result_expr)
+   if (jsestate->result_expr)
    {
-       op->d.jsonexpr.res_expr->value = res;
-       op->d.jsonexpr.res_expr->isnull = *isNull;
+       jsestate->res_expr->value = res;
+       jsestate->res_expr->isnull = *isNull;
 
-       res = ExecEvalExpr(op->d.jsonexpr.result_expr, econtext, isNull);
+       res = ExecEvalExpr(jsestate->result_expr, econtext, isNull);
    }
 
    return res;
@@ -4895,7 +4899,8 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
 {
    ExecEvalJsonExprContext *cxt = pcxt;
    JsonPath   *path = cxt->path;
-   JsonExpr   *jexpr = op->d.jsonexpr.jsexpr;
+   JsonExprState *jsestate = op->d.jsonexpr.jsestate;
+   JsonExpr   *jexpr = jsestate->jsexpr;
    ExprState  *estate = NULL;
    bool        empty = false;
    Datum       res = (Datum) 0;
@@ -4904,7 +4909,7 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
    {
        case JSON_QUERY_OP:
            res = JsonPathQuery(item, path, jexpr->wrapper, &empty, error,
-                               op->d.jsonexpr.args);
+                               jsestate->args);
            if (error && *error)
            {
                *resnull = true;
@@ -4917,7 +4922,7 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
            {
                struct JsonCoercionState *jcstate;
                JsonbValue *jbv = JsonPathValue(item, path, &empty, error,
-                                               op->d.jsonexpr.args);
+                                               jsestate->args);
 
                if (error && *error)
                    return (Datum) 0;
@@ -4940,8 +4945,8 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
 
                /* Use coercion from SQL/JSON item type to the output type */
                res = ExecPrepareJsonItemCoercion(jbv,
-                                                 op->d.jsonexpr.jsexpr->returning,
-                                                 &op->d.jsonexpr.coercions,
+                                                 jsestate->jsexpr->returning,
+                                                 &jsestate->coercions,
                                                  &jcstate);
 
                if (jcstate->coercion &&
@@ -4973,27 +4978,27 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
 
                /* coerce using specific expression */
                estate = jcstate->estate;
-               op->d.jsonexpr.coercion_expr->value = res;
-               op->d.jsonexpr.coercion_expr->isnull = *resnull;
+               jsestate->coercion_expr->value = res;
+               jsestate->coercion_expr->isnull = *resnull;
                break;
            }
 
        case JSON_EXISTS_OP:
            {
                bool        exists = JsonPathExists(item, path,
-                                                   op->d.jsonexpr.args,
+                                                   jsestate->args,
                                                    error);
 
                *resnull = error && *error;
                res = BoolGetDatum(exists);
 
-               if (!op->d.jsonexpr.result_expr)
+               if (!jsestate->result_expr)
                    return res;
 
                /* coerce using result expression */
-               estate = op->d.jsonexpr.result_expr;
-               op->d.jsonexpr.res_expr->value = res;
-               op->d.jsonexpr.res_expr->isnull = *resnull;
+               estate = jsestate->result_expr;
+               jsestate->res_expr->value = res;
+               jsestate->res_expr->isnull = *resnull;
                break;
            }
 
@@ -5029,11 +5034,11 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
             * Execute DEFAULT expression as a coercion expression, because
             * its result is already coerced to the target type.
             */
-           estate = op->d.jsonexpr.default_on_empty;
+           estate = jsestate->default_on_empty;
        else
            /* Execute ON EMPTY behavior */
            res = ExecEvalJsonBehavior(econtext, jexpr->on_empty,
-                                      op->d.jsonexpr.default_on_empty,
+                                      jsestate->default_on_empty,
                                       resnull);
    }
 
@@ -5066,7 +5071,8 @@ void
 ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 {
    ExecEvalJsonExprContext cxt;
-   JsonExpr   *jexpr = op->d.jsonexpr.jsexpr;
+   JsonExprState *jsestate = op->d.jsonexpr.jsestate;
+   JsonExpr   *jexpr = jsestate->jsexpr;
    Datum       item;
    Datum       res = (Datum) 0;
    JsonPath   *path;
@@ -5078,7 +5084,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    *op->resnull = true;        /* until we get a result */
    *op->resvalue = (Datum) 0;
 
-   if (op->d.jsonexpr.formatted_expr->isnull || op->d.jsonexpr.pathspec->isnull)
+   if (jsestate->formatted_expr->isnull || jsestate->pathspec->isnull)
    {
        /* execute domain checks for NULLs */
        (void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
@@ -5088,11 +5094,11 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
        return;
    }
 
-   item = op->d.jsonexpr.formatted_expr->value;
-   path = DatumGetJsonPathP(op->d.jsonexpr.pathspec->value);
+   item = jsestate->formatted_expr->value;
+   path = DatumGetJsonPathP(jsestate->pathspec->value);
 
    /* reset JSON path variable contexts */
-   foreach(lc, op->d.jsonexpr.args)
+   foreach(lc, jsestate->args)
    {
        JsonPathVariableEvalContext *var = lfirst(lc);
 
@@ -5100,7 +5106,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
        var->evaluated = false;
    }
 
-   needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &op->d.jsonexpr.coercions);
+   needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &jsestate->coercions);
 
    cxt.path = path;
    cxt.error = throwErrors ? NULL : &error;
@@ -5115,7 +5121,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
    {
        /* Execute ON ERROR behavior */
        res = ExecEvalJsonBehavior(econtext, jexpr->on_error,
-                                  op->d.jsonexpr.default_on_error,
+                                  jsestate->default_on_error,
                                   op->resnull);
 
        /* result is already coerced in DEFAULT behavior case */
index e34db8c93cb1bec1b3a70a2cc010c390aa551abc..fa2d9be4c9932fa0b158dd4ef80853d248162c25 100644 (file)
@@ -22,6 +22,8 @@ struct ExprEvalStep;
 struct SubscriptingRefState;
 struct ScalarArrayOpExprHashTable;
 struct JsonbValue;
+struct JsonExprState;
+struct JsonConstructorExprState;
 
 /* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
 /* expression's interpreter has been initialized */
@@ -676,16 +678,7 @@ typedef struct ExprEvalStep
        /* for EEOP_JSON_CONSTRUCTOR */
        struct
        {
-           JsonConstructorExpr *constructor;
-           Datum      *arg_values;
-           bool       *arg_nulls;
-           Oid        *arg_types;
-           struct
-           {
-               int         category;
-               Oid         outfuncid;
-           }          *arg_type_cache; /* cache for datum_to_json[b]() */
-           int         nargs;
+           struct JsonConstructorExprState *jcstate;
        }           json_constructor;
 
        /* for EEOP_IS_JSON */
@@ -697,45 +690,7 @@ typedef struct ExprEvalStep
        /* for EEOP_JSONEXPR */
        struct
        {
-           JsonExpr   *jsexpr; /* original expression node */
-
-           struct
-           {
-               FmgrInfo    func;   /* typinput function for output type */
-               Oid         typioparam;
-           }           input;  /* I/O info for output type */
-
-           NullableDatum
-                      *formatted_expr, /* formatted context item value */
-                      *res_expr,   /* result item */
-                      *coercion_expr,  /* input for JSON item coercion */
-                      *pathspec;   /* path specification value */
-
-           ExprState  *result_expr;    /* coerced to output type */
-           ExprState  *default_on_empty;   /* ON EMPTY DEFAULT expression */
-           ExprState  *default_on_error;   /* ON ERROR DEFAULT expression */
-           List       *args;   /* passing arguments */
-
-           void       *cache;  /* cache for json_populate_type() */
-
-           struct JsonCoercionsState
-           {
-               struct JsonCoercionState
-               {
-                   JsonCoercion *coercion; /* coercion expression */
-                   ExprState  *estate; /* coercion expression state */
-               }           null,
-                           string,
-               numeric    ,
-                           boolean,
-                           date,
-                           time,
-                           timetz,
-                           timestamp,
-                           timestamptz,
-                           composite;
-           }           coercions;  /* states for coercion from SQL/JSON item
-                                    * types directly to the output type */
+           struct JsonExprState *jsestate;
        }           jsonexpr;
 
    }           d;
@@ -782,6 +737,64 @@ typedef struct SubscriptExecSteps
    ExecEvalSubroutine sbs_fetch_old;   /* fetch old value for assignment */
 } SubscriptExecSteps;
 
+/* EEOP_JSON_CONSTRUCTOR state, too big to inline */
+typedef struct JsonConstructorExprState
+{
+   JsonConstructorExpr *constructor;
+   Datum      *arg_values;
+   bool       *arg_nulls;
+   Oid        *arg_types;
+   struct
+   {
+       int         category;
+       Oid         outfuncid;
+   }          *arg_type_cache; /* cache for datum_to_json[b]() */
+   int         nargs;
+} JsonConstructorExprState;
+
+/* EEOP_JSONEXPR state, too big to inline */
+typedef struct JsonExprState
+{
+   JsonExpr   *jsexpr;         /* original expression node */
+
+   struct
+   {
+       FmgrInfo    func;       /* typinput function for output type */
+       Oid         typioparam;
+   }           input;          /* I/O info for output type */
+
+   NullableDatum
+              *formatted_expr, /* formatted context item value */
+              *res_expr,       /* result item */
+              *coercion_expr,  /* input for JSON item coercion */
+              *pathspec;       /* path specification value */
+
+   ExprState  *result_expr;    /* coerced to output type */
+   ExprState  *default_on_empty;   /* ON EMPTY DEFAULT expression */
+   ExprState  *default_on_error;   /* ON ERROR DEFAULT expression */
+   List       *args;           /* passing arguments */
+
+   void       *cache;          /* cache for json_populate_type() */
+
+   struct JsonCoercionsState
+   {
+       struct JsonCoercionState
+       {
+           JsonCoercion *coercion; /* coercion expression */
+           ExprState  *estate; /* coercion expression state */
+       }           null,
+                   string,
+       numeric    ,
+                   boolean,
+                   date,
+                   time,
+                   timetz,
+                   timestamp,
+                   timestamptz,
+                   composite;
+   }           coercions;      /* states for coercion from SQL/JSON item
+                                * types directly to the output type */
+} JsonExprState;
 
 /* functions in execExpr.c */
 extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
index 4fb746930aa099e5b926307b3a3c792ad8be90ba..c7f550e822d5ba895ec33dca2ef94a84ec123bea 100644 (file)
@@ -1237,10 +1237,12 @@ JsonBehaviorType
 JsonCoercion
 JsonCommon
 JsonConstructorExpr
+JsonConstructorExprState
 JsonConstructorType
 JsonEncoding
 JsonExpr
 JsonExprOp
+JsonExprState
 JsonFormat
 JsonFormatType
 JsonFunc