diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2000-01-16 20:05:00 +0000 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2000-01-16 20:05:00 +0000 |
commit | 759fba48734fdb93094ed6fe6b0d0c4d533fd0ca (patch) | |
tree | 504e54982096b18273f254a553bddbbcf16ae5f0 /src/backend/commands/command.c | |
parent | a4e1304ed1700c9831fdacc908fa0461ef0f5151 (diff) | |
download | postgresql-759fba48734fdb93094ed6fe6b0d0c4d533fd0ca.tar.gz postgresql-759fba48734fdb93094ed6fe6b0d0c4d533fd0ca.zip |
Included all yacc and lex files into the distribution.
Diffstat (limited to 'src/backend/commands/command.c')
-rw-r--r-- | src/backend/commands/command.c | 256 |
1 files changed, 238 insertions, 18 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 1874e0e2369..93322d7a7f7 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.62 1999/12/20 10:40:41 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.63 2000/01/16 20:04:55 petere Exp $ * * NOTES * The PortalExecutorHeapMemory crap needs to be eliminated @@ -23,13 +23,16 @@ #include "postgres.h" #include "access/heapam.h" +#include "access/skey.h" #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/indexing.h" +#include "catalog/pg_attrdef.h" #include "catalog/pg_type.h" #include "commands/command.h" #include "executor/execdefs.h" #include "executor/executor.h" +#include "catalog/heap.h" #include "miscadmin.h" #include "optimizer/prep.h" #include "utils/acl.h" @@ -37,6 +40,7 @@ #include "utils/syscache.h" #include "utils/temprel.h" + /* ---------------- * PortalExecutorHeapMemory stuff * @@ -246,7 +250,8 @@ PerformPortalClose(char *name, CommandDest dest) } /* ---------------- - * PerformAddAttribute + * AlterTableAddColumn + * (formerly known as PerformAddAttribute) * * adds an additional attribute to a relation * @@ -276,8 +281,7 @@ PerformPortalClose(char *name, CommandDest dest) * ---------------- */ void -PerformAddAttribute(char *relationName, - char *userName, +AlterTableAddColumn(const char *relationName, bool inherits, ColumnDef *colDef) { @@ -295,6 +299,7 @@ PerformAddAttribute(char *relationName, Relation idescs[Num_pg_attr_indices]; Relation ridescs[Num_pg_class_indices]; bool hasindex; + List *rawDefaults = NIL; /* * permissions checking. this would normally be done in utility.c, @@ -303,19 +308,18 @@ PerformAddAttribute(char *relationName, * normally, only the owner of a class can change its schema. */ if (!allowSystemTableMods && IsSystemRelationName(relationName)) - elog(ERROR, "PerformAddAttribute: class \"%s\" is a system catalog", + elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", relationName); #ifndef NO_SECURITY - if (!pg_ownercheck(userName, relationName, RELNAME)) - elog(ERROR, "PerformAddAttribute: you do not own class \"%s\"", - relationName); + if (!pg_ownercheck(UserName, relationName, RELNAME)) + elog(ERROR, "ALTER TABLE: permission denied"); #endif /* * Grab an exclusive lock on the target table, which we will NOT release * until end of transaction. */ - rel = heap_openr(relationName, AccessExclusiveLock); + rel = heap_openr((char *)relationName, AccessExclusiveLock); myrelid = RelationGetRelid(rel); heap_close(rel, NoLock); /* close rel but keep lock! */ @@ -324,8 +328,10 @@ PerformAddAttribute(char *relationName, */ if (colDef->is_not_null) elog(ERROR, "Can't add a NOT NULL attribute to an existing relation"); + if (colDef->raw_default || colDef->cooked_default) - elog(ERROR, "ADD ATTRIBUTE: DEFAULT not yet implemented"); + elog(ERROR, "Adding columns with defaults is not implemented."); + /* * if the first element in the 'schema' list is a "*" then we are @@ -358,8 +364,8 @@ PerformAddAttribute(char *relationName, if (childrelid == myrelid) continue; rel = heap_open(childrelid, AccessExclusiveLock); - PerformAddAttribute(RelationGetRelationName(rel), - userName, false, colDef); + AlterTableAddColumn(RelationGetRelationName(rel), + false, colDef); heap_close(rel, AccessExclusiveLock); } } @@ -372,7 +378,7 @@ PerformAddAttribute(char *relationName, 0, 0, 0); if (!HeapTupleIsValid(reltup)) - elog(ERROR, "PerformAddAttribute: relation \"%s\" not found", + elog(ERROR, "ALTER TABLE: relation \"%s\" not found", relationName); /* @@ -380,14 +386,14 @@ PerformAddAttribute(char *relationName, */ if (((Form_pg_class) GETSTRUCT(reltup))->relkind == RELKIND_INDEX) { - elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed", + elog(ERROR, "ALTER TABLE: index relation \"%s\" not changed", relationName); } minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts; maxatts = minattnum + 1; if (maxatts > MaxHeapAttributeNumber) - elog(ERROR, "PerformAddAttribute: relations limited to %d attributes", + elog(ERROR, "ALTER TABLE: relations limited to %d columns", MaxHeapAttributeNumber); attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock); @@ -421,7 +427,7 @@ PerformAddAttribute(char *relationName, 0, 0); if (HeapTupleIsValid(tup)) - elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"", + elog(ERROR, "ALTER TABLE: column name \"%s\" already exists in relation \"%s\"", colDef->colname, relationName); /* @@ -444,7 +450,7 @@ PerformAddAttribute(char *relationName, tform = (Form_pg_type) GETSTRUCT(typeTuple); if (!HeapTupleIsValid(typeTuple)) - elog(ERROR, "Add: type \"%s\" nonexistent", typename); + elog(ERROR, "ALTER TABLE: type \"%s\" does not exist", typename); namestrcpy(&(attribute->attname), colDef->colname); attribute->atttypid = typeTuple->t_data->t_oid; attribute->attlen = tform->typlen; @@ -483,9 +489,223 @@ PerformAddAttribute(char *relationName, CatalogCloseIndices(Num_pg_class_indices, ridescs); heap_freetuple(reltup); - heap_close(rel, RowExclusiveLock); + + heap_close(rel, NoLock); +} + + + +static void drop_default(Oid relid, int16 attnum); + + +/* + * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT + */ +void +AlterTableAlterColumn(const char *relationName, + bool inh, const char *colName, + Node *newDefault) +{ + Relation rel; + HeapTuple tuple; + int16 attnum; + Oid myrelid; + + if (!allowSystemTableMods && IsSystemRelationName(relationName)) + elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", + relationName); +#ifndef NO_SECURITY + if (!pg_ownercheck(UserName, relationName, RELNAME)) + elog(ERROR, "ALTER TABLE: permission denied"); +#endif + + /* XXX should heap_openr take const char * ? */ + rel = heap_openr((char *)relationName, AccessExclusiveLock); + myrelid = RelationGetRelid(rel); + heap_close(rel, NoLock); + + /* + * Propagate to children if desired + */ + if (inh) + { + 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; + rel = heap_open(childrelid, AccessExclusiveLock); + AlterTableAlterColumn(RelationGetRelationName(rel), + false, colName, newDefault); + heap_close(rel, AccessExclusiveLock); + } + } + + /* -= now do the thing on this relation =- */ + + /* reopen the business */ + rel = heap_openr((char *)relationName, AccessExclusiveLock); + + /* + * get the number of the attribute + */ + tuple = SearchSysCacheTuple(ATTNAME, + ObjectIdGetDatum(myrelid), + NameGetDatum(namein((char *)colName)), + 0, 0); + + if (!HeapTupleIsValid(tuple)) + { + heap_close(rel, AccessExclusiveLock); + elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"", + relationName, colName); + } + + attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum; + + if (newDefault) /* SET DEFAULT */ + { + List* rawDefaults = NIL; + RawColumnDefault *rawEnt; + + /* Get rid of the old one first */ + drop_default(myrelid, attnum); + + rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); + rawEnt->attnum = attnum; + rawEnt->raw_default = newDefault; + rawDefaults = lappend(rawDefaults, rawEnt); + + /* + * This function is intended for CREATE TABLE, + * so it processes a _list_ of defaults, but we just do one. + */ + AddRelationRawConstraints(rel, rawDefaults, NIL); + } + + else /* DROP DEFAULT */ + { + Relation attr_rel; + ScanKeyData scankeys[3]; + HeapScanDesc scan; + HeapTuple tuple; + + attr_rel = heap_openr(AttributeRelationName, AccessExclusiveLock); + ScanKeyEntryInitialize(&scankeys[0], 0x0, Anum_pg_attribute_attrelid, F_OIDEQ, + ObjectIdGetDatum(myrelid)); + ScanKeyEntryInitialize(&scankeys[1], 0x0, Anum_pg_attribute_attnum, F_INT2EQ, + Int16GetDatum(attnum)); + ScanKeyEntryInitialize(&scankeys[2], 0x0, Anum_pg_attribute_atthasdef, F_BOOLEQ, + TRUE); + + scan = heap_beginscan(attr_rel, false, SnapshotNow, 3, scankeys); + AssertState(scan!=NULL); + + if (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) + { + HeapTuple newtuple; + Relation irelations[Num_pg_attr_indices]; + + /* update to false */ + newtuple = heap_copytuple(tuple); + ((Form_pg_attribute) GETSTRUCT(newtuple))->atthasdef = FALSE; + heap_update(attr_rel, &tuple->t_self, newtuple, NULL); + + /* keep the system catalog indices current */ + CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations); + CatalogIndexInsert(irelations, Num_pg_attr_indices, attr_rel, newtuple); + CatalogCloseIndices(Num_pg_class_indices, irelations); + + /* get rid of actual default definition */ + drop_default(myrelid, attnum); + } + else + elog(NOTICE, "ALTER TABLE: there was no default on column \"%s\" of relation \"%s\"", + colName, relationName); + heap_endscan(scan); + heap_close(attr_rel, NoLock); + } + + heap_close(rel, NoLock); +} + + + +static void +drop_default(Oid relid, int16 attnum) +{ + ScanKeyData scankeys[2]; + HeapScanDesc scan; + Relation attrdef_rel; + HeapTuple tuple; + + attrdef_rel = heap_openr(AttrDefaultRelationName, AccessExclusiveLock); + ScanKeyEntryInitialize(&scankeys[0], 0x0, Anum_pg_attrdef_adrelid, F_OIDEQ, + ObjectIdGetDatum(relid)); + ScanKeyEntryInitialize(&scankeys[1], 0x0, Anum_pg_attrdef_adnum, F_INT2EQ, + Int16GetDatum(attnum)); + + scan = heap_beginscan(attrdef_rel, false, SnapshotNow, 2, scankeys); + AssertState(scan!=NULL); + + if (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) + heap_delete(attrdef_rel, &tuple->t_self, NULL); + + heap_endscan(scan); + + heap_close(attrdef_rel, NoLock); +} + + + +/* + * ALTER TABLE DROP COLUMN + */ +void +AlterTableDropColumn(const char *relationName, + bool inh, const char *colName, + int behavior) +{ + elog(NOTICE, "ALTER TABLE / DROP COLUMN is not implemented"); } + + +void +AlterTableAddConstraint(const char *relationName, + bool inh, Node *newConstraint) +{ + elog(NOTICE, "ALTER TABLE / ADD CONSTRAINT is not implemented"); +} + + + +void AlterTableDropConstraint(const char *relationName, + bool inh, const char *constrName, + int behavior) +{ + elog(NOTICE, "ALTER TABLE / DROP CONSTRAINT is not implemented"); +} + + + +/* + * + * LOCK TABLE + * + */ void LockTableCommand(LockStmt *lockstmt) { |