]> granicus.if.org Git - postgresql/blob - src/backend/catalog/pg_largeobject.c
d08b94e28f443275de63cde5e0dfc7d257b0bda2
[postgresql] / src / backend / catalog / pg_largeobject.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_largeobject.c
4  *        routines to support manipulation of the pg_largeobject relation
5  *
6  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/catalog/pg_largeobject.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "access/htup_details.h"
20 #include "access/sysattr.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/pg_largeobject.h"
24 #include "catalog/pg_largeobject_metadata.h"
25 #include "miscadmin.h"
26 #include "utils/acl.h"
27 #include "utils/fmgroids.h"
28 #include "utils/rel.h"
29 #include "utils/tqual.h"
30
31
32 /*
33  * Create a large object having the given LO identifier.
34  *
35  * We create a new large object by inserting an entry into
36  * pg_largeobject_metadata without any data pages, so that the object
37  * will appear to exist with size 0.
38  */
39 Oid
40 LargeObjectCreate(Oid loid)
41 {
42         Relation        pg_lo_meta;
43         HeapTuple       ntup;
44         Oid                     loid_new;
45         Datum           values[Natts_pg_largeobject_metadata];
46         bool            nulls[Natts_pg_largeobject_metadata];
47
48         pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
49                                                    RowExclusiveLock);
50
51         /*
52          * Insert metadata of the largeobject
53          */
54         memset(values, 0, sizeof(values));
55         memset(nulls, false, sizeof(nulls));
56
57         values[Anum_pg_largeobject_metadata_lomowner - 1]
58                 = ObjectIdGetDatum(GetUserId());
59         nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
60
61         ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
62                                                    values, nulls);
63         if (OidIsValid(loid))
64                 HeapTupleSetOid(ntup, loid);
65
66         loid_new = simple_heap_insert(pg_lo_meta, ntup);
67         Assert(!OidIsValid(loid) || loid == loid_new);
68
69         CatalogUpdateIndexes(pg_lo_meta, ntup);
70
71         heap_freetuple(ntup);
72
73         heap_close(pg_lo_meta, RowExclusiveLock);
74
75         return loid_new;
76 }
77
78 /*
79  * Drop a large object having the given LO identifier.  Both the data pages
80  * and metadata must be dropped.
81  */
82 void
83 LargeObjectDrop(Oid loid)
84 {
85         Relation        pg_lo_meta;
86         Relation        pg_largeobject;
87         ScanKeyData skey[1];
88         SysScanDesc scan;
89         HeapTuple       tuple;
90
91         pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
92                                                    RowExclusiveLock);
93
94         pg_largeobject = heap_open(LargeObjectRelationId,
95                                                            RowExclusiveLock);
96
97         /*
98          * Delete an entry from pg_largeobject_metadata
99          */
100         ScanKeyInit(&skey[0],
101                                 ObjectIdAttributeNumber,
102                                 BTEqualStrategyNumber, F_OIDEQ,
103                                 ObjectIdGetDatum(loid));
104
105         scan = systable_beginscan(pg_lo_meta,
106                                                           LargeObjectMetadataOidIndexId, true,
107                                                           NULL, 1, skey);
108
109         tuple = systable_getnext(scan);
110         if (!HeapTupleIsValid(tuple))
111                 ereport(ERROR,
112                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
113                                  errmsg("large object %u does not exist", loid)));
114
115         simple_heap_delete(pg_lo_meta, &tuple->t_self);
116
117         systable_endscan(scan);
118
119         /*
120          * Delete all the associated entries from pg_largeobject
121          */
122         ScanKeyInit(&skey[0],
123                                 Anum_pg_largeobject_loid,
124                                 BTEqualStrategyNumber, F_OIDEQ,
125                                 ObjectIdGetDatum(loid));
126
127         scan = systable_beginscan(pg_largeobject,
128                                                           LargeObjectLOidPNIndexId, true,
129                                                           NULL, 1, skey);
130         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
131         {
132                 simple_heap_delete(pg_largeobject, &tuple->t_self);
133         }
134
135         systable_endscan(scan);
136
137         heap_close(pg_largeobject, RowExclusiveLock);
138
139         heap_close(pg_lo_meta, RowExclusiveLock);
140 }
141
142 /*
143  * LargeObjectExists
144  *
145  * We don't use the system cache for large object metadata, for fear of
146  * using too much local memory.
147  *
148  * This function always scans the system catalog using an up-to-date snapshot,
149  * so it should not be used when a large object is opened in read-only mode
150  * (because large objects opened in read only mode are supposed to be viewed
151  * relative to the caller's snapshot, whereas in read-write mode they are
152  * relative to a current snapshot).
153  */
154 bool
155 LargeObjectExists(Oid loid)
156 {
157         Relation        pg_lo_meta;
158         ScanKeyData skey[1];
159         SysScanDesc sd;
160         HeapTuple       tuple;
161         bool            retval = false;
162
163         ScanKeyInit(&skey[0],
164                                 ObjectIdAttributeNumber,
165                                 BTEqualStrategyNumber, F_OIDEQ,
166                                 ObjectIdGetDatum(loid));
167
168         pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
169                                                    AccessShareLock);
170
171         sd = systable_beginscan(pg_lo_meta,
172                                                         LargeObjectMetadataOidIndexId, true,
173                                                         NULL, 1, skey);
174
175         tuple = systable_getnext(sd);
176         if (HeapTupleIsValid(tuple))
177                 retval = true;
178
179         systable_endscan(sd);
180
181         heap_close(pg_lo_meta, AccessShareLock);
182
183         return retval;
184 }