summaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
authorPeter Eisentraut2018-03-02 13:57:38 +0000
committerPeter Eisentraut2018-03-02 18:48:33 +0000
commitfd1a421fe66173fb9b85d3fe150afde8e812cbe4 (patch)
tree24c80c87337ec2d1bb46ee8463207d0cfff5ffc3 /src/pl
parent1733460f0205fc6d6bbe4c14911049a918c6e073 (diff)
Add prokind column, replacing proisagg and proiswindow
The new column distinguishes normal functions, procedures, aggregates, and window functions. This replaces the existing columns proisagg and proiswindow, and replaces the convention that procedures are indicated by prorettype == 0. Also change prorettype to be VOIDOID for procedures. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Michael Paquier <michael@paquier.xyz>
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;