* InitFCInfoForCallStmt initializes given fcinfo by evaluating * expressions passed by given CallStmt and utility hook params. */
| 1237 | * expressions passed by given CallStmt and utility hook params. |
| 1238 | */ |
| 1239 | void |
| 1240 | InitFCInfoForCallStmt(FunctionCallInfo fcinfo, const CallStmt *callStmt, |
| 1241 | ProcessUtilityContext context, const ParamListInfo params) |
| 1242 | { |
| 1243 | /* verify that function exists */ |
| 1244 | const FuncExpr *funcexpr = callStmt->funcexpr; |
| 1245 | HeapTuple procTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcexpr->funcid)); |
| 1246 | if (!HeapTupleIsValid(procTuple)) |
| 1247 | { |
| 1248 | ereport(ERROR, (errmsg("The function identified by OID %u could not be found", |
| 1249 | funcexpr->funcid))); |
| 1250 | } |
| 1251 | |
| 1252 | ReleaseSysCache(procTuple); |
| 1253 | |
| 1254 | /* |
| 1255 | * Seems that we don't need to expand function arguments in pg >= 14, see |
| 1256 | * pg commit e56bce5d43789cce95d099554ae9593ada92b3b7. |
| 1257 | * |
| 1258 | * Also, copy expr list in case executor functions scribble on Expr nodes |
| 1259 | * we pass. |
| 1260 | */ |
| 1261 | List *funcexprArgs = copyObject(funcexpr->args); |
| 1262 | |
| 1263 | EState *estate = CreateExecutorState(); |
| 1264 | estate->es_param_list_info = params; |
| 1265 | ExprContext *econtext = CreateExprContext(estate); |
| 1266 | |
| 1267 | int argIdx = 0; |
| 1268 | ListCell *expandedArgCell; |
| 1269 | foreach(expandedArgCell, funcexprArgs) |
| 1270 | { |
| 1271 | ExprState *exprstate = ExecPrepareExpr(lfirst(expandedArgCell), estate); |
| 1272 | |
| 1273 | /* |
| 1274 | * Since we will shutdown estate soon, we should not switch to |
| 1275 | * its per tuple memory context to evaluate params, so we use |
| 1276 | * ExecEvalExpr here instead of ExecEvalExprSwitchContext. |
| 1277 | */ |
| 1278 | bool isnull = false; |
| 1279 | Datum val = ExecEvalExpr(exprstate, econtext, &isnull); |
| 1280 | fcinfo->args[argIdx].value = val; |
| 1281 | fcinfo->args[argIdx].isnull = isnull; |
| 1282 | |
| 1283 | argIdx++; |
| 1284 | } |
| 1285 | |
| 1286 | /* initialize everything except args array, which we've already done */ |
| 1287 | FmgrInfo *flinfo = palloc0(sizeof(FmgrInfo)); |
| 1288 | fmgr_info(funcexpr->funcid, flinfo); |
| 1289 | fmgr_info_set_expr((Node *) funcexpr, flinfo); |
| 1290 | CallContext *callcontext = makeNode(CallContext); |
| 1291 | callcontext->atomic = (!(context == PROCESS_UTILITY_TOPLEVEL || |
| 1292 | context == PROCESS_UTILITY_QUERY_NONATOMIC) || |
| 1293 | IsTransactionBlock()); |
| 1294 | InitFunctionCallInfoData(*fcinfo, flinfo, list_length(funcexprArgs), |
| 1295 | funcexpr->inputcollid, (Node *) callcontext, NULL); |
| 1296 |
no test coverage detected