45
45
#include "pgstat.h"
46
46
#include "utils/builtins.h"
47
47
#include "utils/datum.h"
48
+ #include "utils/jsonpath.h"
48
49
#include "utils/lsyscache.h"
49
50
#include "utils/typcache.h"
50
51
@@ -81,6 +82,40 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
81
82
int transno , int setno , int setoff , bool ishash );
82
83
83
84
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
+
84
119
/*
85
120
* ExecInitExpr: prepare an expression tree for execution
86
121
*
@@ -119,32 +154,7 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
119
154
ExprState *
120
155
ExecInitExpr (Expr * node , PlanState * parent )
121
156
{
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 );
148
158
}
149
159
150
160
/*
@@ -156,32 +166,20 @@ ExecInitExpr(Expr *node, PlanState *parent)
156
166
ExprState *
157
167
ExecInitExprWithParams (Expr * node , ParamListInfo ext_params )
158
168
{
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
+ }
183
171
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 );
185
183
}
186
184
187
185
/*
@@ -2115,6 +2113,126 @@ ExecInitExprRec(Expr *node, ExprState *state,
2115
2113
break ;
2116
2114
}
2117
2115
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
+
2118
2236
default :
2119
2237
elog (ERROR , "unrecognized node type: %d" ,
2120
2238
(int ) nodeTag (node ));
0 commit comments