]> granicus.if.org Git - postgresql/blob - src/backend/catalog/pg_largeobject.c
Fix initialization of fake LSN for unlogged relations
[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-2019, 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/htup_details.h"
19 #include "access/sysattr.h"
20 #include "access/table.h"
21 #include "catalog/catalog.h"
22 #include "catalog/dependency.h"
23 #include "catalog/indexing.h"
24 #include "catalog/pg_largeobject.h"
25 #include "catalog/pg_largeobject_metadata.h"
26 #include "miscadmin.h"
27 #include "utils/acl.h"
28 #include "utils/fmgroids.h"
29 #include "utils/rel.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 = table_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         if (OidIsValid(loid))
58                 loid_new = loid;
59         else
60                 loid_new = GetNewOidWithIndex(pg_lo_meta,
61                                                                           LargeObjectMetadataOidIndexId,
62                                                                           Anum_pg_largeobject_metadata_oid);
63
64         values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
65         values[Anum_pg_largeobject_metadata_lomowner - 1]
66                 = ObjectIdGetDatum(GetUserId());
67         nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
68
69         ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
70                                                    values, nulls);
71
72         CatalogTupleInsert(pg_lo_meta, ntup);
73
74         heap_freetuple(ntup);
75
76         table_close(pg_lo_meta, RowExclusiveLock);
77
78         return loid_new;
79 }
80
81 /*
82  * Drop a large object having the given LO identifier.  Both the data pages
83  * and metadata must be dropped.
84  */
85 void
86 LargeObjectDrop(Oid loid)
87 {
88         Relation        pg_lo_meta;
89         Relation        pg_largeobject;
90         ScanKeyData skey[1];
91         SysScanDesc scan;
92         HeapTuple       tuple;
93
94         pg_lo_meta = table_open(LargeObjectMetadataRelationId,
95                                                         RowExclusiveLock);
96
97         pg_largeobject = table_open(LargeObjectRelationId,
98                                                                 RowExclusiveLock);
99
100         /*
101          * Delete an entry from pg_largeobject_metadata
102          */
103         ScanKeyInit(&skey[0],
104                                 Anum_pg_largeobject_metadata_oid,
105                                 BTEqualStrategyNumber, F_OIDEQ,
106                                 ObjectIdGetDatum(loid));
107
108         scan = systable_beginscan(pg_lo_meta,
109                                                           LargeObjectMetadataOidIndexId, true,
110                                                           NULL, 1, skey);
111
112         tuple = systable_getnext(scan);
113         if (!HeapTupleIsValid(tuple))
114                 ereport(ERROR,
115                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
116                                  errmsg("large object %u does not exist", loid)));
117
118         CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
119
120         systable_endscan(scan);
121
122         /*
123          * Delete all the associated entries from pg_largeobject
124          */
125         ScanKeyInit(&skey[0],
126                                 Anum_pg_largeobject_loid,
127                                 BTEqualStrategyNumber, F_OIDEQ,
128                                 ObjectIdGetDatum(loid));
129
130         scan = systable_beginscan(pg_largeobject,
131                                                           LargeObjectLOidPNIndexId, true,
132                                                           NULL, 1, skey);
133         while (HeapTupleIsValid(tuple = systable_getnext(scan)))
134         {
135                 CatalogTupleDelete(pg_largeobject, &tuple->t_self);
136         }
137
138         systable_endscan(scan);
139
140         table_close(pg_largeobject, RowExclusiveLock);
141
142         table_close(pg_lo_meta, RowExclusiveLock);
143 }
144
145 /*
146  * LargeObjectExists
147  *
148  * We don't use the system cache for large object metadata, for fear of
149  * using too much local memory.
150  *
151  * This function always scans the system catalog using an up-to-date snapshot,
152  * so it should not be used when a large object is opened in read-only mode
153  * (because large objects opened in read only mode are supposed to be viewed
154  * relative to the caller's snapshot, whereas in read-write mode they are
155  * relative to a current snapshot).
156  */
157 bool
158 LargeObjectExists(Oid loid)
159 {
160         Relation        pg_lo_meta;
161         ScanKeyData skey[1];
162         SysScanDesc sd;
163         HeapTuple       tuple;
164         bool            retval = false;
165
166         ScanKeyInit(&skey[0],
167                                 Anum_pg_largeobject_metadata_oid,
168                                 BTEqualStrategyNumber, F_OIDEQ,
169                                 ObjectIdGetDatum(loid));
170
171         pg_lo_meta = table_open(LargeObjectMetadataRelationId,
172                                                         AccessShareLock);
173
174         sd = systable_beginscan(pg_lo_meta,
175                                                         LargeObjectMetadataOidIndexId, true,
176                                                         NULL, 1, skey);
177
178         tuple = systable_getnext(sd);
179         if (HeapTupleIsValid(tuple))
180                 retval = true;
181
182         systable_endscan(sd);
183
184         table_close(pg_lo_meta, AccessShareLock);
185
186         return retval;
187 }