1 /*-------------------------------------------------------------------------
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
11 * src/backend/catalog/pg_largeobject.c
13 *-------------------------------------------------------------------------
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.
35 LargeObjectCreate(Oid loid
)
40 Datum values
[Natts_pg_largeobject_metadata
];
41 bool nulls
[Natts_pg_largeobject_metadata
];
43 pg_lo_meta
= table_open(LargeObjectMetadataRelationId
,
47 * Insert metadata of the largeobject
49 memset(values
, 0, sizeof(values
));
50 memset(nulls
, false, sizeof(nulls
));
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
),
67 CatalogTupleInsert(pg_lo_meta
, ntup
);
71 table_close(pg_lo_meta
, RowExclusiveLock
);
77 * Drop a large object having the given LO identifier. Both the data pages
78 * and metadata must be dropped.
81 LargeObjectDrop(Oid loid
)
84 Relation pg_largeobject
;
89 pg_lo_meta
= table_open(LargeObjectMetadataRelationId
,
92 pg_largeobject
= table_open(LargeObjectRelationId
,
96 * Delete an entry from pg_largeobject_metadata
99 Anum_pg_largeobject_metadata_oid
,
100 BTEqualStrategyNumber
, F_OIDEQ
,
101 ObjectIdGetDatum(loid
));
103 scan
= systable_beginscan(pg_lo_meta
,
104 LargeObjectMetadataOidIndexId
, true,
107 tuple
= systable_getnext(scan
);
108 if (!HeapTupleIsValid(tuple
))
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,
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
);
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).
153 LargeObjectExists(Oid loid
)
155 return LargeObjectExistsWithSnapshot(loid
, NULL
);
159 * Same as LargeObjectExists(), except snapshot to read with can be specified.
162 LargeObjectExistsWithSnapshot(Oid loid
, Snapshot snapshot
)
170 ScanKeyInit(&skey
[0],
171 Anum_pg_largeobject_metadata_oid
,
172 BTEqualStrategyNumber
, F_OIDEQ
,
173 ObjectIdGetDatum(loid
));
175 pg_lo_meta
= table_open(LargeObjectMetadataRelationId
,
178 sd
= systable_beginscan(pg_lo_meta
,
179 LargeObjectMetadataOidIndexId
, true,
182 tuple
= systable_getnext(sd
);
183 if (HeapTupleIsValid(tuple
))
186 systable_endscan(sd
);
188 table_close(pg_lo_meta
, AccessShareLock
);