PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
pg_attrdef.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/relation.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_attrdef.h"
#include "executor/executor.h"
#include "optimizer/optimizer.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for pg_attrdef.c:

Go to the source code of this file.

Functions

Oid StoreAttrDefault (Relation rel, AttrNumber attnum, Node *expr, bool is_internal, bool add_column_mode)
 
void RemoveAttrDefault (Oid relid, AttrNumber attnum, DropBehavior behavior, bool complain, bool internal)
 
void RemoveAttrDefaultById (Oid attrdefId)
 
Oid GetAttrDefaultOid (Oid relid, AttrNumber attnum)
 
ObjectAddress GetAttrDefaultColumnAddress (Oid attrdefoid)
 

Function Documentation

◆ GetAttrDefaultColumnAddress()

ObjectAddress GetAttrDefaultColumnAddress ( Oid  attrdefoid)

Definition at line 381 of file pg_attrdef.c.

382{
384 Relation attrdef;
385 ScanKeyData skey[1];
386 SysScanDesc scan;
387 HeapTuple tup;
388
389 attrdef = table_open(AttrDefaultRelationId, AccessShareLock);
390 ScanKeyInit(&skey[0],
391 Anum_pg_attrdef_oid,
392 BTEqualStrategyNumber, F_OIDEQ,
393 ObjectIdGetDatum(attrdefoid));
394 scan = systable_beginscan(attrdef, AttrDefaultOidIndexId, true,
395 NULL, 1, skey);
396
397 if (HeapTupleIsValid(tup = systable_getnext(scan)))
398 {
400
401 result.classId = RelationRelationId;
402 result.objectId = atdform->adrelid;
403 result.objectSubId = atdform->adnum;
404 }
405
406 systable_endscan(scan);
408
409 return result;
410}
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
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define AccessShareLock
Definition: lockdefs.h:36
const ObjectAddress InvalidObjectAddress
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:49
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References AccessShareLock, BTEqualStrategyNumber, ObjectAddress::classId, GETSTRUCT, HeapTupleIsValid, InvalidObjectAddress, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by getObjectDescription(), getObjectIdentityParts(), and RememberAllDependentForRebuilding().

◆ GetAttrDefaultOid()

Oid GetAttrDefaultOid ( Oid  relid,
AttrNumber  attnum 
)

Definition at line 339 of file pg_attrdef.c.

340{
341 Oid result = InvalidOid;
342 Relation attrdef;
343 ScanKeyData keys[2];
344 SysScanDesc scan;
345 HeapTuple tup;
346
347 attrdef = table_open(AttrDefaultRelationId, AccessShareLock);
348 ScanKeyInit(&keys[0],
349 Anum_pg_attrdef_adrelid,
351 F_OIDEQ,
352 ObjectIdGetDatum(relid));
353 ScanKeyInit(&keys[1],
354 Anum_pg_attrdef_adnum,
356 F_INT2EQ,
358 scan = systable_beginscan(attrdef, AttrDefaultIndexId, true,
359 NULL, 2, keys);
360
361 if (HeapTupleIsValid(tup = systable_getnext(scan)))
362 {
364
365 result = atdform->oid;
366 }
367
368 systable_endscan(scan);
370
371 return result;
372}
int16 attnum
Definition: pg_attribute.h:74
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:177
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32

References AccessShareLock, attnum, BTEqualStrategyNumber, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), InvalidOid, ObjectIdGetDatum(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ATExecAlterColumnType(), ATExecDropExpression(), ATExecSetExpression(), and get_object_address_attrdef().

◆ RemoveAttrDefault()

void RemoveAttrDefault ( Oid  relid,
AttrNumber  attnum,
DropBehavior  behavior,
bool  complain,
bool  internal 
)

Definition at line 213 of file pg_attrdef.c.

215{
216 Relation attrdef_rel;
217 ScanKeyData scankeys[2];
218 SysScanDesc scan;
219 HeapTuple tuple;
220 bool found = false;
221
222 attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
223
224 ScanKeyInit(&scankeys[0],
225 Anum_pg_attrdef_adrelid,
226 BTEqualStrategyNumber, F_OIDEQ,
227 ObjectIdGetDatum(relid));
228 ScanKeyInit(&scankeys[1],
229 Anum_pg_attrdef_adnum,
230 BTEqualStrategyNumber, F_INT2EQ,
232
233 scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
234 NULL, 2, scankeys);
235
236 /* There should be at most one matching tuple, but we loop anyway */
237 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
238 {
239 ObjectAddress object;
240 Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
241
242 object.classId = AttrDefaultRelationId;
243 object.objectId = attrtuple->oid;
244 object.objectSubId = 0;
245
246 performDeletion(&object, behavior,
247 internal ? PERFORM_DELETION_INTERNAL : 0);
248
249 found = true;
250 }
251
252 systable_endscan(scan);
253 table_close(attrdef_rel, RowExclusiveLock);
254
255 if (complain && !found)
256 elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
257 relid, attnum);
258}
void performDeletion(const ObjectAddress *object, DropBehavior behavior, int flags)
Definition: dependency.c:273
#define PERFORM_DELETION_INTERNAL
Definition: dependency.h:92
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define RowExclusiveLock
Definition: lockdefs.h:38

References attnum, BTEqualStrategyNumber, elog, ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), PERFORM_DELETION_INTERNAL, performDeletion(), RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by ATExecAlterColumnType(), ATExecColumnDefault(), ATExecCookedColumnDefault(), ATExecDropExpression(), and ATExecSetExpression().

◆ RemoveAttrDefaultById()

void RemoveAttrDefaultById ( Oid  attrdefId)

Definition at line 268 of file pg_attrdef.c.

269{
270 Relation attrdef_rel;
271 Relation attr_rel;
272 Relation myrel;
273 ScanKeyData scankeys[1];
274 SysScanDesc scan;
275 HeapTuple tuple;
276 Oid myrelid;
277 AttrNumber myattnum;
278
279 /* Grab an appropriate lock on the pg_attrdef relation */
280 attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
281
282 /* Find the pg_attrdef tuple */
283 ScanKeyInit(&scankeys[0],
284 Anum_pg_attrdef_oid,
285 BTEqualStrategyNumber, F_OIDEQ,
286 ObjectIdGetDatum(attrdefId));
287
288 scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
289 NULL, 1, scankeys);
290
291 tuple = systable_getnext(scan);
292 if (!HeapTupleIsValid(tuple))
293 elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
294
295 myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
296 myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
297
298 /* Get an exclusive lock on the relation owning the attribute */
299 myrel = relation_open(myrelid, AccessExclusiveLock);
300
301 /* Now we can delete the pg_attrdef row */
302 CatalogTupleDelete(attrdef_rel, &tuple->t_self);
303
304 systable_endscan(scan);
305 table_close(attrdef_rel, RowExclusiveLock);
306
307 /* Fix the pg_attribute row */
308 attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
309
310 tuple = SearchSysCacheCopy2(ATTNUM,
311 ObjectIdGetDatum(myrelid),
312 Int16GetDatum(myattnum));
313 if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
314 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
315 myattnum, myrelid);
316
317 ((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
318
319 CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
320
321 /*
322 * Our update of the pg_attribute row will force a relcache rebuild, so
323 * there's nothing else to do here.
324 */
325 table_close(attr_rel, RowExclusiveLock);
326
327 /* Keep lock on attribute's rel until end of xact */
328 relation_close(myrel, NoLock);
329}
int16 AttrNumber
Definition: attnum.h:21
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
ItemPointerData t_self
Definition: htup.h:65
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:93

References AccessExclusiveLock, BTEqualStrategyNumber, CatalogTupleDelete(), CatalogTupleUpdate(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), NoLock, ObjectIdGetDatum(), relation_close(), relation_open(), RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy2, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ StoreAttrDefault()

Oid StoreAttrDefault ( Relation  rel,
AttrNumber  attnum,
Node expr,
bool  is_internal,
bool  add_column_mode 
)

Definition at line 46 of file pg_attrdef.c.

48{
49 char *adbin;
50 Relation adrel;
51 HeapTuple tuple;
52 Datum values[4];
53 static bool nulls[4] = {false, false, false, false};
54 Relation attrrel;
55 HeapTuple atttup;
56 Form_pg_attribute attStruct;
57 char attgenerated;
58 Oid attrdefOid;
59 ObjectAddress colobject,
60 defobject;
61
62 adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
63
64 /*
65 * Flatten expression to string form for storage.
66 */
67 adbin = nodeToString(expr);
68
69 /*
70 * Make the pg_attrdef entry.
71 */
72 attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
73 Anum_pg_attrdef_oid);
74 values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
75 values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
76 values[Anum_pg_attrdef_adnum - 1] = attnum;
77 values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
78
79 tuple = heap_form_tuple(adrel->rd_att, values, nulls);
80 CatalogTupleInsert(adrel, tuple);
81
82 defobject.classId = AttrDefaultRelationId;
83 defobject.objectId = attrdefOid;
84 defobject.objectSubId = 0;
85
87
88 /* now can free some of the stuff allocated above */
89 pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
90 heap_freetuple(tuple);
91 pfree(adbin);
92
93 /*
94 * Update the pg_attribute entry for the column to show that a default
95 * exists.
96 */
97 attrrel = table_open(AttributeRelationId, RowExclusiveLock);
98 atttup = SearchSysCacheCopy2(ATTNUM,
101 if (!HeapTupleIsValid(atttup))
102 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
104 attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
105 attgenerated = attStruct->attgenerated;
106 if (!attStruct->atthasdef)
107 {
108 Form_pg_attribute defAttStruct;
109
110 ExprState *exprState;
111 Expr *expr2 = (Expr *) expr;
112 EState *estate = NULL;
113 ExprContext *econtext;
114 Datum valuesAtt[Natts_pg_attribute] = {0};
115 bool nullsAtt[Natts_pg_attribute] = {0};
116 bool replacesAtt[Natts_pg_attribute] = {0};
117 Datum missingval = (Datum) 0;
118 bool missingIsNull = true;
119
120 valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
121 replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
122
123 if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode &&
124 !attgenerated)
125 {
126 expr2 = expression_planner(expr2);
127 estate = CreateExecutorState();
128 exprState = ExecPrepareExpr(expr2, estate);
129 econtext = GetPerTupleExprContext(estate);
130
131 missingval = ExecEvalExpr(exprState, econtext,
132 &missingIsNull);
133
134 FreeExecutorState(estate);
135
136 defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
137
138 if (missingIsNull)
139 {
140 /* if the default evaluates to NULL, just store a NULL array */
141 missingval = (Datum) 0;
142 }
143 else
144 {
145 /* otherwise make a one-element array of the value */
146 missingval = PointerGetDatum(construct_array(&missingval,
147 1,
148 defAttStruct->atttypid,
149 defAttStruct->attlen,
150 defAttStruct->attbyval,
151 defAttStruct->attalign));
152 }
153
154 valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
155 replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
156 valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
157 replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
158 nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
159 }
160 atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
161 valuesAtt, nullsAtt, replacesAtt);
162
163 CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
164
165 if (!missingIsNull)
166 pfree(DatumGetPointer(missingval));
167 }
169 heap_freetuple(atttup);
170
171 /*
172 * Make a dependency so that the pg_attrdef entry goes away if the column
173 * (or whole table) is deleted. In the case of a generated column, make
174 * it an internal dependency to prevent the default expression from being
175 * deleted separately.
176 */
177 colobject.classId = RelationRelationId;
178 colobject.objectId = RelationGetRelid(rel);
179 colobject.objectSubId = attnum;
180
181 recordDependencyOn(&defobject, &colobject,
182 attgenerated ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO);
183
184 /*
185 * Record dependencies on objects used in the expression, too.
186 */
189 DEPENDENCY_NORMAL, false);
190
191 /*
192 * Post creation hook for attribute defaults.
193 *
194 * XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
195 * couple of deletion/creation of the attribute's default entry, so the
196 * callee should check existence of an older version of this entry if it
197 * needs to distinguish.
198 */
199 InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
200 RelationGetRelid(rel), attnum, is_internal);
201
202 return attrdefOid;
203}
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3361
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:419
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
Definition: dependency.c:1596
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execExpr.c:765
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
EState * CreateExecutorState(void)
Definition: execUtils.c:88
#define GetPerTupleExprContext(estate)
Definition: executor.h:563
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:346
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
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void pfree(void *pointer)
Definition: mcxt.c:1521
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:175
char * nodeToString(const void *obj)
Definition: outfuncs.c:794
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:45
Expr * expression_planner(Expr *expr)
Definition: planner.c:6570
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
TupleDesc rd_att
Definition: rel.h:112
Form_pg_class rd_rel
Definition: rel.h:111
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153

References attnum, CatalogTupleInsert(), CatalogTupleUpdate(), ObjectAddress::classId, construct_array(), CreateExecutorState(), CStringGetTextDatum, DatumGetPointer(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, elog, ERROR, ExecEvalExpr(), ExecPrepareExpr(), expression_planner(), FreeExecutorState(), GetNewOidWithIndex(), GetPerTupleExprContext, GETSTRUCT, heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), InvokeObjectPostCreateHookArg, nodeToString(), ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, pfree(), PointerGetDatum(), RelationData::rd_att, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnSingleRelExpr(), RelationGetDescr, RelationGetRelid, RowExclusiveLock, SearchSysCacheCopy2, HeapTupleData::t_self, table_close(), table_open(), TupleDescAttr(), and values.

Referenced by AddRelationNewConstraints(), ATExecAlterColumnType(), ATExecCookedColumnDefault(), and StoreConstraints().