Commit 7bd631bf authored by Tom Lane's avatar Tom Lane

Use the dependency mechanism to manage column defaults. We need this

so that dependencies in default expressions (on operators, functions,
etc) can be expressed properly.
parent 3c580b8d
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.1 2002/07/12 18:43:13 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.2 2002/07/15 16:33:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "catalog/heap.h" #include "catalog/heap.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_constraint.h" #include "catalog/pg_constraint.h"
#include "catalog/pg_depend.h" #include "catalog/pg_depend.h"
#include "catalog/pg_language.h" #include "catalog/pg_language.h"
...@@ -46,6 +47,7 @@ typedef enum ObjectClasses ...@@ -46,6 +47,7 @@ typedef enum ObjectClasses
OCLASS_PROC, /* pg_proc */ OCLASS_PROC, /* pg_proc */
OCLASS_TYPE, /* pg_type */ OCLASS_TYPE, /* pg_type */
OCLASS_CONSTRAINT, /* pg_constraint */ OCLASS_CONSTRAINT, /* pg_constraint */
OCLASS_DEFAULT, /* pg_attrdef */
OCLASS_LANGUAGE, /* pg_language */ OCLASS_LANGUAGE, /* pg_language */
OCLASS_OPERATOR, /* pg_operator */ OCLASS_OPERATOR, /* pg_operator */
OCLASS_REWRITE, /* pg_rewrite */ OCLASS_REWRITE, /* pg_rewrite */
...@@ -59,6 +61,7 @@ static bool recursiveDeletion(const ObjectAddress *object, ...@@ -59,6 +61,7 @@ static bool recursiveDeletion(const ObjectAddress *object,
static void doDeletion(const ObjectAddress *object); static void doDeletion(const ObjectAddress *object);
static ObjectClasses getObjectClass(const ObjectAddress *object); static ObjectClasses getObjectClass(const ObjectAddress *object);
static char *getObjectDescription(const ObjectAddress *object); static char *getObjectDescription(const ObjectAddress *object);
static void getRelationDescription(StringInfo buffer, Oid relid);
/* /*
...@@ -285,7 +288,7 @@ recursiveDeletion(const ObjectAddress *object, ...@@ -285,7 +288,7 @@ recursiveDeletion(const ObjectAddress *object,
* RESTRICT case. (However, normal dependencies on the * RESTRICT case. (However, normal dependencies on the
* component object could still cause failure.) * component object could still cause failure.)
*/ */
elog(DEBUG1, "Drop internally cascades to %s", elog(DEBUG1, "Drop auto-cascades to %s",
getObjectDescription(&otherObject)); getObjectDescription(&otherObject));
if (!recursiveDeletion(&otherObject, behavior, if (!recursiveDeletion(&otherObject, behavior,
...@@ -392,6 +395,10 @@ doDeletion(const ObjectAddress *object) ...@@ -392,6 +395,10 @@ doDeletion(const ObjectAddress *object)
RemoveConstraintById(object->objectId); RemoveConstraintById(object->objectId);
break; break;
case OCLASS_DEFAULT:
RemoveAttrDefaultById(object->objectId);
break;
case OCLASS_LANGUAGE: case OCLASS_LANGUAGE:
DropProceduralLanguageById(object->objectId); DropProceduralLanguageById(object->objectId);
break; break;
...@@ -425,6 +432,7 @@ getObjectClass(const ObjectAddress *object) ...@@ -425,6 +432,7 @@ getObjectClass(const ObjectAddress *object)
{ {
static bool reloids_initialized = false; static bool reloids_initialized = false;
static Oid reloid_pg_constraint; static Oid reloid_pg_constraint;
static Oid reloid_pg_attrdef;
static Oid reloid_pg_language; static Oid reloid_pg_language;
static Oid reloid_pg_operator; static Oid reloid_pg_operator;
static Oid reloid_pg_rewrite; static Oid reloid_pg_rewrite;
...@@ -456,6 +464,7 @@ getObjectClass(const ObjectAddress *object) ...@@ -456,6 +464,7 @@ getObjectClass(const ObjectAddress *object)
if (!reloids_initialized) if (!reloids_initialized)
{ {
reloid_pg_constraint = get_system_catalog_relid(ConstraintRelationName); reloid_pg_constraint = get_system_catalog_relid(ConstraintRelationName);
reloid_pg_attrdef = get_system_catalog_relid(AttrDefaultRelationName);
reloid_pg_language = get_system_catalog_relid(LanguageRelationName); reloid_pg_language = get_system_catalog_relid(LanguageRelationName);
reloid_pg_operator = get_system_catalog_relid(OperatorRelationName); reloid_pg_operator = get_system_catalog_relid(OperatorRelationName);
reloid_pg_rewrite = get_system_catalog_relid(RewriteRelationName); reloid_pg_rewrite = get_system_catalog_relid(RewriteRelationName);
...@@ -468,6 +477,11 @@ getObjectClass(const ObjectAddress *object) ...@@ -468,6 +477,11 @@ getObjectClass(const ObjectAddress *object)
Assert(object->objectSubId == 0); Assert(object->objectSubId == 0);
return OCLASS_CONSTRAINT; return OCLASS_CONSTRAINT;
} }
if (object->classId == reloid_pg_attrdef)
{
Assert(object->objectSubId == 0);
return OCLASS_DEFAULT;
}
if (object->classId == reloid_pg_language) if (object->classId == reloid_pg_language)
{ {
Assert(object->objectSubId == 0); Assert(object->objectSubId == 0);
...@@ -509,63 +523,12 @@ getObjectDescription(const ObjectAddress *object) ...@@ -509,63 +523,12 @@ getObjectDescription(const ObjectAddress *object)
switch (getObjectClass(object)) switch (getObjectClass(object))
{ {
case OCLASS_CLASS: case OCLASS_CLASS:
{ getRelationDescription(&buffer, object->objectId);
HeapTuple relTup;
Form_pg_class relForm;
relTup = SearchSysCache(RELOID,
ObjectIdGetDatum(object->objectId),
0, 0, 0);
if (!HeapTupleIsValid(relTup))
elog(ERROR, "getObjectDescription: Relation %u does not exist",
object->objectId);
relForm = (Form_pg_class) GETSTRUCT(relTup);
switch (relForm->relkind)
{
case RELKIND_RELATION:
appendStringInfo(&buffer, "table %s",
NameStr(relForm->relname));
break;
case RELKIND_INDEX:
appendStringInfo(&buffer, "index %s",
NameStr(relForm->relname));
break;
case RELKIND_SPECIAL:
appendStringInfo(&buffer, "special system relation %s",
NameStr(relForm->relname));
break;
case RELKIND_SEQUENCE:
appendStringInfo(&buffer, "sequence %s",
NameStr(relForm->relname));
break;
case RELKIND_UNCATALOGED:
appendStringInfo(&buffer, "uncataloged table %s",
NameStr(relForm->relname));
break;
case RELKIND_TOASTVALUE:
appendStringInfo(&buffer, "toast table %s",
NameStr(relForm->relname));
break;
case RELKIND_VIEW:
appendStringInfo(&buffer, "view %s",
NameStr(relForm->relname));
break;
default:
/* shouldn't get here */
appendStringInfo(&buffer, "relation %s",
NameStr(relForm->relname));
break;
}
if (object->objectSubId != 0) if (object->objectSubId != 0)
appendStringInfo(&buffer, " column %s", appendStringInfo(&buffer, " column %s",
get_attname(object->objectId, get_attname(object->objectId,
object->objectSubId)); object->objectSubId));
ReleaseSysCache(relTup);
break; break;
}
case OCLASS_PROC: case OCLASS_PROC:
/* XXX could improve on this */ /* XXX could improve on this */
...@@ -614,17 +577,61 @@ getObjectDescription(const ObjectAddress *object) ...@@ -614,17 +577,61 @@ getObjectDescription(const ObjectAddress *object)
con = (Form_pg_constraint) GETSTRUCT(tup); con = (Form_pg_constraint) GETSTRUCT(tup);
if (OidIsValid(con->conrelid))
{
appendStringInfo(&buffer, "constraint %s on ",
NameStr(con->conname));
getRelationDescription(&buffer, con->conrelid);
}
else
{
appendStringInfo(&buffer, "constraint %s", appendStringInfo(&buffer, "constraint %s",
NameStr(con->conname)); NameStr(con->conname));
if (OidIsValid(con->conrelid)) }
appendStringInfo(&buffer, " on table %s",
get_rel_name(con->conrelid));
systable_endscan(rcscan); systable_endscan(rcscan);
heap_close(conDesc, AccessShareLock); heap_close(conDesc, AccessShareLock);
break; break;
} }
case OCLASS_DEFAULT:
{
Relation attrdefDesc;
ScanKeyData skey[1];
SysScanDesc adscan;
HeapTuple tup;
Form_pg_attrdef attrdef;
ObjectAddress colobject;
attrdefDesc = heap_openr(AttrDefaultRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey[0], 0x0,
ObjectIdAttributeNumber, F_OIDEQ,
ObjectIdGetDatum(object->objectId));
adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndex, true,
SnapshotNow, 1, skey);
tup = systable_getnext(adscan);
if (!HeapTupleIsValid(tup))
elog(ERROR, "getObjectDescription: Default %u does not exist",
object->objectId);
attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
colobject.classId = RelOid_pg_class;
colobject.objectId = attrdef->adrelid;
colobject.objectSubId = attrdef->adnum;
appendStringInfo(&buffer, "default for %s",
getObjectDescription(&colobject));
systable_endscan(adscan);
heap_close(attrdefDesc, AccessShareLock);
break;
}
case OCLASS_LANGUAGE: case OCLASS_LANGUAGE:
{ {
HeapTuple langTup; HeapTuple langTup;
...@@ -672,11 +679,9 @@ getObjectDescription(const ObjectAddress *object) ...@@ -672,11 +679,9 @@ getObjectDescription(const ObjectAddress *object)
rule = (Form_pg_rewrite) GETSTRUCT(tup); rule = (Form_pg_rewrite) GETSTRUCT(tup);
appendStringInfo(&buffer, "rule %s", appendStringInfo(&buffer, "rule %s on ",
NameStr(rule->rulename)); NameStr(rule->rulename));
if (OidIsValid(rule->ev_class)) getRelationDescription(&buffer, rule->ev_class);
appendStringInfo(&buffer, " on table %s",
get_rel_name(rule->ev_class));
systable_endscan(rcscan); systable_endscan(rcscan);
heap_close(ruleDesc, AccessShareLock); heap_close(ruleDesc, AccessShareLock);
...@@ -708,11 +713,9 @@ getObjectDescription(const ObjectAddress *object) ...@@ -708,11 +713,9 @@ getObjectDescription(const ObjectAddress *object)
trig = (Form_pg_trigger) GETSTRUCT(tup); trig = (Form_pg_trigger) GETSTRUCT(tup);
appendStringInfo(&buffer, "trigger %s", appendStringInfo(&buffer, "trigger %s on ",
NameStr(trig->tgname)); NameStr(trig->tgname));
if (OidIsValid(trig->tgrelid)) getRelationDescription(&buffer, trig->tgrelid);
appendStringInfo(&buffer, " on table %s",
get_rel_name(trig->tgrelid));
systable_endscan(tgscan); systable_endscan(tgscan);
heap_close(trigDesc, AccessShareLock); heap_close(trigDesc, AccessShareLock);
...@@ -729,3 +732,60 @@ getObjectDescription(const ObjectAddress *object) ...@@ -729,3 +732,60 @@ getObjectDescription(const ObjectAddress *object)
return buffer.data; return buffer.data;
} }
/*
* subroutine for getObjectDescription: describe a relation
*/
static void
getRelationDescription(StringInfo buffer, Oid relid)
{
HeapTuple relTup;
Form_pg_class relForm;
relTup = SearchSysCache(RELOID,
ObjectIdGetDatum(relid),
0, 0, 0);
if (!HeapTupleIsValid(relTup))
elog(ERROR, "getObjectDescription: Relation %u does not exist",
relid);
relForm = (Form_pg_class) GETSTRUCT(relTup);
switch (relForm->relkind)
{
case RELKIND_RELATION:
appendStringInfo(buffer, "table %s",
NameStr(relForm->relname));
break;
case RELKIND_INDEX:
appendStringInfo(buffer, "index %s",
NameStr(relForm->relname));
break;
case RELKIND_SPECIAL:
appendStringInfo(buffer, "special system relation %s",
NameStr(relForm->relname));
break;
case RELKIND_SEQUENCE:
appendStringInfo(buffer, "sequence %s",
NameStr(relForm->relname));
break;
case RELKIND_UNCATALOGED:
appendStringInfo(buffer, "uncataloged table %s",
NameStr(relForm->relname));
break;
case RELKIND_TOASTVALUE:
appendStringInfo(buffer, "toast table %s",
NameStr(relForm->relname));
break;
case RELKIND_VIEW:
appendStringInfo(buffer, "view %s",
NameStr(relForm->relname));
break;
default:
/* shouldn't get here */
appendStringInfo(buffer, "relation %s",
NameStr(relForm->relname));
break;
}
ReleaseSysCache(relTup);
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.206 2002/07/14 21:08:08 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.207 2002/07/15 16:33:31 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -75,7 +75,6 @@ static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin); ...@@ -75,7 +75,6 @@ static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin);
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
static void StoreConstraints(Relation rel, TupleDesc tupdesc); static void StoreConstraints(Relation rel, TupleDesc tupdesc);
static void SetRelationNumChecks(Relation rel, int numchecks); static void SetRelationNumChecks(Relation rel, int numchecks);
static void RemoveDefaults(Relation rel);
static void RemoveStatistics(Relation rel); static void RemoveStatistics(Relation rel);
...@@ -767,18 +766,18 @@ static void ...@@ -767,18 +766,18 @@ static void
RelationRemoveInheritance(Relation relation) RelationRemoveInheritance(Relation relation)
{ {
Relation catalogRelation; Relation catalogRelation;
HeapTuple tuple;
SysScanDesc scan; SysScanDesc scan;
ScanKeyData entry; ScanKeyData key;
HeapTuple tuple;
catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock); catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&entry, 0x0, ScanKeyEntryInitialize(&key, 0x0,
Anum_pg_inherits_inhrelid, F_OIDEQ, Anum_pg_inherits_inhrelid, F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation))); ObjectIdGetDatum(RelationGetRelid(relation)));
scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndex, true, scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndex, true,
SnapshotNow, 1, &entry); SnapshotNow, 1, &key);
while (HeapTupleIsValid(tuple = systable_getnext(scan))) while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{ {
...@@ -859,6 +858,125 @@ DeleteAttributeTuples(Oid relid) ...@@ -859,6 +858,125 @@ DeleteAttributeTuples(Oid relid)
heap_close(attrel, RowExclusiveLock); heap_close(attrel, RowExclusiveLock);
} }
/*
* RemoveAttrDefault
*
* If the specified relation/attribute has a default, remove it.
* (If no default, raise error if complain is true, else return quietly.)
*/
void
RemoveAttrDefault(Oid relid, AttrNumber attnum,
DropBehavior behavior, bool complain)
{
Relation attrdef_rel;
ScanKeyData scankeys[2];
SysScanDesc scan;
HeapTuple tuple;
bool found = false;
attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0,
Anum_pg_attrdef_adrelid, F_OIDEQ,
ObjectIdGetDatum(relid));
ScanKeyEntryInitialize(&scankeys[1], 0x0,
Anum_pg_attrdef_adnum, F_INT2EQ,
Int16GetDatum(attnum));
scan = systable_beginscan(attrdef_rel, AttrDefaultIndex, true,
SnapshotNow, 2, scankeys);
/* There should be at most one matching tuple, but we loop anyway */
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
{
ObjectAddress object;
object.classId = RelationGetRelid(attrdef_rel);
object.objectId = tuple->t_data->t_oid;
object.objectSubId = 0;
performDeletion(&object, behavior);
found = true;
}
systable_endscan(scan);
heap_close(attrdef_rel, RowExclusiveLock);
if (complain && !found)
elog(ERROR, "RemoveAttrDefault: no default found for rel %u attnum %d",
relid, attnum);
}
/*
* RemoveAttrDefaultById
*
* Remove a pg_attrdef entry specified by OID. This is the guts of
* attribute-default removal. Note it should be called via performDeletion,
* not directly.
*/
void
RemoveAttrDefaultById(Oid attrdefId)
{
Relation attrdef_rel;
Relation attr_rel;
ScanKeyData scankeys[1];
SysScanDesc scan;
HeapTuple tuple;
Oid myrelid;
AttrNumber myattnum;
/* Grab an appropriate lock on the pg_attrdef relation */
attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0,
ObjectIdAttributeNumber, F_OIDEQ,
ObjectIdGetDatum(attrdefId));
scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndex, true,
SnapshotNow, 1, scankeys);
tuple = systable_getnext(scan);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "RemoveAttrDefaultById: cache lookup failed for attrdef %u",
attrdefId);
myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
simple_heap_delete(attrdef_rel, &tuple->t_self);
systable_endscan(scan);
heap_close(attrdef_rel, RowExclusiveLock);
/* Fix the pg_attribute row */
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopy(ATTNUM,
ObjectIdGetDatum(myrelid),
Int16GetDatum(myattnum),
0, 0);
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "RemoveAttrDefaultById: cache lookup failed for rel %u attr %d",
myrelid, myattnum);
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
simple_heap_update(attr_rel, &tuple->t_self, tuple);
/* keep the system catalog indices current */
if (RelationGetForm(attr_rel)->relhasindex)
{
Relation idescs[Num_pg_attr_indices];
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_attr_indices, attr_rel, tuple);
CatalogCloseIndices(Num_pg_attr_indices, idescs);
}
heap_close(attr_rel, RowExclusiveLock);
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* heap_drop_with_catalog - removes specified relation from catalogs * heap_drop_with_catalog - removes specified relation from catalogs
* *
...@@ -866,7 +984,7 @@ DeleteAttributeTuples(Oid relid) ...@@ -866,7 +984,7 @@ DeleteAttributeTuples(Oid relid)
* 2) flush relation buffers from bufmgr * 2) flush relation buffers from bufmgr
* 3) remove inheritance information * 3) remove inheritance information
* 4) remove pg_statistic tuples * 4) remove pg_statistic tuples
* 5) remove pg_attribute tuples and related items * 5) remove pg_attribute tuples
* 6) remove pg_class tuple * 6) remove pg_class tuple
* 7) unlink relation file * 7) unlink relation file
* *
...@@ -908,12 +1026,10 @@ heap_drop_with_catalog(Oid rid) ...@@ -908,12 +1026,10 @@ heap_drop_with_catalog(Oid rid)
RemoveStatistics(rel); RemoveStatistics(rel);
/* /*
* delete attribute tuples and associated defaults * delete attribute tuples
*/ */
DeleteAttributeTuples(RelationGetRelid(rel)); DeleteAttributeTuples(RelationGetRelid(rel));
RemoveDefaults(rel);
/* /*
* delete relation tuple * delete relation tuple
*/ */
...@@ -957,6 +1073,9 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin) ...@@ -957,6 +1073,9 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
Relation attridescs[Num_pg_attr_indices]; Relation attridescs[Num_pg_attr_indices];
HeapTuple atttup; HeapTuple atttup;
Form_pg_attribute attStruct; Form_pg_attribute attStruct;
Oid attrdefOid;
ObjectAddress colobject,
defobject;
/* /*
* Need to construct source equivalent of given node-string. * Need to construct source equivalent of given node-string.
...@@ -971,21 +1090,33 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin) ...@@ -971,21 +1090,33 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
RelationGetRelid(rel)), RelationGetRelid(rel)),
false); false);
/*
* Make the pg_attrdef entry.
*/
values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel); values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
values[Anum_pg_attrdef_adnum - 1] = attnum; values[Anum_pg_attrdef_adnum - 1] = attnum;
values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin, values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin,
CStringGetDatum(adbin)); CStringGetDatum(adbin));
values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin, values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin,
CStringGetDatum(adsrc)); CStringGetDatum(adsrc));
adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock); adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
tuple = heap_formtuple(adrel->rd_att, values, nulls); tuple = heap_formtuple(adrel->rd_att, values, nulls);
simple_heap_insert(adrel, tuple); attrdefOid = simple_heap_insert(adrel, tuple);
CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
idescs); idescs);
CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple); CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
CatalogCloseIndices(Num_pg_attrdef_indices, idescs); CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
defobject.classId = RelationGetRelid(adrel);
defobject.objectId = attrdefOid;
defobject.objectSubId = 0;
heap_close(adrel, RowExclusiveLock); heap_close(adrel, RowExclusiveLock);
/* now can free some of the stuff allocated above */
pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1])); pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1])); pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
heap_freetuple(tuple); heap_freetuple(tuple);
...@@ -1016,6 +1147,16 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin) ...@@ -1016,6 +1147,16 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
} }
heap_close(attrrel, RowExclusiveLock); heap_close(attrrel, RowExclusiveLock);
heap_freetuple(atttup); heap_freetuple(atttup);
/*
* Make a dependency so that the pg_attrdef entry goes away if the
* column (or whole table) is deleted.
*/
colobject.classId = RelOid_pg_class;
colobject.objectId = RelationGetRelid(rel);
colobject.objectSubId = attnum;
recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
} }
/* /*
...@@ -1497,29 +1638,6 @@ cookDefault(ParseState *pstate, ...@@ -1497,29 +1638,6 @@ cookDefault(ParseState *pstate,
} }
static void
RemoveAttrDefaults(Relation rel)
{
Relation adrel;
HeapScanDesc adscan;
ScanKeyData key;
HeapTuple tup;
adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(rel)));
adscan = heap_beginscan(adrel, SnapshotNow, 1, &key);
while ((tup = heap_getnext(adscan, ForwardScanDirection)) != NULL)
simple_heap_delete(adrel, &tup->t_self);
heap_endscan(adscan);
heap_close(adrel, RowExclusiveLock);
}
/* /*
* Removes all constraints on a relation that match the given name. * Removes all constraints on a relation that match the given name.
* *
...@@ -1577,18 +1695,6 @@ RemoveRelConstraints(Relation rel, const char *constrName, ...@@ -1577,18 +1695,6 @@ RemoveRelConstraints(Relation rel, const char *constrName,
return ndeleted; return ndeleted;
} }
static void
RemoveDefaults(Relation rel)
{
TupleConstr *constr = rel->rd_att->constr;
/*
* We can skip looking at pg_attrdef if there are no defaults recorded
* in the Relation.
*/
if (constr && constr->num_defval > 0)
RemoveAttrDefaults(rel);
}
static void static void
RemoveStatistics(Relation rel) RemoveStatistics(Relation rel)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.96 2002/07/12 18:43:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.97 2002/07/15 16:33:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,13 +42,13 @@ char *Name_pg_amproc_indices[Num_pg_amproc_indices] = ...@@ -42,13 +42,13 @@ char *Name_pg_amproc_indices[Num_pg_amproc_indices] =
char *Name_pg_attr_indices[Num_pg_attr_indices] = char *Name_pg_attr_indices[Num_pg_attr_indices] =
{AttributeRelidNameIndex, AttributeRelidNumIndex}; {AttributeRelidNameIndex, AttributeRelidNumIndex};
char *Name_pg_attrdef_indices[Num_pg_attrdef_indices] = char *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
{AttrDefaultIndex}; {AttrDefaultIndex, AttrDefaultOidIndex};
char *Name_pg_class_indices[Num_pg_class_indices] = char *Name_pg_class_indices[Num_pg_class_indices] =
{ClassNameNspIndex, ClassOidIndex}; {ClassNameNspIndex, ClassOidIndex};
char *Name_pg_constraint_indices[Num_pg_constraint_indices] = char *Name_pg_constraint_indices[Num_pg_constraint_indices] =
{ConstraintNameNspIndex, ConstraintOidIndex, ConstraintRelidIndex}; {ConstraintNameNspIndex, ConstraintOidIndex, ConstraintRelidIndex};
char *Name_pg_conversion_indices[Num_pg_conversion_indices] = char *Name_pg_conversion_indices[Num_pg_conversion_indices] =
{ConversionNameNspIndex, ConversionDefaultIndex}; {ConversionDefaultIndex, ConversionNameNspIndex, ConversionOidIndex};
char *Name_pg_database_indices[Num_pg_database_indices] = char *Name_pg_database_indices[Num_pg_database_indices] =
{DatabaseNameIndex, DatabaseOidIndex}; {DatabaseNameIndex, DatabaseOidIndex};
char *Name_pg_depend_indices[Num_pg_depend_indices] = char *Name_pg_depend_indices[Num_pg_depend_indices] =
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.20 2002/07/12 18:43:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.21 2002/07/15 16:33:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/indexing.h" #include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_constraint.h" #include "catalog/pg_constraint.h"
#include "catalog/pg_inherits.h" #include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h" #include "catalog/pg_namespace.h"
...@@ -57,7 +56,6 @@ static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno); ...@@ -57,7 +56,6 @@ static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
static void StoreCatalogInheritance(Oid relationId, List *supers); static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema); static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
static void drop_default(Oid relid, int16 attnum);
static void CheckTupleType(Form_pg_class tuple_class); static void CheckTupleType(Form_pg_class tuple_class);
static bool needs_toast_table(Relation rel); static bool needs_toast_table(Relation rel);
static void validateForeignKeyConstraint(FkConstraint *fkconstraint, static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
...@@ -2080,14 +2078,18 @@ AlterTableAlterColumnDefault(Oid myrelid, ...@@ -2080,14 +2078,18 @@ AlterTableAlterColumnDefault(Oid myrelid,
attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum; attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
/*
* Remove any old default for the column. We use RESTRICT here for
* safety, but at present we do not expect anything to depend on the
* default.
*/
RemoveAttrDefault(myrelid, attnum, DROP_RESTRICT, false);
if (newDefault) if (newDefault)
{ {
/* SET DEFAULT */ /* SET DEFAULT */
RawColumnDefault *rawEnt; RawColumnDefault *rawEnt;
/* Get rid of the old one first */
drop_default(myrelid, attnum);
rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
rawEnt->attnum = attnum; rawEnt->attnum = attnum;
rawEnt->raw_default = newDefault; rawEnt->raw_default = newDefault;
...@@ -2098,73 +2100,10 @@ AlterTableAlterColumnDefault(Oid myrelid, ...@@ -2098,73 +2100,10 @@ AlterTableAlterColumnDefault(Oid myrelid,
*/ */
AddRelationRawConstraints(rel, makeList1(rawEnt), NIL); AddRelationRawConstraints(rel, makeList1(rawEnt), NIL);
} }
else
{
/* DROP DEFAULT */
Relation attr_rel;
/* Fix the pg_attribute row */
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopy(ATTNAME,
ObjectIdGetDatum(myrelid),
PointerGetDatum(colName),
0, 0);
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = FALSE;
simple_heap_update(attr_rel, &tuple->t_self, tuple);
/* keep the system catalog indices current */
if (RelationGetForm(attr_rel)->relhasindex)
{
Relation idescs[Num_pg_attr_indices];
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_attr_indices, attr_rel, tuple);
CatalogCloseIndices(Num_pg_attr_indices, idescs);
}
heap_close(attr_rel, RowExclusiveLock);
/* get rid of actual default definition in pg_attrdef */
drop_default(myrelid, attnum);
}
heap_close(rel, NoLock); heap_close(rel, NoLock);
} }
static void
drop_default(Oid relid, int16 attnum)
{
ScanKeyData scankeys[2];
HeapScanDesc scan;
Relation attrdef_rel;
HeapTuple tuple;
attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0,
Anum_pg_attrdef_adrelid, F_OIDEQ,
ObjectIdGetDatum(relid));
ScanKeyEntryInitialize(&scankeys[1], 0x0,
Anum_pg_attrdef_adnum, F_INT2EQ,
Int16GetDatum(attnum));
scan = heap_beginscan(attrdef_rel, SnapshotNow, 2, scankeys);
if ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
simple_heap_delete(attrdef_rel, &tuple->t_self);
heap_endscan(scan);
heap_close(attrdef_rel, NoLock);
}
/* /*
* ALTER TABLE ALTER COLUMN SET STATISTICS / STORAGE * ALTER TABLE ALTER COLUMN SET STATISTICS / STORAGE
*/ */
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.139 2002/07/12 18:43:19 tgl Exp $ * $Id: catversion.h,v 1.140 2002/07/15 16:33:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200207112 #define CATALOG_VERSION_NO 200207141
#endif #endif
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: heap.h,v 1.53 2002/07/14 21:08:08 tgl Exp $ * $Id: heap.h,v 1.54 2002/07/15 16:33:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -63,6 +63,9 @@ extern int RemoveRelConstraints(Relation rel, const char *constrName, ...@@ -63,6 +63,9 @@ extern int RemoveRelConstraints(Relation rel, const char *constrName,
extern void DeleteRelationTuple(Oid relid); extern void DeleteRelationTuple(Oid relid);
extern void DeleteAttributeTuples(Oid relid); extern void DeleteAttributeTuples(Oid relid);
extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
DropBehavior behavior, bool complain);
extern void RemoveAttrDefaultById(Oid attrdefId);
extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
bool relhasoids); bool relhasoids);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: indexing.h,v 1.69 2002/07/12 18:43:19 tgl Exp $ * $Id: indexing.h,v 1.70 2002/07/15 16:33:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,10 +25,10 @@ ...@@ -25,10 +25,10 @@
#define Num_pg_amop_indices 2 #define Num_pg_amop_indices 2
#define Num_pg_amproc_indices 1 #define Num_pg_amproc_indices 1
#define Num_pg_attr_indices 2 #define Num_pg_attr_indices 2
#define Num_pg_attrdef_indices 1 #define Num_pg_attrdef_indices 2
#define Num_pg_class_indices 2 #define Num_pg_class_indices 2
#define Num_pg_constraint_indices 3 #define Num_pg_constraint_indices 3
#define Num_pg_conversion_indices 2 #define Num_pg_conversion_indices 3
#define Num_pg_database_indices 2 #define Num_pg_database_indices 2
#define Num_pg_depend_indices 2 #define Num_pg_depend_indices 2
#define Num_pg_description_indices 1 #define Num_pg_description_indices 1
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#define AmNameIndex "pg_am_name_index" #define AmNameIndex "pg_am_name_index"
#define AmOidIndex "pg_am_oid_index" #define AmOidIndex "pg_am_oid_index"
#define AttrDefaultIndex "pg_attrdef_adrelid_adnum_index" #define AttrDefaultIndex "pg_attrdef_adrelid_adnum_index"
#define AttrDefaultOidIndex "pg_attrdef_oid_index"
#define AttributeRelidNameIndex "pg_attribute_relid_attnam_index" #define AttributeRelidNameIndex "pg_attribute_relid_attnam_index"
#define AttributeRelidNumIndex "pg_attribute_relid_attnum_index" #define AttributeRelidNumIndex "pg_attribute_relid_attnum_index"
#define ClassNameNspIndex "pg_class_relname_nsp_index" #define ClassNameNspIndex "pg_class_relname_nsp_index"
...@@ -66,6 +67,7 @@ ...@@ -66,6 +67,7 @@
#define ConstraintRelidIndex "pg_constraint_conrelid_index" #define ConstraintRelidIndex "pg_constraint_conrelid_index"
#define ConversionDefaultIndex "pg_conversion_default_index" #define ConversionDefaultIndex "pg_conversion_default_index"
#define ConversionNameNspIndex "pg_conversion_name_nsp_index" #define ConversionNameNspIndex "pg_conversion_name_nsp_index"
#define ConversionOidIndex "pg_conversion_oid_index"
#define DatabaseNameIndex "pg_database_datname_index" #define DatabaseNameIndex "pg_database_datname_index"
#define DatabaseOidIndex "pg_database_oid_index" #define DatabaseOidIndex "pg_database_oid_index"
#define DependDependerIndex "pg_depend_depender_index" #define DependDependerIndex "pg_depend_depender_index"
...@@ -161,6 +163,7 @@ DECLARE_UNIQUE_INDEX(pg_amop_opc_opr_index on pg_amop using btree(amopclaid oid_ ...@@ -161,6 +163,7 @@ DECLARE_UNIQUE_INDEX(pg_amop_opc_opr_index on pg_amop using btree(amopclaid oid_
DECLARE_UNIQUE_INDEX(pg_amop_opc_strategy_index on pg_amop using btree(amopclaid oid_ops, amopstrategy int2_ops)); DECLARE_UNIQUE_INDEX(pg_amop_opc_strategy_index on pg_amop using btree(amopclaid oid_ops, amopstrategy int2_ops));
DECLARE_UNIQUE_INDEX(pg_amproc_opc_procnum_index on pg_amproc using btree(amopclaid oid_ops, amprocnum int2_ops)); DECLARE_UNIQUE_INDEX(pg_amproc_opc_procnum_index on pg_amproc using btree(amopclaid oid_ops, amprocnum int2_ops));
DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops)); DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index on pg_attrdef using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops)); DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops));
DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops)); DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops));
...@@ -173,6 +176,7 @@ DECLARE_UNIQUE_INDEX(pg_constraint_oid_index on pg_constraint using btree(oid oi ...@@ -173,6 +176,7 @@ DECLARE_UNIQUE_INDEX(pg_constraint_oid_index on pg_constraint using btree(oid oi
/* This following index is not used for a cache and is not unique */ /* This following index is not used for a cache and is not unique */
DECLARE_INDEX(pg_conversion_default_index on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops)); DECLARE_INDEX(pg_conversion_default_index on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops));
DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index on pg_conversion using btree(conname name_ops, connamespace oid_ops)); DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index on pg_conversion using btree(conname name_ops, connamespace oid_ops));
DECLARE_UNIQUE_INDEX(pg_conversion_oid_index on pg_conversion using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_database_datname_index on pg_database using btree(datname name_ops)); DECLARE_UNIQUE_INDEX(pg_database_datname_index on pg_database using btree(datname name_ops));
DECLARE_UNIQUE_INDEX(pg_database_oid_index on pg_database using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_database_oid_index on pg_database using btree(oid oid_ops));
/* This following index is not used for a cache and is not unique */ /* This following index is not used for a cache and is not unique */
......
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* pg_attrdef.h * pg_attrdef.h
* definition of the system "attribute defaults" relation (pg_attrdef)
* along with the relation's initial contents.
* *
* *
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_attrdef.h,v 1.13 2002/07/15 16:33:32 tgl Exp $
*
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
* information from the DATA() statements. * information from the DATA() statements.
...@@ -27,7 +31,7 @@ ...@@ -27,7 +31,7 @@
* typedef struct FormData_pg_attrdef * typedef struct FormData_pg_attrdef
* ---------------- * ----------------
*/ */
CATALOG(pg_attrdef) BKI_WITHOUT_OIDS CATALOG(pg_attrdef)
{ {
Oid adrelid; Oid adrelid;
int2 adnum; int2 adnum;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment