PostgreSQL Source Code git master
pg_largeobject.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_largeobject.c
4 * routines to support manipulation of the pg_largeobject relation
5 *
6 * Portions Copyright (c) 1996-2025, 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/table.h"
18#include "catalog/catalog.h"
19#include "catalog/indexing.h"
22#include "miscadmin.h"
23#include "utils/fmgroids.h"
24#include "utils/rel.h"
25
26
27/*
28 * Create a large object having the given LO identifier.
29 *
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.
33 */
34Oid
36{
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];
42
43 pg_lo_meta = table_open(LargeObjectMetadataRelationId,
45
46 /*
47 * Insert metadata of the largeobject
48 */
49 memset(values, 0, sizeof(values));
50 memset(nulls, false, sizeof(nulls));
51
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);
58
59 values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
60 values[Anum_pg_largeobject_metadata_lomowner - 1]
62 nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
63
64 ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
65 values, nulls);
66
67 CatalogTupleInsert(pg_lo_meta, ntup);
68
69 heap_freetuple(ntup);
70
71 table_close(pg_lo_meta, RowExclusiveLock);
72
73 return loid_new;
74}
75
76/*
77 * Drop a large object having the given LO identifier. Both the data pages
78 * and metadata must be dropped.
79 */
80void
82{
83 Relation pg_lo_meta;
84 Relation pg_largeobject;
85 ScanKeyData skey[1];
86 SysScanDesc scan;
87 HeapTuple tuple;
88
89 pg_lo_meta = table_open(LargeObjectMetadataRelationId,
91
92 pg_largeobject = table_open(LargeObjectRelationId,
94
95 /*
96 * Delete an entry from pg_largeobject_metadata
97 */
98 ScanKeyInit(&skey[0],
99 Anum_pg_largeobject_metadata_oid,
100 BTEqualStrategyNumber, F_OIDEQ,
101 ObjectIdGetDatum(loid));
102
103 scan = systable_beginscan(pg_lo_meta,
104 LargeObjectMetadataOidIndexId, true,
105 NULL, 1, skey);
106
107 tuple = systable_getnext(scan);
108 if (!HeapTupleIsValid(tuple))
110 (errcode(ERRCODE_UNDEFINED_OBJECT),
111 errmsg("large object %u does not exist", loid)));
112
113 CatalogTupleDelete(pg_lo_meta, &tuple->t_self);
114
115 systable_endscan(scan);
116
117 /*
118 * Delete all the associated entries from pg_largeobject
119 */
120 ScanKeyInit(&skey[0],
121 Anum_pg_largeobject_loid,
122 BTEqualStrategyNumber, F_OIDEQ,
123 ObjectIdGetDatum(loid));
124
125 scan = systable_beginscan(pg_largeobject,
126 LargeObjectLOidPNIndexId, true,
127 NULL, 1, skey);
128 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
129 {
130 CatalogTupleDelete(pg_largeobject, &tuple->t_self);
131 }
132
133 systable_endscan(scan);
134
135 table_close(pg_largeobject, RowExclusiveLock);
136
137 table_close(pg_lo_meta, RowExclusiveLock);
138}
139
140/*
141 * LargeObjectExists
142 *
143 * We don't use the system cache for large object metadata, for fear of
144 * using too much local memory.
145 *
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).
151 */
152bool
154{
155 return LargeObjectExistsWithSnapshot(loid, NULL);
156}
157
158/*
159 * Same as LargeObjectExists(), except snapshot to read with can be specified.
160 */
161bool
163{
164 Relation pg_lo_meta;
165 ScanKeyData skey[1];
166 SysScanDesc sd;
167 HeapTuple tuple;
168 bool retval = false;
169
170 ScanKeyInit(&skey[0],
171 Anum_pg_largeobject_metadata_oid,
172 BTEqualStrategyNumber, F_OIDEQ,
173 ObjectIdGetDatum(loid));
174
175 pg_lo_meta = table_open(LargeObjectMetadataRelationId,
177
178 sd = systable_beginscan(pg_lo_meta,
179 LargeObjectMetadataOidIndexId, true,
180 snapshot, 1, skey);
181
182 tuple = systable_getnext(sd);
183 if (HeapTupleIsValid(tuple))
184 retval = true;
185
187
188 table_close(pg_lo_meta, AccessShareLock);
189
190 return retval;
191}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define OidIsValid(objectId)
Definition: c.h:746
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:419
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:520
void LargeObjectDrop(Oid loid)
bool LargeObjectExistsWithSnapshot(Oid loid, Snapshot snapshot)
bool LargeObjectExists(Oid loid)
Oid LargeObjectCreate(Oid loid)
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetDescr(relation)
Definition: rel.h:539
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40