Skip to content

Commit

Permalink
Allow ALTER TABLE with conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
natanfelles committed May 16, 2022
1 parent 3180a5d commit 6cfa9f5
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 17 deletions.
106 changes: 90 additions & 16 deletions src/Definition/AlterTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,30 @@ protected function renderNoWait() : ?string

/**
* @param callable $definition
* @param bool $ifNotExists
*
* @return static
*/
public function add(callable $definition) : static
public function add(callable $definition, bool $ifNotExists = false) : static
{
$this->sql['add'] = $definition;
$this->sql['add'][] = [
'definition' => $definition,
'if_not_exists' => $ifNotExists,
];
return $this;
}

/**
* @param callable $definition
*
* @return static
*/
public function addIfNotExists(callable $definition) : static
{
$this->sql['add'][] = [
'definition' => $definition,
'if_not_exists' => true,
];
return $this;
}

Expand All @@ -184,19 +202,42 @@ protected function renderAdd() : ?string
if ( ! isset($this->sql['add'])) {
return null;
}
$definition = new TableDefinition($this->database);
$this->sql['add']($definition);
return $definition->sql('ADD') ?: null;
$parts = [];
foreach ($this->sql['add'] as $add) {
$definition = new TableDefinition(
$this->database,
$add['if_not_exists'] ? 'IF NOT EXISTS' : null
);
$add['definition']($definition);
$part = $definition->sql('ADD');
if ($part) {
$parts[] = $part;
}
}
return $parts ? \implode(',' . \PHP_EOL, $parts) : null;
}

/**
* @param callable $definition
* @param bool $ifExists
*
* @return static
*/
public function change(callable $definition) : static
public function change(callable $definition, bool $ifExists = false) : static
{
$this->sql['change'][] = [
'definition' => $definition,
'if_exists' => $ifExists,
];
return $this;
}

public function changeIfExists(callable $definition) : static
{
$this->sql['change'] = $definition;
$this->sql['change'][] = [
'definition' => $definition,
'if_exists' => true,
];
return $this;
}

Expand All @@ -205,19 +246,42 @@ protected function renderChange() : ?string
if ( ! isset($this->sql['change'])) {
return null;
}
$definition = new TableDefinition($this->database);
$this->sql['change']($definition);
return $definition->sql('CHANGE') ?: null;
$parts = [];
foreach ($this->sql['change'] as $change) {
$definition = new TableDefinition(
$this->database,
$change['if_exists'] ? 'IF EXISTS' : null
);
$change['definition']($definition);
$part = $definition->sql('CHANGE');
if ($part) {
$parts[] = $part;
}
}
return $parts ? \implode(',' . \PHP_EOL, $parts) : null;
}

/**
* @param callable $definition
* @param bool $ifExists
*
* @return static
*/
public function modify(callable $definition) : static
public function modify(callable $definition, bool $ifExists = false) : static
{
$this->sql['modify'][] = [
'definition' => $definition,
'if_exists' => $ifExists,
];
return $this;
}

public function modifyIfExists(callable $definition) : static
{
$this->sql['modify'] = $definition;
$this->sql['modify'][] = [
'definition' => $definition,
'if_exists' => true,
];
return $this;
}

Expand All @@ -226,9 +290,19 @@ protected function renderModify() : ?string
if ( ! isset($this->sql['modify'])) {
return null;
}
$definition = new TableDefinition($this->database);
$this->sql['modify']($definition);
return $definition->sql('MODIFY') ?: null;
$parts = [];
foreach ($this->sql['modify'] as $modify) {
$definition = new TableDefinition(
$this->database,
$modify['if_exists'] ? 'IF EXISTS' : null
);
$modify['definition']($definition);
$part = $definition->sql('MODIFY');
if ($part) {
$parts[] = $part;
}
}
return $parts ? \implode(',' . \PHP_EOL, $parts) : null;
}

public function dropColumn(string $name, bool $ifExists = false) : static
Expand Down Expand Up @@ -652,7 +726,7 @@ protected function joinParts(array $parts) : string
*
* @return int|string The number of affected rows
*/
public function run() : int|string
public function run() : int | string
{
return $this->database->exec($this->sql());
}
Expand Down
12 changes: 11 additions & 1 deletion src/Definition/Table/TableDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ class TableDefinition extends DefinitionPart
* @var array<int,Check>
*/
protected array $checks = [];
protected ?string $condition = null;

/**
* TableDefinition constructor.
*
* @param Database $database
* @param string|null $condition
*/
public function __construct(Database $database)
public function __construct(Database $database, string $condition = null)
{
$this->database = $database;
$this->condition = $condition;
}

/**
Expand Down Expand Up @@ -99,6 +102,9 @@ protected function renderColumns(string $prefix = null) : string
if ($prefix) {
$prefix .= ' COLUMN';
}
if ($this->condition) {
$prefix .= ' ' . $this->condition;
}
$sql = [];
foreach ($this->columns as $column) {
$name = $this->database->protectIdentifier($column['name']);
Expand All @@ -116,6 +122,10 @@ protected function renderIndexes(string $prefix = null) : string
$sql = [];
foreach ($this->indexes as $index) {
$definition = $index['definition']->sql();
if ($this->condition) {
$definition = \explode('(', $definition, 2);
$definition = $definition[0] . $this->condition . ' (' . $definition[1];
}
$sql[] = " {$prefix}{$definition}";
}
return \implode(',' . \PHP_EOL, $sql);
Expand Down
55 changes: 55 additions & 0 deletions tests/Definition/AlterTableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ public function testAddEmpty() : void
);
}

public function testAddIfNotExists() : void
{
$sql = $this->alterTable->table('t1')
->addIfNotExists(static function (TableDefinition $definition) : void {
$definition->column('c1')->varchar(255);
$definition->column('c5')->int()->null();
$definition->index()->key('c1');
})->add(static function (TableDefinition $definition) : void {
$definition->column('c2')->int();
});
self::assertSame(
"ALTER TABLE `t1`\n ADD COLUMN IF NOT EXISTS `c1` varchar(255) NOT NULL,\n"
. " ADD COLUMN IF NOT EXISTS `c5` int NULL,\n"
. " ADD KEY IF NOT EXISTS (`c1`),\n"
. ' ADD COLUMN `c2` int NOT NULL',
$sql->sql()
);
}

public function testChange() : void
{
$sql = $this->alterTable->table('t1')
Expand All @@ -101,6 +120,24 @@ public function testChangeEmpty() : void
);
}

public function testChangeIfExists() : void
{
$sql = $this->alterTable->table('t1')
->change(static function (TableDefinition $definition) : void {
$definition->column('c2')->int();
})
->changeIfExists(static function (TableDefinition $definition) : void {
$definition->column('c1')->varchar(255);
$definition->column('c5')->int()->null();
});
self::assertSame(
"ALTER TABLE `t1`\n CHANGE COLUMN `c2` int NOT NULL,\n"
. " CHANGE COLUMN IF EXISTS `c1` varchar(255) NOT NULL,\n"
. ' CHANGE COLUMN IF EXISTS `c5` int NULL',
$sql->sql()
);
}

public function testModify() : void
{
$sql = $this->alterTable->table('t1')
Expand All @@ -124,6 +161,24 @@ public function testModifyEmpty() : void
);
}

public function testModifyIfExists() : void
{
$sql = $this->alterTable->table('t1')
->modify(static function (TableDefinition $definition) : void {
$definition->column('c2')->int();
})
->modifyIfExists(static function (TableDefinition $definition) : void {
$definition->column('c1')->varchar(255);
$definition->column('c5')->int()->null();
});
self::assertSame(
"ALTER TABLE `t1`\n MODIFY COLUMN `c2` int NOT NULL,\n"
. " MODIFY COLUMN IF EXISTS `c1` varchar(255) NOT NULL,\n"
. ' MODIFY COLUMN IF EXISTS `c5` int NULL',
$sql->sql()
);
}

public function testDropColumnIfExists() : void
{
$alterTable = $this->alterTable->table('t1')->dropColumnIfExists('foo');
Expand Down

0 comments on commit 6cfa9f5

Please sign in to comment.