~ubuntu-branches/ubuntu/lucid/postgresql-8.4/lucid-proposed

« back to all changes in this revision

Viewing changes to src/backend/catalog/dependency.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-11 16:59:35 UTC
  • mfrom: (5.1.1 karmic)
  • Revision ID: james.westby@ubuntu.com-20090711165935-jfwin6gfrxf0gfsi
Tags: 8.4.0-2
* debian/libpq-dev.install: Ship catalog/genbki.h. (Closes: #536139)
* debian/rules: Drop --enable-cassert for final release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 * Portions Copyright (c) 1994, Regents of the University of California
9
9
 *
10
10
 * IDENTIFICATION
11
 
 *        $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.87 2009/03/26 22:26:06 petere Exp $
 
11
 *        $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.89 2009/06/11 14:48:54 momjian Exp $
12
12
 *
13
13
 *-------------------------------------------------------------------------
14
14
 */
94
94
struct ObjectAddresses
95
95
{
96
96
        ObjectAddress *refs;            /* => palloc'd array */
97
 
        ObjectAddressExtra *extras;     /* => palloc'd array, or NULL if not used */
 
97
        ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
98
98
        int                     numrefs;                /* current number of references */
99
99
        int                     maxrefs;                /* current size of palloc'd array(s) */
100
100
};
104
104
/* threaded list of ObjectAddresses, for recursion detection */
105
105
typedef struct ObjectAddressStack
106
106
{
107
 
        const ObjectAddress *object; /* object being visited */
 
107
        const ObjectAddress *object;    /* object being visited */
108
108
        int                     flags;                  /* its current flag bits */
109
 
        struct ObjectAddressStack *next; /* next outer stack level */
 
109
        struct ObjectAddressStack *next;        /* next outer stack level */
110
110
} ObjectAddressStack;
111
111
 
112
112
/* for find_expr_references_walker */
171
171
                                                           const ObjectAddressExtra *extra,
172
172
                                                           ObjectAddresses *addrs);
173
173
static bool object_address_present_add_flags(const ObjectAddress *object,
174
 
                                                                                         int flags,
175
 
                                                                                         ObjectAddresses *addrs);
 
174
                                                                 int flags,
 
175
                                                                 ObjectAddresses *addrs);
176
176
static void getRelationDescription(StringInfo buffer, Oid relid);
177
177
static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
178
178
 
204
204
        depRel = heap_open(DependRelationId, RowExclusiveLock);
205
205
 
206
206
        /*
207
 
         * Acquire deletion lock on the target object.  (Ideally the caller has
 
207
         * Acquire deletion lock on the target object.  (Ideally the caller has
208
208
         * done this already, but many places are sloppy about it.)
209
209
         */
210
210
        AcquireDeletionLock(object);
276
276
        /*
277
277
         * Construct a list of objects to delete (ie, the given objects plus
278
278
         * everything directly or indirectly dependent on them).  Note that
279
 
         * because we pass the whole objects list as pendingObjects context,
280
 
         * we won't get a failure from trying to delete an object that is
281
 
         * internally dependent on another one in the list; we'll just skip
282
 
         * that object and delete it when we reach its owner.
 
279
         * because we pass the whole objects list as pendingObjects context, we
 
280
         * won't get a failure from trying to delete an object that is internally
 
281
         * dependent on another one in the list; we'll just skip that object and
 
282
         * delete it when we reach its owner.
283
283
         */
284
284
        targetObjects = new_object_addresses();
285
285
 
295
295
 
296
296
                findDependentObjects(thisobj,
297
297
                                                         DEPFLAG_ORIGINAL,
298
 
                                                         NULL,  /* empty stack */
 
298
                                                         NULL,          /* empty stack */
299
299
                                                         targetObjects,
300
300
                                                         objects,
301
301
                                                         depRel);
304
304
        /*
305
305
         * Check if deletion is allowed, and report about cascaded deletes.
306
306
         *
307
 
         * If there's exactly one object being deleted, report it the same
308
 
         * way as in performDeletion(), else we have to be vaguer.
 
307
         * If there's exactly one object being deleted, report it the same way as
 
308
         * in performDeletion(), else we have to be vaguer.
309
309
         */
310
310
        reportDependentObjects(targetObjects,
311
311
                                                   behavior,
352
352
        depRel = heap_open(DependRelationId, RowExclusiveLock);
353
353
 
354
354
        /*
355
 
         * Acquire deletion lock on the target object.  (Ideally the caller has
 
355
         * Acquire deletion lock on the target object.  (Ideally the caller has
356
356
         * done this already, but many places are sloppy about it.)
357
357
         */
358
358
        AcquireDeletionLock(object);
404
404
 *
405
405
 * For every object that depends on the starting object, acquire a deletion
406
406
 * lock on the object, add it to targetObjects (if not already there),
407
 
 * and recursively find objects that depend on it.  An object's dependencies
 
407
 * and recursively find objects that depend on it.      An object's dependencies
408
408
 * will be placed into targetObjects before the object itself; this means
409
409
 * that the finished list's order represents a safe deletion order.
410
410
 *
446
446
 
447
447
        /*
448
448
         * If the target object is already being visited in an outer recursion
449
 
         * level, just report the current flags back to that level and exit.
450
 
         * This is needed to avoid infinite recursion in the face of circular
 
449
         * level, just report the current flags back to that level and exit. This
 
450
         * is needed to avoid infinite recursion in the face of circular
451
451
         * dependencies.
452
452
         *
453
453
         * The stack check alone would result in dependency loops being broken at
457
457
         * will not break a loop at an internal dependency: if we enter the loop
458
458
         * at an "owned" object we will switch and start at the "owning" object
459
459
         * instead.  We could probably hack something up to avoid breaking at an
460
 
         * auto dependency, too, if we had to.  However there are no known cases
 
460
         * auto dependency, too, if we had to.  However there are no known cases
461
461
         * where that would be necessary.
462
462
         */
463
463
        for (stackptr = stack; stackptr; stackptr = stackptr->next)
470
470
                                stackptr->flags |= flags;
471
471
                                return;
472
472
                        }
 
473
 
473
474
                        /*
474
475
                         * Could visit column with whole table already on stack; this is
475
476
                         * the same case noted in object_address_present_add_flags().
487
488
         * specified flags to its entry and return.
488
489
         *
489
490
         * (Note: in these early-exit cases we could release the caller-taken
490
 
         * lock, since the object is presumably now locked multiple times;
491
 
         * but it seems not worth the cycles.)
 
491
         * lock, since the object is presumably now locked multiple times; but it
 
492
         * seems not worth the cycles.)
492
493
         */
493
494
        if (object_address_present_add_flags(object, flags, targetObjects))
494
495
                return;
499
500
         * object, we have to transform this deletion request into a deletion
500
501
         * request of the owning object.  (We'll eventually recurse back to this
501
502
         * object, but the owning object has to be visited first so it will be
502
 
         * deleted after.)  The way to find out about this is to scan the
 
503
         * deleted after.)      The way to find out about this is to scan the
503
504
         * pg_depend entries that show what this object depends on.
504
505
         */
505
506
        ScanKeyInit(&key[0],
546
547
                                 *
547
548
                                 * 1. At the outermost recursion level, disallow the DROP. (We
548
549
                                 * just ereport here, rather than proceeding, since no other
549
 
                                 * dependencies are likely to be interesting.)  However, if
 
550
                                 * dependencies are likely to be interesting.)  However, if
550
551
                                 * the other object is listed in pendingObjects, just release
551
 
                                 * the caller's lock and return; we'll eventually complete
552
 
                                 * the DROP when we reach that entry in the pending list.
 
552
                                 * the caller's lock and return; we'll eventually complete the
 
553
                                 * DROP when we reach that entry in the pending list.
553
554
                                 */
554
555
                                if (stack == NULL)
555
556
                                {
597
598
                                AcquireDeletionLock(&otherObject);
598
599
 
599
600
                                /*
600
 
                                 * The other object might have been deleted while we waited
601
 
                                 * to lock it; if so, neither it nor the current object are
 
601
                                 * The other object might have been deleted while we waited to
 
602
                                 * lock it; if so, neither it nor the current object are
602
603
                                 * interesting anymore.  We test this by checking the
603
604
                                 * pg_depend entry (see notes below).
604
605
                                 */
610
611
                                }
611
612
 
612
613
                                /*
613
 
                                 * Okay, recurse to the other object instead of proceeding.
614
 
                                 * We treat this exactly as if the original reference had
615
 
                                 * linked to that object instead of this one; hence, pass
616
 
                                 * through the same flags and stack.
 
614
                                 * Okay, recurse to the other object instead of proceeding. We
 
615
                                 * treat this exactly as if the original reference had linked
 
616
                                 * to that object instead of this one; hence, pass through the
 
617
                                 * same flags and stack.
617
618
                                 */
618
619
                                findDependentObjects(&otherObject,
619
620
                                                                         flags,
643
644
        systable_endscan(scan);
644
645
 
645
646
        /*
646
 
         * Now recurse to any dependent objects.  We must visit them first
647
 
         * since they have to be deleted before the current object.
 
647
         * Now recurse to any dependent objects.  We must visit them first since
 
648
         * they have to be deleted before the current object.
648
649
         */
649
650
        mystack.object = object;        /* set up a new stack level */
650
651
        mystack.flags = flags;
675
676
        while (HeapTupleIsValid(tup = systable_getnext(scan)))
676
677
        {
677
678
                Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
678
 
                int             subflags;
 
679
                int                     subflags;
679
680
 
680
681
                otherObject.classId = foundDep->classid;
681
682
                otherObject.objectId = foundDep->objid;
687
688
                AcquireDeletionLock(&otherObject);
688
689
 
689
690
                /*
690
 
                 * The dependent object might have been deleted while we waited
691
 
                 * to lock it; if so, we don't need to do anything more with it.
692
 
                 * We can test this cheaply and independently of the object's type
693
 
                 * by seeing if the pg_depend tuple we are looking at is still live.
694
 
                 * (If the object got deleted, the tuple would have been deleted too.)
 
691
                 * The dependent object might have been deleted while we waited to
 
692
                 * lock it; if so, we don't need to do anything more with it. We can
 
693
                 * test this cheaply and independently of the object's type by seeing
 
694
                 * if the pg_depend tuple we are looking at is still live. (If the
 
695
                 * object got deleted, the tuple would have been deleted too.)
695
696
                 */
696
697
                if (!systable_recheck_tuple(scan, tup))
697
698
                {
743
744
        systable_endscan(scan);
744
745
 
745
746
        /*
746
 
         * Finally, we can add the target object to targetObjects.  Be careful
747
 
         * to include any flags that were passed back down to us from inner
748
 
         * recursion levels.
 
747
         * Finally, we can add the target object to targetObjects.      Be careful to
 
748
         * include any flags that were passed back down to us from inner recursion
 
749
         * levels.
749
750
         */
750
751
        extra.flags = mystack.flags;
751
752
        if (stack)
782
783
        int                     i;
783
784
 
784
785
        /*
785
 
         * If no error is to be thrown, and the msglevel is too low to be shown
786
 
         * to either client or server log, there's no need to do any of the work.
 
786
         * If no error is to be thrown, and the msglevel is too low to be shown to
 
787
         * either client or server log, there's no need to do any of the work.
787
788
         *
788
789
         * Note: this code doesn't know all there is to be known about elog
789
790
         * levels, but it works for NOTICE and DEBUG2, which are the only values
822
823
                objDesc = getObjectDescription(obj);
823
824
 
824
825
                /*
825
 
                 * If, at any stage of the recursive search, we reached the object
826
 
                 * via an AUTO or INTERNAL dependency, then it's okay to delete it
827
 
                 * even in RESTRICT mode.
 
826
                 * If, at any stage of the recursive search, we reached the object via
 
827
                 * an AUTO or INTERNAL dependency, then it's okay to delete it even in
 
828
                 * RESTRICT mode.
828
829
                 */
829
830
                if (extra->flags & (DEPFLAG_AUTO | DEPFLAG_INTERNAL))
830
831
                {
831
832
                        /*
832
 
                         * auto-cascades are reported at DEBUG2, not msglevel.  We
833
 
                         * don't try to combine them with the regular message because
834
 
                         * the results are too confusing when client_min_messages and
 
833
                         * auto-cascades are reported at DEBUG2, not msglevel.  We don't
 
834
                         * try to combine them with the regular message because the
 
835
                         * results are too confusing when client_min_messages and
835
836
                         * log_min_messages are different.
836
837
                         */
837
838
                        ereport(DEBUG2,
840
841
                }
841
842
                else if (behavior == DROP_RESTRICT)
842
843
                {
843
 
                        char   *otherDesc = getObjectDescription(&extra->dependee);
 
844
                        char       *otherDesc = getObjectDescription(&extra->dependee);
844
845
 
845
846
                        if (numReportedClient < MAX_REPORTED_DEPS)
846
847
                        {
897
898
                if (origObject)
898
899
                        ereport(ERROR,
899
900
                                        (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
900
 
                                         errmsg("cannot drop %s because other objects depend on it",
901
 
                                                        getObjectDescription(origObject)),
 
901
                                  errmsg("cannot drop %s because other objects depend on it",
 
902
                                                 getObjectDescription(origObject)),
902
903
                                         errdetail("%s", clientdetail.data),
903
904
                                         errdetail_log("%s", logdetail.data),
904
905
                                         errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
913
914
        else if (numReportedClient > 1)
914
915
        {
915
916
                ereport(msglevel,
916
 
                                /* translator: %d always has a value larger than 1 */
917
 
                                (errmsg(ngettext("drop cascades to %d other object",
918
 
                                                                 "drop cascades to %d other objects",
919
 
                                                                 numReportedClient + numNotReportedClient),
920
 
                                                numReportedClient + numNotReportedClient),
 
917
                /* translator: %d always has a value larger than 1 */
 
918
                                (errmsg_plural("drop cascades to %d other object",
 
919
                                                           "drop cascades to %d other objects",
 
920
                                                           numReportedClient + numNotReportedClient,
 
921
                                                           numReportedClient + numNotReportedClient),
921
922
                                 errdetail("%s", clientdetail.data),
922
923
                                 errdetail_log("%s", logdetail.data)));
923
924
        }
947
948
 
948
949
        /*
949
950
         * First remove any pg_depend records that link from this object to
950
 
         * others.  (Any records linking to this object should be gone already.)
 
951
         * others.      (Any records linking to this object should be gone already.)
951
952
         *
952
953
         * When dropping a whole object (subId = 0), remove all pg_depend records
953
954
         * for its sub-objects too.
982
983
        systable_endscan(scan);
983
984
 
984
985
        /*
985
 
         * Delete shared dependency references related to this object.  Again,
986
 
         * if subId = 0, remove records for sub-objects too.
 
986
         * Delete shared dependency references related to this object.  Again, if
 
987
         * subId = 0, remove records for sub-objects too.
987
988
         */
988
989
        deleteSharedDependencyRecordsFor(object->classId, object->objectId,
989
990
                                                                         object->objectSubId);
1651
1652
                                newrefs;
1652
1653
 
1653
1654
        /*
1654
 
         * We can't sort if the array has "extra" data, because there's no way
1655
 
         * to keep it in sync.  Fortunately that combination of features is
1656
 
         * not needed.
 
1655
         * We can't sort if the array has "extra" data, because there's no way to
 
1656
         * keep it in sync.  Fortunately that combination of features is not
 
1657
         * needed.
1657
1658
         */
1658
1659
        Assert(!addrs->extras);
1659
1660
 
1828
1829
                addrs->refs = (ObjectAddress *)
1829
1830
                        repalloc(addrs->refs, addrs->maxrefs * sizeof(ObjectAddress));
1830
1831
                addrs->extras = (ObjectAddressExtra *)
1831
 
                  repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
 
1832
                        repalloc(addrs->extras, addrs->maxrefs * sizeof(ObjectAddressExtra));
1832
1833
        }
1833
1834
        /* record this item */
1834
1835
        item = addrs->refs + addrs->numrefs;
1894
1895
                        {
1895
1896
                                /*
1896
1897
                                 * We get here if we find a need to delete a column after
1897
 
                                 * having already decided to drop its whole table.  Obviously
 
1898
                                 * having already decided to drop its whole table.      Obviously
1898
1899
                                 * we no longer need to drop the column.  But don't plaster
1899
1900
                                 * its flags on the table.
1900
1901
                                 */
2136
2137
 
2137
2138
                                if (OidIsValid(con->conrelid))
2138
2139
                                {
2139
 
                                        StringInfoData  rel;
 
2140
                                        StringInfoData rel;
2140
2141
 
2141
2142
                                        initStringInfo(&rel);
2142
2143
                                        getRelationDescription(&rel, con->conrelid);
2304
2305
 
2305
2306
                                initStringInfo(&opfam);
2306
2307
                                getOpFamilyDescription(&opfam, amopForm->amopfamily);
 
2308
 
2307
2309
                                /*
2308
2310
                                 * translator: %d is the operator strategy (a number), the
2309
 
                                 * first %s is the textual form of the operator, and the second
2310
 
                                 * %s is the description of the operator family.
 
2311
                                 * first %s is the textual form of the operator, and the
 
2312
                                 * second %s is the description of the operator family.
2311
2313
                                 */
2312
2314
                                appendStringInfo(&buffer, _("operator %d %s of %s"),
2313
2315
                                                                 amopForm->amopstrategy,
2350
2352
 
2351
2353
                                initStringInfo(&opfam);
2352
2354
                                getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
 
2355
 
2353
2356
                                /*
2354
2357
                                 * translator: %d is the function number, the first %s is the
2355
2358
                                 * textual form of the function with arguments, and the second
2563
2566
 
2564
2567
                case OCLASS_USER_MAPPING:
2565
2568
                        {
2566
 
                                HeapTuple               tup;
2567
 
                                Oid                             useid;
2568
 
                                char               *usename;
 
2569
                                HeapTuple       tup;
 
2570
                                Oid                     useid;
 
2571
                                char       *usename;
2569
2572
 
2570
2573
                                tup = SearchSysCache(USERMAPPINGOID,
2571
2574
                                                                         ObjectIdGetDatum(object->objectId),