diff options
Diffstat (limited to 'src/backend/tcop/utility.c')
-rw-r--r-- | src/backend/tcop/utility.c | 158 |
1 files changed, 103 insertions, 55 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index be47708d4b1..068ae2a724f 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.201 2003/06/27 14:45:30 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.202 2003/07/22 19:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -60,69 +60,90 @@ * Error-checking support for DROP commands */ -struct kindstrings +struct msgstrings { char kind; - char *indef_article; - char *name; - char *command; + int nonexistent_code; + const char *nonexistent_msg; + const char *nota_msg; + const char *drophint_msg; }; -static struct kindstrings kindstringarray[] = { - {RELKIND_RELATION, "a", "table", "TABLE"}, - {RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"}, - {RELKIND_VIEW, "a", "view", "VIEW"}, - {RELKIND_INDEX, "an", "index", "INDEX"}, - {RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"}, - {'\0', "a", "???", "???"} +static const struct msgstrings msgstringarray[] = { + { RELKIND_RELATION, + ERRCODE_UNDEFINED_TABLE, + gettext_noop("table \"%s\" does not exist"), + gettext_noop("\"%s\" is not a table"), + gettext_noop("Use DROP TABLE to remove a table.") }, + { RELKIND_SEQUENCE, + ERRCODE_UNDEFINED_TABLE, + gettext_noop("sequence \"%s\" does not exist"), + gettext_noop("\"%s\" is not a sequence"), + gettext_noop("Use DROP SEQUENCE to remove a sequence.") }, + { RELKIND_VIEW, + ERRCODE_UNDEFINED_TABLE, + gettext_noop("view \"%s\" does not exist"), + gettext_noop("\"%s\" is not a view"), + gettext_noop("Use DROP VIEW to remove a view.") }, + { RELKIND_INDEX, + ERRCODE_UNDEFINED_OBJECT, + gettext_noop("index \"%s\" does not exist"), + gettext_noop("\"%s\" is not an index"), + gettext_noop("Use DROP INDEX to remove an index.") }, + { RELKIND_COMPOSITE_TYPE, + ERRCODE_UNDEFINED_OBJECT, + gettext_noop("type \"%s\" does not exist"), + gettext_noop("\"%s\" is not a type"), + gettext_noop("Use DROP TYPE to remove a type.") }, + { '\0', 0, NULL, NULL, NULL } }; static void DropErrorMsg(char *relname, char wrongkind, char rightkind) { - struct kindstrings *rentry; - struct kindstrings *wentry; + const struct msgstrings *rentry; + const struct msgstrings *wentry; - for (rentry = kindstringarray; rentry->kind != '\0'; rentry++) + for (rentry = msgstringarray; rentry->kind != '\0'; rentry++) if (rentry->kind == rightkind) break; Assert(rentry->kind != '\0'); - for (wentry = kindstringarray; wentry->kind != '\0'; wentry++) + for (wentry = msgstringarray; wentry->kind != '\0'; wentry++) if (wentry->kind == wrongkind) break; /* wrongkind could be something we don't have in our table... */ - if (wentry->kind != '\0') - elog(ERROR, "\"%s\" is not %s %s. Use DROP %s to remove %s %s", - relname, rentry->indef_article, rentry->name, - wentry->command, wentry->indef_article, wentry->name); - else - elog(ERROR, "\"%s\" is not %s %s", - relname, rentry->indef_article, rentry->name); + + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg(rentry->nota_msg, relname), + (wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0)); } static void CheckDropPermissions(RangeVar *rel, char rightkind) { - struct kindstrings *rentry; + const struct msgstrings *rentry; Oid relOid; HeapTuple tuple; Form_pg_class classform; - for (rentry = kindstringarray; rentry->kind != '\0'; rentry++) + for (rentry = msgstringarray; rentry->kind != '\0'; rentry++) if (rentry->kind == rightkind) break; Assert(rentry->kind != '\0'); relOid = RangeVarGetRelid(rel, true); if (!OidIsValid(relOid)) - elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname); + ereport(ERROR, + (errcode(rentry->nonexistent_code), + errmsg(rentry->nonexistent_msg, rel->relname))); tuple = SearchSysCache(RELOID, ObjectIdGetDatum(relOid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname); + elog(ERROR, "cache lookup failed for relation %u", relOid); classform = (Form_pg_class) GETSTRUCT(tuple); @@ -135,14 +156,22 @@ CheckDropPermissions(RangeVar *rel, char rightkind) aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); if (!allowSystemTableMods && IsSystemClass(classform)) - elog(ERROR, "%s \"%s\" is a system %s", - rentry->name, rel->relname, rentry->name); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("\"%s\" is a system catalog", + rel->relname))); ReleaseSysCache(tuple); } -static void -CheckOwnership(RangeVar *rel, bool noCatalogs) +/* + * Verify user has ownership of specified relation, else ereport. + * + * If noCatalogs is true then we also deny access to system catalogs, + * except when allowSystemTableMods is true. + */ +void +CheckRelationOwnership(RangeVar *rel, bool noCatalogs) { Oid relOid; HeapTuple tuple; @@ -151,8 +180,8 @@ CheckOwnership(RangeVar *rel, bool noCatalogs) tuple = SearchSysCache(RELOID, ObjectIdGetDatum(relOid), 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "Relation \"%s\" does not exist", rel->relname); + if (!HeapTupleIsValid(tuple)) /* should not happen */ + elog(ERROR, "cache lookup failed for relation %u", relOid); if (!pg_class_ownercheck(relOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname); @@ -161,8 +190,10 @@ CheckOwnership(RangeVar *rel, bool noCatalogs) { if (!allowSystemTableMods && IsSystemClass((Form_pg_class) GETSTRUCT(tuple))) - elog(ERROR, "relation \"%s\" is a system catalog", - rel->relname); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("\"%s\" is a system catalog", + rel->relname))); } ReleaseSysCache(tuple); @@ -222,10 +253,13 @@ check_xact_readonly(Node *parsetree) case T_DropUserStmt: case T_GrantStmt: case T_TruncateStmt: - elog(ERROR, "transaction is read-only"); + ereport(ERROR, + (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), + errmsg("transaction is read-only"))); break; default: - /*nothing*/; + /* do nothing */ + break; } } @@ -407,7 +441,9 @@ ProcessUtility(Node *parsetree, break; default: - elog(ERROR, "invalid object type for DropStmt: %d", stmt->removeType); + elog(ERROR, "unrecognized drop object type: %d", + (int) stmt->removeType); + break; } /* @@ -551,7 +587,9 @@ ProcessUtility(Node *parsetree, case 'U': /* ALTER OWNER */ /* check that we are the superuser */ if (!superuser()) - elog(ERROR, "ALTER TABLE: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* get_usesysid raises an error if no such user */ AlterTableOwner(relid, get_usesysid(stmt->name)); @@ -565,8 +603,8 @@ ProcessUtility(Node *parsetree, false); break; default: /* oops */ - elog(ERROR, "ProcessUtility: Invalid type for AlterTableStmt: %d", - stmt->subtype); + elog(ERROR, "unrecognized alter table type: %d", + (int) stmt->subtype); break; } } @@ -611,14 +649,16 @@ ProcessUtility(Node *parsetree, case 'U': /* OWNER TO */ /* check that we are the superuser */ if (!superuser()) - elog(ERROR, "ALTER DOMAIN: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); /* get_usesysid raises an error if no such user */ AlterTypeOwner(stmt->typename, get_usesysid(stmt->name)); break; default: /* oops */ - elog(ERROR, "ProcessUtility: Invalid type for AlterDomainStmt: %d", - stmt->subtype); + elog(ERROR, "unrecognized alter domain type: %d", + (int) stmt->subtype); break; } } @@ -650,7 +690,9 @@ ProcessUtility(Node *parsetree, DefineType(stmt->defnames, stmt->definition); break; default: - elog(ERROR, "invalid object type for DefineStmt: %d", stmt->kind); + elog(ERROR, "unrecognized define stmt type: %d", + (int) stmt->kind); + break; } } break; @@ -679,7 +721,7 @@ ProcessUtility(Node *parsetree, { IndexStmt *stmt = (IndexStmt *) parsetree; - CheckOwnership(stmt->relation, true); + CheckRelationOwnership(stmt->relation, true); DefineIndex(stmt->relation, /* relation */ stmt->idxname, /* index name */ @@ -865,7 +907,9 @@ ProcessUtility(Node *parsetree, stmt->behavior); break; default: - elog(ERROR, "invalid object type for DropPropertyStmt: %d", stmt->removeType); + elog(ERROR, "unrecognized object type: %d", + (int) stmt->removeType); + break; } } break; @@ -926,7 +970,9 @@ ProcessUtility(Node *parsetree, case T_CheckPointStmt: if (!superuser()) - elog(ERROR, "CHECKPOINT: permission denied"); + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied"))); CreateCheckPoint(false, false); break; @@ -937,18 +983,20 @@ ProcessUtility(Node *parsetree, switch (stmt->kind) { case OBJECT_INDEX: - CheckOwnership(stmt->relation, false); + CheckRelationOwnership(stmt->relation, false); ReindexIndex(stmt->relation, stmt->force); break; case OBJECT_TABLE: - CheckOwnership(stmt->relation, false); + CheckRelationOwnership(stmt->relation, false); ReindexTable(stmt->relation, stmt->force); break; case OBJECT_DATABASE: ReindexDatabase(stmt->name, stmt->force, false); break; default: - elog(ERROR, "invalid object type for ReindexStmt: %d", stmt->kind); + elog(ERROR, "unrecognized object type: %d", + (int) stmt->kind); + break; } break; } @@ -975,8 +1023,8 @@ ProcessUtility(Node *parsetree, break; default: - elog(ERROR, "ProcessUtility: command #%d unsupported", - nodeTag(parsetree)); + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(parsetree)); break; } } @@ -1500,8 +1548,8 @@ CreateCommandTag(Node *parsetree) break; default: - elog(LOG, "CreateCommandTag: unknown parse node type %d", - nodeTag(parsetree)); + elog(NOTICE, "unrecognized node type: %d", + (int) nodeTag(parsetree)); tag = "???"; break; } |