summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane2021-06-10 21:11:36 +0000
committerTom Lane2021-06-10 21:11:36 +0000
commite56bce5d43789cce95d099554ae9593ada92b3b7 (patch)
tree7c5db32085c578c1ec662a05a4404f75e5f824a9 /src/include
parent3a09d75b4f6cabc8331e228b6988dbfcd9afdfbe (diff)
Reconsider the handling of procedure OUT parameters.
Commit 2453ea142 redefined pg_proc.proargtypes to include the types of OUT parameters, for procedures only. While that had some advantages for implementing the SQL-spec behavior of DROP PROCEDURE, it was pretty disastrous from a number of other perspectives. Notably, since the primary key of pg_proc is name + proargtypes, this made it possible to have multiple procedures with identical names + input arguments and differing output argument types. That would make it impossible to call any one of the procedures by writing just NULL (or "?", or any other data-type-free notation) for the output argument(s). The change also seems likely to cause grave confusion for client applications that examine pg_proc and expect the traditional definition of proargtypes. Hence, revert the definition of proargtypes to what it was, and undo a number of complications that had been added to support that. To support the SQL-spec behavior of DROP PROCEDURE, when there are no argmode markers in the command's parameter list, we perform the lookup both ways (that is, matching against both proargtypes and proallargtypes), succeeding if we get just one unique match. In principle this could result in ambiguous-function failures that would not happen when using only one of the two rules. However, overloading of procedure names is thought to be a pretty rare usage, so this shouldn't cause many problems in practice. Postgres-specific code such as pg_dump can defend against any possibility of such failures by being careful to specify argmodes for all procedure arguments. This also fixes a few other bugs in the area of CALL statements with named parameters, and improves the documentation a little. catversion bump forced because the representation of procedures with OUT arguments changes. Discussion: https://postgr.es/m/3742981.1621533210@sss.pgh.pa.us
Diffstat (limited to 'src/include')
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/namespace.h2
-rw-r--r--src/include/catalog/pg_proc.h2
-rw-r--r--src/include/funcapi.h3
-rw-r--r--src/include/nodes/parsenodes.h37
-rw-r--r--src/include/optimizer/optimizer.h3
-rw-r--r--src/include/parser/parse_func.h1
7 files changed, 36 insertions, 14 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 38fb958a8db..d5dada949c3 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202106062
+#define CATALOG_VERSION_NO 202106101
#endif
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index aa2774e2d4e..b98f2843560 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -30,6 +30,7 @@ typedef struct _FuncCandidateList
struct _FuncCandidateList *next;
int pathpos; /* for internal use of namespace lookup */
Oid oid; /* the function or operator's OID */
+ int nominalnargs; /* either pronargs or length(proallargtypes) */
int nargs; /* number of arg types returned */
int nvargs; /* number of args to become variadic array */
int ndargs; /* number of defaulted args */
@@ -99,6 +100,7 @@ extern FuncCandidateList FuncnameGetCandidates(List *names,
int nargs, List *argnames,
bool expand_variadic,
bool expand_defaults,
+ bool include_out_arguments,
bool missing_ok);
extern bool FunctionIsVisible(Oid funcid);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 448d9898cb3..a65afe7bc4b 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -91,7 +91,7 @@ CATALOG(pg_proc,1255,ProcedureRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81,Proce
* proargtypes
*/
- /* parameter types (excludes OUT params of functions) */
+ /* parameter types (excludes OUT params) */
oidvector proargtypes BKI_LOOKUP(pg_type) BKI_FORCE_NOT_NULL;
#ifdef CATALOG_VARLEN
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
index 83e6bc2a1fb..f1304d47e34 100644
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -172,8 +172,7 @@ extern int get_func_arg_info(HeapTuple procTup,
Oid **p_argtypes, char ***p_argnames,
char **p_argmodes);
-extern int get_func_input_arg_names(char prokind,
- Datum proargnames, Datum proargmodes,
+extern int get_func_input_arg_names(Datum proargnames, Datum proargmodes,
char ***arg_names);
extern int get_func_trftypes(HeapTuple procTup, Oid **p_trftypes);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ef73342019f..58328c43774 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2024,18 +2024,29 @@ typedef struct GrantStmt
} GrantStmt;
/*
- * Note: ObjectWithArgs carries only the types of the input parameters of the
- * function. So it is sufficient to identify an existing function, but it
- * is not enough info to define a function nor to call it.
+ * ObjectWithArgs represents a function/procedure/operator name plus parameter
+ * identification.
+ *
+ * objargs includes only the types of the input parameters of the object.
+ * In some contexts, that will be all we have, and it's enough to look up
+ * objects according to the traditional Postgres rules (i.e., when only input
+ * arguments matter).
+ *
+ * objfuncargs, if not NIL, carries the full specification of the parameter
+ * list, including parameter mode annotations.
+ *
+ * Some grammar productions can set args_unspecified = true instead of
+ * providing parameter info. In this case, lookup will succeed only if
+ * the object name is unique. Note that otherwise, NIL parameter lists
+ * mean zero arguments.
*/
typedef struct ObjectWithArgs
{
NodeTag type;
List *objname; /* qualified name of function/operator */
- List *objargs; /* list of Typename nodes */
- bool args_unspecified; /* argument list was omitted, so name must
- * be unique (note that objargs == NIL
- * means zero args) */
+ List *objargs; /* list of Typename nodes (input args only) */
+ List *objfuncargs; /* list of FunctionParameter nodes */
+ bool args_unspecified; /* argument list was omitted? */
} ObjectWithArgs;
/*
@@ -2955,7 +2966,9 @@ typedef enum FunctionParameterMode
FUNC_PARAM_OUT = 'o', /* output only */
FUNC_PARAM_INOUT = 'b', /* both */
FUNC_PARAM_VARIADIC = 'v', /* variadic (always input) */
- FUNC_PARAM_TABLE = 't' /* table function output column */
+ FUNC_PARAM_TABLE = 't', /* table function output column */
+ /* this is not used in pg_proc: */
+ FUNC_PARAM_DEFAULT = 'd' /* default; effectively same as IN */
} FunctionParameterMode;
typedef struct FunctionParameter
@@ -2998,13 +3011,19 @@ typedef struct InlineCodeBlock
/* ----------------------
* CALL statement
+ *
+ * OUT-mode arguments are removed from the transformed funcexpr. The outargs
+ * list contains copies of the expressions for all output arguments, in the
+ * order of the procedure's declared arguments. (outargs is never evaluated,
+ * but is useful to the caller as a reference for what to assign to.)
* ----------------------
*/
typedef struct CallStmt
{
NodeTag type;
FuncCall *funccall; /* from the parser */
- FuncExpr *funcexpr; /* transformed */
+ FuncExpr *funcexpr; /* transformed call, with only input args */
+ List *outargs; /* transformed output-argument expressions */
} CallStmt;
typedef struct CallContext
diff --git a/src/include/optimizer/optimizer.h b/src/include/optimizer/optimizer.h
index 68ebb84bf5d..41b49b26625 100644
--- a/src/include/optimizer/optimizer.h
+++ b/src/include/optimizer/optimizer.h
@@ -153,7 +153,8 @@ extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
extern Expr *evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
Oid result_collation);
-extern List *expand_function_arguments(List *args, Oid result_type,
+extern List *expand_function_arguments(List *args, bool include_out_arguments,
+ Oid result_type,
struct HeapTupleData *func_tuple);
/* in util/predtest.c: */
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index aaf07f8f73d..57795a86e4a 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -39,6 +39,7 @@ extern FuncDetailCode func_get_detail(List *funcname,
List *fargs, List *fargnames,
int nargs, Oid *argtypes,
bool expand_variadic, bool expand_defaults,
+ bool include_out_arguments,
Oid *funcid, Oid *rettype,
bool *retset, int *nvargs, Oid *vatype,
Oid **true_typeids, List **argdefaults);