mirror of
https://github.com/postgres/postgres.git
synced 2025-09-03 15:22:11 +03:00
Support for OUT parameters in procedures
Unlike for functions, OUT parameters for procedures are part of the signature. Therefore, they have to be listed in pg_proc.proargtypes as well as mentioned in ALTER PROCEDURE and DROP PROCEDURE. Reviewed-by: Andrew Dunstan <andrew.dunstan@2ndquadrant.com> Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/2b8490fe-51af-e671-c504-47359dc453c5@2ndquadrant.com
This commit is contained in:
@@ -249,6 +249,9 @@ ProcedureCreate(const char *procedureName,
|
||||
elog(ERROR, "variadic parameter must be last");
|
||||
break;
|
||||
case PROARGMODE_OUT:
|
||||
if (OidIsValid(variadicType) && prokind == PROKIND_PROCEDURE)
|
||||
elog(ERROR, "variadic parameter must be last");
|
||||
break;
|
||||
case PROARGMODE_TABLE:
|
||||
/* okay */
|
||||
break;
|
||||
@@ -462,10 +465,12 @@ ProcedureCreate(const char *procedureName,
|
||||
if (isnull)
|
||||
proargmodes = PointerGetDatum(NULL); /* just to be sure */
|
||||
|
||||
n_old_arg_names = get_func_input_arg_names(proargnames,
|
||||
n_old_arg_names = get_func_input_arg_names(prokind,
|
||||
proargnames,
|
||||
proargmodes,
|
||||
&old_arg_names);
|
||||
n_new_arg_names = get_func_input_arg_names(parameterNames,
|
||||
n_new_arg_names = get_func_input_arg_names(prokind,
|
||||
parameterNames,
|
||||
parameterModes,
|
||||
&new_arg_names);
|
||||
for (j = 0; j < n_old_arg_names; j++)
|
||||
|
@@ -194,8 +194,8 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
Oid *requiredResultType)
|
||||
{
|
||||
int parameterCount = list_length(parameters);
|
||||
Oid *inTypes;
|
||||
int inCount = 0;
|
||||
Oid *sigArgTypes;
|
||||
int sigArgCount = 0;
|
||||
Datum *allTypes;
|
||||
Datum *paramModes;
|
||||
Datum *paramNames;
|
||||
@@ -209,7 +209,7 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
*variadicArgType = InvalidOid; /* default result */
|
||||
*requiredResultType = InvalidOid; /* default result */
|
||||
|
||||
inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
|
||||
sigArgTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
|
||||
allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
|
||||
paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
|
||||
paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
|
||||
@@ -281,25 +281,21 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
errmsg("functions cannot accept set arguments")));
|
||||
}
|
||||
|
||||
if (objtype == OBJECT_PROCEDURE)
|
||||
{
|
||||
if (fp->mode == FUNC_PARAM_OUT)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("procedures cannot have OUT arguments"),
|
||||
errhint("INOUT arguments are permitted.")));
|
||||
}
|
||||
|
||||
/* handle input parameters */
|
||||
if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
|
||||
isinput = true;
|
||||
|
||||
/* handle signature parameters */
|
||||
if (fp->mode == FUNC_PARAM_IN || fp->mode == FUNC_PARAM_INOUT ||
|
||||
(objtype == OBJECT_PROCEDURE && fp->mode == FUNC_PARAM_OUT) ||
|
||||
fp->mode == FUNC_PARAM_VARIADIC)
|
||||
{
|
||||
/* other input parameters can't follow a VARIADIC parameter */
|
||||
/* other signature parameters can't follow a VARIADIC parameter */
|
||||
if (varCount > 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("VARIADIC parameter must be the last input parameter")));
|
||||
inTypes[inCount++] = toid;
|
||||
isinput = true;
|
||||
errmsg("VARIADIC parameter must be the last signature parameter")));
|
||||
sigArgTypes[sigArgCount++] = toid;
|
||||
}
|
||||
|
||||
/* handle output parameters */
|
||||
@@ -429,7 +425,7 @@ interpret_function_parameter_list(ParseState *pstate,
|
||||
}
|
||||
|
||||
/* Now construct the proper outputs as needed */
|
||||
*parameterTypes = buildoidvector(inTypes, inCount);
|
||||
*parameterTypes = buildoidvector(sigArgTypes, sigArgCount);
|
||||
|
||||
if (outCount > 0 || varCount > 0)
|
||||
{
|
||||
@@ -2067,6 +2063,9 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
|
||||
int nargs;
|
||||
int i;
|
||||
AclResult aclresult;
|
||||
Oid *argtypes;
|
||||
char **argnames;
|
||||
char *argmodes;
|
||||
FmgrInfo flinfo;
|
||||
CallContext *callcontext;
|
||||
EState *estate;
|
||||
@@ -2127,6 +2126,8 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
|
||||
tp);
|
||||
nargs = list_length(fexpr->args);
|
||||
|
||||
get_func_arg_info(tp, &argtypes, &argnames, &argmodes);
|
||||
|
||||
ReleaseSysCache(tp);
|
||||
|
||||
/* safety check; see ExecInitFunc() */
|
||||
@@ -2156,16 +2157,24 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
|
||||
i = 0;
|
||||
foreach(lc, fexpr->args)
|
||||
{
|
||||
ExprState *exprstate;
|
||||
Datum val;
|
||||
bool isnull;
|
||||
if (argmodes && argmodes[i] == PROARGMODE_OUT)
|
||||
{
|
||||
fcinfo->args[i].value = 0;
|
||||
fcinfo->args[i].isnull = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExprState *exprstate;
|
||||
Datum val;
|
||||
bool isnull;
|
||||
|
||||
exprstate = ExecPrepareExpr(lfirst(lc), estate);
|
||||
exprstate = ExecPrepareExpr(lfirst(lc), estate);
|
||||
|
||||
val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
|
||||
val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
|
||||
|
||||
fcinfo->args[i].value = val;
|
||||
fcinfo->args[i].isnull = isnull;
|
||||
fcinfo->args[i].value = val;
|
||||
fcinfo->args[i].isnull = isnull;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
@@ -259,7 +259,8 @@ prepare_sql_fn_parse_info(HeapTuple procedureTuple,
|
||||
if (isNull)
|
||||
proargmodes = PointerGetDatum(NULL); /* just to be sure */
|
||||
|
||||
n_arg_names = get_func_input_arg_names(proargnames, proargmodes,
|
||||
n_arg_names = get_func_input_arg_names(procedureStruct->prokind,
|
||||
proargnames, proargmodes,
|
||||
&pinfo->argnames);
|
||||
|
||||
/* Paranoia: ignore the result if too few array entries */
|
||||
|
@@ -166,7 +166,7 @@ static RoleSpec *makeRoleSpec(RoleSpecType type, int location);
|
||||
static void check_qualified_name(List *names, core_yyscan_t yyscanner);
|
||||
static List *check_func_name(List *names, core_yyscan_t yyscanner);
|
||||
static List *check_indirection(List *indirection, core_yyscan_t yyscanner);
|
||||
static List *extractArgTypes(List *parameters);
|
||||
static List *extractArgTypes(ObjectType objtype, List *parameters);
|
||||
static List *extractAggrArgTypes(List *aggrargs);
|
||||
static List *makeOrderedSetArgs(List *directargs, List *orderedargs,
|
||||
core_yyscan_t yyscanner);
|
||||
@@ -375,8 +375,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
||||
%type <accesspriv> privilege
|
||||
%type <list> privileges privilege_list
|
||||
%type <privtarget> privilege_target
|
||||
%type <objwithargs> function_with_argtypes aggregate_with_argtypes operator_with_argtypes
|
||||
%type <list> function_with_argtypes_list aggregate_with_argtypes_list operator_with_argtypes_list
|
||||
%type <objwithargs> function_with_argtypes aggregate_with_argtypes operator_with_argtypes procedure_with_argtypes function_with_argtypes_common
|
||||
%type <list> function_with_argtypes_list aggregate_with_argtypes_list operator_with_argtypes_list procedure_with_argtypes_list
|
||||
%type <ival> defacl_privilege_target
|
||||
%type <defelt> DefACLOption
|
||||
%type <list> DefACLOptionList
|
||||
@@ -4623,7 +4623,7 @@ AlterExtensionContentsStmt:
|
||||
n->object = (Node *) lcons(makeString($9), $7);
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER EXTENSION name add_drop PROCEDURE function_with_argtypes
|
||||
| ALTER EXTENSION name add_drop PROCEDURE procedure_with_argtypes
|
||||
{
|
||||
AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
|
||||
n->extname = $3;
|
||||
@@ -4632,7 +4632,7 @@ AlterExtensionContentsStmt:
|
||||
n->object = (Node *) $6;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER EXTENSION name add_drop ROUTINE function_with_argtypes
|
||||
| ALTER EXTENSION name add_drop ROUTINE procedure_with_argtypes
|
||||
{
|
||||
AlterExtensionContentsStmt *n = makeNode(AlterExtensionContentsStmt);
|
||||
n->extname = $3;
|
||||
@@ -6365,7 +6365,7 @@ CommentStmt:
|
||||
n->comment = $8;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| COMMENT ON PROCEDURE function_with_argtypes IS comment_text
|
||||
| COMMENT ON PROCEDURE procedure_with_argtypes IS comment_text
|
||||
{
|
||||
CommentStmt *n = makeNode(CommentStmt);
|
||||
n->objtype = OBJECT_PROCEDURE;
|
||||
@@ -6373,7 +6373,7 @@ CommentStmt:
|
||||
n->comment = $6;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| COMMENT ON ROUTINE function_with_argtypes IS comment_text
|
||||
| COMMENT ON ROUTINE procedure_with_argtypes IS comment_text
|
||||
{
|
||||
CommentStmt *n = makeNode(CommentStmt);
|
||||
n->objtype = OBJECT_ROUTINE;
|
||||
@@ -6519,7 +6519,7 @@ SecLabelStmt:
|
||||
n->label = $9;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| SECURITY LABEL opt_provider ON PROCEDURE function_with_argtypes
|
||||
| SECURITY LABEL opt_provider ON PROCEDURE procedure_with_argtypes
|
||||
IS security_label
|
||||
{
|
||||
SecLabelStmt *n = makeNode(SecLabelStmt);
|
||||
@@ -6880,7 +6880,7 @@ privilege_target:
|
||||
n->objs = $2;
|
||||
$$ = n;
|
||||
}
|
||||
| PROCEDURE function_with_argtypes_list
|
||||
| PROCEDURE procedure_with_argtypes_list
|
||||
{
|
||||
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
|
||||
n->targtype = ACL_TARGET_OBJECT;
|
||||
@@ -6888,7 +6888,7 @@ privilege_target:
|
||||
n->objs = $2;
|
||||
$$ = n;
|
||||
}
|
||||
| ROUTINE function_with_argtypes_list
|
||||
| ROUTINE procedure_with_argtypes_list
|
||||
{
|
||||
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
|
||||
n->targtype = ACL_TARGET_OBJECT;
|
||||
@@ -7409,20 +7409,33 @@ function_with_argtypes_list:
|
||||
{ $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
procedure_with_argtypes_list:
|
||||
procedure_with_argtypes { $$ = list_make1($1); }
|
||||
| procedure_with_argtypes_list ',' procedure_with_argtypes
|
||||
{ $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
function_with_argtypes:
|
||||
func_name func_args
|
||||
{
|
||||
ObjectWithArgs *n = makeNode(ObjectWithArgs);
|
||||
n->objname = $1;
|
||||
n->objargs = extractArgTypes($2);
|
||||
n->objargs = extractArgTypes(OBJECT_FUNCTION, $2);
|
||||
$$ = n;
|
||||
}
|
||||
| function_with_argtypes_common
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
function_with_argtypes_common:
|
||||
/*
|
||||
* Because of reduce/reduce conflicts, we can't use func_name
|
||||
* below, but we can write it out the long way, which actually
|
||||
* allows more cases.
|
||||
*/
|
||||
| type_func_name_keyword
|
||||
type_func_name_keyword
|
||||
{
|
||||
ObjectWithArgs *n = makeNode(ObjectWithArgs);
|
||||
n->objname = list_make1(makeString(pstrdup($1)));
|
||||
@@ -7446,6 +7459,24 @@ function_with_argtypes:
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
* This is different from function_with_argtypes in the call to
|
||||
* extractArgTypes().
|
||||
*/
|
||||
procedure_with_argtypes:
|
||||
func_name func_args
|
||||
{
|
||||
ObjectWithArgs *n = makeNode(ObjectWithArgs);
|
||||
n->objname = $1;
|
||||
n->objargs = extractArgTypes(OBJECT_PROCEDURE, $2);
|
||||
$$ = n;
|
||||
}
|
||||
| function_with_argtypes_common
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
* func_args_with_defaults is separate because we only want to accept
|
||||
* defaults in CREATE FUNCTION, not in ALTER etc.
|
||||
@@ -7824,7 +7855,7 @@ AlterFunctionStmt:
|
||||
n->actions = $4;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| ALTER PROCEDURE function_with_argtypes alterfunc_opt_list opt_restrict
|
||||
| ALTER PROCEDURE procedure_with_argtypes alterfunc_opt_list opt_restrict
|
||||
{
|
||||
AlterFunctionStmt *n = makeNode(AlterFunctionStmt);
|
||||
n->objtype = OBJECT_PROCEDURE;
|
||||
@@ -7832,7 +7863,7 @@ AlterFunctionStmt:
|
||||
n->actions = $4;
|
||||
$$ = (Node *) n;
|
||||
}
|
||||
| ALTER ROUTINE function_with_argtypes alterfunc_opt_list opt_restrict
|
||||
| ALTER ROUTINE procedure_with_argtypes alterfunc_opt_list opt_restrict
|
||||
{
|
||||
AlterFunctionStmt *n = makeNode(AlterFunctionStmt);
|
||||
n->objtype = OBJECT_ROUTINE;
|
||||
@@ -7888,7 +7919,7 @@ RemoveFuncStmt:
|
||||
n->concurrent = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| DROP PROCEDURE function_with_argtypes_list opt_drop_behavior
|
||||
| DROP PROCEDURE procedure_with_argtypes_list opt_drop_behavior
|
||||
{
|
||||
DropStmt *n = makeNode(DropStmt);
|
||||
n->removeType = OBJECT_PROCEDURE;
|
||||
@@ -7898,7 +7929,7 @@ RemoveFuncStmt:
|
||||
n->concurrent = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| DROP PROCEDURE IF_P EXISTS function_with_argtypes_list opt_drop_behavior
|
||||
| DROP PROCEDURE IF_P EXISTS procedure_with_argtypes_list opt_drop_behavior
|
||||
{
|
||||
DropStmt *n = makeNode(DropStmt);
|
||||
n->removeType = OBJECT_PROCEDURE;
|
||||
@@ -7908,7 +7939,7 @@ RemoveFuncStmt:
|
||||
n->concurrent = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| DROP ROUTINE function_with_argtypes_list opt_drop_behavior
|
||||
| DROP ROUTINE procedure_with_argtypes_list opt_drop_behavior
|
||||
{
|
||||
DropStmt *n = makeNode(DropStmt);
|
||||
n->removeType = OBJECT_ROUTINE;
|
||||
@@ -7918,7 +7949,7 @@ RemoveFuncStmt:
|
||||
n->concurrent = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| DROP ROUTINE IF_P EXISTS function_with_argtypes_list opt_drop_behavior
|
||||
| DROP ROUTINE IF_P EXISTS procedure_with_argtypes_list opt_drop_behavior
|
||||
{
|
||||
DropStmt *n = makeNode(DropStmt);
|
||||
n->removeType = OBJECT_ROUTINE;
|
||||
@@ -8393,7 +8424,7 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
|
||||
n->missing_ok = true;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER PROCEDURE function_with_argtypes RENAME TO name
|
||||
| ALTER PROCEDURE procedure_with_argtypes RENAME TO name
|
||||
{
|
||||
RenameStmt *n = makeNode(RenameStmt);
|
||||
n->renameType = OBJECT_PROCEDURE;
|
||||
@@ -8411,7 +8442,7 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
|
||||
n->missing_ok = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER ROUTINE function_with_argtypes RENAME TO name
|
||||
| ALTER ROUTINE procedure_with_argtypes RENAME TO name
|
||||
{
|
||||
RenameStmt *n = makeNode(RenameStmt);
|
||||
n->renameType = OBJECT_ROUTINE;
|
||||
@@ -8822,7 +8853,7 @@ AlterObjectDependsStmt:
|
||||
n->remove = $4;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER PROCEDURE function_with_argtypes opt_no DEPENDS ON EXTENSION name
|
||||
| ALTER PROCEDURE procedure_with_argtypes opt_no DEPENDS ON EXTENSION name
|
||||
{
|
||||
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
|
||||
n->objectType = OBJECT_PROCEDURE;
|
||||
@@ -8831,7 +8862,7 @@ AlterObjectDependsStmt:
|
||||
n->remove = $4;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER ROUTINE function_with_argtypes opt_no DEPENDS ON EXTENSION name
|
||||
| ALTER ROUTINE procedure_with_argtypes opt_no DEPENDS ON EXTENSION name
|
||||
{
|
||||
AlterObjectDependsStmt *n = makeNode(AlterObjectDependsStmt);
|
||||
n->objectType = OBJECT_ROUTINE;
|
||||
@@ -8962,7 +8993,7 @@ AlterObjectSchemaStmt:
|
||||
n->missing_ok = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER PROCEDURE function_with_argtypes SET SCHEMA name
|
||||
| ALTER PROCEDURE procedure_with_argtypes SET SCHEMA name
|
||||
{
|
||||
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
|
||||
n->objectType = OBJECT_PROCEDURE;
|
||||
@@ -8971,7 +9002,7 @@ AlterObjectSchemaStmt:
|
||||
n->missing_ok = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER ROUTINE function_with_argtypes SET SCHEMA name
|
||||
| ALTER ROUTINE procedure_with_argtypes SET SCHEMA name
|
||||
{
|
||||
AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
|
||||
n->objectType = OBJECT_ROUTINE;
|
||||
@@ -9273,7 +9304,7 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
|
||||
n->newowner = $9;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER PROCEDURE function_with_argtypes OWNER TO RoleSpec
|
||||
| ALTER PROCEDURE procedure_with_argtypes OWNER TO RoleSpec
|
||||
{
|
||||
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
||||
n->objectType = OBJECT_PROCEDURE;
|
||||
@@ -9281,7 +9312,7 @@ AlterOwnerStmt: ALTER AGGREGATE aggregate_with_argtypes OWNER TO RoleSpec
|
||||
n->newowner = $6;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| ALTER ROUTINE function_with_argtypes OWNER TO RoleSpec
|
||||
| ALTER ROUTINE procedure_with_argtypes OWNER TO RoleSpec
|
||||
{
|
||||
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
||||
n->objectType = OBJECT_ROUTINE;
|
||||
@@ -16218,13 +16249,14 @@ check_indirection(List *indirection, core_yyscan_t yyscanner)
|
||||
}
|
||||
|
||||
/* extractArgTypes()
|
||||
*
|
||||
* Given a list of FunctionParameter nodes, extract a list of just the
|
||||
* argument types (TypeNames) for input parameters only. This is what
|
||||
* is needed to look up an existing function, which is what is wanted by
|
||||
* the productions that use this call.
|
||||
* argument types (TypeNames) for signature parameters only (e.g., only input
|
||||
* parameters for functions). This is what is needed to look up an existing
|
||||
* function, which is what is wanted by the productions that use this call.
|
||||
*/
|
||||
static List *
|
||||
extractArgTypes(List *parameters)
|
||||
extractArgTypes(ObjectType objtype, List *parameters)
|
||||
{
|
||||
List *result = NIL;
|
||||
ListCell *i;
|
||||
@@ -16233,7 +16265,7 @@ extractArgTypes(List *parameters)
|
||||
{
|
||||
FunctionParameter *p = (FunctionParameter *) lfirst(i);
|
||||
|
||||
if (p->mode != FUNC_PARAM_OUT && p->mode != FUNC_PARAM_TABLE)
|
||||
if ((p->mode != FUNC_PARAM_OUT || objtype == OBJECT_PROCEDURE) && p->mode != FUNC_PARAM_TABLE)
|
||||
result = lappend(result, p->argType);
|
||||
}
|
||||
return result;
|
||||
@@ -16246,7 +16278,7 @@ static List *
|
||||
extractAggrArgTypes(List *aggrargs)
|
||||
{
|
||||
Assert(list_length(aggrargs) == 2);
|
||||
return extractArgTypes((List *) linitial(aggrargs));
|
||||
return extractArgTypes(OBJECT_AGGREGATE, (List *) linitial(aggrargs));
|
||||
}
|
||||
|
||||
/* makeOrderedSetArgs()
|
||||
|
@@ -1233,7 +1233,8 @@ get_func_trftypes(HeapTuple procTup,
|
||||
* are set to NULL. You don't get anything if proargnames is NULL.
|
||||
*/
|
||||
int
|
||||
get_func_input_arg_names(Datum proargnames, Datum proargmodes,
|
||||
get_func_input_arg_names(char prokind,
|
||||
Datum proargnames, Datum proargmodes,
|
||||
char ***arg_names)
|
||||
{
|
||||
ArrayType *arr;
|
||||
@@ -1291,6 +1292,7 @@ get_func_input_arg_names(Datum proargnames, Datum proargmodes,
|
||||
if (argmodes == NULL ||
|
||||
argmodes[i] == PROARGMODE_IN ||
|
||||
argmodes[i] == PROARGMODE_INOUT ||
|
||||
(argmodes[i] == PROARGMODE_OUT && prokind == PROKIND_PROCEDURE) ||
|
||||
argmodes[i] == PROARGMODE_VARIADIC)
|
||||
{
|
||||
char *pname = TextDatumGetCString(argnames[i]);
|
||||
|
Reference in New Issue
Block a user