diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index 7fd8c92e371b85bd131d6376f7d9993bb5291694..f215c84b93e0c0c73808f36020b071b6302ba95f 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.140 2002/07/12 18:43:12 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.141 2002/07/16 22:12:18 tgl Exp $ --> <appendix id="release"> @@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without worries about funny characters. --> <literallayout><![CDATA[ +Sequences created by SERIAL column definitions now auto-drop with the column Most forms of DROP now support RESTRICT and CASCADE options Recursive SQL functions can be defined User-defined procedural languages can register a validator function to check new functions as they are created diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index a8700c5efd9f8d8dc4701a1bfc674e105436034a..51933d32ede8891df61e5f1be660bb77a4dd3437 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.208 2002/07/16 05:53:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.209 2002/07/16 22:12:18 tgl Exp $ * * * INTERFACE ROUTINES @@ -97,37 +97,37 @@ static void RemoveStatistics(Relation rel); static FormData_pg_attribute a1 = { 0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData), SelfItemPointerAttributeNumber, 0, -1, -1, - false, 'p', false, 'i', false, false + false, 'p', false, 'i', true, false }; static FormData_pg_attribute a2 = { 0, {"oid"}, OIDOID, 0, sizeof(Oid), ObjectIdAttributeNumber, 0, -1, -1, - true, 'p', false, 'i', false, false + true, 'p', false, 'i', true, false }; static FormData_pg_attribute a3 = { 0, {"xmin"}, XIDOID, 0, sizeof(TransactionId), MinTransactionIdAttributeNumber, 0, -1, -1, - true, 'p', false, 'i', false, false + true, 'p', false, 'i', true, false }; static FormData_pg_attribute a4 = { 0, {"cmin"}, CIDOID, 0, sizeof(CommandId), MinCommandIdAttributeNumber, 0, -1, -1, - true, 'p', false, 'i', false, false + true, 'p', false, 'i', true, false }; static FormData_pg_attribute a5 = { 0, {"xmax"}, XIDOID, 0, sizeof(TransactionId), MaxTransactionIdAttributeNumber, 0, -1, -1, - true, 'p', false, 'i', false, false + true, 'p', false, 'i', true, false }; static FormData_pg_attribute a6 = { 0, {"cmax"}, CIDOID, 0, sizeof(CommandId), MaxCommandIdAttributeNumber, 0, -1, -1, - true, 'p', false, 'i', false, false + true, 'p', false, 'i', true, false }; /* @@ -139,7 +139,7 @@ static FormData_pg_attribute a6 = { static FormData_pg_attribute a7 = { 0, {"tableoid"}, OIDOID, 0, sizeof(Oid), TableOidAttributeNumber, 0, -1, -1, - true, 'p', false, 'i', false, false + true, 'p', false, 'i', true, false }; static Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7}; @@ -416,6 +416,8 @@ AddNewAttributeTuples(Oid new_rel_oid, bool hasindex; Relation idescs[Num_pg_attr_indices]; int natts = tupdesc->natts; + ObjectAddress myself, + referenced; /* * open pg_attribute @@ -430,7 +432,8 @@ AddNewAttributeTuples(Oid new_rel_oid, CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs); /* - * first we add the user attributes.. + * First we add the user attributes. This is also a convenient place + * to add dependencies on their datatypes. */ dpp = tupdesc->attrs; for (i = 0; i < natts; i++) @@ -451,11 +454,22 @@ AddNewAttributeTuples(Oid new_rel_oid, CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup); heap_freetuple(tup); + + myself.classId = RelOid_pg_class; + myself.objectId = new_rel_oid; + myself.objectSubId = i+1; + referenced.classId = RelOid_pg_type; + referenced.objectId = (*dpp)->atttypid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + dpp++; } /* - * next we add the system attributes. Skip OID if rel has no OIDs. + * Next we add the system attributes. Skip OID if rel has no OIDs. + * Skip all for a view. We don't bother with making datatype + * dependencies here, since presumably all these types are pinned. */ if (relkind != RELKIND_VIEW) { @@ -493,7 +507,7 @@ AddNewAttributeTuples(Oid new_rel_oid, } /* - * close pg_attribute indices + * clean up */ if (hasindex) CatalogCloseIndices(Num_pg_attr_indices, idescs); diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index be84bf4acf281d2251b71026355aad91ab50bc49..28d7e83f575e8026e191ec2304fd3ebf678ffb5c 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.49 2002/06/20 20:29:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.50 2002/07/16 22:12:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" @@ -53,6 +54,8 @@ AggregateCreate(const char *aggName, Oid procOid; TupleDesc tupDesc; int i; + ObjectAddress myself, + referenced; /* sanity checks */ if (!aggName) @@ -187,4 +190,29 @@ AggregateCreate(const char *aggName, } heap_close(aggdesc, RowExclusiveLock); + + /* + * Create dependencies for the aggregate (above and beyond those + * already made by ProcedureCreate). Note: we don't need an explicit + * dependency on aggTransType since we depend on it indirectly through + * transfn. + */ + myself.classId = RelOid_pg_proc; + myself.objectId = procOid; + myself.objectSubId = 0; + + /* Depends on transition function */ + referenced.classId = RelOid_pg_proc; + referenced.objectId = transfn; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + + /* Depends on final function, if any */ + if (OidIsValid(finalfn)) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = finalfn; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } } diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 41580f2c53fe518a7bbe687d5227484c6dfdf277..96784e73e36f164415ff8a9a49621c17c4622a42 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.2 2002/07/16 05:53:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.3 2002/07/16 22:12:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -198,17 +198,11 @@ CreateConstraintEntry(const char *constraintName, if (OidIsValid(foreignRelId)) { /* - * Register dependency from constraint to foreign relation, + * Register normal dependency from constraint to foreign relation, * or to specific column(s) if any are mentioned. - * - * In normal case of two separate relations, make this a NORMAL - * dependency (so dropping the FK table would require CASCADE). - * However, for a self-reference just make it AUTO. */ - DependencyType deptype; ObjectAddress relobject; - deptype = (foreignRelId == relId) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL; relobject.classId = RelOid_pg_class; relobject.objectId = foreignRelId; if (foreignNKeys > 0) @@ -217,14 +211,14 @@ CreateConstraintEntry(const char *constraintName, { relobject.objectSubId = foreignKey[i]; - recordDependencyOn(&conobject, &relobject, deptype); + recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL); } } else { relobject.objectSubId = 0; - recordDependencyOn(&conobject, &relobject, deptype); + recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL); } } diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 75a1ba01c4e44c1c7eaabe02e6f6c15440cd73c6..7319cec682e24bcb8518a188c0d4d2a6d2b48be1 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.2 2002/07/16 05:53:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.3 2002/07/16 22:12:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -121,6 +121,43 @@ recordMultipleDependencies(const ObjectAddress *depender, heap_close(dependDesc, RowExclusiveLock); } +/* + * deleteDependencyRecordsFor -- delete all records with given depender + * classId/objectId. + * + * This is used when redefining an existing object. Links leading to the + * object do not change, and links leading from it will be recreated + * (possibly with some differences from before). + */ +void +deleteDependencyRecordsFor(Oid classId, Oid objectId) +{ + Relation depRel; + ScanKeyData key[2]; + SysScanDesc scan; + HeapTuple tup; + + depRel = heap_openr(DependRelationName, RowExclusiveLock); + + ScanKeyEntryInitialize(&key[0], 0x0, + Anum_pg_depend_classid, F_OIDEQ, + ObjectIdGetDatum(classId)); + ScanKeyEntryInitialize(&key[1], 0x0, + Anum_pg_depend_objid, F_OIDEQ, + ObjectIdGetDatum(objectId)); + + scan = systable_beginscan(depRel, DependDependerIndex, true, + SnapshotNow, 2, key); + + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + simple_heap_delete(depRel, &tup->t_self); + } + + systable_endscan(scan); + + heap_close(depRel, RowExclusiveLock); +} /* * isObjectPinned() diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 95eac6bd4ef113c2d3f9bdc9e11508ec54ef887d..09c3f6be76fb8b653b0e68d1d2f059e4b01de20b 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.70 2002/06/20 20:29:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.71 2002/07/16 22:12:18 tgl Exp $ * * NOTES * these routines moved here from commands/define.c and somewhat cleaned up. @@ -19,6 +19,7 @@ #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_operator.h" @@ -56,6 +57,8 @@ static Oid get_other_operator(List *otherOp, Oid leftTypeId, Oid rightTypeId, bool isCommutator); +static void makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid); + /* * Check whether a proposed operator name is legal @@ -271,6 +274,9 @@ OperatorShellMake(const char *operatorName, CatalogCloseIndices(Num_pg_operator_indices, idescs); } + /* Add dependencies for the entry */ + makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc)); + heap_freetuple(tup); /* @@ -659,6 +665,9 @@ OperatorCreate(const char *operatorName, CatalogCloseIndices(Num_pg_operator_indices, idescs); } + /* Add dependencies for the entry */ + makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc)); + heap_close(pg_operator_desc, RowExclusiveLock); /* @@ -893,3 +902,89 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId) heap_close(pg_operator_desc, RowExclusiveLock); } + +/* + * Create dependencies for a new operator (either a freshly inserted + * complete operator, a new shell operator, or a just-updated shell). + * + * NB: the OidIsValid tests in this routine are *all* necessary, in case + * the given operator is a shell. + */ +static void +makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid) +{ + Form_pg_operator oper = (Form_pg_operator) GETSTRUCT(tuple); + ObjectAddress myself, + referenced; + + myself.classId = pg_operator_relid; + myself.objectId = tuple->t_data->t_oid; + myself.objectSubId = 0; + + /* In case we are updating a shell, delete any existing entries */ + deleteDependencyRecordsFor(myself.classId, myself.objectId); + + /* Dependency on left type */ + if (OidIsValid(oper->oprleft)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = oper->oprleft; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Dependency on right type */ + if (OidIsValid(oper->oprright)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = oper->oprright; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Dependency on result type */ + if (OidIsValid(oper->oprresult)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = oper->oprresult; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* + * NOTE: we do not consider the operator to depend on the associated + * operators oprcom, oprnegate, oprlsortop, oprrsortop, oprltcmpop, + * oprgtcmpop. We would not want to delete this operator if those + * go away, but only reset the link fields; which is not a function + * that the dependency code can presently handle. (Something could + * perhaps be done with objectSubId though.) For now, it's okay to + * let those links dangle if a referenced operator is removed. + */ + + /* Dependency on implementation function */ + if (OidIsValid(oper->oprcode)) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = oper->oprcode; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Dependency on restriction selectivity function */ + if (OidIsValid(oper->oprrest)) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = oper->oprrest; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Dependency on join selectivity function */ + if (OidIsValid(oper->oprjoin)) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = oper->oprjoin; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } +} diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index a7e33270063bdf7b9388c66fd476e6a9ef3f586b..18746d9e2196d058b14c3be0990c1f9ecf9e85d2 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.76 2002/06/20 20:29:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.77 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" @@ -76,6 +77,9 @@ ProcedureCreate(const char *procedureName, NameData procname; TupleDesc tupDesc; Oid retval; + bool is_update; + ObjectAddress myself, + referenced; /* * sanity checks @@ -227,6 +231,7 @@ ProcedureCreate(const char *procedureName, simple_heap_update(rel, &tup->t_self, tup); ReleaseSysCache(oldtup); + is_update = true; } else { @@ -237,6 +242,7 @@ ProcedureCreate(const char *procedureName, tup = heap_formtuple(tupDesc, values, nulls); simple_heap_insert(rel, tup); + is_update = false; } /* Need to update indices for either the insert or update case */ @@ -250,6 +256,45 @@ ProcedureCreate(const char *procedureName, } retval = tup->t_data->t_oid; + + /* + * Create dependencies for the new function. If we are updating an + * existing function, first delete any existing pg_depend entries. + */ + if (is_update) + deleteDependencyRecordsFor(RelOid_pg_proc, retval); + + myself.classId = RelOid_pg_proc; + myself.objectId = retval; + myself.objectSubId = 0; + + /* dependency on implementation language */ + referenced.classId = get_system_catalog_relid(LanguageRelationName); + referenced.objectId = languageObjectId; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + + /* dependency on return type */ + if (OidIsValid(returnType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = returnType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* dependency on input types */ + for (i = 0; i < parameterCount; i++) + { + if (OidIsValid(typev[i])) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = typev[i]; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + } + heap_freetuple(tup); heap_close(rel, RowExclusiveLock); diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 56dc320e2ef4416db7fce6b742ee2365c8b9de38..98b613242625b11126c5d8a4208cd0132651edab 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.35 2002/07/12 18:43:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.36 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,6 +49,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) HeapTuple tup; TupleDesc tupDesc; int i; + ObjectAddress myself, + referenced; /* * Check permission @@ -91,7 +93,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) NameListToString(stmt->plvalidator)); } else - valProcOid = 0; + valProcOid = InvalidOid; /* * Insert the new language into pg_language @@ -128,6 +130,28 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) CatalogCloseIndices(Num_pg_language_indices, idescs); } + /* + * Create dependencies for language + */ + myself.classId = RelationGetRelid(rel); + myself.objectId = tup->t_data->t_oid; + myself.objectSubId = 0; + + /* dependency on the PL handler function */ + referenced.classId = RelOid_pg_proc; + referenced.objectId = procOid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + + /* dependency on the validator function, if any */ + if (OidIsValid(valProcOid)) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = valProcOid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + heap_close(rel, RowExclusiveLock); } diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 1d013612da43a6d6225bddd94c580c68b1ab0e64..f8a05b619de484897ddb9e88cec4e34b8ef0627d 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.82 2002/06/20 20:29:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.83 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -124,11 +124,15 @@ DefineSequence(CreateSeqStmt *seq) typnam->setof = FALSE; typnam->arrayBounds = NIL; typnam->typmod = -1; + coldef = makeNode(ColumnDef); coldef->typename = typnam; + coldef->is_not_null = true; coldef->raw_default = NULL; coldef->cooked_default = NULL; - coldef->is_not_null = false; + coldef->constraints = NIL; + coldef->support = NULL; + null[i - 1] = ' '; switch (i) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 099c6351b7f5f4c5e6688aa14d9d1d057f3e2f1e..391adb042254ab7962ead36f1d25ee1f50353fc6 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.22 2002/07/16 05:53:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.23 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -239,6 +239,10 @@ DefineRelation(CreateStmt *stmt, char relkind) * So, the transformation has to be postponed to this final step of * CREATE TABLE. * + * Another task that's conveniently done at this step is to add + * dependency links between columns and supporting relations (such + * as SERIAL sequences). + * * First, scan schema to find new column defaults. */ rawDefaults = NIL; @@ -247,18 +251,35 @@ DefineRelation(CreateStmt *stmt, char relkind) foreach(listptr, schema) { ColumnDef *colDef = lfirst(listptr); - RawColumnDefault *rawEnt; attnum++; - if (colDef->raw_default == NULL) - continue; - Assert(colDef->cooked_default == NULL); + if (colDef->raw_default != NULL) + { + RawColumnDefault *rawEnt; - rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); - rawEnt->attnum = attnum; - rawEnt->raw_default = colDef->raw_default; - rawDefaults = lappend(rawDefaults, rawEnt); + Assert(colDef->cooked_default == NULL); + + rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault)); + rawEnt->attnum = attnum; + rawEnt->raw_default = colDef->raw_default; + rawDefaults = lappend(rawDefaults, rawEnt); + } + + if (colDef->support != NULL) + { + /* Create dependency for supporting relation for this column */ + ObjectAddress colobject, + suppobject; + + colobject.classId = RelOid_pg_class; + colobject.objectId = relationId; + colobject.objectSubId = attnum; + suppobject.classId = RelOid_pg_class; + suppobject.objectId = RangeVarGetRelid(colDef->support, false); + suppobject.objectSubId = 0; + recordDependencyOn(&suppobject, &colobject, DEPENDENCY_INTERNAL); + } } /* @@ -533,6 +554,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, def->raw_default = NULL; def->cooked_default = NULL; def->constraints = NIL; + def->support = NULL; inhSchema = lappend(inhSchema, def); newattno[parent_attno - 1] = ++child_attno; } @@ -1524,6 +1546,8 @@ AlterTableAddColumn(Oid myrelid, HeapTuple typeTuple; Form_pg_type tform; int attndims; + ObjectAddress myself, + referenced; /* * Grab an exclusive lock on the target table, which we will NOT @@ -1697,6 +1721,17 @@ AlterTableAddColumn(Oid myrelid, heap_close(rel, NoLock); /* close rel but keep lock! */ + /* + * Add datatype dependency for the new column. + */ + myself.classId = RelOid_pg_class; + myself.objectId = myrelid; + myself.objectSubId = i; + referenced.classId = RelOid_pg_type; + referenced.objectId = attribute->atttypid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + /* * Make our catalog updates visible for subsequent steps. */ diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index f148ff658918db7401d530d87d1f4cc65f492d0e..c94b67883be030428ae32e91a543395b43dc5aa2 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.5 2002/07/12 18:43:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.6 2002/07/16 22:12:19 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -358,15 +358,18 @@ DefineDomain(CreateDomainStmt *stmt) char typtype; Datum datum; bool isnull; + Node *defaultExpr = NULL; char *defaultValue = NULL; char *defaultValueBin = NULL; bool typNotNull = false; + bool nullDefined = false; Oid basetypelem; int32 typNDims = length(stmt->typename->arrayBounds); HeapTuple typeTup; List *schema = stmt->constraints; List *listptr; Oid basetypeoid; + Oid domainoid; Form_pg_type baseType; /* Convert list of names to a name and namespace */ @@ -459,8 +462,6 @@ DefineDomain(CreateDomainStmt *stmt) foreach(listptr, schema) { Constraint *colDef = lfirst(listptr); - bool nullDefined = false; - Node *expr; ParseState *pstate; switch (colDef->contype) @@ -473,47 +474,45 @@ DefineDomain(CreateDomainStmt *stmt) * don't want to cook or fiddle too much. */ case CONSTR_DEFAULT: + if (defaultExpr) + elog(ERROR, "CREATE DOMAIN has multiple DEFAULT expressions"); /* Create a dummy ParseState for transformExpr */ pstate = make_parsestate(NULL); /* * Cook the colDef->raw_expr into an expression. * Note: Name is strictly for error message */ - expr = cookDefault(pstate, colDef->raw_expr, - basetypeoid, - stmt->typename->typmod, - domainName); + defaultExpr = cookDefault(pstate, colDef->raw_expr, + basetypeoid, + stmt->typename->typmod, + domainName); /* * Expression must be stored as a nodeToString result, * but we also require a valid textual representation * (mainly to make life easier for pg_dump). */ - defaultValue = deparse_expression(expr, + defaultValue = deparse_expression(defaultExpr, deparse_context_for(domainName, InvalidOid), false); - defaultValueBin = nodeToString(expr); + defaultValueBin = nodeToString(defaultExpr); break; /* * Find the NULL constraint. */ case CONSTR_NOTNULL: - if (nullDefined) { + if (nullDefined) elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint"); - } else { - typNotNull = true; - nullDefined = true; - } + typNotNull = true; + nullDefined = true; break; case CONSTR_NULL: - if (nullDefined) { + if (nullDefined) elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint"); - } else { - typNotNull = false; - nullDefined = true; - } + typNotNull = false; + nullDefined = true; break; case CONSTR_UNIQUE: @@ -544,28 +543,44 @@ DefineDomain(CreateDomainStmt *stmt) /* * Have TypeCreate do all the real work. */ - TypeCreate(domainName, /* type name */ - domainNamespace, /* namespace */ - InvalidOid, /* preassigned type oid (none here) */ - InvalidOid, /* relation oid (n/a here) */ - internalLength, /* internal size */ - externalLength, /* external size */ - 'd', /* type-type (domain type) */ - delimiter, /* array element delimiter */ - inputProcedure, /* input procedure */ - outputProcedure, /* output procedure */ - receiveProcedure, /* receive procedure */ - sendProcedure, /* send procedure */ - basetypelem, /* element type ID */ - basetypeoid, /* base type ID */ - defaultValue, /* default type value (text) */ - defaultValueBin, /* default type value (binary) */ - byValue, /* passed by value */ - alignment, /* required alignment */ - storage, /* TOAST strategy */ - stmt->typename->typmod, /* typeMod value */ - typNDims, /* Array dimensions for base type */ - typNotNull); /* Type NOT NULL */ + domainoid = + TypeCreate(domainName, /* type name */ + domainNamespace, /* namespace */ + InvalidOid, /* preassigned type oid (none here) */ + InvalidOid, /* relation oid (n/a here) */ + internalLength, /* internal size */ + externalLength, /* external size */ + 'd', /* type-type (domain type) */ + delimiter, /* array element delimiter */ + inputProcedure, /* input procedure */ + outputProcedure, /* output procedure */ + receiveProcedure, /* receive procedure */ + sendProcedure, /* send procedure */ + basetypelem, /* element type ID */ + basetypeoid, /* base type ID */ + defaultValue, /* default type value (text) */ + defaultValueBin, /* default type value (binary) */ + byValue, /* passed by value */ + alignment, /* required alignment */ + storage, /* TOAST strategy */ + stmt->typename->typmod, /* typeMod value */ + typNDims, /* Array dimensions for base type */ + typNotNull); /* Type NOT NULL */ + + /* + * Add any dependencies needed for the default expression. + */ + if (defaultExpr) + { + ObjectAddress domobject; + + domobject.classId = RelOid_pg_type; + domobject.objectId = domainoid; + domobject.objectSubId = 0; + + recordDependencyOnExpr(&domobject, defaultExpr, NIL, + DEPENDENCY_NORMAL); + } /* * Now we can clean up. diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 519df157184960b1192f06be935e5db9e0393ae9..faaff48fa053fc7a0fe7ad4d707e04798b90ff98 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: view.c,v 1.66 2002/07/12 18:43:16 tgl Exp $ + * $Id: view.c,v 1.67 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -72,6 +72,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist) def->raw_default = NULL; def->cooked_default = NULL; def->constraints = NIL; + def->support = NULL; attrList = lappend(attrList, def); } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 4e568a3c531ba5daa9bbb13a6b55d631dfe51dd4..426180dc1111d04bbb7ece656b9bc9530d70a99d 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.193 2002/07/12 18:43:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.194 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1749,6 +1749,7 @@ _copyColumnDef(ColumnDef *from) if (from->cooked_default) newnode->cooked_default = pstrdup(from->cooked_default); Node_Copy(from, newnode, constraints); + Node_Copy(from, newnode, support); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index e15870b2c800b4f4fc4534317e51a59136a4e0bb..ed5d638f0cb6b522af8e508b205512eada815ad0 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.140 2002/07/12 18:43:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.141 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1636,6 +1636,8 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b) return false; if (!equal(a->constraints, b->constraints)) return false; + if (!equal(a->support, b->support)) + return false; return true; } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index ae3139a6ea65e06f396b25ff5958b90a3b25bd5d..a9e6a8382d52807312b9b283be22ceb9254fb7af 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.162 2002/07/12 18:43:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.163 2002/07/16 22:12:19 tgl Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -183,6 +183,8 @@ _outColumnDef(StringInfo str, ColumnDef *node) _outToken(str, node->cooked_default); appendStringInfo(str, " :constraints "); _outNode(str, node->constraints); + appendStringInfo(str, " :support "); + _outNode(str, node->support); } static void diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 2fbca505987b7b84e164d526cdb9dd717cb14e0b..6337b61f2acda5ddb1f3e5c54328cc14302e0f8d 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.238 2002/07/12 18:43:17 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.239 2002/07/16 22:12:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -847,6 +847,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, cxt->blist = lappend(cxt->blist, seqstmt); + /* + * Mark the ColumnDef so that during execution, an appropriate + * dependency will be added from the sequence to the column. + */ + column->support = makeRangeVar(snamespace, sname); + /* * Create appropriate constraints for SERIAL. We do this in full, * rather than shortcutting, so that we will detect any diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ef83d92a6d39b0cdd366e586eeab2bce58a48f77..9b8e52620a6879750b231741b33472eb8d3b6806 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.340 2002/07/14 23:38:13 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.341 2002/07/16 22:12:20 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1852,10 +1852,11 @@ CreateAsElement: ColumnDef *n = makeNode(ColumnDef); n->colname = $1; n->typename = NULL; + n->is_not_null = false; n->raw_default = NULL; n->cooked_default = NULL; - n->is_not_null = FALSE; - n->constraints = NULL; + n->constraints = NIL; + n->support = NULL; $$ = (Node *)n; } ; diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index bcadaee732f2ab125b9bc1b3efbcfc5388a41ef8..b2780071ff30d345642e4c8b810d71114c77553f 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: dependency.h,v 1.2 2002/07/16 05:53:34 tgl Exp $ + * $Id: dependency.h,v 1.3 2002/07/16 22:12:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -98,4 +98,6 @@ extern void recordMultipleDependencies(const ObjectAddress *depender, int nreferenced, DependencyType behavior); +extern void deleteDependencyRecordsFor(Oid classId, Oid objectId); + #endif /* DEPENDENCY_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index f0542990f2e5d1f9cc0e2c8777ec96f54dc5d31c..c0933f8ae7ffbbb8c5a7abfcafadf41752586a07 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.186 2002/07/14 23:38:13 tgl Exp $ + * $Id: parsenodes.h,v 1.187 2002/07/16 22:12:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -269,6 +269,10 @@ typedef struct BooleanTest * parsetree produced by gram.y, but transformCreateStmt will remove * the item and set raw_default instead. CONSTR_DEFAULT items * should not appear in any subsequent processing. + * + * The "support" field, if not null, denotes a supporting relation that + * should be linked by an internal dependency to the column. Currently + * this is only used to link a SERIAL column's sequence to the column. */ typedef struct ColumnDef { @@ -280,6 +284,7 @@ typedef struct ColumnDef * tree) */ char *cooked_default; /* nodeToString representation */ List *constraints; /* other constraints on column */ + RangeVar *support; /* supporting relation, if any */ } ColumnDef; /*