fix: DockerSecretsResolver - don't normalize absolute paths like /var/www/html/...
Some checks failed
Deploy Application / deploy (push) Has been cancelled
Some checks failed
Deploy Application / deploy (push) Has been cancelled
This commit is contained in:
@@ -5,15 +5,20 @@ declare(strict_types=1);
|
||||
namespace App\Framework\Database\Browser\Discovery;
|
||||
|
||||
use App\Framework\Database\Browser\ValueObjects\TableMetadata;
|
||||
use App\Framework\Database\ConnectionInterface;
|
||||
use App\Framework\Database\DatabaseManager;
|
||||
use App\Framework\Database\ValueObjects\SqlQuery;
|
||||
|
||||
final readonly class TableDiscovery
|
||||
{
|
||||
public function __construct(
|
||||
private ConnectionInterface $connection
|
||||
private DatabaseManager $databaseManager
|
||||
) {
|
||||
}
|
||||
|
||||
private function getConnection(): \App\Framework\Database\ConnectionInterface
|
||||
{
|
||||
return $this->databaseManager->getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover all tables in the current database
|
||||
@@ -21,6 +26,72 @@ final readonly class TableDiscovery
|
||||
* @return array<TableMetadata>
|
||||
*/
|
||||
public function discoverAllTables(): array
|
||||
{
|
||||
$driver = $this->getDriver();
|
||||
|
||||
if ($driver === 'pgsql') {
|
||||
return $this->discoverPostgreSQLTables();
|
||||
}
|
||||
|
||||
return $this->discoverMySQLTables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover PostgreSQL tables
|
||||
*/
|
||||
private function discoverPostgreSQLTables(): array
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
t.tablename as table_name,
|
||||
COALESCE(s.n_live_tup::bigint, 0) as estimated_rows,
|
||||
ROUND(pg_total_relation_size('public.'||t.tablename) / 1024.0 / 1024.0, 2) as size_mb,
|
||||
NULL as engine,
|
||||
NULL as table_collation
|
||||
FROM pg_tables t
|
||||
LEFT JOIN pg_stat_user_tables s ON s.relname = t.tablename
|
||||
WHERE t.schemaname = 'public'
|
||||
ORDER BY t.tablename
|
||||
";
|
||||
|
||||
$query = SqlQuery::create($sql, []);
|
||||
$result = $this->getConnection()->query($query);
|
||||
$tables = $result->fetchAll();
|
||||
|
||||
$tableMetadata = [];
|
||||
foreach ($tables as $tableData) {
|
||||
$estimatedRows = isset($tableData['estimated_rows']) && $tableData['estimated_rows'] !== null ? (int) $tableData['estimated_rows'] : 0;
|
||||
|
||||
// For small tables (< 1000 estimated rows), get exact count
|
||||
// This ensures accuracy for small tables where pg_stat_user_tables might be outdated
|
||||
$rowCount = $estimatedRows;
|
||||
if ($estimatedRows < 1000) {
|
||||
try {
|
||||
$countQuery = SqlQuery::create("SELECT COUNT(*) FROM \"{$tableData['table_name']}\"", []);
|
||||
$exactCount = $this->getConnection()->queryScalar($countQuery);
|
||||
$rowCount = $exactCount !== null ? (int) $exactCount : $estimatedRows;
|
||||
} catch (\Throwable $e) {
|
||||
// If exact count fails, fall back to estimated count
|
||||
$rowCount = $estimatedRows;
|
||||
}
|
||||
}
|
||||
|
||||
$tableMetadata[] = new TableMetadata(
|
||||
name: $tableData['table_name'],
|
||||
rowCount: $rowCount,
|
||||
sizeMb: isset($tableData['size_mb']) ? (float) $tableData['size_mb'] : null,
|
||||
engine: null, // PostgreSQL doesn't have engine concept
|
||||
collation: null, // PostgreSQL collation is per-column, not per-table
|
||||
);
|
||||
}
|
||||
|
||||
return $tableMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover MySQL tables
|
||||
*/
|
||||
private function discoverMySQLTables(): array
|
||||
{
|
||||
$databaseName = $this->getCurrentDatabase();
|
||||
|
||||
@@ -38,7 +109,7 @@ final readonly class TableDiscovery
|
||||
";
|
||||
|
||||
$query = SqlQuery::create($sql, [$databaseName]);
|
||||
$result = $this->connection->query($query);
|
||||
$result = $this->getConnection()->query($query);
|
||||
$tables = $result->fetchAll();
|
||||
|
||||
$tableMetadata = [];
|
||||
@@ -59,6 +130,55 @@ final readonly class TableDiscovery
|
||||
* Discover a specific table by name
|
||||
*/
|
||||
public function discoverTable(string $tableName): ?TableMetadata
|
||||
{
|
||||
$driver = $this->getDriver();
|
||||
|
||||
if ($driver === 'pgsql') {
|
||||
return $this->discoverPostgreSQLTable($tableName);
|
||||
}
|
||||
|
||||
return $this->discoverMySQLTable($tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover a specific PostgreSQL table
|
||||
*/
|
||||
private function discoverPostgreSQLTable(string $tableName): ?TableMetadata
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
t.tablename as table_name,
|
||||
COALESCE(s.n_live_tup::bigint, 0) as table_rows,
|
||||
ROUND(pg_total_relation_size('public.'||?) / 1024.0 / 1024.0, 2) as size_mb,
|
||||
NULL as engine,
|
||||
NULL as table_collation
|
||||
FROM pg_tables t
|
||||
LEFT JOIN pg_stat_user_tables s ON s.relname = t.tablename
|
||||
WHERE t.schemaname = 'public'
|
||||
AND t.tablename = ?
|
||||
";
|
||||
|
||||
$query = SqlQuery::create($sql, [$tableName, $tableName]);
|
||||
$result = $this->getConnection()->query($query);
|
||||
$row = $result->fetch();
|
||||
|
||||
if ($row === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TableMetadata(
|
||||
name: $row['table_name'],
|
||||
rowCount: isset($row['table_rows']) && $row['table_rows'] !== null ? (int) $row['table_rows'] : null,
|
||||
sizeMb: isset($row['size_mb']) ? (float) $row['size_mb'] : null,
|
||||
engine: null,
|
||||
collation: null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover a specific MySQL table
|
||||
*/
|
||||
private function discoverMySQLTable(string $tableName): ?TableMetadata
|
||||
{
|
||||
$databaseName = $this->getCurrentDatabase();
|
||||
|
||||
@@ -75,7 +195,7 @@ final readonly class TableDiscovery
|
||||
";
|
||||
|
||||
$query = SqlQuery::create($sql, [$databaseName, $tableName]);
|
||||
$result = $this->connection->query($query);
|
||||
$result = $this->getConnection()->query($query);
|
||||
$row = $result->fetch();
|
||||
|
||||
if ($row === null) {
|
||||
@@ -96,12 +216,28 @@ final readonly class TableDiscovery
|
||||
*/
|
||||
private function getCurrentDatabase(): string
|
||||
{
|
||||
$sql = "SELECT DATABASE() as db";
|
||||
$driver = $this->getDriver();
|
||||
|
||||
if ($driver === 'pgsql') {
|
||||
$sql = "SELECT current_database() as db";
|
||||
} else {
|
||||
$sql = "SELECT DATABASE() as db";
|
||||
}
|
||||
|
||||
$query = SqlQuery::create($sql, []);
|
||||
$result = $this->connection->query($query);
|
||||
$result = $this->getConnection()->query($query);
|
||||
$row = $result->fetch();
|
||||
|
||||
return $row['db'] ?? 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database driver name
|
||||
*/
|
||||
private function getDriver(): string
|
||||
{
|
||||
$pdo = $this->getConnection()->getPdo();
|
||||
return $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user