summaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/functioncmds.c87
-rw-r--r--src/backend/commands/proclang.c25
-rw-r--r--src/backend/commands/trigger.c23
-rw-r--r--src/backend/commands/typecmds.c282
4 files changed, 99 insertions, 318 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 6d824a5ebfb..43a23c69af3 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1399,93 +1399,6 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
return address;
}
-/*
- * SetFunctionReturnType - change declared return type of a function
- *
- * This is presently only used for adjusting legacy functions that return
- * OPAQUE to return whatever we find their correct definition should be.
- * The caller should emit a suitable warning explaining what we did.
- */
-void
-SetFunctionReturnType(Oid funcOid, Oid newRetType)
-{
- Relation pg_proc_rel;
- HeapTuple tup;
- Form_pg_proc procForm;
- ObjectAddress func_address;
- ObjectAddress type_address;
-
- pg_proc_rel = table_open(ProcedureRelationId, RowExclusiveLock);
-
- tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
- if (!HeapTupleIsValid(tup)) /* should not happen */
- elog(ERROR, "cache lookup failed for function %u", funcOid);
- procForm = (Form_pg_proc) GETSTRUCT(tup);
-
- if (procForm->prorettype != OPAQUEOID) /* caller messed up */
- elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
-
- /* okay to overwrite copied tuple */
- procForm->prorettype = newRetType;
-
- /* update the catalog and its indexes */
- CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
-
- table_close(pg_proc_rel, RowExclusiveLock);
-
- /*
- * Also update the dependency to the new type. Opaque is a pinned type, so
- * there is no old dependency record for it that we would need to remove.
- */
- ObjectAddressSet(type_address, TypeRelationId, newRetType);
- ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
- recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
-}
-
-
-/*
- * SetFunctionArgType - change declared argument type of a function
- *
- * As above, but change an argument's type.
- */
-void
-SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
-{
- Relation pg_proc_rel;
- HeapTuple tup;
- Form_pg_proc procForm;
- ObjectAddress func_address;
- ObjectAddress type_address;
-
- pg_proc_rel = table_open(ProcedureRelationId, RowExclusiveLock);
-
- tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(funcOid));
- if (!HeapTupleIsValid(tup)) /* should not happen */
- elog(ERROR, "cache lookup failed for function %u", funcOid);
- procForm = (Form_pg_proc) GETSTRUCT(tup);
-
- if (argIndex < 0 || argIndex >= procForm->pronargs ||
- procForm->proargtypes.values[argIndex] != OPAQUEOID)
- elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
-
- /* okay to overwrite copied tuple */
- procForm->proargtypes.values[argIndex] = newArgType;
-
- /* update the catalog and its indexes */
- CatalogTupleUpdate(pg_proc_rel, &tup->t_self, tup);
-
- table_close(pg_proc_rel, RowExclusiveLock);
-
- /*
- * Also update the dependency to the new type. Opaque is a pinned type, so
- * there is no old dependency record for it that we would need to remove.
- */
- ObjectAddressSet(type_address, TypeRelationId, newArgType);
- ObjectAddressSet(func_address, ProcedureRelationId, funcOid);
- recordDependencyOn(&func_address, &type_address, DEPENDENCY_NORMAL);
-}
-
-
/*
* CREATE CAST
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 9d72edbfec5..21ceeb7e9a1 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -74,27 +74,10 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
handlerOid = LookupFuncName(stmt->plhandler, 0, NULL, false);
funcrettype = get_func_rettype(handlerOid);
if (funcrettype != LANGUAGE_HANDLEROID)
- {
- /*
- * We allow OPAQUE just so we can load old dump files. When we see a
- * handler function declared OPAQUE, change it to LANGUAGE_HANDLER.
- * (This is probably obsolete and removable?)
- */
- if (funcrettype == OPAQUEOID)
- {
- ereport(WARNING,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("changing return type of function %s from %s to %s",
- NameListToString(stmt->plhandler),
- "opaque", "language_handler")));
- SetFunctionReturnType(handlerOid, LANGUAGE_HANDLEROID);
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("function %s must return type %s",
- NameListToString(stmt->plhandler), "language_handler")));
- }
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("function %s must return type %s",
+ NameListToString(stmt->plhandler), "language_handler")));
/* validate the inline function */
if (stmt->plinline)
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 35b4bb35106..b408efb11ea 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -694,25 +694,10 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
}
funcrettype = get_func_rettype(funcoid);
if (funcrettype != TRIGGEROID)
- {
- /*
- * We allow OPAQUE just so we can load old dump files. When we see a
- * trigger function declared OPAQUE, change it to TRIGGER.
- */
- if (funcrettype == OPAQUEOID)
- {
- ereport(WARNING,
- (errmsg("changing return type of function %s from %s to %s",
- NameListToString(stmt->funcname),
- "opaque", "trigger")));
- SetFunctionReturnType(funcoid, TRIGGEROID);
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("function %s must return type %s",
- NameListToString(stmt->funcname), "trigger")));
- }
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("function %s must return type %s",
+ NameListToString(stmt->funcname), "trigger")));
/*
* If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 99528bf1d58..d732a3af450 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -163,7 +163,6 @@ DefineType(ParseState *pstate, List *names, List *parameters)
char *array_type;
Oid array_oid;
Oid typoid;
- Oid resulttype;
ListCell *pl;
ObjectAddress address;
@@ -196,8 +195,7 @@ DefineType(ParseState *pstate, List *names, List *parameters)
#endif
/*
- * Look to see if type already exists (presumably as a shell; if not,
- * TypeCreate will complain).
+ * Look to see if type already exists.
*/
typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
CStringGetDatum(typeName),
@@ -211,35 +209,37 @@ DefineType(ParseState *pstate, List *names, List *parameters)
{
if (moveArrayTypeName(typoid, typeName, typeNamespace))
typoid = InvalidOid;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" already exists", typeName)));
}
/*
- * If it doesn't exist, create it as a shell, so that the OID is known for
- * use in the I/O function definitions.
+ * If this command is a parameterless CREATE TYPE, then we're just here to
+ * make a shell type, so do that (or fail if there already is a shell).
*/
- if (!OidIsValid(typoid))
+ if (parameters == NIL)
{
- address = TypeShellMake(typeName, typeNamespace, GetUserId());
- typoid = address.objectId;
- /* Make new shell type visible for modification below */
- CommandCounterIncrement();
-
- /*
- * If the command was a parameterless CREATE TYPE, we're done ---
- * creating the shell type was all we're supposed to do.
- */
- if (parameters == NIL)
- return address;
- }
- else
- {
- /* Complain if dummy CREATE TYPE and entry already exists */
- if (parameters == NIL)
+ if (OidIsValid(typoid))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("type \"%s\" already exists", typeName)));
+
+ address = TypeShellMake(typeName, typeNamespace, GetUserId());
+ return address;
}
+ /*
+ * Otherwise, we must already have a shell type, since there is no other
+ * way that the I/O functions could have been created.
+ */
+ if (!OidIsValid(typoid))
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" does not exist", typeName),
+ errhint("Create the type as a shell type, then create its I/O functions, then do a full CREATE TYPE.")));
+
/* Extract the parameters from the parameter list */
foreach(pl, parameters)
{
@@ -445,63 +445,6 @@ DefineType(ParseState *pstate, List *names, List *parameters)
sendOid = findTypeSendFunction(sendName, typoid);
/*
- * Verify that I/O procs return the expected thing. If we see OPAQUE,
- * complain and change it to the correct type-safe choice.
- */
- resulttype = get_func_rettype(inputOid);
- if (resulttype != typoid)
- {
- if (resulttype == OPAQUEOID)
- {
- /* backwards-compatibility hack */
- ereport(WARNING,
- (errmsg("changing return type of function %s from %s to %s",
- NameListToString(inputName), "opaque", typeName)));
- SetFunctionReturnType(inputOid, typoid);
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("type input function %s must return type %s",
- NameListToString(inputName), typeName)));
- }
- resulttype = get_func_rettype(outputOid);
- if (resulttype != CSTRINGOID)
- {
- if (resulttype == OPAQUEOID)
- {
- /* backwards-compatibility hack */
- ereport(WARNING,
- (errmsg("changing return type of function %s from %s to %s",
- NameListToString(outputName), "opaque", "cstring")));
- SetFunctionReturnType(outputOid, CSTRINGOID);
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("type output function %s must return type %s",
- NameListToString(outputName), "cstring")));
- }
- if (receiveOid)
- {
- resulttype = get_func_rettype(receiveOid);
- if (resulttype != typoid)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("type receive function %s must return type %s",
- NameListToString(receiveName), typeName)));
- }
- if (sendOid)
- {
- resulttype = get_func_rettype(sendOid);
- if (resulttype != BYTEAOID)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("type send function %s must return type %s",
- NameListToString(sendName), "bytea")));
- }
-
- /*
* Convert typmodin/out function proc names to OIDs.
*/
if (typmodinName)
@@ -1404,16 +1347,9 @@ DefineRange(CreateRangeStmt *stmt)
}
/*
- * If it doesn't exist, create it as a shell, so that the OID is known for
- * use in the range function definitions.
+ * Unlike DefineType(), we don't insist on a shell type existing first, as
+ * it's only needed if the user wants to specify a canonical function.
*/
- if (!OidIsValid(typoid))
- {
- address = TypeShellMake(typeName, typeNamespace, GetUserId());
- typoid = address.objectId;
- /* Make new shell type visible for modification below */
- CommandCounterIncrement();
- }
/* Extract the parameters from the parameter list */
foreach(lc, stmt->params)
@@ -1502,8 +1438,15 @@ DefineRange(CreateRangeStmt *stmt)
/* Identify support functions, if provided */
if (rangeCanonicalName != NIL)
+ {
+ if (!OidIsValid(typoid))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("cannot specify a canonical function without a pre-created shell type"),
+ errhint("Create the type as a shell type, then create its canonicalization function, then do a full CREATE TYPE.")));
rangeCanonical = findRangeCanonicalFunction(rangeCanonicalName,
typoid);
+ }
else
rangeCanonical = InvalidOid;
@@ -1555,7 +1498,8 @@ DefineRange(CreateRangeStmt *stmt)
0, /* Array dimensions of typbasetype */
false, /* Type NOT NULL */
InvalidOid); /* type's collation (ranges never have one) */
- Assert(typoid == address.objectId);
+ Assert(typoid == InvalidOid || typoid == address.objectId);
+ typoid = address.objectId;
/* Create the entry in pg_range */
RangeCreate(typoid, rangeSubtype, rangeCollation, rangeSubOpclass,
@@ -1695,63 +1639,32 @@ findTypeInputFunction(List *procname, Oid typeOid)
/*
* Input functions can take a single argument of type CSTRING, or three
- * arguments (string, typioparam OID, typmod).
- *
- * For backwards compatibility we allow OPAQUE in place of CSTRING; if we
- * see this, we issue a warning and fix up the pg_proc entry.
+ * arguments (string, typioparam OID, typmod). They must return the
+ * target type.
*/
argList[0] = CSTRINGOID;
procOid = LookupFuncName(procname, 1, argList, true);
- if (OidIsValid(procOid))
- return procOid;
-
- argList[1] = OIDOID;
- argList[2] = INT4OID;
-
- procOid = LookupFuncName(procname, 3, argList, true);
- if (OidIsValid(procOid))
- return procOid;
-
- /* No luck, try it with OPAQUE */
- argList[0] = OPAQUEOID;
-
- procOid = LookupFuncName(procname, 1, argList, true);
-
if (!OidIsValid(procOid))
{
argList[1] = OIDOID;
argList[2] = INT4OID;
procOid = LookupFuncName(procname, 3, argList, true);
+ if (!OidIsValid(procOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function %s does not exist",
+ func_signature_string(procname, 1, NIL, argList))));
}
- if (OidIsValid(procOid))
- {
- /* Found, but must complain and fix the pg_proc entry */
- ereport(WARNING,
- (errmsg("changing argument type of function %s from \"opaque\" to \"cstring\"",
- NameListToString(procname))));
- SetFunctionArgType(procOid, 0, CSTRINGOID);
-
- /*
- * Need CommandCounterIncrement since DefineType will likely try to
- * alter the pg_proc tuple again.
- */
- CommandCounterIncrement();
-
- return procOid;
- }
-
- /* Use CSTRING (preferred) in the error message */
- argList[0] = CSTRINGOID;
-
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("function %s does not exist",
- func_signature_string(procname, 1, NIL, argList))));
+ if (get_func_rettype(procOid) != typeOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("type input function %s must return type %s",
+ NameListToString(procname), format_type_be(typeOid))));
- return InvalidOid; /* keep compiler quiet */
+ return procOid;
}
static Oid
@@ -1761,48 +1674,25 @@ findTypeOutputFunction(List *procname, Oid typeOid)
Oid procOid;
/*
- * Output functions can take a single argument of the type.
- *
- * For backwards compatibility we allow OPAQUE in place of the actual type
- * name; if we see this, we issue a warning and fix up the pg_proc entry.
+ * Output functions always take a single argument of the type and return
+ * cstring.
*/
argList[0] = typeOid;
procOid = LookupFuncName(procname, 1, argList, true);
- if (OidIsValid(procOid))
- return procOid;
-
- /* No luck, try it with OPAQUE */
- argList[0] = OPAQUEOID;
-
- procOid = LookupFuncName(procname, 1, argList, true);
-
- if (OidIsValid(procOid))
- {
- /* Found, but must complain and fix the pg_proc entry */
- ereport(WARNING,
- (errmsg("changing argument type of function %s from \"opaque\" to %s",
- NameListToString(procname), format_type_be(typeOid))));
- SetFunctionArgType(procOid, 0, typeOid);
-
- /*
- * Need CommandCounterIncrement since DefineType will likely try to
- * alter the pg_proc tuple again.
- */
- CommandCounterIncrement();
-
- return procOid;
- }
-
- /* Use type name, not OPAQUE, in the failure message. */
- argList[0] = typeOid;
+ if (!OidIsValid(procOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function %s does not exist",
+ func_signature_string(procname, 1, NIL, argList))));
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("function %s does not exist",
- func_signature_string(procname, 1, NIL, argList))));
+ if (get_func_rettype(procOid) != CSTRINGOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("type output function %s must return type %s",
+ NameListToString(procname), "cstring")));
- return InvalidOid; /* keep compiler quiet */
+ return procOid;
}
static Oid
@@ -1813,27 +1703,32 @@ findTypeReceiveFunction(List *procname, Oid typeOid)
/*
* Receive functions can take a single argument of type INTERNAL, or three
- * arguments (internal, typioparam OID, typmod).
+ * arguments (internal, typioparam OID, typmod). They must return the
+ * target type.
*/
argList[0] = INTERNALOID;
procOid = LookupFuncName(procname, 1, argList, true);
- if (OidIsValid(procOid))
- return procOid;
-
- argList[1] = OIDOID;
- argList[2] = INT4OID;
+ if (!OidIsValid(procOid))
+ {
+ argList[1] = OIDOID;
+ argList[2] = INT4OID;
- procOid = LookupFuncName(procname, 3, argList, true);
- if (OidIsValid(procOid))
- return procOid;
+ procOid = LookupFuncName(procname, 3, argList, true);
+ if (!OidIsValid(procOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function %s does not exist",
+ func_signature_string(procname, 1, NIL, argList))));
+ }
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("function %s does not exist",
- func_signature_string(procname, 1, NIL, argList))));
+ if (get_func_rettype(procOid) != typeOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("type receive function %s must return type %s",
+ NameListToString(procname), format_type_be(typeOid))));
- return InvalidOid; /* keep compiler quiet */
+ return procOid;
}
static Oid
@@ -1843,20 +1738,25 @@ findTypeSendFunction(List *procname, Oid typeOid)
Oid procOid;
/*
- * Send functions can take a single argument of the type.
+ * Send functions always take a single argument of the type and return
+ * bytea.
*/
argList[0] = typeOid;
procOid = LookupFuncName(procname, 1, argList, true);
- if (OidIsValid(procOid))
- return procOid;
+ if (!OidIsValid(procOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("function %s does not exist",
+ func_signature_string(procname, 1, NIL, argList))));
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("function %s does not exist",
- func_signature_string(procname, 1, NIL, argList))));
+ if (get_func_rettype(procOid) != BYTEAOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("type send function %s must return type %s",
+ NameListToString(procname), "bytea")));
- return InvalidOid; /* keep compiler quiet */
+ return procOid;
}
static Oid