mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
First bits of work on error message editing.
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.27 2003/07/04 02:51:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.28 2003/07/18 23:20:32 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
@@ -78,11 +78,15 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
if (!get_typisdefined(rettype))
|
||||
{
|
||||
if (languageOid == SQLlanguageId)
|
||||
elog(ERROR, "SQL function cannot return shell type \"%s\"",
|
||||
TypeNameToString(returnType));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("SQL function cannot return shell type %s",
|
||||
TypeNameToString(returnType))));
|
||||
else
|
||||
elog(NOTICE, "Return type \"%s\" is only a shell",
|
||||
TypeNameToString(returnType));
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("return type %s is only a shell",
|
||||
TypeNameToString(returnType))));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -100,11 +104,15 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
*/
|
||||
if (languageOid != INTERNALlanguageId &&
|
||||
languageOid != ClanguageId)
|
||||
elog(ERROR, "Type \"%s\" does not exist", typnam);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type %s does not exist", typnam)));
|
||||
|
||||
/* Otherwise, go ahead and make a shell type */
|
||||
elog(NOTICE, "ProcedureCreate: type %s is not yet defined",
|
||||
typnam);
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type %s is not yet defined", typnam),
|
||||
errdetail("Creating a shell type definition.")));
|
||||
namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
|
||||
&typname);
|
||||
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
|
||||
@@ -112,8 +120,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
rettype = TypeShellMake(typname, namespaceId);
|
||||
if (!OidIsValid(rettype))
|
||||
elog(ERROR, "could not create type %s", typnam);
|
||||
Assert(OidIsValid(rettype));
|
||||
}
|
||||
|
||||
*prorettype_p = rettype;
|
||||
@@ -137,8 +144,10 @@ compute_parameter_types(List *argTypes, Oid languageOid,
|
||||
Oid toid;
|
||||
|
||||
if (parameterCount >= FUNC_MAX_ARGS)
|
||||
elog(ERROR, "functions cannot have more than %d arguments",
|
||||
FUNC_MAX_ARGS);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
|
||||
errmsg("functions cannot have more than %d arguments",
|
||||
FUNC_MAX_ARGS)));
|
||||
|
||||
toid = LookupTypeName(t);
|
||||
if (OidIsValid(toid))
|
||||
@@ -147,21 +156,29 @@ compute_parameter_types(List *argTypes, Oid languageOid,
|
||||
{
|
||||
/* As above, hard error if language is SQL */
|
||||
if (languageOid == SQLlanguageId)
|
||||
elog(ERROR, "SQL function cannot accept shell type \"%s\"",
|
||||
TypeNameToString(t));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("SQL function cannot accept shell type %s",
|
||||
TypeNameToString(t))));
|
||||
else
|
||||
elog(NOTICE, "Argument type \"%s\" is only a shell",
|
||||
TypeNameToString(t));
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("argument type %s is only a shell",
|
||||
TypeNameToString(t))));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "Type \"%s\" does not exist",
|
||||
TypeNameToString(t));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type %s does not exist",
|
||||
TypeNameToString(t))));
|
||||
}
|
||||
|
||||
if (t->setof)
|
||||
elog(ERROR, "Functions cannot accept set arguments");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("functions cannot accept set arguments")));
|
||||
|
||||
parameterTypes[parameterCount++] = toid;
|
||||
}
|
||||
@@ -197,46 +214,61 @@ compute_attributes_sql_style(const List *options,
|
||||
if (strcmp(defel->defname, "as") == 0)
|
||||
{
|
||||
if (as_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
as_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "language") == 0)
|
||||
{
|
||||
if (language_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
language_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "volatility") == 0)
|
||||
{
|
||||
if (volatility_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
volatility_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "strict") == 0)
|
||||
{
|
||||
if (strict_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
strict_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "security") == 0)
|
||||
{
|
||||
if (security_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
security_item = defel;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "invalid CREATE FUNCTION option");
|
||||
elog(ERROR, "option \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
|
||||
if (as_item)
|
||||
*as = (List *) as_item->arg;
|
||||
else
|
||||
elog(ERROR, "no function body specified");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("no function body specified")));
|
||||
|
||||
if (language_item)
|
||||
*language = strVal(language_item->arg);
|
||||
else
|
||||
elog(ERROR, "no language specified");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("no language specified")));
|
||||
|
||||
if (volatility_item)
|
||||
{
|
||||
@@ -247,7 +279,8 @@ compute_attributes_sql_style(const List *options,
|
||||
else if (strcmp(strVal(volatility_item->arg), "volatile") == 0)
|
||||
*volatility_p = PROVOLATILE_VOLATILE;
|
||||
else
|
||||
elog(ERROR, "invalid volatility");
|
||||
elog(ERROR, "invalid volatility \"%s\"",
|
||||
strVal(volatility_item->arg));
|
||||
}
|
||||
|
||||
if (strict_item)
|
||||
@@ -294,8 +327,10 @@ compute_attributes_with_style(List *parameters, bool *isStrict_p, char *volatili
|
||||
*volatility_p = PROVOLATILE_IMMUTABLE;
|
||||
}
|
||||
else
|
||||
elog(WARNING, "Unrecognized function attribute '%s' ignored",
|
||||
param->defname);
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("unrecognized function attribute \"%s\" ignored",
|
||||
param->defname)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,8 +371,10 @@ interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
|
||||
*probin_str_p = "-";
|
||||
|
||||
if (lnext(as) != NIL)
|
||||
elog(ERROR, "CREATE FUNCTION: only one AS item needed for %s language",
|
||||
languageName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
|
||||
errmsg("only one AS item needed for language \"%s\"",
|
||||
languageName)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +433,9 @@ CreateFunction(CreateFunctionStmt *stmt)
|
||||
PointerGetDatum(languageName),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(languageTuple))
|
||||
elog(ERROR, "language \"%s\" does not exist", languageName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("language \"%s\" does not exist", languageName)));
|
||||
|
||||
languageOid = HeapTupleGetOid(languageTuple);
|
||||
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
||||
@@ -501,8 +540,7 @@ RemoveFunction(RemoveFuncStmt *stmt)
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveFunction: couldn't find tuple for function %s",
|
||||
NameListToString(functionName));
|
||||
elog(ERROR, "cache lookup failed for function %u", funcOid);
|
||||
|
||||
/* Permission check: must own func or its namespace */
|
||||
if (!pg_proc_ownercheck(funcOid, GetUserId()) &&
|
||||
@@ -511,15 +549,19 @@ RemoveFunction(RemoveFuncStmt *stmt)
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(functionName));
|
||||
|
||||
if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
|
||||
elog(ERROR, "RemoveFunction: function '%s' is an aggregate"
|
||||
"\n\tUse DROP AGGREGATE to remove it",
|
||||
NameListToString(functionName));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an aggregate function",
|
||||
NameListToString(functionName)),
|
||||
errhint("Use DROP AGGREGATE to drop aggregate functions.")));
|
||||
|
||||
if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
|
||||
{
|
||||
/* "Helpful" NOTICE when removing a builtin function ... */
|
||||
elog(NOTICE, "Removing built-in function \"%s\"",
|
||||
NameListToString(functionName));
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_WARNING),
|
||||
errmsg("removing built-in function \"%s\"",
|
||||
NameListToString(functionName))));
|
||||
}
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
@@ -556,8 +598,7 @@ RemoveFunctionById(Oid funcOid)
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveFunctionById: couldn't find tuple for function %u",
|
||||
funcOid);
|
||||
elog(ERROR, "cache lookup failed for function %u", funcOid);
|
||||
|
||||
isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg;
|
||||
|
||||
@@ -578,8 +619,7 @@ RemoveFunctionById(Oid funcOid)
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveFunctionById: couldn't find pg_aggregate tuple for %u",
|
||||
funcOid);
|
||||
elog(ERROR, "cache lookup failed for pg_aggregate tuple for function %u", funcOid);
|
||||
|
||||
simple_heap_delete(relation, &tup->t_self);
|
||||
|
||||
@@ -598,11 +638,10 @@ RenameFunction(List *name, List *argtypes, const char *newname)
|
||||
{
|
||||
Oid procOid;
|
||||
Oid namespaceOid;
|
||||
Oid oid_array[FUNC_MAX_ARGS];
|
||||
HeapTuple tup;
|
||||
Form_pg_proc procForm;
|
||||
Relation rel;
|
||||
AclResult aclresult;
|
||||
int16 nargs;
|
||||
|
||||
rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
|
||||
|
||||
@@ -612,29 +651,31 @@ RenameFunction(List *name, List *argtypes, const char *newname)
|
||||
ObjectIdGetDatum(procOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RenameFunction: couldn't find pg_proc tuple for %s",
|
||||
NameListToString(name));
|
||||
elog(ERROR, "cache lookup failed for function %u", procOid);
|
||||
procForm = (Form_pg_proc) GETSTRUCT(tup);
|
||||
|
||||
if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
|
||||
if (procForm->proisagg)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
errmsg("%s is an aggregate function", NameListToString(name)),
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an aggregate function",
|
||||
NameListToString(name)),
|
||||
errhint("Use ALTER AGGREGATE to rename aggregate functions.")));
|
||||
|
||||
namespaceOid = ((Form_pg_proc) GETSTRUCT(tup))->pronamespace;
|
||||
namespaceOid = procForm->pronamespace;
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
nargs = compute_parameter_types(argtypes, ((Form_pg_proc) GETSTRUCT(tup))->prolang, oid_array);
|
||||
if (SearchSysCacheExists(PROCNAMENSP,
|
||||
CStringGetDatum(newname),
|
||||
Int16GetDatum(nargs),
|
||||
PointerGetDatum(oid_array),
|
||||
Int16GetDatum(procForm->pronargs),
|
||||
PointerGetDatum(procForm->proargtypes),
|
||||
ObjectIdGetDatum(namespaceOid)))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
errmsg("function %s with the same argument types already exists in schema %s",
|
||||
newname, get_namespace_name(namespaceOid))));
|
||||
(errcode(ERRCODE_DUPLICATE_FUNCTION),
|
||||
errmsg("function %s already exists",
|
||||
func_signature_string(name,
|
||||
procForm->pronargs,
|
||||
procForm->proargtypes))));
|
||||
}
|
||||
|
||||
/* must be owner */
|
||||
@@ -647,7 +688,7 @@ RenameFunction(List *name, List *argtypes, const char *newname)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceOid));
|
||||
|
||||
/* rename */
|
||||
namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname);
|
||||
namestrcpy(&(procForm->proname), newname);
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
@@ -676,13 +717,11 @@ SetFunctionReturnType(Oid funcOid, Oid newRetType)
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "SetFunctionReturnType: couldn't find tuple for function %u",
|
||||
funcOid);
|
||||
elog(ERROR, "cache lookup failed for function %u", funcOid);
|
||||
procForm = (Form_pg_proc) GETSTRUCT(tup);
|
||||
|
||||
if (procForm->prorettype != OPAQUEOID)
|
||||
elog(ERROR, "SetFunctionReturnType: function %u doesn't return OPAQUE",
|
||||
funcOid);
|
||||
if (procForm->prorettype != OPAQUEOID) /* caller messed up */
|
||||
elog(ERROR, "function %u doesn't return OPAQUE", funcOid);
|
||||
|
||||
/* okay to overwrite copied tuple */
|
||||
procForm->prorettype = newRetType;
|
||||
@@ -714,14 +753,12 @@ SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType)
|
||||
ObjectIdGetDatum(funcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "SetFunctionArgType: couldn't find tuple for function %u",
|
||||
funcOid);
|
||||
elog(ERROR, "cache lookup failed for function %u", funcOid);
|
||||
procForm = (Form_pg_proc) GETSTRUCT(tup);
|
||||
|
||||
if (argIndex < 0 || argIndex >= procForm->pronargs ||
|
||||
procForm->proargtypes[argIndex] != OPAQUEOID)
|
||||
elog(ERROR, "SetFunctionArgType: function %u doesn't take OPAQUE",
|
||||
funcOid);
|
||||
elog(ERROR, "function %u doesn't take OPAQUE", funcOid);
|
||||
|
||||
/* okay to overwrite copied tuple */
|
||||
procForm->proargtypes[argIndex] = newArgType;
|
||||
@@ -755,39 +792,56 @@ CreateCast(CreateCastStmt *stmt)
|
||||
|
||||
sourcetypeid = LookupTypeName(stmt->sourcetype);
|
||||
if (!OidIsValid(sourcetypeid))
|
||||
elog(ERROR, "source data type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("source data type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype))));
|
||||
|
||||
targettypeid = LookupTypeName(stmt->targettype);
|
||||
if (!OidIsValid(targettypeid))
|
||||
elog(ERROR, "target data type %s does not exist",
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("target data type %s does not exist",
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
if (sourcetypeid == targettypeid)
|
||||
elog(ERROR, "source data type and target data type are the same");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("source data type and target data type are the same")));
|
||||
|
||||
/* No shells, no pseudo-types allowed */
|
||||
if (!get_typisdefined(sourcetypeid))
|
||||
elog(ERROR, "source data type %s is only a shell",
|
||||
TypeNameToString(stmt->sourcetype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("source data type %s is only a shell",
|
||||
TypeNameToString(stmt->sourcetype))));
|
||||
|
||||
if (!get_typisdefined(targettypeid))
|
||||
elog(ERROR, "target data type %s is only a shell",
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("target data type %s is only a shell",
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
if (get_typtype(sourcetypeid) == 'p')
|
||||
elog(ERROR, "source data type %s is a pseudo-type",
|
||||
TypeNameToString(stmt->sourcetype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("source data type %s is a pseudo-type",
|
||||
TypeNameToString(stmt->sourcetype))));
|
||||
|
||||
if (get_typtype(targettypeid) == 'p')
|
||||
elog(ERROR, "target data type %s is a pseudo-type",
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("target data type %s is a pseudo-type",
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
/* Permission check */
|
||||
if (!pg_type_ownercheck(sourcetypeid, GetUserId())
|
||||
&& !pg_type_ownercheck(targettypeid, GetUserId()))
|
||||
elog(ERROR, "must be owner of type %s or type %s",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be owner of type %s or type %s",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
if (stmt->func != NULL)
|
||||
{
|
||||
@@ -801,15 +855,21 @@ CreateCast(CreateCastStmt *stmt)
|
||||
ObjectIdGetDatum(funcid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cache lookup of function %u failed", funcid);
|
||||
elog(ERROR, "cache lookup failed for function %u", funcid);
|
||||
|
||||
procstruct = (Form_pg_proc) GETSTRUCT(tuple);
|
||||
if (procstruct->pronargs != 1)
|
||||
elog(ERROR, "cast function must take 1 argument");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("cast function must take 1 argument")));
|
||||
if (procstruct->proargtypes[0] != sourcetypeid)
|
||||
elog(ERROR, "argument of cast function must match source data type");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("argument of cast function must match source data type")));
|
||||
if (procstruct->prorettype != targettypeid)
|
||||
elog(ERROR, "return data type of cast function must match target data type");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("return data type of cast function must match target data type")));
|
||||
/*
|
||||
* Restricting the volatility of a cast function may or may not be
|
||||
* a good idea in the abstract, but it definitely breaks many old
|
||||
@@ -817,12 +877,18 @@ CreateCast(CreateCastStmt *stmt)
|
||||
*/
|
||||
#ifdef NOT_USED
|
||||
if (procstruct->provolatile == PROVOLATILE_VOLATILE)
|
||||
elog(ERROR, "cast function must not be volatile");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("cast function must not be volatile")));
|
||||
#endif
|
||||
if (procstruct->proisagg)
|
||||
elog(ERROR, "cast function must not be an aggregate function");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("cast function must not be an aggregate function")));
|
||||
if (procstruct->proretset)
|
||||
elog(ERROR, "cast function must not return a set");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("cast function must not return a set")));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
}
|
||||
@@ -843,7 +909,9 @@ CreateCast(CreateCastStmt *stmt)
|
||||
* erroneous casts can easily crash the backend.
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "Must be superuser to create a cast WITHOUT FUNCTION");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to create a cast WITHOUT FUNCTION")));
|
||||
|
||||
/*
|
||||
* Also, insist that the types match as to size, alignment, and
|
||||
@@ -856,7 +924,9 @@ CreateCast(CreateCastStmt *stmt)
|
||||
if (typ1len != typ2len ||
|
||||
typ1byval != typ2byval ||
|
||||
typ1align != typ2align)
|
||||
elog(ERROR, "source and target datatypes are not physically compatible");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("source and target datatypes are not physically compatible")));
|
||||
}
|
||||
|
||||
/* convert CoercionContext enum to char value for castcontext */
|
||||
@@ -872,7 +942,7 @@ CreateCast(CreateCastStmt *stmt)
|
||||
castcontext = COERCION_CODE_EXPLICIT;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "CreateCast: bogus CoercionContext %c", stmt->context);
|
||||
elog(ERROR, "unrecognized CoercionContext: %d", stmt->context);
|
||||
castcontext = 0; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
@@ -889,9 +959,11 @@ CreateCast(CreateCastStmt *stmt)
|
||||
ObjectIdGetDatum(targettypeid),
|
||||
0, 0);
|
||||
if (HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cast from data type %s to data type %s already exists",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("cast from data type %s to data type %s already exists",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
/* ready to go */
|
||||
values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
|
||||
@@ -953,29 +1025,37 @@ DropCast(DropCastStmt *stmt)
|
||||
|
||||
sourcetypeid = LookupTypeName(stmt->sourcetype);
|
||||
if (!OidIsValid(sourcetypeid))
|
||||
elog(ERROR, "source data type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("source data type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype))));
|
||||
|
||||
targettypeid = LookupTypeName(stmt->targettype);
|
||||
if (!OidIsValid(targettypeid))
|
||||
elog(ERROR, "target data type %s does not exist",
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("target data type %s does not exist",
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
tuple = SearchSysCache(CASTSOURCETARGET,
|
||||
ObjectIdGetDatum(sourcetypeid),
|
||||
ObjectIdGetDatum(targettypeid),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "cast from type %s to type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("cast from type %s to type %s does not exist",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
/* Permission check */
|
||||
if (!pg_type_ownercheck(sourcetypeid, GetUserId())
|
||||
&& !pg_type_ownercheck(targettypeid, GetUserId()))
|
||||
elog(ERROR, "must be owner of type %s or type %s",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be owner of type %s or type %s",
|
||||
TypeNameToString(stmt->sourcetype),
|
||||
TypeNameToString(stmt->targettype))));
|
||||
|
||||
/*
|
||||
* Do the deletion
|
||||
@@ -1006,10 +1086,9 @@ DropCastById(Oid castOid)
|
||||
1, F_OIDEQ, ObjectIdGetDatum(castOid));
|
||||
scan = index_beginscan(relation, index, SnapshotNow, 1, &scankey);
|
||||
tuple = index_getnext(scan, ForwardScanDirection);
|
||||
if (HeapTupleIsValid(tuple))
|
||||
simple_heap_delete(relation, &tuple->t_self);
|
||||
else
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "could not find tuple for cast %u", castOid);
|
||||
simple_heap_delete(relation, &tuple->t_self);
|
||||
index_endscan(scan);
|
||||
|
||||
index_close(index);
|
||||
|
Reference in New Issue
Block a user