X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbackend%2Fcatalog%2Fpg_largeobject.c;h=d08b94e28f443275de63cde5e0dfc7d257b0bda2;hb=ee943004466418595363d567f18c053bae407792;hp=bce3a47b93128165675d440f7554333a4bfad2fc;hpb=406a942820d260382c54e69c6cdf911af5836547;p=postgresql diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index bce3a47b93..d08b94e28f 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -3,12 +3,12 @@ * pg_largeobject.c * routines to support manipulation of the pg_largeobject relation * - * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_largeobject.c,v 1.23 2005/02/23 23:27:54 neilc Exp $ + * src/backend/catalog/pg_largeobject.c * *------------------------------------------------------------------------- */ @@ -16,124 +16,169 @@ #include "access/genam.h" #include "access/heapam.h" -#include "catalog/catname.h" +#include "access/htup_details.h" +#include "access/sysattr.h" +#include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/pg_largeobject.h" +#include "catalog/pg_largeobject_metadata.h" #include "miscadmin.h" -#include "utils/builtins.h" +#include "utils/acl.h" #include "utils/fmgroids.h" +#include "utils/rel.h" +#include "utils/tqual.h" /* * Create a large object having the given LO identifier. * - * We do this by inserting an empty first page, so that the object will - * appear to exist with size 0. Note that the unique index will reject - * an attempt to create a duplicate page. + * We create a new large object by inserting an entry into + * pg_largeobject_metadata without any data pages, so that the object + * will appear to exist with size 0. */ -void +Oid LargeObjectCreate(Oid loid) { - Relation pg_largeobject; + Relation pg_lo_meta; HeapTuple ntup; - Datum values[Natts_pg_largeobject]; - char nulls[Natts_pg_largeobject]; - int i; + Oid loid_new; + Datum values[Natts_pg_largeobject_metadata]; + bool nulls[Natts_pg_largeobject_metadata]; - pg_largeobject = heap_openr(LargeObjectRelationName, RowExclusiveLock); + pg_lo_meta = heap_open(LargeObjectMetadataRelationId, + RowExclusiveLock); /* - * Form new tuple + * Insert metadata of the largeobject */ - for (i = 0; i < Natts_pg_largeobject; i++) - { - values[i] = (Datum) NULL; - nulls[i] = ' '; - } - - i = 0; - values[i++] = ObjectIdGetDatum(loid); - values[i++] = Int32GetDatum(0); - values[i++] = DirectFunctionCall1(byteain, - CStringGetDatum("")); + memset(values, 0, sizeof(values)); + memset(nulls, false, sizeof(nulls)); - ntup = heap_formtuple(pg_largeobject->rd_att, values, nulls); + values[Anum_pg_largeobject_metadata_lomowner - 1] + = ObjectIdGetDatum(GetUserId()); + nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true; - /* - * Insert it - */ - simple_heap_insert(pg_largeobject, ntup); + ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta), + values, nulls); + if (OidIsValid(loid)) + HeapTupleSetOid(ntup, loid); - /* Update indexes */ - CatalogUpdateIndexes(pg_largeobject, ntup); + loid_new = simple_heap_insert(pg_lo_meta, ntup); + Assert(!OidIsValid(loid) || loid == loid_new); - heap_close(pg_largeobject, RowExclusiveLock); + CatalogUpdateIndexes(pg_lo_meta, ntup); heap_freetuple(ntup); + + heap_close(pg_lo_meta, RowExclusiveLock); + + return loid_new; } +/* + * Drop a large object having the given LO identifier. Both the data pages + * and metadata must be dropped. + */ void LargeObjectDrop(Oid loid) { - bool found = false; + Relation pg_lo_meta; Relation pg_largeobject; ScanKeyData skey[1]; - SysScanDesc sd; + SysScanDesc scan; HeapTuple tuple; + pg_lo_meta = heap_open(LargeObjectMetadataRelationId, + RowExclusiveLock); + + pg_largeobject = heap_open(LargeObjectRelationId, + RowExclusiveLock); + + /* + * Delete an entry from pg_largeobject_metadata + */ ScanKeyInit(&skey[0], - Anum_pg_largeobject_loid, + ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(loid)); - pg_largeobject = heap_openr(LargeObjectRelationName, RowExclusiveLock); + scan = systable_beginscan(pg_lo_meta, + LargeObjectMetadataOidIndexId, true, + NULL, 1, skey); + + tuple = systable_getnext(scan); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("large object %u does not exist", loid))); + + simple_heap_delete(pg_lo_meta, &tuple->t_self); - sd = systable_beginscan(pg_largeobject, LargeObjectLOidPNIndex, true, - SnapshotNow, 1, skey); + systable_endscan(scan); - while ((tuple = systable_getnext(sd)) != NULL) + /* + * Delete all the associated entries from pg_largeobject + */ + ScanKeyInit(&skey[0], + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(loid)); + + scan = systable_beginscan(pg_largeobject, + LargeObjectLOidPNIndexId, true, + NULL, 1, skey); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) { simple_heap_delete(pg_largeobject, &tuple->t_self); - found = true; } - systable_endscan(sd); + systable_endscan(scan); heap_close(pg_largeobject, RowExclusiveLock); - if (!found) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("large object %u does not exist", loid))); + heap_close(pg_lo_meta, RowExclusiveLock); } +/* + * LargeObjectExists + * + * We don't use the system cache for large object metadata, for fear of + * using too much local memory. + * + * This function always scans the system catalog using an up-to-date snapshot, + * so it should not be used when a large object is opened in read-only mode + * (because large objects opened in read only mode are supposed to be viewed + * relative to the caller's snapshot, whereas in read-write mode they are + * relative to a current snapshot). + */ bool LargeObjectExists(Oid loid) { - bool retval = false; - Relation pg_largeobject; + Relation pg_lo_meta; ScanKeyData skey[1]; SysScanDesc sd; + HeapTuple tuple; + bool retval = false; - /* - * See if we can find any tuples belonging to the specified LO - */ ScanKeyInit(&skey[0], - Anum_pg_largeobject_loid, + ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(loid)); - pg_largeobject = heap_openr(LargeObjectRelationName, AccessShareLock); + pg_lo_meta = heap_open(LargeObjectMetadataRelationId, + AccessShareLock); - sd = systable_beginscan(pg_largeobject, LargeObjectLOidPNIndex, true, - SnapshotNow, 1, skey); + sd = systable_beginscan(pg_lo_meta, + LargeObjectMetadataOidIndexId, true, + NULL, 1, skey); - if (systable_getnext(sd) != NULL) + tuple = systable_getnext(sd); + if (HeapTupleIsValid(tuple)) retval = true; systable_endscan(sd); - heap_close(pg_largeobject, AccessShareLock); + heap_close(pg_lo_meta, AccessShareLock); return retval; }