Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bb3da43

Browse files
committed
Allow use of table rowtypes directly as column types of other tables.
Instead of prohibiting that, put code into ALTER TABLE to reject ALTERs that would affect other tables' columns. Eventually we will probably want to extend ALTER TABLE to actually do something useful here, but in the meantime it seems wrong to forbid the feature completely just because ALTER isn't fully baked.
1 parent 19e3bdd commit bb3da43

File tree

2 files changed

+98
-16
lines changed

2 files changed

+98
-16
lines changed

src/backend/catalog/heap.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.268 2004/06/06 04:52:55 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.269 2004/06/06 20:30:07 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -416,10 +416,7 @@ CheckAttributeType(const char *attname, Oid atttypid)
416416
* Warn user, but don't fail, if column to be created has UNKNOWN type
417417
* (usually as a result of a 'retrieve into' - jolly)
418418
*
419-
* Refuse any attempt to create a pseudo-type column or one that uses a
420-
* non-standalone composite type. (We could support using table rowtypes
421-
* as attributes, if we were willing to make ALTER TABLE hugely more
422-
* complex, but for now let's limit the damage ...)
419+
* Refuse any attempt to create a pseudo-type column.
423420
*/
424421
if (atttypid == UNKNOWNOID)
425422
ereport(WARNING,
@@ -435,16 +432,6 @@ CheckAttributeType(const char *attname, Oid atttypid)
435432
errmsg("column \"%s\" has pseudo-type %s",
436433
attname, format_type_be(atttypid))));
437434
}
438-
else if (att_typtype == 'c')
439-
{
440-
Oid typrelid = get_typ_typrelid(atttypid);
441-
442-
if (get_rel_relkind(typrelid) != RELKIND_COMPOSITE_TYPE)
443-
ereport(ERROR,
444-
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
445-
errmsg("column \"%s\" has composite type %s",
446-
attname, format_type_be(atttypid))));
447-
}
448435
}
449436

450437
/* --------------------------------

src/backend/commands/tablecmds.c

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.111 2004/06/05 19:48:07 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.112 2004/06/06 20:30:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -194,6 +194,8 @@ static void ATSimpleRecursion(List **wqueue, Relation rel,
194194
AlterTableCmd *cmd, bool recurse);
195195
static void ATOneLevelRecursion(List **wqueue, Relation rel,
196196
AlterTableCmd *cmd);
197+
static void find_composite_type_dependencies(Oid typeOid,
198+
const char *origTblName);
197199
static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
198200
AlterTableCmd *cmd);
199201
static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
@@ -2281,6 +2283,18 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap)
22812283
else
22822284
newrel = NULL;
22832285

2286+
/*
2287+
* If we need to rewrite the table, the operation has to be propagated
2288+
* to tables that use this table's rowtype as a column type.
2289+
*
2290+
* (Eventually this will probably become true for scans as well, but
2291+
* at the moment a composite type does not enforce any constraints,
2292+
* so it's not necessary/appropriate to enforce them just during ALTER.)
2293+
*/
2294+
if (newrel)
2295+
find_composite_type_dependencies(oldrel->rd_rel->reltype,
2296+
RelationGetRelationName(oldrel));
2297+
22842298
/*
22852299
* Generate the constraint and default execution states
22862300
*/
@@ -2606,6 +2620,87 @@ ATOneLevelRecursion(List **wqueue, Relation rel,
26062620
}
26072621
}
26082622

2623+
2624+
/*
2625+
* find_composite_type_dependencies
2626+
*
2627+
* Check to see if a table's rowtype is being used as a column in some
2628+
* other table (possibly nested several levels deep in composite types!).
2629+
* Eventually, we'd like to propagate the check or rewrite operation
2630+
* into other such tables, but for now, just error out if we find any.
2631+
*
2632+
* We assume that functions and views depending on the type are not reasons
2633+
* to reject the ALTER. (How safe is this really?)
2634+
*/
2635+
static void
2636+
find_composite_type_dependencies(Oid typeOid, const char *origTblName)
2637+
{
2638+
Relation depRel;
2639+
ScanKeyData key[2];
2640+
SysScanDesc depScan;
2641+
HeapTuple depTup;
2642+
2643+
/*
2644+
* We scan pg_depend to find those things that depend on the rowtype.
2645+
* (We assume we can ignore refobjsubid for a rowtype.)
2646+
*/
2647+
depRel = relation_openr(DependRelationName, AccessShareLock);
2648+
2649+
ScanKeyInit(&key[0],
2650+
Anum_pg_depend_refclassid,
2651+
BTEqualStrategyNumber, F_OIDEQ,
2652+
ObjectIdGetDatum(RelOid_pg_type));
2653+
ScanKeyInit(&key[1],
2654+
Anum_pg_depend_refobjid,
2655+
BTEqualStrategyNumber, F_OIDEQ,
2656+
ObjectIdGetDatum(typeOid));
2657+
2658+
depScan = systable_beginscan(depRel, DependReferenceIndex, true,
2659+
SnapshotNow, 2, key);
2660+
2661+
while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2662+
{
2663+
Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2664+
Relation rel;
2665+
Form_pg_attribute att;
2666+
2667+
/* Ignore dependees that aren't user columns of relations */
2668+
/* (we assume system columns are never of rowtypes) */
2669+
if (pg_depend->classid != RelOid_pg_class ||
2670+
pg_depend->objsubid <= 0)
2671+
continue;
2672+
2673+
rel = relation_open(pg_depend->objid, AccessShareLock);
2674+
att = rel->rd_att->attrs[pg_depend->objsubid - 1];
2675+
2676+
if (rel->rd_rel->relkind == RELKIND_RELATION)
2677+
{
2678+
ereport(ERROR,
2679+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2680+
errmsg("cannot alter table \"%s\" because column \"%s\".\"%s\" uses its rowtype",
2681+
origTblName,
2682+
RelationGetRelationName(rel),
2683+
NameStr(att->attname))));
2684+
}
2685+
else if (OidIsValid(rel->rd_rel->reltype))
2686+
{
2687+
/*
2688+
* A view or composite type itself isn't a problem, but we must
2689+
* recursively check for indirect dependencies via its rowtype.
2690+
*/
2691+
find_composite_type_dependencies(rel->rd_rel->reltype,
2692+
origTblName);
2693+
}
2694+
2695+
relation_close(rel, AccessShareLock);
2696+
}
2697+
2698+
systable_endscan(depScan);
2699+
2700+
relation_close(depRel, AccessShareLock);
2701+
}
2702+
2703+
26092704
/*
26102705
* ALTER TABLE ADD COLUMN
26112706
*

0 commit comments

Comments
 (0)