mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
DROP objecttype IF EXISTS for the following objects:
table view index sequence schema type domain conversion
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.23 2005/10/15 02:49:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.24 2005/11/19 17:39:44 adunstan Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -98,16 +98,29 @@ CreateConversionCommand(CreateConversionStmt *stmt)
|
||||
* DROP CONVERSION
|
||||
*/
|
||||
void
|
||||
DropConversionCommand(List *name, DropBehavior behavior)
|
||||
DropConversionCommand(List *name, DropBehavior behavior, bool missing_ok)
|
||||
{
|
||||
Oid conversionOid;
|
||||
|
||||
conversionOid = FindConversionByName(name);
|
||||
if (!OidIsValid(conversionOid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("conversion \"%s\" does not exist",
|
||||
NameListToString(name))));
|
||||
{
|
||||
if (! missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("conversion \"%s\" does not exist",
|
||||
NameListToString(name))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("conversion \"%s\" does not exist, skipping",
|
||||
NameListToString(name))));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ConversionDrop(conversionOid, behavior);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.35 2005/10/15 02:49:15 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.36 2005/11/19 17:39:44 adunstan Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -147,7 +147,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
* Removes a schema.
|
||||
*/
|
||||
void
|
||||
RemoveSchema(List *names, DropBehavior behavior)
|
||||
RemoveSchema(List *names, DropBehavior behavior, bool missing_ok)
|
||||
{
|
||||
char *namespaceName;
|
||||
Oid namespaceId;
|
||||
@@ -163,9 +163,22 @@ RemoveSchema(List *names, DropBehavior behavior)
|
||||
CStringGetDatum(namespaceName),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(namespaceId))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
||||
errmsg("schema \"%s\" does not exist", namespaceName)));
|
||||
{
|
||||
if (!missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_SCHEMA),
|
||||
errmsg("schema \"%s\" does not exist", namespaceName)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("schema \"%s\" does not exist, skipping",
|
||||
namespaceName)));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Permission check */
|
||||
if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.82 2005/10/18 01:06:24 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.83 2005/11/19 17:39:44 adunstan Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -398,7 +398,7 @@ DefineType(List *names, List *parameters)
|
||||
* Removes a datatype.
|
||||
*/
|
||||
void
|
||||
RemoveType(List *names, DropBehavior behavior)
|
||||
RemoveType(List *names, DropBehavior behavior, bool missing_ok)
|
||||
{
|
||||
TypeName *typename;
|
||||
Oid typeoid;
|
||||
@@ -414,10 +414,23 @@ RemoveType(List *names, DropBehavior behavior)
|
||||
/* Use LookupTypeName here so that shell types can be removed. */
|
||||
typeoid = LookupTypeName(typename);
|
||||
if (!OidIsValid(typeoid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
{
|
||||
if (!missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("type \"%s\" does not exist, skipping",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(typeoid),
|
||||
@@ -779,7 +792,7 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
* This is identical to RemoveType except we insist it be a domain.
|
||||
*/
|
||||
void
|
||||
RemoveDomain(List *names, DropBehavior behavior)
|
||||
RemoveDomain(List *names, DropBehavior behavior, bool missing_ok)
|
||||
{
|
||||
TypeName *typename;
|
||||
Oid typeoid;
|
||||
@@ -796,10 +809,23 @@ RemoveDomain(List *names, DropBehavior behavior)
|
||||
/* Use LookupTypeName here so that shell types can be removed. */
|
||||
typeoid = LookupTypeName(typename);
|
||||
if (!OidIsValid(typeoid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
{
|
||||
if (!missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" does not exist",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE,
|
||||
(errmsg("type \"%s\" does not exist, skipping",
|
||||
TypeNameToString(typename))));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(typeoid),
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.512 2005/11/13 19:11:28 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.513 2005/11/19 17:39:44 adunstan Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -173,7 +173,7 @@ static void doNegateFloat(Value *v);
|
||||
%type <ival> opt_lock lock_type cast_context
|
||||
%type <boolean> opt_force opt_or_replace
|
||||
opt_grant_grant_option opt_grant_admin_option
|
||||
opt_nowait
|
||||
opt_nowait
|
||||
|
||||
%type <boolean> like_including_defaults
|
||||
|
||||
@@ -362,7 +362,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
HANDLER HAVING HEADER HOLD HOUR_P
|
||||
|
||||
ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
|
||||
IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
|
||||
INDEX INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
|
||||
INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
|
||||
INTERVAL INTO INVOKER IS ISNULL ISOLATION
|
||||
@@ -2818,20 +2818,32 @@ DropOpClassStmt:
|
||||
*
|
||||
* QUERY:
|
||||
*
|
||||
* DROP itemtype itemname [, itemname ...] [ RESTRICT | CASCADE ]
|
||||
* DROP itemtype [ IF EXISTS ] itemname [, itemname ...]
|
||||
* [ RESTRICT | CASCADE ]
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
DropStmt: DROP drop_type any_name_list opt_drop_behavior
|
||||
DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
|
||||
{
|
||||
DropStmt *n = makeNode(DropStmt);
|
||||
n->removeType = $2;
|
||||
n->missing_ok = TRUE;
|
||||
n->objects = $5;
|
||||
n->behavior = $6;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| DROP drop_type any_name_list opt_drop_behavior
|
||||
{
|
||||
DropStmt *n = makeNode(DropStmt);
|
||||
n->removeType = $2;
|
||||
n->missing_ok = FALSE;
|
||||
n->objects = $3;
|
||||
n->behavior = $4;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
drop_type: TABLE { $$ = OBJECT_TABLE; }
|
||||
| SEQUENCE { $$ = OBJECT_SEQUENCE; }
|
||||
| VIEW { $$ = OBJECT_VIEW; }
|
||||
@@ -8159,6 +8171,7 @@ unreserved_keyword:
|
||||
| HEADER
|
||||
| HOLD
|
||||
| HOUR_P
|
||||
| IF_P
|
||||
| IMMEDIATE
|
||||
| IMMUTABLE
|
||||
| IMPLICIT_P
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.166 2005/10/15 02:49:22 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.167 2005/11/19 17:39:44 adunstan Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -160,6 +160,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"header", HEADER},
|
||||
{"hold", HOLD},
|
||||
{"hour", HOUR_P},
|
||||
{"if",IF_P},
|
||||
{"ilike", ILIKE},
|
||||
{"immediate", IMMEDIATE},
|
||||
{"immutable", IMMUTABLE},
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.245 2005/10/15 02:49:27 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.246 2005/11/19 17:39:45 adunstan Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -67,6 +67,7 @@ struct msgstrings
|
||||
char kind;
|
||||
int nonexistent_code;
|
||||
const char *nonexistent_msg;
|
||||
const char *skipping_msg;
|
||||
const char *nota_msg;
|
||||
const char *drophint_msg;
|
||||
};
|
||||
@@ -75,26 +76,31 @@ static const struct msgstrings msgstringarray[] = {
|
||||
{RELKIND_RELATION,
|
||||
ERRCODE_UNDEFINED_TABLE,
|
||||
gettext_noop("table \"%s\" does not exist"),
|
||||
gettext_noop("table \"%s\" does not exist, skipping"),
|
||||
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("sequence \"%s\" does not exist, skipping"),
|
||||
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("view \"%s\" does not exist, skipping"),
|
||||
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("index \"%s\" does not exist, skipping"),
|
||||
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("type \"%s\" does not exist, skipping"),
|
||||
gettext_noop("\"%s\" is not a type"),
|
||||
gettext_noop("Use DROP TYPE to remove a type.")},
|
||||
{'\0', 0, NULL, NULL, NULL}
|
||||
@@ -132,23 +138,40 @@ DropErrorMsgWrongType(char *relname, char wrongkind, char rightkind)
|
||||
* non-existent relation
|
||||
*/
|
||||
static void
|
||||
DropErrorMsgNonExistent(RangeVar *rel, char rightkind)
|
||||
DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
|
||||
{
|
||||
const struct msgstrings *rentry;
|
||||
|
||||
for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
|
||||
{
|
||||
if (rentry->kind == rightkind)
|
||||
ereport(ERROR,
|
||||
(errcode(rentry->nonexistent_code),
|
||||
errmsg(rentry->nonexistent_msg, rel->relname)));
|
||||
{
|
||||
if (! missing_ok)
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(rentry->nonexistent_code),
|
||||
errmsg(rentry->nonexistent_msg, rel->relname)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert(false); /* Should be impossible */
|
||||
Assert(rentry->kind != '\0'); /* Should be impossible */
|
||||
}
|
||||
|
||||
static void
|
||||
CheckDropPermissions(RangeVar *rel, char rightkind)
|
||||
/*
|
||||
* returns false if missing_ok is true and the object does not exist,
|
||||
* true if object exists and permissions are OK,
|
||||
* errors otherwise
|
||||
*
|
||||
*/
|
||||
|
||||
static bool
|
||||
CheckDropPermissions(RangeVar *rel, char rightkind, bool missing_ok)
|
||||
{
|
||||
Oid relOid;
|
||||
HeapTuple tuple;
|
||||
@@ -156,7 +179,10 @@ CheckDropPermissions(RangeVar *rel, char rightkind)
|
||||
|
||||
relOid = RangeVarGetRelid(rel, true);
|
||||
if (!OidIsValid(relOid))
|
||||
DropErrorMsgNonExistent(rel, rightkind);
|
||||
{
|
||||
DropErrorMsgNonExistent(rel, rightkind, missing_ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
tuple = SearchSysCache(RELOID,
|
||||
ObjectIdGetDatum(relOid),
|
||||
@@ -183,6 +209,8 @@ CheckDropPermissions(RangeVar *rel, char rightkind)
|
||||
rel->relname)));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -528,31 +556,36 @@ ProcessUtility(Node *parsetree,
|
||||
{
|
||||
case OBJECT_TABLE:
|
||||
rel = makeRangeVarFromNameList(names);
|
||||
CheckDropPermissions(rel, RELKIND_RELATION);
|
||||
RemoveRelation(rel, stmt->behavior);
|
||||
if (CheckDropPermissions(rel, RELKIND_RELATION,
|
||||
stmt->missing_ok))
|
||||
RemoveRelation(rel, stmt->behavior);
|
||||
break;
|
||||
|
||||
case OBJECT_SEQUENCE:
|
||||
rel = makeRangeVarFromNameList(names);
|
||||
CheckDropPermissions(rel, RELKIND_SEQUENCE);
|
||||
RemoveRelation(rel, stmt->behavior);
|
||||
if (CheckDropPermissions(rel, RELKIND_SEQUENCE,
|
||||
stmt->missing_ok))
|
||||
RemoveRelation(rel, stmt->behavior);
|
||||
break;
|
||||
|
||||
case OBJECT_VIEW:
|
||||
rel = makeRangeVarFromNameList(names);
|
||||
CheckDropPermissions(rel, RELKIND_VIEW);
|
||||
RemoveView(rel, stmt->behavior);
|
||||
if (CheckDropPermissions(rel, RELKIND_VIEW,
|
||||
stmt->missing_ok))
|
||||
RemoveView(rel, stmt->behavior);
|
||||
break;
|
||||
|
||||
case OBJECT_INDEX:
|
||||
rel = makeRangeVarFromNameList(names);
|
||||
CheckDropPermissions(rel, RELKIND_INDEX);
|
||||
RemoveIndex(rel, stmt->behavior);
|
||||
if (CheckDropPermissions(rel, RELKIND_INDEX,
|
||||
stmt->missing_ok))
|
||||
RemoveIndex(rel, stmt->behavior);
|
||||
break;
|
||||
|
||||
case OBJECT_TYPE:
|
||||
/* RemoveType does its own permissions checks */
|
||||
RemoveType(names, stmt->behavior);
|
||||
RemoveType(names, stmt->behavior,
|
||||
stmt->missing_ok);
|
||||
break;
|
||||
|
||||
case OBJECT_DOMAIN:
|
||||
@@ -560,11 +593,13 @@ ProcessUtility(Node *parsetree,
|
||||
/*
|
||||
* RemoveDomain does its own permissions checks
|
||||
*/
|
||||
RemoveDomain(names, stmt->behavior);
|
||||
RemoveDomain(names, stmt->behavior,
|
||||
stmt->missing_ok);
|
||||
break;
|
||||
|
||||
case OBJECT_CONVERSION:
|
||||
DropConversionCommand(names, stmt->behavior);
|
||||
DropConversionCommand(names, stmt->behavior,
|
||||
stmt->missing_ok);
|
||||
break;
|
||||
|
||||
case OBJECT_SCHEMA:
|
||||
@@ -572,7 +607,8 @@ ProcessUtility(Node *parsetree,
|
||||
/*
|
||||
* RemoveSchema does its own permissions checks
|
||||
*/
|
||||
RemoveSchema(names, stmt->behavior);
|
||||
RemoveSchema(names, stmt->behavior,
|
||||
stmt->missing_ok);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user