Skip to content

Commit c4f2a04

Browse files
committed
Improve reporting of dependencies in DROP to work like the scheme that we
devised for pg_shdepend, namely the individual dependencies are reported as DETAIL lines rather than coming out as separate NOTICEs. The client-side report is capped at 100 lines, but the server log always gets a full report.
1 parent ebff1d4 commit c4f2a04

File tree

10 files changed

+199
-87
lines changed

10 files changed

+199
-87
lines changed

src/backend/catalog/dependency.c

+109-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.74 2008/06/08 22:41:04 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.75 2008/06/11 21:53:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -62,6 +62,7 @@
6262
#include "storage/lmgr.h"
6363
#include "utils/builtins.h"
6464
#include "utils/fmgroids.h"
65+
#include "utils/guc.h"
6566
#include "utils/lsyscache.h"
6667
#include "utils/syscache.h"
6768
#include "utils/tqual.h"
@@ -752,7 +753,7 @@ findDependentObjects(const ObjectAddress *object,
752753
*
753754
* targetObjects: list of objects that are scheduled to be deleted
754755
* behavior: RESTRICT or CASCADE
755-
* msglevel: elog level for non-debug notice messages
756+
* msglevel: elog level for non-error report messages
756757
* origObject: base object of deletion, or NULL if not available
757758
* (the latter case occurs in DROP OWNED)
758759
*/
@@ -763,8 +764,36 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
763764
const ObjectAddress *origObject)
764765
{
765766
bool ok = true;
767+
StringInfoData clientdetail;
768+
StringInfoData logdetail;
769+
int numReportedClient = 0;
770+
int numNotReportedClient = 0;
766771
int i;
767772

773+
/*
774+
* If no error is to be thrown, and the msglevel is too low to be shown
775+
* to either client or server log, there's no need to do any of the work.
776+
*
777+
* Note: this code doesn't know all there is to be known about elog
778+
* levels, but it works for NOTICE and DEBUG2, which are the only values
779+
* msglevel can currently have. We also assume we are running in a normal
780+
* operating environment.
781+
*/
782+
if (behavior == DROP_CASCADE &&
783+
msglevel < client_min_messages &&
784+
(msglevel < log_min_messages || log_min_messages == LOG))
785+
return;
786+
787+
/*
788+
* We limit the number of dependencies reported to the client to
789+
* MAX_REPORTED_DEPS, since client software may not deal well with
790+
* enormous error strings. The server log always gets a full report.
791+
*/
792+
#define MAX_REPORTED_DEPS 100
793+
794+
initStringInfo(&clientdetail);
795+
initStringInfo(&logdetail);
796+
768797
/*
769798
* We process the list back to front (ie, in dependency order not deletion
770799
* order), since this makes for a more understandable display.
@@ -773,48 +802,118 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
773802
{
774803
const ObjectAddress *obj = &targetObjects->refs[i];
775804
const ObjectAddressExtra *extra = &targetObjects->extras[i];
805+
char *objDesc;
776806

777807
/* Ignore the original deletion target(s) */
778808
if (extra->flags & DEPFLAG_ORIGINAL)
779809
continue;
780810

811+
objDesc = getObjectDescription(obj);
812+
781813
/*
782814
* If, at any stage of the recursive search, we reached the object
783815
* via an AUTO or INTERNAL dependency, then it's okay to delete it
784816
* even in RESTRICT mode.
785817
*/
786818
if (extra->flags & (DEPFLAG_AUTO | DEPFLAG_INTERNAL))
819+
{
820+
/*
821+
* auto-cascades are reported at DEBUG2, not msglevel. We
822+
* don't try to combine them with the regular message because
823+
* the results are too confusing when client_min_messages and
824+
* log_min_messages are different.
825+
*/
787826
ereport(DEBUG2,
788827
(errmsg("drop auto-cascades to %s",
789-
getObjectDescription(obj))));
828+
objDesc)));
829+
}
790830
else if (behavior == DROP_RESTRICT)
791831
{
792-
ereport(msglevel,
793-
(errmsg("%s depends on %s",
794-
getObjectDescription(obj),
795-
getObjectDescription(&extra->dependee))));
832+
char *otherDesc = getObjectDescription(&extra->dependee);
833+
834+
if (numReportedClient < MAX_REPORTED_DEPS)
835+
{
836+
/* separate entries with a newline */
837+
if (clientdetail.len != 0)
838+
appendStringInfoChar(&clientdetail, '\n');
839+
appendStringInfo(&clientdetail, _("%s depends on %s"),
840+
objDesc, otherDesc);
841+
numReportedClient++;
842+
}
843+
else
844+
numNotReportedClient++;
845+
/* separate entries with a newline */
846+
if (logdetail.len != 0)
847+
appendStringInfoChar(&logdetail, '\n');
848+
appendStringInfo(&logdetail, _("%s depends on %s"),
849+
objDesc, otherDesc);
850+
pfree(otherDesc);
796851
ok = false;
797852
}
798853
else
799-
ereport(msglevel,
800-
(errmsg("drop cascades to %s",
801-
getObjectDescription(obj))));
854+
{
855+
if (numReportedClient < MAX_REPORTED_DEPS)
856+
{
857+
/* separate entries with a newline */
858+
if (clientdetail.len != 0)
859+
appendStringInfoChar(&clientdetail, '\n');
860+
appendStringInfo(&clientdetail, _("drop cascades to %s"),
861+
objDesc);
862+
numReportedClient++;
863+
}
864+
else
865+
numNotReportedClient++;
866+
/* separate entries with a newline */
867+
if (logdetail.len != 0)
868+
appendStringInfoChar(&logdetail, '\n');
869+
appendStringInfo(&logdetail, _("drop cascades to %s"),
870+
objDesc);
871+
}
872+
873+
pfree(objDesc);
802874
}
803875

876+
if (numNotReportedClient > 0)
877+
appendStringInfo(&clientdetail, _("\nand %d other objects "
878+
"(see server log for list)"),
879+
numNotReportedClient);
880+
804881
if (!ok)
805882
{
806883
if (origObject)
807884
ereport(ERROR,
808885
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
809886
errmsg("cannot drop %s because other objects depend on it",
810887
getObjectDescription(origObject)),
888+
errdetail("%s", clientdetail.data),
889+
errdetail_log("%s", logdetail.data),
811890
errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
812891
else
813892
ereport(ERROR,
814893
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
815894
errmsg("cannot drop desired object(s) because other objects depend on them"),
895+
errdetail("%s", clientdetail.data),
896+
errdetail_log("%s", logdetail.data),
816897
errhint("Use DROP ... CASCADE to drop the dependent objects too.")));
817898
}
899+
else if (numReportedClient > 1)
900+
{
901+
ereport(msglevel,
902+
/* translator: %d always has a value larger than 1 */
903+
(errmsg("drop cascades to %d other objects",
904+
numReportedClient + numNotReportedClient),
905+
errdetail("%s", clientdetail.data),
906+
errdetail_log("%s", logdetail.data)));
907+
}
908+
else if (numReportedClient == 1)
909+
{
910+
/* we just use the single item as-is */
911+
ereport(msglevel,
912+
(errmsg_internal("%s", clientdetail.data)));
913+
}
914+
915+
pfree(clientdetail.data);
916+
pfree(logdetail.data);
818917
}
819918

820919
/*

src/test/regress/expected/alter_table.out

+9-7
Original file line numberDiff line numberDiff line change
@@ -1161,8 +1161,9 @@ order by relname, attnum;
11611161
(8 rows)
11621162

11631163
drop table p1, p2 cascade;
1164-
NOTICE: drop cascades to table c1
1165-
NOTICE: drop cascades to table gc1
1164+
NOTICE: drop cascades to 2 other objects
1165+
DETAIL: drop cascades to table c1
1166+
drop cascades to table gc1
11661167
--
11671168
-- Test the ALTER TABLE WITHOUT OIDS command
11681169
--
@@ -1469,8 +1470,9 @@ select alter2.plus1(41);
14691470

14701471
-- clean up
14711472
drop schema alter2 cascade;
1472-
NOTICE: drop cascades to table alter2.t1
1473-
NOTICE: drop cascades to view alter2.v1
1474-
NOTICE: drop cascades to function alter2.plus1(integer)
1475-
NOTICE: drop cascades to type alter2.posint
1476-
NOTICE: drop cascades to type alter2.ctype
1473+
NOTICE: drop cascades to 5 other objects
1474+
DETAIL: drop cascades to table alter2.t1
1475+
drop cascades to view alter2.v1
1476+
drop cascades to function alter2.plus1(integer)
1477+
drop cascades to type alter2.posint
1478+
drop cascades to type alter2.ctype

src/test/regress/expected/create_view.out

+40-38
Original file line numberDiff line numberDiff line change
@@ -237,43 +237,45 @@ And relnamespace IN (SELECT OID FROM pg_namespace WHERE nspname LIKE 'pg_temp%')
237237
(1 row)
238238

239239
DROP SCHEMA temp_view_test CASCADE;
240-
NOTICE: drop cascades to table temp_view_test.base_table
241-
NOTICE: drop cascades to view v7_temp
242-
NOTICE: drop cascades to view v10_temp
243-
NOTICE: drop cascades to view v11_temp
244-
NOTICE: drop cascades to view v12_temp
245-
NOTICE: drop cascades to view v2_temp
246-
NOTICE: drop cascades to view v4_temp
247-
NOTICE: drop cascades to view v6_temp
248-
NOTICE: drop cascades to view v8_temp
249-
NOTICE: drop cascades to view v9_temp
250-
NOTICE: drop cascades to table temp_view_test.base_table2
251-
NOTICE: drop cascades to view v5_temp
252-
NOTICE: drop cascades to view temp_view_test.v1
253-
NOTICE: drop cascades to view temp_view_test.v2
254-
NOTICE: drop cascades to view temp_view_test.v3
255-
NOTICE: drop cascades to view temp_view_test.v4
256-
NOTICE: drop cascades to view temp_view_test.v5
257-
NOTICE: drop cascades to view temp_view_test.v6
258-
NOTICE: drop cascades to view temp_view_test.v7
259-
NOTICE: drop cascades to view temp_view_test.v8
260-
NOTICE: drop cascades to sequence temp_view_test.seq1
261-
NOTICE: drop cascades to view temp_view_test.v9
240+
NOTICE: drop cascades to 22 other objects
241+
DETAIL: drop cascades to table temp_view_test.base_table
242+
drop cascades to view v7_temp
243+
drop cascades to view v10_temp
244+
drop cascades to view v11_temp
245+
drop cascades to view v12_temp
246+
drop cascades to view v2_temp
247+
drop cascades to view v4_temp
248+
drop cascades to view v6_temp
249+
drop cascades to view v8_temp
250+
drop cascades to view v9_temp
251+
drop cascades to table temp_view_test.base_table2
252+
drop cascades to view v5_temp
253+
drop cascades to view temp_view_test.v1
254+
drop cascades to view temp_view_test.v2
255+
drop cascades to view temp_view_test.v3
256+
drop cascades to view temp_view_test.v4
257+
drop cascades to view temp_view_test.v5
258+
drop cascades to view temp_view_test.v6
259+
drop cascades to view temp_view_test.v7
260+
drop cascades to view temp_view_test.v8
261+
drop cascades to sequence temp_view_test.seq1
262+
drop cascades to view temp_view_test.v9
262263
DROP SCHEMA testviewschm2 CASCADE;
263-
NOTICE: drop cascades to table t1
264-
NOTICE: drop cascades to view temporal1
265-
NOTICE: drop cascades to view temporal2
266-
NOTICE: drop cascades to view temporal3
267-
NOTICE: drop cascades to view temporal4
268-
NOTICE: drop cascades to table t2
269-
NOTICE: drop cascades to view nontemp1
270-
NOTICE: drop cascades to view nontemp2
271-
NOTICE: drop cascades to view nontemp3
272-
NOTICE: drop cascades to view nontemp4
273-
NOTICE: drop cascades to table tbl1
274-
NOTICE: drop cascades to table tbl2
275-
NOTICE: drop cascades to table tbl3
276-
NOTICE: drop cascades to table tbl4
277-
NOTICE: drop cascades to view mytempview
278-
NOTICE: drop cascades to view pubview
264+
NOTICE: drop cascades to 16 other objects
265+
DETAIL: drop cascades to table t1
266+
drop cascades to view temporal1
267+
drop cascades to view temporal2
268+
drop cascades to view temporal3
269+
drop cascades to view temporal4
270+
drop cascades to table t2
271+
drop cascades to view nontemp1
272+
drop cascades to view nontemp2
273+
drop cascades to view nontemp3
274+
drop cascades to view nontemp4
275+
drop cascades to table tbl1
276+
drop cascades to table tbl2
277+
drop cascades to table tbl3
278+
drop cascades to table tbl4
279+
drop cascades to view mytempview
280+
drop cascades to view pubview
279281
SET search_path to public;

src/test/regress/expected/domain.out

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ comment on domain domaindroptest is 'About to drop this..';
77
create domain dependenttypetest domaindroptest;
88
-- fail because of dependent type
99
drop domain domaindroptest;
10-
NOTICE: type dependenttypetest depends on type domaindroptest
1110
ERROR: cannot drop type domaindroptest because other objects depend on it
11+
DETAIL: type dependenttypetest depends on type domaindroptest
1212
HINT: Use DROP ... CASCADE to drop the dependent objects too.
1313
drop domain domaindroptest cascade;
1414
NOTICE: drop cascades to type dependenttypetest
@@ -266,8 +266,9 @@ ERROR: domain dnotnulltest does not allow null values
266266
alter domain dnotnulltest drop not null;
267267
update domnotnull set col1 = null;
268268
drop domain dnotnulltest cascade;
269-
NOTICE: drop cascades to table domnotnull column col1
270-
NOTICE: drop cascades to table domnotnull column col2
269+
NOTICE: drop cascades to 2 other objects
270+
DETAIL: drop cascades to table domnotnull column col1
271+
drop cascades to table domnotnull column col2
271272
-- Test ALTER DOMAIN .. DEFAULT ..
272273
create table domdeftest (col1 ddef1);
273274
insert into domdeftest default values;
@@ -395,8 +396,9 @@ insert into dtest values('xz23'); -- fail
395396
ERROR: value for domain dtop violates check constraint "dtop_check"
396397
drop table dtest;
397398
drop domain vchar4 cascade;
398-
NOTICE: drop cascades to type dinter
399-
NOTICE: drop cascades to type dtop
399+
NOTICE: drop cascades to 2 other objects
400+
DETAIL: drop cascades to type dinter
401+
drop cascades to type dtop
400402
-- Make sure that constraints of newly-added domain columns are
401403
-- enforced correctly, even if there's no default value for the new
402404
-- column. Per bug #1433

src/test/regress/expected/foreign_key.out

+11-10
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ SELECT * FROM FKTABLE;
257257

258258
-- this should fail for lack of CASCADE
259259
DROP TABLE PKTABLE;
260-
NOTICE: constraint constrname2 on table fktable depends on table pktable
261260
ERROR: cannot drop table pktable because other objects depend on it
261+
DETAIL: constraint constrname2 on table fktable depends on table pktable
262262
HINT: Use DROP ... CASCADE to drop the dependent objects too.
263263
DROP TABLE PKTABLE CASCADE;
264264
NOTICE: drop cascades to constraint constrname2 on table fktable
@@ -1157,15 +1157,16 @@ FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2);
11571157
ERROR: foreign key constraint "fk_241_132" cannot be implemented
11581158
DETAIL: Key columns "x2" and "id1" are of incompatible types: character varying and integer.
11591159
DROP TABLE pktable, fktable CASCADE;
1160-
NOTICE: drop cascades to constraint fktable_x3_fkey on table fktable
1161-
NOTICE: drop cascades to constraint fk_1_3 on table fktable
1162-
NOTICE: drop cascades to constraint fktable_x2_fkey on table fktable
1163-
NOTICE: drop cascades to constraint fk_4_2 on table fktable
1164-
NOTICE: drop cascades to constraint fktable_x1_fkey on table fktable
1165-
NOTICE: drop cascades to constraint fk_5_1 on table fktable
1166-
NOTICE: drop cascades to constraint fk_123_123 on table fktable
1167-
NOTICE: drop cascades to constraint fk_213_213 on table fktable
1168-
NOTICE: drop cascades to constraint fk_253_213 on table fktable
1160+
NOTICE: drop cascades to 9 other objects
1161+
DETAIL: drop cascades to constraint fktable_x3_fkey on table fktable
1162+
drop cascades to constraint fk_1_3 on table fktable
1163+
drop cascades to constraint fktable_x2_fkey on table fktable
1164+
drop cascades to constraint fk_4_2 on table fktable
1165+
drop cascades to constraint fktable_x1_fkey on table fktable
1166+
drop cascades to constraint fk_5_1 on table fktable
1167+
drop cascades to constraint fk_123_123 on table fktable
1168+
drop cascades to constraint fk_213_213 on table fktable
1169+
drop cascades to constraint fk_253_213 on table fktable
11691170
-- test a tricky case: we can elide firing the FK check trigger during
11701171
-- an UPDATE if the UPDATE did not change the foreign key
11711172
-- field. However, we can't do this if our transaction was the one that

src/test/regress/expected/inherit.out

+7-5
Original file line numberDiff line numberDiff line change
@@ -844,9 +844,10 @@ Inherits: c1,
844844
c2
845845

846846
drop table p1 cascade;
847-
NOTICE: drop cascades to table c1
848-
NOTICE: drop cascades to table c2
849-
NOTICE: drop cascades to table c3
847+
NOTICE: drop cascades to 3 other objects
848+
DETAIL: drop cascades to table c1
849+
drop cascades to table c2
850+
drop cascades to table c3
850851
drop table p2 cascade;
851852
create table pp1 (f1 int);
852853
create table cc1 (f2 text, f3 int) inherits (pp1);
@@ -900,5 +901,6 @@ Inherits: pp1,
900901
cc1
901902

902903
drop table pp1 cascade;
903-
NOTICE: drop cascades to table cc1
904-
NOTICE: drop cascades to table cc2
904+
NOTICE: drop cascades to 2 other objects
905+
DETAIL: drop cascades to table cc1
906+
drop cascades to table cc2

0 commit comments

Comments
 (0)