*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.18 2007/05/11 17:57:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.19 2007/05/14 16:50:36 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
* Check whether there are shared dependency entries for a given shared
* object. Returns a string containing a newline-separated list of object
* descriptions that depend on the shared object, or NULL if none is found.
+ * The size of the returned string is limited to about MAX_REPORTED_DEPS lines;
+ * if there are more objects than that, the output is returned truncated at
+ * that point and the full message is logged to the postmaster log.
*
* We can find three different kinds of dependencies: dependencies on objects
* of the current database; dependencies on shared objects; and dependencies
ScanKeyData key[2];
SysScanDesc scan;
HeapTuple tup;
- int totalDeps = 0;
- int numLocalDeps = 0;
- int numSharedDeps = 0;
+ int numNotReportedDeps = 0;
+ int numReportedDeps = 0;
+ int numNotReportedDbs = 0;
List *remDeps = NIL;
ListCell *cell;
ObjectAddress object;
StringInfoData descs;
+ StringInfoData alldescs;
/*
- * We try to limit the number of reported dependencies to something sane,
- * both for the user's sake and to avoid blowing out memory.
+ * We try to limit the number of dependencies reported to the client to
+ * something sane, both for the user's sake and to avoid blowing out
+ * memory. The server log always gets a full report, which is collected
+ * in a separate StringInfo if and only if we detect that the original
+ * report is going to be truncated.
*/
#define MAX_REPORTED_DEPS 100
initStringInfo(&descs);
+ initStringInfo(&alldescs);
sdepRel = heap_open(SharedDependRelationId, AccessShareLock);
*/
if (sdepForm->dbid == MyDatabaseId)
{
- numLocalDeps++;
- if (++totalDeps <= MAX_REPORTED_DEPS)
+ if (++numReportedDeps <= MAX_REPORTED_DEPS)
storeObjectDescription(&descs, LOCAL_OBJECT, &object,
sdepForm->deptype, 0);
+ else
+ {
+ numNotReportedDeps++;
+ /* initialize the server-only log line */
+ if (alldescs.len == 0)
+ appendBinaryStringInfo(&alldescs, descs.data, descs.len);
+
+ storeObjectDescription(&alldescs, LOCAL_OBJECT, &object,
+ sdepForm->deptype, 0);
+ }
}
else if (sdepForm->dbid == InvalidOid)
{
- numSharedDeps++;
- if (++totalDeps <= MAX_REPORTED_DEPS)
+ if (++numReportedDeps <= MAX_REPORTED_DEPS)
storeObjectDescription(&descs, SHARED_OBJECT, &object,
sdepForm->deptype, 0);
+ else
+ {
+ numNotReportedDeps++;
+ /* initialize the server-only log line */
+ if (alldescs.len == 0)
+ appendBinaryStringInfo(&alldescs, descs.data, descs.len);
+
+ storeObjectDescription(&alldescs, SHARED_OBJECT, &object,
+ sdepForm->deptype, 0);
+ }
}
else
{
dep->dbOid = sdepForm->dbid;
dep->count = 1;
remDeps = lappend(remDeps, dep);
- totalDeps++;
}
}
}
heap_close(sdepRel, AccessShareLock);
- if (totalDeps > MAX_REPORTED_DEPS)
- {
- /*
- * Report seems unreasonably long, so reduce it to per-database info
- *
- * Note: we don't ever suppress per-database totals, which should be
- * OK as long as there aren't too many databases ...
- */
- resetStringInfo(&descs);
-
- if (numLocalDeps > 0)
- {
- appendStringInfo(&descs, _("%d objects in this database"),
- numLocalDeps);
- if (numSharedDeps > 0)
- appendStringInfoChar(&descs, '\n');
- }
- if (numSharedDeps > 0)
- appendStringInfo(&descs, _("%d shared objects"),
- numSharedDeps);
- }
-
+ /*
+ * Report dependencies on remote databases. If we're truncating the
+ * output already, don't put a line per database, but a single one for all
+ * of them. Otherwise add as many as fit in MAX_REPORTED_DEPS.
+ */
foreach(cell, remDeps)
{
remoteDep *dep = lfirst(cell);
object.objectId = dep->dbOid;
object.objectSubId = 0;
- storeObjectDescription(&descs, REMOTE_OBJECT, &object,
- SHARED_DEPENDENCY_INVALID, dep->count);
+ if (alldescs.len != 0)
+ {
+ numNotReportedDbs++;
+ storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
+ SHARED_DEPENDENCY_INVALID, dep->count);
+ }
+ else
+ {
+ if (numReportedDeps <= MAX_REPORTED_DEPS)
+ {
+ numReportedDeps++;
+ storeObjectDescription(&descs, REMOTE_OBJECT, &object,
+ SHARED_DEPENDENCY_INVALID, dep->count);
+ }
+ else
+ {
+ /* initialize the server-only log line */
+ numNotReportedDbs++;
+ appendBinaryStringInfo(&alldescs, descs.data, descs.len);
+ storeObjectDescription(&alldescs, REMOTE_OBJECT, &object,
+ SHARED_DEPENDENCY_INVALID, dep->count);
+ }
+ }
+ }
+
+ if (numNotReportedDbs > 0)
+ {
+ appendStringInfo(&descs, "\nand objects in other %d databases",
+ numNotReportedDbs);
}
list_free_deep(remDeps);
if (descs.len == 0)
{
pfree(descs.data);
+ pfree(alldescs.data);
return NULL;
}
+ if (numNotReportedDbs + numNotReportedDeps > 0)
+ {
+ ObjectAddress obj;
+
+ obj.classId = classId;
+ obj.objectId = objectId;
+ obj.objectSubId = 0;
+ ereport(LOG,
+ (errmsg("objects dependent on %s", getObjectDescription(&obj)),
+ errdetail(alldescs.data)));
+
+ if (numNotReportedDeps > 0)
+ appendStringInfo(&descs, "\nand other %d objects",
+ numNotReportedDeps);
+ }
+ pfree(alldescs.data);
+
return descs.data;
}
break;
case REMOTE_OBJECT:
- /* translator: %s will always be "database %s" */
- appendStringInfo(descs, _("%d objects in %s"), count, objdesc);
+ if (count == 1)
+ /* translator: %s will always be "database %s" */
+ appendStringInfo(descs, _("one object in %s"), objdesc);
+ else
+ /* translator: %s will always be "database %s" */
+ appendStringInfo(descs, _("%d objects in %s"), count, objdesc);
break;
default: