diff options
Diffstat (limited to 'src/pl')
| -rw-r--r-- | src/pl/plperl/plperl.c | 3 | ||||
| -rw-r--r-- | src/pl/plpgsql/src/pl_comp.c | 89 | ||||
| -rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 12 | ||||
| -rw-r--r-- | src/pl/plpgsql/src/pl_gram.y | 4 | ||||
| -rw-r--r-- | src/pl/plpgsql/src/plpgsql.h | 1 | ||||
| -rw-r--r-- | src/pl/plpython/plpy_procedure.c | 4 | ||||
| -rw-r--r-- | src/pl/tcl/pltcl.c | 4 |
7 files changed, 61 insertions, 56 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 77c41b28215..fa8e2fdc695 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -2832,7 +2832,8 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger) * Get the required information for input conversion of the * return value. ************************************************************/ - if (!is_trigger && !is_event_trigger && procStruct->prorettype) + if (!is_trigger && !is_event_trigger && + procStruct->prokind != PROKIND_PROCEDURE) { Oid rettype = procStruct->prorettype; diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index d07a16a7ea3..391ec41b802 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -275,6 +275,7 @@ do_compile(FunctionCallInfo fcinfo, bool isnull; char *proc_source; HeapTuple typeTup; + Form_pg_type typeStruct; PLpgSQL_variable *var; PLpgSQL_rec *rec; int i; @@ -365,6 +366,8 @@ do_compile(FunctionCallInfo fcinfo, else function->fn_is_trigger = PLPGSQL_NOT_TRIGGER; + function->fn_prokind = procStruct->prokind; + /* * Initialize the compiler, particularly the namespace stack. The * outermost namespace contains function parameters and other special @@ -529,55 +532,50 @@ do_compile(FunctionCallInfo fcinfo, /* * Lookup the function's return type */ - if (rettypeid) + typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid)); + if (!HeapTupleIsValid(typeTup)) + elog(ERROR, "cache lookup failed for type %u", rettypeid); + typeStruct = (Form_pg_type) GETSTRUCT(typeTup); + + /* Disallow pseudotype result, except VOID or RECORD */ + /* (note we already replaced polymorphic types) */ + if (typeStruct->typtype == TYPTYPE_PSEUDO) { - Form_pg_type typeStruct; - - typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid)); - if (!HeapTupleIsValid(typeTup)) - elog(ERROR, "cache lookup failed for type %u", rettypeid); - typeStruct = (Form_pg_type) GETSTRUCT(typeTup); - - /* Disallow pseudotype result, except VOID or RECORD */ - /* (note we already replaced polymorphic types) */ - if (typeStruct->typtype == TYPTYPE_PSEUDO) - { - if (rettypeid == VOIDOID || - rettypeid == RECORDOID) - /* okay */ ; - else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("trigger functions can only be called as triggers"))); - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("PL/pgSQL functions cannot return type %s", - format_type_be(rettypeid)))); - } - - function->fn_retistuple = type_is_rowtype(rettypeid); - function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN); - function->fn_retbyval = typeStruct->typbyval; - function->fn_rettyplen = typeStruct->typlen; + if (rettypeid == VOIDOID || + rettypeid == RECORDOID) + /* okay */ ; + else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("trigger functions can only be called as triggers"))); + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("PL/pgSQL functions cannot return type %s", + format_type_be(rettypeid)))); + } - /* - * install $0 reference, but only for polymorphic return - * types, and not when the return is specified through an - * output parameter. - */ - if (IsPolymorphicType(procStruct->prorettype) && - num_out_args == 0) - { - (void) plpgsql_build_variable("$0", 0, - build_datatype(typeTup, - -1, - function->fn_input_collation), - true); - } + function->fn_retistuple = type_is_rowtype(rettypeid); + function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN); + function->fn_retbyval = typeStruct->typbyval; + function->fn_rettyplen = typeStruct->typlen; - ReleaseSysCache(typeTup); + /* + * install $0 reference, but only for polymorphic return + * types, and not when the return is specified through an + * output parameter. + */ + if (IsPolymorphicType(procStruct->prorettype) && + num_out_args == 0) + { + (void) plpgsql_build_variable("$0", 0, + build_datatype(typeTup, + -1, + function->fn_input_collation), + true); } + + ReleaseSysCache(typeTup); break; case PLPGSQL_DML_TRIGGER: @@ -890,6 +888,7 @@ plpgsql_compile_inline(char *proc_source) function->fn_retset = false; function->fn_retistuple = false; function->fn_retisdomain = false; + function->fn_prokind = PROKIND_FUNCTION; /* a bit of hardwired knowledge about type VOID here */ function->fn_retbyval = true; function->fn_rettyplen = sizeof(int32); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 4ff87e08799..297aa3e4732 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -573,7 +573,7 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, estate.err_text = NULL; estate.err_stmt = (PLpgSQL_stmt *) (func->action); rc = exec_stmt_block(&estate, func->action); - if (rc != PLPGSQL_RC_RETURN && func->fn_rettype) + if (rc != PLPGSQL_RC_RETURN) { estate.err_stmt = NULL; estate.err_text = NULL; @@ -617,9 +617,10 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, } else if (!estate.retisnull) { - if (!func->fn_rettype) + if (func->fn_prokind == PROKIND_PROCEDURE) ereport(ERROR, - (errmsg("cannot return a value from a procedure"))); + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot return a value from a procedure"))); /* * Cast result value to function's declared result type, and copy it @@ -2956,9 +2957,10 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt) /* * Special hack for function returning VOID: instead of NULL, return a * non-null VOID value. This is of dubious importance but is kept for - * backwards compatibility. + * backwards compatibility. We don't do it for procedures, though. */ - if (estate->fn_rettype == VOIDOID) + if (estate->fn_rettype == VOIDOID && + estate->func->fn_prokind != PROKIND_PROCEDURE) { estate->retval = (Datum) 0; estate->retisnull = false; diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y index 688fbd6531e..697ead0570e 100644 --- a/src/pl/plpgsql/src/pl_gram.y +++ b/src/pl/plpgsql/src/pl_gram.y @@ -16,6 +16,7 @@ #include "postgres.h" #include "catalog/namespace.h" +#include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "parser/parser.h" #include "parser/parse_type.h" @@ -3137,7 +3138,8 @@ make_return_stmt(int location) parser_errposition(yylloc))); new->retvarno = plpgsql_curr_compile->out_param_varno; } - else if (plpgsql_curr_compile->fn_rettype == VOIDOID) + else if (plpgsql_curr_compile->fn_rettype == VOIDOID && + plpgsql_curr_compile->fn_prokind != PROKIND_PROCEDURE) { if (yylex() != ';') ereport(ERROR, diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index 26a7344e9a6..dd59036de09 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -918,6 +918,7 @@ typedef struct PLpgSQL_function bool fn_retisdomain; bool fn_retset; bool fn_readonly; + char fn_prokind; int fn_nargs; int fn_argvarnos[FUNC_MAX_ARGS]; diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c index 4e06413cd4e..82cc3f28b8d 100644 --- a/src/pl/plpython/plpy_procedure.c +++ b/src/pl/plpython/plpy_procedure.c @@ -188,7 +188,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) proc->fn_tid = procTup->t_self; proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE); proc->is_setof = procStruct->proretset; - proc->is_procedure = (procStruct->prorettype == InvalidOid); + proc->is_procedure = (procStruct->prokind == PROKIND_PROCEDURE); proc->src = NULL; proc->argnames = NULL; proc->args = NULL; @@ -208,7 +208,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger) * get information required for output conversion of the return value, * but only if this isn't a trigger or procedure. */ - if (!is_trigger && procStruct->prorettype) + if (!is_trigger && procStruct->prokind != PROKIND_PROCEDURE) { Oid rettype = procStruct->prorettype; HeapTuple rvTypeTup; diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 5df4dfdf552..2eb6c337aae 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -1523,9 +1523,9 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, * Get the required information for input conversion of the * return value. ************************************************************/ - prodesc->fn_is_procedure = (procStruct->prorettype == InvalidOid); + prodesc->fn_is_procedure = (procStruct->prokind == PROKIND_PROCEDURE); - if (!is_trigger && !is_event_trigger && procStruct->prorettype) + if (!is_trigger && !is_event_trigger && !prodesc->fn_is_procedure) { Oid rettype = procStruct->prorettype; |
