Fix a memory leak in dumping functions with TRANSFORMs
[pgsql.git] / src / backend / catalog / pg_largeobject.c
blob5d9fdfbd4cd7bfd7ee3a1c68c572d96ecadb4450
1 /*-------------------------------------------------------------------------
3 * pg_largeobject.c
4 * routines to support manipulation of the pg_largeobject relation
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * src/backend/catalog/pg_largeobject.c
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include "access/table.h"
18 #include "catalog/catalog.h"
19 #include "catalog/indexing.h"
20 #include "catalog/pg_largeobject.h"
21 #include "catalog/pg_largeobject_metadata.h"
22 #include "miscadmin.h"
23 #include "utils/fmgroids.h"
24 #include "utils/rel.h"
28 * Create a large object having the given LO identifier.
30 * We create a new large object by inserting an entry into
31 * pg_largeobject_metadata without any data pages, so that the object
32 * will appear to exist with size 0.
34 Oid
35 LargeObjectCreate(Oid loid)
37 Relation pg_lo_meta;
38 HeapTuple ntup;
39 Oid loid_new;
40 Datum values[Natts_pg_largeobject_metadata];
41 bool nulls[Natts_pg_largeobject_metadata];
43 pg_lo_meta = table_open(LargeObjectMetadataRelationId,
44 RowExclusiveLock);
47 * Insert metadata of the largeobject
49 memset(values, 0, sizeof(values));
50 memset(nulls, false, sizeof(nulls));
52 if (OidIsValid(loid))
53 loid_new = loid;
54 else
55 loid_new = GetNewOidWithIndex(pg_lo_meta,
56 LargeObjectMetadataOidIndexId,
57 Anum_pg_largeobject_metadata_oid);
59 values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
60 values[Anum_pg_largeobject_metadata_lomowner - 1]
61 = ObjectIdGetDatum(GetUserId());
62 nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
64 ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
65 values, nulls);
67 CatalogTupleInsert(pg_lo_meta, ntup);
69 heap_freetuple(ntup);
71 table_close(pg_lo_meta, RowExclusiveLock);
73 return loid_new;
77 * Drop a large object having the given LO identifier. Both the data pages
78 * and metadata must be dropped.
80 void
81 LargeObjectDrop(Oid loid)
83 Relation pg_lo_meta;
84 Relation pg_largeobject;
85 ScanKeyData skey[1];
86 SysScanDesc scan;
87 HeapTuple tuple;
89 pg_lo_meta = table_open(LargeObjectMetadataRelationId,
90 RowExclusiveLock);
92 pg_largeobject = table_open(LargeObjectRelationId,
93 RowExclusiveLock);
96 * Delete an entry from pg_largeobject_metadata
98 ScanKeyInit(&skey[0],
99 Anum_pg_largeobject_metadata_oid,
100 BTEqualStrategyNumber, F_OIDEQ,
101 ObjectIdGetDatum(loid));
103 scan = systable_beginscan(pg_lo_meta,
104 LargeObjectMetadataOidIndexId, true,
105 NULL, 1, skey);
107 tuple = systable_getnext(scan);
108 if (!HeapTupleIsValid(tuple))
109 ereport(ERROR,
110 (errcode(ERRCODE_UNDEFINED_OBJECT),
111 errmsg("large object %u does not exist", loid)));
113 CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
115 systable_endscan(scan);
118 * Delete all the associated entries from pg_largeobject
120 ScanKeyInit(&skey[0],
121 Anum_pg_largeobject_loid,
122 BTEqualStrategyNumber, F_OIDEQ,
123 ObjectIdGetDatum(loid));
125 scan = systable_beginscan(pg_largeobject,
126 LargeObjectLOidPNIndexId, true,
127 NULL, 1, skey);
128 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
130 CatalogTupleDelete(pg_largeobject, &tuple->t_self);
133 systable_endscan(scan);
135 table_close(pg_largeobject, RowExclusiveLock);
137 table_close(pg_lo_meta, RowExclusiveLock);
141 * LargeObjectExists
143 * We don't use the system cache for large object metadata, for fear of
144 * using too much local memory.
146 * This function always scans the system catalog using an up-to-date snapshot,
147 * so it should not be used when a large object is opened in read-only mode
148 * (because large objects opened in read only mode are supposed to be viewed
149 * relative to the caller's snapshot, whereas in read-write mode they are
150 * relative to a current snapshot).
152 bool
153 LargeObjectExists(Oid loid)
155 return LargeObjectExistsWithSnapshot(loid, NULL);
159 * Same as LargeObjectExists(), except snapshot to read with can be specified.
161 bool
162 LargeObjectExistsWithSnapshot(Oid loid, Snapshot snapshot)
164 Relation pg_lo_meta;
165 ScanKeyData skey[1];
166 SysScanDesc sd;
167 HeapTuple tuple;
168 bool retval = false;
170 ScanKeyInit(&skey[0],
171 Anum_pg_largeobject_metadata_oid,
172 BTEqualStrategyNumber, F_OIDEQ,
173 ObjectIdGetDatum(loid));
175 pg_lo_meta = table_open(LargeObjectMetadataRelationId,
176 AccessShareLock);
178 sd = systable_beginscan(pg_lo_meta,
179 LargeObjectMetadataOidIndexId, true,
180 snapshot, 1, skey);
182 tuple = systable_getnext(sd);
183 if (HeapTupleIsValid(tuple))
184 retval = true;
186 systable_endscan(sd);
188 table_close(pg_lo_meta, AccessShareLock);
190 return retval;