Header And Logo

PostgreSQL
| The world's most advanced open source database.

pg_largeobject.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pg_largeobject.c
00004  *    routines to support manipulation of the pg_largeobject relation
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/catalog/pg_largeobject.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/genam.h"
00018 #include "access/heapam.h"
00019 #include "access/htup_details.h"
00020 #include "access/sysattr.h"
00021 #include "catalog/dependency.h"
00022 #include "catalog/indexing.h"
00023 #include "catalog/pg_largeobject.h"
00024 #include "catalog/pg_largeobject_metadata.h"
00025 #include "miscadmin.h"
00026 #include "utils/acl.h"
00027 #include "utils/fmgroids.h"
00028 #include "utils/rel.h"
00029 #include "utils/tqual.h"
00030 
00031 
00032 /*
00033  * Create a large object having the given LO identifier.
00034  *
00035  * We create a new large object by inserting an entry into
00036  * pg_largeobject_metadata without any data pages, so that the object
00037  * will appear to exist with size 0.
00038  */
00039 Oid
00040 LargeObjectCreate(Oid loid)
00041 {
00042     Relation    pg_lo_meta;
00043     HeapTuple   ntup;
00044     Oid         loid_new;
00045     Datum       values[Natts_pg_largeobject_metadata];
00046     bool        nulls[Natts_pg_largeobject_metadata];
00047 
00048     pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
00049                            RowExclusiveLock);
00050 
00051     /*
00052      * Insert metadata of the largeobject
00053      */
00054     memset(values, 0, sizeof(values));
00055     memset(nulls, false, sizeof(nulls));
00056 
00057     values[Anum_pg_largeobject_metadata_lomowner - 1]
00058         = ObjectIdGetDatum(GetUserId());
00059     nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
00060 
00061     ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
00062                            values, nulls);
00063     if (OidIsValid(loid))
00064         HeapTupleSetOid(ntup, loid);
00065 
00066     loid_new = simple_heap_insert(pg_lo_meta, ntup);
00067     Assert(!OidIsValid(loid) || loid == loid_new);
00068 
00069     CatalogUpdateIndexes(pg_lo_meta, ntup);
00070 
00071     heap_freetuple(ntup);
00072 
00073     heap_close(pg_lo_meta, RowExclusiveLock);
00074 
00075     return loid_new;
00076 }
00077 
00078 /*
00079  * Drop a large object having the given LO identifier.  Both the data pages
00080  * and metadata must be dropped.
00081  */
00082 void
00083 LargeObjectDrop(Oid loid)
00084 {
00085     Relation    pg_lo_meta;
00086     Relation    pg_largeobject;
00087     ScanKeyData skey[1];
00088     SysScanDesc scan;
00089     HeapTuple   tuple;
00090 
00091     pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
00092                            RowExclusiveLock);
00093 
00094     pg_largeobject = heap_open(LargeObjectRelationId,
00095                                RowExclusiveLock);
00096 
00097     /*
00098      * Delete an entry from pg_largeobject_metadata
00099      */
00100     ScanKeyInit(&skey[0],
00101                 ObjectIdAttributeNumber,
00102                 BTEqualStrategyNumber, F_OIDEQ,
00103                 ObjectIdGetDatum(loid));
00104 
00105     scan = systable_beginscan(pg_lo_meta,
00106                               LargeObjectMetadataOidIndexId, true,
00107                               SnapshotNow, 1, skey);
00108 
00109     tuple = systable_getnext(scan);
00110     if (!HeapTupleIsValid(tuple))
00111         ereport(ERROR,
00112                 (errcode(ERRCODE_UNDEFINED_OBJECT),
00113                  errmsg("large object %u does not exist", loid)));
00114 
00115     simple_heap_delete(pg_lo_meta, &tuple->t_self);
00116 
00117     systable_endscan(scan);
00118 
00119     /*
00120      * Delete all the associated entries from pg_largeobject
00121      */
00122     ScanKeyInit(&skey[0],
00123                 Anum_pg_largeobject_loid,
00124                 BTEqualStrategyNumber, F_OIDEQ,
00125                 ObjectIdGetDatum(loid));
00126 
00127     scan = systable_beginscan(pg_largeobject,
00128                               LargeObjectLOidPNIndexId, true,
00129                               SnapshotNow, 1, skey);
00130     while (HeapTupleIsValid(tuple = systable_getnext(scan)))
00131     {
00132         simple_heap_delete(pg_largeobject, &tuple->t_self);
00133     }
00134 
00135     systable_endscan(scan);
00136 
00137     heap_close(pg_largeobject, RowExclusiveLock);
00138 
00139     heap_close(pg_lo_meta, RowExclusiveLock);
00140 }
00141 
00142 /*
00143  * LargeObjectExists
00144  *
00145  * We don't use the system cache for large object metadata, for fear of
00146  * using too much local memory.
00147  *
00148  * This function always scans the system catalog using SnapshotNow, so it
00149  * should not be used when a large object is opened in read-only mode (because
00150  * large objects opened in read only mode are supposed to be viewed relative
00151  * to the caller's snapshot, whereas in read-write mode they are relative to
00152  * SnapshotNow).
00153  */
00154 bool
00155 LargeObjectExists(Oid loid)
00156 {
00157     Relation    pg_lo_meta;
00158     ScanKeyData skey[1];
00159     SysScanDesc sd;
00160     HeapTuple   tuple;
00161     bool        retval = false;
00162 
00163     ScanKeyInit(&skey[0],
00164                 ObjectIdAttributeNumber,
00165                 BTEqualStrategyNumber, F_OIDEQ,
00166                 ObjectIdGetDatum(loid));
00167 
00168     pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
00169                            AccessShareLock);
00170 
00171     sd = systable_beginscan(pg_lo_meta,
00172                             LargeObjectMetadataOidIndexId, true,
00173                             SnapshotNow, 1, skey);
00174 
00175     tuple = systable_getnext(sd);
00176     if (HeapTupleIsValid(tuple))
00177         retval = true;
00178 
00179     systable_endscan(sd);
00180 
00181     heap_close(pg_lo_meta, AccessShareLock);
00182 
00183     return retval;
00184 }