Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * pg_largeobject.c
4 : : * routines to support manipulation of the pg_largeobject relation
5 : : *
6 : : * Portions Copyright (c) 1996-2024, 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/table.h"
20 : : #include "catalog/catalog.h"
21 : : #include "catalog/indexing.h"
22 : : #include "catalog/pg_largeobject.h"
23 : : #include "catalog/pg_largeobject_metadata.h"
24 : : #include "miscadmin.h"
25 : : #include "utils/fmgroids.h"
26 : : #include "utils/rel.h"
27 : :
28 : :
29 : : /*
30 : : * Create a large object having the given LO identifier.
31 : : *
32 : : * We create a new large object by inserting an entry into
33 : : * pg_largeobject_metadata without any data pages, so that the object
34 : : * will appear to exist with size 0.
35 : : */
36 : : Oid
8573 tgl@sss.pgh.pa.us 37 :CBC 56 : LargeObjectCreate(Oid loid)
38 : : {
39 : : Relation pg_lo_meta;
40 : : HeapTuple ntup;
41 : : Oid loid_new;
42 : : Datum values[Natts_pg_largeobject_metadata];
43 : : bool nulls[Natts_pg_largeobject_metadata];
44 : :
1910 andres@anarazel.de 45 : 56 : pg_lo_meta = table_open(LargeObjectMetadataRelationId,
46 : : RowExclusiveLock);
47 : :
48 : : /*
49 : : * Insert metadata of the largeobject
50 : : */
5238 itagaki.takahiro@gma 51 : 56 : memset(values, 0, sizeof(values));
52 : 56 : memset(nulls, false, sizeof(nulls));
53 : :
1972 andres@anarazel.de 54 [ + + ]: 56 : if (OidIsValid(loid))
55 : 32 : loid_new = loid;
56 : : else
57 : 24 : loid_new = GetNewOidWithIndex(pg_lo_meta,
58 : : LargeObjectMetadataOidIndexId,
59 : : Anum_pg_largeobject_metadata_oid);
60 : :
61 : 56 : values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
62 : : values[Anum_pg_largeobject_metadata_lomowner - 1]
5238 itagaki.takahiro@gma 63 : 56 : = ObjectIdGetDatum(GetUserId());
64 : 56 : nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
65 : :
66 : 56 : ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
67 : : values, nulls);
68 : :
1972 andres@anarazel.de 69 : 56 : CatalogTupleInsert(pg_lo_meta, ntup);
70 : :
8573 tgl@sss.pgh.pa.us 71 : 56 : heap_freetuple(ntup);
72 : :
1910 andres@anarazel.de 73 : 56 : table_close(pg_lo_meta, RowExclusiveLock);
74 : :
5238 itagaki.takahiro@gma 75 : 56 : 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
8573 tgl@sss.pgh.pa.us 83 : 44 : LargeObjectDrop(Oid loid)
84 : : {
85 : : Relation pg_lo_meta;
86 : : Relation pg_largeobject;
87 : : ScanKeyData skey[1];
88 : : SysScanDesc scan;
89 : : HeapTuple tuple;
90 : :
1910 andres@anarazel.de 91 : 44 : pg_lo_meta = table_open(LargeObjectMetadataRelationId,
92 : : RowExclusiveLock);
93 : :
94 : 44 : pg_largeobject = table_open(LargeObjectRelationId,
95 : : RowExclusiveLock);
96 : :
97 : : /*
98 : : * Delete an entry from pg_largeobject_metadata
99 : : */
7459 tgl@sss.pgh.pa.us 100 : 44 : ScanKeyInit(&skey[0],
101 : : Anum_pg_largeobject_metadata_oid,
102 : : BTEqualStrategyNumber, F_OIDEQ,
103 : : ObjectIdGetDatum(loid));
104 : :
5238 itagaki.takahiro@gma 105 : 44 : scan = systable_beginscan(pg_lo_meta,
106 : : LargeObjectMetadataOidIndexId, true,
107 : : NULL, 1, skey);
108 : :
109 : 44 : tuple = systable_getnext(scan);
110 [ - + ]: 44 : if (!HeapTupleIsValid(tuple))
5238 itagaki.takahiro@gma 111 [ # # ]:UBC 0 : ereport(ERROR,
112 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
113 : : errmsg("large object %u does not exist", loid)));
114 : :
2629 tgl@sss.pgh.pa.us 115 :CBC 44 : CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
116 : :
5238 itagaki.takahiro@gma 117 : 44 : systable_endscan(scan);
118 : :
119 : : /*
120 : : * Delete all the associated entries from pg_largeobject
121 : : */
122 : 44 : ScanKeyInit(&skey[0],
123 : : Anum_pg_largeobject_loid,
124 : : BTEqualStrategyNumber, F_OIDEQ,
125 : : ObjectIdGetDatum(loid));
126 : :
127 : 44 : scan = systable_beginscan(pg_largeobject,
128 : : LargeObjectLOidPNIndexId, true,
129 : : NULL, 1, skey);
130 [ + + ]: 4007 : while (HeapTupleIsValid(tuple = systable_getnext(scan)))
131 : : {
2629 tgl@sss.pgh.pa.us 132 : 3963 : CatalogTupleDelete(pg_largeobject, &tuple->t_self);
133 : : }
134 : :
5238 itagaki.takahiro@gma 135 : 44 : systable_endscan(scan);
136 : :
1910 andres@anarazel.de 137 : 44 : table_close(pg_largeobject, RowExclusiveLock);
138 : :
139 : 44 : table_close(pg_lo_meta, RowExclusiveLock);
5238 itagaki.takahiro@gma 140 : 44 : }
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
8573 tgl@sss.pgh.pa.us 155 : 75 : LargeObjectExists(Oid loid)
156 : : {
157 : : Relation pg_lo_meta;
158 : : ScanKeyData skey[1];
159 : : SysScanDesc sd;
160 : : HeapTuple tuple;
161 : 75 : bool retval = false;
162 : :
7459 163 : 75 : ScanKeyInit(&skey[0],
164 : : Anum_pg_largeobject_metadata_oid,
165 : : BTEqualStrategyNumber, F_OIDEQ,
166 : : ObjectIdGetDatum(loid));
167 : :
1910 andres@anarazel.de 168 : 75 : pg_lo_meta = table_open(LargeObjectMetadataRelationId,
169 : : AccessShareLock);
170 : :
5238 itagaki.takahiro@gma 171 : 75 : sd = systable_beginscan(pg_lo_meta,
172 : : LargeObjectMetadataOidIndexId, true,
173 : : NULL, 1, skey);
174 : :
175 : 75 : tuple = systable_getnext(sd);
176 [ + + ]: 75 : if (HeapTupleIsValid(tuple))
8000 tgl@sss.pgh.pa.us 177 : 57 : retval = true;
178 : :
7508 179 : 75 : systable_endscan(sd);
180 : :
1910 andres@anarazel.de 181 : 75 : table_close(pg_lo_meta, AccessShareLock);
182 : :
8573 tgl@sss.pgh.pa.us 183 : 75 : return retval;
184 : : }
|