Skip to content

Commit 689dea4

Browse files
committed
Report all dependent objects to the server log when a shared object is dropped,
and only a truncated log of the objects in the current database to the client. Also, instead of reporting object counts for all databases on which the user might own objects, report only as many as fit in the predefined line count. This is to avoid flooding the client when the user owns too many objects, which could cause problems. Per report from Ed L. on April 4th and subsequent discussion.
1 parent ed9a31b commit 689dea4

File tree

1 file changed

+94
-37
lines changed

1 file changed

+94
-37
lines changed

src/backend/catalog/pg_shdepend.c

Lines changed: 94 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.18 2007/05/11 17:57:12 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.19 2007/05/14 16:50:36 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -456,6 +456,9 @@ typedef struct
456456
* Check whether there are shared dependency entries for a given shared
457457
* object. Returns a string containing a newline-separated list of object
458458
* descriptions that depend on the shared object, or NULL if none is found.
459+
* The size of the returned string is limited to about MAX_REPORTED_DEPS lines;
460+
* if there are more objects than that, the output is returned truncated at
461+
* that point and the full message is logged to the postmaster log.
459462
*
460463
* We can find three different kinds of dependencies: dependencies on objects
461464
* of the current database; dependencies on shared objects; and dependencies
@@ -472,21 +475,26 @@ checkSharedDependencies(Oid classId, Oid objectId)
472475
ScanKeyData key[2];
473476
SysScanDesc scan;
474477
HeapTuple tup;
475-
int totalDeps = 0;
476-
int numLocalDeps = 0;
477-
int numSharedDeps = 0;
478+
int numNotReportedDeps = 0;
479+
int numReportedDeps = 0;
480+
int numNotReportedDbs = 0;
478481
List *remDeps = NIL;
479482
ListCell *cell;
480483
ObjectAddress object;
481484
StringInfoData descs;
485+
StringInfoData alldescs;
482486

483487
/*
484-
* We try to limit the number of reported dependencies to something sane,
485-
* both for the user's sake and to avoid blowing out memory.
488+
* We try to limit the number of dependencies reported to the client to
489+
* something sane, both for the user's sake and to avoid blowing out
490+
* memory. The server log always gets a full report, which is collected
491+
* in a separate StringInfo if and only if we detect that the original
492+
* report is going to be truncated.
486493
*/
487494
#define MAX_REPORTED_DEPS 100
488495

489496
initStringInfo(&descs);
497+
initStringInfo(&alldescs);
490498

491499
sdepRel = heap_open(SharedDependRelationId, AccessShareLock);
492500

@@ -531,17 +539,35 @@ checkSharedDependencies(Oid classId, Oid objectId)
531539
*/
532540
if (sdepForm->dbid == MyDatabaseId)
533541
{
534-
numLocalDeps++;
535-
if (++totalDeps <= MAX_REPORTED_DEPS)
542+
if (++numReportedDeps <= MAX_REPORTED_DEPS)
536543
storeObjectDescription(&descs, LOCAL_OBJECT, &object,
537544
sdepForm->deptype, 0);
545+
else
546+
{
547+
numNotReportedDeps++;
548+
/* initialize the server-only log line */
549+
if (alldescs.len == 0)
550+
appendBinaryStringInfo(&alldescs, descs.data, descs.len);
551+
552+
storeObjectDescription(&alldescs, LOCAL_OBJECT, &object,
553+
sdepForm->deptype, 0);
554+
}
538555
}
539556
else if (sdepForm->dbid == InvalidOid)
540557
{
541-
numSharedDeps++;
542-
if (++totalDeps <= MAX_REPORTED_DEPS)
558+
if (++numReportedDeps <= MAX_REPORTED_DEPS)
543559
storeObjectDescription(&descs, SHARED_OBJECT, &object,
544560
sdepForm->deptype, 0);
561+
else
562+
{
563+
numNotReportedDeps++;
564+
/* initialize the server-only log line */
565+
if (alldescs.len == 0)
566+
appendBinaryStringInfo(&alldescs, descs.data, descs.len);
567+
568+
storeObjectDescription(&alldescs, SHARED_OBJECT, &object,
569+
sdepForm->deptype, 0);
570+
}
545571
}
546572
else
547573
{
@@ -571,7 +597,6 @@ checkSharedDependencies(Oid classId, Oid objectId)
571597
dep->dbOid = sdepForm->dbid;
572598
dep->count = 1;
573599
remDeps = lappend(remDeps, dep);
574-
totalDeps++;
575600
}
576601
}
577602
}
@@ -580,28 +605,11 @@ checkSharedDependencies(Oid classId, Oid objectId)
580605

581606
heap_close(sdepRel, AccessShareLock);
582607

583-
if (totalDeps > MAX_REPORTED_DEPS)
584-
{
585-
/*
586-
* Report seems unreasonably long, so reduce it to per-database info
587-
*
588-
* Note: we don't ever suppress per-database totals, which should be
589-
* OK as long as there aren't too many databases ...
590-
*/
591-
resetStringInfo(&descs);
592-
593-
if (numLocalDeps > 0)
594-
{
595-
appendStringInfo(&descs, _("%d objects in this database"),
596-
numLocalDeps);
597-
if (numSharedDeps > 0)
598-
appendStringInfoChar(&descs, '\n');
599-
}
600-
if (numSharedDeps > 0)
601-
appendStringInfo(&descs, _("%d shared objects"),
602-
numSharedDeps);
603-
}
604-
608+
/*
609+
* Report dependencies on remote databases. If we're truncating the
610+
* output already, don't put a line per database, but a single one for all
611+
* of them. Otherwise add as many as fit in MAX_REPORTED_DEPS.
612+
*/
605613
foreach(cell, remDeps)
606614
{
607615
remoteDep *dep = lfirst(cell);
@@ -610,18 +618,63 @@ checkSharedDependencies(Oid classId, Oid objectId)
610618
object.objectId = dep->dbOid;
611619
object.objectSubId = 0;
612620

613-
storeObjectDescription(&descs, REMOTE_OBJECT, &object,
614-
SHARED_DEPENDENCY_INVALID, dep->count);
621+
if (alldescs.len != 0)
622+
{
623+
numNotReportedDbs++;
624+
storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
625+
SHARED_DEPENDENCY_INVALID, dep->count);
626+
}
627+
else
628+
{
629+
if (numReportedDeps <= MAX_REPORTED_DEPS)
630+
{
631+
numReportedDeps++;
632+
storeObjectDescription(&descs, REMOTE_OBJECT, &object,
633+
SHARED_DEPENDENCY_INVALID, dep->count);
634+
}
635+
else
636+
{
637+
/* initialize the server-only log line */
638+
numNotReportedDbs++;
639+
appendBinaryStringInfo(&alldescs, descs.data, descs.len);
640+
storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
641+
SHARED_DEPENDENCY_INVALID, dep->count);
642+
}
643+
}
644+
}
645+
646+
if (numNotReportedDbs > 0)
647+
{
648+
appendStringInfo(&descs, "\nand objects in other %d databases",
649+
numNotReportedDbs);
615650
}
616651

617652
list_free_deep(remDeps);
618653

619654
if (descs.len == 0)
620655
{
621656
pfree(descs.data);
657+
pfree(alldescs.data);
622658
return NULL;
623659
}
624660

661+
if (numNotReportedDbs + numNotReportedDeps > 0)
662+
{
663+
ObjectAddress obj;
664+
665+
obj.classId = classId;
666+
obj.objectId = objectId;
667+
obj.objectSubId = 0;
668+
ereport(LOG,
669+
(errmsg("objects dependent on %s", getObjectDescription(&obj)),
670+
errdetail(alldescs.data)));
671+
672+
if (numNotReportedDeps > 0)
673+
appendStringInfo(&descs, "\nand other %d objects",
674+
numNotReportedDeps);
675+
}
676+
pfree(alldescs.data);
677+
625678
return descs.data;
626679
}
627680

@@ -977,8 +1030,12 @@ storeObjectDescription(StringInfo descs, objectType type,
9771030
break;
9781031

9791032
case REMOTE_OBJECT:
980-
/* translator: %s will always be "database %s" */
981-
appendStringInfo(descs, _("%d objects in %s"), count, objdesc);
1033+
if (count == 1)
1034+
/* translator: %s will always be "database %s" */
1035+
appendStringInfo(descs, _("one object in %s"), objdesc);
1036+
else
1037+
/* translator: %s will always be "database %s" */
1038+
appendStringInfo(descs, _("%d objects in %s"), count, objdesc);
9821039
break;
9831040

9841041
default:

0 commit comments

Comments
 (0)