Skip to content

Commit

Permalink
Port of PR#247 on zend-db to laminas-db (Fix for MySQL DROP CONSTRAINT)
Browse files Browse the repository at this point in the history
Signed-off-by: nanawel <nanawel@gmail.com>
  • Loading branch information
nanawel committed Dec 27, 2020
1 parent d2d2606 commit 2a6f131
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 13 deletions.
28 changes: 27 additions & 1 deletion docs/book/sql-ddl.md
Expand Up @@ -102,8 +102,34 @@ $table->changeColumn('name', Column\Varchar('new_name', 50));
You may also *drop* existing columns or constraints:

```php
use \Laminas\Db\Metadata\Object\ConstraintObject;

$table->dropColumn('foo');
$table->dropConstraint('my_index');

$constraint = new ConstraintObject('my_index', null);
$table->dropConstraint($constraint);
```

Notice: On MySQL, you need to specify the type of constraint you want to drop.
To do so you may use a `\Laminas\Db\Metadata\Object\ConstraintObject` and set its
type accordingly or directly a subclass of
`\Laminas\Db\Sql\Ddl\Constraint\ConstraintInterface`.

```php
use \Laminas\Db\Metadata\Object\ConstraintObject;

$fkConstraint = new ConstraintObject('my_fk', null);
$fkConstraint->setType('FOREIGN KEY');
$table->dropConstraint($fkConstraint);
```

```php
use \Laminas\Db\Sql\Ddl\Constraint\UniqueKey;

$idxConstraint = new UniqueKey(
null, 'my_unique_index'
);
$table->dropConstraint($idxConstraint);
```

## Dropping Tables
Expand Down
15 changes: 8 additions & 7 deletions src/Sql/Ddl/AlterTable.php
Expand Up @@ -9,6 +9,7 @@
namespace Laminas\Db\Sql\Ddl;

use Laminas\Db\Adapter\Platform\PlatformInterface;
use Laminas\Db\Metadata\Object\ConstraintObject;
use Laminas\Db\Sql\AbstractSql;
use Laminas\Db\Sql\TableIdentifier;

Expand All @@ -27,7 +28,7 @@ class AlterTable extends AbstractSql implements SqlInterface
protected $addColumns = [];

/**
* @var array
* @var Constraint\ConstraintInterface[]
*/
protected $addConstraints = [];

Expand All @@ -42,7 +43,7 @@ class AlterTable extends AbstractSql implements SqlInterface
protected $dropColumns = [];

/**
* @var array
* @var Constraint\ConstraintInterface[]|ConstraintObject[]
*/
protected $dropConstraints = [];

Expand Down Expand Up @@ -74,7 +75,7 @@ class AlterTable extends AbstractSql implements SqlInterface
],
self::DROP_CONSTRAINTS => [
"%1\$s" => [
[1 => "DROP CONSTRAINT %1\$s,\n", 'combinedby' => ""],
[1 => "DROP CONSTRAINT %1\$s,\n", 'combinedby' => " "],
]
]
];
Expand Down Expand Up @@ -138,12 +139,12 @@ public function dropColumn($name)
}

/**
* @param string $name
* @param Constraint\ConstraintInterface|ConstraintObject $constraint
* @return self Provides a fluent interface
*/
public function dropConstraint($name)
public function dropConstraint($constraint)
{
$this->dropConstraints[] = $name;
$this->dropConstraints[] = $constraint;

return $this;
}
Expand Down Expand Up @@ -229,7 +230,7 @@ protected function processDropConstraints(PlatformInterface $adapterPlatform = n
{
$sqls = [];
foreach ($this->dropConstraints as $constraint) {
$sqls[] = $adapterPlatform->quoteIdentifier($constraint);
$sqls[] = $adapterPlatform->quoteIdentifier($constraint->getName());
}

return [$sqls];
Expand Down
5 changes: 5 additions & 0 deletions src/Sql/Ddl/Constraint/ConstraintInterface.php
Expand Up @@ -13,4 +13,9 @@
interface ConstraintInterface extends ExpressionInterface
{
public function getColumns();

/**
* @return string
*/
public function getName();
}
42 changes: 42 additions & 0 deletions src/Sql/Platform/Mysql/Ddl/AlterTableDecorator.php
Expand Up @@ -9,7 +9,11 @@
namespace Laminas\Db\Sql\Platform\Mysql\Ddl;

use Laminas\Db\Adapter\Platform\PlatformInterface;
use Laminas\Db\Metadata\Object\ConstraintObject;
use Laminas\Db\Sql\Ddl\AlterTable;
use Laminas\Db\Sql\Ddl\Constraint\ForeignKey;
use Laminas\Db\Sql\Ddl\Constraint\PrimaryKey;
use Laminas\Db\Sql\Ddl\Index\AbstractIndex;
use Laminas\Db\Sql\Platform\PlatformDecoratorInterface;

class AlterTableDecorator extends AlterTable implements PlatformDecoratorInterface
Expand Down Expand Up @@ -42,6 +46,11 @@ class AlterTableDecorator extends AlterTable implements PlatformDecoratorInterfa
public function setSubject($subject)
{
$this->subject = $subject;
$this->subject->specifications[self::DROP_CONSTRAINTS] = [
"%1\$s" => [
[2 => "DROP %1\$s %2\$s,\n", 'combinedby' => " "],
]
];

return $this;
}
Expand Down Expand Up @@ -247,4 +256,37 @@ private function compareColumnOptions($columnA, $columnB)

return $columnA - $columnB;
}

protected function processDropConstraints(PlatformInterface $adapterPlatform = null)
{
$sqls = [];
foreach ($this->dropConstraints as $constraint) {
$sqls[] = [
$this->getConstraintType($constraint),
$adapterPlatform->quoteIdentifier($constraint->getName())
];
}

return [$sqls];
}

/**
* @param $constraint
* @return string
*/
protected function getConstraintType($constraint)
{
if ($constraint instanceof ConstraintObject) {
return $constraint->getType();
}
if ($constraint instanceof PrimaryKey) {
return 'PRIMARY KEY';
} elseif ($constraint instanceof ForeignKey) {
return 'FOREIGN KEY';
} elseif ($constraint instanceof AbstractIndex) {
return 'INDEX';
} else {
return 'KEY';
}
}
}
7 changes: 5 additions & 2 deletions test/unit/Sql/Ddl/AlterTableTest.php
Expand Up @@ -8,6 +8,7 @@

namespace LaminasTest\Db\Sql\Ddl;

use Laminas\Db\Metadata\Object\ConstraintObject;
use Laminas\Db\Sql\Ddl\AlterTable;
use Laminas\Db\Sql\Ddl\Column;
use Laminas\Db\Sql\Ddl\Constraint;
Expand Down Expand Up @@ -94,14 +95,16 @@ public function testGetSqlString()
$at->changeColumn('name', new Column\Varchar('new_name', 50));
$at->dropColumn('foo');
$at->addConstraint(new Constraint\ForeignKey('my_fk', 'other_id', 'other_table', 'id', 'CASCADE', 'CASCADE'));
$at->dropConstraint('my_index');
$at->dropConstraint(new ConstraintObject('my_index', null));
$at->dropConstraint(new Constraint\UniqueKey(null, 'my_unique_index'));
$expected = <<<EOS
ALTER TABLE "foo"
ADD COLUMN "another" VARCHAR(255) NOT NULL,
CHANGE COLUMN "name" "new_name" VARCHAR(50) NOT NULL,
DROP COLUMN "foo",
ADD CONSTRAINT "my_fk" FOREIGN KEY ("other_id") REFERENCES "other_table" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
DROP CONSTRAINT "my_index"
DROP CONSTRAINT "my_index",
DROP CONSTRAINT "my_unique_index"
EOS;

$actual = $at->getSqlString();
Expand Down
17 changes: 14 additions & 3 deletions test/unit/Sql/Platform/Mysql/Ddl/AlterTableDecoratorTest.php
Expand Up @@ -9,9 +9,11 @@
namespace LaminasTest\Db\Sql\Platform\Mysql\Ddl;

use Laminas\Db\Adapter\Platform\Mysql;
use Laminas\Db\Metadata\Object\ConstraintObject;
use Laminas\Db\Sql\Ddl\AlterTable;
use Laminas\Db\Sql\Ddl\Column\Column;
use Laminas\Db\Sql\Ddl\Constraint\PrimaryKey;
use Laminas\Db\Sql\Ddl\Constraint\UniqueKey;
use Laminas\Db\Sql\Platform\Mysql\Ddl\AlterTableDecorator;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -45,9 +47,18 @@ public function testGetSqlString()
$col->addConstraint(new PrimaryKey());
$ct->addColumn($col);

self::assertEquals(
"ALTER TABLE `foo`\n ADD COLUMN `bar` INTEGER UNSIGNED ZEROFILL " .
"NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'baz' AFTER `bar`",
$fk = new ConstraintObject('my_fk', null);
$fk->setType('FOREIGN KEY');
$ct->dropConstraint($fk);

$ct->dropConstraint(new UniqueKey(null, 'my_unique_index'));

$this->assertEquals(
"ALTER TABLE `foo`\n"
." ADD COLUMN `bar` INTEGER UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'baz'"
." AFTER `bar`,\n"
." DROP FOREIGN KEY `my_fk`,\n"
." DROP KEY `my_unique_index`",
@$ctd->getSqlString(new Mysql())
);
}
Expand Down

0 comments on commit 2a6f131

Please sign in to comment.