mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +03:00
Code review for function default parameters patch. Fix numerous problems as
per recent discussions. In passing this also fixes a couple of bugs in the previous variadic-parameters patch.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.155 2008/12/04 17:51:26 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.156 2008/12/18 18:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "funcapi.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "tcop/pquery.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
@@ -73,10 +74,10 @@ ProcedureCreate(const char *procedureName,
|
||||
Datum allParameterTypes,
|
||||
Datum parameterModes,
|
||||
Datum parameterNames,
|
||||
List *parameterDefaults,
|
||||
Datum proconfig,
|
||||
float4 procost,
|
||||
float4 prorows,
|
||||
List *parameterDefaults)
|
||||
float4 prorows)
|
||||
{
|
||||
Oid retval;
|
||||
int parameterCount;
|
||||
@@ -311,11 +312,8 @@ ProcedureCreate(const char *procedureName,
|
||||
values[Anum_pg_proc_proargnames - 1] = parameterNames;
|
||||
else
|
||||
nulls[Anum_pg_proc_proargnames - 1] = true;
|
||||
if (parameterDefaults != PointerGetDatum(NULL))
|
||||
{
|
||||
Assert(list_length(parameterDefaults) > 0);
|
||||
if (parameterDefaults != NIL)
|
||||
values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults));
|
||||
}
|
||||
else
|
||||
nulls[Anum_pg_proc_proargdefaults - 1] = true;
|
||||
values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
|
||||
@@ -389,6 +387,57 @@ ProcedureCreate(const char *procedureName,
|
||||
errhint("Use DROP FUNCTION first.")));
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are existing defaults, check compatibility: redefinition
|
||||
* must not remove any defaults nor change their types. (Removing
|
||||
* a default might cause a function to fail to satisfy an existing
|
||||
* call. Changing type would only be possible if the associated
|
||||
* parameter is polymorphic, and in such cases a change of default
|
||||
* type might alter the resolved output type of existing calls.)
|
||||
*/
|
||||
if (oldproc->pronargdefaults != 0)
|
||||
{
|
||||
Datum proargdefaults;
|
||||
bool isnull;
|
||||
List *oldDefaults;
|
||||
ListCell *oldlc;
|
||||
ListCell *newlc;
|
||||
|
||||
if (list_length(parameterDefaults) < oldproc->pronargdefaults)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("cannot remove parameter defaults from existing function"),
|
||||
errhint("Use DROP FUNCTION first.")));
|
||||
|
||||
proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
|
||||
Anum_pg_proc_proargdefaults,
|
||||
&isnull);
|
||||
Assert(!isnull);
|
||||
oldDefaults = (List *) stringToNode(TextDatumGetCString(proargdefaults));
|
||||
Assert(IsA(oldDefaults, List));
|
||||
Assert(list_length(oldDefaults) == oldproc->pronargdefaults);
|
||||
|
||||
/* new list can have more defaults than old, advance over 'em */
|
||||
newlc = list_head(parameterDefaults);
|
||||
for (i = list_length(parameterDefaults) - oldproc->pronargdefaults;
|
||||
i > 0;
|
||||
i--)
|
||||
newlc = lnext(newlc);
|
||||
|
||||
foreach(oldlc, oldDefaults)
|
||||
{
|
||||
Node *oldDef = (Node *) lfirst(oldlc);
|
||||
Node *newDef = (Node *) lfirst(newlc);
|
||||
|
||||
if (exprType(oldDef) != exprType(newDef))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("cannot change data type of existing parameter default value"),
|
||||
errhint("Use DROP FUNCTION first.")));
|
||||
newlc = lnext(newlc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Can't change aggregate status, either */
|
||||
if (oldproc->proisagg != isAgg)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user