diff -cr pgsql.orig/src/backend/commands/command.c pgsql.work/src/backend/commands/command.c *** pgsql.orig/src/backend/commands/command.c Sun Sep 10 20:56:06 2000 --- pgsql.work/src/backend/commands/command.c Mon Sep 11 10:00:48 2000 *************** *** 46,51 **** --- 46,52 ---- #include "utils/temprel.h" #include "executor/spi_priv.h" #include "catalog/pg_index.h" + #include "catalog/pg_shadow.h" #include "utils/relcache.h" #ifdef _DROP_COLUMN_HACK__ *************** *** 1457,1462 **** --- 1458,1527 ---- } + + /* + * ALTER TABLE OWNER + */ + void + AlterTableOwner(const char *relationName, const char *newOwnerName) + { + Relation class_rel; + HeapTuple tuple; + int4 newOwnerSysid; + Relation idescs[Num_pg_class_indices]; + + /* + * first check that we are a superuser + */ + if (! superuser() ) + elog(ERROR, "ALTER TABLE: permission denied"); + + /* + * look up the new owner in pg_shadow and get the sysid + */ + tuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(newOwnerName), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "ALTER TABLE: user \"%s\" not found", newOwnerName); + + newOwnerSysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; + heap_freetuple(tuple); + + /* + * find the table's entry in pg_class and lock it for writing + */ + class_rel = heap_openr(RelationRelationName, RowExclusiveLock); + + tuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(relationName), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "ALTER TABLE: relation \"%s\" not found", + relationName); + + if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION) + elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", + relationName); + + /* + * modify the table's entry and write to the heap + */ + ((Form_pg_class) GETSTRUCT(tuple))->relowner = newOwnerSysid; + + heap_update(class_rel, &tuple->t_self, tuple, NULL); + + /* Keep the catalog indices up to date */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_class_indices, class_rel, tuple); + CatalogCloseIndices(Num_pg_class_indices, idescs); + + /* + * unlock everything and return + */ + heap_freetuple(tuple); + heap_close(class_rel, RowExclusiveLock); + + return; + } /* * ALTER TABLE CREATE TOAST TABLE diff -cr pgsql.orig/src/backend/parser/gram.y pgsql.work/src/backend/parser/gram.y *** pgsql.orig/src/backend/parser/gram.y Sun Sep 10 20:56:08 2000 --- pgsql.work/src/backend/parser/gram.y Mon Sep 11 09:16:56 2000 *************** *** 350,356 **** LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE, MINVALUE, MODE, MOVE, NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL, ! OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL, REINDEX, RENAME, RESET, RETURNS, ROW, RULE, SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID, TEMP, TOAST, TRUNCATE, TRUSTED, --- 350,356 ---- LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE, MINVALUE, MODE, MOVE, NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL, ! OFFSET, OIDS, OPERATOR, OWNER, PASSWORD, PROCEDURAL, REINDEX, RENAME, RESET, RETURNS, ROW, RULE, SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID, TEMP, TOAST, TRUNCATE, TRUSTED, *************** *** 1031,1036 **** --- 1031,1046 ---- n->relname = $3; $$ = (Node *)n; } + + /* ALTER TABLE OWNER TO UserId */ + | ALTER TABLE relation_name OWNER TO UserId + { + AlterTableStmt *n = makeNode(AlterTableStmt); + n->subtype = 'U'; + n->relname = $3; + n->name = $6; + $$ = (Node *)n; + } ; alter_column_action: *************** *** 5641,5646 **** --- 5651,5657 ---- | OIDS { $$ = "oids"; } | OPERATOR { $$ = "operator"; } | OPTION { $$ = "option"; } + | OWNER { $$ = "owner"; } | PARTIAL { $$ = "partial"; } | PASSWORD { $$ = "password"; } | PENDANT { $$ = "pendant"; } diff -cr pgsql.orig/src/backend/parser/keywords.c pgsql.work/src/backend/parser/keywords.c *** pgsql.orig/src/backend/parser/keywords.c Sun Sep 10 20:56:08 2000 --- pgsql.work/src/backend/parser/keywords.c Mon Sep 11 09:48:58 2000 *************** *** 196,201 **** --- 196,202 ---- {"out", OUT}, {"outer", OUTER_P}, {"overlaps", OVERLAPS}, + {"owner", OWNER}, {"partial", PARTIAL}, {"password", PASSWORD}, {"path", PATH_P}, diff -cr pgsql.orig/src/backend/tcop/utility.c pgsql.work/src/backend/tcop/utility.c *** pgsql.orig/src/backend/tcop/utility.c Sun Sep 10 20:56:15 2000 --- pgsql.work/src/backend/tcop/utility.c Sun Sep 10 21:23:01 2000 *************** *** 368,373 **** --- 368,376 ---- case 'E': /* CREATE TOAST TABLE */ AlterTableCreateToastTable(stmt->relname, false); break; + case 'U': /* ALTER OWNER */ + AlterTableOwner(stmt->relname, stmt->name); + break; default: /* oops */ elog(ERROR, "T_AlterTableStmt: unknown subtype"); break; diff -cr pgsql.orig/src/include/commands/command.h pgsql.work/src/include/commands/command.h *** pgsql.orig/src/include/commands/command.h Sun Sep 10 20:56:22 2000 --- pgsql.work/src/include/commands/command.h Mon Sep 11 09:25:20 2000 *************** *** 61,66 **** --- 61,68 ---- extern void AlterTableCreateToastTable(const char *relationName, bool silent); + extern void AlterTableOwner(const char *relationName, const char *newOwnerName); + /* * LOCK */ diff -cr pgsql.orig/src/include/nodes/parsenodes.h pgsql.work/src/include/nodes/parsenodes.h *** pgsql.orig/src/include/nodes/parsenodes.h Sun Sep 10 20:56:23 2000 --- pgsql.work/src/include/nodes/parsenodes.h Sun Sep 10 21:14:54 2000 *************** *** 95,105 **** typedef struct AlterTableStmt { NodeTag type; ! char subtype; /* A = add, T = alter, D = drop, C = add ! * constr, X = drop constr */ char *relname; /* table to work on */ bool inh; /* recursively on children? */ ! char *name; /* column or constraint name to act on */ Node *def; /* definition of new column or constraint */ int behavior; /* CASCADE or RESTRICT drop behavior */ } AlterTableStmt; --- 95,107 ---- typedef struct AlterTableStmt { NodeTag type; ! char subtype; /* A = add column, T = alter column, D = drop column, ! * C = add constraint, X = drop constraint, ! * E = add toast table, ! * U = change owner */ char *relname; /* table to work on */ bool inh; /* recursively on children? */ ! char *name; /* column or constraint name to act on, or new owner */ Node *def; /* definition of new column or constraint */ int behavior; /* CASCADE or RESTRICT drop behavior */ } AlterTableStmt;