From 8195f8f0427e0387f595ca951e4dcc257655e891 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 13 Feb 2003 05:20:05 +0000 Subject: [PATCH] Code for WITHOUT OIDS. On Wed, 2003-01-08 at 21:59, Christopher Kings-Lynne wrote: > I agree. I want to remove OIDs from heaps of our tables when we go to 7.3. > I'd rather not have to do it in the dump due to down time. Rod Taylor --- doc/src/sgml/ref/alter_table.sgml | 19 +++- src/backend/commands/tablecmds.c | 119 +++++++++++++++++++++- src/backend/parser/gram.y | 12 ++- src/backend/tcop/utility.c | 9 +- src/include/commands/tablecmds.h | 4 +- src/include/nodes/parsenodes.h | 5 +- src/test/regress/expected/alter_table.out | 56 ++++++++++ src/test/regress/sql/alter_table.sql | 33 ++++++ 8 files changed, 246 insertions(+), 11 deletions(-) diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 2287a72cb6..5499cd158c 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -1,5 +1,5 @@ @@ -33,6 +33,8 @@ ALTER TABLE [ ONLY ] table [ * ] ALTER [ COLUMN ] column SET STATISTICS integer ALTER TABLE [ ONLY ] table [ * ] ALTER [ COLUMN ] column SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } +ALTER TABLE [ ONLY ] table [ * ] + SET WITHOUT OIDS ALTER TABLE [ ONLY ] table [ * ] RENAME [ COLUMN ] column TO new_column @@ -286,11 +288,24 @@ ALTER TABLE table + + SET WITHOUT OIDS + + + Removes the OID column from the the table. 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 + 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. diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index c7b19124db..13401ed107 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.66 2003/02/09 06:56:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.67 2003/02/13 05:19:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2134,7 +2134,6 @@ AlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse, heap_close(rel, NoLock); } - /* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT */ @@ -2384,6 +2383,122 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse, heap_close(rel, NoLock); /* close rel, but keep lock! */ } +/* + * ALTER TABLE SET {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) + /* + * TODO: Generate the now required OID pg_attribute entry + */ + elog(ERROR, "ALTER TABLE WITH OIDS is unsupported"); + 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 diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ba15349782..f6ce850f37 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.401 2003/02/10 04:44:45 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.402 2003/02/13 05:19:59 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1132,7 +1132,7 @@ AlterTableStmt: | ALTER TABLE relation_expr ALTER opt_column ColId SET NOT NULL_P { AlterTableStmt *n = makeNode(AlterTableStmt); - n->subtype = 'O'; + n->subtype = 'n'; n->relation = $3; n->name = $6; $$ = (Node *)n; @@ -1187,6 +1187,14 @@ AlterTableStmt: n->behavior = $7; $$ = (Node *)n; } + /* ALTER TABLE SET WITHOUT OIDS */ + | ALTER TABLE relation_expr SET WITHOUT OIDS + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->relation = $3; + n->subtype = 'o'; + $$ = (Node *)n; + } /* ALTER TABLE CREATE TOAST TABLE */ | ALTER TABLE qualified_name CREATE TOAST TABLE { diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 18a474f34b..b48550428f 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.191 2003/02/10 04:44:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.192 2003/02/13 05:20:01 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -549,7 +549,7 @@ ProcessUtility(Node *parsetree, interpretInhOption(stmt->relation->inhOpt), stmt->name); break; - case 'O': /* ALTER COLUMN SET NOT NULL */ + case 'n': /* ALTER COLUMN SET NOT NULL */ AlterTableAlterColumnSetNotNull(relid, interpretInhOption(stmt->relation->inhOpt), stmt->name); @@ -611,6 +611,11 @@ ProcessUtility(Node *parsetree, AlterTableOwner(relid, get_usesysid(stmt->name)); break; + case 'o': /* ADD OIDS */ + AlterTableAlterOids(relid, + interpretInhOption(stmt->relation->inhOpt), + false); + break; default: /* oops */ elog(ERROR, "ProcessUtility: Invalid type for AlterTableStmt: %d", stmt->subtype); diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 13873dad1b..6b533cab2f 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tablecmds.h,v 1.10 2002/11/11 22:19:24 tgl Exp $ + * $Id: tablecmds.h,v 1.11 2003/02/13 05:20:03 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,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 Oid DefineRelation(CreateStmt *stmt, char relkind); extern void RemoveRelation(const RangeVar *relation, DropBehavior behavior); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 5f8f4794f9..9474bc6490 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.229 2003/02/10 04:44:47 tgl Exp $ + * $Id: parsenodes.h,v 1.230 2003/02/13 05:20:03 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -698,7 +698,7 @@ typedef struct AlterTableStmt * A = add column * T = alter column default * N = alter column drop not null - * O = alter column set not null + * n = alter column set not null * S = alter column statistics * M = alter column storage * D = drop column @@ -708,6 +708,7 @@ typedef struct AlterTableStmt * X = drop constraint * E = create toast table * U = change owner + * o = DROP OIDS *------------ */ RangeVar *relation; /* table to work on */ diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 877d8bdd84..7015753d17 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -1179,6 +1179,62 @@ order by relname, attnum; drop table p1, p2 cascade; NOTICE: Drop cascades to table c1 NOTICE: Drop cascades to table gc1 +-- +-- Test the ALTER TABLE WITHOUT OIDS command +-- +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 without oids; +select oid > 0, * from altstartwith; -- fails +ERROR: Attribute "oid" not found +select * from altstartwith; + col +----- + 1 +(1 row) + +-- 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) + -- test renumbering of child-table columns in inherited operations create table p1 (f1 int); create table c1 (f2 text, f3 int) inherits (p1); diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index 79ea952ade..8e98d077a4 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -850,6 +850,39 @@ order by relname, attnum; drop table p1, p2 cascade; +-- +-- Test the ALTER TABLE WITHOUT OIDS command +-- +create table altstartwith (col integer) with oids; + +insert into altstartwith values (1); + +select oid > 0, * from altstartwith; + +alter table altstartwith set without oids; + +select oid > 0, * from altstartwith; -- fails +select * 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; + -- test renumbering of child-table columns in inherited operations create table p1 (f1 int);