diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 3411c1f24a7..0c536c6d3b8 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -1,5 +1,5 @@ @@ -150,12 +150,11 @@ ALTER TABLE name SET WITHOUT OIDS - This form removes the oid column from the - table. Removing OIDs from a table does not occur immediately. - The space that the OID uses will be reclaimed when the row is - updated. Without updating the row, both the space and the value - of the OID are kept indefinitely. This is semantically similar - to the DROP COLUMN process. + This form removes the oid system column from the + table. This is exactly equivalent to + DROP COLUMN oid RESTRICT, + except that it will not complain if there is already no + oid column. diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index e768fb24b4f..e6bde26d337 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.64 2004/01/07 18:56:25 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.65 2004/03/23 19:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -197,6 +197,8 @@ Boot_CreateStmt: tupdesc, RELKIND_RELATION, $3, + true, + 0, ONCOMMIT_NOOP, true); elog(DEBUG4, "relation created with oid %u", id); diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 1fcc8e071da..ed68f9124d5 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.260 2004/02/15 21:01:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.261 2004/03/23 19:35:16 tgl Exp $ * * * INTERFACE ROUTINES @@ -458,7 +458,9 @@ CheckAttributeType(const char *attname, Oid atttypid) static void AddNewAttributeTuples(Oid new_rel_oid, TupleDesc tupdesc, - char relkind) + char relkind, + bool oidislocal, + int oidinhcount) { Form_pg_attribute *dpp; int i; @@ -531,11 +533,18 @@ AddNewAttributeTuples(Oid new_rel_oid, false, ATTRIBUTE_TUPLE_SIZE, (void *) *dpp); + attStruct = (Form_pg_attribute) GETSTRUCT(tup); /* Fill in the correct relation OID in the copied tuple */ - attStruct = (Form_pg_attribute) GETSTRUCT(tup); attStruct->attrelid = new_rel_oid; + /* Fill in correct inheritance info for the OID column */ + if (attStruct->attnum == ObjectIdAttributeNumber) + { + attStruct->attislocal = oidislocal; + attStruct->attinhcount = oidinhcount; + } + /* * Unneeded since they should be OK in the constant data * anyway @@ -713,6 +722,8 @@ heap_create_with_catalog(const char *relname, TupleDesc tupdesc, char relkind, bool shared_relation, + bool oidislocal, + int oidinhcount, OnCommitAction oncommit, bool allow_system_table_mods) { @@ -786,7 +797,8 @@ heap_create_with_catalog(const char *relname, * now add tuples to pg_attribute for the attributes in our new * relation. */ - AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relkind); + AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relkind, + oidislocal, oidinhcount); /* * make a dependency link to force the relation to be deleted if its @@ -973,35 +985,46 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) attnum, relid); attStruct = (Form_pg_attribute) GETSTRUCT(tuple); - /* Mark the attribute as dropped */ - attStruct->attisdropped = true; + if (attnum < 0) + { + /* System attribute (probably OID) ... just delete the row */ - /* - * Set the type OID to invalid. A dropped attribute's type link - * cannot be relied on (once the attribute is dropped, the type might - * be too). Fortunately we do not need the type row --- the only - * really essential information is the type's typlen and typalign, - * which are preserved in the attribute's attlen and attalign. We set - * atttypid to zero here as a means of catching code that incorrectly - * expects it to be valid. - */ - attStruct->atttypid = InvalidOid; + simple_heap_delete(attr_rel, &tuple->t_self); + } + else + { + /* Dropping user attributes is lots harder */ - /* Remove any NOT NULL constraint the column may have */ - attStruct->attnotnull = false; + /* Mark the attribute as dropped */ + attStruct->attisdropped = true; - /* We don't want to keep stats for it anymore */ - attStruct->attstattarget = 0; + /* + * Set the type OID to invalid. A dropped attribute's type link + * cannot be relied on (once the attribute is dropped, the type might + * be too). Fortunately we do not need the type row --- the only + * really essential information is the type's typlen and typalign, + * which are preserved in the attribute's attlen and attalign. We set + * atttypid to zero here as a means of catching code that incorrectly + * expects it to be valid. + */ + attStruct->atttypid = InvalidOid; - /* Change the column name to something that isn't likely to conflict */ - snprintf(newattname, sizeof(newattname), - "........pg.dropped.%d........", attnum); - namestrcpy(&(attStruct->attname), newattname); + /* Remove any NOT NULL constraint the column may have */ + attStruct->attnotnull = false; - simple_heap_update(attr_rel, &tuple->t_self, tuple); + /* We don't want to keep stats for it anymore */ + attStruct->attstattarget = 0; - /* keep the system catalog indexes current */ - CatalogUpdateIndexes(attr_rel, tuple); + /* Change the column name to something that isn't likely to conflict */ + snprintf(newattname, sizeof(newattname), + "........pg.dropped.%d........", attnum); + namestrcpy(&(attStruct->attname), newattname); + + simple_heap_update(attr_rel, &tuple->t_self, tuple); + + /* keep the system catalog indexes current */ + CatalogUpdateIndexes(attr_rel, tuple); + } /* * Because updating the pg_attribute row will trigger a relcache flush @@ -1011,7 +1034,8 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) heap_close(attr_rel, RowExclusiveLock); - RemoveStatistics(rel, attnum); + if (attnum > 0) + RemoveStatistics(rel, attnum); relation_close(rel, NoLock); } diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index e39320d9edd..a10bbbd746c 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.119 2003/11/29 19:51:47 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.120 2004/03/23 19:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -501,6 +501,8 @@ make_new_heap(Oid OIDOldHeap, const char *NewName) tupdesc, OldHeap->rd_rel->relkind, OldHeap->rd_rel->relisshared, + true, + 0, ONCOMMIT_NOOP, allowSystemTableMods); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 25794ce93fe..1a6bd2fdfc0 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.100 2004/03/13 22:09:13 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.101 2004/03/23 19:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -77,7 +77,7 @@ static List *on_commits = NIL; static List *MergeAttributes(List *schema, List *supers, bool istemp, - List **supOids, List **supconstr, bool *supHasOids); + List **supOids, List **supconstr, int *supOidCount); static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno); static void StoreCatalogInheritance(Oid relationId, List *supers); static int findAttrByName(const char *attributeName, List *schema); @@ -133,7 +133,8 @@ DefineRelation(CreateStmt *stmt, char relkind) TupleDesc descriptor; List *inheritOids; List *old_constraints; - bool parentHasOids; + bool localHasOids; + int parentOidCount; List *rawDefaults; List *listptr; int i; @@ -177,7 +178,7 @@ DefineRelation(CreateStmt *stmt, char relkind) */ schema = MergeAttributes(schema, stmt->inhRelations, stmt->relation->istemp, - &inheritOids, &old_constraints, &parentHasOids); + &inheritOids, &old_constraints, &parentOidCount); /* * Create a relation descriptor from the relation schema and create @@ -188,10 +189,8 @@ DefineRelation(CreateStmt *stmt, char relkind) */ descriptor = BuildDescForRelation(schema); - if (parentHasOids) - descriptor->tdhasoid = true; - else - descriptor->tdhasoid = interpretOidsOption(stmt->hasoids); + localHasOids = interpretOidsOption(stmt->hasoids); + descriptor->tdhasoid = (localHasOids || parentOidCount > 0); if (old_constraints != NIL) { @@ -255,6 +254,8 @@ DefineRelation(CreateStmt *stmt, char relkind) descriptor, relkind, false, + localHasOids, + parentOidCount, stmt->oncommit, allowSystemTableMods); @@ -436,7 +437,7 @@ TruncateRelation(const RangeVar *relation) * 'supOids' receives a list of the OIDs of the parent relations. * 'supconstr' receives a list of constraints belonging to the parents, * updated as necessary to be valid for the child. - * 'supHasOids' is set TRUE if any parent has OIDs, else it is set FALSE. + * 'supOidCount' is set to the number of parents that have OID columns. * * Return value: * Completed schema list. @@ -482,13 +483,13 @@ TruncateRelation(const RangeVar *relation) */ static List * MergeAttributes(List *schema, List *supers, bool istemp, - List **supOids, List **supconstr, bool *supHasOids) + List **supOids, List **supconstr, int *supOidCount) { List *entry; List *inhSchema = NIL; List *parentOids = NIL; List *constraints = NIL; - bool parentHasOids = false; + int parentsWithOids = 0; bool have_bogus_defaults = false; char *bogus_marker = "Bogus!"; /* marks conflicting * defaults */ @@ -566,7 +567,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, parentOids = lappendo(parentOids, RelationGetRelid(relation)); - parentHasOids |= relation->rd_rel->relhasoids; + if (relation->rd_rel->relhasoids) + parentsWithOids++; tupleDesc = RelationGetDescr(relation); constr = tupleDesc->constr; @@ -825,7 +827,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, *supOids = parentOids; *supconstr = constraints; - *supHasOids = parentHasOids; + *supOidCount = parentsWithOids; return schema; } @@ -2422,92 +2424,30 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse, } /* - * ALTER TABLE SET {WITHOUT} OIDS + * ALTER TABLE SET WITH/WITHOUT OIDS */ void -AlterTableAlterOids(Oid myrelid, bool recurse, bool setOid) +AlterTableAlterOids(Oid myrelid, bool setOid, bool recurse, + DropBehavior behavior) { Relation rel; - Relation class_rel; - HeapTuple tuple; - Form_pg_class tuple_class; rel = heap_open(myrelid, AccessExclusiveLock); - if (rel->rd_rel->relkind != RELKIND_RELATION) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table", - RelationGetRelationName(rel)))); - - /* Permissions checks */ - if (!pg_class_ownercheck(myrelid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - RelationGetRelationName(rel)); - - if (!allowSystemTableMods && IsSystemRelation(rel)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied: \"%s\" is a system catalog", - RelationGetRelationName(rel)))); - - /* - * Propagate to children if desired - */ - if (recurse) - { - List *child, - *children; - - /* this routine is actually in the planner */ - children = find_all_inheritors(myrelid); - - /* - * find_all_inheritors does the recursive search of the - * inheritance hierarchy, so all we have to do is process all of - * the relids in the list that it returns. - */ - foreach(child, children) - { - Oid childrelid = lfirsti(child); - - if (childrelid == myrelid) - continue; - - AlterTableAlterOids(childrelid, false, setOid); - } - } - - /* Do the thing on this relation */ - class_rel = heap_openr(RelationRelationName, RowExclusiveLock); - - tuple = SearchSysCacheCopy(RELOID, - ObjectIdGetDatum(myrelid), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "cache lookup failed for relation %u", myrelid); - tuple_class = (Form_pg_class) GETSTRUCT(tuple); - /* * check to see if we actually need to change anything */ - if (tuple_class->relhasoids == setOid) + if (rel->rd_rel->relhasoids == setOid) { - heap_close(class_rel, RowExclusiveLock); heap_close(rel, NoLock); /* close rel, but keep lock! */ return; } - tuple_class->relhasoids = setOid; - simple_heap_update(class_rel, &tuple->t_self, tuple); - - /* Keep the catalog indexes up to date */ - CatalogUpdateIndexes(class_rel, tuple); - if (setOid) { /* - * TODO: Generate the now required OID pg_attribute entry + * TODO: Generate the now required OID pg_attribute entry, and + * modify physical rows to have OIDs. */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -2515,34 +2455,10 @@ AlterTableAlterOids(Oid myrelid, bool recurse, bool setOid) } else { - HeapTuple atttup; - Relation attrel; + heap_close(rel, NoLock); /* close rel, but keep lock! */ - /* Add / Remove the oid record from pg_attribute */ - attrel = heap_open(RelOid_pg_attribute, RowExclusiveLock); - - /* - * Oids are being removed from the relation, so we need to remove - * the oid pg_attribute record relating. - */ - atttup = SearchSysCache(ATTNUM, - ObjectIdGetDatum(myrelid), - Int16GetDatum(ObjectIdAttributeNumber), - 0, 0); - if (!HeapTupleIsValid(atttup)) - elog(ERROR, "cache lookup failed for attribute %d of relation %u", - ObjectIdAttributeNumber, myrelid); - - simple_heap_delete(attrel, &atttup->t_self); - - ReleaseSysCache(atttup); - - heap_close(attrel, RowExclusiveLock); + AlterTableDropColumn(myrelid, recurse, false, "oid", behavior); } - - heap_close(class_rel, RowExclusiveLock); - - heap_close(rel, NoLock); /* close rel, but keep lock! */ } /* @@ -2555,7 +2471,8 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing, { Relation rel; AttrNumber attnum; - TupleDesc tupleDesc; + HeapTuple tuple; + Form_pg_attribute targetatt; ObjectAddress object; rel = heap_open(myrelid, AccessExclusiveLock); @@ -2580,29 +2497,32 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing, /* * get the number of the attribute */ - attnum = get_attnum(myrelid, colName); - if (attnum == InvalidAttrNumber) + tuple = SearchSysCacheAttName(myrelid, colName); + if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", - colName, RelationGetRelationName(rel)))); + errmsg("column \"%s\" of relation \"%s\" does not exist", + colName, RelationGetRelationName(rel)))); + targetatt = (Form_pg_attribute) GETSTRUCT(tuple); - /* Can't drop a system attribute */ - /* XXX perhaps someday allow dropping OID? */ - if (attnum < 0) + attnum = targetatt->attnum; + + /* Can't drop a system attribute, except OID */ + if (attnum <= 0 && attnum != ObjectIdAttributeNumber) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot drop system column \"%s\"", colName))); /* Don't drop inherited columns */ - tupleDesc = RelationGetDescr(rel); - if (tupleDesc->attrs[attnum - 1]->attinhcount > 0 && !recursing) + if (targetatt->attinhcount > 0 && !recursing) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("cannot drop inherited column \"%s\"", colName))); + ReleaseSysCache(tuple); + /* * If we are asked to drop ONLY in this table (no recursion), we need * to mark the inheritors' attribute as locally defined rather than @@ -2622,7 +2542,6 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing, { Oid childrelid = lfirsto(child); Relation childrel; - HeapTuple tuple; Form_pg_attribute childatt; childrel = heap_open(childrelid, AccessExclusiveLock); @@ -2670,7 +2589,6 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing, { Oid childrelid = lfirsto(child); Relation childrel; - HeapTuple tuple; Form_pg_attribute childatt; if (childrelid == myrelid) @@ -2712,7 +2630,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing, } /* - * Perform the actual deletion + * Perform the actual column deletion */ object.classId = RelOid_pg_class; object.objectId = myrelid; @@ -2720,6 +2638,32 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing, performDeletion(&object, behavior); + /* + * If we dropped the OID column, must adjust pg_class.relhasoids + */ + if (attnum == ObjectIdAttributeNumber) + { + Relation class_rel; + Form_pg_class tuple_class; + + class_rel = heap_openr(RelationRelationName, RowExclusiveLock); + + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(myrelid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for relation %u", myrelid); + tuple_class = (Form_pg_class) GETSTRUCT(tuple); + + tuple_class->relhasoids = false; + simple_heap_update(class_rel, &tuple->t_self, tuple); + + /* Keep the catalog indexes up to date */ + CatalogUpdateIndexes(class_rel, tuple); + + heap_close(class_rel, RowExclusiveLock); + } + heap_close(rel, NoLock); /* close rel, but keep lock! */ } @@ -4171,6 +4115,8 @@ AlterTableCreateToastTable(Oid relOid, bool silent) tupdesc, RELKIND_TOASTVALUE, shared_relation, + true, + 0, ONCOMMIT_NOOP, true); diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index caae6e880e5..13b38d37529 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.229 2004/03/02 18:56:15 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.230 2004/03/23 19:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -797,6 +797,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly) tupdesc, RELKIND_RELATION, false, + true, + 0, ONCOMMIT_NOOP, allowSystemTableMods); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 8a23fcc70ef..11b3ff168ac 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.210 2004/02/10 01:55:26 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.211 2004/03/23 19:35:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -608,10 +608,11 @@ ProcessUtility(Node *parsetree, case 'L': /* CLUSTER ON */ AlterTableClusterOn(relid, stmt->name); break; - case 'o': /* ADD OIDS */ + case 'o': /* SET WITHOUT OIDS */ AlterTableAlterOids(relid, + false, interpretInhOption(stmt->relation->inhOpt), - false); + DROP_RESTRICT); break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 741b0a129e6..f635ef1bd09 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.64 2004/02/15 21:01:39 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.65 2004/03/23 19:35:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,6 +41,8 @@ extern Oid heap_create_with_catalog(const char *relname, TupleDesc tupdesc, char relkind, bool shared_relation, + bool oidislocal, + int oidinhcount, OnCommitAction oncommit, bool allow_system_table_mods); diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 1f71eebe8ec..889b4dfa626 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.14 2003/11/29 22:40:59 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.15 2004/03/23 19:35:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,8 @@ extern void AlterTableCreateToastTable(Oid relOid, bool silent); extern void AlterTableOwner(Oid relationOid, int32 newOwnerSysId); -extern void AlterTableAlterOids(Oid myrelid, bool recurse, bool setOid); +extern void AlterTableAlterOids(Oid myrelid, bool setOid, bool recurse, + DropBehavior behavior); extern Oid DefineRelation(CreateStmt *stmt, char relkind); diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 0396351f1ff..089651c7278 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -688,9 +688,11 @@ delete from atacc1; -- try dropping a non-existent column, should fail alter table atacc1 drop bar; ERROR: column "bar" of relation "atacc1" does not exist --- try dropping the oid column, should fail +-- try dropping the oid column, should succeed alter table atacc1 drop oid; -ERROR: cannot drop system column "oid" +-- try dropping the xmin column, should fail +alter table atacc1 drop xmin; +ERROR: cannot drop system column "xmin" -- try creating a view and altering that, should fail create view myview as select * from atacc1; select * from myview; diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 749af267107..dcd968a0b65 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -632,9 +632,12 @@ delete from atacc1; -- try dropping a non-existent column, should fail alter table atacc1 drop bar; --- try dropping the oid column, should fail +-- try dropping the oid column, should succeed alter table atacc1 drop oid; +-- try dropping the xmin column, should fail +alter table atacc1 drop xmin; + -- try creating a view and altering that, should fail create view myview as select * from atacc1; select * from myview;