Skip to content

Commit

Permalink
[11.x] feat: Create missing pgsql database when running migrations (#…
Browse files Browse the repository at this point in the history
…54314)

* feat: Create missing pgsql database

* feat: Create missing pgsql database

* feat: Create missing pgsql database

* feat: Create missing pgsql database

* feat: Create missing pgsql database

* feat: Create missing pgsql database

* formatting

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
mathiasgrimm and taylorotwell authored Jan 27, 2025
1 parent 8d2c225 commit 96302bf
Showing 1 changed file with 46 additions and 19 deletions.
65 changes: 46 additions & 19 deletions src/Illuminate/Database/Console/Migrations/MigrateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Illuminate\Database\Migrations\Migrator;
use Illuminate\Database\SQLiteDatabaseDoesNotExistException;
use Illuminate\Database\SqlServerConnection;
use Illuminate\Support\Str;
use PDOException;
use RuntimeException;
use Symfony\Component\Console\Attribute\AsCommand;
Expand Down Expand Up @@ -163,26 +164,41 @@ protected function repositoryExists()
{
return retry(2, fn () => $this->migrator->repositoryExists(), 0, function ($e) {
try {
if ($e->getPrevious() instanceof SQLiteDatabaseDoesNotExistException) {
return $this->createMissingSqliteDatabase($e->getPrevious()->path);
}

$connection = $this->migrator->resolveConnection($this->option('database'));

if (
$e->getPrevious() instanceof PDOException &&
$e->getPrevious()->getCode() === 1049 &&
in_array($connection->getDriverName(), ['mysql', 'mariadb'])) {
return $this->createMissingMysqlDatabase($connection);
}

return false;
return $this->handleMissingDatabase($e->getPrevious());
} catch (Throwable) {
return false;
}
});
}

/**
* Attempt to create the database if it is missing.
*
* @param \Throwable $e
* @return bool
*/
protected function handleMissingDatabase(Throwable $e)
{
if ($e instanceof SQLiteDatabaseDoesNotExistException) {
return $this->createMissingSqliteDatabase($e->path);
}

$connection = $this->migrator->resolveConnection($this->option('database'));

if (! $e instanceof PDOException) {
return false;
}

if (($e->getCode() === 1049 && in_array($connection->getDriverName(), ['mysql', 'mariadb'])) ||
(($e->errorInfo[0] ?? null) == '08006' &&
$connection->getDriverName() == 'pgsql' &&
Str::contains($e->getMessage(), '"'.$connection->getDatabaseName().'"'))) {
return $this->createMissingMySqlOrPgsqlDatabase($connection);
}

return false;
}

/**
* Create a missing SQLite database.
*
Expand Down Expand Up @@ -213,13 +229,14 @@ protected function createMissingSqliteDatabase($path)
}

/**
* Create a missing MySQL database.
* Create a missing MySQL or Postgres database.
*
* @param \Illuminate\Database\Connection $connection
* @return bool
*
* @throws \RuntimeException
*/
protected function createMissingMysqlDatabase($connection)
protected function createMissingMySqlOrPgsqlDatabase($connection)
{
if ($this->laravel['config']->get("database.connections.{$connection->getName()}.database") !== $connection->getDatabaseName()) {
return false;
Expand All @@ -238,15 +255,25 @@ protected function createMissingMysqlDatabase($connection)
throw new RuntimeException('Database was not created. Aborting migration.');
}
}

try {
$this->laravel['config']->set("database.connections.{$connection->getName()}.database", null);
$this->laravel['config']->set(
"database.connections.{$connection->getName()}.database",
match ($connection->getDriverName()) {
'mysql', 'mariadb' => null,
'pgsql' => 'postgres',
},
);

$this->laravel['db']->purge();

$freshConnection = $this->migrator->resolveConnection($this->option('database'));

return tap($freshConnection->unprepared("CREATE DATABASE IF NOT EXISTS `{$connection->getDatabaseName()}`"), function () {
return tap($freshConnection->unprepared(
match ($connection->getDriverName()) {
'mysql', 'mariadb' => "CREATE DATABASE IF NOT EXISTS `{$connection->getDatabaseName()}`",
'pgsql' => 'CREATE DATABASE "'.$connection->getDatabaseName().'"',
}
), function () {
$this->laravel['db']->purge();
});
} finally {
Expand Down

0 comments on commit 96302bf

Please sign in to comment.