Skip to content

Commit

Permalink
[11.x] Enhance database migrations (#51373)
Browse files Browse the repository at this point in the history
* enhance migrations

* formatting

* support drop column on legacy sqlite

* formatting

* fix tests

* force re-run tests

* formatting

* fix altering a table that has a column with zero as default

fixes #51747

* formatting

* formatting

* formatting

* formatting

* formatting

* Formatting

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
hafezdivandari and taylorotwell authored Jul 4, 2024
1 parent cdf6e21 commit 980e8d5
Show file tree
Hide file tree
Showing 15 changed files with 946 additions and 251 deletions.
106 changes: 98 additions & 8 deletions src/Illuminate/Database/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Schema\Grammars\Grammar;
use Illuminate\Database\Schema\Grammars\MySqlGrammar;
use Illuminate\Database\Schema\Grammars\SQLiteGrammar;
use Illuminate\Support\Fluent;
use Illuminate\Support\Traits\Macroable;

Expand Down Expand Up @@ -78,6 +79,13 @@ class Blueprint
*/
public $after;

/**
* The blueprint state instance.
*
* @var \Illuminate\Database\Schema\BlueprintState|null
*/
protected $state;

/**
* Create a new schema blueprint.
*
Expand Down Expand Up @@ -136,6 +144,10 @@ public function toSql(Connection $connection, Grammar $grammar)
$method = 'compile'.ucfirst($command->name);

if (method_exists($grammar, $method) || $grammar::hasMacro($method)) {
if ($this->hasState()) {
$this->state->update($command);
}

if (! is_null($sql = $grammar->$method($this, $command, $connection))) {
$statements = array_merge($statements, (array) $sql);
}
Expand All @@ -161,6 +173,8 @@ protected function ensureCommandsAreValid(Connection $connection)
/**
* Get all of the commands matching the given names.
*
* @deprecated Will be removed in a future Laravel version.
*
* @param array $names
* @return \Illuminate\Support\Collection
*/
Expand All @@ -180,17 +194,20 @@ protected function commandsNamed(array $names)
*/
protected function addImpliedCommands(Connection $connection, Grammar $grammar)
{
if (count($this->getAddedColumns()) > 0 && ! $this->creating()) {
array_unshift($this->commands, $this->createCommand('add'));
}

if (count($this->getChangedColumns()) > 0 && ! $this->creating()) {
array_unshift($this->commands, $this->createCommand('change'));
}

$this->addFluentIndexes($connection, $grammar);

$this->addFluentCommands($connection, $grammar);

if (! $this->creating()) {
$this->commands = array_map(
fn ($command) => $command instanceof ColumnDefinition
? $this->createCommand($command->change ? 'change' : 'add', ['column' => $command])
: $command,
$this->commands
);

$this->addAlterCommands($connection, $grammar);
}
}

/**
Expand Down Expand Up @@ -260,6 +277,48 @@ public function addFluentCommands(Connection $connection, Grammar $grammar)
}
}

/**
* Add the alter commands if whenever needed.
*
* @param \Illuminate\Database\Connection $connection
* @param \Illuminate\Database\Schema\Grammars\Grammar $grammar
* @return void
*/
public function addAlterCommands(Connection $connection, Grammar $grammar)
{
if (! $grammar instanceof SQLiteGrammar) {
return;
}

$alterCommands = $grammar->getAlterCommands($connection);

[$commands, $lastCommandWasAlter, $hasAlterCommand] = [
[], false, false,
];

foreach ($this->commands as $command) {
if (in_array($command->name, $alterCommands)) {
$hasAlterCommand = true;
$lastCommandWasAlter = true;
} elseif ($lastCommandWasAlter) {
$commands[] = $this->createCommand('alter');
$lastCommandWasAlter = false;
}

$commands[] = $command;
}

if ($lastCommandWasAlter) {
$commands[] = $this->createCommand('alter');
}

if ($hasAlterCommand) {
$this->state = new BlueprintState($this, $connection, $grammar);
}

$this->commands = $commands;
}

/**
* Determine if the blueprint has a create command.
*
Expand Down Expand Up @@ -1634,6 +1693,10 @@ protected function addColumnDefinition($definition)
{
$this->columns[] = $definition;

if (! $this->creating()) {
$this->commands[] = $definition;
}

if ($this->after) {
$definition->after($this->after);

Expand Down Expand Up @@ -1671,6 +1734,10 @@ public function removeColumn($name)
return $c['name'] != $name;
}));

$this->commands = array_values(array_filter($this->commands, function ($c) use ($name) {
return ! $c instanceof ColumnDefinition || $c['name'] != $name;
}));

return $this;
}

Expand Down Expand Up @@ -1740,6 +1807,27 @@ public function getCommands()
return $this->commands;
}

/*
* Determine if the blueprint has state.
*
* @param mixed $name
* @return bool
*/
private function hasState(): bool
{
return ! is_null($this->state);
}

/**
* Get the state of the blueprint.
*
* @return \Illuminate\Database\Schema\BlueprintState
*/
public function getState()
{
return $this->state;
}

/**
* Get the columns on the blueprint that should be added.
*
Expand All @@ -1755,6 +1843,8 @@ public function getAddedColumns()
/**
* Get the columns on the blueprint that should be changed.
*
* @deprecated Will be removed in a future Laravel version.
*
* @return \Illuminate\Database\Schema\ColumnDefinition[]
*/
public function getChangedColumns()
Expand Down
Loading

0 comments on commit 980e8d5

Please sign in to comment.