'string', 'citext' => 'string', 'enum' => 'string', 'geometry' => 'string', 'geomcollection' => 'string', 'linestring' => 'string', 'ltree' => 'string', 'multilinestring' => 'string', 'multipoint' => 'string', 'multipolygon' => 'string', 'point' => 'string', 'polygon' => 'string', 'sysname' => 'string', ]; /** * The Composer instance. * * @var \Illuminate\Support\Composer */ protected $composer; /** * Create a new command instance. * * @param \Illuminate\Support\Composer|null $composer * @return void */ public function __construct(Composer $composer = null) { parent::__construct(); $this->composer = $composer ?? $this->laravel->make(Composer::class); } /** * Register the custom Doctrine type mappings for inspection commands. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * @return void */ protected function registerTypeMappings(AbstractPlatform $platform) { foreach ($this->typeMappings as $type => $value) { $platform->registerDoctrineTypeMapping($type, $value); } } /** * Get a human-readable platform name for the given platform. * * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * @param string $database * @return string */ protected function getPlatformName(AbstractPlatform $platform, $database) { return match (class_basename($platform)) { 'MySQLPlatform' => 'MySQL <= 5', 'MySQL57Platform' => 'MySQL 5.7', 'MySQL80Platform' => 'MySQL 8', 'PostgreSQL100Platform', 'PostgreSQLPlatform' => 'Postgres', 'SqlitePlatform' => 'SQLite', 'SQLServerPlatform' => 'SQL Server', 'SQLServer2012Platform' => 'SQL Server 2012', default => $database, }; } /** * Get the size of a table in bytes. * * @param \Illuminate\Database\ConnectionInterface $connection * @param string $table * @return int|null */ protected function getTableSize(ConnectionInterface $connection, string $table) { return match (true) { $connection instanceof MySqlConnection => $this->getMySQLTableSize($connection, $table), $connection instanceof PostgresConnection => $this->getPostgresTableSize($connection, $table), $connection instanceof SQLiteConnection => $this->getSqliteTableSize($connection, $table), default => null, }; } /** * Get the size of a MySQL table in bytes. * * @param \Illuminate\Database\ConnectionInterface $connection * @param string $table * @return mixed */ protected function getMySQLTableSize(ConnectionInterface $connection, string $table) { $result = $connection->selectOne('SELECT (data_length + index_length) AS size FROM information_schema.TABLES WHERE table_schema = ? AND table_name = ?', [ $connection->getDatabaseName(), $table, ]); return Arr::wrap((array) $result)['size']; } /** * Get the size of a Postgres table in bytes. * * @param \Illuminate\Database\ConnectionInterface $connection * @param string $table * @return mixed */ protected function getPostgresTableSize(ConnectionInterface $connection, string $table) { $result = $connection->selectOne('SELECT pg_total_relation_size(?) AS size;', [ $table, ]); return Arr::wrap((array) $result)['size']; } /** * Get the size of a SQLite table in bytes. * * @param \Illuminate\Database\ConnectionInterface $connection * @param string $table * @return mixed */ protected function getSqliteTableSize(ConnectionInterface $connection, string $table) { try { $result = $connection->selectOne('SELECT SUM(pgsize) AS size FROM dbstat WHERE name=?', [ $table, ]); return Arr::wrap((array) $result)['size']; } catch (QueryException $e) { return null; } } /** * Get the number of open connections for a database. * * @param \Illuminate\Database\ConnectionInterface $connection * @return int|null */ protected function getConnectionCount(ConnectionInterface $connection) { $result = match (true) { $connection instanceof MySqlConnection => $connection->selectOne('show status where variable_name = "threads_connected"'), $connection instanceof PostgresConnection => $connection->selectOne('select count(*) AS "Value" from pg_stat_activity'), $connection instanceof SqlServerConnection => $connection->selectOne('SELECT COUNT(*) Value FROM sys.dm_exec_sessions WHERE status = ?', ['running']), default => null, }; if (! $result) { return null; } return Arr::wrap((array) $result)['Value']; } /** * Get the connection configuration details for the given connection. * * @param string $database * @return array */ protected function getConfigFromDatabase($database) { $database ??= config('database.default'); return Arr::except(config('database.connections.'.$database), ['password']); } /** * Ensure the dependencies for the database commands are available. * * @return bool */ protected function ensureDependenciesExist() { return tap(interface_exists('Doctrine\DBAL\Driver'), function ($dependenciesExist) { if (! $dependenciesExist && $this->components->confirm('Inspecting database information requires the Doctrine DBAL (doctrine/dbal) package. Would you like to install it?')) { $this->installDependencies(); } }); } /** * Install the command's dependencies. * * @return void * * @throws \Symfony\Component\Process\Exception\ProcessSignaledException */ protected function installDependencies() { $command = collect($this->composer->findComposer()) ->push('require doctrine/dbal') ->implode(' '); $process = Process::fromShellCommandline($command, null, null, null, null); if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { try { $process->setTty(true); } catch (RuntimeException $e) { $this->components->warn($e->getMessage()); } } try { $process->run(fn ($type, $line) => $this->output->write($line)); } catch (ProcessSignaledException $e) { if (extension_loaded('pcntl') && $e->getSignal() !== SIGINT) { throw $e; } } } }