diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/cluster.c | 9 | ||||
-rw-r--r-- | src/backend/commands/command.c | 84 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 456 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 96 | ||||
-rw-r--r-- | src/backend/commands/creatinh.c | 21 | ||||
-rw-r--r-- | src/backend/commands/dbcommands.c | 8 | ||||
-rw-r--r-- | src/backend/commands/indexcmds.c | 4 | ||||
-rw-r--r-- | src/backend/commands/remove.c | 32 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 5 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 14 | ||||
-rw-r--r-- | src/backend/commands/vacuum.c | 11 | ||||
-rw-r--r-- | src/backend/commands/vacuumlazy.c | 5 | ||||
-rw-r--r-- | src/backend/commands/view.c | 5 |
13 files changed, 421 insertions, 329 deletions
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index e72d13897dc..0d76c6e8d37 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.67 2001/07/12 20:35:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.68 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -160,7 +160,9 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp) tupdesc = CreateTupleDescCopyConstr(OldHeapDesc); OIDNewHeap = heap_create_with_catalog(NewName, tupdesc, - RELKIND_RELATION, istemp, + OldHeap->rd_rel->relkind, + OldHeap->rd_rel->relhasoids, + istemp, allowSystemTableMods); /* @@ -227,7 +229,8 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName) Old_pg_index_Form->indisprimary, allowSystemTableMods); - setRelhasindex(OIDNewHeap, true); + setRelhasindex(OIDNewHeap, true, + Old_pg_index_Form->indisprimary, InvalidOid); ReleaseSysCache(Old_pg_index_Tuple); ReleaseSysCache(Old_pg_index_relation_Tuple); diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 3d02fdb5fd2..1e8b7c56992 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.139 2001/08/10 14:30:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.140 2001/08/10 18:57:34 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -102,7 +102,7 @@ PerformPortalFetch(char *name, QueryDesc *queryDesc; EState *estate; MemoryContext oldcontext; - bool faked_desc = false; + bool temp_desc = false; /* * sanity checks @@ -130,24 +130,33 @@ PerformPortalFetch(char *name, oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); /* - * tell the destination to prepare to receive some tuples. + * If the requested destination is not the same as the query's + * original destination, make a temporary QueryDesc with the proper + * destination. This supports MOVE, for example, which will pass in + * dest = None. * - * If we've been asked for a MOVE, make a temporary QueryDesc with the - * appropriate dummy destination. + * EXCEPTION: if the query's original dest is RemoteInternal (ie, it's + * a binary cursor) and the request is Remote, we do NOT override the + * original dest. This is necessary since a FETCH command will pass + * dest = Remote, not knowing whether the cursor is binary or not. */ queryDesc = PortalGetQueryDesc(portal); estate = PortalGetState(portal); - if (dest != queryDesc->dest) /* MOVE */ + if (dest != queryDesc->dest && + !(queryDesc->dest == RemoteInternal && dest == Remote)) { QueryDesc *qdesc = (QueryDesc *) palloc(sizeof(QueryDesc)); memcpy(qdesc, queryDesc, sizeof(QueryDesc)); qdesc->dest = dest; queryDesc = qdesc; - faked_desc = true; + temp_desc = true; } + /* + * tell the destination to prepare to receive some tuples. + */ BeginCommand(name, queryDesc->operation, PortalGetTupleDesc(portal), @@ -156,7 +165,7 @@ PerformPortalFetch(char *name, false, /* this is a portal fetch, not a "retrieve * portal" */ tag, - dest); + queryDesc->dest); /* * Determine which direction to go in, and check to see if we're @@ -205,7 +214,7 @@ PerformPortalFetch(char *name, /* * Clean up and switch back to old context. */ - if (faked_desc) /* MOVE */ + if (temp_desc) pfree(queryDesc); MemoryContextSwitchTo(oldcontext); @@ -1004,8 +1013,7 @@ AlterTableDropColumn(const char *relationName, #ifdef _DROP_COLUMN_HACK__ Relation rel, attrdesc; - Oid myrelid, - attoid; + Oid myrelid; HeapTuple reltup; HeapTupleData classtuple; Buffer buffer; @@ -1094,7 +1102,6 @@ AlterTableDropColumn(const char *relationName, if (attnum <= 0) elog(ERROR, "ALTER TABLE: column name \"%s\" was already dropped", colName); - attoid = tup->t_data->t_oid; /* * Check constraints/indices etc here @@ -1124,8 +1131,9 @@ AlterTableDropColumn(const char *relationName, heap_close(attrdesc, NoLock); heap_freetuple(tup); - /* delete comments */ - DeleteComments(attoid); + /* delete comment for this attribute only */ + CreateComments(RelationGetRelid(rel), RelOid_pg_class, + (int32) attnum, NULL); /* delete attrdef */ drop_default(myrelid, attnum); @@ -1750,9 +1758,8 @@ AlterTableCreateToastTable(const char *relationName, bool silent) Oid toast_idxid; char toast_relname[NAMEDATALEN + 1]; char toast_idxname[NAMEDATALEN + 1]; - Relation toast_idxrel; IndexInfo *indexInfo; - Oid classObjectId[1]; + Oid classObjectId[2]; /* * permissions checking. XXX exactly what is appropriate here? @@ -1870,50 +1877,49 @@ AlterTableCreateToastTable(const char *relationName, bool silent) * so there's no need to handle the toast rel as temp. */ toast_relid = heap_create_with_catalog(toast_relname, tupdesc, - RELKIND_TOASTVALUE, + RELKIND_TOASTVALUE, false, false, true); /* make the toast relation visible, else index creation will fail */ CommandCounterIncrement(); - /* create index on chunk_id */ + /* + * Create unique index on chunk_id, chunk_seq. + * + * NOTE: the tuple toaster could actually function with a single-column + * index on chunk_id only. However, it couldn't be unique then. We + * want it to be unique as a check against the possibility of duplicate + * TOAST chunk OIDs. Too, the index might be a little more efficient this + * way, since btree isn't all that happy with large numbers of equal keys. + */ indexInfo = makeNode(IndexInfo); - indexInfo->ii_NumIndexAttrs = 1; - indexInfo->ii_NumKeyAttrs = 1; + indexInfo->ii_NumIndexAttrs = 2; + indexInfo->ii_NumKeyAttrs = 2; indexInfo->ii_KeyAttrNumbers[0] = 1; + indexInfo->ii_KeyAttrNumbers[1] = 2; indexInfo->ii_Predicate = NIL; indexInfo->ii_FuncOid = InvalidOid; - indexInfo->ii_Unique = false; + indexInfo->ii_Unique = true; classObjectId[0] = OID_OPS_OID; + classObjectId[1] = INT4_OPS_OID; - index_create(toast_relname, toast_idxname, indexInfo, - BTREE_AM_OID, classObjectId, - false, false, true); + toast_idxid = index_create(toast_relname, toast_idxname, indexInfo, + BTREE_AM_OID, classObjectId, + false, true, true); /* * Update toast rel's pg_class entry to show that it has an index. + * The index OID is stored into the reltoastidxid field for + * easy access by the tuple toaster. */ - setRelhasindex(toast_relid, true); - - /* - * Make index visible - */ - CommandCounterIncrement(); - - /* - * Get the OID of the newly created index - */ - toast_idxrel = index_openr(toast_idxname); - toast_idxid = RelationGetRelid(toast_idxrel); - index_close(toast_idxrel); + setRelhasindex(toast_relid, true, true, toast_idxid); /* - * Store the toast table- and index-Oid's in the relation tuple + * Store the toast table's OID in the parent relation's tuple */ ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid; - ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid; simple_heap_update(class_rel, &reltup->t_self, reltup); /* diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 2f28130f8b9..4bf6993d02a 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,13 +7,14 @@ * Copyright (c) 1999-2001, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.31 2001/06/25 21:11:43 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.32 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" @@ -22,7 +23,6 @@ #include "catalog/pg_operator.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" -#include "catalog/pg_class.h" #include "commands/comment.h" #include "miscadmin.h" #include "parser/parse_expr.h" @@ -32,6 +32,7 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" @@ -54,7 +55,7 @@ static void CommentAggregate(char *aggregate, List *arguments, char *comment); static void CommentProc(char *function, List *arguments, char *comment); static void CommentOperator(char *opname, List *arguments, char *comment); static void CommentTrigger(char *trigger, char *relation, char *comments); -static void CreateComments(Oid oid, char *comment); + /*------------------------------------------------------------------ * CommentObject -- @@ -64,7 +65,7 @@ static void CreateComments(Oid oid, char *comment); * to this routine. If the routine cannot determine an Oid to * associated with the parameters handed to this routine, an * error is thrown. Otherwise the comment is added to pg_description - * by calling the CreateComments() routine. If the comments were + * by calling the CreateComments() routine. If the comment string is * empty, CreateComments() will drop any comments associated with * the object. *------------------------------------------------------------------ @@ -74,135 +75,158 @@ void CommentObject(int objtype, char *objname, char *objproperty, List *objlist, char *comment) { - switch (objtype) { - case (INDEX): - case (SEQUENCE): - case (TABLE): - case (VIEW): + case INDEX: + case SEQUENCE: + case TABLE: + case VIEW: CommentRelation(objtype, objname, comment); break; - case (COLUMN): + case COLUMN: CommentAttribute(objname, objproperty, comment); break; - case (DATABASE): + case DATABASE: CommentDatabase(objname, comment); break; - case (RULE): + case RULE: CommentRewrite(objname, comment); break; - case (TYPE_P): + case TYPE_P: CommentType(objname, comment); break; - case (AGGREGATE): + case AGGREGATE: CommentAggregate(objname, objlist, comment); break; - case (FUNCTION): + case FUNCTION: CommentProc(objname, objlist, comment); break; - case (OPERATOR): + case OPERATOR: CommentOperator(objname, objlist, comment); break; - case (TRIGGER): + case TRIGGER: CommentTrigger(objname, objproperty, comment); break; default: - elog(ERROR, "An attempt was made to comment on a unknown type: %i", + elog(ERROR, "An attempt was made to comment on a unknown type: %d", objtype); } - - } /*------------------------------------------------------------------ * CreateComments -- * - * This routine is handed the oid and the command associated - * with that id and will insert, update, or delete (if the - * comment is an empty string or a NULL pointer) the associated - * comment from the system cataloge, pg_description. + * Create a comment for the specified object descriptor. Inserts a new + * pg_description tuple, or replaces an existing one with the same key. * + * If the comment given is null or an empty string, instead delete any + * existing comment for the specified key. *------------------------------------------------------------------ */ -static void -CreateComments(Oid oid, char *comment) +void +CreateComments(Oid oid, Oid classoid, int32 subid, char *comment) { - Relation description; - TupleDesc tupDesc; - HeapScanDesc scan; - ScanKeyData entry; - HeapTuple desctuple = NULL, - searchtuple; + Relation descriptionindex; + ScanKeyData skey[3]; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + HeapTupleData oldtuple; + Buffer buffer; + HeapTuple newtuple = NULL; Datum values[Natts_pg_description]; char nulls[Natts_pg_description]; char replaces[Natts_pg_description]; - bool modified = false; int i; - /*** Open pg_description, form a new tuple, if necessary ***/ + /* Reduce empty-string to NULL case */ + if (comment != NULL && strlen(comment) == 0) + comment = NULL; - description = heap_openr(DescriptionRelationName, RowExclusiveLock); - tupDesc = description->rd_att; - if ((comment != NULL) && (strlen(comment) > 0)) + /* Prepare to form or update a tuple, if necessary */ + if (comment != NULL) { for (i = 0; i < Natts_pg_description; i++) { nulls[i] = ' '; replaces[i] = 'r'; - values[i] = (Datum) NULL; } i = 0; values[i++] = ObjectIdGetDatum(oid); + values[i++] = ObjectIdGetDatum(classoid); + values[i++] = Int32GetDatum(subid); values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment)); } - /*** Now, open pg_description and attempt to find the old tuple ***/ + /* Open pg_description and its index */ - ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ, + description = heap_openr(DescriptionRelationName, RowExclusiveLock); + descriptionindex = index_openr(DescriptionObjIndex); + + /* Use the index to search for a matching old tuple */ + + ScanKeyEntryInitialize(&skey[0], + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) F_OIDEQ, ObjectIdGetDatum(oid)); - scan = heap_beginscan(description, false, SnapshotNow, 1, &entry); - searchtuple = heap_getnext(scan, 0); - /*** If a previous tuple exists, either delete or prep replacement ***/ + ScanKeyEntryInitialize(&skey[1], + (bits16) 0x0, + (AttrNumber) 2, + (RegProcedure) F_OIDEQ, + ObjectIdGetDatum(classoid)); + + ScanKeyEntryInitialize(&skey[2], + (bits16) 0x0, + (AttrNumber) 3, + (RegProcedure) F_INT4EQ, + Int32GetDatum(subid)); + + sd = index_beginscan(descriptionindex, false, 3, skey); - if (HeapTupleIsValid(searchtuple)) + oldtuple.t_datamcxt = CurrentMemoryContext; + oldtuple.t_data = NULL; + + while ((indexRes = index_getnext(sd, ForwardScanDirection))) { + oldtuple.t_self = indexRes->heap_iptr; + heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd); + pfree(indexRes); + + if (oldtuple.t_data == NULL) + continue; /* time qual failed */ - /*** If the comment is blank, delete old entry, else update it ***/ + /* Found the old tuple, so delete or update it */ - if ((comment == NULL) || (strlen(comment) == 0)) - simple_heap_delete(description, &searchtuple->t_self); + if (comment == NULL) + simple_heap_delete(description, &oldtuple.t_self); else { - desctuple = heap_modifytuple(searchtuple, description, values, - nulls, replaces); - simple_heap_update(description, &searchtuple->t_self, desctuple); - modified = TRUE; + newtuple = heap_modifytuple(&oldtuple, description, values, + nulls, replaces); + simple_heap_update(description, &oldtuple.t_self, newtuple); } + ReleaseBuffer(buffer); + break; /* Assume there can be only one match */ } - else - { - /*** Only if comment is non-blank do we form a new tuple ***/ + index_endscan(sd); - if ((comment != NULL) && (strlen(comment) > 0)) - { - desctuple = heap_formtuple(tupDesc, values, nulls); - heap_insert(description, desctuple); - modified = TRUE; - } + /* If we didn't find an old tuple, insert a new one */ + if (oldtuple.t_data == NULL && comment != NULL) + { + newtuple = heap_formtuple(RelationGetDescr(description), + values, nulls); + heap_insert(description, newtuple); } - /*** Complete the scan, update indices, if necessary ***/ + /* Update indexes, if necessary */ - heap_endscan(scan); - - if (modified) + if (newtuple != NULL) { if (RelationGetForm(description)->relhasindex) { @@ -211,57 +235,78 @@ CreateComments(Oid oid, char *comment) CatalogOpenIndices(Num_pg_description_indices, Name_pg_description_indices, idescs); CatalogIndexInsert(idescs, Num_pg_description_indices, description, - desctuple); + newtuple); CatalogCloseIndices(Num_pg_description_indices, idescs); } - heap_freetuple(desctuple); - + heap_freetuple(newtuple); } - heap_close(description, RowExclusiveLock); + /* Done */ + index_close(descriptionindex); + heap_close(description, NoLock); } /*------------------------------------------------------------------ * DeleteComments -- * - * This routine is used to purge any comments - * associated with the Oid handed to this routine, - * regardless of the actual object type. It is - * called, for example, when a relation is destroyed. + * This routine is used to purge all comments associated with an object, + * regardless of their objsubid. It is called, for example, when a relation + * is destroyed. *------------------------------------------------------------------ */ void -DeleteComments(Oid oid) +DeleteComments(Oid oid, Oid classoid) { - Relation description; - TupleDesc tupDesc; - ScanKeyData entry; - HeapScanDesc scan; - HeapTuple searchtuple; + Relation descriptionindex; + ScanKeyData skey[2]; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + HeapTupleData oldtuple; + Buffer buffer; + + /* Open pg_description and its index */ description = heap_openr(DescriptionRelationName, RowExclusiveLock); - tupDesc = description->rd_att; + descriptionindex = index_openr(DescriptionObjIndex); - /*** Now, open pg_description and attempt to find the old tuple ***/ + /* Use the index to search for all matching old tuples */ - ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ, + ScanKeyEntryInitialize(&skey[0], + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) F_OIDEQ, ObjectIdGetDatum(oid)); - scan = heap_beginscan(description, false, SnapshotNow, 1, &entry); - searchtuple = heap_getnext(scan, 0); - /*** If a previous tuple exists, delete it ***/ + ScanKeyEntryInitialize(&skey[1], + (bits16) 0x0, + (AttrNumber) 2, + (RegProcedure) F_OIDEQ, + ObjectIdGetDatum(classoid)); + + sd = index_beginscan(descriptionindex, false, 2, skey); - if (HeapTupleIsValid(searchtuple)) - simple_heap_delete(description, &searchtuple->t_self); + while ((indexRes = index_getnext(sd, ForwardScanDirection))) + { + oldtuple.t_self = indexRes->heap_iptr; + heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd); + pfree(indexRes); - /*** Complete the scan, update indices, if necessary ***/ + if (oldtuple.t_data == NULL) + continue; /* time qual failed */ - heap_endscan(scan); - heap_close(description, RowExclusiveLock); + simple_heap_delete(description, &oldtuple.t_self); + + ReleaseBuffer(buffer); + } + + /* Done */ + index_endscan(sd); + index_close(descriptionindex); + heap_close(description, NoLock); } /*------------------------------------------------------------------ @@ -273,59 +318,65 @@ DeleteComments(Oid oid) * the appropriate tuple, and inserting a comment using that * tuple's oid. Its parameters are the relation name and comments. *------------------------------------------------------------------ -*/ + */ static void CommentRelation(int reltype, char *relname, char *comment) { - HeapTuple reltuple; - Oid oid; - char relkind; + Relation relation; - /*** First, check object security ***/ + /* First, check object security */ if (!pg_ownercheck(GetUserId(), relname, RELNAME)) elog(ERROR, "you are not permitted to comment on class '%s'", relname); - /*** Now, attempt to find the oid in the cached version of pg_class ***/ - - reltuple = SearchSysCache(RELNAME, - PointerGetDatum(relname), - 0, 0, 0); - if (!HeapTupleIsValid(reltuple)) - elog(ERROR, "relation '%s' does not exist", relname); - - oid = reltuple->t_data->t_oid; - - relkind = ((Form_pg_class) GETSTRUCT(reltuple))->relkind; - - ReleaseSysCache(reltuple); + /* + * Open the relation. We do this mainly to acquire a lock that ensures + * no one else drops the relation before we commit. (If they did, they'd + * fail to remove the entry we are about to make in pg_description.) + * + * heap_openr will complain if it's an index, so we must do this: + */ + if (reltype != INDEX) + relation = heap_openr(relname, AccessShareLock); + else + { + relation = index_openr(relname); + LockRelation(relation, AccessShareLock); + } - /*** Next, verify that the relation type matches the intent ***/ + /* Next, verify that the relation type matches the intent */ switch (reltype) { - case (INDEX): - if (relkind != RELKIND_INDEX) + case INDEX: + if (relation->rd_rel->relkind != RELKIND_INDEX) elog(ERROR, "relation '%s' is not an index", relname); break; - case (TABLE): - if (relkind != RELKIND_RELATION) + case TABLE: + if (relation->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "relation '%s' is not a table", relname); break; - case (VIEW): - if (relkind != RELKIND_VIEW) + case VIEW: + if (relation->rd_rel->relkind != RELKIND_VIEW) elog(ERROR, "relation '%s' is not a view", relname); break; - case (SEQUENCE): - if (relkind != RELKIND_SEQUENCE) + case SEQUENCE: + if (relation->rd_rel->relkind != RELKIND_SEQUENCE) elog(ERROR, "relation '%s' is not a sequence", relname); break; } - /*** Create the comments using the tuple's oid ***/ + /* Create the comment using the relation's oid */ + + CreateComments(RelationGetRelid(relation), RelOid_pg_class, 0, comment); - CreateComments(oid, comment); + /* Done, but hold lock until commit */ + + if (reltype != INDEX) + heap_close(relation, NoLock); + else + index_close(relation); } /*------------------------------------------------------------------ @@ -333,7 +384,7 @@ CommentRelation(int reltype, char *relname, char *comment) * * This routine is used to add/drop a comment from an attribute * such as a table's column. The routine will check security - * restrictions and then attempt to fetch the oid of the associated + * restrictions and then attempt to look up the specified * attribute. If successful, a comment is added/dropped, else an * elog() exception is thrown. The parameters are the relation * and attribute names, and the comments @@ -344,32 +395,30 @@ static void CommentAttribute(char *relname, char *attrname, char *comment) { Relation relation; - Oid oid; + AttrNumber attnum; - /*** First, check object security ***/ + /* First, check object security */ if (!pg_ownercheck(GetUserId(), relname, RELNAME)) - elog(ERROR, "you are not permitted to comment on class '%s\'", relname); + elog(ERROR, "you are not permitted to comment on class '%s'", relname); /* Open the containing relation to ensure it won't go away meanwhile */ relation = heap_openr(relname, AccessShareLock); - /*** Now, fetch the attribute oid from the system cache ***/ + /* Now, fetch the attribute number from the system cache */ - oid = GetSysCacheOid(ATTNAME, - ObjectIdGetDatum(relation->rd_id), - PointerGetDatum(attrname), - 0, 0); - if (!OidIsValid(oid)) + attnum = get_attnum(RelationGetRelid(relation), attrname); + if (attnum == InvalidAttrNumber) elog(ERROR, "'%s' is not an attribute of class '%s'", attrname, relname); - /*** Call CreateComments() to create/drop the comments ***/ + /* Create the comment using the relation's oid */ - CreateComments(oid, comment); + CreateComments(RelationGetRelid(relation), RelOid_pg_class, + (int32) attnum, comment); - /*** Now, close the heap relation and return ***/ + /* Done, but hold lock until commit */ heap_close(relation, NoLock); } @@ -394,7 +443,7 @@ CommentDatabase(char *database, char *comment) HeapTuple dbtuple; Oid oid; - /*** First find the tuple in pg_database for the database ***/ + /* First find the tuple in pg_database for the database */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname, @@ -402,23 +451,23 @@ CommentDatabase(char *database, char *comment) scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry); dbtuple = heap_getnext(scan, 0); - /*** Validate database exists, and fetch the db oid ***/ + /* Validate database exists, and fetch the db oid */ if (!HeapTupleIsValid(dbtuple)) elog(ERROR, "database '%s' does not exist", database); oid = dbtuple->t_data->t_oid; - /*** Allow if the user matches the database dba or is a superuser ***/ + /* Allow if the user matches the database dba or is a superuser */ if (!(superuser() || is_dbadmin(oid))) elog(ERROR, "you are not permitted to comment on database '%s'", database); - /*** Create the comments with the pg_database oid ***/ + /* Create the comments with the pg_database oid */ - CreateComments(oid, comment); + CreateComments(oid, RelOid_pg_database, 0, comment); - /*** Complete the scan and close any opened relations ***/ + /* Complete the scan and close any opened relations */ heap_endscan(scan); heap_close(pg_database, AccessShareLock); @@ -438,22 +487,19 @@ static void CommentRewrite(char *rule, char *comment) { Oid oid; + Oid classoid; char *relation; int aclcheck; - /*** First, validate user ***/ + /* First, validate user */ -#ifndef NO_SECURITY relation = RewriteGetRuleEventRel(rule); aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE); if (aclcheck != ACLCHECK_OK) - { elog(ERROR, "you are not permitted to comment on rule '%s'", rule); - } -#endif - /*** Next, find the rule's oid ***/ + /* Next, find the rule's oid */ oid = GetSysCacheOid(RULENAME, PointerGetDatum(rule), @@ -461,9 +507,16 @@ CommentRewrite(char *rule, char *comment) if (!OidIsValid(oid)) elog(ERROR, "rule '%s' does not exist", rule); - /*** Call CreateComments() to create/drop the comments ***/ + /* pg_rewrite doesn't have a hard-coded OID, so must look it up */ + + classoid = GetSysCacheOid(RELNAME, + PointerGetDatum(RewriteRelationName), + 0, 0, 0); + Assert(OidIsValid(classoid)); - CreateComments(oid, comment); + /* Call CreateComments() to create/drop the comments */ + + CreateComments(oid, classoid, 0, comment); } /*------------------------------------------------------------------ @@ -482,13 +535,13 @@ CommentType(char *type, char *comment) { Oid oid; - /*** First, validate user ***/ + /* First, validate user */ if (!pg_ownercheck(GetUserId(), type, TYPENAME)) elog(ERROR, "you are not permitted to comment on type '%s'", type); - /*** Next, find the type's oid ***/ + /* Next, find the type's oid */ oid = GetSysCacheOid(TYPENAME, PointerGetDatum(type), @@ -496,9 +549,9 @@ CommentType(char *type, char *comment) if (!OidIsValid(oid)) elog(ERROR, "type '%s' does not exist", type); - /*** Call CreateComments() to create/drop the comments ***/ + /* Call CreateComments() to create/drop the comments */ - CreateComments(oid, comment); + CreateComments(oid, RelOid_pg_type, 0, comment); } /*------------------------------------------------------------------ @@ -518,9 +571,10 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) char *aggtypename = NULL; Oid baseoid, oid; + Oid classoid; bool defined; - /*** First, attempt to determine the base aggregate oid ***/ + /* First, attempt to determine the base aggregate oid */ if (aggtype) { @@ -530,21 +584,21 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) elog(ERROR, "type '%s' does not exist", aggtypename); } else - baseoid = 0; + baseoid = InvalidOid; - /*** Next, validate the user's attempt to comment ***/ + /* Next, validate the user's attempt to comment */ if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid)) { if (aggtypename) - elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'", - aggregate, "with type", aggtypename); + elog(ERROR, "you are not permitted to comment on aggregate '%s' with type '%s'", + aggregate, aggtypename); else elog(ERROR, "you are not permitted to comment on aggregate '%s'", aggregate); } - /*** Now, attempt to find the actual tuple in pg_aggregate ***/ + /* Now, attempt to find the actual tuple in pg_aggregate */ oid = GetSysCacheOid(AGGNAME, PointerGetDatum(aggregate), @@ -553,17 +607,22 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) if (!OidIsValid(oid)) { if (aggtypename) - { elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'", aggtypename, aggregate); - } else elog(ERROR, "aggregate '%s' does not exist", aggregate); } - /*** Call CreateComments() to create/drop the comments ***/ + /* pg_aggregate doesn't have a hard-coded OID, so must look it up */ + + classoid = GetSysCacheOid(RELNAME, + PointerGetDatum(AggregateRelationName), + 0, 0, 0); + Assert(OidIsValid(classoid)); - CreateComments(oid, comment); + /* Call CreateComments() to create/drop the comments */ + + CreateComments(oid, classoid, 0, comment); } /*------------------------------------------------------------------ @@ -585,7 +644,7 @@ CommentProc(char *function, List *arguments, char *comment) int i, argcount; - /*** First, initialize function's argument list with their type oids ***/ + /* First, initialize function's argument list with their type oids */ MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid)); argcount = length(arguments); @@ -611,13 +670,13 @@ CommentProc(char *function, List *arguments, char *comment) } } - /*** Now, validate the user's ability to comment on this function ***/ + /* Now, validate the user's ability to comment on this function */ if (!pg_func_ownercheck(GetUserId(), function, argcount, argoids)) elog(ERROR, "you are not permitted to comment on function '%s'", function); - /*** Now, find the corresponding oid for this procedure ***/ + /* Now, find the corresponding oid for this procedure */ oid = GetSysCacheOid(PROCNAME, PointerGetDatum(function), @@ -627,9 +686,9 @@ CommentProc(char *function, List *arguments, char *comment) if (!OidIsValid(oid)) func_error("CommentProc", function, argcount, argoids, NULL); - /*** Call CreateComments() to create/drop the comments ***/ + /* Call CreateComments() to create/drop the comments */ - CreateComments(oid, comment); + CreateComments(oid, RelOid_pg_proc, 0, comment); } /*------------------------------------------------------------------ @@ -642,6 +701,10 @@ CommentProc(char *function, List *arguments, char *comment) * expected to be a couple of parse nodes pointed to be a List * object. If the comments string is empty, the associated comment * is dropped. + * + * NOTE: we actually attach the comment to the procedure that underlies + * the operator. This is a feature, not a bug: we want the same comment + * to be visible for both operator and function. *------------------------------------------------------------------ */ @@ -660,14 +723,14 @@ CommentOperator(char *opername, List *arguments, char *comment) rightoid = InvalidOid; bool defined; - /*** Initialize our left and right argument types ***/ + /* Initialize our left and right argument types */ if (typenode1 != NULL) lefttype = TypeNameToInternalName(typenode1); if (typenode2 != NULL) righttype = TypeNameToInternalName(typenode2); - /*** Attempt to fetch the left oid, if specified ***/ + /* Attempt to fetch the left oid, if specified */ if (lefttype != NULL) { @@ -676,7 +739,7 @@ CommentOperator(char *opername, List *arguments, char *comment) elog(ERROR, "left type '%s' does not exist", lefttype); } - /*** Attempt to fetch the right oid, if specified ***/ + /* Attempt to fetch the right oid, if specified */ if (righttype != NULL) { @@ -685,7 +748,7 @@ CommentOperator(char *opername, List *arguments, char *comment) elog(ERROR, "right type '%s' does not exist", righttype); } - /*** Determine operator type ***/ + /* Determine operator type */ if (OidIsValid(leftoid) && (OidIsValid(rightoid))) oprtype = 'b'; @@ -696,7 +759,7 @@ CommentOperator(char *opername, List *arguments, char *comment) else elog(ERROR, "operator '%s' is of an illegal type'", opername); - /*** Attempt to fetch the operator oid ***/ + /* Attempt to fetch the operator oid */ optuple = SearchSysCache(OPERNAME, PointerGetDatum(opername), @@ -708,13 +771,13 @@ CommentOperator(char *opername, List *arguments, char *comment) oid = optuple->t_data->t_oid; - /*** Valid user's ability to comment on this operator ***/ + /* Valid user's ability to comment on this operator */ if (!pg_oper_ownercheck(GetUserId(), oid)) elog(ERROR, "you are not permitted to comment on operator '%s'", opername); - /*** Get the procedure associated with the operator ***/ + /* Get the procedure associated with the operator */ data = (Form_pg_operator) GETSTRUCT(optuple); oid = data->oprcode; @@ -723,9 +786,9 @@ CommentOperator(char *opername, List *arguments, char *comment) ReleaseSysCache(optuple); - /*** Call CreateComments() to create/drop the comments ***/ + /* Call CreateComments() to create/drop the comments */ - CreateComments(oid, comment); + CreateComments(oid, RelOid_pg_proc, 0, comment); } /*------------------------------------------------------------------ @@ -742,55 +805,48 @@ CommentOperator(char *opername, List *arguments, char *comment) static void CommentTrigger(char *trigger, char *relname, char *comment) { - - Form_pg_trigger data; Relation pg_trigger, relation; HeapTuple triggertuple; HeapScanDesc scan; - ScanKeyData entry; - Oid oid = InvalidOid; + ScanKeyData entry[2]; + Oid oid; - /*** First, validate the user's action ***/ + /* First, validate the user's action */ if (!pg_ownercheck(GetUserId(), relname, RELNAME)) elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'", trigger, "defined for relation", relname); - /*** Now, fetch the trigger oid from pg_trigger ***/ + /* Now, fetch the trigger oid from pg_trigger */ relation = heap_openr(relname, AccessShareLock); pg_trigger = heap_openr(TriggerRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry, 0, Anum_pg_trigger_tgrelid, - F_OIDEQ, RelationGetRelid(relation)); - scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 1, &entry); + ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid, + F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); + ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname, + F_NAMEEQ, + NameGetDatum(trigger)); + scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 2, entry); triggertuple = heap_getnext(scan, 0); - while (HeapTupleIsValid(triggertuple)) - { - data = (Form_pg_trigger) GETSTRUCT(triggertuple); - if (namestrcmp(&(data->tgname), trigger) == 0) - { - oid = triggertuple->t_data->t_oid; - break; - } - triggertuple = heap_getnext(scan, 0); - } - /*** If no trigger exists for the relation specified, notify user ***/ + /* If no trigger exists for the relation specified, notify user */ - if (oid == InvalidOid) - { + if (!HeapTupleIsValid(triggertuple)) elog(ERROR, "trigger '%s' defined for relation '%s' does not exist", trigger, relname); - } - /*** Create the comments with the pg_trigger oid ***/ + oid = triggertuple->t_data->t_oid; - CreateComments(oid, comment); + heap_endscan(scan); - /*** Complete the scan and close any opened relations ***/ + /* Create the comments with the pg_trigger oid */ + + CreateComments(oid, RelationGetRelid(pg_trigger), 0, comment); + + /* Done, but hold lock on relation */ - heap_endscan(scan); heap_close(pg_trigger, AccessShareLock); heap_close(relation, NoLock); } diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index e1b85a46ff0..ce7ea9fd6d3 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.140 2001/07/11 21:53:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.141 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -235,43 +235,45 @@ CopyDonePeek(FILE *fp, int c, int pickup) /* * DoCopy executes the SQL COPY statement. + * + * Either unload or reload contents of table <relname>, depending on <from>. + * (<from> = TRUE means we are inserting into the table.) + * + * If <pipe> is false, transfer is between the table and the file named + * <filename>. Otherwise, transfer is between the table and our regular + * input/output stream. The latter could be either stdin/stdout or a + * socket, depending on whether we're running under Postmaster control. + * + * Iff <binary>, unload or reload in the binary format, as opposed to the + * more wasteful but more robust and portable text format. + * + * Iff <oids>, unload or reload the format that includes OID information. + * On input, we accept OIDs whether or not the table has an OID column, + * but silently drop them if it does not. On output, we report an error + * if the user asks for OIDs in a table that has none (not providing an + * OID column might seem friendlier, but could seriously confuse programs). + * + * If in the text format, delimit columns with delimiter <delim> and print + * NULL values as <null_print>. + * + * When loading in the text format from an input stream (as opposed to + * a file), recognize a "." on a line by itself as EOF. Also recognize + * a stream EOF. When unloading in the text format to an output stream, + * write a "." on a line by itself at the end of the data. + * + * Do not allow a Postgres user without superuser privilege to read from + * or write to a file. + * + * Do not allow the copy if user doesn't have proper permission to access + * the table. */ - void DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, char *filename, char *delim, char *null_print) { -/*---------------------------------------------------------------------------- - Either unload or reload contents of class <relname>, depending on <from>. - - If <pipe> is false, transfer is between the class and the file named - <filename>. Otherwise, transfer is between the class and our regular - input/output stream. The latter could be either stdin/stdout or a - socket, depending on whether we're running under Postmaster control. - - Iff <binary>, unload or reload in the binary format, as opposed to the - more wasteful but more robust and portable text format. - - If in the text format, delimit columns with delimiter <delim> and print - NULL values as <null_print>. - - When loading in the text format from an input stream (as opposed to - a file), recognize a "." on a line by itself as EOF. Also recognize - a stream EOF. When unloading in the text format to an output stream, - write a "." on a line by itself at the end of the data. - - Iff <oids>, unload or reload the format that includes OID information. - - Do not allow a Postgres user without superuser privilege to read from - or write to a file. - - Do not allow the copy if user doesn't have proper permission to access - the class. -----------------------------------------------------------------------------*/ - FILE *fp; Relation rel; - const AclMode required_access = from ? ACL_INSERT : ACL_SELECT; + const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT); int result; /* @@ -305,10 +307,15 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, if (from) { /* copy from file to database */ - if (rel->rd_rel->relkind == RELKIND_SEQUENCE) - elog(ERROR, "You cannot change sequence relation %s", relname); - if (rel->rd_rel->relkind == RELKIND_VIEW) - elog(ERROR, "You cannot copy view %s", relname); + if (rel->rd_rel->relkind != RELKIND_RELATION) + { + if (rel->rd_rel->relkind == RELKIND_VIEW) + elog(ERROR, "You cannot copy view %s", relname); + else if (rel->rd_rel->relkind == RELKIND_SEQUENCE) + elog(ERROR, "You cannot change sequence relation %s", relname); + else + elog(ERROR, "You cannot copy object %s", relname); + } if (pipe) { if (IsUnderPostmaster) @@ -332,8 +339,15 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, } else { /* copy from database to file */ - if (rel->rd_rel->relkind == RELKIND_VIEW) - elog(ERROR, "You cannot copy view %s", relname); + if (rel->rd_rel->relkind != RELKIND_RELATION) + { + if (rel->rd_rel->relkind == RELKIND_VIEW) + elog(ERROR, "You cannot copy view %s", relname); + else if (rel->rd_rel->relkind == RELKIND_SEQUENCE) + elog(ERROR, "You cannot copy sequence %s", relname); + else + elog(ERROR, "You cannot copy object %s", relname); + } if (pipe) { if (IsUnderPostmaster) @@ -410,6 +424,10 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, int16 fld_size; char *string; + if (oids && !rel->rd_rel->relhasoids) + elog(ERROR, "COPY: table %s does not have OIDs", + RelationGetRelationName(rel)); + tupDesc = rel->rd_att; attr_count = rel->rd_att->natts; attr = rel->rd_att->attrs; @@ -706,6 +724,10 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, elements = NULL; } + /* Silently drop incoming OIDs if table does not have OIDs */ + if (!rel->rd_rel->relhasoids) + oids = false; + values = (Datum *) palloc(attr_count * sizeof(Datum)); nulls = (char *) palloc(attr_count * sizeof(char)); diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index 780ec31f232..19bedb12b79 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.78 2001/06/22 21:37:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.79 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,7 @@ */ static List *MergeAttributes(List *schema, List *supers, bool istemp, - List **supOids, List **supconstr); + List **supOids, List **supconstr, bool *supHasOids); 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); @@ -57,6 +57,7 @@ DefineRelation(CreateStmt *stmt, char relkind) TupleDesc descriptor; List *inheritOids; List *old_constraints; + bool parentHasOids; List *rawDefaults; List *listptr; int i; @@ -73,7 +74,7 @@ DefineRelation(CreateStmt *stmt, char relkind) * including inherited attributes. */ schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp, - &inheritOids, &old_constraints); + &inheritOids, &old_constraints, &parentHasOids); numberOfAttributes = length(schema); if (numberOfAttributes <= 0) @@ -135,7 +136,9 @@ DefineRelation(CreateStmt *stmt, char relkind) } relationId = heap_create_with_catalog(relname, descriptor, - relkind, stmt->istemp, + relkind, + stmt->hasoids || parentHasOids, + stmt->istemp, allowSystemTableMods); StoreCatalogInheritance(relationId, inheritOids); @@ -248,6 +251,7 @@ TruncateRelation(char *name) * 'supOids' receives an integer 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. * * Return value: * Completed schema list. @@ -293,12 +297,13 @@ TruncateRelation(char *name) */ static List * MergeAttributes(List *schema, List *supers, bool istemp, - List **supOids, List **supconstr) + List **supOids, List **supconstr, bool *supHasOids) { List *entry; List *inhSchema = NIL; List *parentOids = NIL; List *constraints = NIL; + bool parentHasOids = false; bool have_bogus_defaults = false; char *bogus_marker = "Bogus!"; /* marks conflicting defaults */ int child_attno; @@ -341,7 +346,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, /* * Scan the parents left-to-right, and merge their attributes to form - * a list of inherited attributes (inhSchema). + * a list of inherited attributes (inhSchema). Also check to see if + * we need to inherit an OID column. */ child_attno = 0; foreach(entry, supers) @@ -371,6 +377,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, parentOids = lappendi(parentOids, relation->rd_id); setRelhassubclassInRelation(relation->rd_id, true); + parentHasOids |= relation->rd_rel->relhasoids; + tupleDesc = RelationGetDescr(relation); constr = tupleDesc->constr; @@ -598,6 +606,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, *supOids = parentOids; *supconstr = constraints; + *supHasOids = parentHasOids; return schema; } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 16b1241a027..b20525e77d9 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.77 2001/08/04 00:14:43 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.78 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -354,15 +354,15 @@ dropdb(const char *dbname) heap_endscan(pgdbscan); + /* Delete any comments associated with the database */ + DeleteComments(db_id, RelationGetRelid(pgdbrel)); + /* * Close pg_database, but keep exclusive lock till commit to ensure * that any new backend scanning pg_database will see the tuple dead. */ heap_close(pgdbrel, NoLock); - /* Delete any comments associated with the database */ - DeleteComments(db_id); - /* * Drop pages for this database that are in the shared buffer cache. * This is important to ensure that no remaining backend tries to diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index f5f815f1954..3b556da3ed5 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.55 2001/08/09 18:28:17 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.56 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -212,7 +212,7 @@ DefineIndex(char *heapRelationName, * backends to flush their relcache entries and in particular their * cached lists of the indexes for this relation. */ - setRelhasindex(relationId, true); + setRelhasindex(relationId, true, primary, InvalidOid); } diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index 48701a893a8..50b483f21fd 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.61 2001/06/05 19:34:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.62 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,9 +85,8 @@ RemoveOperator(char *operatorName, /* operator name */ elog(ERROR, "RemoveOperator: operator '%s': permission denied", operatorName); - /*** Delete any comments associated with this operator ***/ - - DeleteComments(tup->t_data->t_oid); + /* Delete any comments associated with this operator */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); simple_heap_delete(relation, &tup->t_self); @@ -146,11 +145,8 @@ SingleOpOperatorRemove(Oid typeOid) scan = heap_beginscan(rel, 0, SnapshotNow, 1, key); while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) { - - /*** This is apparently a routine not in use, but remove ***/ - /*** any comments anyways ***/ - - DeleteComments(tup->t_data->t_oid); + /* Delete any comments associated with this operator */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(rel)); simple_heap_delete(rel, &tup->t_self); } @@ -242,7 +238,6 @@ RemoveType(char *typeName) /* type name to be removed */ { Relation relation; HeapTuple tup; - Oid typeOid; char *shadow_type; if (!pg_ownercheck(GetUserId(), typeName, TYPENAME)) @@ -257,11 +252,8 @@ RemoveType(char *typeName) /* type name to be removed */ if (!HeapTupleIsValid(tup)) elog(ERROR, "RemoveType: type '%s' does not exist", typeName); - typeOid = tup->t_data->t_oid; - - /*** Delete any comments associated with this type ***/ - - DeleteComments(typeOid); + /* Delete any comments associated with this type */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); simple_heap_delete(relation, &tup->t_self); @@ -347,9 +339,8 @@ RemoveFunction(char *functionName, /* function name to be removed */ elog(NOTICE, "Removing built-in function \"%s\"", functionName); } - /*** Delete any comments associated with this function ***/ - - DeleteComments(tup->t_data->t_oid); + /* Delete any comments associated with this function */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); simple_heap_delete(relation, &tup->t_self); @@ -421,9 +412,8 @@ RemoveAggregate(char *aggName, char *aggType) } } - /*** Remove any comments related to this aggregate ***/ - - DeleteComments(tup->t_data->t_oid); + /* Remove any comments related to this aggregate */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); simple_heap_delete(relation, &tup->t_self); diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 1da20e1c098..3bd3971003d 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.61 2001/06/29 21:08:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.62 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -161,9 +161,10 @@ DefineSequence(CreateSeqStmt *seq) } stmt->relname = seq->seqname; - stmt->istemp = seq->istemp; stmt->inhRelnames = NIL; stmt->constraints = NIL; + stmt->istemp = seq->istemp; + stmt->hasoids = false; DefineRelation(stmt, RELKIND_SEQUENCE); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 833d7876974..1cdbe791227 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.94 2001/08/02 15:59:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.95 2001/08/10 18:57:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -336,10 +336,8 @@ DropTrigger(DropTrigStmt *stmt) if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0) { - - /*** Delete any comments associated with this trigger ***/ - - DeleteComments(tuple->t_data->t_oid); + /* Delete any comments associated with this trigger */ + DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel)); simple_heap_delete(tgrel, &tuple->t_self); tgfound++; @@ -407,10 +405,8 @@ RelationRemoveTriggers(Relation rel) while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0))) { - - /*** Delete any comments associated with this trigger ***/ - - DeleteComments(tup->t_data->t_oid); + /* Delete any comments associated with this trigger */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(tgrel)); simple_heap_delete(tgrel, &tup->t_self); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 8e141133a42..9a9d90fa2cf 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.206 2001/07/18 00:46:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.207 2001/08/10 18:57:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -434,6 +434,12 @@ vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples, pgcform->relpages = (int32) num_pages; pgcform->reltuples = num_tuples; pgcform->relhasindex = hasindex; + /* + * If we have discovered that there are no indexes, then there's + * no primary key either. This could be done more thoroughly... + */ + if (!hasindex) + pgcform->relhaspkey = false; /* invalidate the tuple in the cache and write the buffer */ RelationInvalidateHeapTuple(rd, &rtup); @@ -904,7 +910,8 @@ scan_heap(VRelStats *vacrelstats, Relation onerel, /* * Other checks... */ - if (!OidIsValid(tuple.t_data->t_oid)) + if (!OidIsValid(tuple.t_data->t_oid) && + onerel->rd_rel->relhasoids) elog(NOTICE, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.", relname, blkno, offnum, (int) tupgone); diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index f509086b52f..bdde6114133 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -31,7 +31,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.3 2001/07/18 00:46:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.4 2001/08/10 18:57:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -339,7 +339,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* * Other checks... */ - if (!OidIsValid(tuple.t_data->t_oid)) + if (!OidIsValid(tuple.t_data->t_oid) && + onerel->rd_rel->relhasoids) elog(NOTICE, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.", relname, blkno, offnum, (int) tupgone); diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 320f2c08e92..a8cddde2dd6 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: view.c,v 1.54 2001/03/22 03:59:25 momjian Exp $ + * $Id: view.c,v 1.55 2001/08/10 18:57:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -88,10 +88,11 @@ DefineVirtualRelation(char *relname, List *tlist) * nil... */ createStmt->relname = relname; - createStmt->istemp = false; createStmt->tableElts = attrList; createStmt->inhRelnames = NIL; createStmt->constraints = NIL; + createStmt->istemp = false; + createStmt->hasoids = false; /* * finally create the relation... |