? src/backend/catalog/pg_constraint.c ? src/backend/catalog/pg_depend.c ? src/bin/pg_passwd/pg_passwd ? src/include/catalog/pg_constraint.h ? src/include/catalog/pg_depend.h ? src/test/regress/expected/drop.out Index: src/backend/catalog/Makefile =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/Makefile,v retrieving revision 1.39 diff -c -r1.39 Makefile *** src/backend/catalog/Makefile 2002/03/26 19:15:22 1.39 --- src/backend/catalog/Makefile 2002/05/09 01:42:53 *************** *** 12,18 **** OBJS = catalog.o heap.o index.o indexing.o namespace.o aclchk.o \ pg_aggregate.o pg_largeobject.o pg_namespace.o \ ! pg_operator.o pg_proc.o pg_type.o BKIFILES = postgres.bki postgres.description --- 12,18 ---- OBJS = catalog.o heap.o index.o indexing.o namespace.o aclchk.o \ pg_aggregate.o pg_largeobject.o pg_namespace.o \ ! pg_operator.o pg_proc.o pg_type.o pg_depend.o pg_constraint.o BKIFILES = postgres.bki postgres.description *************** *** 26,33 **** # indexing.h had better be last. POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\ ! pg_proc.h pg_type.h pg_attribute.h pg_class.h \ ! pg_attrdef.h pg_relcheck.h pg_inherits.h pg_index.h \ pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \ pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \ pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \ --- 26,33 ---- # indexing.h had better be last. POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\ ! pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_depend.h \ ! pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \ pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \ pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \ pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \ Index: src/backend/catalog/genbki.sh =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/genbki.sh,v retrieving revision 1.27 diff -c -r1.27 genbki.sh *** src/backend/catalog/genbki.sh 2002/04/27 21:24:33 1.27 --- src/backend/catalog/genbki.sh 2002/05/09 01:42:54 *************** *** 224,229 **** --- 224,233 ---- comment_level = 0; nextbkioid = ENVIRON["BKIOBJECTID"]; oid = 0; + pin = ""; + pindata[-1] = ""; + pinoid = 0; + pinwrite = ""; } # ---------------- *************** *** 251,256 **** --- 255,264 ---- # stripping off the DATA( and the ) on the end. However, # if we see "OID = 0" then we should assign an oid from nextbkioid. # Remember any explicit or assigned OID for use by DESCR(). + # + # If this is a base table with a PIN id recorded, dump the dependency + # information to a depend file which will be appended onto the data + # for the pg_depend table. # ---------------- /^DATA\(/ { data = substr($0, 6, length($0) - 6); *************** *** 265,270 **** --- 273,285 ---- nextbkioid++; sub("OID *= *0", "OID = " oid, data); } + + if (pin != "") + { + pinoid = pincount; + pindata[pinoid] = sprintf("insert (%d %d 0 0 0 0 f)", pin, oid); + pincount++; + } } print data; next; *************** *** 285,290 **** --- 300,306 ---- # end any prior catalog data insertions before starting a define index # ---- if (reln_open == 1) { + pinwritedata(pinwrite); # print "show"; print "close " catalog; reln_open = 0; *************** *** 299,304 **** --- 315,321 ---- # end any prior catalog data insertions before starting a define unique index # ---- if (reln_open == 1) { + pinwritedata(pinwrite); # print "show"; print "close " catalog; reln_open = 0; *************** *** 309,315 **** } /^BUILD_INDICES/ { print "build indices"; } ! # ---------------- # CATALOG() definitions take some more work. # ---------------- --- 326,340 ---- } /^BUILD_INDICES/ { print "build indices"; } ! ! /^PINTABLE\(/ { ! ret = match($0, /[0-9]+/); ! pin = substr($0, RSTART, RLENGTH); ! ! pinwrite = ""; ! next; ! } ! # ---------------- # CATALOG() definitions take some more work. # ---------------- *************** *** 318,323 **** --- 343,349 ---- # end any prior catalog data insertions before starting a new one.. # ---- if (reln_open == 1) { + pinwritedata(pinwrite); # print "show"; print "close " catalog; reln_open = 0; *************** *** 339,344 **** --- 365,378 ---- without_oids = "without_oids "; } + if ($0 ~ /BKI_PINWRITE/) { + pinwrite = "pinwrite"; + } else { + pinwrite = ""; + } + + pin = ""; + i = 1; inside = 1; nc++; *************** *** 402,410 **** --- 436,456 ---- END { if (reln_open == 1) { + pinwritedata(pinwrite); # print "show"; print "close " catalog; reln_open = 0; + } + } + + ## + # write out PINd records + function pinwritedata(pinwrite) + { + if (pinwrite == "pinwrite") { + for (i=0; i < pincount; i++) { + print pindata[i]; + } } } ' "descriptionfile=${OUTPUT_PREFIX}.description.$$" > $TMPFILE || exit Index: src/backend/catalog/heap.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/heap.c,v retrieving revision 1.198 diff -c -r1.198 heap.c *** src/backend/catalog/heap.c 2002/05/03 04:11:08 1.198 --- src/backend/catalog/heap.c 2002/05/09 01:42:56 *************** *** 36,44 **** #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_inherits.h" - #include "catalog/pg_relcheck.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" #include "commands/comment.h" --- 36,46 ---- #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/indexing.h" + #include "catalog/namespace.h" #include "catalog/pg_attrdef.h" + #include "catalog/pg_constraint.h" + #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" #include "commands/comment.h" *************** *** 68,75 **** char relkind, bool relhasoids); static void DeleteAttributeTuples(Relation rel); static void DeleteRelationTuple(Relation rel); - static void DeleteTypeTuple(Relation rel); - static void RelationRemoveIndexes(Relation relation); static void RelationRemoveInheritance(Relation relation); static void AddNewRelationType(const char *typeName, Oid typeNamespace, --- 70,75 ---- *************** *** 822,848 **** heap_close(catalogRelation, RowExclusiveLock); } - /* - * RelationRemoveIndexes - */ - static void - RelationRemoveIndexes(Relation relation) - { - List *indexoidlist, - *indexoidscan; - - indexoidlist = RelationGetIndexList(relation); - - foreach(indexoidscan, indexoidlist) - { - Oid indexoid = lfirsti(indexoidscan); - index_drop(indexoid); - } - - freeList(indexoidlist); - } - /* -------------------------------- * DeleteRelationTuple * --- 822,828 ---- *************** *** 1036,1161 **** heap_close(pg_attribute_desc, RowExclusiveLock); } - /* -------------------------------- - * DeleteTypeTuple - * - * If the user attempts to destroy a relation and there - * exists attributes in other relations of type - * "relation we are deleting", then we have to do something - * special. presently we disallow the destroy. - * -------------------------------- - */ - static void - DeleteTypeTuple(Relation rel) - { - Relation pg_type_desc; - HeapScanDesc pg_type_scan; - Relation pg_attribute_desc; - HeapScanDesc pg_attribute_scan; - ScanKeyData key; - ScanKeyData attkey; - HeapTuple tup; - HeapTuple atttup; - Oid typoid; - - /* - * open pg_type - */ - pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); - - /* - * create a scan key to locate the type tuple corresponding to this - * relation. - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_type_typrelid, - F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel))); - - pg_type_scan = heap_beginscan(pg_type_desc, - 0, - SnapshotNow, - 1, - &key); - - /* - * use heap_getnext() to fetch the pg_type tuple. If this tuple is - * not valid then something's wrong. - */ - tup = heap_getnext(pg_type_scan, 0); - - if (!HeapTupleIsValid(tup)) - { - heap_endscan(pg_type_scan); - heap_close(pg_type_desc, RowExclusiveLock); - elog(ERROR, "DeleteTypeTuple: type \"%s\" does not exist", - RelationGetRelationName(rel)); - } - - /* - * now scan pg_attribute. if any other relations have attributes of - * the type of the relation we are deleteing then we have to disallow - * the deletion. should talk to stonebraker about this. -cim 6/19/90 - */ - typoid = tup->t_data->t_oid; - - pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock); - - ScanKeyEntryInitialize(&attkey, - 0, - Anum_pg_attribute_atttypid, - F_OIDEQ, - ObjectIdGetDatum(typoid)); - - pg_attribute_scan = heap_beginscan(pg_attribute_desc, - 0, - SnapshotNow, - 1, - &attkey); - - /* - * try and get a pg_attribute tuple. if we succeed it means we can't - * delete the relation because something depends on the schema. - */ - atttup = heap_getnext(pg_attribute_scan, 0); - - if (HeapTupleIsValid(atttup)) - { - Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid; - - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc, RowExclusiveLock); - heap_endscan(pg_type_scan); - heap_close(pg_type_desc, RowExclusiveLock); - - elog(ERROR, "DeleteTypeTuple: column of type %s exists in relation %u", - RelationGetRelationName(rel), relid); - } - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc, RowExclusiveLock); - - /* - * Ok, it's safe so we delete the relation tuple from pg_type and - * finish up. - */ - simple_heap_delete(pg_type_desc, &tup->t_self); - - heap_endscan(pg_type_scan); - heap_close(pg_type_desc, RowExclusiveLock); - } - /* ---------------------------------------------------------------- * heap_drop_with_catalog - removes all record of named relation from catalogs * * 1) open relation, check for existence, etc. * 2) remove inheritance information ! * 3) remove indexes ! * 4) remove pg_class tuple ! * 5) remove pg_attribute tuples and related descriptions ! * 6) remove pg_description tuples ! * 7) remove pg_type tuples ! * 8) RemoveConstraints () ! * 9) unlink relation * * old comments * Except for vital relations, removes relation from --- 1016,1031 ---- heap_close(pg_attribute_desc, RowExclusiveLock); } /* ---------------------------------------------------------------- * heap_drop_with_catalog - removes all record of named relation from catalogs * * 1) open relation, check for existence, etc. * 2) remove inheritance information ! * 3) remove pg_class tuple ! * 4) remove pg_attribute tuples and related descriptions ! * 5) remove pg_description tuples ! * 6) Let dependDelete() do it's work. ! * 7) unlink relation * * old comments * Except for vital relations, removes relation from *************** *** 1176,1192 **** */ void heap_drop_with_catalog(Oid rid, ! bool allow_system_table_mods) { Relation rel; - Oid toasttableOid; int i; /* * Open and lock the relation. */ rel = heap_open(rid, AccessExclusiveLock); - toasttableOid = rel->rd_rel->reltoastrelid; /* * prevent deletion of system relations --- 1046,1065 ---- */ void heap_drop_with_catalog(Oid rid, ! bool allow_system_table_mods, ! int behavior) { Relation rel; int i; + HeapTuple tuple; + int natts; + Oid relHasOids; + ObjectAddress myself; /* * Open and lock the relation. */ rel = heap_open(rid, AccessExclusiveLock); /* * prevent deletion of system relations *************** *** 1206,1228 **** i); /* ! * remove rules if necessary */ ! if (rel->rd_rules != NULL) ! RelationRemoveRules(rid); ! ! /* triggers */ ! RelationRemoveTriggers(rel); /* ! * remove inheritance information */ ! RelationRemoveInheritance(rel); /* ! * remove indexes if necessary */ ! RelationRemoveIndexes(rel); /* * delete attribute tuples --- 1079,1123 ---- i); /* ! * remove inheritance information */ ! RelationRemoveInheritance(rel); /* ! * Deal with dependencies ! * ! * Take care of any attributes first, then the main object ! * last when objectSubId = 0. Ignore system attributes. */ ! tuple = SearchSysCache(RELOID, rid, 0, 0, 0); ! if (!HeapTupleIsValid(tuple)) ! elog(ERROR, "Relation %s doesn't exist", RelationGetRelationName(rel)); + natts = ((Form_pg_class) GETSTRUCT(tuple))->relnatts; + relHasOids = ((Form_pg_class) GETSTRUCT(tuple))->relnatts; + + /* Must free before calling dependDelete */ + ReleaseSysCache(tuple); + /* ! * Drop in decending order so the table is handled after all ! * of its columns. ! * ! * Oid column first due to abilities like Primary Key on Oid. */ ! myself.classId = RelOid_pg_class; ! myself.objectId = rid; ! if (relHasOids) ! { ! myself.objectSubId = ObjectIdAttributeNumber; ! dependDelete(&myself, behavior); ! } ! ! for (i = natts; i >= 0; i--) ! { ! myself.objectSubId = i; ! dependDelete(&myself, behavior); ! } /* * delete attribute tuples *************** *** 1239,1249 **** RemoveConstraints(rel); /* - * delete type tuple - */ - DeleteTypeTuple(rel); - - /* * delete relation tuple */ DeleteRelationTuple(rel); --- 1134,1139 ---- *************** *** 1265,1274 **** * flush the relation from the relcache */ RelationForgetRelation(rid); - - /* If it has a toast table, recurse to get rid of that too */ - if (OidIsValid(toasttableOid)) - heap_drop_with_catalog(toasttableOid, true); } --- 1155,1160 ---- *************** *** 1363,1373 **** { Node *expr; char *ccsrc; ! Relation rcrel; ! Relation idescs[Num_pg_relcheck_indices]; ! HeapTuple tuple; ! Datum values[4]; ! static char nulls[4] = {' ', ' ', ' ', ' '}; /* * Convert condition to a normal boolean expression tree. --- 1249,1259 ---- { Node *expr; char *ccsrc; ! List *varList; ! List *vl; ! int i = 0; ! int keycount = 0; ! AttrNumber *attNos; /* * Convert condition to a normal boolean expression tree. *************** *** 1383,1409 **** RelationGetRelid(rel)), false); ! values[Anum_pg_relcheck_rcrelid - 1] = RelationGetRelid(rel); ! values[Anum_pg_relcheck_rcname - 1] = DirectFunctionCall1(namein, ! CStringGetDatum(ccname)); ! values[Anum_pg_relcheck_rcbin - 1] = DirectFunctionCall1(textin, ! CStringGetDatum(ccbin)); ! values[Anum_pg_relcheck_rcsrc - 1] = DirectFunctionCall1(textin, ! CStringGetDatum(ccsrc)); ! rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); ! tuple = heap_formtuple(rcrel->rd_att, values, nulls); ! heap_insert(rcrel, tuple); ! CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, ! idescs); ! CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple); ! CatalogCloseIndices(Num_pg_relcheck_indices, idescs); ! heap_close(rcrel, RowExclusiveLock); ! ! pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1])); ! pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1])); ! pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1])); ! heap_freetuple(tuple); pfree(ccsrc); } /* --- 1269,1306 ---- RelationGetRelid(rel)), false); ! /* Find columns of rel that are used in ccbin */ ! varList = pull_var_clause(expr, false); ! foreach(vl, varList) ! keycount++; ! ! attNos = (AttrNumber *) palloc(keycount * sizeof(AttrNumber)); ! foreach(vl, varList) ! { ! Var *var = (Var *) lfirsti(vl); ! ! attNos[i++] = var->varattno; ! } ! ! /* Create the Check Constraint */ ! constraintCreate(RelationGetRelid(rel), /* Relation the constraint is on */ ! ccname, /* Constraint Name */ ! CONSTRAINT_CHECK, /* Constraint Type */ ! false, /* Is Derrerable */ ! false, /* Is Deferred */ ! attNos, /* List of attrributes in the constraint */ ! keycount, /* Number of attributes in the constraint */ ! NULL, /* Foreign Key fields (6) */ ! NULL, ! NULL, ! NULL, ! NULL, ! NULL, ! ccbin, /* Binary form check constraint */ ! ccsrc); /* Source form check constraint */ ! pfree(ccsrc); + pfree(attNos); } /* *************** *** 1528,1674 **** numchecks = numoldchecks; foreach(listptr, rawConstraints) { ! Constraint *cdef = (Constraint *) lfirst(listptr); ! char *ccname; ! ! if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL) ! continue; ! Assert(cdef->cooked_expr == NULL); ! /* Check name uniqueness, or generate a new name */ ! if (cdef->name != NULL) { ! int i; ! List *listptr2; ! ccname = cdef->name; ! /* Check against old constraints */ ! for (i = 0; i < numoldchecks; i++) ! { ! if (strcmp(oldchecks[i].ccname, ccname) == 0) ! elog(ERROR, "Duplicate CHECK constraint name: '%s'", ! ccname); ! } ! /* Check against other new constraints */ ! foreach(listptr2, rawConstraints) ! { ! Constraint *cdef2 = (Constraint *) lfirst(listptr2); ! ! if (cdef2 == cdef || ! cdef2->contype != CONSTR_CHECK || ! cdef2->raw_expr == NULL || ! cdef2->name == NULL) ! continue; ! if (strcmp(cdef2->name, ccname) == 0) ! elog(ERROR, "Duplicate CHECK constraint name: '%s'", ! ccname); ! } ! } ! else ! { ! int i; ! int j; ! bool success; ! List *listptr2; ! ! ccname = (char *) palloc(NAMEDATALEN); ! ! /* Loop until we find a non-conflicting constraint name */ ! /* What happens if this loops forever? */ ! j = numchecks + 1; ! do ! { ! success = true; ! snprintf(ccname, NAMEDATALEN, "$%d", j); ! /* Check against old constraints */ ! for (i = 0; i < numoldchecks; i++) { ! if (strcmp(oldchecks[i].ccname, ccname) == 0) { ! success = false; ! break; } - } ! /* ! * Check against other new constraints, if the check ! * hasn't already failed ! */ ! if (success) ! { ! foreach(listptr2, rawConstraints) { ! Constraint *cdef2 = (Constraint *) lfirst(listptr2); ! if (cdef2 == cdef || ! cdef2->contype != CONSTR_CHECK || ! cdef2->raw_expr == NULL || ! cdef2->name == NULL) ! continue; ! if (strcmp(cdef2->name, ccname) == 0) ! { ! success = false; break; ! } } - } ! ++j; ! } while (!success); ! } ! /* ! * Transform raw parsetree to executable expression. ! */ ! expr = transformExpr(pstate, cdef->raw_expr); ! /* ! * Make sure it yields a boolean result. ! */ ! if (exprType(expr) != BOOLOID) ! elog(ERROR, "CHECK constraint expression '%s' does not yield boolean result", ! ccname); ! /* ! * Make sure no outside relations are referred to. ! */ ! if (length(pstate->p_rtable) != 1) ! elog(ERROR, "Only relation \"%s\" can be referenced in CHECK constraint expression", ! relname); ! /* ! * No subplans or aggregates, either... ! */ ! if (contain_subplans(expr)) ! elog(ERROR, "cannot use subselect in CHECK constraint expression"); ! if (contain_agg_clause(expr)) ! elog(ERROR, "cannot use aggregate function in CHECK constraint expression"); ! /* ! * Might as well try to reduce any constant expressions. ! */ ! expr = eval_const_expressions(expr); ! /* ! * Constraints are evaluated with execQual, which expects an ! * implicit-AND list, so convert expression to implicit-AND form. ! * (We could go so far as to convert to CNF, but that's probably ! * overkill...) ! */ ! expr = (Node *) make_ands_implicit((Expr *) expr); ! /* ! * Must fix opids in operator clauses. ! */ ! fix_opids(expr); - /* - * OK, store it. - */ - StoreRelCheck(rel, ccname, nodeToString(expr)); ! numchecks++; } /* --- 1425,1652 ---- numchecks = numoldchecks; foreach(listptr, rawConstraints) { ! Node *newConstraint = lfirst(listptr); ! switch (nodeTag(newConstraint)) { ! case T_Constraint: ! { ! Constraint *cdef = (Constraint *) newConstraint; ! char *ccname = cdef->name; ! if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL) ! continue; ! Assert(cdef->cooked_expr == NULL); ! ! /* ! * Transform raw parsetree to executable expression. ! */ ! expr = transformExpr(pstate, cdef->raw_expr); ! ! /* ! * Make sure it yields a boolean result. ! */ ! if (exprType(expr) != BOOLOID) ! elog(ERROR, "CHECK constraint expression '%s' does not yield boolean result", ! ccname); ! ! /* ! * Make sure no outside relations are referred to. ! */ ! if (length(pstate->p_rtable) != 1) ! elog(ERROR, "Only relation \"%s\" can be referenced in CHECK constraint expression", ! relname); ! ! /* ! * No subplans or aggregates, either... ! */ ! if (contain_subplans(expr)) ! elog(ERROR, "cannot use subselect in CHECK constraint expression"); ! if (contain_agg_clause(expr)) ! elog(ERROR, "cannot use aggregate function in CHECK constraint expression"); ! ! /* ! * Might as well try to reduce any constant expressions. ! */ ! expr = eval_const_expressions(expr); ! ! /* ! * Constraints are evaluated with execQual, which expects an ! * implicit-AND list, so convert expression to implicit-AND form. ! * (We could go so far as to convert to CNF, but that's probably ! * overkill...) ! */ ! expr = (Node *) make_ands_implicit((Expr *) expr); ! ! /* ! * Must fix opids in operator clauses. ! */ ! fix_opids(expr); ! ! /* ! * OK, store it. ! * ! * Will check name uniqueness for us. ! */ ! StoreRelCheck(rel, ccname, nodeToString(expr)); ! ! numchecks++; ! break; ! } ! case T_FkConstraint: { ! FkConstraint *fkconstraint = (FkConstraint *) newConstraint; ! Relation pkrel; ! List *list; ! Oid conId; ! AttrNumber *pkattr = NULL; ! AttrNumber *fkattr = NULL; ! int pkcount = 0; ! int fkcount = 0; ! int i; ! char updateType = CONSTRAINT_FKEY_RESTRICT; /* Defaults kill warnings */ ! char deleteType = CONSTRAINT_FKEY_RESTRICT; ! int matchType = CONSTRAINT_FKEY_FULL; ! ! /* ! * Grab an exclusive lock on the pk table, so that ! * someone doesn't delete rows out from under us. ! * ! * XXX wouldn't a lesser lock be sufficient? ! */ ! pkrel = heap_openrv(fkconstraint->pktable, ! AccessExclusiveLock); ! ! /* ! * Validity checks ! */ ! if (pkrel->rd_rel->relkind != RELKIND_RELATION) ! elog(ERROR, "referenced table \"%s\" not a relation", ! fkconstraint->pktable->relname); ! ! if (isTempNamespace(RelationGetNamespace(pkrel)) && ! !isTempNamespace(RelationGetNamespace(rel))) ! elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint."); ! ! /* Foreign Keyd table AttrNumber array */ ! foreach(list, fkconstraint->fk_attrs) ! fkcount++; ! ! fkattr = (AttrNumber *) palloc(fkcount * sizeof(AttrNumber)); ! i = 0; ! foreach(list, fkconstraint->fk_attrs) { ! Ident *id = (Ident *) lfirsti(list); ! ! fkattr[i++] = get_attnum(RelationGetRelid(rel), id->name); } ! /* Foreign Referenced table AttrNumber array */ ! foreach(list, fkconstraint->pk_attrs) ! pkcount++; ! ! pkattr = (AttrNumber *) palloc(pkcount * sizeof(AttrNumber)); ! i = 0; ! foreach(list, fkconstraint->pk_attrs) { ! Ident *id = (Ident *) lfirsti(list); ! ! pkattr[i++] = get_attnum(RelationGetRelid(pkrel), id->name); ! } ! ! /* Find the update type */ ! switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK) ! >> FKCONSTR_ON_UPDATE_SHIFT) ! { ! case FKCONSTR_ON_KEY_CASCADE: ! deleteType = CONSTRAINT_FKEY_CASCADE; ! break; ! ! case FKCONSTR_ON_KEY_NOACTION: ! deleteType = CONSTRAINT_FKEY_NOACTION; ! break; ! case FKCONSTR_ON_KEY_RESTRICT: ! deleteType = CONSTRAINT_FKEY_RESTRICT; break; ! ! case FKCONSTR_ON_KEY_SETNULL: ! deleteType = CONSTRAINT_FKEY_NULL; ! break; ! ! case FKCONSTR_ON_KEY_SETDEFAULT: ! deleteType = CONSTRAINT_FKEY_DEFAULT; ! break; ! ! default: ! elog(ERROR, "AlterTableAddConstraint: Foreign key type %d unknown", ! fkconstraint->actions); } ! /* Find the delete type */ ! switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK) ! >> FKCONSTR_ON_DELETE_SHIFT) ! { ! case FKCONSTR_ON_KEY_CASCADE: ! updateType = CONSTRAINT_FKEY_CASCADE; ! break; ! case FKCONSTR_ON_KEY_NOACTION: ! updateType = CONSTRAINT_FKEY_NOACTION; ! break; ! case FKCONSTR_ON_KEY_RESTRICT: ! updateType = CONSTRAINT_FKEY_RESTRICT; ! break; ! case FKCONSTR_ON_KEY_SETNULL: ! updateType = CONSTRAINT_FKEY_NULL; ! break; ! case FKCONSTR_ON_KEY_SETDEFAULT: ! updateType = CONSTRAINT_FKEY_DEFAULT; ! break; ! default: ! elog(ERROR, "AlterTableAddConstraint: Foreign key type %d unknown", ! fkconstraint->actions); ! } ! /* Determine match type */ ! if (strcmp(fkconstraint->match_type, "FULL") == 0) ! matchType = CONSTRAINT_FKEY_FULL; ! if (strcmp(fkconstraint->match_type, "PARTIAL") == 0) ! matchType = CONSTRAINT_FKEY_PARTIAL; ! ! /* ! * Record the Foreign Key constraint ! */ ! conId = constraintCreate(RelationGetRelid(rel), ! fkconstraint->constr_name, ! CONSTRAINT_FOREIGN, ! fkconstraint->deferrable, ! fkconstraint->initdeferred, ! fkattr, ! fkcount, ! RelationGetRelid(pkrel), ! pkattr, ! pkcount, ! updateType, ! deleteType, ! matchType, ! NULL, ! NULL); ! heap_close(pkrel, NoLock); ! ! break; ! } ! default: ! elog(ERROR, "AddRelationRawConstraints: Unable to determine type of constraint passed"); ! } } /* *************** *** 1813,1819 **** return(expr); } - static void RemoveAttrDefaults(Relation rel) { --- 1791,1796 ---- *************** *** 1838,1981 **** } static void - RemoveRelChecks(Relation rel) - { - Relation rcrel; - HeapScanDesc rcscan; - ScanKeyData key; - HeapTuple tup; - - rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); - - ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid, - F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel))); - - rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key); - - while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0))) - simple_heap_delete(rcrel, &tup->t_self); - - heap_endscan(rcscan); - heap_close(rcrel, RowExclusiveLock); - - } - - /* - * Removes all CHECK constraints on a relation that match the given name. - * It is the responsibility of the calling function to acquire a lock on - * the relation. - * Returns: The number of CHECK constraints removed. - */ - int - RemoveCheckConstraint(Relation rel, const char *constrName, bool inh) - { - Oid relid; - Relation rcrel; - TupleDesc tupleDesc; - TupleConstr *oldconstr; - int numoldchecks; - int numchecks; - HeapScanDesc rcscan; - ScanKeyData key[2]; - HeapTuple rctup; - int rel_deleted = 0; - int all_deleted = 0; - - /* Find id of the relation */ - relid = RelationGetRelid(rel); - - /* - * Process child tables and remove constraints of the same name. - */ - if (inh) - { - List *child, - *children; - - /* This routine is actually in the planner */ - children = find_all_inheritors(relid); - - /* - * find_all_inheritors does the recursive search of the - * inheritance hierarchy, so all we have to do is process all of - * the relids in the list that it returns. - */ - foreach(child, children) - { - Oid childrelid = lfirsti(child); - Relation inhrel; - - if (childrelid == relid) - continue; - inhrel = heap_open(childrelid, AccessExclusiveLock); - all_deleted += RemoveCheckConstraint(inhrel, constrName, false); - heap_close(inhrel, NoLock); - } - } - - /* - * Get number of existing constraints. - */ - tupleDesc = RelationGetDescr(rel); - oldconstr = tupleDesc->constr; - if (oldconstr) - numoldchecks = oldconstr->num_check; - else - numoldchecks = 0; - - /* Grab an appropriate lock on the pg_relcheck relation */ - rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock); - - /* - * Create two scan keys. We need to match on the oid of the table the - * CHECK is in and also we need to match the name of the CHECK - * constraint. - */ - ScanKeyEntryInitialize(&key[0], 0, Anum_pg_relcheck_rcrelid, - F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel))); - - ScanKeyEntryInitialize(&key[1], 0, Anum_pg_relcheck_rcname, - F_NAMEEQ, - PointerGetDatum(constrName)); - - /* Begin scanning the heap */ - rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 2, key); - - /* - * Scan over the result set, removing any matching entries. Note that - * this has the side-effect of removing ALL CHECK constraints that - * share the specified constraint name. - */ - while (HeapTupleIsValid(rctup = heap_getnext(rcscan, 0))) - { - simple_heap_delete(rcrel, &rctup->t_self); - ++rel_deleted; - ++all_deleted; - } - - /* Clean up after the scan */ - heap_endscan(rcscan); - heap_close(rcrel, RowExclusiveLock); - - if (rel_deleted) - { - /* - * Update the count of constraints in the relation's pg_class tuple. - */ - numchecks = numoldchecks - rel_deleted; - if (numchecks < 0) - elog(ERROR, "check count became negative"); - - SetRelationNumChecks(rel, numchecks); - } - - /* Return the number of tuples deleted, including all children */ - return all_deleted; - } - - static void RemoveConstraints(Relation rel) { TupleConstr *constr = rel->rd_att->constr; --- 1815,1820 ---- *************** *** 1985,1993 **** if (constr->num_defval > 0) RemoveAttrDefaults(rel); - - if (constr->num_check > 0) - RemoveRelChecks(rel); } static void --- 1824,1829 ---- Index: src/backend/catalog/index.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/index.c,v retrieving revision 1.177 diff -c -r1.177 index.c *** src/backend/catalog/index.c 2002/04/27 21:24:34 1.177 --- src/backend/catalog/index.c 2002/05/09 01:42:59 *************** *** 32,39 **** --- 32,43 ---- #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/indexing.h" + #include "catalog/pg_class.h" + #include "catalog/pg_constraint.h" + #include "catalog/pg_depend.h" #include "catalog/pg_index.h" #include "catalog/pg_opclass.h" + #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/comment.h" *************** *** 543,548 **** --- 547,555 ---- bool shared_relation; Oid namespaceId; Oid indexoid; + ObjectAddress myself, + dependee; + int i; SetReindexProcessing(false); *************** *** 593,599 **** else indexTupDesc = ConstructTupleDescriptor(heapRelation, indexInfo->ii_NumKeyAttrs, ! indexInfo->ii_KeyAttrNumbers, classObjectId); /* --- 600,606 ---- else indexTupDesc = ConstructTupleDescriptor(heapRelation, indexInfo->ii_NumKeyAttrs, ! indexInfo->ii_KeyAttrNumbers, classObjectId); /* *************** *** 630,636 **** --- 637,706 ---- */ UpdateRelationRelation(indexRelation); + myself.classId = RelOid_pg_class; + myself.objectId = indexoid; + myself.objectSubId = 0; + /* + * If this is a unique index, we need to store the constraint + * information as well as the dependency on it. + */ + if (indexInfo->ii_Unique || primary) + { + char constraintType; + Oid conOid; + + if (primary) + constraintType = CONSTRAINT_PRIMARY; + else + constraintType = CONSTRAINT_UNIQUE; + + conOid = constraintCreate(heapRelationId, + indexRelationName, + constraintType, + false, /* isDeferrable */ + false, /* isDeferred */ + indexInfo->ii_KeyAttrNumbers, + indexInfo->ii_NumIndexAttrs, + NULL, /* Foreign Key Information */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* Constraint Bin & Src */ + NULL); + + dependee.classId = get_relname_relid(ConstraintRelationName, PG_CATALOG_NAMESPACE); + dependee.objectId = conOid; + dependee.objectSubId = 0; + + /* We always cascade index drops with constraint drops */ + dependCreate(&myself, &dependee, true); + } + + /* Store dependencies on the attributes */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + { + dependee.classId = RelOid_pg_class; + dependee.objectId = heapRelationId; + dependee.objectSubId = indexInfo->ii_KeyAttrNumbers[i]; + + /* We always cascade index drops with attribute drops */ + dependCreate(&myself, &dependee, true); + } + + /* Store the dependency on the function (if appropriate) */ + if (OidIsValid(indexInfo->ii_FuncOid)) + { + dependee.classId = RelOid_pg_proc; + dependee.objectId = indexInfo->ii_FuncOid; + dependee.objectSubId = 0; + + dependCreate(&myself, &dependee, false); + } + + /* * We create the disk file for this relation here */ heap_storage_create(indexRelation); *************** *** 698,704 **** * ---------------------------------------------------------------- */ void ! index_drop(Oid indexId) { Oid heapId; Relation userHeapRelation; --- 768,774 ---- * ---------------------------------------------------------------- */ void ! index_drop(Oid indexId, int behavior) { Oid heapId; Relation userHeapRelation; *************** *** 709,714 **** --- 779,786 ---- HeapTuple tuple; int16 attnum; int i; + + ObjectAddress myself; Assert(OidIsValid(indexId)); *************** *** 818,823 **** --- 890,900 ---- heap_close(userHeapRelation, NoLock); RelationForgetRelation(indexId); + + myself.classId = RelOid_pg_class; + myself.objectId = indexId; + myself.objectSubId = 0; + dependDelete(&myself, behavior); } /* ---------------------------------------------------------------- Index: src/backend/catalog/indexing.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/indexing.c,v retrieving revision 1.92 diff -c -r1.92 indexing.c *** src/backend/catalog/indexing.c 2002/04/19 16:36:08 1.92 --- src/backend/catalog/indexing.c 2002/05/09 01:42:59 *************** *** 45,52 **** --- 45,56 ---- {AttrDefaultIndex}; char *Name_pg_class_indices[Num_pg_class_indices] = {ClassNameNspIndex, ClassOidIndex}; + char *Name_pg_constraint_indices[Num_pg_constraint_indices] = + {ConstraintOidIndex, ConstraintRelidNameIndex}; char *Name_pg_database_indices[Num_pg_database_indices] = {DatabaseNameIndex, DatabaseOidIndex}; + char *Name_pg_depend_indices[Num_pg_depend_indices] = + {DependDependerIndex, DependDependeeIndex}; char *Name_pg_group_indices[Num_pg_group_indices] = {GroupNameIndex, GroupSysidIndex}; char *Name_pg_index_indices[Num_pg_index_indices] = *************** *** 65,72 **** {OperatorOidIndex, OperatorNameNspIndex}; char *Name_pg_proc_indices[Num_pg_proc_indices] = {ProcedureOidIndex, ProcedureNameNspIndex}; - char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] = - {RelCheckIndex}; char *Name_pg_rewrite_indices[Num_pg_rewrite_indices] = {RewriteOidIndex, RewriteRelRulenameIndex}; char *Name_pg_shadow_indices[Num_pg_shadow_indices] = --- 69,74 ---- Index: src/backend/catalog/namespace.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/namespace.c,v retrieving revision 1.18 diff -c -r1.18 namespace.c *** src/backend/catalog/namespace.c 2002/05/05 00:03:28 1.18 --- src/backend/catalog/namespace.c 2002/05/09 01:43:02 *************** *** 25,30 **** --- 25,31 ---- #include "catalog/catname.h" #include "catalog/heap.h" #include "catalog/namespace.h" + #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" *************** *** 1501,1507 **** { Oid reloid = (Oid) lfirsti(lptr); ! heap_drop_with_catalog(reloid, true); /* * Advance cmd counter to make catalog changes visible, in case * a later entry depends on this one. --- 1502,1512 ---- { Oid reloid = (Oid) lfirsti(lptr); ! /* ! * Cascade through all objects which depend on this one, ! * temporary or otherwise. ! */ ! heap_drop_with_catalog(reloid, true, DEPEND_CASCADE); /* * Advance cmd counter to make catalog changes visible, in case * a later entry depends on this one. Index: src/backend/catalog/pg_aggregate.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v retrieving revision 1.44 diff -c -r1.44 pg_aggregate.c *** src/backend/catalog/pg_aggregate.c 2002/04/11 19:59:57 1.44 --- src/backend/catalog/pg_aggregate.c 2002/05/09 01:43:03 *************** *** 19,24 **** --- 19,26 ---- #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" + #include "catalog/pg_depend.h" + #include "catalog/pg_namespace.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "optimizer/cost.h" *************** *** 54,59 **** --- 56,63 ---- Oid procOid; TupleDesc tupDesc; int i; + ObjectAddress myself, + dependee; /* sanity checks */ if (!aggName) *************** *** 186,190 **** --- 190,224 ---- CatalogCloseIndices(Num_pg_aggregate_indices, idescs); } + /* Define Dependencies */ + myself.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(AggregateRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + myself.objectId = tup->t_data->t_oid; + myself.objectSubId = 0; + + /* Depends on transition function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_aggregate_aggtransfn - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Depends on final function */ + if (values[Anum_pg_aggregate_aggfinalfn - 1] != InvalidOid) + { + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_aggregate_aggfinalfn - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Depends on final transition type */ + dependee.classId = RelOid_pg_type; + dependee.objectId = DatumGetObjectId(values[Anum_pg_aggregate_aggtranstype - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Cleanup */ heap_close(aggdesc, RowExclusiveLock); } Index: src/backend/catalog/pg_operator.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_operator.c,v retrieving revision 1.68 diff -c -r1.68 pg_operator.c *** src/backend/catalog/pg_operator.c 2002/04/27 03:45:00 1.68 --- src/backend/catalog/pg_operator.c 2002/05/09 01:43:04 *************** *** 21,26 **** --- 21,28 ---- #include "catalog/catname.h" #include "catalog/indexing.h" #include "catalog/namespace.h" + #include "catalog/pg_depend.h" + #include "catalog/pg_namespace.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" #include "miscadmin.h" *************** *** 263,268 **** --- 265,271 ---- heap_insert(pg_operator_desc, tup); operatorObjectId = tup->t_data->t_oid; + /* Keep indexes up to date */ if (RelationGetForm(pg_operator_desc)->relhasindex) { Relation idescs[Num_pg_operator_indices]; *************** *** 404,409 **** --- 407,415 ---- TupleDesc tupDesc; int i; + ObjectAddress myself, + dependee; + /* * Sanity checks */ *************** *** 659,664 **** --- 665,766 ---- CatalogOpenIndices(Num_pg_operator_indices, Name_pg_operator_indices, idescs); CatalogIndexInsert(idescs, Num_pg_operator_indices, pg_operator_desc, tup); CatalogCloseIndices(Num_pg_operator_indices, idescs); + } + + /* Load our object address */ + myself.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(OperatorRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + myself.objectId = operatorObjectId; + myself.objectSubId = 0; + + /* Dependency on left type */ + if (DatumGetObjectId(values[Anum_pg_operator_oprleft - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_type; + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprleft - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on right type */ + if (DatumGetObjectId(values[Anum_pg_operator_oprright - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_type; + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprright - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on result type */ + dependee.classId = RelOid_pg_type; + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprresult - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on commutator */ + if (DatumGetObjectId(values[Anum_pg_operator_oprcom - 1]) != InvalidOid) { + dependee.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(OperatorRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprcom - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on negator */ + if (DatumGetObjectId(values[Anum_pg_operator_oprnegate - 1]) != InvalidOid) { + dependee.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(OperatorRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprnegate - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on sort left hand operator */ + if (DatumGetObjectId(values[Anum_pg_operator_oprjoin - 1]) != InvalidOid) { + dependee.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(OperatorRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprlsortop - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on sort right hand operator */ + if (DatumGetObjectId(values[Anum_pg_operator_oprrsortop - 1]) != InvalidOid) { + dependee.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(OperatorRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprrsortop - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on implementation function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprcode - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on restriction selectivity function */ + if (DatumGetObjectId(values[Anum_pg_operator_oprjoin - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprrest - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + /* Dependency on join selectifity function */ + if (DatumGetObjectId(values[Anum_pg_operator_oprjoin - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_operator_oprjoin - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); } heap_close(pg_operator_desc, RowExclusiveLock); Index: src/backend/catalog/pg_proc.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_proc.c,v retrieving revision 1.70 diff -c -r1.70 pg_proc.c *** src/backend/catalog/pg_proc.c 2002/04/11 19:59:57 1.70 --- src/backend/catalog/pg_proc.c 2002/05/09 01:43:05 *************** *** 17,23 **** --- 17,25 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/pg_language.h" + #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "executor/executor.h" #include "miscadmin.h" *************** *** 73,78 **** --- 75,83 ---- TupleDesc tupDesc; Oid retval; + ObjectAddress myself, + dependee; + /* * sanity checks */ *************** *** 312,317 **** --- 317,361 ---- } retval = tup->t_data->t_oid; + + /* Record Dependencies */ + myself.classId = RelOid_pg_proc; + myself.objectId = retval; + myself.objectSubId = 0; + + /* Procedure on Language */ + dependee.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(LanguageRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + dependee.objectId = languageObjectId; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* + * Return Types are skipped in it's an InvalidOid (opaque) or if + * the type is a shell type (prevent a type <-> function dependency) + */ + if (returnType != InvalidOid && get_typisdefined(returnType)) + { + dependee.classId = RelOid_pg_type; + dependee.objectId = returnType; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + + for (i = 0; i < parameterCount; i++) + { + /* Parameter Types */ + if (typev[i] != InvalidOid) + { + dependee.classId = RelOid_pg_type; + dependee.objectId = typev[i]; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + } + } + heap_freetuple(tup); heap_close(rel, RowExclusiveLock); Index: src/backend/catalog/pg_type.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_type.c,v retrieving revision 1.70 diff -c -r1.70 pg_type.c *** src/backend/catalog/pg_type.c 2002/03/29 19:06:02 1.70 --- src/backend/catalog/pg_type.c 2002/05/09 01:43:05 *************** *** 17,22 **** --- 17,23 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/builtins.h" *************** *** 167,172 **** --- 168,175 ---- NameData name; TupleDesc tupDesc; int i; + ObjectAddress myself, + dependee; /* * validate size specifications: either positive (fixed-length) or -1 *************** *** 299,304 **** --- 302,363 ---- CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs); CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup); CatalogCloseIndices(Num_pg_type_indices, idescs); + } + + /* + * Create dependencies + */ + + /* Load our object address */ + myself.classId = RelOid_pg_type; + myself.objectId = typeObjectId; + myself.objectSubId = 0; + + /* Dependency on the input function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typinput - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on the output function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typoutput - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on the receive function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typreceive - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* Dependency on the send function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typsend - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* + * Dependency on the relation for complex types. Assume it's for + * a relation of somekind and drop it when the relation is removed. + */ + if (DatumGetObjectId(values[Anum_pg_type_typrelid - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_class; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typrelid - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); + } + + /* + * Dependency on the element Id for arrays. We can assume that it's for + * an array and that we should always cascade into this type when the base + * type is being removed. + */ + if (DatumGetObjectId(values[Anum_pg_type_typelem - 1]) != InvalidOid) { + dependee.classId = RelOid_pg_type; + dependee.objectId = DatumGetObjectId(values[Anum_pg_type_typelem - 1]); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); } /* Index: src/backend/commands/aggregatecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v retrieving revision 1.2 diff -c -r1.2 aggregatecmds.c *** src/backend/commands/aggregatecmds.c 2002/04/27 03:45:00 1.2 --- src/backend/commands/aggregatecmds.c 2002/05/09 01:43:06 *************** *** 26,31 **** --- 26,32 ---- #include "catalog/catname.h" #include "catalog/namespace.h" #include "catalog/pg_aggregate.h" + #include "catalog/pg_depend.h" #include "catalog/pg_proc.h" #include "commands/comment.h" #include "commands/defrem.h" *************** *** 142,148 **** void ! RemoveAggregate(List *aggName, TypeName *aggType) { Relation relation; HeapTuple tup; --- 143,149 ---- void ! RemoveAggregate(List *aggName, TypeName *aggType, int behavior) { Relation relation; HeapTuple tup; *************** *** 178,183 **** --- 179,187 ---- !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(aggName)); + + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, behavior); /* Delete any comments associated with this function */ DeleteComments(procOid, RelationGetRelid(relation)); Index: src/backend/commands/cluster.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/cluster.c,v retrieving revision 1.79 diff -c -r1.79 cluster.c *** src/backend/commands/cluster.c 2002/04/27 21:24:34 1.79 --- src/backend/commands/cluster.c 2002/05/09 01:43:06 *************** *** 26,31 **** --- 26,32 ---- #include "access/heapam.h" #include "catalog/heap.h" #include "catalog/index.h" + #include "catalog/pg_depend.h" #include "catalog/pg_index.h" #include "catalog/pg_proc.h" #include "commands/cluster.h" *************** *** 118,125 **** CommandCounterIncrement(); ! /* Destroy old heap (along with its index) and rename new. */ ! heap_drop_with_catalog(OIDOldHeap, allowSystemTableMods); CommandCounterIncrement(); --- 119,129 ---- CommandCounterIncrement(); ! /* ! * Destroy old heap (along with its index) and rename new without ! * blowing away objects which depend on this one. ! */ ! heap_drop_with_catalog(OIDOldHeap, allowSystemTableMods, DEPEND_IMPLICITONLY); CommandCounterIncrement(); Index: src/backend/commands/functioncmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/functioncmds.c,v retrieving revision 1.3 diff -c -r1.3 functioncmds.c *** src/backend/commands/functioncmds.c 2002/04/27 03:45:01 1.3 --- src/backend/commands/functioncmds.c 2002/05/09 01:43:08 *************** *** 34,39 **** --- 34,40 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/namespace.h" + #include "catalog/pg_depend.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" *************** *** 399,404 **** --- 400,406 ---- /* * RemoveFunction + * RemoveFunctionById * Deletes a function. * * Exceptions: *************** *** 408,422 **** */ void RemoveFunction(List *functionName, /* function name to be removed */ ! List *argTypes) /* list of TypeName nodes */ { Oid funcOid; - Relation relation; - HeapTuple tup; funcOid = LookupFuncNameTypeNames(functionName, argTypes, true, "RemoveFunction"); relation = heap_openr(ProcedureRelationName, RowExclusiveLock); tup = SearchSysCache(PROCOID, --- 410,432 ---- */ void RemoveFunction(List *functionName, /* function name to be removed */ ! List *argTypes, /* list of TypeName nodes */ ! int behavior) { Oid funcOid; funcOid = LookupFuncNameTypeNames(functionName, argTypes, true, "RemoveFunction"); + RemoveFunctionById(funcOid, behavior); + }; + + void + RemoveFunctionById(Oid funcOid, int behavior) + { + Relation relation; + HeapTuple tup; + relation = heap_openr(ProcedureRelationName, RowExclusiveLock); tup = SearchSysCache(PROCOID, *************** *** 424,448 **** 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "RemoveFunction: couldn't find tuple for function %s", ! NameListToString(functionName)); /* Permission check: must own func or its namespace */ if (!pg_proc_ownercheck(funcOid, GetUserId()) && !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace, GetUserId())) ! aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(functionName)); if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) elog(ERROR, "RemoveFunction: function '%s' is an aggregate" "\n\tUse DROP AGGREGATE to remove it", ! NameListToString(functionName)); ! if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId) ! { ! /* "Helpful" WARNING when removing a builtin function ... */ ! elog(WARNING, "Removing built-in function \"%s\"", ! NameListToString(functionName)); ! } /* Delete any comments associated with this function */ DeleteComments(funcOid, RelationGetRelid(relation)); --- 434,457 ---- 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "RemoveFunction: couldn't find tuple for function %s", ! get_func_name(funcOid)); /* Permission check: must own func or its namespace */ if (!pg_proc_ownercheck(funcOid, GetUserId()) && !pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace, GetUserId())) ! aclcheck_error(ACLCHECK_NOT_OWNER, get_func_name(funcOid)); if (((Form_pg_proc) GETSTRUCT(tup))->proisagg) elog(ERROR, "RemoveFunction: function '%s' is an aggregate" "\n\tUse DROP AGGREGATE to remove it", ! get_func_name(funcOid)); ! /* ! * Deal with dependencies ! * Manages system function restrictions for us as well. ! */ ! dependDeleteTuple(tup, relation, behavior); /* Delete any comments associated with this function */ DeleteComments(funcOid, RelationGetRelid(relation)); Index: src/backend/commands/indexcmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/indexcmds.c,v retrieving revision 1.72 diff -c -r1.72 indexcmds.c *** src/backend/commands/indexcmds.c 2002/04/27 03:45:01 1.72 --- src/backend/commands/indexcmds.c 2002/05/09 01:43:09 *************** *** 566,572 **** * ... */ void ! RemoveIndex(RangeVar *relation) { Oid indOid; HeapTuple tuple; --- 566,572 ---- * ... */ void ! RemoveIndex(RangeVar *relation, int behavior) { Oid indOid; HeapTuple tuple; *************** *** 584,590 **** ReleaseSysCache(tuple); ! index_drop(indOid); } /* --- 584,590 ---- ReleaseSysCache(tuple); ! index_drop(indOid, behavior); } /* Index: src/backend/commands/operatorcmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/operatorcmds.c,v retrieving revision 1.3 diff -c -r1.3 operatorcmds.c *** src/backend/commands/operatorcmds.c 2002/04/27 03:45:01 1.3 --- src/backend/commands/operatorcmds.c 2002/05/09 01:43:10 *************** *** 37,42 **** --- 37,43 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/namespace.h" + #include "catalog/pg_depend.h" #include "catalog/pg_operator.h" #include "commands/comment.h" #include "commands/defrem.h" *************** *** 208,213 **** --- 209,215 ---- /* * RemoveOperator + * RemoveOperatorById * Deletes an operator. * * Exceptions: *************** *** 219,233 **** void RemoveOperator(List *operatorName, /* operator name */ TypeName *typeName1, /* left argument type name */ ! TypeName *typeName2) /* right argument type name */ { Oid operOid; - Relation relation; - HeapTuple tup; operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2, "RemoveOperator"); relation = heap_openr(OperatorRelationName, RowExclusiveLock); tup = SearchSysCacheCopy(OPEROID, --- 221,242 ---- void RemoveOperator(List *operatorName, /* operator name */ TypeName *typeName1, /* left argument type name */ ! TypeName *typeName2, /* right argument type name */ ! int behavior) { Oid operOid; operOid = LookupOperNameTypeNames(operatorName, typeName1, typeName2, "RemoveOperator"); + RemoveOperatorById(operOid, behavior); + } + + void + RemoveOperatorById(Oid operOid, int behavior) + { + Relation relation; + HeapTuple tup; relation = heap_openr(OperatorRelationName, RowExclusiveLock); tup = SearchSysCacheCopy(OPEROID, *************** *** 235,248 **** 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'", ! NameListToString(operatorName)); /* Permission check: must own operator or its namespace */ if (!pg_oper_ownercheck(operOid, GetUserId()) && !pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace, GetUserId())) ! aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(operatorName)); /* Delete any comments associated with this operator */ DeleteComments(operOid, RelationGetRelid(relation)); --- 244,264 ---- 0, 0, 0); if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'", ! get_opname(operOid)); /* Permission check: must own operator or its namespace */ if (!pg_oper_ownercheck(operOid, GetUserId()) && !pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace, GetUserId())) ! aclcheck_error(ACLCHECK_NOT_OWNER, get_opname(operOid)); + if (!pg_oper_ownercheck(operOid, GetUserId())) + elog(ERROR, "RemoveOperator: operator '%s': permission denied", + get_opname(operOid)); + + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, behavior); + /* Delete any comments associated with this operator */ DeleteComments(operOid, RelationGetRelid(relation)); Index: src/backend/commands/proclang.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/proclang.c,v retrieving revision 1.31 diff -c -r1.31 proclang.c *** src/backend/commands/proclang.c 2002/04/15 05:22:03 1.31 --- src/backend/commands/proclang.c 2002/05/09 01:43:10 *************** *** 18,23 **** --- 18,24 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/namespace.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" *************** *** 48,53 **** --- 49,57 ---- TupleDesc tupDesc; int i; + ObjectAddress myself, + dependee; + /* * Check permission */ *************** *** 79,84 **** --- 83,93 ---- elog(ERROR, "PL handler function %s() isn't of return type Opaque", NameListToString(stmt->plhandler)); + /* Address of the PL handler function */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = procOid; + dependee.objectSubId = 0; + /* * Insert the new language into pg_language */ *************** *** 113,118 **** --- 122,135 ---- CatalogCloseIndices(Num_pg_language_indices, idescs); } + /* Address of myself */ + myself.classId = RelationGetRelid(rel); + myself.objectId = tup->t_data->t_oid; + myself.objectSubId = 0; + + /* Create dependency on the language PL Handler function */ + dependCreate(&myself, &dependee, false); + heap_close(rel, RowExclusiveLock); } *************** *** 152,157 **** --- 169,177 ---- if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl) elog(ERROR, "Language %s isn't a created procedural language", languageName); + + /* Deal with Dependencies */ + dependDeleteTuple(langTup, rel, stmt->behavior); simple_heap_delete(rel, &langTup->t_self); Index: src/backend/commands/tablecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablecmds.c,v retrieving revision 1.12 diff -c -r1.12 tablecmds.c *** src/backend/commands/tablecmds.c 2002/04/27 21:24:34 1.12 --- src/backend/commands/tablecmds.c 2002/05/09 01:43:15 *************** *** 23,28 **** --- 23,30 ---- #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_attrdef.h" + #include "catalog/pg_constraint.h" + #include "catalog/pg_depend.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" *************** *** 239,247 **** --- 241,274 ---- { ColumnDef *colDef = lfirst(listptr); RawColumnDefault *rawEnt; + ObjectAddress myself, + dependee; attnum++; + myself.classId = RelOid_pg_class; + myself.objectId = relationId; + myself.objectSubId = attnum; + + /* + * Seek for serial dependency + * The sequence must have been created first! + */ + if (colDef->typename->serial != NULL) { + ObjectAddress depender; + + depender.classId = RelOid_pg_class; + depender.objectId = RangeVarGetRelid(colDef->typename->serial, false); + depender.objectSubId = 0; + dependCreate(&depender, &myself, true); + } + + /* Store the column dependency on the column type */ + dependee.classId = RelOid_pg_type; + dependee.objectId = LookupTypeName(colDef->typename); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + if (colDef->raw_default == NULL) continue; Assert(colDef->cooked_default == NULL); *************** *** 279,290 **** * themselves will be destroyed, too. */ void ! RemoveRelation(const RangeVar *relation) { Oid relOid; relOid = RangeVarGetRelid(relation, false); ! heap_drop_with_catalog(relOid, allowSystemTableMods); } /* --- 306,317 ---- * themselves will be destroyed, too. */ void ! RemoveRelation(const RangeVar *relation, int behavior) { Oid relOid; relOid = RangeVarGetRelid(relation, false); ! heap_drop_with_catalog(relOid, allowSystemTableMods, behavior); } /* *************** *** 2649,2654 **** --- 2676,2691 ---- pfree(trig.tgargs); + /* + * Call AddRelationRawConstraints to do + * the real adding -- It duplicates some + * of the above, but does not check the + * validity of the constraint against + * tuples already in the table. + */ + AddRelationRawConstraints(rel, NIL, + makeList1(fkconstraint)); + heap_close(pkrel, NoLock); break; *************** *** 2662,2668 **** heap_close(rel, NoLock); } - /* * ALTER TABLE DROP CONSTRAINT * Note: It is legal to remove a constraint with name "" as it is possible --- 2699,2704 ---- *************** *** 2678,2690 **** int deleted; /* - * We don't support CASCADE yet - in fact, RESTRICT doesn't work to - * the spec either! - */ - if (behavior == CASCADE) - elog(ERROR, "ALTER TABLE / DROP CONSTRAINT does not support the CASCADE keyword"); - - /* * Acquire an exclusive lock on the target relation for the duration * of the operation. */ --- 2714,2719 ---- *************** *** 2711,2722 **** */ deleted = 0; - - /* - * First, we remove all CHECK constraints with the given name - */ - - deleted += RemoveCheckConstraint(rel, constrName, inh); /* * Now we remove NULL, UNIQUE, PRIMARY KEY and FOREIGN KEY --- 2740,2745 ---- Index: src/backend/commands/trigger.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/trigger.c,v retrieving revision 1.117 diff -c -r1.117 trigger.c *** src/backend/commands/trigger.c 2002/04/30 01:24:57 1.117 --- src/backend/commands/trigger.c 2002/05/09 01:43:20 *************** *** 18,23 **** --- 18,24 ---- #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" #include "catalog/namespace.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" *************** *** 74,79 **** --- 75,83 ---- char constrtrigname[NAMEDATALEN]; char *constrname = ""; Oid constrrelid = InvalidOid; + Oid insertOid, insertTupOid; + ObjectAddress myself, + dependee; rel = heap_openrv(stmt->relation, AccessExclusiveLock); *************** *** 267,272 **** --- 271,278 ---- tuple = heap_formtuple(tgrel->rd_att, values, nulls); + insertOid = tgrel->rd_id; + /* * Insert tuple into pg_trigger. */ *************** *** 274,279 **** --- 280,289 ---- CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs); CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple); CatalogCloseIndices(Num_pg_trigger_indices, idescs); + + /* Need the Inserted Tup Oid below for the address of 'myself' */ + insertTupOid = tuple->t_data->t_oid; + heap_freetuple(tuple); heap_close(tgrel, RowExclusiveLock); *************** *** 302,307 **** --- 312,345 ---- heap_close(pgrel, RowExclusiveLock); /* + * Insert dependencies + */ + myself.classId = insertOid; + myself.objectId = insertTupOid; + myself.objectSubId = 0; + + /* tgrelid */ + dependee.classId = RelOid_pg_class; + dependee.objectId = RelationGetRelid(rel); + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); + + /* tgfoid */ + dependee.classId = RelOid_pg_proc; + dependee.objectId = funcoid; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, false); + + /* tgconstrrelid */ + if (constrrelid != InvalidOid) + { + dependee.classId = RelOid_pg_class; + dependee.objectId = constrrelid; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); + } + + /* * We used to try to update the rel's relcache entry here, but that's * fairly pointless since it will happen as a byproduct of the * upcoming CommandCounterIncrement... *************** *** 315,321 **** * DropTrigger - drop an individual trigger by name */ void ! DropTrigger(Oid relid, const char *trigname) { Relation rel; Relation tgrel; --- 353,359 ---- * DropTrigger - drop an individual trigger by name */ void ! DropTrigger(Oid relid, const char *trigname, int behavior) { Relation rel; Relation tgrel; *************** *** 363,368 **** --- 401,409 ---- if (namestrcmp(&(pg_trigger->tgname), trigname) == 0) { + /* Deal with dependencies */ + dependDeleteTuple(tuple, tgrel, behavior); + /* Delete any comments associated with this trigger */ DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel)); *************** *** 408,505 **** } /* ! * Remove all triggers for a relation that's being deleted. */ void ! RelationRemoveTriggers(Relation rel) { ! Relation tgrel; ! SysScanDesc tgscan; ! ScanKeyData key; ! HeapTuple tup; ! bool found = false; tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); ! ScanKeyEntryInitialize(&key, 0, ! Anum_pg_trigger_tgrelid, F_OIDEQ, ! ObjectIdGetDatum(RelationGetRelid(rel))); ! tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, ! SnapshotNow, 1, &key); ! while (HeapTupleIsValid(tup = systable_getnext(tgscan))) ! { ! /* Delete any comments associated with this trigger */ ! DeleteComments(tup->t_data->t_oid, RelationGetRelid(tgrel)); ! simple_heap_delete(tgrel, &tup->t_self); ! found = true; ! } ! systable_endscan(tgscan); ! /* ! * If we deleted any triggers, must update pg_class entry and advance ! * command counter to make the updated entry visible. This is fairly ! * annoying, since we'e just going to drop the durn thing later, but ! * it's necessary to have a consistent state in case we do ! * CommandCounterIncrement() below --- if RelationBuildTriggers() ! * runs, it will complain otherwise. Perhaps RelationBuildTriggers() ! * shouldn't be so picky... ! */ ! if (found) ! { ! Relation pgrel; ! Relation ridescs[Num_pg_class_indices]; ! pgrel = heap_openr(RelationRelationName, RowExclusiveLock); ! tup = SearchSysCacheCopy(RELOID, ! ObjectIdGetDatum(RelationGetRelid(rel)), ! 0, 0, 0); ! if (!HeapTupleIsValid(tup)) ! elog(ERROR, "RelationRemoveTriggers: relation %u not found in pg_class", ! RelationGetRelid(rel)); ! ! ((Form_pg_class) GETSTRUCT(tup))->reltriggers = 0; ! simple_heap_update(pgrel, &tup->t_self, tup); ! CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); ! CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tup); ! CatalogCloseIndices(Num_pg_class_indices, ridescs); ! heap_freetuple(tup); ! heap_close(pgrel, RowExclusiveLock); ! CommandCounterIncrement(); ! } /* ! * Also drop all constraint triggers referencing this relation */ ! ScanKeyEntryInitialize(&key, 0, ! Anum_pg_trigger_tgconstrrelid, ! F_OIDEQ, ! ObjectIdGetDatum(RelationGetRelid(rel))); ! tgscan = systable_beginscan(tgrel, TriggerConstrRelidIndex, true, ! SnapshotNow, 1, &key); ! ! while (HeapTupleIsValid(tup = systable_getnext(tgscan))) ! { ! Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tup); ! elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", ! get_rel_name(pg_trigger->tgrelid)); ! DropTrigger(pg_trigger->tgrelid, NameStr(pg_trigger->tgname)); ! /* ! * Need to do a command counter increment here to show up new ! * pg_class.reltriggers in the next loop iteration (in case there ! * are multiple referential integrity action triggers for the same ! * FK table defined on the PK table). ! */ ! CommandCounterIncrement(); ! } ! systable_endscan(tgscan); heap_close(tgrel, RowExclusiveLock); } --- 449,528 ---- } /* ! * DropTriggerById - Drop a trigger by it's OID */ void ! DropTriggerById(Oid trigId, int behavior) { ! Relation rel; ! Relation tgrel; ! HeapScanDesc tgscan; ! ScanKeyData key[1]; ! Relation pgrel; ! HeapTuple tuple; ! Relation ridescs[Num_pg_class_indices]; ! Form_pg_trigger pg_trigger; ! Form_pg_class pg_class; ! int nkeys = 0; + /* + * Search pg_trigger, delete target trigger, count remaining triggers + * for relation. Note this is OK only because we have + * AccessExclusiveLock on the rel, so no one else is creating/deleting + * triggers on this rel at the same time. + */ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); ! ScanKeyEntryInitialize(&key[nkeys++], 0, ObjectIdAttributeNumber, F_OIDEQ, ! ObjectIdGetDatum(trigId)); ! tgscan = heap_beginscan(tgrel, 0, SnapshotNow, nkeys, key); ! tuple = heap_getnext(tgscan, 0); ! if (!HeapTupleIsValid(tuple)) ! elog(ERROR, "DropTriggerById: TriggerID %d not valid", trigId); ! /* Grab the info, and lock the triggers relation */ ! pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple); ! ! rel = heap_open(pg_trigger->tgrelid, AccessExclusiveLock); ! /* Deal with dependencies */ ! dependDeleteTuple(tuple, tgrel, behavior); ! /* Delete any comments associated with this trigger */ ! DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel)); ! ! simple_heap_delete(tgrel, &tuple->t_self); ! ! heap_endscan(tgscan); ! heap_close(rel, AccessExclusiveLock); /* ! * Update relation's pg_class entry. Crucial side-effect: other ! * backends (and this one too!) are sent SI message to make them ! * rebuild relcache entries. */ ! pgrel = heap_openr(RelationRelationName, RowExclusiveLock); ! tuple = SearchSysCacheCopy(RELOID, ! ObjectIdGetDatum(RelationGetRelid(rel)), ! 0, 0, 0); ! if (!HeapTupleIsValid(tuple)) ! elog(ERROR, "DropTriggerById: relation %s not found in pg_class", ! RelationGetRelationName(rel)); ! pg_class = (Form_pg_class) GETSTRUCT(tuple); ! pg_class->reltriggers -= 1; ! simple_heap_update(pgrel, &tuple->t_self, tuple); ! CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); ! CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple); ! CatalogCloseIndices(Num_pg_class_indices, ridescs); ! heap_freetuple(tuple); + heap_close(pgrel, RowExclusiveLock); heap_close(tgrel, RowExclusiveLock); } Index: src/backend/commands/typecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/typecmds.c,v retrieving revision 1.3 diff -c -r1.3 typecmds.c *** src/backend/commands/typecmds.c 2002/05/03 00:32:16 1.3 --- src/backend/commands/typecmds.c 2002/05/09 01:43:20 *************** *** 35,40 **** --- 35,41 ---- #include "catalog/catname.h" #include "catalog/heap.h" #include "catalog/namespace.h" + #include "catalog/pg_depend.h" #include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/defrem.h" *************** *** 268,279 **** * only work on scalar types. */ void ! RemoveType(List *names) { TypeName *typename; - Relation relation; - Oid typeoid; - HeapTuple tup; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeNode(TypeName); --- 269,277 ---- * only work on scalar types. */ void ! RemoveType(List *names, int behavior) { TypeName *typename; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeNode(TypeName); *************** *** 281,286 **** --- 279,298 ---- typename->typmod = -1; typename->arrayBounds = NIL; + RemoveTypeByTypeName(typename, behavior); + } + + /* + * TypeRemove + * Removes a datatype by the typename struct + */ + void + RemoveTypeByTypeName(TypeName *typename, int behavior) + { + Relation relation; + Oid typeoid; + HeapTuple tup; + relation = heap_openr(TypeRelationName, RowExclusiveLock); /* Use LookupTypeName here so that shell types can be removed. */ *************** *** 301,329 **** !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename)); - - /* Delete any comments associated with this type */ - DeleteComments(typeoid, RelationGetRelid(relation)); ! /* Remove the type tuple from pg_type */ ! simple_heap_delete(relation, &tup->t_self); ! ! ReleaseSysCache(tup); ! ! /* Now, delete the "array of" that type */ ! typename->arrayBounds = makeList1(makeInteger(1)); ! ! typeoid = LookupTypeName(typename); ! if (!OidIsValid(typeoid)) ! elog(ERROR, "Type \"%s\" does not exist", TypeNameToString(typename)); ! tup = SearchSysCache(TYPEOID, ! ObjectIdGetDatum(typeoid), ! 0, 0, 0); ! if (!HeapTupleIsValid(tup)) ! elog(ERROR, "Type \"%s\" does not exist", ! TypeNameToString(typename)); DeleteComments(typeoid, RelationGetRelid(relation)); --- 313,325 ---- !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename)); ! if (!pg_type_ownercheck(typeoid, GetUserId())) ! elog(ERROR, "RemoveType: type '%s': permission denied", TypeNameToString(typename)); ! /* Deal with dependencies */ ! dependDeleteTuple(tup, relation, behavior); DeleteComments(typeoid, RelationGetRelid(relation)); *************** *** 582,591 **** HeapTuple tup; char typtype; - /* CASCADE unsupported */ - if (behavior == CASCADE) - elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword"); - /* Make a TypeName so we can use standard type lookup machinery */ typename = makeNode(TypeName); typename->names = names; --- 578,583 ---- *************** *** 615,620 **** --- 607,615 ---- if (typtype != 'd') elog(ERROR, "%s is not a domain", TypeNameToString(typename)); + + /* Deal with dependencies */ + dependDeleteTuple(tup, relation, behavior); /* Delete any comments associated with this type */ DeleteComments(typeoid, RelationGetRelid(relation)); Index: src/backend/commands/view.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/view.c,v retrieving revision 1.63 diff -c -r1.63 view.c *** src/backend/commands/view.c 2002/04/19 23:13:54 1.63 --- src/backend/commands/view.c 2002/05/09 01:43:20 *************** *** 255,261 **** *------------------------------------------------------------------ */ void ! RemoveView(const RangeVar *view) { Oid viewOid; --- 255,261 ---- *------------------------------------------------------------------ */ void ! RemoveView(const RangeVar *view, int behavior) { Oid viewOid; *************** *** 264,268 **** * We just have to drop the relation; the associated rules will be * cleaned up automatically. */ ! heap_drop_with_catalog(viewOid, allowSystemTableMods); } --- 264,268 ---- * We just have to drop the relation; the associated rules will be * cleaned up automatically. */ ! heap_drop_with_catalog(viewOid, allowSystemTableMods, behavior); } Index: src/backend/nodes/copyfuncs.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v retrieving revision 1.182 diff -c -r1.182 copyfuncs.c *** src/backend/nodes/copyfuncs.c 2002/04/28 19:54:28 1.182 --- src/backend/nodes/copyfuncs.c 2002/05/09 01:43:23 *************** *** 1633,1638 **** --- 1633,1639 ---- newnode->setof = from->setof; newnode->pct_type = from->pct_type; newnode->typmod = from->typmod; + newnode->serial = from->serial; Node_Copy(from, newnode, arrayBounds); return newnode; Index: src/backend/nodes/equalfuncs.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v retrieving revision 1.130 diff -c -r1.130 equalfuncs.c *** src/backend/nodes/equalfuncs.c 2002/04/28 19:54:28 1.130 --- src/backend/nodes/equalfuncs.c 2002/05/09 01:43:26 *************** *** 1590,1595 **** --- 1590,1597 ---- return false; if (!equal(a->arrayBounds, b->arrayBounds)) return false; + if (a->serial != b->serial) + return false; return true; } Index: src/backend/parser/analyze.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/analyze.c,v retrieving revision 1.233 diff -c -r1.233 analyze.c *** src/backend/parser/analyze.c 2002/04/28 19:54:28 1.233 --- src/backend/parser/analyze.c 2002/05/09 01:43:32 *************** *** 773,781 **** q->commandType = CMD_UTILITY; q->utilityStmt = (Node *) stmt; stmt->tableElts = cxt.columns; ! stmt->constraints = cxt.ckconstraints; ! *extras_before = nconc (*extras_before, cxt.blist); ! *extras_after = nconc (cxt.alist, *extras_after); return q; } --- 773,781 ---- q->commandType = CMD_UTILITY; q->utilityStmt = (Node *) stmt; stmt->tableElts = cxt.columns; ! stmt->constraints = nconc(cxt.ckconstraints, cxt.fkconstraints); ! *extras_before = nconc(*extras_before, cxt.blist); ! *extras_after = nconc(cxt.alist, *extras_after); return q; } *************** *** 826,837 **** --- 826,839 ---- A_Const *snamenode; FuncCall *funccallnode; CreateSeqStmt *seqstmt; + RangeVar *srvar; /* * Determine name and namespace to use for the sequence. */ sname = makeObjectName(cxt->relation->relname, column->colname, "seq"); snamespace = get_namespace_name(RangeVarGetCreationNamespace(cxt->relation)); + srvar=makeRangeVar(snamespace, sname); elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'", cxt->stmtType, sname, cxt->relation->relname, column->colname); *************** *** 842,853 **** * CREATE/ALTER TABLE. */ seqstmt = makeNode(CreateSeqStmt); ! seqstmt->sequence = makeRangeVar(snamespace, sname); seqstmt->options = NIL; cxt->blist = lappend(cxt->blist, seqstmt); /* * Create appropriate constraints for SERIAL. We do this in full, * rather than shortcutting, so that we will detect any * conflicting constraints the user wrote (like a different --- 844,861 ---- * CREATE/ALTER TABLE. */ seqstmt = makeNode(CreateSeqStmt); ! seqstmt->sequence = srvar; seqstmt->options = NIL; cxt->blist = lappend(cxt->blist, seqstmt); /* + * Keep the serial name so that lateron the table can create an + * implicit dependency to drop the serial with the table + */ + column->typename->serial = srvar; + + /* * Create appropriate constraints for SERIAL. We do this in full, * rather than shortcutting, so that we will detect any * conflicting constraints the user wrote (like a different *************** *** 1326,1337 **** FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist); int attnum; List *fkattrs; /* * If the constraint has no name, set it to */ if (fkconstraint->constr_name == NULL) ! fkconstraint->constr_name = ""; for (attnum = 0; attnum < INDEX_MAX_KEYS; attnum++) pktypoid[attnum] = fktypoid[attnum] = InvalidOid; --- 1334,1348 ---- FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist); int attnum; List *fkattrs; + char *fkname; /* * If the constraint has no name, set it to */ if (fkconstraint->constr_name == NULL) ! fkname = ""; ! else ! fkname = fkconstraint->constr_name; for (attnum = 0; attnum < INDEX_MAX_KEYS; attnum++) pktypoid[attnum] = fktypoid[attnum] = InvalidOid; *************** *** 1478,1484 **** * action. */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); ! fk_trigger->trigname = fkconstraint->constr_name; fk_trigger->relation = cxt->relation; fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins"); fk_trigger->before = false; --- 1489,1495 ---- * action. */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); ! fk_trigger->trigname = fkname; fk_trigger->relation = cxt->relation; fk_trigger->funcname = SystemFuncName("RI_FKey_check_ins"); fk_trigger->before = false; *************** *** 1498,1504 **** fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, ! makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, --- 1509,1515 ---- fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, ! makeString(fkname)); fk_trigger->args = lappend(fk_trigger->args, makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, *************** *** 1533,1539 **** * action fired on the PK table !!! */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); ! fk_trigger->trigname = fkconstraint->constr_name; fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; --- 1544,1550 ---- * action fired on the PK table !!! */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); ! fk_trigger->trigname = fkname; fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; *************** *** 1575,1581 **** fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, ! makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, --- 1586,1592 ---- fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, ! makeString(fkname)); fk_trigger->args = lappend(fk_trigger->args, makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, *************** *** 1605,1611 **** * action fired on the PK table !!! */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); ! fk_trigger->trigname = fkconstraint->constr_name; fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; --- 1616,1622 ---- * action fired on the PK table !!! */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); ! fk_trigger->trigname = fkname; fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; *************** *** 1647,1653 **** fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, ! makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, --- 1658,1664 ---- fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, ! makeString(fkname)); fk_trigger->args = lappend(fk_trigger->args, makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, *************** *** 2596,2602 **** transformIndexConstraints(pstate, &cxt); transformFKConstraints(pstate, &cxt); ! ((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints; *extras_before = nconc(*extras_before, cxt.blist); *extras_after = nconc(cxt.alist, *extras_after); break; --- 2607,2613 ---- transformIndexConstraints(pstate, &cxt); transformFKConstraints(pstate, &cxt); ! ((ColumnDef *) stmt->def)->constraints = nconc(cxt.ckconstraints, cxt.fkconstraints); *extras_before = nconc(*extras_before, cxt.blist); *extras_after = nconc(cxt.alist, *extras_after); break; Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.313 diff -c -r2.313 gram.y *** src/backend/parser/gram.y 2002/05/06 19:47:30 2.313 --- src/backend/parser/gram.y 2002/05/09 01:43:41 *************** *** 52,57 **** --- 52,58 ---- #include "access/htup.h" #include "catalog/index.h" + #include "catalog/pg_depend.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "nodes/params.h" *************** *** 1197,1209 **** | DROP DEFAULT { $$ = NULL; } ; ! drop_behavior: CASCADE { $$ = CASCADE; } ! | RESTRICT { $$ = RESTRICT; } ; ! opt_drop_behavior: CASCADE { $$ = CASCADE; } ! | RESTRICT { $$ = RESTRICT; } ! | /* EMPTY */ { $$ = RESTRICT; /* default */ } ; --- 1198,1210 ---- | DROP DEFAULT { $$ = NULL; } ; ! drop_behavior: CASCADE { $$ = DEPEND_CASCADE; } ! | RESTRICT { $$ = DEPEND_RESTRICT; } ; ! opt_drop_behavior: CASCADE { $$ = DEPEND_CASCADE; } ! | RESTRICT { $$ = DEPEND_RESTRICT; } ! | /* EMPTY */ { $$ = DEPEND_RESTRICT; /* default */ } ; *************** *** 1819,1825 **** n->plname = $5; n->plhandler = $7; n->plcompiler = $8; ! n->pltrusted = $2; $$ = (Node *)n; } ; --- 1820,1826 ---- n->plname = $5; n->plhandler = $7; n->plcompiler = $8; ! n->pltrusted = $2; $$ = (Node *)n; } ; *************** *** 1842,1851 **** | /*EMPTY*/ { $$ = ""; } ; ! DropPLangStmt: DROP opt_procedural LANGUAGE ColId_or_Sconst { DropPLangStmt *n = makeNode(DropPLangStmt); n->plname = $4; $$ = (Node *)n; } ; --- 1843,1853 ---- | /*EMPTY*/ { $$ = ""; } ; ! DropPLangStmt: DROP opt_procedural LANGUAGE ColId_or_Sconst opt_drop_behavior { DropPLangStmt *n = makeNode(DropPLangStmt); n->plname = $4; + n->behavior = $5; $$ = (Node *)n; } ; *************** *** 2034,2044 **** ; ! DropTrigStmt: DROP TRIGGER name ON qualified_name { DropPropertyStmt *n = makeNode(DropPropertyStmt); n->relation = $5; n->property = $3; n->removeType = DROP_TRIGGER; $$ = (Node *) n; } --- 2036,2047 ---- ; ! DropTrigStmt: DROP TRIGGER name ON qualified_name opt_drop_behavior { DropPropertyStmt *n = makeNode(DropPropertyStmt); n->relation = $5; n->property = $3; + n->behavior = $6; n->removeType = DROP_TRIGGER; $$ = (Node *) n; } *************** *** 2843,2862 **** * *****************************************************************************/ ! RemoveFuncStmt: DROP FUNCTION func_name func_args { RemoveFuncStmt *n = makeNode(RemoveFuncStmt); n->funcname = $3; n->args = $4; $$ = (Node *)n; } ; ! RemoveAggrStmt: DROP AGGREGATE func_name '(' aggr_argtype ')' { RemoveAggrStmt *n = makeNode(RemoveAggrStmt); n->aggname = $3; n->aggtype = $5; $$ = (Node *)n; } ; --- 2846,2867 ---- * *****************************************************************************/ ! RemoveFuncStmt: DROP FUNCTION func_name func_args opt_drop_behavior { RemoveFuncStmt *n = makeNode(RemoveFuncStmt); n->funcname = $3; n->args = $4; + n->behavior = $5; $$ = (Node *)n; } ; ! RemoveAggrStmt: DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior { RemoveAggrStmt *n = makeNode(RemoveAggrStmt); n->aggname = $3; n->aggtype = $5; + n->behavior = $7; $$ = (Node *)n; } ; *************** *** 2865,2875 **** | '*' { $$ = NULL; } ; ! RemoveOperStmt: DROP OPERATOR any_operator '(' oper_argtypes ')' { RemoveOperStmt *n = makeNode(RemoveOperStmt); n->opname = $3; n->args = $5; $$ = (Node *)n; } ; --- 2870,2881 ---- | '*' { $$ = NULL; } ; ! RemoveOperStmt: DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior { RemoveOperStmt *n = makeNode(RemoveOperStmt); n->opname = $3; n->args = $5; + n->behavior = $7; $$ = (Node *)n; } ; *************** *** 3037,3047 **** ; ! DropRuleStmt: DROP RULE name ON qualified_name { DropPropertyStmt *n = makeNode(DropPropertyStmt); n->relation = $5; n->property = $3; n->removeType = DROP_RULE; $$ = (Node *) n; } --- 3043,3054 ---- ; ! DropRuleStmt: DROP RULE name ON qualified_name opt_drop_behavior { DropPropertyStmt *n = makeNode(DropPropertyStmt); n->relation = $5; n->property = $3; + n->behavior = $6; n->removeType = DROP_RULE; $$ = (Node *) n; } Index: src/backend/rewrite/rewriteDefine.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v retrieving revision 1.69 diff -c -r1.69 rewriteDefine.c *** src/backend/rewrite/rewriteDefine.c 2002/04/27 03:45:03 1.69 --- src/backend/rewrite/rewriteDefine.c 2002/05/09 01:43:42 *************** *** 17,22 **** --- 17,24 ---- #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" + #include "catalog/pg_depend.h" + #include "catalog/pg_namespace.h" #include "catalog/pg_rewrite.h" #include "commands/view.h" #include "miscadmin.h" *************** *** 49,62 **** char *evqual, char *actiontree) { ! int i; ! Datum values[Natts_pg_rewrite]; ! char nulls[Natts_pg_rewrite]; ! NameData rname; ! Relation pg_rewrite_desc; ! TupleDesc tupDesc; ! HeapTuple tup; ! Oid rewriteObjectId; if (IsDefinedRewriteRule(eventrel_oid, rulname)) elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists", --- 51,66 ---- char *evqual, char *actiontree) { ! int i; ! Datum values[Natts_pg_rewrite]; ! char nulls[Natts_pg_rewrite]; ! NameData rname; ! Relation pg_rewrite_desc; ! TupleDesc tupDesc; ! HeapTuple tup; ! Oid rewriteObjectId; ! ObjectAddress myself, ! dependee; if (IsDefinedRewriteRule(eventrel_oid, rulname)) elog(ERROR, "Attempt to insert rule \"%s\" failed: already exists", *************** *** 102,107 **** --- 106,127 ---- tup); CatalogCloseIndices(Num_pg_rewrite_indices, idescs); } + + /* + * Create Dependencies + * - Class of relation + */ + myself.classId = GetSysCacheOid(RELNAMENSP, + CStringGetDatum(RewriteRelationName), + ObjectIdGetDatum(PG_CATALOG_NAMESPACE), + 0, 0); + myself.objectId = tup->t_data->t_oid; + myself.objectSubId = 0; + + dependee.classId = RelOid_pg_class; + dependee.objectId = eventrel_oid; + dependee.objectSubId = 0; + dependCreate(&myself, &dependee, true); heap_freetuple(tup); Index: src/backend/rewrite/rewriteRemove.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v retrieving revision 1.49 diff -c -r1.49 rewriteRemove.c *** src/backend/rewrite/rewriteRemove.c 2002/04/27 03:45:03 1.49 --- src/backend/rewrite/rewriteRemove.c 2002/05/09 01:43:42 *************** *** 17,32 **** --- 17,35 ---- #include "access/genam.h" #include "access/heapam.h" #include "catalog/catname.h" + #include "catalog/pg_depend.h" #include "catalog/indexing.h" #include "catalog/pg_rewrite.h" #include "commands/comment.h" #include "miscadmin.h" #include "rewrite/rewriteRemove.h" #include "rewrite/rewriteSupport.h" + #include "utils/builtins.h" #include "utils/acl.h" #include "utils/fmgroids.h" #include "utils/syscache.h" + void RemoveRewriteRuleByTuple(Relation rewriteRelation, HeapTuple tuple, bool force, int behavior); /* * RemoveRewriteRule *************** *** 34,48 **** * Delete a rule given its name. */ void ! RemoveRewriteRule(Oid owningRel, const char *ruleName) { Relation RewriteRelation; - Relation event_relation; HeapTuple tuple; - Oid ruleId; - Oid eventRelationOid; - bool hasMoreRules; - AclResult aclresult; /* * Open the pg_rewrite relation. --- 37,46 ---- * Delete a rule given its name. */ void ! RemoveRewriteRule(Oid owningRel, const char *ruleName, int behavior) { Relation RewriteRelation; HeapTuple tuple; /* * Open the pg_rewrite relation. *************** *** 58,64 **** 0, 0); /* ! * complain if no rule with such name existed */ if (!HeapTupleIsValid(tuple)) elog(ERROR, "Rule \"%s\" not found", ruleName); --- 56,62 ---- 0, 0); /* ! * complain if no rule with such nam*e existed */ if (!HeapTupleIsValid(tuple)) elog(ERROR, "Rule \"%s\" not found", ruleName); *************** *** 67,75 **** * Save the OID of the rule (i.e. the tuple's OID) and the event * relation's OID */ ruleId = tuple->t_data->t_oid; eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; - Assert(eventRelationOid == owningRel); /* * We had better grab AccessExclusiveLock so that we know no other --- 65,133 ---- * Save the OID of the rule (i.e. the tuple's OID) and the event * relation's OID */ + Assert(((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class == owningRel); + + RemoveRewriteRuleByTuple(RewriteRelation, tuple, false, behavior); + + heap_freetuple(tuple); + + heap_close(RewriteRelation, RowExclusiveLock); + } + + void + RemoveRewriteRuleById(Oid ruleId, int behavior) + { + Relation RewriteRelation; + HeapScanDesc scanDesc = NULL; + ScanKeyData scanKeyData; + HeapTuple tuple; + + /* + * Open the pg_rewrite relation. + */ + RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); + + /* + * Find the tuple for the target rule. + */ + ScanKeyEntryInitialize(&scanKeyData, + 0, + ObjectIdAttributeNumber, + F_OIDEQ, + ObjectIdGetDatum(ruleId)); + + scanDesc = heap_beginscan(RewriteRelation, + 0, SnapshotNow, 1, &scanKeyData); + + /* Assume only 1 will be found */ + while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0))) + { + RemoveRewriteRuleByTuple(RewriteRelation, tuple, true, behavior); + } + + heap_endscan(scanDesc); + + heap_close(RewriteRelation, RowExclusiveLock); + } + + /* + * RemoveRewriteRuleByTuple + * + * If force is true then the fact that the rule is owned by a view is ignored + * by the system. It will remove it anyway. + */ + void + RemoveRewriteRuleByTuple(Relation rewriteRelation, HeapTuple tuple, bool force, int behavior) + { + + Relation event_relation; + bool hasMoreRules; + Oid ruleId; + Oid eventRelationOid; + AclResult aclresult; + ruleId = tuple->t_data->t_oid; eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; /* * We had better grab AccessExclusiveLock so that we know no other *************** *** 87,113 **** aclcheck_error(aclresult, RelationGetRelationName(event_relation)); /* do not allow the removal of a view's SELECT rule */ ! if (event_relation->rd_rel->relkind == RELKIND_VIEW && ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1') ! elog(ERROR, "Cannot remove a view's SELECT rule"); hasMoreRules = event_relation->rd_rules != NULL && event_relation->rd_rules->numLocks > 1; /* * Delete any comments associated with this rule */ ! DeleteComments(ruleId, RelationGetRelid(RewriteRelation)); ! /* * Now delete the pg_rewrite tuple for the rule */ ! simple_heap_delete(RewriteRelation, &tuple->t_self); - heap_freetuple(tuple); - - heap_close(RewriteRelation, RowExclusiveLock); - /* * Set pg_class 'relhasrules' field correctly for event relation. * --- 145,169 ---- aclcheck_error(aclresult, RelationGetRelationName(event_relation)); /* do not allow the removal of a view's SELECT rule */ ! if (force == false && event_relation->rd_rel->relkind == RELKIND_VIEW && ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1') ! elog(ERROR, "RemoveRewriteRuleByTuple: Cannot remove a view's SELECT rule"); hasMoreRules = event_relation->rd_rules != NULL && event_relation->rd_rules->numLocks > 1; + /* Deal with dependencies */ + dependDeleteTuple(tuple, rewriteRelation, behavior); + /* * Delete any comments associated with this rule */ ! DeleteComments(ruleId, RelationGetRelid(rewriteRelation)); /* * Now delete the pg_rewrite tuple for the rule */ ! simple_heap_delete(rewriteRelation, &tuple->t_self); /* * Set pg_class 'relhasrules' field correctly for event relation. * *************** *** 119,168 **** /* Close rel, but keep lock till commit... */ heap_close(event_relation, NoLock); ! } ! ! /* ! * RelationRemoveRules - ! * removes all rules associated with the relation when the relation is ! * being removed. ! */ ! void ! RelationRemoveRules(Oid relid) ! { ! Relation RewriteRelation; ! SysScanDesc scanDesc; ! ScanKeyData scanKeyData; ! HeapTuple tuple; ! ! /* ! * Open the pg_rewrite relation. ! */ ! RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock); ! ! /* ! * Scan pg_rewrite for all the tuples that have the same ev_class ! * as relid (the relation to be removed). ! */ ! ScanKeyEntryInitialize(&scanKeyData, ! 0, ! Anum_pg_rewrite_ev_class, ! F_OIDEQ, ! ObjectIdGetDatum(relid)); ! ! scanDesc = systable_beginscan(RewriteRelation, ! RewriteRelRulenameIndex, ! true, SnapshotNow, ! 1, &scanKeyData); ! ! while (HeapTupleIsValid(tuple = systable_getnext(scanDesc))) ! { ! /* Delete any comments associated with this rule */ ! DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation)); ! ! simple_heap_delete(RewriteRelation, &tuple->t_self); ! } ! ! systable_endscan(scanDesc); ! ! heap_close(RewriteRelation, RowExclusiveLock); ! } --- 175,178 ---- /* Close rel, but keep lock till commit... */ heap_close(event_relation, NoLock); ! } \ No newline at end of file Index: src/backend/tcop/utility.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v retrieving revision 1.153 diff -c -r1.153 utility.c *** src/backend/tcop/utility.c 2002/04/30 01:26:26 1.153 --- src/backend/tcop/utility.c 2002/05/09 01:43:43 *************** *** 291,320 **** case DROP_TABLE: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_RELATION); ! RemoveRelation(rel); break; case DROP_SEQUENCE: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_SEQUENCE); ! RemoveRelation(rel); break; case DROP_VIEW: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_VIEW); ! RemoveView(rel); break; case DROP_INDEX: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_INDEX); ! RemoveIndex(rel); break; case DROP_TYPE: /* RemoveType does its own permissions checks */ ! RemoveType(names); break; case DROP_DOMAIN: --- 291,320 ---- case DROP_TABLE: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_RELATION); ! RemoveRelation(rel, stmt->behavior); break; case DROP_SEQUENCE: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_SEQUENCE); ! RemoveRelation(rel, stmt->behavior); break; case DROP_VIEW: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_VIEW); ! RemoveView(rel, stmt->behavior); break; case DROP_INDEX: rel = makeRangeVarFromNameList(names); CheckDropPermissions(rel, RELKIND_INDEX); ! RemoveIndex(rel, stmt->behavior); break; case DROP_TYPE: /* RemoveType does its own permissions checks */ ! RemoveType(names, stmt->behavior); break; case DROP_DOMAIN: *************** *** 607,613 **** { RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree; ! RemoveAggregate(stmt->aggname, stmt->aggtype); } break; --- 607,613 ---- { RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree; ! RemoveAggregate(stmt->aggname, stmt->aggtype, stmt->behavior); } break; *************** *** 615,621 **** { RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree; ! RemoveFunction(stmt->funcname, stmt->args); } break; --- 615,621 ---- { RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree; ! RemoveFunction(stmt->funcname, stmt->args, stmt->behavior); } break; *************** *** 625,631 **** TypeName *typenode1 = (TypeName *) lfirst(stmt->args); TypeName *typenode2 = (TypeName *) lsecond(stmt->args); ! RemoveOperator(stmt->opname, typenode1, typenode2); } break; --- 625,631 ---- TypeName *typenode1 = (TypeName *) lfirst(stmt->args); TypeName *typenode2 = (TypeName *) lsecond(stmt->args); ! RemoveOperator(stmt->opname, typenode1, typenode2, stmt->behavior); } break; *************** *** 753,763 **** { case DROP_RULE: /* RemoveRewriteRule checks permissions */ ! RemoveRewriteRule(relId, stmt->property); break; case DROP_TRIGGER: /* DropTrigger checks permissions */ ! DropTrigger(relId, stmt->property); break; } } --- 753,763 ---- { case DROP_RULE: /* RemoveRewriteRule checks permissions */ ! RemoveRewriteRule(relId, stmt->property, stmt->behavior); break; case DROP_TRIGGER: /* DropTrigger checks permissions */ ! DropTrigger(relId, stmt->property, stmt->behavior); break; } } Index: src/backend/utils/cache/relcache.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v retrieving revision 1.163 diff -c -r1.163 relcache.c *** src/backend/utils/cache/relcache.c 2002/04/27 21:24:34 1.163 --- src/backend/utils/cache/relcache.c 2002/05/09 01:43:48 *************** *** 43,53 **** #include "catalog/pg_amproc.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_attribute.h" #include "catalog/pg_index.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" #include "catalog/pg_proc.h" - #include "catalog/pg_relcheck.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_type.h" #include "commands/trigger.h" --- 43,53 ---- #include "catalog/pg_amproc.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_attribute.h" + #include "catalog/pg_constraint.h" #include "catalog/pg_index.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" #include "catalog/pg_proc.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_type.h" #include "commands/trigger.h" *************** *** 296,302 **** static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo, Relation oldrelation); static void AttrDefaultFetch(Relation relation); ! static void RelCheckFetch(Relation relation); static List *insert_ordered_oid(List *list, Oid datum); static void IndexSupportInitialize(Form_pg_index iform, IndexStrategy indexStrategy, --- 296,302 ---- static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo, Relation oldrelation); static void AttrDefaultFetch(Relation relation); ! static void CheckConstraintFetch(Relation relation); static List *insert_ordered_oid(List *list, Oid datum); static void IndexSupportInitialize(Form_pg_index iform, IndexStrategy indexStrategy, *************** *** 451,457 **** * RelationBuildTupleDesc * * Form the relation's tuple descriptor from information in ! * the pg_attribute, pg_attrdef & pg_relcheck system catalogs. */ static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, --- 451,457 ---- * RelationBuildTupleDesc * * Form the relation's tuple descriptor from information in ! * the pg_attribute, pg_attrdef & pg_constraint system catalogs. */ static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, *************** *** 603,609 **** MemoryContextAlloc(CacheMemoryContext, constr->num_check * sizeof(ConstrCheck)); MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck)); ! RelCheckFetch(relation); } else constr->num_check = 0; --- 603,609 ---- MemoryContextAlloc(CacheMemoryContext, constr->num_check * sizeof(ConstrCheck)); MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck)); ! CheckConstraintFetch(relation); } else constr->num_check = 0; *************** *** 2479,2528 **** } static void ! RelCheckFetch(Relation relation) { ConstrCheck *check = relation->rd_att->constr->check; int ncheck = relation->rd_att->constr->num_check; Relation rcrel; SysScanDesc rcscan; ! ScanKeyData skey; HeapTuple htup; Name rcname; Datum val; bool isnull; int found; ! ScanKeyEntryInitialize(&skey, ! (bits16) 0x0, ! (AttrNumber) Anum_pg_relcheck_rcrelid, ! (RegProcedure) F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); ! rcrel = heap_openr(RelCheckRelationName, AccessShareLock); ! rcscan = systable_beginscan(rcrel, RelCheckIndex, true, ! SnapshotNow, ! 1, &skey); found = 0; while (HeapTupleIsValid(htup = systable_getnext(rcscan))) { if (found == ncheck) ! elog(ERROR, "RelCheckFetch: unexpected record found for rel %s", RelationGetRelationName(relation)); rcname = (Name) fastgetattr(htup, ! Anum_pg_relcheck_rcname, rcrel->rd_att, &isnull); if (isnull) ! elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s", RelationGetRelationName(relation)); check[found].ccname = MemoryContextStrdup(CacheMemoryContext, NameStr(*rcname)); val = fastgetattr(htup, ! Anum_pg_relcheck_rcbin, rcrel->rd_att, &isnull); if (isnull) ! elog(ERROR, "RelCheckFetch: rcbin IS NULL for rel %s", RelationGetRelationName(relation)); check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, DatumGetCString(DirectFunctionCall1(textout, --- 2479,2526 ---- } static void ! CheckConstraintFetch(Relation relation) { ConstrCheck *check = relation->rd_att->constr->check; int ncheck = relation->rd_att->constr->num_check; Relation rcrel; SysScanDesc rcscan; ! ScanKeyData skey[2]; ! int skeyCount = 0; HeapTuple htup; Name rcname; Datum val; bool isnull; int found; ! ScanKeyEntryInitialize(&skey[skeyCount++], ! 0, Anum_pg_constraint_conrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); ! rcrel = heap_openr(ConstraintRelationName, AccessShareLock); ! rcscan = systable_beginscan(rcrel, ConstraintRelidNameIndex, true, ! SnapshotNow, skeyCount, skey); found = 0; while (HeapTupleIsValid(htup = systable_getnext(rcscan))) { if (found == ncheck) ! elog(ERROR, "CheckConstraintFetch: unexpected record found for rel %s", RelationGetRelationName(relation)); rcname = (Name) fastgetattr(htup, ! Anum_pg_constraint_conname, rcrel->rd_att, &isnull); if (isnull) ! elog(ERROR, "CheckConstraintFetch: conname IS NULL for rel %s", RelationGetRelationName(relation)); check[found].ccname = MemoryContextStrdup(CacheMemoryContext, NameStr(*rcname)); val = fastgetattr(htup, ! Anum_pg_constraint_conbin, rcrel->rd_att, &isnull); if (isnull) ! elog(ERROR, "CheckConstraintFetch: conbin IS NULL for rel %s", RelationGetRelationName(relation)); check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, DatumGetCString(DirectFunctionCall1(textout, *************** *** 2534,2540 **** heap_close(rcrel, AccessShareLock); if (found != ncheck) ! elog(ERROR, "RelCheckFetch: %d record(s) not found for rel %s", ncheck - found, RelationGetRelationName(relation)); } --- 2532,2538 ---- heap_close(rcrel, AccessShareLock); if (found != ncheck) ! elog(ERROR, "CheckConstraintFetch: %d record(s) not found for rel %s", ncheck - found, RelationGetRelationName(relation)); } Index: src/include/postgres.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/postgres.h,v retrieving revision 1.57 diff -c -r1.57 postgres.h *** src/include/postgres.h 2002/04/27 21:24:34 1.57 --- src/include/postgres.h 2002/05/09 01:43:51 *************** *** 597,608 **** --- 597,613 ---- #define CATALOG(x) typedef struct CppConcat(FormData_,x) #define BOOTSTRAP + + #define BKI_PINWRITE + #define BKI_SHARED_RELATION + #define BKI_WITHOUT_OIDS /* these need to expand into some harmless, repeatable declaration */ #define DATA(x) extern int errno #define DESCR(x) extern int errno + #define PINTABLE(x) extern int errno #define BKI_BEGIN #define BKI_END Index: src/include/access/tupdesc.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/access/tupdesc.h,v retrieving revision 1.34 diff -c -r1.34 tupdesc.h *** src/include/access/tupdesc.h 2002/03/29 19:06:16 1.34 --- src/include/access/tupdesc.h 2002/05/09 01:43:51 *************** *** 43,49 **** /* * This structure contains all information (i.e. from Classes ! * pg_attribute, pg_attrdef, pg_relcheck) for a tuple. */ typedef struct tupleDesc { --- 43,49 ---- /* * This structure contains all information (i.e. from Classes ! * pg_attribute, pg_attrdef, pg_constraint) for a tuple. */ typedef struct tupleDesc { Index: src/include/catalog/catname.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/catname.h,v retrieving revision 1.25 diff -c -r1.25 catname.h *** src/include/catalog/catname.h 2002/04/27 21:24:34 1.25 --- src/include/catalog/catname.h 2002/05/09 01:43:51 *************** *** 20,26 **** --- 20,28 ---- #define AccessMethodOperatorRelationName "pg_amop" #define AccessMethodProcedureRelationName "pg_amproc" #define AttributeRelationName "pg_attribute" + #define ConstraintRelationName "pg_constraint" #define DatabaseRelationName "pg_database" + #define DependRelationName "pg_depend" #define DescriptionRelationName "pg_description" #define GroupRelationName "pg_group" #define IndexRelationName "pg_index" *************** *** 39,45 **** #define TypeRelationName "pg_type" #define VersionRelationName "pg_version" #define AttrDefaultRelationName "pg_attrdef" - #define RelCheckRelationName "pg_relcheck" #define TriggerRelationName "pg_trigger" #endif /* CATNAME_H */ --- 41,46 ---- Index: src/include/catalog/heap.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/heap.h,v retrieving revision 1.50 diff -c -r1.50 heap.h *** src/include/catalog/heap.h 2002/04/27 21:24:34 1.50 --- src/include/catalog/heap.h 2002/05/09 01:43:51 *************** *** 44,50 **** bool relhasoids, bool allow_system_table_mods); ! extern void heap_drop_with_catalog(Oid rid, bool allow_system_table_mods); extern void heap_truncate(Oid rid); --- 44,50 ---- bool relhasoids, bool allow_system_table_mods); ! extern void heap_drop_with_catalog(Oid rid, bool allow_system_table_mods, int behavior); extern void heap_truncate(Oid rid); Index: src/include/catalog/index.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/index.h,v retrieving revision 1.47 diff -c -r1.47 index.h *** src/include/catalog/index.h 2002/03/31 06:26:32 1.47 --- src/include/catalog/index.h 2002/05/09 01:43:51 *************** *** 37,43 **** bool primary, bool allow_system_table_mods); ! extern void index_drop(Oid indexId); extern IndexInfo *BuildIndexInfo(Form_pg_index indexStruct); --- 37,43 ---- bool primary, bool allow_system_table_mods); ! extern void index_drop(Oid indexId, int behavior); extern IndexInfo *BuildIndexInfo(Form_pg_index indexStruct); Index: src/include/catalog/indexing.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/indexing.h,v retrieving revision 1.66 diff -c -r1.66 indexing.h *** src/include/catalog/indexing.h 2002/04/19 16:36:08 1.66 --- src/include/catalog/indexing.h 2002/05/09 01:43:51 *************** *** 27,33 **** --- 27,35 ---- #define Num_pg_attr_indices 2 #define Num_pg_attrdef_indices 1 #define Num_pg_class_indices 2 + #define Num_pg_constraint_indices 2 #define Num_pg_database_indices 2 + #define Num_pg_depend_indices 2 #define Num_pg_description_indices 1 #define Num_pg_group_indices 2 #define Num_pg_index_indices 2 *************** *** 38,44 **** #define Num_pg_opclass_indices 2 #define Num_pg_operator_indices 2 #define Num_pg_proc_indices 2 - #define Num_pg_relcheck_indices 1 #define Num_pg_rewrite_indices 2 #define Num_pg_shadow_indices 2 #define Num_pg_statistic_indices 1 --- 40,45 ---- *************** *** 59,66 **** --- 60,71 ---- #define AttributeRelidNumIndex "pg_attribute_relid_attnum_index" #define ClassNameNspIndex "pg_class_relname_nsp_index" #define ClassOidIndex "pg_class_oid_index" + #define ConstraintOidIndex "pg_constraint_oid_index" + #define ConstraintRelidNameIndex "pg_constraint_relid_name_index" #define DatabaseNameIndex "pg_database_datname_index" #define DatabaseOidIndex "pg_database_oid_index" + #define DependDependerIndex "pg_depend_depender_index" + #define DependDependeeIndex "pg_depend_dependee_index" #define DescriptionObjIndex "pg_description_o_c_o_index" #define GroupNameIndex "pg_group_name_index" #define GroupSysidIndex "pg_group_sysid_index" *************** *** 78,84 **** #define OperatorOidIndex "pg_operator_oid_index" #define ProcedureNameNspIndex "pg_proc_proname_args_nsp_index" #define ProcedureOidIndex "pg_proc_oid_index" - #define RelCheckIndex "pg_relcheck_rcrelid_index" #define RewriteOidIndex "pg_rewrite_oid_index" #define RewriteRelRulenameIndex "pg_rewrite_rel_rulename_index" #define ShadowNameIndex "pg_shadow_usename_index" --- 83,88 ---- *************** *** 99,105 **** --- 103,111 ---- extern char *Name_pg_attr_indices[]; extern char *Name_pg_attrdef_indices[]; extern char *Name_pg_class_indices[]; + extern char *Name_pg_constraint_indices[]; extern char *Name_pg_database_indices[]; + extern char *Name_pg_depend_indices[]; extern char *Name_pg_description_indices[]; extern char *Name_pg_group_indices[]; extern char *Name_pg_index_indices[]; *************** *** 110,116 **** extern char *Name_pg_opclass_indices[]; extern char *Name_pg_operator_indices[]; extern char *Name_pg_proc_indices[]; - extern char *Name_pg_relcheck_indices[]; extern char *Name_pg_rewrite_indices[]; extern char *Name_pg_shadow_indices[]; extern char *Name_pg_statistic_indices[]; --- 116,121 ---- *************** *** 155,160 **** --- 160,167 ---- 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_relname_nsp_index on pg_class using btree(relname name_ops, relnamespace oid_ops)); + DECLARE_UNIQUE_INDEX(pg_constraint_oid_index on pg_constraint using btree(oid oid_ops)); + DECLARE_UNIQUE_INDEX(pg_constraint_relid_name_index on pg_constraint using btree(conrelid oid_ops, conname 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_description_o_c_o_index on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops)); *************** *** 176,182 **** DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops, pronamespace oid_ops)); /* This following index is not used for a cache and is not unique */ - DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops)); DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index on pg_rewrite using btree(ev_class oid_ops, rulename name_ops)); DECLARE_UNIQUE_INDEX(pg_shadow_usename_index on pg_shadow using btree(usename name_ops)); --- 183,188 ---- *************** *** 190,195 **** --- 196,206 ---- DECLARE_UNIQUE_INDEX(pg_trigger_oid_index on pg_trigger using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_type_oid_index on pg_type using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index on pg_type using btree(typname name_ops, typnamespace oid_ops)); + + /* This following index is not used for a cache and is not unique */ + DECLARE_INDEX(pg_depend_depender_index on pg_depend using btree(classid oid_ops, objid oid_ops, objsubid int4_ops)); + /* This following index is not used for a cache and is not unique */ + DECLARE_INDEX(pg_depend_dependee_index on pg_depend using btree(depclassid oid_ops, depobjid oid_ops, depobjsubid int4_ops)); /* last step of initialization script: build the indices declared above */ BUILD_INDICES Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.236 diff -c -r1.236 pg_proc.h *** src/include/catalog/pg_proc.h 2002/05/03 00:32:16 1.236 --- src/include/catalog/pg_proc.h 2002/05/09 01:44:03 *************** *** 94,99 **** --- 94,102 ---- #define Anum_pg_proc_probin 19 #define Anum_pg_proc_proacl 20 + /* Make the below functions permenant */ + PINTABLE(1255); + /* ---------------- * initial contents of pg_proc * ---------------- Index: src/include/catalog/pg_type.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_type.h,v retrieving revision 1.122 diff -c -r1.122 pg_type.h *** src/include/catalog/pg_type.h 2002/04/25 02:56:56 1.122 --- src/include/catalog/pg_type.h 2002/05/09 01:44:05 *************** *** 228,233 **** --- 228,235 ---- #define Anum_pg_type_typdefaultbin 22 #define Anum_pg_type_typdefault 23 + /* Make the below types permenant */ + PINTABLE(1247); /* ---------------- * initial contents of pg_type Index: src/include/commands/defrem.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/defrem.h,v retrieving revision 1.36 diff -c -r1.36 defrem.h *** src/include/commands/defrem.h 2002/04/16 23:08:12 1.36 --- src/include/commands/defrem.h 2002/05/09 01:44:05 *************** *** 29,35 **** bool primary, Expr *predicate, List *rangetable); ! extern void RemoveIndex(RangeVar *relation); extern void ReindexIndex(RangeVar *indexRelation, bool force); extern void ReindexTable(RangeVar *relation, bool force); extern void ReindexDatabase(const char *databaseName, bool force, bool all); --- 29,35 ---- bool primary, Expr *predicate, List *rangetable); ! extern void RemoveIndex(RangeVar *relation, int behavior); extern void ReindexIndex(RangeVar *indexRelation, bool force); extern void ReindexTable(RangeVar *relation, bool force); extern void ReindexDatabase(const char *databaseName, bool force, bool all); *************** *** 39,61 **** */ extern void CreateFunction(ProcedureStmt *stmt); ! extern void RemoveFunction(List *functionName, List *argTypes); extern void DefineOperator(List *names, List *parameters); extern void RemoveOperator(List *operatorName, ! TypeName *typeName1, TypeName *typeName2); extern void DefineAggregate(List *names, List *parameters); ! extern void RemoveAggregate(List *aggName, TypeName *aggType); extern void DefineType(List *names, List *parameters); ! extern void RemoveType(List *names); extern void DefineDomain(CreateDomainStmt *stmt); extern void RemoveDomain(List *names, int behavior); - /* support routines in define.c */ - extern void case_translate_language_name(const char *input, char *output); extern char *defGetString(DefElem *def); --- 39,62 ---- */ extern void CreateFunction(ProcedureStmt *stmt); ! extern void RemoveFunction(List *functionName, List *argTypes, int behavior); ! extern void RemoveFunctionById(Oid funcOid, int behavior); extern void DefineOperator(List *names, List *parameters); extern void RemoveOperator(List *operatorName, ! TypeName *typeName1, TypeName *typeName2, int behavior); ! extern void RemoveOperatorById(Oid operOid, int behavior); extern void DefineAggregate(List *names, List *parameters); ! extern void RemoveAggregate(List *aggName, TypeName *aggType, int behavior); extern void DefineType(List *names, List *parameters); ! extern void RemoveType(List *names, int behavior); ! extern void RemoveTypeByTypeName(TypeName *typename, int behavior); extern void DefineDomain(CreateDomainStmt *stmt); extern void RemoveDomain(List *names, int behavior); /* support routines in define.c */ extern void case_translate_language_name(const char *input, char *output); extern char *defGetString(DefElem *def); Index: src/include/commands/tablecmds.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/tablecmds.h,v retrieving revision 1.4 diff -c -r1.4 tablecmds.h *** src/include/commands/tablecmds.h 2002/04/30 01:24:52 1.4 --- src/include/commands/tablecmds.h 2002/05/09 01:44:05 *************** *** 48,54 **** extern Oid DefineRelation(CreateStmt *stmt, char relkind); ! extern void RemoveRelation(const RangeVar *relation); extern void TruncateRelation(const RangeVar *relation); --- 48,54 ---- extern Oid DefineRelation(CreateStmt *stmt, char relkind); ! extern void RemoveRelation(const RangeVar *relation, int behavior); extern void TruncateRelation(const RangeVar *relation); Index: src/include/commands/trigger.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/trigger.h,v retrieving revision 1.35 diff -c -r1.35 trigger.h *** src/include/commands/trigger.h 2002/04/26 19:29:47 1.35 --- src/include/commands/trigger.h 2002/05/09 01:44:06 *************** *** 102,109 **** extern void CreateTrigger(CreateTrigStmt *stmt); ! extern void DropTrigger(Oid relid, const char *trigname); ! extern void RelationRemoveTriggers(Relation rel); extern void renametrig(Oid relid, const char *oldname, const char *newname); --- 102,109 ---- extern void CreateTrigger(CreateTrigStmt *stmt); ! extern void DropTrigger(Oid relid, const char *trigname, int behavior); ! extern void DropTriggerById(Oid trigId, int behavior); extern void renametrig(Oid relid, const char *oldname, const char *newname); Index: src/include/commands/view.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/view.h,v retrieving revision 1.14 diff -c -r1.14 view.h *** src/include/commands/view.h 2002/03/29 19:06:22 1.14 --- src/include/commands/view.h 2002/05/09 01:44:06 *************** *** 17,22 **** #include "nodes/parsenodes.h" extern void DefineView(const RangeVar *view, Query *view_parse); ! extern void RemoveView(const RangeVar *view); #endif /* VIEW_H */ --- 17,22 ---- #include "nodes/parsenodes.h" extern void DefineView(const RangeVar *view, Query *view_parse); ! extern void RemoveView(const RangeVar *view, int behavior); #endif /* VIEW_H */ Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.175 diff -c -r1.175 parsenodes.h *** src/include/nodes/parsenodes.h 2002/04/28 19:54:28 1.175 --- src/include/nodes/parsenodes.h 2002/05/09 01:44:09 *************** *** 123,128 **** --- 123,129 ---- bool pct_type; /* %TYPE specified? */ int32 typmod; /* type modifier */ List *arrayBounds; /* array bounds */ + RangeVar *serial; /* Serial sequence reference*/ } TypeName; /* *************** *** 982,987 **** --- 983,989 ---- { NodeTag type; char *plname; /* PL name */ + int behavior; } DropPLangStmt; /* ---------------------- *************** *** 1114,1119 **** --- 1116,1122 ---- RangeVar *relation; /* owning relation */ char *property; /* name of rule, trigger, etc */ int removeType; + int behavior; } DropPropertyStmt; /* ---------------------- *************** *** 1205,1210 **** --- 1208,1214 ---- NodeTag type; List *aggname; /* aggregate to drop */ TypeName *aggtype; /* TypeName for input datatype, or NULL */ + int behavior; } RemoveAggrStmt; /* ---------------------- *************** *** 1216,1221 **** --- 1220,1226 ---- NodeTag type; List *funcname; /* function to drop */ List *args; /* types of the arguments */ + int behavior; } RemoveFuncStmt; /* ---------------------- *************** *** 1227,1232 **** --- 1232,1238 ---- NodeTag type; List *opname; /* operator to drop */ List *args; /* types of the arguments */ + int behavior; } RemoveOperStmt; /* ---------------------- Index: src/include/rewrite/rewriteRemove.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/rewrite/rewriteRemove.h,v retrieving revision 1.13 diff -c -r1.13 rewriteRemove.h *** src/include/rewrite/rewriteRemove.h 2002/04/18 20:01:11 1.13 --- src/include/rewrite/rewriteRemove.h 2002/05/09 01:44:09 *************** *** 14,20 **** #ifndef REWRITEREMOVE_H #define REWRITEREMOVE_H ! extern void RemoveRewriteRule(Oid owningRel, const char *ruleName); ! extern void RelationRemoveRules(Oid relid); #endif /* REWRITEREMOVE_H */ --- 14,20 ---- #ifndef REWRITEREMOVE_H #define REWRITEREMOVE_H ! extern void RemoveRewriteRule(Oid owningRel, const char *ruleName, int behavior); ! extern void RemoveRewriteRuleById(Oid ruleId, int behavior); #endif /* REWRITEREMOVE_H */ Index: src/include/utils/lsyscache.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/utils/lsyscache.h,v retrieving revision 1.51 diff -c -r1.51 lsyscache.h *** src/include/utils/lsyscache.h 2002/04/30 01:26:26 1.51 --- src/include/utils/lsyscache.h 2002/05/09 01:44:09 *************** *** 39,44 **** --- 39,45 ---- extern RegProcedure get_oprjoin(Oid opno); extern char *get_func_name(Oid funcid); extern Oid get_func_rettype(Oid funcid); + extern char *get_func_name(Oid funcid); extern char func_volatile(Oid funcid); extern Oid get_relname_relid(const char *relname, Oid relnamespace); extern char *get_rel_name(Oid relid); Index: src/test/regress/parallel_schedule =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/parallel_schedule,v retrieving revision 1.9 diff -c -r1.9 parallel_schedule *** src/test/regress/parallel_schedule 2002/04/05 11:56:55 1.9 --- src/test/regress/parallel_schedule 2002/05/09 01:44:12 *************** *** 75,77 **** --- 75,79 ---- # ---------- # "plpgsql" cannot run concurrently with "rules" test: limit plpgsql temp domain + + test: drop Index: src/test/regress/serial_schedule =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/serial_schedule,v retrieving revision 1.9 diff -c -r1.9 serial_schedule *** src/test/regress/serial_schedule 2002/04/05 11:56:55 1.9 --- src/test/regress/serial_schedule 2002/05/09 01:44:12 *************** *** 82,85 **** --- 82,86 ---- test: plpgsql test: temp test: domain + test: drop Index: src/test/regress/expected/alter_table.out =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/alter_table.out,v retrieving revision 1.41 diff -c -r1.41 alter_table.out *** src/test/regress/expected/alter_table.out 2002/05/03 00:32:18 1.41 --- src/test/regress/expected/alter_table.out 2002/05/09 01:44:13 *************** *** 332,337 **** --- 332,340 ---- -- Try (and succeed) ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full; NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) + -- Fail to add check constraint of same name as foreign key constraint + ALTER TABLE tmp3 add constraint tmpconstr check(a is not null); + ERROR: constraint "tmpconstr" already exists -- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on -- tmp4 is a,b ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full; *************** *** 340,347 **** DROP TABLE tmp5; DROP TABLE tmp4; DROP TABLE tmp3; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "tmp2" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "tmp2" DROP TABLE tmp2; -- Foreign key adding test with mixed types -- Note: these tables are TEMP to avoid name conflicts when this test --- 343,348 ---- *************** *** 369,378 **** -- As should this ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ! DROP TABLE pktable; ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" DROP TABLE fktable; CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' --- 370,381 ---- -- As should this ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ! DROP TABLE pktable restrict; ! ERROR: Drop Restricted as Table fktable Depends on Table pktable ! DROP TABLE pktable cascade; ! NOTICE: Cascading drop to Table fktable DROP TABLE fktable; + ERROR: table "fktable" does not exist CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' *************** *** 445,451 **** alter table atacc1 add check (test2>test); -- should fail for $2 insert into atacc1 (test2, test) values (3, 4); ! ERROR: ExecAppend: rejected due to CHECK constraint $2 drop table atacc1; -- inheritance related tests create table atacc1 (test int); --- 448,454 ---- alter table atacc1 add check (test2>test); -- should fail for $2 insert into atacc1 (test2, test) values (3, 4); ! ERROR: ExecAppend: rejected due to CHECK constraint Constraint_139363 drop table atacc1; -- inheritance related tests create table atacc1 (test int); Index: src/test/regress/expected/create_misc.out =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/create_misc.out,v retrieving revision 1.13 diff -c -r1.13 create_misc.out *** src/test/regress/expected/create_misc.out 2002/03/06 06:10:52 1.13 --- src/test/regress/expected/create_misc.out 2002/05/09 01:44:13 *************** *** 151,153 **** --- 151,159 ---- force | 100 (3 rows) + DROP TABLE serialTest; + -- Ensure that Serial sequences are dropped with the table + CREATE TABLE serialTest (f1 text, f2 serial); + NOTICE: CREATE TABLE will create implicit sequence 'serialtest_f2_seq' for SERIAL column 'serialtest.f2' + NOTICE: CREATE TABLE / UNIQUE will create implicit index 'serialtest_f2_key' for table 'serialtest' + DROP TABLE serialTest; Index: src/test/regress/expected/domain.out =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/domain.out,v retrieving revision 1.2 diff -c -r1.2 domain.out *** src/test/regress/expected/domain.out 2002/03/20 19:45:12 1.2 --- src/test/regress/expected/domain.out 2002/05/09 01:44:13 *************** *** 3,10 **** comment on domain domaindroptest is 'About to drop this..'; create domain basetypetest domaindroptest; ERROR: DefineDomain: domaindroptest is not a basetype - drop domain domaindroptest cascade; - ERROR: DROP DOMAIN does not support the CASCADE keyword drop domain domaindroptest; -- TEST Domains. create domain domainvarchar varchar(5); --- 3,8 ---- *************** *** 135,144 **** 3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12 (3 rows) - drop sequence ddef4_seq; - drop table defaulttest; - drop domain ddef1 restrict; - drop domain ddef2 restrict; - drop domain ddef3 restrict; - drop domain ddef4 restrict; - drop domain ddef5 restrict; --- 133,135 ---- Index: src/test/regress/expected/foreign_key.out =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/foreign_key.out,v retrieving revision 1.16 diff -c -r1.16 foreign_key.out *** src/test/regress/expected/foreign_key.out 2002/05/03 00:32:19 1.16 --- src/test/regress/expected/foreign_key.out 2002/05/09 01:44:14 *************** *** 55,63 **** 1 | 3 (3 rows) ! DROP TABLE PKTABLE; ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" ! DROP TABLE FKTABLE; -- -- check set NULL and table constraint on multiple columns -- --- 55,62 ---- 1 | 3 (3 rows) ! DROP TABLE PKTABLE CASCADE; ! NOTICE: Cascading drop to Table fktable -- -- check set NULL and table constraint on multiple columns -- *************** *** 138,146 **** | | 8 (5 rows) ! DROP TABLE PKTABLE; ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" ! DROP TABLE FKTABLE; -- -- check set default and table constraint on multiple columns -- --- 137,144 ---- | | 8 (5 rows) ! DROP TABLE PKTABLE CASCADE; ! NOTICE: Cascading drop to Table fktable -- -- check set default and table constraint on multiple columns -- *************** *** 223,231 **** -1 | -2 | 8 (5 rows) ! DROP TABLE PKTABLE; ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" ! DROP TABLE FKTABLE; -- -- First test, check with no on delete or on update -- --- 221,228 ---- -1 | -2 | 8 (5 rows) ! DROP TABLE PKTABLE CASCADE; ! NOTICE: Cascading drop to Table fktable -- -- First test, check with no on delete or on update -- *************** *** 298,306 **** 0 | Test4 (4 rows) ! DROP TABLE PKTABLE; ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "fktable" ! DROP TABLE FKTABLE; -- MATCH unspecified -- Base test restricting update/delete CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); --- 295,302 ---- 0 | Test4 (4 rows) ! DROP TABLE PKTABLE CASCADE; ! NOTICE: Cascading drop to Table fktable -- MATCH unspecified -- Base test restricting update/delete CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); *************** *** 363,370 **** (5 rows) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" DROP TABLE PKTABLE; -- cascade update/delete CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); --- 359,364 ---- *************** *** 462,469 **** (4 rows) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" DROP TABLE PKTABLE; -- set null update / set default delete CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); --- 456,461 ---- *************** *** 568,575 **** (6 rows) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" DROP TABLE PKTABLE; -- set default update / set null delete CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); --- 560,565 ---- *************** *** 687,694 **** (7 rows) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" DROP TABLE PKTABLE; CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'pktable_pkey' for table 'pktable' --- 677,682 ---- *************** *** 734,747 **** CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable); NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" -- As should this CREATE TABLE FKTABLE (ftest1 varchar REFERENCES pktable(ptest1)); NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" DROP TABLE PKTABLE; -- Two columns, two tables CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)); --- 722,731 ---- *************** *** 775,788 **** CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1)); NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" -- As does this CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)); NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) DROP TABLE FKTABLE; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" DROP TABLE PKTABLE; -- Two columns, same table -- Make sure this still works... --- 759,768 ---- *************** *** 849,856 **** delete from pktable where base1>3; -- cleanup drop table fktable; - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" - NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" delete from pktable; -- Now 2 columns 2 tables, matching types create table fktable (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references pktable(base1, ptest1)); --- 829,834 ---- *************** *** 877,885 **** delete from pktable where base1>3; -- cleanup drop table fktable; ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" ! NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "pktable" ! drop table pktable; drop table pktable_base; -- Now we'll do one all in 1 table with 2 columns of matching types create table pktable_base(base1 int not null, base2 int); --- 855,861 ---- delete from pktable where base1>3; -- cleanup drop table fktable; ! drop table pktable cascade; drop table pktable_base; -- Now we'll do one all in 1 table with 2 columns of matching types create table pktable_base(base1 int not null, base2 int); *************** *** 903,909 **** -- this sequence of two deletes will work, since after the first there will be no (2,*) references delete from pktable where base2=2; delete from pktable where base1=2; ! drop table pktable; drop table pktable_base; -- 2 columns (2 tables), mismatched types create table pktable_base(base1 int not null); --- 879,885 ---- -- this sequence of two deletes will work, since after the first there will be no (2,*) references delete from pktable where base2=2; delete from pktable where base1=2; ! drop table pktable cascade; drop table pktable_base; -- 2 columns (2 tables), mismatched types create table pktable_base(base1 int not null); *************** *** 931,937 **** NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ERROR: Unable to identify an operator '=' for types 'integer' and 'inet' You will have to retype this query using an explicit cast ! drop table pktable; drop table pktable_base; -- 2 columns (1 table), mismatched types create table pktable_base(base1 int not null, base2 int); --- 907,913 ---- NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ERROR: Unable to identify an operator '=' for types 'integer' and 'inet' You will have to retype this query using an explicit cast ! drop table pktable cascade; drop table pktable_base; -- 2 columns (1 table), mismatched types create table pktable_base(base1 int not null, base2 int); *************** *** 959,964 **** NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) ERROR: Unable to identify an operator '=' for types 'inet' and 'integer' You will have to retype this query using an explicit cast - drop table pktable; - ERROR: table "pktable" does not exist drop table pktable_base; --- 935,938 ---- Index: src/test/regress/expected/sanity_check.out =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/sanity_check.out,v retrieving revision 1.17 diff -c -r1.17 sanity_check.out *** src/test/regress/expected/sanity_check.out 2002/03/22 21:34:44 1.17 --- src/test/regress/expected/sanity_check.out 2002/05/09 01:44:15 *************** *** 38,44 **** --- 38,46 ---- pg_attrdef | t pg_attribute | t pg_class | t + pg_constraint | t pg_database | t + pg_depend | t pg_description | t pg_group | t pg_index | t *************** *** 49,62 **** pg_opclass | t pg_operator | t pg_proc | t - pg_relcheck | t pg_rewrite | t pg_shadow | t pg_statistic | t pg_trigger | t pg_type | t road | t - serialtest | t shighway | t tenk1 | t tenk2 | t --- 51,62 ---- Index: src/test/regress/sql/alter_table.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/alter_table.sql,v retrieving revision 1.28 diff -c -r1.28 alter_table.sql *** src/test/regress/sql/alter_table.sql 2002/05/03 00:32:19 1.28 --- src/test/regress/sql/alter_table.sql 2002/05/09 01:44:16 *************** *** 218,228 **** -- Try (and succeed) ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full; -- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on -- tmp4 is a,b - ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full; DROP TABLE tmp5; DROP TABLE tmp4; --- 218,231 ---- -- Try (and succeed) ALTER TABLE tmp3 add constraint tmpconstr foreign key (a) references tmp2 match full; + -- Fail to add check constraint of same name as foreign key constraint + ALTER TABLE tmp3 add constraint tmpconstr check(a is not null); + -- Try (and fail) to create constraint from tmp5(a) to tmp4(a) - unique constraint on -- tmp4 is a,b ALTER TABLE tmp5 add constraint tmpconstr foreign key(a) references tmp4(a) match full; + DROP TABLE tmp5; DROP TABLE tmp4; *************** *** 250,256 **** ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; -- As should this ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); ! DROP TABLE pktable; DROP TABLE fktable; CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet, --- 253,260 ---- ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable; -- As should this ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1); ! DROP TABLE pktable restrict; ! DROP TABLE pktable cascade; DROP TABLE fktable; CREATE TEMP TABLE PKTABLE (ptest1 int, ptest2 inet, *************** *** 570,573 **** drop rule def_view_test_ins on def_view_test; drop view def_view_test; ! drop table def_test; --- 574,577 ---- drop rule def_view_test_ins on def_view_test; drop view def_view_test; ! drop table def_test; \ No newline at end of file Index: src/test/regress/sql/create_misc.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/create_misc.sql,v retrieving revision 1.9 diff -c -r1.9 create_misc.sql *** src/test/regress/sql/create_misc.sql 2001/05/21 16:54:46 1.9 --- src/test/regress/sql/create_misc.sql 2002/05/09 01:44:16 *************** *** 217,219 **** --- 217,226 ---- INSERT INTO serialTest VALUES ('wrong', NULL); SELECT * FROM serialTest; + + DROP TABLE serialTest; + + -- Ensure that Serial sequences are dropped with the table + CREATE TABLE serialTest (f1 text, f2 serial); + + DROP TABLE serialTest; Index: src/test/regress/sql/create_view.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/create_view.sql,v retrieving revision 1.3 diff -c -r1.3 create_view.sql *** src/test/regress/sql/create_view.sql 2000/06/10 05:19:26 1.3 --- src/test/regress/sql/create_view.sql 2002/05/09 01:44:16 *************** *** 17,21 **** CREATE VIEW toyemp AS SELECT name, age, location, 12*salary AS annualsal ! FROM emp; ! --- 17,20 ---- CREATE VIEW toyemp AS SELECT name, age, location, 12*salary AS annualsal ! FROM emp; \ No newline at end of file Index: src/test/regress/sql/domain.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/domain.sql,v retrieving revision 1.2 diff -c -r1.2 domain.sql *** src/test/regress/sql/domain.sql 2002/03/20 19:45:13 1.2 --- src/test/regress/sql/domain.sql 2002/05/09 01:44:16 *************** *** 6,12 **** create domain basetypetest domaindroptest; - drop domain domaindroptest cascade; drop domain domaindroptest; --- 6,11 ---- *************** *** 108,118 **** insert into defaulttest default values; insert into defaulttest default values; select * from defaulttest; - - drop sequence ddef4_seq; - drop table defaulttest; - drop domain ddef1 restrict; - drop domain ddef2 restrict; - drop domain ddef3 restrict; - drop domain ddef4 restrict; - drop domain ddef5 restrict; --- 107,109 ---- Index: src/test/regress/sql/drop.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/drop.sql,v retrieving revision 1.5 diff -c -r1.5 drop.sql *** src/test/regress/sql/drop.sql 2001/10/03 20:54:22 1.5 --- src/test/regress/sql/drop.sql 2002/05/09 01:44:16 *************** *** 1,247 **** -- ! -- drop.source -- ! -- ! -- this will fail if the user is not the postgres superuser. ! -- if it does, don't worry about it (you can turn usersuper ! -- back on as "postgres"). too many people don't follow ! -- directions and run this as "postgres", though... ! -- ! UPDATE pg_user ! SET usesuper = 't'::bool ! WHERE usename = 'postgres'; ! ! ! -- ! -- FUNCTION REMOVAL ! -- ! DROP FUNCTION hobbies(person); ! ! DROP FUNCTION hobby_construct(text,text); ! ! DROP FUNCTION equipment(hobbies_r); ! ! DROP FUNCTION user_relns(); ! ! DROP FUNCTION widget_in(opaque); ! ! DROP FUNCTION widget_out(opaque); ! ! DROP FUNCTION pt_in_widget(point,widget); ! ! DROP FUNCTION overpaid(emp); ! ! DROP FUNCTION boxarea(box); ! ! DROP FUNCTION interpt_pp(path,path); ! ! DROP FUNCTION reverse_name(name); ! ! DROP FUNCTION oldstyle_length(int4, text); ! ! -- ! -- OPERATOR REMOVAL ! -- ! DROP OPERATOR ## (path, path); ! ! DROP OPERATOR <% (point, widget); ! ! -- left unary ! DROP OPERATOR @#@ (none, int4); ! ! -- right unary ! DROP OPERATOR #@# (int4, none); ! ! -- right unary ! DROP OPERATOR #%# (int4, none); ! ! ! -- ! -- ABSTRACT DATA TYPE REMOVAL ! -- ! DROP TYPE city_budget; ! ! DROP TYPE widget; ! ! ! -- ! -- RULE REMOVAL ! -- (is also tested in queries.source) ! -- ! ! -- ! -- AGGREGATE REMOVAL ! -- ! DROP AGGREGATE newavg (int4); ! ! DROP AGGREGATE newsum (int4); ! ! DROP AGGREGATE newcnt (int4); ! ! ! -- ! -- CLASS REMOVAL ! -- (inheritance hierarchies are deleted in reverse order) ! -- ! ! -- ! -- DROP ancillary data structures (i.e. indices) ! -- ! DROP INDEX onek_unique1; ! ! DROP INDEX onek_unique2; ! ! DROP INDEX onek_hundred; ! ! DROP INDEX onek_stringu1; ! ! DROP INDEX tenk1_unique1; ! ! DROP INDEX tenk1_unique2; ! ! DROP INDEX tenk1_hundred; ! ! DROP INDEX tenk2_unique1; ! ! DROP INDEX tenk2_unique2; ! ! DROP INDEX tenk2_hundred; ! ! -- DROP INDEX onek2_u1_prtl; ! ! -- DROP INDEX onek2_u2_prtl; - -- DROP INDEX onek2_stu1_prtl; ! DROP INDEX rect2ind; - DROP INDEX rix; ! DROP INDEX iix; - DROP INDEX six; ! DROP INDEX hash_i4_index; - DROP INDEX hash_name_index; ! DROP INDEX hash_txt_index; - DROP INDEX hash_f8_index; ! -- DROP INDEX hash_ovfl_index; - DROP INDEX bt_i4_index; - DROP INDEX bt_name_index; - DROP INDEX bt_txt_index; - - DROP INDEX bt_f8_index; - - - DROP TABLE onek; - - DROP TABLE onek2; - - DROP TABLE tenk1; - - DROP TABLE tenk2; - - DROP TABLE Bprime; - - - DROP TABLE hobbies_r; - - DROP TABLE equipment_r; - - - DROP TABLE aggtest; - - DROP TABLE xacttest; - - DROP TABLE arrtest; - - DROP TABLE iportaltest; - - - DROP TABLE f_star; - - DROP TABLE e_star; - - DROP TABLE d_star; - - DROP TABLE c_star; - - DROP TABLE b_star; - - DROP TABLE a_star; - - - -- - -- must be in reverse inheritance order - -- - DROP TABLE stud_emp; - - DROP TABLE student; - - DROP TABLE slow_emp4000; - - DROP TABLE fast_emp4000; - - DROP TABLE emp; - - DROP TABLE person; - - - DROP TABLE ramp; - - DROP TABLE real_city; - - DROP TABLE dept; - - DROP TABLE ihighway; - - DROP TABLE shighway; - - DROP TABLE road; - - DROP TABLE city; - - - DROP TABLE hash_i4_heap; - - DROP TABLE hash_name_heap; - - DROP TABLE hash_txt_heap; - - DROP TABLE hash_f8_heap; - - -- DROP TABLE hash_ovfl_heap; - - DROP TABLE bt_i4_heap; - - DROP TABLE bt_name_heap; - - DROP TABLE bt_txt_heap; - - DROP TABLE bt_f8_heap; - - - DROP TABLE ABSTIME_TBL; - - DROP TABLE RELTIME_TBL; - - DROP TABLE TINTERVAL_TBL; - - -- - -- VIRTUAL CLASS REMOVAL - -- (also tests removal of rewrite rules) - -- - DROP VIEW street; - DROP VIEW iexit; - DROP VIEW toyemp; --- 1,43 ---- -- ! -- Test RESTRICT and CASCADE keywords. -- ! -- Ensure system types cannot be removed ! DROP TYPE int4 CASCADE; ! DROP FUNCTION nextval(text) CASCADE; ! DROP TABLE pg_type CASCADE; ! -- Function RESTRICT / CASCADE ! DROP FUNCTION widget_in(opaque) RESTRICT; -- fail ! DROP TYPE widget RESTRICT; -- fail ! DROP FUNCTION widget_in(opaque) CASCADE; ! DROP TYPE widget RESTRICT; -- doesn't exist ! -- Type RESTRICT / CASCADE ! DROP TYPE city_budget RESTRICT; -- fail ! DROP TYPE city_budget CASCADE; ! DROP TABLE city RESTRICT; -- doesn't exist ! -- Domain RESTRICT / CASCADE ! DROP DOMAIN ddef1 RESTRICT; -- fail ! DROP DOMAIN ddef1 CASCADE; ! DROP TABLE defaulttest RESTRICT; -- doesn't exist ! -- Procedural languge RESTRICT / CASCADE ! DROP LANGUAGE plpgsql RESTRICT; -- fail ! DROP LANGUAGE plpgsql CASCADE; ! SELECT recursion_test(2,3); -- doesn't exist ! -- Foreign Key RESTRICT / CASCADE ! -- See alter table pktable and fktable tests Index: src/test/regress/sql/foreign_key.sql =================================================================== RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/foreign_key.sql,v retrieving revision 1.6 diff -c -r1.6 foreign_key.sql *** src/test/regress/sql/foreign_key.sql 2002/05/03 00:32:19 1.6 --- src/test/regress/sql/foreign_key.sql 2002/05/09 01:44:19 *************** *** 40,47 **** -- Check FKTABLE for update of matched row SELECT * FROM FKTABLE; ! DROP TABLE PKTABLE; ! DROP TABLE FKTABLE; -- -- check set NULL and table constraint on multiple columns --- 40,46 ---- -- Check FKTABLE for update of matched row SELECT * FROM FKTABLE; ! DROP TABLE PKTABLE CASCADE; -- -- check set NULL and table constraint on multiple columns *************** *** 92,99 **** -- Check FKTABLE for update of matched row SELECT * FROM FKTABLE; ! DROP TABLE PKTABLE; ! DROP TABLE FKTABLE; -- -- check set default and table constraint on multiple columns --- 91,97 ---- -- Check FKTABLE for update of matched row SELECT * FROM FKTABLE; ! DROP TABLE PKTABLE CASCADE; -- -- check set default and table constraint on multiple columns *************** *** 147,154 **** -- Check FKTABLE for update of matched row SELECT * FROM FKTABLE; ! DROP TABLE PKTABLE; ! DROP TABLE FKTABLE; -- --- 145,151 ---- -- Check FKTABLE for update of matched row SELECT * FROM FKTABLE; ! DROP TABLE PKTABLE CASCADE; -- *************** *** 197,204 **** -- Check PKTABLE for updates SELECT * FROM PKTABLE; ! DROP TABLE PKTABLE; ! DROP TABLE FKTABLE; -- MATCH unspecified --- 194,200 ---- -- Check PKTABLE for updates SELECT * FROM PKTABLE; ! DROP TABLE PKTABLE CASCADE; -- MATCH unspecified *************** *** 532,538 **** delete from pktable where base1>3; -- cleanup drop table fktable; ! drop table pktable; drop table pktable_base; -- Now we'll do one all in 1 table with 2 columns of matching types --- 528,534 ---- delete from pktable where base1>3; -- cleanup drop table fktable; ! drop table pktable cascade; drop table pktable_base; -- Now we'll do one all in 1 table with 2 columns of matching types *************** *** 552,558 **** -- this sequence of two deletes will work, since after the first there will be no (2,*) references delete from pktable where base2=2; delete from pktable where base1=2; ! drop table pktable; drop table pktable_base; -- 2 columns (2 tables), mismatched types --- 548,554 ---- -- this sequence of two deletes will work, since after the first there will be no (2,*) references delete from pktable where base2=2; delete from pktable where base1=2; ! drop table pktable cascade; drop table pktable_base; -- 2 columns (2 tables), mismatched types *************** *** 565,571 **** create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable); create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1)); create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1)); ! drop table pktable; drop table pktable_base; -- 2 columns (1 table), mismatched types --- 561,567 ---- create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable); create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1)); create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1)); ! drop table pktable cascade; drop table pktable_base; -- 2 columns (1 table), mismatched types *************** *** 578,583 **** pktable(base1, ptest1)) inherits (pktable_base); create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references pktable(base1, ptest1)) inherits (pktable_base); - drop table pktable; drop table pktable_base; --- 574,578 ----