4545#include "pgstat.h"
4646#include "utils/builtins.h"
4747#include "utils/datum.h"
48+ #include "utils/jsonpath.h"
4849#include "utils/lsyscache.h"
4950#include "utils/typcache.h"
5051
@@ -81,6 +82,40 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
8182 int transno , int setno , int setoff , bool ishash );
8283
8384
85+ static ExprState *
86+ ExecInitExprInternal (Expr * node , PlanState * parent , ParamListInfo ext_params ,
87+ Datum * caseval , bool * casenull )
88+ {
89+ ExprState * state ;
90+ ExprEvalStep scratch = {0 };
91+
92+ /* Special case: NULL expression produces a NULL ExprState pointer */
93+ if (node == NULL )
94+ return NULL ;
95+
96+ /* Initialize ExprState with empty step list */
97+ state = makeNode (ExprState );
98+ state -> expr = node ;
99+ state -> parent = parent ;
100+ state -> ext_params = ext_params ;
101+ state -> innermost_caseval = caseval ;
102+ state -> innermost_casenull = casenull ;
103+
104+ /* Insert EEOP_*_FETCHSOME steps as needed */
105+ ExecInitExprSlots (state , (Node * ) node );
106+
107+ /* Compile the expression proper */
108+ ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
109+
110+ /* Finally, append a DONE step */
111+ scratch .opcode = EEOP_DONE ;
112+ ExprEvalPushStep (state , & scratch );
113+
114+ ExecReadyExpr (state );
115+
116+ return state ;
117+ }
118+
84119/*
85120 * ExecInitExpr: prepare an expression tree for execution
86121 *
@@ -119,32 +154,7 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
119154ExprState *
120155ExecInitExpr (Expr * node , PlanState * parent )
121156{
122- ExprState * state ;
123- ExprEvalStep scratch = {0 };
124-
125- /* Special case: NULL expression produces a NULL ExprState pointer */
126- if (node == NULL )
127- return NULL ;
128-
129- /* Initialize ExprState with empty step list */
130- state = makeNode (ExprState );
131- state -> expr = node ;
132- state -> parent = parent ;
133- state -> ext_params = NULL ;
134-
135- /* Insert EEOP_*_FETCHSOME steps as needed */
136- ExecInitExprSlots (state , (Node * ) node );
137-
138- /* Compile the expression proper */
139- ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
140-
141- /* Finally, append a DONE step */
142- scratch .opcode = EEOP_DONE ;
143- ExprEvalPushStep (state , & scratch );
144-
145- ExecReadyExpr (state );
146-
147- return state ;
157+ return ExecInitExprInternal (node , parent , NULL , NULL , NULL );
148158}
149159
150160/*
@@ -156,32 +166,20 @@ ExecInitExpr(Expr *node, PlanState *parent)
156166ExprState *
157167ExecInitExprWithParams (Expr * node , ParamListInfo ext_params )
158168{
159- ExprState * state ;
160- ExprEvalStep scratch = {0 };
161-
162- /* Special case: NULL expression produces a NULL ExprState pointer */
163- if (node == NULL )
164- return NULL ;
165-
166- /* Initialize ExprState with empty step list */
167- state = makeNode (ExprState );
168- state -> expr = node ;
169- state -> parent = NULL ;
170- state -> ext_params = ext_params ;
171-
172- /* Insert EEOP_*_FETCHSOME steps as needed */
173- ExecInitExprSlots (state , (Node * ) node );
174-
175- /* Compile the expression proper */
176- ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
177-
178- /* Finally, append a DONE step */
179- scratch .opcode = EEOP_DONE ;
180- ExprEvalPushStep (state , & scratch );
181-
182- ExecReadyExpr (state );
169+ return ExecInitExprInternal (node , NULL , ext_params , NULL , NULL );
170+ }
183171
184- return state ;
172+ /*
173+ * ExecInitExprWithCaseValue: prepare an expression tree for execution
174+ *
175+ * This is the same as ExecInitExpr, except that a pointer to the value for
176+ * CasTestExpr is passed here.
177+ */
178+ ExprState *
179+ ExecInitExprWithCaseValue (Expr * node , PlanState * parent ,
180+ Datum * caseval , bool * casenull )
181+ {
182+ return ExecInitExprInternal (node , parent , NULL , caseval , casenull );
185183}
186184
187185/*
@@ -2115,6 +2113,126 @@ ExecInitExprRec(Expr *node, ExprState *state,
21152113 break ;
21162114 }
21172115
2116+ case T_JsonValueExpr :
2117+ ExecInitExprRec (((JsonValueExpr * ) node )-> expr , state , resv ,
2118+ resnull );
2119+ break ;
2120+
2121+ case T_JsonExpr :
2122+ {
2123+ JsonExpr * jexpr = castNode (JsonExpr , node );
2124+ ListCell * argexprlc ;
2125+ ListCell * argnamelc ;
2126+
2127+ scratch .opcode = EEOP_JSONEXPR ;
2128+ scratch .d .jsonexpr .jsexpr = jexpr ;
2129+
2130+ scratch .d .jsonexpr .raw_expr =
2131+ palloc (sizeof (* scratch .d .jsonexpr .raw_expr ));
2132+
2133+ ExecInitExprRec ((Expr * ) jexpr -> raw_expr , state ,
2134+ & scratch .d .jsonexpr .raw_expr -> value ,
2135+ & scratch .d .jsonexpr .raw_expr -> isnull );
2136+
2137+ scratch .d .jsonexpr .pathspec =
2138+ palloc (sizeof (* scratch .d .jsonexpr .pathspec ));
2139+
2140+ ExecInitExprRec ((Expr * ) jexpr -> path_spec , state ,
2141+ & scratch .d .jsonexpr .pathspec -> value ,
2142+ & scratch .d .jsonexpr .pathspec -> isnull );
2143+
2144+ scratch .d .jsonexpr .formatted_expr =
2145+ ExecInitExprWithCaseValue ((Expr * ) jexpr -> formatted_expr ,
2146+ state -> parent ,
2147+ & scratch .d .jsonexpr .raw_expr -> value ,
2148+ & scratch .d .jsonexpr .raw_expr -> isnull );
2149+
2150+ scratch .d .jsonexpr .res_expr =
2151+ palloc (sizeof (* scratch .d .jsonexpr .res_expr ));
2152+
2153+
2154+ scratch .d .jsonexpr .result_expr = jexpr -> result_coercion
2155+ ? ExecInitExprWithCaseValue ((Expr * ) jexpr -> result_coercion -> expr ,
2156+ state -> parent ,
2157+ & scratch .d .jsonexpr .res_expr -> value ,
2158+ & scratch .d .jsonexpr .res_expr -> isnull )
2159+ : NULL ;
2160+
2161+ scratch .d .jsonexpr .default_on_empty =
2162+ ExecInitExpr ((Expr * ) jexpr -> on_empty .default_expr ,
2163+ state -> parent );
2164+
2165+ scratch .d .jsonexpr .default_on_error =
2166+ ExecInitExpr ((Expr * ) jexpr -> on_error .default_expr ,
2167+ state -> parent );
2168+
2169+ if (jexpr -> omit_quotes ||
2170+ (jexpr -> result_coercion && jexpr -> result_coercion -> via_io ))
2171+ {
2172+ Oid typinput ;
2173+
2174+ /* lookup the result type's input function */
2175+ getTypeInputInfo (jexpr -> returning .typid , & typinput ,
2176+ & scratch .d .jsonexpr .input .typioparam );
2177+ fmgr_info (typinput , & scratch .d .jsonexpr .input .func );
2178+ }
2179+
2180+ scratch .d .jsonexpr .args = NIL ;
2181+
2182+ forboth (argexprlc , jexpr -> passing .values ,
2183+ argnamelc , jexpr -> passing .names )
2184+ {
2185+ Expr * argexpr = (Expr * ) lfirst (argexprlc );
2186+ Value * argname = (Value * ) lfirst (argnamelc );
2187+ JsonPathVariableEvalContext * var = palloc (sizeof (* var ));
2188+
2189+ var -> var .varName = cstring_to_text (argname -> val .str );
2190+ var -> var .typid = exprType ((Node * ) argexpr );
2191+ var -> var .typmod = exprTypmod ((Node * ) argexpr );
2192+ var -> var .cb = EvalJsonPathVar ;
2193+ var -> var .cb_arg = var ;
2194+ var -> estate = ExecInitExpr (argexpr , state -> parent );
2195+ var -> econtext = NULL ;
2196+ var -> evaluated = false;
2197+ var -> value = (Datum ) 0 ;
2198+ var -> isnull = true;
2199+
2200+ scratch .d .jsonexpr .args =
2201+ lappend (scratch .d .jsonexpr .args , var );
2202+ }
2203+
2204+ scratch .d .jsonexpr .cache = NULL ;
2205+
2206+ if (jexpr -> coercions )
2207+ {
2208+ JsonCoercion * * coercion ;
2209+ struct JsonCoercionState * cstate ;
2210+ Datum * caseval ;
2211+ bool * casenull ;
2212+
2213+ scratch .d .jsonexpr .coercion_expr =
2214+ palloc (sizeof (* scratch .d .jsonexpr .coercion_expr ));
2215+
2216+ caseval = & scratch .d .jsonexpr .coercion_expr -> value ;
2217+ casenull = & scratch .d .jsonexpr .coercion_expr -> isnull ;
2218+
2219+ for (cstate = & scratch .d .jsonexpr .coercions .null ,
2220+ coercion = & jexpr -> coercions -> null ;
2221+ coercion <= & jexpr -> coercions -> composite ;
2222+ coercion ++ , cstate ++ )
2223+ {
2224+ cstate -> coercion = * coercion ;
2225+ cstate -> estate = * coercion ?
2226+ ExecInitExprWithCaseValue ((Expr * )(* coercion )-> expr ,
2227+ state -> parent ,
2228+ caseval , casenull ) : NULL ;
2229+ }
2230+ }
2231+
2232+ ExprEvalPushStep (state , & scratch );
2233+ }
2234+ break ;
2235+
21182236 default :
21192237 elog (ERROR , "unrecognized node type: %d" ,
21202238 (int ) nodeTag (node ));
0 commit comments