summaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/pl')
-rw-r--r--src/pl/plperl/plperl.c3
-rw-r--r--src/pl/plpgsql/src/pl_comp.c89
-rw-r--r--src/pl/plpgsql/src/pl_exec.c12
-rw-r--r--src/pl/plpgsql/src/pl_gram.y4
-rw-r--r--src/pl/plpgsql/src/plpgsql.h1
-rw-r--r--src/pl/plpython/plpy_procedure.c4
-rw-r--r--src/pl/tcl/pltcl.c4
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;