? src/backend/commands/.tablecmds.c.swp Index: doc/src/sgml/ref/alter_table.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/ref/alter_table.sgml,v retrieving revision 1.52 diff -c -r1.52 alter_table.sgml *** doc/src/sgml/ref/alter_table.sgml 2002/10/19 23:09:20 1.52 --- doc/src/sgml/ref/alter_table.sgml 2002/12/08 14:34:48 *************** *** 34,39 **** --- 34,41 ---- ALTER TABLE [ ONLY ] table [ * ] ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ALTER TABLE [ ONLY ] table [ * ] + SET { WITH | WITHOUT } OIDS + ALTER TABLE [ ONLY ] table [ * ] RENAME [ COLUMN ] column TO new_column ALTER TABLE table *************** *** 287,296 **** RENAME ! The RENAME forms change the name of a table (or an index, sequence, or view) or the name of an individual column in a table. There is no effect on the stored data. --- 289,317 ---- + SET WITH/WITHOUT OIDS + + + Adds or removes the OID column from the the table. When enabling + (setting with) oids in a table, the currently existing tuples are not immediately + numbered. Rather, it is treated as if a new column has been added to the table. + Since OIDs cannot be NULL, 0 is used instead. + + + Removing (setting without) oids from a table also do not occur immediately. The + space an OID uses will be reclaimed when the tuple is updated. + Without updating the tuple, both the space and the value of the OID + are maintained indefinitely. This is semantically similar to the + DROP COLUMN process. + + + + + RENAME ! The RENAME forms change the name of a table (or an index, sequence, or view) or the name of an individual column in a table. There is no effect on the stored data. Index: src/backend/catalog/heap.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/catalog/heap.c,v retrieving revision 1.235 diff -c -r1.235 heap.c *** src/backend/catalog/heap.c 2002/11/15 02:50:05 1.235 --- src/backend/catalog/heap.c 2002/12/08 14:35:30 *************** *** 528,533 **** --- 528,585 ---- heap_close(rel, RowExclusiveLock); } + /* + * AddNewOidAttributeTuple + * + * Create a pg_attribute entry for OIDs + */ + void + AddNewOidAttributeTuple(Oid new_rel_oid) + { + Form_pg_attribute attStruct; + HeapTuple tup; + Relation rel; + CatalogIndexState indstate; + + /* + * open pg_attribute and its indexes. + */ + rel = heap_openr(AttributeRelationName, RowExclusiveLock); + + indstate = CatalogOpenIndexes(rel); + + /* Add the OID attribute */ + tup = heap_addheader(Natts_pg_attribute, + false, + ATTRIBUTE_TUPLE_SIZE, + &a2); + + /* Fill in the correct relation OID in the copied tuple */ + attStruct = (Form_pg_attribute) GETSTRUCT(tup); + attStruct->attrelid = new_rel_oid; + + /* + * Unneeded since they should be OK in the constant data + * anyway + */ + /* attStruct->attstattarget = 0; */ + /* attStruct->attcacheoff = -1; */ + + simple_heap_insert(rel, tup); + + CatalogIndexInsert(indstate, tup); + + heap_freetuple(tup); + + /* + * clean up + */ + CatalogCloseIndexes(indstate); + + heap_close(rel, RowExclusiveLock); + } + + /* -------------------------------- * AddNewRelationTuple * Index: src/backend/commands/tablecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/tablecmds.c,v retrieving revision 1.57 diff -c -r1.57 tablecmds.c *** src/backend/commands/tablecmds.c 2002/11/23 18:26:45 1.57 --- src/backend/commands/tablecmds.c 2002/12/08 14:36:18 *************** *** 2140,2146 **** heap_close(rel, NoLock); } - /* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT */ --- 2140,2145 ---- *************** *** 2390,2395 **** --- 2389,2511 ---- heap_close(rel, NoLock); /* close rel, but keep lock! */ } + /* + * ALTER TABLE SET {WITH | WITHOUT} OIDS + */ + void + AlterTableAlterOids(Oid myrelid, bool recurse, bool setOid) + { + Relation rel; + Relation class_rel; + HeapTuple tuple; + Form_pg_class tuple_class; + + rel = heap_open(myrelid, AccessExclusiveLock); + + if (rel->rd_rel->relkind != RELKIND_RELATION) + elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", + RelationGetRelationName(rel)); + + if (!allowSystemTableMods + && IsSystemRelation(rel)) + elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", + RelationGetRelationName(rel)); + + if (!pg_class_ownercheck(myrelid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); + + + /* Get its pg_class tuple, too */ + class_rel = heap_openr(RelationRelationName, RowExclusiveLock); + + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(myrelid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "ALTER TABLE: relation %u not found", myrelid); + tuple_class = (Form_pg_class) GETSTRUCT(tuple); + + /* Can we change the ownership of this tuple? */ + CheckTupleType(tuple_class); + + /* + * Okay, this is a valid tuple: check it's hasoids flag + * to see if we actually need to change anything + */ + if (tuple_class->relhasoids == setOid) + elog(ERROR, "ALTER TABLE: Table is already %s", + setOid ? "WITH OIDS" : "WITHOUT OIDS"); + + /* + * 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); + } + } + + + 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) + /* + * Generate the now required OID pg_attribute entry + */ + AddNewOidAttributeTuple(myrelid); + else + { + HeapTuple atttup; + Relation attrel; + + /* 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), + ObjectIdAttributeNumber, 0, 0); + if (!HeapTupleIsValid(atttup)) + elog(ERROR, "ALTER TABLE: relation %u doesn't have an Oid column to remove", myrelid); + + simple_heap_delete(attrel, &atttup->t_self); + + ReleaseSysCache(atttup); + + heap_close(attrel, NoLock); /* close rel, but keep lock! */ + } + + + heap_close(rel, NoLock); /* close rel, but keep lock! */ + heap_close(class_rel, NoLock); /* close rel, but keep lock! */ + } /* * ALTER TABLE DROP COLUMN Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/parser/gram.y,v retrieving revision 2.383 diff -c -r2.383 gram.y *** src/backend/parser/gram.y 2002/11/25 21:29:40 2.383 --- src/backend/parser/gram.y 2002/12/08 14:38:01 *************** *** 313,318 **** --- 313,319 ---- %type constraints_set_list %type constraints_set_mode + %type alter_with_without /* *************** *** 1142,1148 **** | ALTER TABLE relation_expr ALTER opt_column ColId SET NOT NULL_P { AlterTableStmt *n = makeNode(AlterTableStmt); ! n->subtype = 'O'; n->relation = $3; n->name = $6; $$ = (Node *)n; --- 1143,1149 ---- | ALTER TABLE relation_expr ALTER opt_column ColId SET NOT NULL_P { AlterTableStmt *n = makeNode(AlterTableStmt); ! n->subtype = 'n'; n->relation = $3; n->name = $6; $$ = (Node *)n; *************** *** 1197,1202 **** --- 1198,1211 ---- n->behavior = $7; $$ = (Node *)n; } + /* ALTER TABLE SET {WITH|WITHOUT} OIDS */ + | ALTER TABLE relation_expr SET alter_with_without OIDS + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->subtype = $5; + $$ = (Node *)n; + } /* ALTER TABLE CREATE TOAST TABLE */ | ALTER TABLE qualified_name CREATE TOAST TABLE { *************** *** 1217,1222 **** --- 1226,1236 ---- $$ = (Node *)n; } ; + + alter_with_without: + WITH { $$ = 'O'; } + | WITHOUT { $$ = 'o'; } + ; alter_column_default: SET DEFAULT a_expr Index: src/backend/tcop/utility.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/tcop/utility.c,v retrieving revision 1.182 diff -c -r1.182 utility.c *** src/backend/tcop/utility.c 2002/11/15 03:09:38 1.182 --- src/backend/tcop/utility.c 2002/12/08 14:38:11 *************** *** 491,497 **** interpretInhOption(stmt->relation->inhOpt), stmt->name); break; ! case 'O': /* ALTER COLUMN SET NOT NULL */ AlterTableAlterColumnSetNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); --- 491,497 ---- interpretInhOption(stmt->relation->inhOpt), stmt->name); break; ! case 'n': /* ALTER COLUMN SET NOT NULL */ AlterTableAlterColumnSetNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); *************** *** 552,557 **** --- 552,567 ---- /* get_usesysid raises an error if no such user */ AlterTableOwner(relid, get_usesysid(stmt->name)); + break; + case 'O': /* ADD OIDS */ + AlterTableAlterOids(relid, + interpretInhOption(stmt->relation->inhOpt), + TRUE); + break; + case 'o': /* DROP OIDS */ + AlterTableAlterOids(relid, + interpretInhOption(stmt->relation->inhOpt), + FALSE); break; default: /* oops */ elog(ERROR, "T_AlterTableStmt: unknown subtype"); Index: src/include/catalog/heap.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/heap.h,v retrieving revision 1.59 diff -c -r1.59 heap.h *** src/include/catalog/heap.h 2002/11/11 22:19:23 1.59 --- src/include/catalog/heap.h 2002/12/08 14:38:27 *************** *** 52,57 **** --- 52,59 ---- List *rawColDefaults, List *rawConstraints); + extern void AddNewOidAttributeTuple(Oid new_rel_oid); + extern Node *cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, Index: src/include/commands/tablecmds.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/commands/tablecmds.h,v retrieving revision 1.10 diff -c -r1.10 tablecmds.h *** src/include/commands/tablecmds.h 2002/11/11 22:19:24 1.10 --- src/include/commands/tablecmds.h 2002/12/08 14:38:34 *************** *** 47,52 **** --- 47,54 ---- extern void AlterTableOwner(Oid relationOid, int32 newOwnerSysId); + extern void AlterTableAlterOids(Oid myrelid, bool recurse, bool setOid); + extern Oid DefineRelation(CreateStmt *stmt, char relkind); extern void RemoveRelation(const RangeVar *relation, DropBehavior behavior); Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/nodes/parsenodes.h,v retrieving revision 1.218 diff -c -r1.218 parsenodes.h *** src/include/nodes/parsenodes.h 2002/11/25 03:36:50 1.218 --- src/include/nodes/parsenodes.h 2002/12/08 14:38:50 *************** *** 808,814 **** * A = add column * T = alter column default * N = alter column drop not null ! * O = alter column set not null * S = alter column statistics * M = alter column storage * D = drop column --- 808,814 ---- * A = add column * T = alter column default * N = alter column drop not null ! * n = alter column set not null * S = alter column statistics * M = alter column storage * D = drop column *************** *** 818,823 **** --- 818,825 ---- * X = drop constraint * E = create toast table * U = change owner + * O = ADD OIDS + * o = DROP OIDS *------------ */ RangeVar *relation; /* table to work on */ Index: src/test/regress/expected/alter_table.out =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/test/regress/expected/alter_table.out,v retrieving revision 1.53 diff -c -r1.53 alter_table.out *** src/test/regress/expected/alter_table.out 2002/10/19 01:35:43 1.53 --- src/test/regress/expected/alter_table.out 2002/12/08 14:39:22 *************** *** 1166,1168 **** --- 1166,1260 ---- drop table p1, p2 cascade; NOTICE: Drop cascades to table c1 NOTICE: Drop cascades to table gc1 + -- + -- Test the ALTER TABLE {WITH|WITHOUT} OIDS commands + -- + create table altstartwith (col integer) with oids; + insert into altstartwith values (1); + select oid > 0, * from altstartwith; + ?column? | col + ----------+----- + t | 1 + (1 row) + + alter table altstartwith set with oids; -- fails + ERROR: ALTER TABLE: Table is already WITH OIDS + alter table altstartwith set without oids; + select oid > 0, * from altstartwith; -- fails + ERROR: Attribute "oid" not found + select * from altstartwith; + col + ----- + 1 + (1 row) + + insert into altstartwith values (2); + alter table altstartwith set without oids; -- fails + ERROR: ALTER TABLE: Table is already WITHOUT OIDS + alter table altstartwith set with oids; + insert into altstartwith values (3); + select oid > 0, * from altstartwith; + ?column? | col + ----------+----- + t | 1 + f | 2 + t | 3 + (3 rows) + + -- Run inheritance tests + create table altwithoid (col integer) with oids; + -- Inherits parents oid column + create table altinhoid () inherits (altwithoid) without oids; + insert into altinhoid values (1); + select oid > 0, * from altwithoid; + ?column? | col + ----------+----- + t | 1 + (1 row) + + select oid > 0, * from altinhoid; + ?column? | col + ----------+----- + t | 1 + (1 row) + + alter table altwithoid set without oids; + alter table altinhoid set without oids; -- fails + ERROR: ALTER TABLE: Table is already WITHOUT OIDS + select oid > 0, * from altwithoid; -- fails + ERROR: Attribute "oid" not found + select oid > 0, * from altinhoid; -- fails + ERROR: Attribute "oid" not found + select * from altwithoid; + col + ----- + 1 + (1 row) + + select * from altinhoid; + col + ----- + 1 + (1 row) + + alter table only altwithoid set with oids; + insert into altwithoid values (2); + insert into altinhoid values (3); + select oid > 0, * from altwithoid; + ?column? | col + ----------+----- + t | 2 + t | 1 + f | 3 + (3 rows) + + select oid > 0, * from altinhoid; -- fails + ERROR: Attribute "oid" not found + select * from altinhoid; -- fails + col + ----- + 1 + 3 + (2 rows) + + drop table altstartwith cascade; Index: src/test/regress/sql/alter_table.sql =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/test/regress/sql/alter_table.sql,v retrieving revision 1.34 diff -c -r1.34 alter_table.sql *** src/test/regress/sql/alter_table.sql 2002/10/19 01:35:43 1.34 --- src/test/regress/sql/alter_table.sql 2002/12/08 14:39:38 *************** *** 845,847 **** --- 845,900 ---- order by relname, attnum; drop table p1, p2 cascade; + + -- + -- Test the ALTER TABLE {WITH|WITHOUT} OIDS commands + -- + create table altstartwith (col integer) with oids; + + insert into altstartwith values (1); + + select oid > 0, * from altstartwith; + + alter table altstartwith set with oids; -- fails + alter table altstartwith set without oids; + + select oid > 0, * from altstartwith; -- fails + select * from altstartwith; + + insert into altstartwith values (2); + + alter table altstartwith set without oids; -- fails + alter table altstartwith set with oids; + + insert into altstartwith values (3); + select oid > 0, * from altstartwith; + + -- Run inheritance tests + create table altwithoid (col integer) with oids; + + -- Inherits parents oid column + create table altinhoid () inherits (altwithoid) without oids; + + insert into altinhoid values (1); + + select oid > 0, * from altwithoid; + select oid > 0, * from altinhoid; + + alter table altwithoid set without oids; + alter table altinhoid set without oids; -- fails + + select oid > 0, * from altwithoid; -- fails + select oid > 0, * from altinhoid; -- fails + select * from altwithoid; + select * from altinhoid; + + alter table only altwithoid set with oids; + + insert into altwithoid values (2); + insert into altinhoid values (3); + + select oid > 0, * from altwithoid; + select oid > 0, * from altinhoid; -- fails + select * from altinhoid; -- fails + + drop table altstartwith cascade;