| 227 | PG_FUNCTION_INFO_V1(plpgsql_call_handler); |
| 228 | |
| 229 | Datum |
| 230 | plpgsql_call_handler(PG_FUNCTION_ARGS) |
| 231 | { |
| 232 | bool nonatomic; |
| 233 | PLpgSQL_function *func; |
| 234 | PLpgSQL_execstate *save_cur_estate; |
| 235 | ResourceOwner procedure_resowner; |
| 236 | volatile Datum retval = (Datum) 0; |
| 237 | int rc; |
| 238 | |
| 239 | nonatomic = fcinfo->context && |
| 240 | IsA(fcinfo->context, CallContext) && |
| 241 | !castNode(CallContext, fcinfo->context)->atomic; |
| 242 | |
| 243 | /* |
| 244 | * Connect to SPI manager |
| 245 | */ |
| 246 | if ((rc = SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0)) != SPI_OK_CONNECT) |
| 247 | elog(ERROR, "SPI_connect failed: %s", SPI_result_code_string(rc)); |
| 248 | |
| 249 | /* Find or compile the function */ |
| 250 | func = plpgsql_compile(fcinfo, false); |
| 251 | |
| 252 | /* Must save and restore prior value of cur_estate */ |
| 253 | save_cur_estate = func->cur_estate; |
| 254 | |
| 255 | /* Mark the function as busy, so it can't be deleted from under us */ |
| 256 | func->use_count++; |
| 257 | |
| 258 | /* |
| 259 | * If we'll need a procedure-lifespan resowner to execute any CALL or DO |
| 260 | * statements, create it now. Since this resowner is not tied to any |
| 261 | * parent, failing to free it would result in process-lifespan leaks. |
| 262 | * Therefore, be very wary of adding any code between here and the PG_TRY |
| 263 | * block. |
| 264 | */ |
| 265 | procedure_resowner = |
| 266 | (nonatomic && func->requires_procedure_resowner) ? |
| 267 | ResourceOwnerCreate(NULL, "PL/pgSQL procedure resources") : NULL; |
| 268 | |
| 269 | PG_TRY(); |
| 270 | { |
| 271 | /* |
| 272 | * Determine if called as function or trigger and call appropriate |
| 273 | * subhandler |
| 274 | */ |
| 275 | if (CALLED_AS_TRIGGER(fcinfo)) |
| 276 | retval = PointerGetDatum(plpgsql_exec_trigger(func, |
| 277 | (TriggerData *) fcinfo->context)); |
| 278 | else if (CALLED_AS_EVENT_TRIGGER(fcinfo)) |
| 279 | { |
| 280 | plpgsql_exec_event_trigger(func, |
| 281 | (EventTriggerData *) fcinfo->context); |
| 282 | /* there's no return value in this case */ |
| 283 | } |
| 284 | else |
| 285 | retval = plpgsql_exec_function(func, fcinfo, |
| 286 | NULL, NULL, |
nothing calls this directly
no test coverage detected