/* * Logic for set-returning functions. * * Currently it uses the simplest, return * one value/tuple per call mechanism. */ static Datum handle_ret_set(FunctionCallInfo fcinfo) { ProxyFunction *func; FuncCallContext *ret_ctx; if (SRF_IS_FIRSTCALL()) { func = compile_and_execute(fcinfo); ret_ctx = SRF_FIRSTCALL_INIT(); ret_ctx->user_fctx = func; } ret_ctx = SRF_PERCALL_SETUP(); func = ret_ctx->user_fctx; if (func->cur_cluster->ret_total > 0) { SRF_RETURN_NEXT(ret_ctx, plproxy_result(func, fcinfo)); } else { plproxy_clean_results(func->cur_cluster); SRF_RETURN_DONE(ret_ctx); } }
/* * The PostgreSQL function & trigger manager calls this function * for execution of PL/Proxy procedures. * * Main entry point for rest of the code. */ Datum plproxy_call_handler(PG_FUNCTION_ARGS) { ProxyFunction *func; Datum ret; if (CALLED_AS_TRIGGER(fcinfo)) elog(ERROR, "PL/Proxy procedures can't be used as triggers"); /* clean old results */ if (!fcinfo->flinfo->fn_retset || SRF_IS_FIRSTCALL()) run_maint(); if (fcinfo->flinfo->fn_retset) { ret = handle_ret_set(fcinfo); } else { func = compile_and_execute(fcinfo); if (func->cur_cluster->ret_total != 1) plproxy_error_with_state(func, (func->cur_cluster->ret_total < 1) ? ERRCODE_NO_DATA_FOUND : ERRCODE_TOO_MANY_ROWS, "Non-SETOF function requires 1 row from remote query, got %d", func->cur_cluster->ret_total); ret = plproxy_result(func, fcinfo); plproxy_clean_results(func->cur_cluster); } return ret; }
/* * Centralised error reporting. * * Also frees any pending results. */ void plproxy_error(ProxyFunction *func, const char *fmt,...) { char msg[1024]; va_list ap; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); plproxy_clean_results(func->cur_cluster); elog(ERROR, "PL/Proxy function %s(%d): %s", func->name, func->arg_count, msg); }
/* * Centralised error reporting. * * Also frees any pending results. */ void plproxy_error_with_state(ProxyFunction *func, int sqlstate, const char *fmt, ...) { char msg[1024]; va_list ap; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); plproxy_clean_results(func->cur_cluster); ereport(ERROR, ( errcode(sqlstate), errmsg("PL/Proxy function %s(%d): %s", func->name, func->arg_count, msg))); }