fix : connect to target database for table count and largest table queries
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
information_schema and pg_class only show tables from the current database. Open a temporary connection to the target database for these queries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace App\Service;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\DriverManager;
|
||||
|
||||
final class DatabaseService
|
||||
{
|
||||
@@ -28,7 +29,7 @@ final class DatabaseService
|
||||
];
|
||||
|
||||
try {
|
||||
// Check database exists
|
||||
// Check database exists (cross-database query via system catalog)
|
||||
$exists = $this->connection->fetchOne(
|
||||
'SELECT 1 FROM pg_database WHERE datname = :dbname',
|
||||
['dbname' => $databaseName]
|
||||
@@ -38,33 +39,40 @@ final class DatabaseService
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
// Database size
|
||||
// Database size (cross-database, works from any connection)
|
||||
$sizeBytes = (int) $this->connection->fetchOne(
|
||||
'SELECT pg_database_size(:dbname)',
|
||||
['dbname' => $databaseName]
|
||||
);
|
||||
$size = $this->formatBytes($sizeBytes);
|
||||
|
||||
// Table count
|
||||
$tableCount = (int) $this->connection->fetchOne(
|
||||
"SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_catalog = :dbname",
|
||||
['dbname' => $databaseName]
|
||||
);
|
||||
|
||||
// Active connections
|
||||
// Active connections (cross-database system view)
|
||||
$activeConnections = (int) $this->connection->fetchOne(
|
||||
'SELECT count(*) FROM pg_stat_activity WHERE datname = :dbname',
|
||||
['dbname' => $databaseName]
|
||||
);
|
||||
|
||||
// Cache hit ratio
|
||||
// Cache hit ratio (cross-database system view)
|
||||
$cacheHitRatio = (float) ($this->connection->fetchOne(
|
||||
'SELECT round(100.0 * sum(blks_hit) / nullif(sum(blks_hit + blks_read), 0), 2) FROM pg_stat_database WHERE datname = :dbname',
|
||||
['dbname' => $databaseName]
|
||||
) ?? 0);
|
||||
|
||||
// Largest table — requires querying the target database catalog
|
||||
$largestTable = $this->fetchLargestTable($databaseName);
|
||||
// Connect to the target database for table-specific queries
|
||||
$targetConn = $this->connectToDatabase($databaseName);
|
||||
|
||||
try {
|
||||
// Table count (must query target database's information_schema)
|
||||
$tableCount = (int) $targetConn->fetchOne(
|
||||
"SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public' AND table_catalog = :dbname",
|
||||
['dbname' => $databaseName]
|
||||
);
|
||||
|
||||
// Largest table (must query target database's pg_class)
|
||||
$largestTable = $this->fetchLargestTable($targetConn);
|
||||
} finally {
|
||||
$targetConn->close();
|
||||
}
|
||||
|
||||
return [
|
||||
'connected' => true,
|
||||
@@ -80,15 +88,22 @@ final class DatabaseService
|
||||
}
|
||||
}
|
||||
|
||||
private function fetchLargestTable(string $databaseName): string
|
||||
private function connectToDatabase(string $databaseName): Connection
|
||||
{
|
||||
$params = $this->connection->getParams();
|
||||
$params['dbname'] = $databaseName;
|
||||
|
||||
return DriverManager::getConnection($params);
|
||||
}
|
||||
|
||||
private function fetchLargestTable(Connection $conn): string
|
||||
{
|
||||
try {
|
||||
$row = $this->connection->fetchAssociative(
|
||||
$row = $conn->fetchAssociative(
|
||||
"SELECT relname, pg_total_relation_size(c.oid) as total_size
|
||||
FROM pg_catalog.pg_class c
|
||||
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE n.nspname = 'public' AND c.relkind = 'r'
|
||||
AND c.relowner = (SELECT oid FROM pg_roles WHERE rolname = current_user)
|
||||
ORDER BY pg_total_relation_size(c.oid) DESC
|
||||
LIMIT 1"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user