DROP objecttype IF EXISTS for the following objects:

table view index sequence schema type domain conversion
This commit is contained in:
Andrew Dunstan
2005-11-19 17:39:45 +00:00
parent 8ef289dba1
commit daea4d8eae
22 changed files with 436 additions and 81 deletions

View File

@ -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);
}

View File

@ -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()))

View File

@ -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),

View File

@ -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

View File

@ -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},

View File

@ -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:

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.10 2005/06/28 05:09:12 tgl Exp $
* $PostgreSQL: pgsql/src/include/commands/conversioncmds.h,v 1.11 2005/11/19 17:39:45 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@ -18,7 +18,8 @@
#include "nodes/parsenodes.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
extern void DropConversionCommand(List *conversion_name, DropBehavior behavior);
extern void DropConversionCommand(List *conversion_name,
DropBehavior behavior, bool missing_ok);
extern void RenameConversion(List *name, const char *newname);
extern void AlterConversionOwner(List *name, Oid newOwnerId);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.10 2005/06/28 05:09:12 tgl Exp $
* $PostgreSQL: pgsql/src/include/commands/schemacmds.h,v 1.11 2005/11/19 17:39:45 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,7 +19,7 @@
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
extern void RemoveSchema(List *names, DropBehavior behavior);
extern void RemoveSchema(List *names, DropBehavior behavior, bool missing_ok);
extern void RemoveSchemaById(Oid schemaOid);
extern void RenameSchema(const char *oldname, const char *newname);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.14 2005/10/15 02:49:44 momjian Exp $
* $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.15 2005/11/19 17:39:45 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,10 +20,10 @@
#define DEFAULT_TYPDELIM ','
extern void DefineType(List *names, List *parameters);
extern void RemoveType(List *names, DropBehavior behavior);
extern void RemoveType(List *names, DropBehavior behavior, bool missing_ok);
extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt);
extern void RemoveDomain(List *names, DropBehavior behavior);
extern void RemoveDomain(List *names, DropBehavior behavior, bool missing_ok);
extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
extern void AlterDomainDefault(List *names, Node *defaultRaw);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.292 2005/10/26 19:21:55 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.293 2005/11/19 17:39:45 adunstan Exp $
*
*-------------------------------------------------------------------------
*/
@ -1278,6 +1278,7 @@ typedef struct DropStmt
List *objects; /* list of sublists of names (as Values) */
ObjectType removeType; /* object type */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
bool missing_ok; /* skip error if object is missing? */
} DropStmt;
/* ----------------------

View File

@ -0,0 +1,67 @@
--
-- IF EXISTS tests
--
-- table (will be really dropped at the end)
DROP TABLE test_exists;
ERROR: table "test_exists" does not exist
DROP TABLE IF EXISTS test_exists;
NOTICE: table "test_exists" does not exist, skipping
CREATE TABLE test_exists (a int, b text);
-- view
DROP VIEW test_view_exists;
ERROR: view "test_view_exists" does not exist
DROP VIEW IF EXISTS test_view_exists;
NOTICE: view "test_view_exists" does not exist, skipping
CREATE VIEW test_view_exists AS select * from test_exists;
DROP VIEW IF EXISTS test_view_exists;
DROP VIEW test_view_exists;
ERROR: view "test_view_exists" does not exist
-- index
DROP INDEX test_index_exists;
ERROR: index "test_index_exists" does not exist
DROP INDEX IF EXISTS test_index_exists;
NOTICE: index "test_index_exists" does not exist, skipping
CREATE INDEX test_index_exists on test_exists(a);
DROP INDEX IF EXISTS test_index_exists;
DROP INDEX test_index_exists;
ERROR: index "test_index_exists" does not exist
-- sequence
DROP SEQUENCE test_sequence_exists;
ERROR: sequence "test_sequence_exists" does not exist
DROP SEQUENCE IF EXISTS test_sequence_exists;
NOTICE: sequence "test_sequence_exists" does not exist, skipping
CREATE SEQUENCE test_sequence_exists;
DROP SEQUENCE IF EXISTS test_sequence_exists;
DROP SEQUENCE test_sequence_exists;
ERROR: sequence "test_sequence_exists" does not exist
-- schema
DROP SCHEMA test_schema_exists;
ERROR: schema "test_schema_exists" does not exist
DROP SCHEMA IF EXISTS test_schema_exists;
NOTICE: schema "test_schema_exists" does not exist, skipping
CREATE SCHEMA test_schema_exists;
DROP SCHEMA IF EXISTS test_schema_exists;
DROP SCHEMA test_schema_exists;
ERROR: schema "test_schema_exists" does not exist
-- type
DROP TYPE test_type_exists;
ERROR: type "test_type_exists" does not exist
DROP TYPE IF EXISTS test_type_exists;
NOTICE: type "test_type_exists" does not exist, skipping
CREATE type test_type_exists as (a int, b text);
DROP TYPE IF EXISTS test_type_exists;
DROP TYPE test_type_exists;
ERROR: type "test_type_exists" does not exist
-- domain
DROP DOMAIN test_domain_exists;
ERROR: type "test_domain_exists" does not exist
DROP DOMAIN IF EXISTS test_domain_exists;
NOTICE: type "test_domain_exists" does not exist, skipping
CREATE domain test_domain_exists as int not null check (value > 0);
DROP DOMAIN IF EXISTS test_domain_exists;
DROP DOMAIN test_domain_exists;
ERROR: type "test_domain_exists" does not exist
-- drop the table
DROP TABLE IF EXISTS test_exists;
DROP TABLE test_exists;
ERROR: table "test_exists" does not exist

View File

@ -38,7 +38,7 @@ test: copy
# ----------
# The third group of parallel test
# ----------
test: constraints triggers create_misc create_aggregate create_operator inherit vacuum
test: constraints triggers create_misc create_aggregate create_operator inherit vacuum drop_if_exists
# Depends on the above
test: create_index create_view

View File

@ -1,4 +1,4 @@
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.28 2005/07/07 20:40:01 tgl Exp $
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.29 2005/11/19 17:39:45 adunstan Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
@ -49,6 +49,7 @@ test: create_misc
test: create_aggregate
test: create_operator
test: create_index
test: drop_if_exists
test: inherit
test: vacuum
test: create_view

View File

@ -0,0 +1,91 @@
--
-- IF EXISTS tests
--
-- table (will be really dropped at the end)
DROP TABLE test_exists;
DROP TABLE IF EXISTS test_exists;
CREATE TABLE test_exists (a int, b text);
-- view
DROP VIEW test_view_exists;
DROP VIEW IF EXISTS test_view_exists;
CREATE VIEW test_view_exists AS select * from test_exists;
DROP VIEW IF EXISTS test_view_exists;
DROP VIEW test_view_exists;
-- index
DROP INDEX test_index_exists;
DROP INDEX IF EXISTS test_index_exists;
CREATE INDEX test_index_exists on test_exists(a);
DROP INDEX IF EXISTS test_index_exists;
DROP INDEX test_index_exists;
-- sequence
DROP SEQUENCE test_sequence_exists;
DROP SEQUENCE IF EXISTS test_sequence_exists;
CREATE SEQUENCE test_sequence_exists;
DROP SEQUENCE IF EXISTS test_sequence_exists;
DROP SEQUENCE test_sequence_exists;
-- schema
DROP SCHEMA test_schema_exists;
DROP SCHEMA IF EXISTS test_schema_exists;
CREATE SCHEMA test_schema_exists;
DROP SCHEMA IF EXISTS test_schema_exists;
DROP SCHEMA test_schema_exists;
-- type
DROP TYPE test_type_exists;
DROP TYPE IF EXISTS test_type_exists;
CREATE type test_type_exists as (a int, b text);
DROP TYPE IF EXISTS test_type_exists;
DROP TYPE test_type_exists;
-- domain
DROP DOMAIN test_domain_exists;
DROP DOMAIN IF EXISTS test_domain_exists;
CREATE domain test_domain_exists as int not null check (value > 0);
DROP DOMAIN IF EXISTS test_domain_exists;
DROP DOMAIN test_domain_exists;
-- drop the table
DROP TABLE IF EXISTS test_exists;
DROP TABLE test_exists;