PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_attrdef.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_attrdef.c
4 * routines to support manipulation of the pg_attrdef relation
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/catalog/pg_attrdef.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "access/genam.h"
18#include "access/htup_details.h"
19#include "access/relation.h"
20#include "access/table.h"
21#include "catalog/dependency.h"
22#include "catalog/indexing.h"
24#include "catalog/pg_attrdef.h"
25#include "utils/builtins.h"
26#include "utils/fmgroids.h"
27#include "utils/rel.h"
28#include "utils/syscache.h"
29
30
31/*
32 * Store a default expression for column attnum of relation rel.
33 *
34 * Returns the OID of the new pg_attrdef tuple.
35 */
36Oid
38 Node *expr, bool is_internal)
39{
40 char *adbin;
42 HeapTuple tuple;
44 static bool nulls[Natts_pg_attrdef] = {false, false, false, false};
49 bool nullsAtt[Natts_pg_attribute] = {0};
51 char attgenerated;
55
57
58 /*
59 * Flatten expression to string form for storage.
60 */
61 adbin = nodeToString(expr);
62
63 /*
64 * Make the pg_attrdef entry.
65 */
72
73 tuple = heap_form_tuple(adrel->rd_att, values, nulls);
75
77 defobject.objectId = attrdefOid;
78 defobject.objectSubId = 0;
79
81
82 /* now can free some of the stuff allocated above */
84 heap_freetuple(tuple);
85 pfree(adbin);
86
87 /*
88 * Update the pg_attribute entry for the column to show that a default
89 * exists.
90 */
96 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
99 attgenerated = attStruct->attgenerated;
100
103
106
108
111
112 /*
113 * Make a dependency so that the pg_attrdef entry goes away if the column
114 * (or whole table) is deleted. In the case of a generated column, make
115 * it an internal dependency to prevent the default expression from being
116 * deleted separately.
117 */
119 colobject.objectId = RelationGetRelid(rel);
120 colobject.objectSubId = attnum;
121
123 attgenerated ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
124
125 /*
126 * Record dependencies on objects used in the expression, too.
127 */
130 DEPENDENCY_NORMAL, false);
131
132 /*
133 * Post creation hook for attribute defaults.
134 *
135 * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
136 * couple of deletion/creation of the attribute's default entry, so the
137 * callee should check existence of an older version of this entry if it
138 * needs to distinguish.
139 */
141 RelationGetRelid(rel), attnum, is_internal);
142
143 return attrdefOid;
144}
145
146
147/*
148 * RemoveAttrDefault
149 *
150 * If the specified relation/attribute has a default, remove it.
151 * (If no default, raise error if complain is true, else return quietly.)
152 */
153void
155 DropBehavior behavior, bool complain, bool internal)
156{
158 ScanKeyData scankeys[2];
159 SysScanDesc scan;
160 HeapTuple tuple;
161 bool found = false;
162
164
165 ScanKeyInit(&scankeys[0],
168 ObjectIdGetDatum(relid));
169 ScanKeyInit(&scankeys[1],
173
175 NULL, 2, scankeys);
176
177 /* There should be at most one matching tuple, but we loop anyway */
178 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
179 {
180 ObjectAddress object;
182
184 object.objectId = attrtuple->oid;
185 object.objectSubId = 0;
186
187 performDeletion(&object, behavior,
188 internal ? PERFORM_DELETION_INTERNAL : 0);
189
190 found = true;
191 }
192
193 systable_endscan(scan);
195
196 if (complain && !found)
197 elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
198 relid, attnum);
199}
200
201/*
202 * RemoveAttrDefaultById
203 *
204 * Remove a pg_attrdef entry specified by OID. This is the guts of
205 * attribute-default removal. Note it should be called via performDeletion,
206 * not directly.
207 */
208void
210{
214 ScanKeyData scankeys[1];
215 SysScanDesc scan;
216 HeapTuple tuple;
217 Oid myrelid;
219
220 /* Grab an appropriate lock on the pg_attrdef relation */
222
223 /* Find the pg_attrdef tuple */
224 ScanKeyInit(&scankeys[0],
228
230 NULL, 1, scankeys);
231
232 tuple = systable_getnext(scan);
233 if (!HeapTupleIsValid(tuple))
234 elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
235
237 myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
238
239 /* Get an exclusive lock on the relation owning the attribute */
241
242 /* Now we can delete the pg_attrdef row */
244
245 systable_endscan(scan);
247
248 /* Fix the pg_attribute row */
250
254 if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
255 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
257
258 ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
259
260 CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
261
262 /*
263 * Our update of the pg_attribute row will force a relcache rebuild, so
264 * there's nothing else to do here.
265 */
267
268 /* Keep lock on attribute's rel until end of xact */
270}
271
272
273/*
274 * Get the pg_attrdef OID of the default expression for a column
275 * identified by relation OID and column number.
276 *
277 * Returns InvalidOid if there is no such pg_attrdef entry.
278 */
279Oid
281{
282 Oid result = InvalidOid;
284 ScanKeyData keys[2];
285 SysScanDesc scan;
287
289 ScanKeyInit(&keys[0],
292 F_OIDEQ,
293 ObjectIdGetDatum(relid));
294 ScanKeyInit(&keys[1],
297 F_INT2EQ,
300 NULL, 2, keys);
301
303 {
305
306 result = atdform->oid;
307 }
308
309 systable_endscan(scan);
311
312 return result;
313}
314
315/*
316 * Given a pg_attrdef OID, return the relation OID and column number of
317 * the owning column (represented as an ObjectAddress for convenience).
318 *
319 * Returns InvalidObjectAddress if there is no such pg_attrdef entry.
320 */
int16 AttrNumber
Definition attnum.h:21
static Datum values[MAXATTR]
Definition bootstrap.c:155
#define CStringGetTextDatum(s)
Definition builtins.h:97
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition dependency.c:274
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
@ DEPENDENCY_NORMAL
Definition dependency.h:33
#define PERFORM_DELETION_INTERNAL
Definition dependency.h:92
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
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_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1210
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
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
#define NoLock
Definition lockdefs.h:34
#define AccessExclusiveLock
Definition lockdefs.h:43
#define AccessShareLock
Definition lockdefs.h:36
#define RowExclusiveLock
Definition lockdefs.h:38
void pfree(void *pointer)
Definition mcxt.c:1616
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
const ObjectAddress InvalidObjectAddress
char * nodeToString(const void *obj)
Definition outfuncs.c:802
DropBehavior
Oid StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr, bool is_internal)
Definition pg_attrdef.c:37
void RemoveAttrDefaultById(Oid attrdefId)
Definition pg_attrdef.c:209
Oid GetAttrDefaultOid(Oid relid, AttrNumber attnum)
Definition pg_attrdef.c:280
ObjectAddress GetAttrDefaultColumnAddress(Oid attrdefoid)
Definition pg_attrdef.c:322
void RemoveAttrDefault(Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal)
Definition pg_attrdef.c:154
FormData_pg_attrdef * Form_pg_attrdef
Definition pg_attrdef.h:49
int16 attnum
FormData_pg_attribute * Form_pg_attribute
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:45
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
#define BTEqualStrategyNumber
Definition stratnum.h:31
ItemPointerData t_self
Definition htup.h:65
Definition nodes.h:135
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition syscache.h:93
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40