mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +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/dbcommands.c,v 1.116 2003/06/27 14:45:27 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.117 2003/07/18 23:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -98,29 +98,37 @@ createdb(const CreatedbStmt *stmt)
|
||||
if (strcmp(defel->defname, "owner") == 0)
|
||||
{
|
||||
if (downer)
|
||||
elog(ERROR, "CREATE DATABASE: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
downer = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "location") == 0)
|
||||
{
|
||||
if (dpath)
|
||||
elog(ERROR, "CREATE DATABASE: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dpath = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "template") == 0)
|
||||
{
|
||||
if (dtemplate)
|
||||
elog(ERROR, "CREATE DATABASE: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dtemplate = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "encoding") == 0)
|
||||
{
|
||||
if (dencoding)
|
||||
elog(ERROR, "CREATE DATABASE: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dencoding = defel;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "CREATE DATABASE: option \"%s\" not recognized",
|
||||
elog(ERROR, "option \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
|
||||
@@ -140,22 +148,29 @@ createdb(const CreatedbStmt *stmt)
|
||||
encoding_name = pg_encoding_to_char(encoding);
|
||||
if (strcmp(encoding_name, "") == 0 ||
|
||||
pg_valid_server_encoding(encoding_name) < 0)
|
||||
elog(ERROR, "%d is not a valid encoding code", encoding);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("%d is not a valid encoding code",
|
||||
encoding)));
|
||||
}
|
||||
else if (IsA(dencoding->arg, String))
|
||||
{
|
||||
encoding_name = strVal(dencoding->arg);
|
||||
if (pg_valid_server_encoding(encoding_name) < 0)
|
||||
elog(ERROR, "%s is not a valid encoding name", encoding_name);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("%s is not a valid encoding name",
|
||||
encoding_name)));
|
||||
encoding = pg_char_to_encoding(encoding_name);
|
||||
}
|
||||
else
|
||||
elog(ERROR, "CREATE DATABASE: bogus encoding parameter");
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
nodeTag(dencoding->arg));
|
||||
}
|
||||
|
||||
/* obtain sysid of proposed owner */
|
||||
if (dbowner)
|
||||
datdba = get_usesysid(dbowner); /* will elog if no such user */
|
||||
datdba = get_usesysid(dbowner); /* will ereport if no such user */
|
||||
else
|
||||
datdba = GetUserId();
|
||||
|
||||
@@ -163,22 +178,29 @@ createdb(const CreatedbStmt *stmt)
|
||||
{
|
||||
/* creating database for self: can be superuser or createdb */
|
||||
if (!superuser() && !have_createdb_privilege())
|
||||
elog(ERROR, "CREATE DATABASE: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* creating database for someone else: must be superuser */
|
||||
/* note that the someone else need not have any permissions */
|
||||
if (!superuser())
|
||||
elog(ERROR, "CREATE DATABASE: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
}
|
||||
|
||||
/* don't call this in a transaction block */
|
||||
PreventTransactionChain((void *) stmt, "CREATE DATABASE");
|
||||
|
||||
/* alternate location requires symlinks */
|
||||
#ifndef HAVE_SYMLINK
|
||||
if (dbpath != NULL)
|
||||
elog(ERROR, "CREATE DATABASE: may not use an alternate location on this platform");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot use an alternate location on this platform")));
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -190,7 +212,9 @@ createdb(const CreatedbStmt *stmt)
|
||||
* after we grab the exclusive lock.
|
||||
*/
|
||||
if (get_db_info(dbname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
|
||||
elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_DATABASE),
|
||||
errmsg("database \"%s\" already exists", dbname)));
|
||||
|
||||
/*
|
||||
* Lookup database (template) to be cloned.
|
||||
@@ -202,8 +226,9 @@ createdb(const CreatedbStmt *stmt)
|
||||
&src_istemplate, &src_lastsysoid,
|
||||
&src_vacuumxid, &src_frozenxid,
|
||||
src_dbpath))
|
||||
elog(ERROR, "CREATE DATABASE: template \"%s\" does not exist",
|
||||
dbtemplate);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("template \"%s\" does not exist", dbtemplate)));
|
||||
|
||||
/*
|
||||
* Permission check: to copy a DB that's not marked datistemplate, you
|
||||
@@ -212,8 +237,10 @@ createdb(const CreatedbStmt *stmt)
|
||||
if (!src_istemplate)
|
||||
{
|
||||
if (!superuser() && GetUserId() != src_owner)
|
||||
elog(ERROR, "CREATE DATABASE: permission to copy \"%s\" denied",
|
||||
dbtemplate);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission to copy \"%s\" denied",
|
||||
dbtemplate)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -231,7 +258,10 @@ createdb(const CreatedbStmt *stmt)
|
||||
* bulletproof, since someone might connect while we are copying...
|
||||
*/
|
||||
if (DatabaseHasActiveBackends(src_dboid, true))
|
||||
elog(ERROR, "CREATE DATABASE: source database \"%s\" is being accessed by other users", dbtemplate);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("source database \"%s\" is being accessed by other users",
|
||||
dbtemplate)));
|
||||
|
||||
/* If encoding is defaulted, use source's encoding */
|
||||
if (encoding < 0)
|
||||
@@ -239,7 +269,9 @@ createdb(const CreatedbStmt *stmt)
|
||||
|
||||
/* Some encodings are client only */
|
||||
if (!PG_VALID_BE_ENCODING(encoding))
|
||||
elog(ERROR, "CREATE DATABASE: invalid backend encoding");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("invalid backend encoding %d", encoding)));
|
||||
|
||||
/*
|
||||
* Preassign OID for pg_database tuple, so that we can compute db
|
||||
@@ -267,11 +299,17 @@ createdb(const CreatedbStmt *stmt)
|
||||
}
|
||||
|
||||
if (strchr(nominal_loc, '\''))
|
||||
elog(ERROR, "database path may not contain single quotes");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_NAME),
|
||||
errmsg("database path may not contain single quotes")));
|
||||
if (alt_loc && strchr(alt_loc, '\''))
|
||||
elog(ERROR, "database path may not contain single quotes");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_NAME),
|
||||
errmsg("database path may not contain single quotes")));
|
||||
if (strchr(src_loc, '\''))
|
||||
elog(ERROR, "database path may not contain single quotes");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_NAME),
|
||||
errmsg("database path may not contain single quotes")));
|
||||
/* ... otherwise we'd be open to shell exploits below */
|
||||
|
||||
/*
|
||||
@@ -294,11 +332,15 @@ createdb(const CreatedbStmt *stmt)
|
||||
target_dir = alt_loc ? alt_loc : nominal_loc;
|
||||
|
||||
if (mkdir(target_dir, S_IRWXU) != 0)
|
||||
elog(ERROR, "CREATE DATABASE: unable to create database directory '%s': %m",
|
||||
target_dir);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("unable to create database directory \"%s\": %m",
|
||||
target_dir)));
|
||||
if (rmdir(target_dir) != 0)
|
||||
elog(ERROR, "CREATE DATABASE: unable to remove temp directory '%s': %m",
|
||||
target_dir);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("unable to remove temp directory \"%s\": %m",
|
||||
target_dir)));
|
||||
|
||||
/* Make the symlink, if needed */
|
||||
if (alt_loc)
|
||||
@@ -306,8 +348,10 @@ createdb(const CreatedbStmt *stmt)
|
||||
#ifdef HAVE_SYMLINK /* already throws error above */
|
||||
if (symlink(alt_loc, nominal_loc) != 0)
|
||||
#endif
|
||||
elog(ERROR, "CREATE DATABASE: could not link '%s' to '%s': %m",
|
||||
nominal_loc, alt_loc);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not link \"%s\" to \"%s\": %m",
|
||||
nominal_loc, alt_loc)));
|
||||
}
|
||||
|
||||
/* Copy the template database to the new location */
|
||||
@@ -319,9 +363,9 @@ createdb(const CreatedbStmt *stmt)
|
||||
#endif
|
||||
{
|
||||
if (remove_dbdirs(nominal_loc, alt_loc))
|
||||
elog(ERROR, "CREATE DATABASE: could not initialize database directory");
|
||||
elog(ERROR, "could not initialize database directory");
|
||||
else
|
||||
elog(ERROR, "CREATE DATABASE: could not initialize database directory; delete failed as well");
|
||||
elog(ERROR, "could not initialize database directory; delete failed as well");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -335,7 +379,9 @@ createdb(const CreatedbStmt *stmt)
|
||||
/* Don't hold lock while doing recursive remove */
|
||||
heap_close(pg_database_rel, AccessExclusiveLock);
|
||||
remove_dbdirs(nominal_loc, alt_loc);
|
||||
elog(ERROR, "CREATE DATABASE: database \"%s\" already exists", dbname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_DATABASE),
|
||||
errmsg("database \"%s\" already exists", dbname)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -411,7 +457,9 @@ dropdb(const char *dbname)
|
||||
AssertArg(dbname);
|
||||
|
||||
if (strcmp(dbname, get_database_name(MyDatabaseId)) == 0)
|
||||
elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("cannot drop the currently open database")));
|
||||
|
||||
PreventTransactionChain((void *) dbname, "DROP DATABASE");
|
||||
|
||||
@@ -428,10 +476,14 @@ dropdb(const char *dbname)
|
||||
|
||||
if (!get_db_info(dbname, &db_id, &db_owner, NULL,
|
||||
&db_istemplate, NULL, NULL, NULL, dbpath))
|
||||
elog(ERROR, "DROP DATABASE: database \"%s\" does not exist", dbname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("database \"%s\" does not exist", dbname)));
|
||||
|
||||
if (GetUserId() != db_owner && !superuser())
|
||||
elog(ERROR, "DROP DATABASE: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/*
|
||||
* Disallow dropping a DB that is marked istemplate. This is just to
|
||||
@@ -439,7 +491,9 @@ dropdb(const char *dbname)
|
||||
* they can do so if they're really determined ...
|
||||
*/
|
||||
if (db_istemplate)
|
||||
elog(ERROR, "DROP DATABASE: database is marked as a template");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("cannot drop a template database")));
|
||||
|
||||
nominal_loc = GetDatabasePath(db_id);
|
||||
alt_loc = resolve_alt_dbpath(dbpath, db_id);
|
||||
@@ -448,7 +502,10 @@ dropdb(const char *dbname)
|
||||
* Check for active backends in the target database.
|
||||
*/
|
||||
if (DatabaseHasActiveBackends(db_id, false))
|
||||
elog(ERROR, "DROP DATABASE: database \"%s\" is being accessed by other users", dbname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("database \"%s\" is being accessed by other users",
|
||||
dbname)));
|
||||
|
||||
/*
|
||||
* Find the database's tuple by OID (should be unique).
|
||||
@@ -465,7 +522,7 @@ dropdb(const char *dbname)
|
||||
* This error should never come up since the existence of the
|
||||
* database is checked earlier
|
||||
*/
|
||||
elog(ERROR, "DROP DATABASE: Database \"%s\" doesn't exist despite earlier reports to the contrary",
|
||||
elog(ERROR, "database \"%s\" doesn't exist despite earlier reports to the contrary",
|
||||
dbname);
|
||||
}
|
||||
|
||||
@@ -539,7 +596,7 @@ RenameDatabase(const char *oldname, const char *newname)
|
||||
tup = systable_getnext(scan);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("database \"%s\" does not exist", oldname)));
|
||||
|
||||
/*
|
||||
@@ -550,7 +607,7 @@ RenameDatabase(const char *oldname, const char *newname)
|
||||
*/
|
||||
if (HeapTupleGetOid(tup) == MyDatabaseId)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("current database may not be renamed")));
|
||||
|
||||
/*
|
||||
@@ -559,18 +616,19 @@ RenameDatabase(const char *oldname, const char *newname)
|
||||
* operations.
|
||||
*/
|
||||
if (DatabaseHasActiveBackends(HeapTupleGetOid(tup), false))
|
||||
elog(ERROR, "database \"%s\" is being accessed by other users", oldname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("database \"%s\" is being accessed by other users",
|
||||
oldname)));
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
ScanKeyEntryInitialize(&key2, 0, Anum_pg_database_datname,
|
||||
F_NAMEEQ, NameGetDatum(newname));
|
||||
scan2 = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key2);
|
||||
if (HeapTupleIsValid(systable_getnext(scan2)))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_DUPLICATE_DATABASE),
|
||||
errmsg("database \"%s\" already exists", newname)));
|
||||
}
|
||||
systable_endscan(scan2);
|
||||
|
||||
/* must be owner */
|
||||
@@ -579,11 +637,9 @@ RenameDatabase(const char *oldname, const char *newname)
|
||||
|
||||
/* must have createdb */
|
||||
if (!have_createdb_privilege())
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
}
|
||||
|
||||
/* rename */
|
||||
newtup = heap_copytuple(tup);
|
||||
@@ -628,11 +684,15 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
|
||||
scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &scankey);
|
||||
tuple = systable_getnext(scan);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "database \"%s\" does not exist", stmt->dbname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_DATABASE),
|
||||
errmsg("database \"%s\" does not exist", stmt->dbname)));
|
||||
|
||||
if (!(superuser()
|
||||
|| ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId()))
|
||||
elog(ERROR, "ALTER DATABASE SET: permission denied");
|
||||
|| ((Form_pg_database) GETSTRUCT(tuple))->datdba == GetUserId()))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
MemSet(repl_repl, ' ', sizeof(repl_repl));
|
||||
repl_repl[Anum_pg_database_datconfig - 1] = 'r';
|
||||
@@ -797,9 +857,13 @@ resolve_alt_dbpath(const char *dbpath, Oid dboid)
|
||||
if (first_path_separator(dbpath))
|
||||
{
|
||||
if (!is_absolute_path(dbpath))
|
||||
elog(ERROR, "Relative paths are not allowed as database locations");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("relative paths are not allowed as database locations")));
|
||||
#ifndef ALLOW_ABSOLUTE_DBPATHS
|
||||
elog(ERROR, "Absolute paths are not allowed as database locations");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("absolute paths are not allowed as database locations")));
|
||||
#endif
|
||||
prefix = dbpath;
|
||||
}
|
||||
@@ -809,15 +873,23 @@ resolve_alt_dbpath(const char *dbpath, Oid dboid)
|
||||
char *var = getenv(dbpath);
|
||||
|
||||
if (!var)
|
||||
elog(ERROR, "Postmaster environment variable '%s' not set", dbpath);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("postmaster environment variable \"%s\" not found",
|
||||
dbpath)));
|
||||
if (!is_absolute_path(var))
|
||||
elog(ERROR, "Postmaster environment variable '%s' must be absolute path", dbpath);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_NAME),
|
||||
errmsg("postmaster environment variable \"%s\" must be absolute path",
|
||||
dbpath)));
|
||||
prefix = var;
|
||||
}
|
||||
|
||||
len = strlen(prefix) + 6 + sizeof(Oid) * 8 + 1;
|
||||
if (len >= MAXPGPATH - 100)
|
||||
elog(ERROR, "Alternate path is too long");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_NAME),
|
||||
errmsg("alternate path is too long")));
|
||||
|
||||
ret = palloc(len);
|
||||
snprintf(ret, len, "%s/base/%u", prefix, dboid);
|
||||
@@ -846,7 +918,9 @@ remove_dbdirs(const char *nominal_loc, const char *alt_loc)
|
||||
/* remove symlink */
|
||||
if (unlink(nominal_loc) != 0)
|
||||
{
|
||||
elog(WARNING, "could not remove '%s': %m", nominal_loc);
|
||||
ereport(WARNING,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not remove \"%s\": %m", nominal_loc)));
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
@@ -859,8 +933,10 @@ remove_dbdirs(const char *nominal_loc, const char *alt_loc)
|
||||
|
||||
if (system(buf) != 0)
|
||||
{
|
||||
elog(WARNING, "database directory '%s' could not be removed",
|
||||
target_dir);
|
||||
ereport(WARNING,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not remove database directory \"%s\": %m",
|
||||
target_dir)));
|
||||
success = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.11 2003/07/04 02:51:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.12 2003/07/18 23:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -85,8 +85,10 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
CStringGetDatum(stmt->amname),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "DefineOpClass: access method \"%s\" not found",
|
||||
stmt->amname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
stmt->amname)));
|
||||
|
||||
amoid = HeapTupleGetOid(tup);
|
||||
numOperators = ((Form_pg_am) GETSTRUCT(tup))->amstrategies;
|
||||
@@ -104,7 +106,9 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
* if it can be done without solving the halting problem :-(
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "Must be superuser to create an operator class");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to create an operator class")));
|
||||
|
||||
/* Look up the datatype */
|
||||
typeoid = typenameTypeId(stmt->datatype);
|
||||
@@ -143,12 +147,16 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
{
|
||||
case OPCLASS_ITEM_OPERATOR:
|
||||
if (item->number <= 0 || item->number > numOperators)
|
||||
elog(ERROR, "DefineOpClass: invalid operator number %d,"
|
||||
" must be between 1 and %d",
|
||||
item->number, numOperators);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("invalid operator number %d,"
|
||||
" must be between 1 and %d",
|
||||
item->number, numOperators)));
|
||||
if (operators[item->number - 1] != InvalidOid)
|
||||
elog(ERROR, "DefineOpClass: operator number %d appears more than once",
|
||||
item->number);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("operator number %d appears more than once",
|
||||
item->number)));
|
||||
if (item->args != NIL)
|
||||
{
|
||||
TypeName *typeName1 = (TypeName *) lfirst(item->args);
|
||||
@@ -176,12 +184,16 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
break;
|
||||
case OPCLASS_ITEM_FUNCTION:
|
||||
if (item->number <= 0 || item->number > numProcs)
|
||||
elog(ERROR, "DefineOpClass: invalid procedure number %d,"
|
||||
" must be between 1 and %d",
|
||||
item->number, numProcs);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("invalid procedure number %d,"
|
||||
" must be between 1 and %d",
|
||||
item->number, numProcs)));
|
||||
if (procedures[item->number - 1] != InvalidOid)
|
||||
elog(ERROR, "DefineOpClass: procedure number %d appears more than once",
|
||||
item->number);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("DefineOpClass: procedure number %d appears more than once",
|
||||
item->number)));
|
||||
funcOid = LookupFuncNameTypeNames(item->name, item->args,
|
||||
false);
|
||||
/* Caller must have execute permission on functions */
|
||||
@@ -193,12 +205,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
break;
|
||||
case OPCLASS_ITEM_STORAGETYPE:
|
||||
if (OidIsValid(storageoid))
|
||||
elog(ERROR, "DefineOpClass: storage type specified more than once");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("storage type specified more than once")));
|
||||
storageoid = typenameTypeId(item->storedtype);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "DefineOpClass: bogus item type %d",
|
||||
item->itemtype);
|
||||
elog(ERROR, "unrecognized item type: %d", item->itemtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -219,8 +232,10 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
* favor of adding another boolean column to pg_am ...
|
||||
*/
|
||||
if (amoid != GIST_AM_OID)
|
||||
elog(ERROR, "Storage type may not be different from datatype for access method %s",
|
||||
stmt->amname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("storage type may not be different from datatype for access method \"%s\"",
|
||||
stmt->amname)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,8 +250,10 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
CStringGetDatum(opcname),
|
||||
ObjectIdGetDatum(namespaceoid),
|
||||
0))
|
||||
elog(ERROR, "Operator class \"%s\" already exists for access method \"%s\"",
|
||||
opcname, stmt->amname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("operator class \"%s\" already exists for access method \"%s\"",
|
||||
opcname, stmt->amname)));
|
||||
|
||||
/*
|
||||
* If we are creating a default opclass, check there isn't one
|
||||
@@ -259,11 +276,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
||||
Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tup);
|
||||
|
||||
if (opclass->opcintype == typeoid && opclass->opcdefault)
|
||||
elog(ERROR, "Can't add class \"%s\" as default for type %s"
|
||||
"\n\tclass \"%s\" already is the default",
|
||||
opcname,
|
||||
TypeNameToString(stmt->datatype),
|
||||
NameStr(opclass->opcname));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("cannot make class \"%s\" be default for type %s",
|
||||
opcname,
|
||||
TypeNameToString(stmt->datatype)),
|
||||
errdetail("class \"%s\" already is the default",
|
||||
NameStr(opclass->opcname))));
|
||||
}
|
||||
|
||||
systable_endscan(scan);
|
||||
@@ -467,8 +486,10 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
|
||||
CStringGetDatum(stmt->amname),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(amID))
|
||||
elog(ERROR, "RemoveOpClass: access method \"%s\" not found",
|
||||
stmt->amname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
stmt->amname)));
|
||||
|
||||
/*
|
||||
* Look up the opclass.
|
||||
@@ -494,16 +515,20 @@ RemoveOpClass(RemoveOpClassStmt *stmt)
|
||||
/* Unqualified opclass name, so search the search path */
|
||||
opcID = OpclassnameGetOpcid(amID, opcname);
|
||||
if (!OidIsValid(opcID))
|
||||
elog(ERROR, "RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"",
|
||||
opcname, stmt->amname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
|
||||
opcname, stmt->amname)));
|
||||
tuple = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opcID),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "RemoveOpClass: operator class \"%s\" not supported by access method \"%s\"",
|
||||
NameListToString(stmt->opclassname), stmt->amname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
|
||||
NameListToString(stmt->opclassname), stmt->amname)));
|
||||
|
||||
opcID = HeapTupleGetOid(tuple);
|
||||
|
||||
@@ -546,8 +571,7 @@ RemoveOpClassById(Oid opclassOid)
|
||||
ObjectIdGetDatum(opclassOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveOpClassById: couldn't find pg_opclass entry %u",
|
||||
opclassOid);
|
||||
elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
|
||||
|
||||
simple_heap_delete(rel, &tup->t_self);
|
||||
|
||||
@@ -612,7 +636,10 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
|
||||
CStringGetDatum(access_method),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(amOid))
|
||||
elog(ERROR, "access method \"%s\" not found", access_method);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("access method \"%s\" does not exist",
|
||||
access_method)));
|
||||
|
||||
rel = heap_openr(OperatorClassRelationName, RowExclusiveLock);
|
||||
|
||||
@@ -631,8 +658,10 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
|
||||
ObjectIdGetDatum(namespaceOid),
|
||||
0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist",
|
||||
opcname, access_method);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
|
||||
opcname, access_method)));
|
||||
|
||||
opcOid = HeapTupleGetOid(tup);
|
||||
}
|
||||
@@ -640,14 +669,16 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
|
||||
{
|
||||
opcOid = OpclassnameGetOpcid(amOid, opcname);
|
||||
if (!OidIsValid(opcOid))
|
||||
elog(ERROR, "operator class \"%s\" for access method \"%s\" does not exist",
|
||||
opcname, access_method);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator class \"%s\" does not exist for access method \"%s\"",
|
||||
opcname, access_method)));
|
||||
|
||||
tup = SearchSysCacheCopy(CLAOID,
|
||||
ObjectIdGetDatum(opcOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "couldn't find pg_opclass tuple for %u", opcOid);
|
||||
elog(ERROR, "cache lookup failed for opclass %u", opcOid);
|
||||
|
||||
namespaceOid = ((Form_pg_opclass) GETSTRUCT(tup))->opcnamespace;
|
||||
}
|
||||
@@ -660,9 +691,10 @@ RenameOpClass(List *name, const char *access_method, const char *newname)
|
||||
0))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("operator class \"%s\" for access method \"%s\" already exists in schema \"%s\"",
|
||||
newname, access_method, get_namespace_name(namespaceOid))));
|
||||
newname, access_method,
|
||||
get_namespace_name(namespaceOid))));
|
||||
}
|
||||
|
||||
/* must be owner */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.45 2003/07/04 02:51:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.46 2003/07/18 23:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -58,8 +58,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
* Check permission
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "Only users with superuser privilege are "
|
||||
"permitted to create procedural languages");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to create procedural language")));
|
||||
|
||||
/*
|
||||
* Translate the language name and check that this language doesn't
|
||||
@@ -70,7 +71,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
if (SearchSysCacheExists(LANGNAME,
|
||||
PointerGetDatum(languageName),
|
||||
0, 0, 0))
|
||||
elog(ERROR, "Language %s already exists", languageName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("language \"%s\" already exists", languageName)));
|
||||
|
||||
/*
|
||||
* Lookup the PL handler function and check that it is of the expected
|
||||
@@ -88,13 +91,17 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
|
||||
*/
|
||||
if (funcrettype == OPAQUEOID)
|
||||
{
|
||||
elog(NOTICE, "CreateProceduralLanguage: changing return type of function %s() from OPAQUE to LANGUAGE_HANDLER",
|
||||
NameListToString(stmt->plhandler));
|
||||
ereport(NOTICE,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("changing return type of function %s() from OPAQUE to LANGUAGE_HANDLER",
|
||||
NameListToString(stmt->plhandler))));
|
||||
SetFunctionReturnType(procOid, LANGUAGE_HANDLEROID);
|
||||
}
|
||||
else
|
||||
elog(ERROR, "CreateProceduralLanguage: function %s() must return LANGUAGE_HANDLER",
|
||||
NameListToString(stmt->plhandler));
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("function %s() must return LANGUAGE_HANDLER",
|
||||
NameListToString(stmt->plhandler))));
|
||||
}
|
||||
|
||||
/* validate the validator function */
|
||||
@@ -174,8 +181,9 @@ DropProceduralLanguage(DropPLangStmt *stmt)
|
||||
* Check permission
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "Only users with superuser privilege are "
|
||||
"permitted to drop procedural languages");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be superuser to drop procedural language")));
|
||||
|
||||
/*
|
||||
* Translate the language name, check that this language exist and is
|
||||
@@ -187,7 +195,9 @@ DropProceduralLanguage(DropPLangStmt *stmt)
|
||||
CStringGetDatum(languageName),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(langTup))
|
||||
elog(ERROR, "Language %s doesn't exist", languageName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("language \"%s\" does not exist", languageName)));
|
||||
|
||||
object.classId = get_system_catalog_relid(LanguageRelationName);
|
||||
object.objectId = HeapTupleGetOid(langTup);
|
||||
@@ -215,9 +225,8 @@ DropProceduralLanguageById(Oid langOid)
|
||||
langTup = SearchSysCache(LANGOID,
|
||||
ObjectIdGetDatum(langOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(langTup))
|
||||
elog(ERROR, "DropProceduralLanguageById: language %u not found",
|
||||
langOid);
|
||||
if (!HeapTupleIsValid(langTup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for language %u", langOid);
|
||||
|
||||
simple_heap_delete(rel, &langTup->t_self);
|
||||
|
||||
@@ -242,23 +251,21 @@ RenameLanguage(const char *oldname, const char *newname)
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("language \"%s\" does not exist", oldname)));
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
if (SearchSysCacheExists(LANGNAME,
|
||||
CStringGetDatum(newname),
|
||||
0, 0, 0))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("language \"%s\" already exists", newname)));
|
||||
}
|
||||
|
||||
/* must be superuser */
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/* rename */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.11 2003/06/27 17:05:46 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.12 2003/07/18 23:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -74,14 +74,16 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
SetUserId(owner_userid);
|
||||
}
|
||||
else
|
||||
/* not superuser */
|
||||
{
|
||||
/* not superuser */
|
||||
owner_userid = saved_userid;
|
||||
owner_name = GetUserNameFromId(owner_userid);
|
||||
if (strcmp(authId, owner_name) != 0)
|
||||
elog(ERROR, "CREATE SCHEMA: permission denied"
|
||||
"\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
|
||||
owner_name, authId);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied"),
|
||||
errdetail("\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
|
||||
owner_name, authId)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -92,8 +94,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
aclcheck_error(aclresult, get_database_name(MyDatabaseId));
|
||||
|
||||
if (!allowSystemTableMods && IsReservedName(schemaName))
|
||||
elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
|
||||
schemaName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("unacceptable schema name \"%s\"", schemaName),
|
||||
errdetail("The prefix pg_ is reserved for system schemas.")));
|
||||
|
||||
/* Create the schema's namespace */
|
||||
namespaceId = NamespaceCreate(schemaName, owner_userid);
|
||||
@@ -162,14 +166,18 @@ RemoveSchema(List *names, DropBehavior behavior)
|
||||
ObjectAddress object;
|
||||
|
||||
if (length(names) != 1)
|
||||
elog(ERROR, "Schema name may not be qualified");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("schema name may not be qualified")));
|
||||
namespaceName = strVal(lfirst(names));
|
||||
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(namespaceName),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(namespaceId))
|
||||
elog(ERROR, "Schema \"%s\" does not exist", namespaceName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
||||
errmsg("schema \"%s\" does not exist", namespaceName)));
|
||||
|
||||
/* Permission check */
|
||||
if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
|
||||
@@ -205,9 +213,8 @@ RemoveSchemaById(Oid schemaOid)
|
||||
tup = SearchSysCache(NAMESPACEOID,
|
||||
ObjectIdGetDatum(schemaOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "RemoveSchemaById: schema %u not found",
|
||||
schemaOid);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for schema %u", schemaOid);
|
||||
|
||||
simple_heap_delete(relation, &tup->t_self);
|
||||
|
||||
@@ -234,7 +241,7 @@ RenameSchema(const char *oldname, const char *newname)
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
||||
errmsg("schema \"%s\" does not exist", oldname)));
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
@@ -242,11 +249,9 @@ RenameSchema(const char *oldname, const char *newname)
|
||||
SearchSysCache(NAMESPACENAME,
|
||||
CStringGetDatum(newname),
|
||||
0, 0, 0)))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_DUPLICATE_SCHEMA),
|
||||
errmsg("schema \"%s\" already exists", newname)));
|
||||
}
|
||||
|
||||
/* must be owner */
|
||||
if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
@@ -258,8 +263,10 @@ RenameSchema(const char *oldname, const char *newname)
|
||||
aclcheck_error(aclresult, get_database_name(MyDatabaseId));
|
||||
|
||||
if (!allowSystemTableMods && IsReservedName(newname))
|
||||
elog(ERROR, "illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
|
||||
newname);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("unacceptable schema name \"%s\"", newname),
|
||||
errdetail("The prefix pg_ is reserved for system schemas.")));
|
||||
|
||||
/* rename */
|
||||
namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.118 2003/06/27 14:45:27 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.119 2003/07/18 23:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -144,7 +144,9 @@ write_group_file(Relation grel)
|
||||
fp = AllocateFile(tempname, "w");
|
||||
umask(oumask);
|
||||
if (fp == NULL)
|
||||
elog(ERROR, "write_group_file: unable to write %s: %m", tempname);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("unable to write temp file \"%s\": %m", tempname)));
|
||||
|
||||
/*
|
||||
* Read pg_group and write the file. Note we use SnapshotSelf to ensure
|
||||
@@ -178,7 +180,7 @@ write_group_file(Relation grel)
|
||||
i = strcspn(groname, "\n");
|
||||
if (groname[i] != '\0')
|
||||
{
|
||||
elog(LOG, "Invalid group name '%s'", groname);
|
||||
elog(LOG, "invalid group name \"%s\"", groname);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -208,7 +210,7 @@ write_group_file(Relation grel)
|
||||
j = strcspn(usename, "\n");
|
||||
if (usename[j] != '\0')
|
||||
{
|
||||
elog(LOG, "Invalid user name '%s'", usename);
|
||||
elog(LOG, "invalid user name \"%s\"", usename);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -239,7 +241,9 @@ write_group_file(Relation grel)
|
||||
|
||||
fflush(fp);
|
||||
if (ferror(fp))
|
||||
elog(ERROR, "%s: %m", tempname);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("unable to write temp file \"%s\": %m", tempname)));
|
||||
FreeFile(fp);
|
||||
|
||||
/*
|
||||
@@ -247,7 +251,10 @@ write_group_file(Relation grel)
|
||||
* expect that rename(2) is an atomic action.
|
||||
*/
|
||||
if (rename(tempname, filename))
|
||||
elog(ERROR, "rename %s to %s: %m", tempname, filename);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not rename \"%s\" to \"%s\": %m",
|
||||
tempname, filename)));
|
||||
|
||||
pfree((void *) tempname);
|
||||
pfree((void *) filename);
|
||||
@@ -283,7 +290,9 @@ write_user_file(Relation urel)
|
||||
fp = AllocateFile(tempname, "w");
|
||||
umask(oumask);
|
||||
if (fp == NULL)
|
||||
elog(ERROR, "write_user_file: unable to write %s: %m", tempname);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("unable to write temp file \"%s\": %m", tempname)));
|
||||
|
||||
/*
|
||||
* Read pg_shadow and write the file. Note we use SnapshotSelf to ensure
|
||||
@@ -332,13 +341,13 @@ write_user_file(Relation urel)
|
||||
i = strcspn(usename, "\n");
|
||||
if (usename[i] != '\0')
|
||||
{
|
||||
elog(LOG, "Invalid user name '%s'", usename);
|
||||
elog(LOG, "invalid user name \"%s\"", usename);
|
||||
continue;
|
||||
}
|
||||
i = strcspn(passwd, "\n");
|
||||
if (passwd[i] != '\0')
|
||||
{
|
||||
elog(LOG, "Invalid user password '%s'", passwd);
|
||||
elog(LOG, "invalid user password \"%s\"", passwd);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -361,7 +370,9 @@ write_user_file(Relation urel)
|
||||
|
||||
fflush(fp);
|
||||
if (ferror(fp))
|
||||
elog(ERROR, "%s: %m", tempname);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("unable to write temp file \"%s\": %m", tempname)));
|
||||
FreeFile(fp);
|
||||
|
||||
/*
|
||||
@@ -369,7 +380,10 @@ write_user_file(Relation urel)
|
||||
* expect that rename(2) is an atomic action.
|
||||
*/
|
||||
if (rename(tempname, filename))
|
||||
elog(ERROR, "rename %s to %s: %m", tempname, filename);
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not rename \"%s\" to \"%s\": %m",
|
||||
tempname, filename)));
|
||||
|
||||
pfree((void *) tempname);
|
||||
pfree((void *) filename);
|
||||
@@ -502,7 +516,9 @@ CreateUser(CreateUserStmt *stmt)
|
||||
strcmp(defel->defname, "unencryptedPassword") == 0)
|
||||
{
|
||||
if (dpassword)
|
||||
elog(ERROR, "CREATE USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dpassword = defel;
|
||||
if (strcmp(defel->defname, "encryptedPassword") == 0)
|
||||
encrypt_password = true;
|
||||
@@ -512,35 +528,45 @@ CreateUser(CreateUserStmt *stmt)
|
||||
else if (strcmp(defel->defname, "sysid") == 0)
|
||||
{
|
||||
if (dsysid)
|
||||
elog(ERROR, "CREATE USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dsysid = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "createdb") == 0)
|
||||
{
|
||||
if (dcreatedb)
|
||||
elog(ERROR, "CREATE USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcreatedb = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "createuser") == 0)
|
||||
{
|
||||
if (dcreateuser)
|
||||
elog(ERROR, "CREATE USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcreateuser = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "groupElts") == 0)
|
||||
{
|
||||
if (dgroupElts)
|
||||
elog(ERROR, "CREATE USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dgroupElts = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "validUntil") == 0)
|
||||
{
|
||||
if (dvalidUntil)
|
||||
elog(ERROR, "CREATE USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dvalidUntil = defel;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "CREATE USER: option \"%s\" not recognized",
|
||||
elog(ERROR, "option \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
|
||||
@@ -552,7 +578,9 @@ CreateUser(CreateUserStmt *stmt)
|
||||
{
|
||||
sysid = intVal(dsysid->arg);
|
||||
if (sysid <= 0)
|
||||
elog(ERROR, "user id must be positive");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("user id must be positive")));
|
||||
havesysid = true;
|
||||
}
|
||||
if (dvalidUntil)
|
||||
@@ -567,11 +595,15 @@ CreateUser(CreateUserStmt *stmt)
|
||||
CheckPgUserAclNotNull();
|
||||
|
||||
if (!superuser())
|
||||
elog(ERROR, "CREATE USER: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
if (strcmp(stmt->user, "public") == 0)
|
||||
elog(ERROR, "CREATE USER: user name \"%s\" is reserved",
|
||||
stmt->user);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("user name \"%s\" is reserved",
|
||||
stmt->user)));
|
||||
|
||||
/*
|
||||
* Scan the pg_shadow relation to be certain the user or id doesn't
|
||||
@@ -605,10 +637,14 @@ CreateUser(CreateUserStmt *stmt)
|
||||
heap_endscan(scan);
|
||||
|
||||
if (user_exists)
|
||||
elog(ERROR, "CREATE USER: user name \"%s\" already exists",
|
||||
stmt->user);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("user \"%s\" already exists",
|
||||
stmt->user)));
|
||||
if (sysid_exists)
|
||||
elog(ERROR, "CREATE USER: sysid %d is already assigned", sysid);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("sysid %d is already assigned", sysid)));
|
||||
|
||||
/* If no sysid given, use max existing id + 1 */
|
||||
if (!havesysid)
|
||||
@@ -639,7 +675,7 @@ CreateUser(CreateUserStmt *stmt)
|
||||
{
|
||||
if (!EncryptMD5(password, stmt->user, strlen(stmt->user),
|
||||
encrypted_password))
|
||||
elog(ERROR, "CREATE USER: password encryption failed");
|
||||
elog(ERROR, "password encryption failed");
|
||||
new_record[Anum_pg_shadow_passwd - 1] =
|
||||
DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
|
||||
}
|
||||
@@ -730,7 +766,9 @@ AlterUser(AlterUserStmt *stmt)
|
||||
strcmp(defel->defname, "unencryptedPassword") == 0)
|
||||
{
|
||||
if (dpassword)
|
||||
elog(ERROR, "ALTER USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dpassword = defel;
|
||||
if (strcmp(defel->defname, "encryptedPassword") == 0)
|
||||
encrypt_password = true;
|
||||
@@ -740,23 +778,29 @@ AlterUser(AlterUserStmt *stmt)
|
||||
else if (strcmp(defel->defname, "createdb") == 0)
|
||||
{
|
||||
if (dcreatedb)
|
||||
elog(ERROR, "ALTER USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcreatedb = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "createuser") == 0)
|
||||
{
|
||||
if (dcreateuser)
|
||||
elog(ERROR, "ALTER USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dcreateuser = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "validUntil") == 0)
|
||||
{
|
||||
if (dvalidUntil)
|
||||
elog(ERROR, "ALTER USER: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dvalidUntil = defel;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "ALTER USER: option \"%s\" not recognized",
|
||||
elog(ERROR, "option \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
|
||||
@@ -779,7 +823,9 @@ AlterUser(AlterUserStmt *stmt)
|
||||
!validUntil &&
|
||||
password &&
|
||||
strcmp(GetUserNameFromId(GetUserId()), stmt->user) == 0))
|
||||
elog(ERROR, "ALTER USER: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/*
|
||||
* Scan the pg_shadow relation to be certain the user exists. Note we
|
||||
@@ -793,7 +839,9 @@ AlterUser(AlterUserStmt *stmt)
|
||||
PointerGetDatum(stmt->user),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "ALTER USER: user \"%s\" does not exist", stmt->user);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("user \"%s\" does not exist", stmt->user)));
|
||||
|
||||
/*
|
||||
* Build an updated tuple, perusing the information just obtained
|
||||
@@ -840,7 +888,7 @@ AlterUser(AlterUserStmt *stmt)
|
||||
{
|
||||
if (!EncryptMD5(password, stmt->user, strlen(stmt->user),
|
||||
encrypted_password))
|
||||
elog(ERROR, "CREATE USER: password encryption failed");
|
||||
elog(ERROR, "password encryption failed");
|
||||
new_record[Anum_pg_shadow_passwd - 1] =
|
||||
DirectFunctionCall1(textin, CStringGetDatum(encrypted_password));
|
||||
}
|
||||
@@ -904,11 +952,15 @@ AlterUserSet(AlterUserSetStmt *stmt)
|
||||
PointerGetDatum(stmt->user),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(oldtuple))
|
||||
elog(ERROR, "user \"%s\" does not exist", stmt->user);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("user \"%s\" does not exist", stmt->user)));
|
||||
|
||||
if (!(superuser()
|
||||
|| ((Form_pg_shadow) GETSTRUCT(oldtuple))->usesysid == GetUserId()))
|
||||
elog(ERROR, "ALTER USER SET: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
for (i = 0; i < Natts_pg_shadow; i++)
|
||||
repl_repl[i] = ' ';
|
||||
@@ -965,7 +1017,9 @@ DropUser(DropUserStmt *stmt)
|
||||
List *item;
|
||||
|
||||
if (!superuser())
|
||||
elog(ERROR, "DROP USER: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/*
|
||||
* Scan the pg_shadow relation to find the usesysid of the user to be
|
||||
@@ -990,19 +1044,20 @@ DropUser(DropUserStmt *stmt)
|
||||
PointerGetDatum(user),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
if (length(stmt->users) > 1)
|
||||
elog(ERROR, "DROP USER: user \"%s\" does not exist (no users removed)", user);
|
||||
else
|
||||
elog(ERROR, "DROP USER: user \"%s\" does not exist", user);
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("user \"%s\" does not exist", user)));
|
||||
|
||||
usesysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid;
|
||||
|
||||
if (usesysid == GetUserId())
|
||||
elog(ERROR, "current user cannot be dropped");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("current user cannot be dropped")));
|
||||
if (usesysid == GetSessionUserId())
|
||||
elog(ERROR, "session user cannot be dropped");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("session user cannot be dropped")));
|
||||
|
||||
/*
|
||||
* Check if user still owns a database. If so, error out.
|
||||
@@ -1026,9 +1081,10 @@ DropUser(DropUserStmt *stmt)
|
||||
char *dbname;
|
||||
|
||||
dbname = NameStr(((Form_pg_database) GETSTRUCT(tmp_tuple))->datname);
|
||||
elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s",
|
||||
user, dbname,
|
||||
(length(stmt->users) > 1) ? " (no users removed)" : "");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_IN_USE),
|
||||
errmsg("user \"%s\" cannot be dropped", user),
|
||||
errdetail("The user owns database \"%s\".", dbname)));
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
@@ -1108,7 +1164,7 @@ RenameUser(const char *oldname, const char *newname)
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("user \"%s\" does not exist", oldname)));
|
||||
|
||||
/*
|
||||
@@ -1119,23 +1175,21 @@ RenameUser(const char *oldname, const char *newname)
|
||||
*/
|
||||
if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("session user may not be renamed")));
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
if (SearchSysCacheExists(SHADOWNAME,
|
||||
CStringGetDatum(newname),
|
||||
0, 0, 0))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("user \"%s\" already exists", newname)));
|
||||
}
|
||||
|
||||
/* must be superuser */
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/* rename */
|
||||
@@ -1163,16 +1217,17 @@ CheckPgUserAclNotNull(void)
|
||||
htup = SearchSysCache(RELOID,
|
||||
ObjectIdGetDatum(RelOid_pg_shadow),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(htup))
|
||||
elog(ERROR, "CheckPgUserAclNotNull: \"%s\" not found",
|
||||
ShadowRelationName);
|
||||
if (!HeapTupleIsValid(htup)) /* should not happen, we hope */
|
||||
elog(ERROR, "cache lookup failed for relation %u", RelOid_pg_shadow);
|
||||
|
||||
if (heap_attisnull(htup, Anum_pg_class_relacl))
|
||||
elog(ERROR,
|
||||
"To use passwords, you have to revoke permissions on %s "
|
||||
"so normal users cannot read the passwords. "
|
||||
"Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.",
|
||||
ShadowRelationName, ShadowRelationName);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("before using passwords you must revoke permissions on %s",
|
||||
ShadowRelationName),
|
||||
errdetail("This restriction is to prevent unprivileged users from reading the passwords."),
|
||||
errhint("Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.",
|
||||
ShadowRelationName)));
|
||||
|
||||
ReleaseSysCache(htup);
|
||||
}
|
||||
@@ -1211,17 +1266,21 @@ CreateGroup(CreateGroupStmt *stmt)
|
||||
if (strcmp(defel->defname, "sysid") == 0)
|
||||
{
|
||||
if (dsysid)
|
||||
elog(ERROR, "CREATE GROUP: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
dsysid = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "userElts") == 0)
|
||||
{
|
||||
if (duserElts)
|
||||
elog(ERROR, "CREATE GROUP: conflicting options");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("conflicting or redundant options")));
|
||||
duserElts = defel;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "CREATE GROUP: option \"%s\" not recognized",
|
||||
elog(ERROR, "option \"%s\" not recognized",
|
||||
defel->defname);
|
||||
}
|
||||
|
||||
@@ -1229,7 +1288,9 @@ CreateGroup(CreateGroupStmt *stmt)
|
||||
{
|
||||
sysid = intVal(dsysid->arg);
|
||||
if (sysid <= 0)
|
||||
elog(ERROR, "group id must be positive");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("group id must be positive")));
|
||||
havesysid = true;
|
||||
}
|
||||
|
||||
@@ -1240,11 +1301,15 @@ CreateGroup(CreateGroupStmt *stmt)
|
||||
* Make sure the user can do this.
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "CREATE GROUP: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
if (strcmp(stmt->name, "public") == 0)
|
||||
elog(ERROR, "CREATE GROUP: group name \"%s\" is reserved",
|
||||
stmt->name);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_RESERVED_NAME),
|
||||
errmsg("group name \"%s\" is reserved",
|
||||
stmt->name)));
|
||||
|
||||
/*
|
||||
* Scan the pg_group relation to be certain the group or id doesn't
|
||||
@@ -1278,12 +1343,16 @@ CreateGroup(CreateGroupStmt *stmt)
|
||||
heap_endscan(scan);
|
||||
|
||||
if (group_exists)
|
||||
elog(ERROR, "CREATE GROUP: group name \"%s\" already exists",
|
||||
stmt->name);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("group \"%s\" already exists",
|
||||
stmt->name)));
|
||||
if (sysid_exists)
|
||||
elog(ERROR, "CREATE GROUP: group sysid %d is already assigned",
|
||||
sysid);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("sysid %d is already assigned", sysid)));
|
||||
|
||||
/* If no sysid given, use max existing id + 1 */
|
||||
if (!havesysid)
|
||||
sysid = max_id + 1;
|
||||
|
||||
@@ -1359,7 +1428,9 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
* Make sure the user can do this.
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "%s: permission denied", tag);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/*
|
||||
* Secure exclusive lock to protect our update of the flat group file.
|
||||
@@ -1374,7 +1445,9 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
PointerGetDatum(stmt->name),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(group_tuple))
|
||||
elog(ERROR, "%s: group \"%s\" does not exist", tag, stmt->name);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("group \"%s\" does not exist", stmt->name)));
|
||||
|
||||
/* Fetch old group membership. */
|
||||
datum = heap_getattr(group_tuple, Anum_pg_group_grolist,
|
||||
@@ -1415,20 +1488,17 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
}
|
||||
else
|
||||
{
|
||||
elog(ERROR, "AlterGroup: unknown tag %s", tag);
|
||||
elog(ERROR, "unexpected tag: \"%s\"", tag);
|
||||
sysid = 0; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
if (!intMember(sysid, newlist))
|
||||
newlist = lappendi(newlist, sysid);
|
||||
else
|
||||
|
||||
/*
|
||||
* we silently assume here that this error will only come
|
||||
* up in a ALTER GROUP statement
|
||||
*/
|
||||
elog(WARNING, "%s: user \"%s\" is already in group \"%s\"",
|
||||
tag, strVal(lfirst(item)), stmt->name);
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("user \"%s\" is already in group \"%s\"",
|
||||
strVal(lfirst(item)), stmt->name)));
|
||||
}
|
||||
|
||||
/* Do the update */
|
||||
@@ -1442,7 +1512,10 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
if (newlist == NIL)
|
||||
{
|
||||
if (!is_dropuser)
|
||||
elog(WARNING, "ALTER GROUP: group \"%s\" does not have any members", stmt->name);
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_WARNING),
|
||||
errmsg("group \"%s\" does not have any members",
|
||||
stmt->name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1467,7 +1540,10 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag)
|
||||
if (intMember(sysid, newlist))
|
||||
newlist = lremovei(sysid, newlist);
|
||||
else if (!is_dropuser)
|
||||
elog(WARNING, "ALTER GROUP: user \"%s\" is not in group \"%s\"", strVal(lfirst(item)), stmt->name);
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_WARNING),
|
||||
errmsg("user \"%s\" is not in group \"%s\"",
|
||||
strVal(lfirst(item)), stmt->name)));
|
||||
}
|
||||
|
||||
/* Do the update */
|
||||
@@ -1596,7 +1672,9 @@ DropGroup(DropGroupStmt *stmt)
|
||||
* Make sure the user can do this.
|
||||
*/
|
||||
if (!superuser())
|
||||
elog(ERROR, "DROP GROUP: permission denied");
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/*
|
||||
* Secure exclusive lock to protect our update of the flat group file.
|
||||
@@ -1609,7 +1687,9 @@ DropGroup(DropGroupStmt *stmt)
|
||||
PointerGetDatum(stmt->name),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name);
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("group \"%s\" does not exist", stmt->name)));
|
||||
|
||||
simple_heap_delete(pg_group_rel, &tuple->t_self);
|
||||
|
||||
@@ -1643,23 +1723,21 @@ RenameGroup(const char *oldname, const char *newname)
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("group \"%s\" does not exist", oldname)));
|
||||
|
||||
/* make sure the new name doesn't exist */
|
||||
if (SearchSysCacheExists(GRONAME,
|
||||
CStringGetDatum(newname),
|
||||
0, 0, 0))
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
errmsg("a group \"%s\" already exists", newname)));
|
||||
}
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("group \"%s\" already exists", newname)));
|
||||
|
||||
/* must be superuser */
|
||||
if (!superuser())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION),
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied")));
|
||||
|
||||
/* rename */
|
||||
|
||||
Reference in New Issue
Block a user