Skip to content

Commit 17f3bc0

Browse files
committed
Move pg_attrdef manipulation code into new file catalog/pg_attrdef.c.
This is a pure refactoring commit: there isn't (I hope) any functional change. StoreAttrDefault and RemoveAttrDefault[ById] are moved from heap.c, reducing the size of that overly-large file by about 300 lines. I took the opportunity to trim unused #includes from heap.c, too. Two new functions for translating between a pg_attrdef OID and the relid/attnum of the owning column are created by extracting ad-hoc code from objectaddress.c. This already removes one copy of said code, and a follow-on bug fix will create more callers. The only other function directly manipulating pg_attrdef is AttrDefaultFetch. I judged it was better to leave that in relcache.c, since it shares special concerns about recursion and error handling with the rest of that module. Discussion: https://postgr.es/m/651168.1647451676@sss.pgh.pa.us
1 parent 7b6ec86 commit 17f3bc0

File tree

7 files changed

+450
-426
lines changed

7 files changed

+450
-426
lines changed

src/backend/catalog/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ OBJS = \
2525
objectaddress.o \
2626
partition.o \
2727
pg_aggregate.o \
28+
pg_attrdef.o \
2829
pg_cast.o \
2930
pg_class.o \
3031
pg_collation.o \

src/backend/catalog/heap.c

Lines changed: 0 additions & 330 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,11 @@
3030
#include "postgres.h"
3131

3232
#include "access/genam.h"
33-
#include "access/htup_details.h"
3433
#include "access/multixact.h"
3534
#include "access/relation.h"
36-
#include "access/sysattr.h"
3735
#include "access/table.h"
3836
#include "access/tableam.h"
39-
#include "access/toast_compression.h"
40-
#include "access/transam.h"
41-
#include "access/xact.h"
42-
#include "access/xlog.h"
43-
#include "catalog/binary_upgrade.h"
4437
#include "catalog/catalog.h"
45-
#include "catalog/dependency.h"
4638
#include "catalog/heap.h"
4739
#include "catalog/index.h"
4840
#include "catalog/objectaccess.h"
@@ -61,10 +53,8 @@
6153
#include "catalog/pg_tablespace.h"
6254
#include "catalog/pg_type.h"
6355
#include "catalog/storage.h"
64-
#include "catalog/storage_xlog.h"
6556
#include "commands/tablecmds.h"
6657
#include "commands/typecmds.h"
67-
#include "executor/executor.h"
6858
#include "miscadmin.h"
6959
#include "nodes/nodeFuncs.h"
7060
#include "optimizer/optimizer.h"
@@ -76,16 +66,10 @@
7666
#include "partitioning/partdesc.h"
7767
#include "storage/lmgr.h"
7868
#include "storage/predicate.h"
79-
#include "storage/smgr.h"
80-
#include "utils/acl.h"
8169
#include "utils/builtins.h"
82-
#include "utils/datum.h"
8370
#include "utils/fmgroids.h"
8471
#include "utils/inval.h"
8572
#include "utils/lsyscache.h"
86-
#include "utils/partcache.h"
87-
#include "utils/ruleutils.h"
88-
#include "utils/snapmgr.h"
8973
#include "utils/syscache.h"
9074

9175

@@ -1757,131 +1741,6 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
17571741
relation_close(rel, NoLock);
17581742
}
17591743

1760-
/*
1761-
* RemoveAttrDefault
1762-
*
1763-
* If the specified relation/attribute has a default, remove it.
1764-
* (If no default, raise error if complain is true, else return quietly.)
1765-
*/
1766-
void
1767-
RemoveAttrDefault(Oid relid, AttrNumber attnum,
1768-
DropBehavior behavior, bool complain, bool internal)
1769-
{
1770-
Relation attrdef_rel;
1771-
ScanKeyData scankeys[2];
1772-
SysScanDesc scan;
1773-
HeapTuple tuple;
1774-
bool found = false;
1775-
1776-
attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1777-
1778-
ScanKeyInit(&scankeys[0],
1779-
Anum_pg_attrdef_adrelid,
1780-
BTEqualStrategyNumber, F_OIDEQ,
1781-
ObjectIdGetDatum(relid));
1782-
ScanKeyInit(&scankeys[1],
1783-
Anum_pg_attrdef_adnum,
1784-
BTEqualStrategyNumber, F_INT2EQ,
1785-
Int16GetDatum(attnum));
1786-
1787-
scan = systable_beginscan(attrdef_rel, AttrDefaultIndexId, true,
1788-
NULL, 2, scankeys);
1789-
1790-
/* There should be at most one matching tuple, but we loop anyway */
1791-
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1792-
{
1793-
ObjectAddress object;
1794-
Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
1795-
1796-
object.classId = AttrDefaultRelationId;
1797-
object.objectId = attrtuple->oid;
1798-
object.objectSubId = 0;
1799-
1800-
performDeletion(&object, behavior,
1801-
internal ? PERFORM_DELETION_INTERNAL : 0);
1802-
1803-
found = true;
1804-
}
1805-
1806-
systable_endscan(scan);
1807-
table_close(attrdef_rel, RowExclusiveLock);
1808-
1809-
if (complain && !found)
1810-
elog(ERROR, "could not find attrdef tuple for relation %u attnum %d",
1811-
relid, attnum);
1812-
}
1813-
1814-
/*
1815-
* RemoveAttrDefaultById
1816-
*
1817-
* Remove a pg_attrdef entry specified by OID. This is the guts of
1818-
* attribute-default removal. Note it should be called via performDeletion,
1819-
* not directly.
1820-
*/
1821-
void
1822-
RemoveAttrDefaultById(Oid attrdefId)
1823-
{
1824-
Relation attrdef_rel;
1825-
Relation attr_rel;
1826-
Relation myrel;
1827-
ScanKeyData scankeys[1];
1828-
SysScanDesc scan;
1829-
HeapTuple tuple;
1830-
Oid myrelid;
1831-
AttrNumber myattnum;
1832-
1833-
/* Grab an appropriate lock on the pg_attrdef relation */
1834-
attrdef_rel = table_open(AttrDefaultRelationId, RowExclusiveLock);
1835-
1836-
/* Find the pg_attrdef tuple */
1837-
ScanKeyInit(&scankeys[0],
1838-
Anum_pg_attrdef_oid,
1839-
BTEqualStrategyNumber, F_OIDEQ,
1840-
ObjectIdGetDatum(attrdefId));
1841-
1842-
scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndexId, true,
1843-
NULL, 1, scankeys);
1844-
1845-
tuple = systable_getnext(scan);
1846-
if (!HeapTupleIsValid(tuple))
1847-
elog(ERROR, "could not find tuple for attrdef %u", attrdefId);
1848-
1849-
myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
1850-
myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
1851-
1852-
/* Get an exclusive lock on the relation owning the attribute */
1853-
myrel = relation_open(myrelid, AccessExclusiveLock);
1854-
1855-
/* Now we can delete the pg_attrdef row */
1856-
CatalogTupleDelete(attrdef_rel, &tuple->t_self);
1857-
1858-
systable_endscan(scan);
1859-
table_close(attrdef_rel, RowExclusiveLock);
1860-
1861-
/* Fix the pg_attribute row */
1862-
attr_rel = table_open(AttributeRelationId, RowExclusiveLock);
1863-
1864-
tuple = SearchSysCacheCopy2(ATTNUM,
1865-
ObjectIdGetDatum(myrelid),
1866-
Int16GetDatum(myattnum));
1867-
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
1868-
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1869-
myattnum, myrelid);
1870-
1871-
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
1872-
1873-
CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
1874-
1875-
/*
1876-
* Our update of the pg_attribute row will force a relcache rebuild, so
1877-
* there's nothing else to do here.
1878-
*/
1879-
table_close(attr_rel, RowExclusiveLock);
1880-
1881-
/* Keep lock on attribute's rel until end of xact */
1882-
relation_close(myrel, NoLock);
1883-
}
1884-
18851744
/*
18861745
* heap_drop_with_catalog - removes specified relation from catalogs
18871746
*
@@ -2193,195 +2052,6 @@ SetAttrMissing(Oid relid, char *attname, char *value)
21932052
table_close(tablerel, AccessExclusiveLock);
21942053
}
21952054

2196-
/*
2197-
* Store a default expression for column attnum of relation rel.
2198-
*
2199-
* Returns the OID of the new pg_attrdef tuple.
2200-
*
2201-
* add_column_mode must be true if we are storing the default for a new
2202-
* attribute, and false if it's for an already existing attribute. The reason
2203-
* for this is that the missing value must never be updated after it is set,
2204-
* which can only be when a column is added to the table. Otherwise we would
2205-
* in effect be changing existing tuples.
2206-
*/
2207-
Oid
2208-
StoreAttrDefault(Relation rel, AttrNumber attnum,
2209-
Node *expr, bool is_internal, bool add_column_mode)
2210-
{
2211-
char *adbin;
2212-
Relation adrel;
2213-
HeapTuple tuple;
2214-
Datum values[4];
2215-
static bool nulls[4] = {false, false, false, false};
2216-
Relation attrrel;
2217-
HeapTuple atttup;
2218-
Form_pg_attribute attStruct;
2219-
char attgenerated;
2220-
Oid attrdefOid;
2221-
ObjectAddress colobject,
2222-
defobject;
2223-
2224-
adrel = table_open(AttrDefaultRelationId, RowExclusiveLock);
2225-
2226-
/*
2227-
* Flatten expression to string form for storage.
2228-
*/
2229-
adbin = nodeToString(expr);
2230-
2231-
/*
2232-
* Make the pg_attrdef entry.
2233-
*/
2234-
attrdefOid = GetNewOidWithIndex(adrel, AttrDefaultOidIndexId,
2235-
Anum_pg_attrdef_oid);
2236-
values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
2237-
values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
2238-
values[Anum_pg_attrdef_adnum - 1] = attnum;
2239-
values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
2240-
2241-
tuple = heap_form_tuple(adrel->rd_att, values, nulls);
2242-
CatalogTupleInsert(adrel, tuple);
2243-
2244-
defobject.classId = AttrDefaultRelationId;
2245-
defobject.objectId = attrdefOid;
2246-
defobject.objectSubId = 0;
2247-
2248-
table_close(adrel, RowExclusiveLock);
2249-
2250-
/* now can free some of the stuff allocated above */
2251-
pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
2252-
heap_freetuple(tuple);
2253-
pfree(adbin);
2254-
2255-
/*
2256-
* Update the pg_attribute entry for the column to show that a default
2257-
* exists.
2258-
*/
2259-
attrrel = table_open(AttributeRelationId, RowExclusiveLock);
2260-
atttup = SearchSysCacheCopy2(ATTNUM,
2261-
ObjectIdGetDatum(RelationGetRelid(rel)),
2262-
Int16GetDatum(attnum));
2263-
if (!HeapTupleIsValid(atttup))
2264-
elog(ERROR, "cache lookup failed for attribute %d of relation %u",
2265-
attnum, RelationGetRelid(rel));
2266-
attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
2267-
attgenerated = attStruct->attgenerated;
2268-
if (!attStruct->atthasdef)
2269-
{
2270-
Form_pg_attribute defAttStruct;
2271-
2272-
ExprState *exprState;
2273-
Expr *expr2 = (Expr *) expr;
2274-
EState *estate = NULL;
2275-
ExprContext *econtext;
2276-
Datum valuesAtt[Natts_pg_attribute];
2277-
bool nullsAtt[Natts_pg_attribute];
2278-
bool replacesAtt[Natts_pg_attribute];
2279-
Datum missingval = (Datum) 0;
2280-
bool missingIsNull = true;
2281-
2282-
MemSet(valuesAtt, 0, sizeof(valuesAtt));
2283-
MemSet(nullsAtt, false, sizeof(nullsAtt));
2284-
MemSet(replacesAtt, false, sizeof(replacesAtt));
2285-
valuesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2286-
replacesAtt[Anum_pg_attribute_atthasdef - 1] = true;
2287-
2288-
if (rel->rd_rel->relkind == RELKIND_RELATION && add_column_mode &&
2289-
!attgenerated)
2290-
{
2291-
expr2 = expression_planner(expr2);
2292-
estate = CreateExecutorState();
2293-
exprState = ExecPrepareExpr(expr2, estate);
2294-
econtext = GetPerTupleExprContext(estate);
2295-
2296-
missingval = ExecEvalExpr(exprState, econtext,
2297-
&missingIsNull);
2298-
2299-
FreeExecutorState(estate);
2300-
2301-
defAttStruct = TupleDescAttr(rel->rd_att, attnum - 1);
2302-
2303-
if (missingIsNull)
2304-
{
2305-
/* if the default evaluates to NULL, just store a NULL array */
2306-
missingval = (Datum) 0;
2307-
}
2308-
else
2309-
{
2310-
/* otherwise make a one-element array of the value */
2311-
missingval = PointerGetDatum(construct_array(&missingval,
2312-
1,
2313-
defAttStruct->atttypid,
2314-
defAttStruct->attlen,
2315-
defAttStruct->attbyval,
2316-
defAttStruct->attalign));
2317-
}
2318-
2319-
valuesAtt[Anum_pg_attribute_atthasmissing - 1] = !missingIsNull;
2320-
replacesAtt[Anum_pg_attribute_atthasmissing - 1] = true;
2321-
valuesAtt[Anum_pg_attribute_attmissingval - 1] = missingval;
2322-
replacesAtt[Anum_pg_attribute_attmissingval - 1] = true;
2323-
nullsAtt[Anum_pg_attribute_attmissingval - 1] = missingIsNull;
2324-
}
2325-
atttup = heap_modify_tuple(atttup, RelationGetDescr(attrrel),
2326-
valuesAtt, nullsAtt, replacesAtt);
2327-
2328-
CatalogTupleUpdate(attrrel, &atttup->t_self, atttup);
2329-
2330-
if (!missingIsNull)
2331-
pfree(DatumGetPointer(missingval));
2332-
2333-
}
2334-
table_close(attrrel, RowExclusiveLock);
2335-
heap_freetuple(atttup);
2336-
2337-
/*
2338-
* Make a dependency so that the pg_attrdef entry goes away if the column
2339-
* (or whole table) is deleted.
2340-
*/
2341-
colobject.classId = RelationRelationId;
2342-
colobject.objectId = RelationGetRelid(rel);
2343-
colobject.objectSubId = attnum;
2344-
2345-
recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
2346-
2347-
/*
2348-
* Record dependencies on objects used in the expression, too.
2349-
*/
2350-
if (attgenerated)
2351-
{
2352-
/*
2353-
* Generated column: Dropping anything that the generation expression
2354-
* refers to automatically drops the generated column.
2355-
*/
2356-
recordDependencyOnSingleRelExpr(&colobject, expr, RelationGetRelid(rel),
2357-
DEPENDENCY_AUTO,
2358-
DEPENDENCY_AUTO, false);
2359-
}
2360-
else
2361-
{
2362-
/*
2363-
* Normal default: Dropping anything that the default refers to
2364-
* requires CASCADE and drops the default only.
2365-
*/
2366-
recordDependencyOnSingleRelExpr(&defobject, expr, RelationGetRelid(rel),
2367-
DEPENDENCY_NORMAL,
2368-
DEPENDENCY_NORMAL, false);
2369-
}
2370-
2371-
/*
2372-
* Post creation hook for attribute defaults.
2373-
*
2374-
* XXX. ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is implemented with a
2375-
* couple of deletion/creation of the attribute's default entry, so the
2376-
* callee should check existence of an older version of this entry if it
2377-
* needs to distinguish.
2378-
*/
2379-
InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
2380-
RelationGetRelid(rel), attnum, is_internal);
2381-
2382-
return attrdefOid;
2383-
}
2384-
23852055
/*
23862056
* Store a check-constraint expression for the given relation.
23872057
*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy