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-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/table.h"
18 #include "catalog/catalog.h"
19 #include "catalog/indexing.h"
20 #include "catalog/pg_largeobject.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  */
34 Oid
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  */
80 void
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))
109  ereport(ERROR,
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  */
152 bool
154 {
155  return LargeObjectExistsWithSnapshot(loid, NULL);
156 }
157 
158 /*
159  * Same as LargeObjectExists(), except snapshot to read with can be specified.
160  */
161 bool
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 
186  systable_endscan(sd);
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:729
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:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#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:524
void LargeObjectDrop(Oid loid)
bool LargeObjectExistsWithSnapshot(Oid loid, Snapshot snapshot)
bool LargeObjectExists(Oid loid)
Oid LargeObjectCreate(Oid loid)
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
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