From 3a07c60398896d6833b9540714ddaf7b27b6c476 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 8 Apr 2018 12:42:57 +0200 Subject: [PATCH 01/21] Start internals refactor Using abumdant value objects to implement an interpreter-like machine with the name "Plan". The idea is that the plan can group the actions in a more intelligent way, that is also faster for the database to execute in most cases. Also refactored so that effects are treated more as data, this helps us compose alter statamentes into a single call when it is an option. --- composer.json | 1 + src/Phinx/Db/Action/Action.php | 7 + src/Phinx/Db/Action/AddColumn.php | 40 +++ src/Phinx/Db/Action/AddForeignKey.php | 46 ++++ src/Phinx/Db/Action/AddIndex.php | 50 ++++ src/Phinx/Db/Action/ChangeColumn.php | 53 ++++ src/Phinx/Db/Action/CreateTable.php | 26 ++ src/Phinx/Db/Action/DropColumn.php | 29 +++ src/Phinx/Db/Action/DropForeignKey.php | 47 ++++ src/Phinx/Db/Action/DropIndex.php | 47 ++++ src/Phinx/Db/Action/DropTable.php | 21 ++ src/Phinx/Db/Action/RemoveColumn.php | 37 +++ src/Phinx/Db/Action/RenameColumn.php | 45 ++++ src/Phinx/Db/Action/RenameTable.php | 29 +++ src/Phinx/Db/Adapter/AdapterInterface.php | 26 +- src/Phinx/Db/Adapter/AdapterWrapper.php | 6 +- src/Phinx/Db/Adapter/MysqlAdapter.php | 225 ++++++++-------- src/Phinx/Db/Adapter/PdoAdapter.php | 257 ++++++++++++++++++- src/Phinx/Db/Adapter/PostgresAdapter.php | 237 ++++++++--------- src/Phinx/Db/Adapter/ProxyAdapter.php | 6 +- src/Phinx/Db/Adapter/SQLiteAdapter.php | 182 +++++++------ src/Phinx/Db/Adapter/SqlServerAdapter.php | 270 +++++++++++--------- src/Phinx/Db/Adapter/TablePrefixAdapter.php | 37 +-- src/Phinx/Db/Adapter/TimedOutputAdapter.php | 6 +- src/Phinx/Db/Plan/AlterTable.php | 32 +++ src/Phinx/Db/Plan/Intent.php | 26 ++ src/Phinx/Db/Plan/NewTable.php | 46 ++++ src/Phinx/Db/Plan/Plan.php | 185 ++++++++++++++ src/Phinx/Db/Table.php | 56 +--- src/Phinx/Db/Table/Table.php | 47 ++++ src/Phinx/Db/Util/AlterInstructions.php | 43 ++++ 31 files changed, 1623 insertions(+), 542 deletions(-) create mode 100644 src/Phinx/Db/Action/Action.php create mode 100644 src/Phinx/Db/Action/AddColumn.php create mode 100644 src/Phinx/Db/Action/AddForeignKey.php create mode 100644 src/Phinx/Db/Action/AddIndex.php create mode 100644 src/Phinx/Db/Action/ChangeColumn.php create mode 100644 src/Phinx/Db/Action/CreateTable.php create mode 100644 src/Phinx/Db/Action/DropColumn.php create mode 100644 src/Phinx/Db/Action/DropForeignKey.php create mode 100644 src/Phinx/Db/Action/DropIndex.php create mode 100644 src/Phinx/Db/Action/DropTable.php create mode 100644 src/Phinx/Db/Action/RemoveColumn.php create mode 100644 src/Phinx/Db/Action/RenameColumn.php create mode 100644 src/Phinx/Db/Action/RenameTable.php create mode 100644 src/Phinx/Db/Plan/AlterTable.php create mode 100644 src/Phinx/Db/Plan/Intent.php create mode 100644 src/Phinx/Db/Plan/NewTable.php create mode 100644 src/Phinx/Db/Plan/Plan.php create mode 100644 src/Phinx/Db/Table/Table.php create mode 100644 src/Phinx/Db/Util/AlterInstructions.php diff --git a/composer.json b/composer.json index b79df277e..786f8b40a 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ }], "require": { "php": ">=5.4", + "cakephp/collection": "^3.5", "symfony/console": "^2.8|^3.0|^4.0", "symfony/config": "^2.8|^3.0|^4.0", "symfony/yaml": "^2.8|^3.0|^4.0" diff --git a/src/Phinx/Db/Action/Action.php b/src/Phinx/Db/Action/Action.php new file mode 100644 index 000000000..96d12fdf9 --- /dev/null +++ b/src/Phinx/Db/Action/Action.php @@ -0,0 +1,7 @@ +table = $able; + $this->column = $column; + } + + public static function build(Table $table, $columnName, $type = null, $options = []) + { + $column = new Column(); + $column->setName($columnName); + $column->setType($type); + $column->setOptions($options); // map options to column methods + + return new static($table, $column); + } + + public function getTable() + { + return $this->table; + } + + public function getColumn() + { + return $this->column; + } +} diff --git a/src/Phinx/Db/Action/AddForeignKey.php b/src/Phinx/Db/Action/AddForeignKey.php new file mode 100644 index 000000000..814e0dc96 --- /dev/null +++ b/src/Phinx/Db/Action/AddForeignKey.php @@ -0,0 +1,46 @@ +table = $table; + $this->foreignKey = $fk; + } + + public static function build(Table $table, $columns, Table $referencedTable, $referencedColumns = ['id'], array $options = []) + { + if (is_string($referencedColumns)) { + $referencedColumns = [$referencedColumns]; // str to array + } + + $fk = new ForeignKey(); + $fk->setReferencedTable($referencedTable) + ->setColumns($columns) + ->setReferencedColumns($referencedColumns) + ->setOptions($options); + + return new static($table, $fk); + } + + public function getTable() + { + return $this->table; + } + + public function getForeignKey() + { + return $this->foreignKey; + } +} diff --git a/src/Phinx/Db/Action/AddIndex.php b/src/Phinx/Db/Action/AddIndex.php new file mode 100644 index 000000000..9faa2e364 --- /dev/null +++ b/src/Phinx/Db/Action/AddIndex.php @@ -0,0 +1,50 @@ +table = $table; + $this->index = $index; + } + + public static function build(Table $table, $columns, array $options = []) + { + // create a new index object if strings or an array of strings were supplied + $index = $columns; + + if (!$columns instanceof Index) { + $index = new Index(); + + if (is_string($columns)) { + $columns = [$columns]; // str to array + } + + $index->setColumns($columns); + $index->setOptions($options); + } + + return new static($table, $index); + } + + public function getTable() + { + return $this->table; + } + + public function getIndex() + { + return $this->index; + } +} diff --git a/src/Phinx/Db/Action/ChangeColumn.php b/src/Phinx/Db/Action/ChangeColumn.php new file mode 100644 index 000000000..33701aa02 --- /dev/null +++ b/src/Phinx/Db/Action/ChangeColumn.php @@ -0,0 +1,53 @@ +table = $table; + $this->columnName = $columnName; + $this->column = $column; + + // if the name was omitted use the existing column name + if ($column->getName() === null || strlen($column->getName()) === 0) { + $column->setName($columnName); + } + } + + public static function build(Table $table, $columnName, $type = null, $options = []) + { + $column = new Column(); + $column->setName($columnName); + $column->setType($type); + $column->setOptions($options); // map options to column methods + + return new static($table, $columnName, $column); + } + + public function getTable() + { + return $this->table; + } + + public function getColumnName() + { + return $this->columnName; + } + + public function getColumn() + { + return $this->column; + } +} diff --git a/src/Phinx/Db/Action/CreateTable.php b/src/Phinx/Db/Action/CreateTable.php new file mode 100644 index 000000000..4d6f2c712 --- /dev/null +++ b/src/Phinx/Db/Action/CreateTable.php @@ -0,0 +1,26 @@ +table = $table; + } + + public function getTable() + { + return $this->table; + } + + public function getTable() + { + return $this->table; + } +} diff --git a/src/Phinx/Db/Action/DropColumn.php b/src/Phinx/Db/Action/DropColumn.php new file mode 100644 index 000000000..8bc5a746e --- /dev/null +++ b/src/Phinx/Db/Action/DropColumn.php @@ -0,0 +1,29 @@ +table = $table; + $this->columnName = $columnName; + } + + public function getTable() + { + return $this->table; + } + + public function getColumnName() + { + return $this->columnName; + } +} diff --git a/src/Phinx/Db/Action/DropForeignKey.php b/src/Phinx/Db/Action/DropForeignKey.php new file mode 100644 index 000000000..6a52a2d3e --- /dev/null +++ b/src/Phinx/Db/Action/DropForeignKey.php @@ -0,0 +1,47 @@ +table = $table; + $this->foreignKey = $foreignKey; + } + + public static function build(Table $table, $columns, $constraint = null) + { + if (is_string($columns)) { + $columns = [$columns]; + } + + $foreignKey = new ForeignKey(); + $foreignKey->setColumns($columns); + + if ($constraint) { + $foreignKey->setConstraint($constraint); + } + + return new static($table, $foreignKey); + } + + public function getTable() + { + return $this->table; + } + + public function getForeignKey() + { + return $this->foreignKey; + } +} diff --git a/src/Phinx/Db/Action/DropIndex.php b/src/Phinx/Db/Action/DropIndex.php new file mode 100644 index 000000000..d9296c7c2 --- /dev/null +++ b/src/Phinx/Db/Action/DropIndex.php @@ -0,0 +1,47 @@ +table = $table; + $this->index = $index; + } + + public static function build(Table $table, array $columns = []) + { + $index = new Index(); + $index->setColumns($columns); + + return new static($table, $index); + } + + public static function buildFromName(Table $table, $name) + { + $index = new Index(); + $index->setName($name); + + return new static($table, $index); + } + + public function getTable() + { + return $this->table; + } + + public function getIndex() + { + return $this->index; + } +} diff --git a/src/Phinx/Db/Action/DropTable.php b/src/Phinx/Db/Action/DropTable.php new file mode 100644 index 000000000..5fb91f8ea --- /dev/null +++ b/src/Phinx/Db/Action/DropTable.php @@ -0,0 +1,21 @@ +table = $table; + } + + public function getTable() + { + return $this->table; + } +} diff --git a/src/Phinx/Db/Action/RemoveColumn.php b/src/Phinx/Db/Action/RemoveColumn.php new file mode 100644 index 000000000..857754aa3 --- /dev/null +++ b/src/Phinx/Db/Action/RemoveColumn.php @@ -0,0 +1,37 @@ +table = $table; + $this->column = $column; + } + + public static function build(Table $table, $columnName) + { + $column = new Column(); + $column->setName($columnName); + return new static($table, $column); + } + + public function getTable() + { + return $this->table; + } + + public function getColumn() + { + return $this->column; + } +} diff --git a/src/Phinx/Db/Action/RenameColumn.php b/src/Phinx/Db/Action/RenameColumn.php new file mode 100644 index 000000000..03f0cf954 --- /dev/null +++ b/src/Phinx/Db/Action/RenameColumn.php @@ -0,0 +1,45 @@ +table = $table; + $this->newName = newName; + $this->column = $column; + } + + public static function build(Table $table, $columnName, $newName) + { + $column = new Column(); + $column->setName($columnName); + return new static($table, $column, $newName); + } + + public function getTable() + { + return $this->table; + } + + public function getColumn() + { + return $this->column; + } + + public function getNewName() + { + return $this->newName; + } +} diff --git a/src/Phinx/Db/Action/RenameTable.php b/src/Phinx/Db/Action/RenameTable.php new file mode 100644 index 000000000..d7df6741b --- /dev/null +++ b/src/Phinx/Db/Action/RenameTable.php @@ -0,0 +1,29 @@ +newName = $newName; + $this->table = $table; + } + + public function getTable() + { + return $this->table; + } + + public function getNewName() + { + return $this->newName; + } +} diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index 7ca228318..41546f9b8 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -28,7 +28,7 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; @@ -257,6 +257,16 @@ public function rollbackTransaction(); */ public function execute($sql); + + /** + * Executes a list of migration actions for the given table + * + * @param Table $table The table to execute the actions for + * @param Phinx\Db\Action\Action[] $table The table to execute the actions for + * @return int + */ + public function executeActions(Table $table, array $actions); + /** * Executes a SQL statement and returns the result as an array. * @@ -284,7 +294,7 @@ public function fetchAll($sql); /** * Inserts data into a table. * - * @param \Phinx\Db\Table $table where to insert data + * @param \Phinx\Db\Table\Table $table Table where to insert data * @param array $row * @return void */ @@ -293,7 +303,7 @@ public function insert(Table $table, $row); /** * Inserts data into a table in a bulk. * - * @param \Phinx\Db\Table $table where to insert data + * @param \Phinx\Db\Table\Table $table Table where to insert data * @param array $rows * @return void */ @@ -326,10 +336,12 @@ public function hasTable($tableName); /** * Creates the specified database table. * - * @param \Phinx\Db\Table $table Table + * @param \Phinx\Db\Table\Table $table Table + * @param \Phinx\Db\Table\Column[] $columns List of columns in the table + * @param \Phinx\Db\Table\Index[] $indexes List of indexes for the table * @return void */ - public function createTable(Table $table); + public function createTable(Table $table, array $columns = [], array $indexes = []); /** * Renames the specified database table. @@ -376,7 +388,7 @@ public function hasColumn($tableName, $columnName); /** * Adds the specified column to a database table. * - * @param \Phinx\Db\Table $table Table + * @param \Phinx\Db\Table\Table $table Table * @param \Phinx\Db\Table\Column $column Column * @return void */ @@ -432,7 +444,7 @@ public function hasIndexByName($tableName, $indexName); /** * Adds the specified index to a database table. * - * @param \Phinx\Db\Table $table Table + * @param \Phinx\Db\Table\Table $table Table * @param \Phinx\Db\Table\Index $index Index * @return void */ diff --git a/src/Phinx/Db/Adapter/AdapterWrapper.php b/src/Phinx/Db/Adapter/AdapterWrapper.php index 2e9a55d6a..0f747cca3 100644 --- a/src/Phinx/Db/Adapter/AdapterWrapper.php +++ b/src/Phinx/Db/Adapter/AdapterWrapper.php @@ -28,7 +28,7 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; @@ -346,9 +346,9 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], $indexes = []) { - $this->getAdapter()->createTable($table); + $this->getAdapter()->createTable($table, $columns, $indexes); } /** diff --git a/src/Phinx/Db/Adapter/MysqlAdapter.php b/src/Phinx/Db/Adapter/MysqlAdapter.php index 8b18ca2ab..92225999e 100644 --- a/src/Phinx/Db/Adapter/MysqlAdapter.php +++ b/src/Phinx/Db/Adapter/MysqlAdapter.php @@ -28,10 +28,11 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; +use Phinx\Db\Util\AlterInstructions; /** * Phinx MySQL Adapter. @@ -201,7 +202,7 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], array $indexes = []) { // This method is based on the MySQL docs here: http://dev.mysql.com/doc/refman/5.1/en/create-index.html $defaultOptions = [ @@ -216,7 +217,6 @@ public function createTable(Table $table) ); // Add the default primary key - $columns = $table->getPendingColumns(); if (!isset($options['id']) || (isset($options['id']) && $options['id'] === true)) { $column = new Column(); $column->setName('id') @@ -279,17 +279,10 @@ public function createTable(Table $table) } // set the indexes - $indexes = $table->getIndexes(); foreach ($indexes as $index) { $sql .= ', ' . $this->getIndexSqlDefinition($index); } - // set the foreign keys - $foreignKeys = $table->getForeignKeys(); - foreach ($foreignKeys as $foreignKey) { - $sql .= ', ' . $this->getForeignKeySqlDefinition($foreignKey); - } - $sql .= ') ' . $optionsStr; $sql = rtrim($sql) . ';'; @@ -300,17 +293,25 @@ public function createTable(Table $table) /** * {@inheritdoc} */ - public function renameTable($tableName, $newTableName) + protected function getRenameTableInstructions($tableName, $newTableName) { - $this->execute(sprintf('RENAME TABLE %s TO %s', $this->quoteTableName($tableName), $this->quoteTableName($newTableName))); + $sql = sprintf( + 'RENAME TABLE %s TO %s', + $this->quoteTableName($tableName), + $this->quoteTableName($newTableName) + ); + + return new AlterInstructions([], [$sql]); } /** * {@inheritdoc} */ - public function dropTable($tableName) + protected function getDropTableInstructions($tableName) { - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tableName))); + $sql = sprintf('DROP TABLE %s', $this->quoteTableName($tableName)); + + return new AlterInstructions([], [$sql]); } /** @@ -393,26 +394,25 @@ protected function getDefaultValueDefinition($default) /** * {@inheritdoc} */ - public function addColumn(Table $table, Column $column) + protected function getAddColumnInstructions(Table $table, Column $column) { - $sql = sprintf( - 'ALTER TABLE %s ADD %s %s', - $this->quoteTableName($table->getName()), + $alter = sprintf( + 'ADD %s %s', $this->quoteColumnName($column->getName()), $this->getColumnSqlDefinition($column) ); if ($column->getAfter()) { - $sql .= ' AFTER ' . $this->quoteColumnName($column->getAfter()); + $alter .= ' AFTER ' . $this->quoteColumnName($column->getAfter()); } - $this->execute($sql); + return new AlterInstructions([$alter]); } /** * {@inheritdoc} */ - public function renameColumn($tableName, $columnName, $newColumnName) + protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName) { $rows = $this->fetchAll(sprintf('DESCRIBE %s', $this->quoteTableName($tableName))); foreach ($rows as $row) { @@ -424,17 +424,14 @@ public function renameColumn($tableName, $columnName, $newColumnName) } $definition = $row['Type'] . ' ' . $null . $extra; - $this->execute( - sprintf( - 'ALTER TABLE %s CHANGE COLUMN %s %s %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName), - $this->quoteColumnName($newColumnName), - $definition - ) + $alter = sprintf( + 'CHANGE COLUMN %s %s %s', + $this->quoteColumnName($columnName), + $this->quoteColumnName($newColumnName), + $definition ); - return; + return new AlterInstructions([$alter]); } } @@ -447,33 +444,28 @@ public function renameColumn($tableName, $columnName, $newColumnName) /** * {@inheritdoc} */ - public function changeColumn($tableName, $columnName, Column $newColumn) + protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn) { $after = $newColumn->getAfter() ? ' AFTER ' . $this->quoteColumnName($newColumn->getAfter()) : ''; - $this->execute( - sprintf( - 'ALTER TABLE %s CHANGE %s %s %s%s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName), - $this->quoteColumnName($newColumn->getName()), - $this->getColumnSqlDefinition($newColumn), - $after - ) + $alter = sprintf( + 'CHANGE %s %s %s%s', + $this->quoteColumnName($columnName), + $this->quoteColumnName($newColumn->getName()), + $this->getColumnSqlDefinition($newColumn), + $after ); + + return new AlterInstructions([$alter]); } /** * {@inheritdoc} */ - public function dropColumn($tableName, $columnName) + protected function getDropColumnInstructions($tableName, $columnName) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP COLUMN %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName) - ) - ); + $alter = sprintf('DROP COLUMN %s', $this->quoteColumnName($columnName)); + + return new AlterInstructions([$alter]); } /** @@ -536,21 +528,20 @@ public function hasIndexByName($tableName, $indexName) /** * {@inheritdoc} */ - public function addIndex(Table $table, Index $index) + protected function getAddIndexInstructions(Table $table, Index $index) { - $this->execute( - sprintf( - 'ALTER TABLE %s ADD %s', - $this->quoteTableName($table->getName()), - $this->getIndexSqlDefinition($index) - ) + $alter = sprintf( + 'ADD %s', + $this->getIndexSqlDefinition($index) ); + + return new AlterInstructions([$alter]); } /** * {@inheritdoc} */ - public function dropIndex($tableName, $columns) + protected function getDropIndexByColumnsInstructions($tableName, $columns) { if (is_string($columns)) { $columns = [$columns]; // str to array @@ -561,40 +552,40 @@ public function dropIndex($tableName, $columns) foreach ($indexes as $indexName => $index) { if ($columns == $index['columns']) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP INDEX %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($indexName) - ) - ); - - return; + return new AlterInstructions([sprintf( + 'DROP INDEX %s', + $this->quoteColumnName($indexName) + )]); } } + + throw new \InvalidArgumentException(sprintf( + "The specified index on columns '%s' does not exist", + implode(',', $columns) + )); } /** * {@inheritdoc} */ - public function dropIndexByName($tableName, $indexName) + protected function getDropIndexByNameInstructions($tableName, $indexName) { + $indexes = $this->getIndexes($tableName); foreach ($indexes as $name => $index) { - //$a = array_diff($columns, $index['columns']); if ($name === $indexName) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP INDEX %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($indexName) - ) - ); - - return; + return new AlterInstructions([sprintf( + 'DROP INDEX %s', + $this->quoteColumnName($indexName) + )]); } } + + throw new \InvalidArgumentException(sprintf( + "The specified index name '%s' does not exist", + $indexName + )); } /** @@ -659,55 +650,67 @@ protected function getForeignKeys($tableName) /** * {@inheritdoc} */ - public function addForeignKey(Table $table, ForeignKey $foreignKey) + protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey) { - $this->execute( - sprintf( - 'ALTER TABLE %s ADD %s', - $this->quoteTableName($table->getName()), - $this->getForeignKeySqlDefinition($foreignKey) - ) + $alter = sprintf( + 'ADD %s', + $this->getForeignKeySqlDefinition($foreignKey) + ); + + return new AlterInstructions([$alter]); + } + + /** + * {@inheritdoc} + */ + protected function getDropForeignKeyInstructions($tableName, $constraint) + { + $alter = sprintf( + 'DROP FOREIGN KEY %s', + $constraint ); + + return new AlterInstructions([$alter]); } /** * {@inheritdoc} */ - public function dropForeignKey($tableName, $columns, $constraint = null) + protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) { if (is_string($columns)) { $columns = [$columns]; // str to array } - if ($constraint) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP FOREIGN KEY %s', - $this->quoteTableName($tableName), - $constraint - ) - ); - - return; - } else { - foreach ($columns as $column) { - $rows = $this->fetchAll(sprintf( - "SELECT - CONSTRAINT_NAME - FROM information_schema.KEY_COLUMN_USAGE - WHERE REFERENCED_TABLE_SCHEMA = DATABASE() - AND REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_NAME = '%s' - AND COLUMN_NAME = '%s' - ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", - $tableName, - $column - )); - foreach ($rows as $row) { - $this->dropForeignKey($tableName, $columns, $row['CONSTRAINT_NAME']); - } + $instructions = new AlterInstructions(); + + foreach ($columns as $column) { + $rows = $this->fetchAll(sprintf( + "SELECT + CONSTRAINT_NAME + FROM information_schema.KEY_COLUMN_USAGE + WHERE REFERENCED_TABLE_SCHEMA = DATABASE() + AND REFERENCED_TABLE_NAME IS NOT NULL + AND TABLE_NAME = '%s' + AND COLUMN_NAME = '%s' + ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", + $tableName, + $column + )); + + foreach ($rows as $row) { + $instructions->merge($this->getDropForeignKeyInstructions($row['CONSTRAINT_NAME'])); } } + + if (empty($instructions->getAlterParts())) { + throw new \InvalidArgumentException(sprintf( + "Not foreign key on columns '%s' exist", + implode(',', $columns) + )); + } + + return $instructions; } /** diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index a9b53bf78..4dabf08fb 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -29,7 +29,23 @@ namespace Phinx\Db\Adapter; use BadMethodCallException; -use Phinx\Db\Table; +use Phinx\Db\Action\AddColumn; +use Phinx\Db\Action\AddForeignKey; +use Phinx\Db\Action\AddIndex; +use Phinx\Db\Action\ChangeColumn; +use Phinx\Db\Action\DropColumn; +use Phinx\Db\Action\DropForeignKey; +use Phinx\Db\Action\DropIndex; +use Phinx\Db\Action\DropTable; +use Phinx\Db\Action\RemoveColumn; +use Phinx\Db\Action\RenameColumn; +use Phinx\Db\Action\RenameTable; +use Phinx\Db\Table\Column; +use Phinx\Db\Table\ForeignKey; +use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; +use Phinx\Db\Table\Table; +use Phinx\Db\Util\AlterInstructions; use Phinx\Migration\MigrationInterface; /** @@ -384,4 +400,243 @@ public function castToBool($value) { return (bool)$value ? 1 : 0; } + + protected function executeAlterSteps($tableName, AlterInstructions $instructions) + { + $alter = sprintf( + 'ALTER TABLE %s %s', + $tableName, + implode(', ', $instructions->getAlterParts()) + ); + + $this->execute($alter); + + foreach ($instructions->getPostSteps() as $sql) { + $this->execute($sql); + } + } + + /** + * {@inheritdoc} + */ + public function addColumn(Table $table, Column $column) + { + $instructions = $this->getAddColumnInstructions($column); + $this->executeAlterSteps($table, $instructions); + } + + abstract protected function getAddColumnInstructions(Table $table, Column $column); + + /** + * {@inheritdoc} + */ + public function renameColumn($tableName, $columnName, $newColumnName) + { + $instructions = $this->getRenameColumnInstructions($tableName, $columnName, $newColumnName); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName); + + /** + * {@inheritdoc} + */ + public function changeColumn($tableName, $columnName, Column $newColumn) + { + $instructions = $this->getChangeColumnInstructions($tableName, $columnName, $newColumn); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn); + + /** + * {@inheritdoc} + */ + public function dropColumn($tableName, $columnName) + { + $instructions = $this->getDropColumnInstructions($columnName); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getDropColumnInstructions($tableName, $columnName); + + /** + * {@inheritdoc} + */ + public function addIndex(Table $table, Index $index) + { + $instructions = $this->getAddIndexInstructions($table, $index); + $this->executeAlterSteps($table->getName(), $instructions); + } + + abstract protected function getAddIndexInstructions(Table $table, Index $index); + + /** + * {@inheritdoc} + */ + public function dropIndex($tableName, $columns) + { + $instructions = $this->getDropIndexByColumnsInstructions($tableName, $columns); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getDropIndexByColumnsInstructions($tableName, $columns); + + /** + * {@inheritdoc} + */ + public function dropIndexByName($tableName, $indexName) + { + $instructions = $this->getDropIndexByNameInstructions($tableName, $indexName); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getDropIndexByNameInstructions($tableName, $indexName); + + /** + * {@inheritdoc} + */ + public function addForeignKey(Table $table, ForeignKey $foreignKey) + { + $instructions = $this->getAddForeignKeyInstructions($table, $foreignKey); + $this->executeAlterSteps($table->getName(), $instructions); + } + + abstract protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey); + + /** + * {@inheritdoc} + */ + public function dropForeignKey($tableName, $columns, $constraint = null) + { + if ($constraint) { + $instructions = $this->getDropForeignKeyInstructions($tableName, $constraint); + } else { + $instructions = $this->getDropForeignKeyByColumnsInstructions($tableName, $columns); + } + + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getDropForeignKeyInstructions($tableName, $constraint); + + abstract protected function getDropForeignKeyByColumnsInstructions($tableName, $columns); + + + /** + * {@inheritdoc} + */ + public function dropTable($tableName) + { + $instructions = $this->getDropTableInstructions($tableName); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getDropTableInstructions($tableName); + + /** + * {@inheritdoc} + */ + public function renameTable($tableName, $newTableName) + { + $instructions = $this->getRenameTableInstructions($tableName, $newTableName); + $this->executeAlterSteps($tableName, $instructions); + } + + abstract protected function getRenameTableInstructions($tableName, $newTableName); + + public function executeActions(Table $table, array $actions) + { + $instructions = AlterInstructions(); + + foreach ($actions as $action) { + switch (true) { + case ($action instanceof AddColumn): + $instructions->merge($this->getAddColumnInstructions($table, $action->getColumn())); + break; + + case ($action instanceof AddIndex): + $instructions->merge($this->getAddIndexInstructions($table, $action->getIndex())); + break; + + case ($action instanceof AddForeignKey): + $instructions->merge($this->getAddForeignKeyInstructions($table, $action->getColumn())); + break; + + case ($action instanceof ChangeColumn): + $instructions->merge($this->getChangeColumnInstructions( + $table->getName(), + $action->getColumnName(), + $action->getColumn() + )); + break; + + case ($action instanceof DropForeignKey && !$action->getForeignKey()->getConstraint()): + $instructions->merge($this->getDropForeignKeyByColumnsInstructions( + $table->getName(), + $action->getForeignKey()->getColumns() + )); + break; + + case ($action instanceof DropForeignKey && $action->getForeignKey()->getConstraint()): + $instructions->merge($this->getDropForeignKeyInstructions( + $table->getName(), + $action->getForeignKey()->getConstraint() + )); + break; + + case ($action instanceof DropColumn): + $instructions->merge($this->getDropColumnInstructions( + $table->getName(), + $action->getColumnName() + )); + break; + + case ($action instanceof DropIndex && $action->getIndex()->getName() !== null): + $instructions->merge($this->getDropIndexByNameInstructions( + $table->getName(), + $action->getIndex()->getName() + )); + break; + + case ($action instanceof DropIndex && $action->getIndex()->getName() == null): + $instructions->merge($this->getDropIndexByColumnsInstructions( + $table->getName(), + $action->getIndex()->getPendingColumns() + )); + break; + + + case ($action instanceof DropTable): + $instructions->merge($this->getDropTableInstructions( + $table->getName(), + $action->getColumn()->getName(), + $action->getNewName() + )); + break; + + case ($action instanceof RenameColumn): + $instructions->merge($this->getRenameColumnInstructions( + $table->getName(), + $action->getColumn()->getName(), + $action->getNewName() + )); + break; + + case ($action instanceof RenameTable): + $instructions->merge($this->getRenameTableInstructions( + $table->getName(), + $action->getNewName() + )); + break; + + default: + throw new \InvalidArgumentException( + sprintf("Don't know how to execute action: '%s'", get_class($action)) + ); + } + } + + $this->executeAlterSteps($table->getName(), $instructions); + } } diff --git a/src/Phinx/Db/Adapter/PostgresAdapter.php b/src/Phinx/Db/Adapter/PostgresAdapter.php index 67e0a0556..b4132b5f1 100644 --- a/src/Phinx/Db/Adapter/PostgresAdapter.php +++ b/src/Phinx/Db/Adapter/PostgresAdapter.php @@ -28,10 +28,11 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; +use Phinx\Db\Util\AlterInstructions; class PostgresAdapter extends PdoAdapter implements AdapterInterface { @@ -168,12 +169,11 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns, array $indexes) { $options = $table->getOptions(); // Add the default primary key - $columns = $table->getPendingColumns(); if (!isset($options['id']) || (isset($options['id']) && $options['id'] === true)) { $column = new Column(); $column->setName('id') @@ -221,14 +221,6 @@ public function createTable(Table $table) $sql = substr(rtrim($sql), 0, -1); // no primary keys } - // set the foreign keys - $foreignKeys = $table->getForeignKeys(); - if (!empty($foreignKeys)) { - foreach ($foreignKeys as $foreignKey) { - $sql .= ', ' . $this->getForeignKeySqlDefinition($foreignKey, $table->getName()); - } - } - $sql .= ');'; // process column comments @@ -239,7 +231,6 @@ public function createTable(Table $table) } // set the indexes - $indexes = $table->getIndexes(); if (!empty($indexes)) { foreach ($indexes as $index) { $sql .= $this->getIndexSqlDefinition($index, $table->getName()); @@ -263,22 +254,25 @@ public function createTable(Table $table) /** * {@inheritdoc} */ - public function renameTable($tableName, $newTableName) + protected function getRenameTableInstructions($tableName, $newTableName) { $sql = sprintf( 'ALTER TABLE %s RENAME TO %s', $this->quoteTableName($tableName), - $this->quoteColumnName($newTableName) + $this->quoteTableName($newTableName) ); - $this->execute($sql); + + return new AlterInstructions([], [$sql]); } /** * {@inheritdoc} */ - public function dropTable($tableName) + protected function getDropTableInstructions($tableName) { - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tableName))); + $sql = sprintf('DROP TABLE %s', $this->quoteTableName($tableName)); + + return new AlterInstructions([], [$sql]); } /** @@ -354,26 +348,26 @@ public function hasColumn($tableName, $columnName) /** * {@inheritdoc} */ - public function addColumn(Table $table, Column $column) + protected function getAddColumnInstructions(Table $table, Column $column) { - $sql = sprintf( - 'ALTER TABLE %s ADD %s %s;', - $this->quoteTableName($table->getName()), + $instructions = new AlterInstructions(); + $instructions->addAlter(sprintf( + 'ADD %s %s;', $this->quoteColumnName($column->getName()), $this->getColumnSqlDefinition($column) - ); + )); if ($column->getComment()) { - $sql .= $this->getColumnCommentSqlDefinition($column, $table->getName()); + $instructions->addPostStep($this->getColumnCommentSqlDefinition($column, $table->getName())); } - $this->execute($sql); + return $instructions; } /** * {@inheritdoc} */ - public function renameColumn($tableName, $columnName, $newColumnName) + protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName) { $sql = sprintf( "SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS column_exists @@ -382,102 +376,102 @@ public function renameColumn($tableName, $columnName, $newColumnName) $tableName, $columnName ); + $result = $this->fetchRow($sql); if (!(bool)$result['column_exists']) { throw new \InvalidArgumentException("The specified column does not exist: $columnName"); } - $this->execute( + + $instructions = new AlterInstructions(); + $instructions->addPostStep( sprintf( 'ALTER TABLE %s RENAME COLUMN %s TO %s', - $this->quoteTableName($tableName), + $tableName, $this->quoteColumnName($columnName), $this->quoteColumnName($newColumnName) ) ); + + return $instructions; } /** * {@inheritdoc} */ - public function changeColumn($tableName, $columnName, Column $newColumn) + protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn) { - // TODO - is it possible to merge these 3 queries into less? - // change data type + $instructions = new AlterInstructions(); + $sql = sprintf( - 'ALTER TABLE %s ALTER COLUMN %s TYPE %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName), + 'ALTER COLUMN %s TYPE %s', $this->getColumnSqlDefinition($newColumn) ); + // //NULL and DEFAULT cannot be set while changing column type $sql = preg_replace('/ NOT NULL/', '', $sql); $sql = preg_replace('/ NULL/', '', $sql); //If it is set, DEFAULT is the last definition $sql = preg_replace('/DEFAULT .*/', '', $sql); - $this->execute($sql); + + $instructions->addAlter($sql); + // process null $sql = sprintf( - 'ALTER TABLE %s ALTER COLUMN %s', - $this->quoteTableName($tableName), + 'ALTER COLUMN %s', $this->quoteColumnName($columnName) ); + if ($newColumn->isNull()) { $sql .= ' DROP NOT NULL'; } else { $sql .= ' SET NOT NULL'; } - $this->execute($sql); + + $instructions->addAlter($sql); + if (!is_null($newColumn->getDefault())) { - //change default - $this->execute( - sprintf( - 'ALTER TABLE %s ALTER COLUMN %s SET %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName), - $this->getDefaultValueDefinition($newColumn->getDefault()) - ) - ); + $instructions->addAlter(sprintf( + 'ALTER COLUMN %s SET %s', + $this->quoteColumnName($columnName), + $this->getDefaultValueDefinition($newColumn->getDefault()) + )); } else { //drop default - $this->execute( - sprintf( - 'ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName) - ) - ); + $instructions->addAlter(sprintf( + 'ALTER COLUMN %s DROP DEFAULT', + $this->quoteColumnName($columnName) + )); } + // rename column if ($columnName !== $newColumn->getName()) { - $this->execute( - sprintf( - 'ALTER TABLE %s RENAME COLUMN %s TO %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName), - $this->quoteColumnName($newColumn->getName()) - ) - ); + $instructions->addPostStep(sprintf( + 'ALTER TABLE %s RENAME COLUMN %s TO %s', + $this->quoteTableName($tableName), + $this->quoteColumnName($columnName), + $this->quoteColumnName($newColumn->getName()) + )); } // change column comment if needed if ($newColumn->getComment()) { - $sql = $this->getColumnCommentSqlDefinition($newColumn, $tableName); - $this->execute($sql); + $instructions->addPostStep($this->getColumnCommentSqlDefinition($newColumn, $tableName)); } + + return $instructions; } /** * {@inheritdoc} */ - public function dropColumn($tableName, $columnName) + protected function getDropColumnInstructions($columnName) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP COLUMN %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName) - ) + $alter = sprintf( + 'DROP COLUMN %s', + $this->quoteColumnName($columnName) ); + + return new AlterInstructions([$alter]); } /** @@ -555,16 +549,17 @@ public function hasIndexByName($tableName, $indexName) /** * {@inheritdoc} */ - public function addIndex(Table $table, Index $index) + protected function getAddIndexInstructions(Table $table, Index $index) { - $sql = $this->getIndexSqlDefinition($index, $table->getName()); - $this->execute($sql); + $instructions = new AlterInstructions(); + $instructions->addPostStep($this->getIndexSqlDefinition($index, $table->getName())); + return $instructions; } /** * {@inheritdoc} */ - public function dropIndex($tableName, $columns) + protected function getDropIndexByColumnsInstructions($tableName, $columns) { if (is_string($columns)) { $columns = [$columns]; // str to array @@ -576,28 +571,30 @@ public function dropIndex($tableName, $columns) foreach ($indexes as $indexName => $index) { $a = array_diff($columns, $index['columns']); if (empty($a)) { - $this->execute( - sprintf( - 'DROP INDEX IF EXISTS %s', - $this->quoteColumnName($indexName) - ) - ); - - return; + return AlterInstructions([], [sprintf( + 'DROP INDEX IF EXISTS %s', + $this->quoteColumnName($indexName) + )]); } } + + throw new \InvalidArgumentException(sprintf( + "The specified index on columns '%s' does not exist", + implode(',', $columns) + )); } /** * {@inheritdoc} */ - public function dropIndexByName($tableName, $indexName) + protected function getDropIndexByNameInstructions($tableName, $indexName) { $sql = sprintf( 'DROP INDEX IF EXISTS %s', - $indexName + $this->quoteColumnName($indexName) ); - $this->execute($sql); + + return new AlterInstructions([], [$sql]); } /** @@ -663,52 +660,56 @@ protected function getForeignKeys($tableName) /** * {@inheritdoc} */ - public function addForeignKey(Table $table, ForeignKey $foreignKey) + protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey) { - $sql = sprintf( - 'ALTER TABLE %s ADD %s', - $this->quoteTableName($table->getName()), + $alter = sprintf( + 'ADD %s', $this->getForeignKeySqlDefinition($foreignKey, $table->getName()) ); - $this->execute($sql); + + return new AlterInstructions([$alter]); } /** * {@inheritdoc} */ - public function dropForeignKey($tableName, $columns, $constraint = null) + protected function getDropForeignKeyInstructions($tableName, $constraint) { - if (is_string($columns)) { - $columns = [$columns]; // str to array - } + $alter = sprintf( + 'DROP CONSTRAINT %s', + $constraint + ); - if ($constraint) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP CONSTRAINT %s', - $this->quoteTableName($tableName), - $constraint - ) - ); - } else { - foreach ($columns as $column) { - $rows = $this->fetchAll(sprintf( - "SELECT CONSTRAINT_NAME - FROM information_schema.KEY_COLUMN_USAGE - WHERE TABLE_SCHEMA = CURRENT_SCHEMA() - AND TABLE_NAME IS NOT NULL - AND TABLE_NAME = '%s' - AND COLUMN_NAME = '%s' - ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", - $tableName, - $column - )); + return new AlterInstructions([$alter]); + } - foreach ($rows as $row) { - $this->dropForeignKey($tableName, $columns, $row['constraint_name']); - } + /** + * {@inheritdoc} + */ + protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) + { + $instructions = new AlterInstructions(); + + foreach ($columns as $column) { + $rows = $this->fetchAll(sprintf( + "SELECT CONSTRAINT_NAME + FROM information_schema.KEY_COLUMN_USAGE + WHERE TABLE_SCHEMA = CURRENT_SCHEMA() + AND TABLE_NAME IS NOT NULL + AND TABLE_NAME = '%s' + AND COLUMN_NAME = '%s' + ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", + $tableName, + $column + )); + + foreach ($rows as $row) { + $newInstr = $this->getDropForeignKeyInstructions($row['constraint_name']); + $instructions->merge($newInstr); } } + + return $instructions; } /** diff --git a/src/Phinx/Db/Adapter/ProxyAdapter.php b/src/Phinx/Db/Adapter/ProxyAdapter.php index 62e83e66e..bdbe55ec5 100644 --- a/src/Phinx/Db/Adapter/ProxyAdapter.php +++ b/src/Phinx/Db/Adapter/ProxyAdapter.php @@ -28,7 +28,7 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; @@ -59,9 +59,9 @@ public function getAdapterType() /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], array $indexes = []) { - $this->recordCommand('createTable', [$table->getName()]); + $this->recordCommand('createTable', [$table, $columns, $indexes]); } /** diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index 6894f8267..2d5ee331f 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -28,10 +28,11 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Util\AlterInstructions; /** * Phinx SQLite Adapter. @@ -161,10 +162,9 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], array $indexes = []) { // Add the default primary key - $columns = $table->getPendingColumns(); $options = $table->getOptions(); if (!isset($options['id']) || (isset($options['id']) && $options['id'] === true)) { $column = new Column(); @@ -203,19 +203,11 @@ public function createTable(Table $table) $sql = substr(rtrim($sql), 0, -1); // no primary keys } - // set the foreign keys - $foreignKeys = $table->getForeignKeys(); - if (!empty($foreignKeys)) { - foreach ($foreignKeys as $foreignKey) { - $sql .= ', ' . $this->getForeignKeySqlDefinition($foreignKey); - } - } - $sql = rtrim($sql) . ');'; // execute the sql $this->execute($sql); - foreach ($table->getIndexes() as $index) { + foreach ($indexes as $index) { $this->addIndex($table, $index); } } @@ -223,17 +215,25 @@ public function createTable(Table $table) /** * {@inheritdoc} */ - public function renameTable($tableName, $newTableName) + protected function getRenameTableInstructions($tableName, $newTableName) { - $this->execute(sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($tableName), $this->quoteTableName($newTableName))); + $sql = sprintf( + 'ALTER TABLE %s RENAME TO %s', + $this->quoteTableName($tableName), + $this->quoteTableName($newTableName) + ); + + return new AlterInstructions([], [$sql]); } /** * {@inheritdoc} */ - public function dropTable($tableName) + protected function getDropTableInstructions($tableName) { - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tableName))); + $sql = sprintf('DROP TABLE %s', $this->quoteTableName($tableName)); + + return new AlterInstructions([], [$sql]); } /** @@ -296,24 +296,25 @@ public function hasColumn($tableName, $columnName) /** * {@inheritdoc} */ - public function addColumn(Table $table, Column $column) + protected function getAddColumnInstructions(Table $table, Column $column) { - $sql = sprintf( - 'ALTER TABLE %s ADD COLUMN %s %s', - $this->quoteTableName($table->getName()), + $alter = sprintf( + 'ADD COLUMN %s %s', $this->quoteColumnName($column->getName()), $this->getColumnSqlDefinition($column) ); - $this->execute($sql); + return new AlterInstructions([$alter]); } /** * {@inheritdoc} */ - public function renameColumn($tableName, $columnName, $newColumnName) + protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName) { $tmpTableName = 'tmp_' . $tableName; + $instructions = new AlterInstructions(); + $instructions->addPostStep(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); @@ -340,35 +341,34 @@ public function renameColumn($tableName, $columnName, $newColumnName) )); } - $this->execute(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); - - $sql = str_replace( + $instructions->addPostStep(str_replace( $this->quoteColumnName($columnName), $this->quoteColumnName($newColumnName), $sql - ); - $this->execute($sql); + )); - $sql = sprintf( + $instructions->addPostStep(sprintf( 'INSERT INTO %s(%s) SELECT %s FROM %s', $tableName, implode(', ', $writeColumns), implode(', ', $selectColumns), $tmpTableName - ); + )); - $this->execute($sql); + $instructions->addPostStep(printf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + return $instructions; } /** * {@inheritdoc} */ - public function changeColumn($tableName, $columnName, Column $newColumn) + protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn) { // TODO: DRY this up.... $tmpTableName = 'tmp_' . $tableName; + $instructions = new AlterInstructions(); + $instructions->addPostStep(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); @@ -395,36 +395,35 @@ public function changeColumn($tableName, $columnName, Column $newColumn) )); } - $this->execute(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); - - $sql = preg_replace( + $instructions->addPostStep(preg_replace( sprintf("/%s(?:\/\*.*?\*\/|\([^)]+\)|'[^']*?'|[^,])+([,)])/", $this->quoteColumnName($columnName)), sprintf('%s %s$1', $this->quoteColumnName($newColumn->getName()), $this->getColumnSqlDefinition($newColumn)), $sql, 1 - ); - - $this->execute($sql); + )); - $sql = sprintf( + $instructions->addPostStep(sprintf( 'INSERT INTO %s(%s) SELECT %s FROM %s', $tableName, implode(', ', $writeColumns), implode(', ', $selectColumns), $tmpTableName - ); + )); - $this->execute($sql); - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + $instructions->addPostStep(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + + return $instructions; } /** * {@inheritdoc} */ - public function dropColumn($tableName, $columnName) + protected function getDropColumnParts($tableName, $columnName) { // TODO: DRY this up.... $tmpTableName = 'tmp_' . $tableName; + $alter = [sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)]; + $postSql = []; $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); @@ -453,8 +452,6 @@ public function dropColumn($tableName, $columnName) )); } - $this->execute(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); - $sql = preg_replace( sprintf("/%s\s%s.*(,\s(?!')|\)$)/U", preg_quote($this->quoteColumnName($columnName)), preg_quote($columnType)), "", @@ -465,9 +462,9 @@ public function dropColumn($tableName, $columnName) $sql = substr($sql, 0, -2) . ')'; } - $this->execute($sql); + $postSql[] = $sql; - $sql = sprintf( + $postSql[] = sprintf( 'INSERT INTO %s(%s) SELECT %s FROM %s', $tableName, implode(', ', $columns), @@ -475,8 +472,9 @@ public function dropColumn($tableName, $columnName) $tmpTableName ); - $this->execute($sql); - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + $postSql[] = sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName)); + + return [$alter, $postSql]; } /** @@ -544,27 +542,25 @@ public function hasIndexByName($tableName, $indexName) /** * {@inheritdoc} */ - public function addIndex(Table $table, Index $index) + protected function getAddIndexPart(Table $table, Index $index) { $indexColumnArray = []; foreach ($index->getColumns() as $column) { $indexColumnArray[] = sprintf('`%s` ASC', $column); } $indexColumns = implode(',', $indexColumnArray); - $this->execute( - sprintf( - 'CREATE %s ON %s (%s)', - $this->getIndexSqlDefinition($table, $index), - $this->quoteTableName($table->getName()), - $indexColumns - ) + return sprintf( + 'CREATE %s ON %s (%s)', + $this->getIndexSqlDefinition($table, $index), + $this->quoteTableName($table->getName()), + $indexColumns ); } /** * {@inheritdoc} */ - public function dropIndex($tableName, $columns) + protected function getDropIndexByColumnsPart($tableName, $columns) { if (is_string($columns)) { $columns = [$columns]; // str to array @@ -576,14 +572,10 @@ public function dropIndex($tableName, $columns) foreach ($indexes as $index) { $a = array_diff($columns, $index['columns']); if (empty($a)) { - $this->execute( - sprintf( - 'DROP INDEX %s', - $this->quoteColumnName($index['index']) - ) + return sprintf( + 'DROP INDEX %s', + $this->quoteColumnName($index['index']) ); - - return; } } } @@ -591,20 +583,16 @@ public function dropIndex($tableName, $columns) /** * {@inheritdoc} */ - public function dropIndexByName($tableName, $indexName) + protected function getDropIndexByNamePart($tableName, $indexName) { $indexes = $this->getIndexes($tableName); foreach ($indexes as $index) { if ($indexName === $index['index']) { - $this->execute( - sprintf( - 'DROP INDEX %s', - $this->quoteColumnName($indexName) - ) + return sprintf( + 'DROP INDEX %s', + $this->quoteColumnName($indexName) ); - - return; } } } @@ -619,12 +607,7 @@ public function hasForeignKey($tableName, $columns, $constraint = null) } $foreignKeys = $this->getForeignKeys($tableName); - $a = array_diff($columns, $foreignKeys); - if (empty($a)) { - return true; - } - - return false; + return !array_diff($columns, $foreignKeys); } /** @@ -668,12 +651,15 @@ protected function getForeignKeys($tableName) /** * {@inheritdoc} */ - public function addForeignKey(Table $table, ForeignKey $foreignKey) + protected function getAddForeignKeyParts(Table $table, ForeignKey $foreignKey) { // TODO: DRY this up.... $this->execute('pragma foreign_keys = ON'); $tmpTableName = 'tmp_' . $table->getName(); + $alter = [sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($table->getName()), $tmpTableName)]; + $postSql = []; + $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); $sql = ''; @@ -689,12 +675,9 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) $columns[] = $this->quoteColumnName($column['name']); } - $this->execute(sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($table->getName()), $tmpTableName)); + $postSql[] = substr($sql, 0, -1) . ',' . $this->getForeignKeySqlDefinition($foreignKey) . ')'; - $sql = substr($sql, 0, -1) . ',' . $this->getForeignKeySqlDefinition($foreignKey) . ')'; - $this->execute($sql); - - $sql = sprintf( + $postSql[] = sprintf( 'INSERT INTO %s(%s) SELECT %s FROM %s', $this->quoteTableName($table->getName()), implode(', ', $columns), @@ -702,20 +685,32 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) $this->quoteTableName($tmpTableName) ); - $this->execute($sql); - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + $postSql[] = sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName)); + + return [$alter, $postSql]; + } + + /** + * {@inheritdoc} + */ + protected function getDropForeignKeyParts($tableName, $constraint) + { + throw new \BadMethodCallException('SQLite does not have named foreign keys'); } /** * {@inheritdoc} */ - public function dropForeignKey($tableName, $columns, $constraint = null) + protected function getDropForeignKeyByColumnsParts($tableName, $columns) { // TODO: DRY this up.... if (is_string($columns)) { $columns = [$columns]; // str to array } + $alter = [sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($tableName), $tmpTableName)]; + $postSql = []; + $tmpTableName = 'tmp_' . $tableName; $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); @@ -743,8 +738,6 @@ public function dropForeignKey($tableName, $columns, $constraint = null) )); } - $this->execute(sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($tableName), $tmpTableName)); - foreach ($columns as $columnName) { $search = sprintf( "/,[^,]*\(%s(?:,`?(.*)`?)?\) REFERENCES[^,]*\([^\)]*\)[^,)]*/", @@ -753,9 +746,9 @@ public function dropForeignKey($tableName, $columns, $constraint = null) $sql = preg_replace($search, '', $sql, 1); } - $this->execute($sql); + $postSql[] = $sql; - $sql = sprintf( + $postSql[] = sprintf( 'INSERT INTO %s(%s) SELECT %s FROM %s', $tableName, implode(', ', $columns), @@ -763,8 +756,9 @@ public function dropForeignKey($tableName, $columns, $constraint = null) $tmpTableName ); - $this->execute($sql); - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + $postSql[] = sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName)); + + return [$alter, $postSql]; } /** diff --git a/src/Phinx/Db/Adapter/SqlServerAdapter.php b/src/Phinx/Db/Adapter/SqlServerAdapter.php index e7bf027d5..575949cfd 100644 --- a/src/Phinx/Db/Adapter/SqlServerAdapter.php +++ b/src/Phinx/Db/Adapter/SqlServerAdapter.php @@ -28,10 +28,11 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Util\AlterInstructions; /** * Phinx SqlServer Adapter. @@ -203,12 +204,11 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], array $indexes = []) { $options = $table->getOptions(); // Add the default primary key - $columns = $table->getPendingColumns(); if (!isset($options['id']) || (isset($options['id']) && $options['id'] === true)) { $column = new Column(); $column->setName('id') @@ -253,12 +253,6 @@ public function createTable(Table $table) $sqlBuffer[] = $pkSql; } - // set the foreign keys - $foreignKeys = $table->getForeignKeys(); - foreach ($foreignKeys as $foreignKey) { - $sqlBuffer[] = $this->getForeignKeySqlDefinition($foreignKey, $table->getName()); - } - $sql .= implode(', ', $sqlBuffer); $sql .= ');'; @@ -268,7 +262,6 @@ public function createTable(Table $table) } // set the indexes - $indexes = $table->getIndexes(); foreach ($indexes as $index) { $sql .= $this->getIndexSqlDefinition($index, $table->getName()); } @@ -306,17 +299,25 @@ protected function getColumnCommentSqlDefinition(Column $column, $tableName) /** * {@inheritdoc} */ - public function renameTable($tableName, $newTableName) + protected function getRenameTableInstructions($tableName, $newTableName) { - $this->execute(sprintf('EXEC sp_rename \'%s\', \'%s\'', $tableName, $newTableName)); + $sql = sprintf( + 'EXEC sp_rename \'%s\', \'%s\'', + $tableName, + $newTableName + ); + + return new AlterInstructions([], [$sql]); } /** * {@inheritdoc} */ - public function dropTable($tableName) + protected function getDropTableInstructions($tableName) { - $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($tableName))); + $sql = sprintf('DROP TABLE %s', $this->quoteTableName($tableName)); + + return new AlterInstructions([], [$sql]); } /** @@ -425,39 +426,29 @@ public function hasColumn($tableName, $columnName) /** * {@inheritdoc} */ - public function addColumn(Table $table, Column $column) + protected function getAddColumnInstructions(Table $table, Column $column) { - $sql = sprintf( + $alter = sprintf( 'ALTER TABLE %s ADD %s %s', - $this->quoteTableName($table->getName()), + $table->getName(), $this->quoteColumnName($column->getName()), $this->getColumnSqlDefinition($column) ); - $this->execute($sql); + return new AlterInstructions([], [$alter]); } /** * {@inheritdoc} */ - public function renameColumn($tableName, $columnName, $newColumnName) + protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName) { if (!$this->hasColumn($tableName, $columnName)) { throw new \InvalidArgumentException("The specified column does not exist: $columnName"); } - $this->renameDefault($tableName, $columnName, $newColumnName); - $this->execute( - sprintf( - "EXECUTE sp_rename N'%s.%s', N'%s', 'COLUMN' ", - $tableName, - $columnName, - $newColumnName - ) - ); - } - protected function renameDefault($tableName, $columnName, $newColumnName) - { + $instructions = new AlterInstructions(); + $oldConstraintName = "DF_{$tableName}_{$columnName}"; $newConstraintName = "DF_{$tableName}_{$newColumnName}"; $sql = <<execute(sprintf( + $instructions->addPostStep(sprintf( $sql, $oldConstraintName, $newConstraintName )); + + $instructions->addPostStep(sprintf( + "EXECUTE sp_rename N'%s.%s', N'%s', 'COLUMN' ", + $tableName, + $columnName, + $newColumnName + )); + + return $instructions; } - public function changeDefault($tableName, Column $newColumn) + protected function getChangeDefault($tableName, Column $newColumn) { $constraintName = "DF_{$tableName}_{$newColumn->getName()}"; $default = $newColumn->getDefault(); + $instructions = new AlterInstructions(); if ($default === null) { $default = 'DEFAULT NULL'; @@ -485,77 +486,85 @@ public function changeDefault($tableName, Column $newColumn) } if (empty($default)) { - return; + return $instructions; } - $this->execute(sprintf( + $instructions->addPostStep(sprintf( 'ALTER TABLE %s ADD CONSTRAINT %s %s FOR %s', $this->quoteTableName($tableName), $constraintName, $default, $this->quoteColumnName($newColumn->getName()) )); + + return $instructions; } /** * {@inheritdoc} */ - public function changeColumn($tableName, $columnName, Column $newColumn) + protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn) { $columns = $this->getColumns($tableName); - $changeDefault = $newColumn->getDefault() !== $columns[$columnName]->getDefault() || $newColumn->getType() !== $columns[$columnName]->getType(); + $changeDefault = + $newColumn->getDefault() !== $columns[$columnName]->getDefault() || + $newColumn->getType() !== $columns[$columnName]->getType(); + + $instructions = new AlterInstructions(); + if ($columnName !== $newColumn->getName()) { - $this->renameColumn($tableName, $columnName, $newColumn->getName()); + $instructions->merge( + $this->getRenameColumnInstructions($tableName, $columnName, $newColumn->getName()) + ); } if ($changeDefault) { - $this->dropDefaultConstraint($tableName, $newColumn->getName()); + $instructions->merge($this->getDropDefaultConstraint($tableName, $newColumn->getName())); } - $this->execute( - sprintf( - 'ALTER TABLE %s ALTER COLUMN %s %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($newColumn->getName()), - $this->getColumnSqlDefinition($newColumn, false) - ) - ); + $instructions->addPostStep(sprintf( + 'ALTER TABLE %s ALTER COLUMN %s %s', + $this->quoteTableName($tableName), + $this->quoteColumnName($newColumn->getName()), + $this->getColumnSqlDefinition($newColumn, false) + )); // change column comment if needed if ($newColumn->getComment()) { - $sql = $this->getColumnCommentSqlDefinition($newColumn, $tableName); - $this->execute($sql); + $instructions->merge($this->getColumnCommentSqlDefinition($newColumn, $tableName)); } if ($changeDefault) { - $this->changeDefault($tableName, $newColumn); + $instructions->merge($this->getChangeDefault($tableName, $newColumn)); } + + return $instructions; } /** * {@inheritdoc} */ - public function dropColumn($tableName, $columnName) + protected function getDropColumnInstructions($tableName, $columnName) { - $this->dropDefaultConstraint($tableName, $columnName); + $instructions = $this->getDropDefaultConstraint($tableName, $columnName); - $this->execute( - sprintf( - 'ALTER TABLE %s DROP COLUMN %s', - $this->quoteTableName($tableName), - $this->quoteColumnName($columnName) - ) - ); + $instructions->addPostStep(sprintf( + 'ALTER TABLE %s DROP COLUMN %s', + $this->quoteTableName($tableName), + $this->quoteColumnName($columnName) + )); + + return $instructions; } - protected function dropDefaultConstraint($tableName, $columnName) + protected function getDropDefaultConstraint($tableName, $columnName) { $defaultConstraint = $this->getDefaultConstraint($tableName, $columnName); if (!$defaultConstraint) { - return; + return new AlterInstructions(); } - $this->dropForeignKey($tableName, $columnName, $defaultConstraint); + return $this->getDropForeignKeyInstructions($tableName, $columnName, $defaultConstraint); } protected function getDefaultConstraint($tableName, $columnName) @@ -670,16 +679,17 @@ public function hasIndexByName($tableName, $indexName) /** * {@inheritdoc} */ - public function addIndex(Table $table, Index $index) + protected function getAddIndexInstructions(Table $table, Index $index) { $sql = $this->getIndexSqlDefinition($index, $table->getName()); - $this->execute($sql); + + return new AlterInstructions([], [$sql]); } /** * {@inheritdoc} */ - public function dropIndex($tableName, $columns) + protected function getDropIndexByColumnsInstructions($tableName, $columns) { if (is_string($columns)) { $columns = [$columns]; // str to array @@ -687,43 +697,51 @@ public function dropIndex($tableName, $columns) $indexes = $this->getIndexes($tableName); $columns = array_map('strtolower', $columns); + $instructions = new AlterInstructions(); foreach ($indexes as $indexName => $index) { $a = array_diff($columns, $index['columns']); if (empty($a)) { - $this->execute( - sprintf( - 'DROP INDEX %s ON %s', - $this->quoteColumnName($indexName), - $this->quoteTableName($tableName) - ) - ); + $instructions->addPostStep(sprintf( + 'DROP INDEX %s ON %s', + $this->quoteColumnName($indexName), + $this->quoteTableName($tableName) + )); - return; + return $instructions; } } + + throw new \InvalidArgumentException(sprintf( + "The specified index on columns '%s' does not exist", + implode(',', $columns) + )); } /** * {@inheritdoc} */ - public function dropIndexByName($tableName, $indexName) + protected function getDropIndexByNameInstructions($tableName, $indexName) { $indexes = $this->getIndexes($tableName); + $instructions = new AlterInstructions(); foreach ($indexes as $name => $index) { if ($name === $indexName) { - $this->execute( - sprintf( - 'DROP INDEX %s ON %s', - $this->quoteColumnName($indexName), - $this->quoteTableName($tableName) - ) - ); + $instructions->addPostStep(sprintf( + 'DROP INDEX %s ON %s', + $this->quoteColumnName($indexName), + $this->quoteTableName($tableName) + )); - return; + return $instructions; } } + + throw new \InvalidArgumentException(sprintf( + "The specified index name '%s' does not exist", + $indexName + )); } /** @@ -789,58 +807,64 @@ protected function getForeignKeys($tableName) /** * {@inheritdoc} */ - public function addForeignKey(Table $table, ForeignKey $foreignKey) + protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey) { - $this->execute( - sprintf( - 'ALTER TABLE %s ADD %s', - $this->quoteTableName($table->getName()), - $this->getForeignKeySqlDefinition($foreignKey, $table->getName()) - ) - ); + $instructions = new AlterInstructions(); + $instructions->addPostStep(sprintf( + 'ALTER TABLE %s ADD %s', + $this->quoteTableName($table->getName()), + $this->getForeignKeySqlDefinition($foreignKey, $table->getName()) + )); + + return $instructions; } /** * {@inheritdoc} */ - public function dropForeignKey($tableName, $columns, $constraint = null) + protected function getDropForeignKeyInstructions($tableName, $constraint) { - if (is_string($columns)) { - $columns = [$columns]; // str to array - } + $instructions = new AlterInstructions(); + $instructions->addPostStep(sprintf( + 'ALTER TABLE %s DROP CONSTRAINT %s', + $this->quoteTableName($tableName), + $constraint + )); - if ($constraint) { - $this->execute( - sprintf( - 'ALTER TABLE %s DROP CONSTRAINT %s', - $this->quoteTableName($tableName), - $constraint - ) - ); + return $instructions; + } - return; - } else { - foreach ($columns as $column) { - $rows = $this->fetchAll(sprintf( - "SELECT - tc.constraint_name, - tc.table_name, kcu.column_name, - ccu.table_name AS referenced_table_name, - ccu.column_name AS referenced_column_name - FROM - information_schema.table_constraints AS tc - JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name - JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name - WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = '%s' and ccu.column_name='%s' - ORDER BY kcu.ordinal_position", - $tableName, - $column - )); - foreach ($rows as $row) { - $this->dropForeignKey($tableName, $columns, $row['constraint_name']); - } + /** + * {@inheritdoc} + */ + protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) + { + $instructions = new AlterInstructions(); + + foreach ($columns as $column) { + $rows = $this->fetchAll(sprintf( + "SELECT + tc.constraint_name, + tc.table_name, kcu.column_name, + ccu.table_name AS referenced_table_name, + ccu.column_name AS referenced_column_name + FROM + information_schema.table_constraints AS tc + JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name + JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name + WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name = '%s' and ccu.column_name='%s' + ORDER BY kcu.ordinal_position", + $tableName, + $column + )); + foreach ($rows as $row) { + $instructions->merge( + $this->getDropForeignKeyInstructions($tableName, $columns, $row['constraint_name']) + ); } } + + return $instructions; } /** diff --git a/src/Phinx/Db/Adapter/TablePrefixAdapter.php b/src/Phinx/Db/Adapter/TablePrefixAdapter.php index 4caa7fbce..331011ed2 100644 --- a/src/Phinx/Db/Adapter/TablePrefixAdapter.php +++ b/src/Phinx/Db/Adapter/TablePrefixAdapter.php @@ -28,7 +28,7 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; @@ -63,19 +63,10 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], array $indexes = []) { - $adapterTable = clone $table; - $adapterTableName = $this->getAdapterTableName($table->getName()); - $adapterTable->setName($adapterTableName); - - foreach ($adapterTable->getForeignKeys() as $fk) { - $adapterReferenceTable = $fk->getReferencedTable(); - $adapterReferenceTableName = $this->getAdapterTableName($adapterReferenceTable->getName()); - $adapterReferenceTable->setName($adapterReferenceTableName); - } - - parent::createTable($adapterTable); + $adapterTable = new Table($table->getName(), $table->getOptions()); + parent::createTable($adapterTable, $columns, $indexes); } /** @@ -131,9 +122,7 @@ public function hasColumn($tableName, $columnName) */ public function addColumn(Table $table, Column $column) { - $adapterTable = clone $table; - $adapterTableName = $this->getAdapterTableName($table->getName()); - $adapterTable->setName($adapterTableName); + $adapterTable = new Table($table->getName(), $table->getOptions()); parent::addColumn($adapterTable, $column); } @@ -190,9 +179,7 @@ public function hasIndexByName($tableName, $indexName) */ public function addIndex(Table $table, Index $index) { - $adapterTable = clone $table; - $adapterTableName = $this->getAdapterTableName($table->getName()); - $adapterTable->setName($adapterTableName); + $adapterTable = new Table($table->getName(), $table->getOptions()); parent::addIndex($adapterTable, $index); } @@ -229,9 +216,7 @@ public function hasForeignKey($tableName, $columns, $constraint = null) */ public function addForeignKey(Table $table, ForeignKey $foreignKey) { - $adapterTable = clone $table; - $adapterTableName = $this->getAdapterTableName($table->getName()); - $adapterTable->setName($adapterTableName); + $adapterTable = new Table($table->getName(), $table->getOptions()); parent::addForeignKey($adapterTable, $foreignKey); } @@ -249,9 +234,7 @@ public function dropForeignKey($tableName, $columns, $constraint = null) */ public function insert(Table $table, $row) { - $adapterTable = clone $table; - $adapterTableName = $this->getAdapterTableName($table->getName()); - $adapterTable->setName($adapterTableName); + $adapterTable = new Table($table->getName(), $table->getOptions()); parent::insert($adapterTable, $row); } @@ -260,9 +243,7 @@ public function insert(Table $table, $row) */ public function bulkinsert(Table $table, $rows) { - $adapterTable = clone $table; - $adapterTableName = $this->getAdapterTableName($table->getName()); - $adapterTable->setName($adapterTableName); + $adapterTable = new Table($table->getName(), $table->getOptions()); parent::bulkinsert($adapterTable, $rows); } diff --git a/src/Phinx/Db/Adapter/TimedOutputAdapter.php b/src/Phinx/Db/Adapter/TimedOutputAdapter.php index fbe00ba35..90e867ad1 100644 --- a/src/Phinx/Db/Adapter/TimedOutputAdapter.php +++ b/src/Phinx/Db/Adapter/TimedOutputAdapter.php @@ -28,7 +28,7 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; @@ -131,11 +131,11 @@ public function bulkinsert(Table $table, $rows) /** * {@inheritdoc} */ - public function createTable(Table $table) + public function createTable(Table $table, array $columns = [], array $indexes = []) { $end = $this->startCommandTimer(); $this->writeCommand('createTable', [$table->getName()]); - parent::createTable($table); + parent::createTable($table, $columns, $indexes); $end(); } diff --git a/src/Phinx/Db/Plan/AlterTable.php b/src/Phinx/Db/Plan/AlterTable.php new file mode 100644 index 000000000..d8b1eb51d --- /dev/null +++ b/src/Phinx/Db/Plan/AlterTable.php @@ -0,0 +1,32 @@ +table = $table; + } + + public function addAction(Action $action) + { + $this->actions[] = $action; + } + + public function getTable() + { + return $this->table; + } + + public function getActions() + { + return $this->actions(); + } +} diff --git a/src/Phinx/Db/Plan/Intent.php b/src/Phinx/Db/Plan/Intent.php new file mode 100644 index 000000000..5567911cc --- /dev/null +++ b/src/Phinx/Db/Plan/Intent.php @@ -0,0 +1,26 @@ +actions[] = $action; + } + + public function getActions() + { + return $this->actions; + } + + public function merge(Intent $another) + { + $this->actions = array_merge($this->actions, $another->getActions()); + } +} diff --git a/src/Phinx/Db/Plan/NewTable.php b/src/Phinx/Db/Plan/NewTable.php new file mode 100644 index 000000000..4ac4cc607 --- /dev/null +++ b/src/Phinx/Db/Plan/NewTable.php @@ -0,0 +1,46 @@ +table = $table; + } + + public function addColumn(Column $column) + { + $this->columns[] = $column; + } + + public function addIndex(Index $index) + { + $this->indexes[] = $index; + } + + public function getTable() + { + return $this->table; + } + + public function getColumns() + { + return $this->columns; + } + + public function getIndexes() + { + return $this->indexes(); + } +} diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php new file mode 100644 index 000000000..01c3ee98c --- /dev/null +++ b/src/Phinx/Db/Plan/Plan.php @@ -0,0 +1,185 @@ +createPlan($intent->actions); + } + + protected function createPlan($actions) + { + $this->gatherCreates($actions); + $this->gatherUpdates($actions); + $this->gatherTableMoves($actions); + $this->gatherIndexes($actions); + $this->gatherConstraints($actions); + } + + public function execute(AdapterInterface $executor) + { + foreach ($this->tableCreates as $newTable) { + $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes()); + } + + foreach ($this->tableUpdates as $update) { + $executor->executeActions($update->getTable(), $update->getActions()); + } + + foreach ($this->tableMoves as $move) { + $executor->executeActions($move->getTable(), $move->getActions()); + } + + foreach ($this->constraints as $update) { + $executor->executeActions($update->getTable(), $update->getActions()); + } + + foreach ($this->indexes as $update) { + $executor->executeActions($update->getTable(), $update->getActions()); + } + } + + protected function gatherCreates($actions) + { + collection($actions) + ->filter(function ($action) { + return $action instanceof CreateTable; + }) + ->map(function ($action) { + $table = $action->getTable(); + return [$table->getName(), new NewTable($table)]; + }) + ->each(function ($step) { + $this->tableCreates[$step[0]] = $step[1]; + }); + + collection($actions) + ->filter(function ($action) { + return $action instanceof AddColumn + || $action instanceof AddIndex; + }) + ->filter(function ($action) { + return isset($this->tableCreates[$action->getTable()->getName()]); + }) + ->each(function ($action) { + $table = $action->getTable(); + + if ($action instanceof AddColumn) { + $this->tableCreates[$table->getName()]-addColumn($action->getColumn()); + } + + if ($action instanceof AddIndex) { + $this->tableCreates[$table->getName()]->addIndex($action->getIndex()); + } + }); + } + + protected function gatherUpdates($actions) + { + collection($actions) + ->filter(function ($action) { + return $action instanceof AddColumn + || $action instanceof ChangeColumn + || $action instanceof DropColumn + || $action instanceof RemoveColumn + || $action instanceof RenameColumn; + }) + // We are only concerned with table changes + ->reject(function ($action) { + return isset($this->tableCreates[$action->getTable()->getName()]); + }) + ->each(function ($action) { + $table = $action->getTable(); + $name = $table->getName(); + + if (!isset($this->tableUpdates[$name])) { + $this->tableUpdates[$name] = new AlterTable($table); + } + + $this->tableUpdates[$name]->addAction($action); + }); + } + + protected function gatherTableMoves($actions) + { + collection($actions) + ->filter(function ($action) { + return $action instanceof DropTable + || $action instanceof RenameTable; + }) + ->each(function ($action) { + $table = $action->getTable(); + $name = $table->getName(); + + if (!isset($this->tableMoves[$name])) { + $this->tableMoves[$name] = new AlterTable($table); + } + + $this->tableMoves[$name]->addAction($action); + }); + } + + protected function gatherIndexes($actions) + { + collection($actions) + ->filter(function ($action) { + return $action instanceof AddIndex + || $action instanceof DropIndex; + }) + ->each(function ($action) { + $table = $action->getTable(); + $name = $table->getName(); + + if (!isset($this->indexes[$name])) { + $this->indexes[$name] = new AlterTable($table); + } + + $this->indexes[$name]->addAction($action); + }); + } + + protected function gatherConstraints($actions) + { + collection($actions) + ->filter(function ($action) { + return $action instanceof AddForeignKey + || $action instanceof DropForeignKey; + }) + ->each(function ($action) { + $table = $action->getTable(); + $name = $table->getName(); + + if (!isset($this->constraints[$name])) { + $this->constraints[$name] = new AlterTable($table); + } + + $this->constraints[$name]->addAction($action); + }); + } +} diff --git a/src/Phinx/Db/Table.php b/src/Phinx/Db/Table.php index 19b00bcec..294241ab5 100644 --- a/src/Phinx/Db/Table.php +++ b/src/Phinx/Db/Table.php @@ -32,6 +32,7 @@ use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table as TableValue; /** * @@ -40,35 +41,15 @@ class Table { /** - * @var string + * @var TableValue */ - protected $name; - - /** - * @var array - */ - protected $options = []; + protected $table; /** * @var \Phinx\Db\Adapter\AdapterInterface */ protected $adapter; - /** - * @var array - */ - protected $columns = []; - - /** - * @var array - */ - protected $indexes = []; - - /** - * @var \Phinx\Db\Table\ForeignKey[] - */ - protected $foreignKeys = []; - /** * @var array */ @@ -83,27 +64,13 @@ class Table */ public function __construct($name, $options = [], AdapterInterface $adapter = null) { - $this->setName($name); - $this->setOptions($options); + $this->table = new TableValue($name, $options); if ($adapter !== null) { $this->setAdapter($adapter); } } - /** - * Sets the table name. - * - * @param string $name Table Name - * @return \Phinx\Db\Table - */ - public function setName($name) - { - $this->name = $name; - - return $this; - } - /** * Gets the table name. * @@ -111,20 +78,7 @@ public function setName($name) */ public function getName() { - return $this->name; - } - - /** - * Sets the table options. - * - * @param array $options - * @return \Phinx\Db\Table - */ - public function setOptions($options) - { - $this->options = $options; - - return $this; + return $this->table->getName(); } /** diff --git a/src/Phinx/Db/Table/Table.php b/src/Phinx/Db/Table/Table.php new file mode 100644 index 000000000..5c15fca62 --- /dev/null +++ b/src/Phinx/Db/Table/Table.php @@ -0,0 +1,47 @@ +name = $name; + } + + /** + * Sets the table name. + * + * @param string $name + * @return \Phinx\Db\Table\Table + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * Gets the table name. + * + * @return string + */ + public function getName() + { + return $this->name; + } +} diff --git a/src/Phinx/Db/Util/AlterInstructions.php b/src/Phinx/Db/Util/AlterInstructions.php new file mode 100644 index 000000000..c5c89836a --- /dev/null +++ b/src/Phinx/Db/Util/AlterInstructions.php @@ -0,0 +1,43 @@ +alterParts = $alterParts; + $this->postSteps = $postSteps; + } + + public function addAlter($part) + { + $this->alterParts[] = $part; + } + + public function addPostStep($sql) + { + $this->postSteps[] = $sql; + } + + public function getAlterParts() + { + return $this->alterParts; + } + + public function getPostSteps() + { + return $this->postSteps; + } + + public function merge(AlterInstructions $other) + { + $this->alterParts = array_merge($this->alterParts, $other->getAlterParts()); + $this->postSteps = array_merge($this->postSteps, $other->getPostSteps()); + } +} From 2a2f8bb49887e65848ee25209bd6267b48b29b45 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 22 Apr 2018 20:29:27 +0200 Subject: [PATCH 02/21] Fixing code and making tests pass Implemented again rversible migrations --- src/Phinx/Db/Action/AddColumn.php | 2 +- src/Phinx/Db/Action/AddForeignKey.php | 10 +- src/Phinx/Db/Action/CreateTable.php | 5 - src/Phinx/Db/Action/DropColumn.php | 29 - src/Phinx/Db/Action/RenameColumn.php | 2 +- src/Phinx/Db/Adapter/AbstractAdapter.php | 2 +- src/Phinx/Db/Adapter/AdapterWrapper.php | 10 +- src/Phinx/Db/Adapter/MysqlAdapter.php | 2 +- src/Phinx/Db/Adapter/PdoAdapter.php | 47 +- src/Phinx/Db/Adapter/PostgresAdapter.php | 13 +- src/Phinx/Db/Adapter/ProxyAdapter.php | 303 +-- src/Phinx/Db/Adapter/TablePrefixAdapter.php | 94 +- src/Phinx/Db/Plan/AlterTable.php | 3 +- src/Phinx/Db/Plan/NewTable.php | 2 +- src/Phinx/Db/Plan/Plan.php | 74 +- src/Phinx/Db/Table.php | 316 ++- src/Phinx/Db/Table/ForeignKey.php | 8 +- src/Phinx/Db/Table/Table.php | 23 +- src/Phinx/Db/Util/AlterInstructions.php | 2 +- tests/Phinx/Console/Command/CreateTest.php | 3 +- tests/Phinx/Db/Adapter/MysqlAdapterTest.php | 291 +-- .../Phinx/Db/Adapter/MysqlAdapterUnitTest.php | 1798 ----------------- .../Phinx/Db/Adapter/PostgresAdapterTest.php | 151 +- tests/Phinx/Db/Adapter/ProxyAdapterTest.php | 139 +- .../Db/Adapter/TablePrefixAdapterTest.php | 109 +- tests/Phinx/Db/TableTest.php | 160 +- .../Phinx/Migration/AbstractMigrationTest.php | 16 - tests/Phinx/Migration/ManagerTest.php | 12 +- ...49_rename_info_table_to_statuses_table.php | 2 +- ...20121224200739_rename_bio_to_biography.php | 2 +- ...49_rename_info_table_to_statuses_table.php | 2 +- ...20151224200739_rename_bio_to_biography.php | 2 +- ...49_rename_info_table_to_statuses_table.php | 2 +- ...20161224200739_rename_bio_to_biography.php | 2 +- 34 files changed, 788 insertions(+), 2850 deletions(-) delete mode 100644 src/Phinx/Db/Action/DropColumn.php delete mode 100644 tests/Phinx/Db/Adapter/MysqlAdapterUnitTest.php diff --git a/src/Phinx/Db/Action/AddColumn.php b/src/Phinx/Db/Action/AddColumn.php index 0446a3283..68370ca30 100644 --- a/src/Phinx/Db/Action/AddColumn.php +++ b/src/Phinx/Db/Action/AddColumn.php @@ -14,7 +14,7 @@ class AddColumn extends Action public function __construct(Table $table, Column $column) { - $this->table = $able; + $this->table = $table; $this->column = $column; } diff --git a/src/Phinx/Db/Action/AddForeignKey.php b/src/Phinx/Db/Action/AddForeignKey.php index 814e0dc96..14663d67f 100644 --- a/src/Phinx/Db/Action/AddForeignKey.php +++ b/src/Phinx/Db/Action/AddForeignKey.php @@ -19,18 +19,26 @@ public function __construct(Table $table, ForeignKey $fk) $this->foreignKey = $fk; } - public static function build(Table $table, $columns, Table $referencedTable, $referencedColumns = ['id'], array $options = []) + public static function build(Table $table, $columns, $referencedTable, $referencedColumns = ['id'], array $options = [], $name = null) { if (is_string($referencedColumns)) { $referencedColumns = [$referencedColumns]; // str to array } + if (is_string($referencedTable)) { + $referencedTable = new Table($referencedTable); + } + $fk = new ForeignKey(); $fk->setReferencedTable($referencedTable) ->setColumns($columns) ->setReferencedColumns($referencedColumns) ->setOptions($options); + if ($name !== null) { + $fk->setConstraint($name); + } + return new static($table, $fk); } diff --git a/src/Phinx/Db/Action/CreateTable.php b/src/Phinx/Db/Action/CreateTable.php index 4d6f2c712..615883d02 100644 --- a/src/Phinx/Db/Action/CreateTable.php +++ b/src/Phinx/Db/Action/CreateTable.php @@ -18,9 +18,4 @@ public function getTable() { return $this->table; } - - public function getTable() - { - return $this->table; - } } diff --git a/src/Phinx/Db/Action/DropColumn.php b/src/Phinx/Db/Action/DropColumn.php deleted file mode 100644 index 8bc5a746e..000000000 --- a/src/Phinx/Db/Action/DropColumn.php +++ /dev/null @@ -1,29 +0,0 @@ -table = $table; - $this->columnName = $columnName; - } - - public function getTable() - { - return $this->table; - } - - public function getColumnName() - { - return $this->columnName; - } -} diff --git a/src/Phinx/Db/Action/RenameColumn.php b/src/Phinx/Db/Action/RenameColumn.php index 03f0cf954..ec0283ba7 100644 --- a/src/Phinx/Db/Action/RenameColumn.php +++ b/src/Phinx/Db/Action/RenameColumn.php @@ -17,7 +17,7 @@ class RenameColumn extends Action public function __construct(Table $table, Column $column, $newName) { $this->table = $table; - $this->newName = newName; + $this->newName = $newName; $this->column = $column; } diff --git a/src/Phinx/Db/Adapter/AbstractAdapter.php b/src/Phinx/Db/Adapter/AbstractAdapter.php index d76ca7fdd..15ad8aea2 100644 --- a/src/Phinx/Db/Adapter/AbstractAdapter.php +++ b/src/Phinx/Db/Adapter/AbstractAdapter.php @@ -222,7 +222,7 @@ public function createSchemaTable() ->addColumn('breakpoint', 'boolean', ['default' => false]) ->save(); } catch (\Exception $exception) { - throw new \InvalidArgumentException('There was a problem creating the schema table: ' . $exception->getMessage()); + throw new \InvalidArgumentException('There was a problem creating the schema table: ' . $exception->getMessage(), $exception->getCode(), $exception); } } diff --git a/src/Phinx/Db/Adapter/AdapterWrapper.php b/src/Phinx/Db/Adapter/AdapterWrapper.php index 0f747cca3..09dcab60d 100644 --- a/src/Phinx/Db/Adapter/AdapterWrapper.php +++ b/src/Phinx/Db/Adapter/AdapterWrapper.php @@ -346,7 +346,7 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table, array $columns = [], $indexes = []) + public function createTable(Table $table, array $columns = [], array $indexes = []) { $this->getAdapter()->createTable($table, $columns, $indexes); } @@ -550,4 +550,12 @@ public function getConnection() { return $this->getAdapter()->getConnection(); } + + /** + * {@inheritdoc} + */ + public function executeActions(Table $table, array $actions) + { + return $this->getAdapter()->executeActions($table, $actions); + } } diff --git a/src/Phinx/Db/Adapter/MysqlAdapter.php b/src/Phinx/Db/Adapter/MysqlAdapter.php index 92225999e..81ee47f91 100644 --- a/src/Phinx/Db/Adapter/MysqlAdapter.php +++ b/src/Phinx/Db/Adapter/MysqlAdapter.php @@ -699,7 +699,7 @@ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) )); foreach ($rows as $row) { - $instructions->merge($this->getDropForeignKeyInstructions($row['CONSTRAINT_NAME'])); + $instructions->merge($this->getDropForeignKeyInstructions($tableName, $row['CONSTRAINT_NAME'])); } } diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index 4dabf08fb..f0f47260f 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -33,7 +33,6 @@ use Phinx\Db\Action\AddForeignKey; use Phinx\Db\Action\AddIndex; use Phinx\Db\Action\ChangeColumn; -use Phinx\Db\Action\DropColumn; use Phinx\Db\Action\DropForeignKey; use Phinx\Db\Action\DropIndex; use Phinx\Db\Action\DropTable; @@ -44,7 +43,6 @@ use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; use Phinx\Db\Table\Table; -use Phinx\Db\Table\Table; use Phinx\Db\Util\AlterInstructions; use Phinx\Migration\MigrationInterface; @@ -88,7 +86,7 @@ public function setConnection(\PDO $connection) if (!$this->hasSchemaTable()) { $this->createSchemaTable(); } else { - $table = new Table($this->getSchemaTableName(), [], $this); + $table = new \Phinx\Db\Table($this->getSchemaTableName(), [], $this); if (!$table->hasColumn('migration_name')) { $table ->addColumn( @@ -403,13 +401,17 @@ public function castToBool($value) protected function executeAlterSteps($tableName, AlterInstructions $instructions) { - $alter = sprintf( - 'ALTER TABLE %s %s', - $tableName, - implode(', ', $instructions->getAlterParts()) - ); + $alterParts = $instructions->getAlterParts(); - $this->execute($alter); + if ($alterParts) { + $alter = sprintf( + 'ALTER TABLE %s %s', + $this->quoteTableName($tableName), + implode(', ', $alterParts) + ); + + $this->execute($alter); + } foreach ($instructions->getPostSteps() as $sql) { $this->execute($sql); @@ -454,7 +456,7 @@ abstract protected function getChangeColumnInstructions($tableName, $columnName, */ public function dropColumn($tableName, $columnName) { - $instructions = $this->getDropColumnInstructions($columnName); + $instructions = $this->getDropColumnInstructions($tableName, $columnName); $this->executeAlterSteps($tableName, $instructions); } @@ -545,9 +547,12 @@ public function renameTable($tableName, $newTableName) abstract protected function getRenameTableInstructions($tableName, $newTableName); + /** + * {@inheritdoc} + */ public function executeActions(Table $table, array $actions) { - $instructions = AlterInstructions(); + $instructions = new AlterInstructions(); foreach ($actions as $action) { switch (true) { @@ -560,7 +565,7 @@ public function executeActions(Table $table, array $actions) break; case ($action instanceof AddForeignKey): - $instructions->merge($this->getAddForeignKeyInstructions($table, $action->getColumn())); + $instructions->merge($this->getAddForeignKeyInstructions($table, $action->getForeignKey())); break; case ($action instanceof ChangeColumn): @@ -585,13 +590,6 @@ public function executeActions(Table $table, array $actions) )); break; - case ($action instanceof DropColumn): - $instructions->merge($this->getDropColumnInstructions( - $table->getName(), - $action->getColumnName() - )); - break; - case ($action instanceof DropIndex && $action->getIndex()->getName() !== null): $instructions->merge($this->getDropIndexByNameInstructions( $table->getName(), @@ -602,16 +600,21 @@ public function executeActions(Table $table, array $actions) case ($action instanceof DropIndex && $action->getIndex()->getName() == null): $instructions->merge($this->getDropIndexByColumnsInstructions( $table->getName(), - $action->getIndex()->getPendingColumns() + $action->getIndex()->getColumns() )); break; case ($action instanceof DropTable): $instructions->merge($this->getDropTableInstructions( + $table->getName() + )); + break; + + case ($action instanceof RemoveColumn): + $instructions->merge($this->getDropColumnInstructions( $table->getName(), - $action->getColumn()->getName(), - $action->getNewName() + $action->getColumn()->getName() )); break; diff --git a/src/Phinx/Db/Adapter/PostgresAdapter.php b/src/Phinx/Db/Adapter/PostgresAdapter.php index b4132b5f1..530dc3069 100644 --- a/src/Phinx/Db/Adapter/PostgresAdapter.php +++ b/src/Phinx/Db/Adapter/PostgresAdapter.php @@ -169,7 +169,7 @@ public function hasTable($tableName) /** * {@inheritdoc} */ - public function createTable(Table $table, array $columns, array $indexes) + public function createTable(Table $table, array $columns = [], array $indexes = []) { $options = $table->getOptions(); @@ -259,7 +259,7 @@ protected function getRenameTableInstructions($tableName, $newTableName) $sql = sprintf( 'ALTER TABLE %s RENAME TO %s', $this->quoteTableName($tableName), - $this->quoteTableName($newTableName) + $this->quoteColumnName($newTableName) ); return new AlterInstructions([], [$sql]); @@ -352,7 +352,7 @@ protected function getAddColumnInstructions(Table $table, Column $column) { $instructions = new AlterInstructions(); $instructions->addAlter(sprintf( - 'ADD %s %s;', + 'ADD %s %s', $this->quoteColumnName($column->getName()), $this->getColumnSqlDefinition($column) )); @@ -404,6 +404,7 @@ protected function getChangeColumnInstructions($tableName, $columnName, Column $ $sql = sprintf( 'ALTER COLUMN %s TYPE %s', + $this->quoteColumnName($columnName), $this->getColumnSqlDefinition($newColumn) ); // @@ -464,7 +465,7 @@ protected function getChangeColumnInstructions($tableName, $columnName, Column $ /** * {@inheritdoc} */ - protected function getDropColumnInstructions($columnName) + protected function getDropColumnInstructions($tableName, $columnName) { $alter = sprintf( 'DROP COLUMN %s', @@ -571,7 +572,7 @@ protected function getDropIndexByColumnsInstructions($tableName, $columns) foreach ($indexes as $indexName => $index) { $a = array_diff($columns, $index['columns']); if (empty($a)) { - return AlterInstructions([], [sprintf( + return new AlterInstructions([], [sprintf( 'DROP INDEX IF EXISTS %s', $this->quoteColumnName($indexName) )]); @@ -704,7 +705,7 @@ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) )); foreach ($rows as $row) { - $newInstr = $this->getDropForeignKeyInstructions($row['constraint_name']); + $newInstr = $this->getDropForeignKeyInstructions($tableName, $row['constraint_name']); $instructions->merge($newInstr); } } diff --git a/src/Phinx/Db/Adapter/ProxyAdapter.php b/src/Phinx/Db/Adapter/ProxyAdapter.php index bdbe55ec5..e4e7ed015 100644 --- a/src/Phinx/Db/Adapter/ProxyAdapter.php +++ b/src/Phinx/Db/Adapter/ProxyAdapter.php @@ -28,10 +28,19 @@ */ namespace Phinx\Db\Adapter; +use Phinx\Db\Action\AddColumn; +use Phinx\Db\Action\AddForeignKey; +use Phinx\Db\Action\AddIndex; +use Phinx\Db\Action\CreateTable; +use Phinx\Db\Action\DropForeignKey; +use Phinx\Db\Action\DropIndex; +use Phinx\Db\Action\DropTable; +use Phinx\Db\Action\RemoveColumn; +use Phinx\Db\Action\RenameColumn; +use Phinx\Db\Action\RenameTable; +use Phinx\Db\Plan\Intent; +use Phinx\Db\Plan\Plan; use Phinx\Db\Table\Table; -use Phinx\Db\Table\Column; -use Phinx\Db\Table\ForeignKey; -use Phinx\Db\Table\Index; use Phinx\Migration\IrreversibleMigrationException; /** @@ -46,7 +55,7 @@ class ProxyAdapter extends AdapterWrapper /** * @var array */ - protected $commands; + protected $commands = []; /** * {@inheritdoc} @@ -61,197 +70,65 @@ public function getAdapterType() */ public function createTable(Table $table, array $columns = [], array $indexes = []) { - $this->recordCommand('createTable', [$table, $columns, $indexes]); + $this->commands[] = new CreateTable($table); } /** * {@inheritdoc} */ - public function renameTable($tableName, $newTableName) + public function executeActions(Table $table, array $actions) { - $this->recordCommand('renameTable', [$tableName, $newTableName]); - } - - /** - * {@inheritdoc} - */ - public function dropTable($tableName) - { - $this->recordCommand('dropTable', [$tableName]); - } - - /** - * {@inheritdoc} - */ - public function truncateTable($tableName) - { - $this->recordCommand('truncateTable', [$tableName]); - } - - /** - * {@inheritdoc} - */ - public function addColumn(Table $table, Column $column) - { - $this->recordCommand('addColumn', [$table, $column]); - } - - /** - * {@inheritdoc} - */ - public function renameColumn($tableName, $columnName, $newColumnName) - { - $this->recordCommand('renameColumn', [$tableName, $columnName, $newColumnName]); - } - - /** - * {@inheritdoc} - */ - public function changeColumn($tableName, $columnName, Column $newColumn) - { - $this->recordCommand('changeColumn', [$tableName, $columnName, $newColumn]); - } - - /** - * {@inheritdoc} - */ - public function dropColumn($tableName, $columnName) - { - $this->recordCommand('dropColumn', [$tableName, $columnName]); - } - - /** - * {@inheritdoc} - */ - public function addIndex(Table $table, Index $index) - { - $this->recordCommand('addIndex', [$table, $index]); - } - - /** - * {@inheritdoc} - */ - public function dropIndex($tableName, $columns, $options = []) - { - $this->recordCommand('dropIndex', [$tableName, $columns, $options]); - } - - /** - * {@inheritdoc} - */ - public function dropIndexByName($tableName, $indexName) - { - $this->recordCommand('dropIndexByName', [$tableName, $indexName]); - } - - /** - * {@inheritdoc} - */ - public function addForeignKey(Table $table, ForeignKey $foreignKey) - { - $this->recordCommand('addForeignKey', [$table, $foreignKey]); - } - - /** - * {@inheritdoc} - */ - public function dropForeignKey($tableName, $columns, $constraint = null) - { - $this->recordCommand('dropForeignKey', [$columns, $constraint]); - } - - /** - * {@inheritdoc} - */ - public function createDatabase($name, $options = []) - { - $this->recordCommand('createDatabase', [$name, $options]); - } - - /** - * Record a command for execution later. - * - * @param string $name Command Name - * @param array $arguments Command Arguments - * @return void - */ - public function recordCommand($name, $arguments) - { - $this->commands[] = [ - 'name' => $name, - 'arguments' => $arguments - ]; - } - - /** - * Sets an array of recorded commands. - * - * @param array $commands Commands - * @return \Phinx\Db\Adapter\ProxyAdapter - */ - public function setCommands($commands) - { - $this->commands = $commands; - - return $this; - } - - /** - * Gets an array of the recorded commands. - * - * @return array - */ - public function getCommands() - { - return $this->commands; + $this->commands = array_merge($this->commands, $actions); } /** * Gets an array of the recorded commands in reverse. * * @throws \Phinx\Migration\IrreversibleMigrationException if a command cannot be reversed. - * @return array + * @return \Phinx\Db\Plan\Intent */ public function getInvertedCommands() { - if ($this->getCommands() === null) { - return []; - } - - $invCommands = []; - $supportedCommands = [ - 'createTable', 'renameTable', 'addColumn', - 'renameColumn', 'addIndex', 'addForeignKey' - ]; - foreach (array_reverse($this->getCommands()) as $command) { - if (!in_array($command['name'], $supportedCommands)) { - throw new IrreversibleMigrationException(sprintf( - 'Cannot reverse a "%s" command', - $command['name'] - )); + $inverted = new Intent(); + + foreach (array_reverse($this->commands) as $com) { + switch (true) { + case $com instanceof CreateTable: + $inverted->addAction(new DropTable($com->getTable())); + break; + + case $com instanceof RenameTable: + $inverted->addAction(new RenameTable(new Table($com->getNewName()), $com->getTable()->getName())); + break; + + case $com instanceof AddColumn: + $inverted->addAction(new RemoveColumn($com->getTable(), $com->getColumn())); + break; + + case $com instanceof RenameColumn: + $column = clone $com->getColumn(); + $name = $column->getName(); + $column->setName($com->getNewName()); + $inverted->addAction(new RenameColumn($com->getTable(), $column, $name)); + break; + + case $com instanceof AddIndex: + $inverted->addAction(new DropIndex($com->getTable(), $com->getIndex())); + break; + + case $com instanceof AddForeignKey: + $inverted->addAction(new DropForeignKey($com->getTable(), $com->getForeignKey())); + break; + + default: + throw new IrreversibleMigrationException(sprintf( + 'Cannot reverse a "%s" command', + get_class($com) + )); } - $invertMethod = 'invert' . ucfirst($command['name']); - $invertedCommand = $this->$invertMethod($command['arguments']); - $invCommands[] = [ - 'name' => $invertedCommand['name'], - 'arguments' => $invertedCommand['arguments'] - ]; } - return $invCommands; - } - - /** - * Execute the recorded commands. - * - * @return void - */ - public function executeCommands() - { - $commands = $this->getCommands(); - foreach ($commands as $command) { - call_user_func_array([$this->getAdapter(), $command['name']], $command['arguments']); - } + return $inverted; } /** @@ -261,75 +138,7 @@ public function executeCommands() */ public function executeInvertedCommands() { - $commands = $this->getInvertedCommands(); - foreach ($commands as $command) { - call_user_func_array([$this->getAdapter(), $command['name']], $command['arguments']); - } - } - - /** - * Returns the reverse of a createTable command. - * - * @param array $args Method Arguments - * @return array - */ - public function invertCreateTable($args) - { - return ['name' => 'dropTable', 'arguments' => [$args[0]]]; - } - - /** - * Returns the reverse of a renameTable command. - * - * @param array $args Method Arguments - * @return array - */ - public function invertRenameTable($args) - { - return ['name' => 'renameTable', 'arguments' => [$args[1], $args[0]]]; - } - - /** - * Returns the reverse of a addColumn command. - * - * @param array $args Method Arguments - * @return array - */ - public function invertAddColumn($args) - { - return ['name' => 'dropColumn', 'arguments' => [$args[0]->getName(), $args[1]->getName()]]; - } - - /** - * Returns the reverse of a renameColumn command. - * - * @param array $args Method Arguments - * @return array - */ - public function invertRenameColumn($args) - { - return ['name' => 'renameColumn', 'arguments' => [$args[0], $args[2], $args[1]]]; - } - - /** - * Returns the reverse of a addIndex command. - * - * @param array $args Method Arguments - * @return array - */ - public function invertAddIndex($args) - { - return ['name' => 'dropIndex', 'arguments' => [$args[0]->getName(), $args[1]->getColumns()]]; - } - - /** - * Returns the reverse of a addForeignKey command. - * - * @param array $args Method Arguments - * @return array - */ - public function invertAddForeignKey($args) - { - return ['name' => 'dropForeignKey', 'arguments' => [$args[0]->getName(), $args[1]->getColumns()]]; + $plan = new Plan($this->getInvertedCommands()); + $plan->executeInverse($this->getAdapter()); } } diff --git a/src/Phinx/Db/Adapter/TablePrefixAdapter.php b/src/Phinx/Db/Adapter/TablePrefixAdapter.php index 331011ed2..cfca4366a 100644 --- a/src/Phinx/Db/Adapter/TablePrefixAdapter.php +++ b/src/Phinx/Db/Adapter/TablePrefixAdapter.php @@ -28,10 +28,20 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; +use Phinx\Db\Action\AddColumn; +use Phinx\Db\Action\AddForeignKey; +use Phinx\Db\Action\AddIndex; +use Phinx\Db\Action\ChangeColumn; +use Phinx\Db\Action\DropForeignKey; +use Phinx\Db\Action\DropIndex; +use Phinx\Db\Action\DropTable; +use Phinx\Db\Action\RemoveColumn; +use Phinx\Db\Action\RenameColumn; +use Phinx\Db\Action\RenameTable; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; /** * Table prefix/suffix adapter. @@ -65,7 +75,10 @@ public function hasTable($tableName) */ public function createTable(Table $table, array $columns = [], array $indexes = []) { - $adapterTable = new Table($table->getName(), $table->getOptions()); + $adapterTable = new Table( + $this->getAdapterTableName($table->getName()), + $table->getOptions() + ); parent::createTable($adapterTable, $columns, $indexes); } @@ -122,7 +135,8 @@ public function hasColumn($tableName, $columnName) */ public function addColumn(Table $table, Column $column) { - $adapterTable = new Table($table->getName(), $table->getOptions()); + $adapterTableName = $this->getAdapterTableName($table->getName()); + $adapterTable = new Table($adapterTableName, $table->getOptions()); parent::addColumn($adapterTable, $column); } @@ -216,7 +230,8 @@ public function hasForeignKey($tableName, $columns, $constraint = null) */ public function addForeignKey(Table $table, ForeignKey $foreignKey) { - $adapterTable = new Table($table->getName(), $table->getOptions()); + $adapterTableName = $this->getAdapterTableName($table->getName()); + $adapterTable = new Table($adapterTableName, $table->getOptions()); parent::addForeignKey($adapterTable, $foreignKey); } @@ -234,7 +249,8 @@ public function dropForeignKey($tableName, $columns, $constraint = null) */ public function insert(Table $table, $row) { - $adapterTable = new Table($table->getName(), $table->getOptions()); + $adapterTableName = $this->getAdapterTableName($table->getName()); + $adapterTable = new Table($adapterTableName, $table->getOptions()); parent::insert($adapterTable, $row); } @@ -243,7 +259,8 @@ public function insert(Table $table, $row) */ public function bulkinsert(Table $table, $rows) { - $adapterTable = new Table($table->getName(), $table->getOptions()); + $adapterTableName = $this->getAdapterTableName($table->getName()); + $adapterTable = new Table($adapterTableName, $table->getOptions()); parent::bulkinsert($adapterTable, $rows); } @@ -277,4 +294,69 @@ public function getAdapterTableName($tableName) { return $this->getPrefix() . $tableName . $this->getSuffix(); } + + /** + * {@inheritdoc} + */ + public function executeActions(Table $table, array $actions) + { + $adapterTableName = $this->getAdapterTableName($table->getName()); + $adapterTable = new Table($adapterTableName, $table->getOptions()); + + foreach ($actions as $k => $action) { + switch (true) { + case ($action instanceof AddColumn): + $actions[$k] = new AddColumn($adapterTable, $action->getColumn()); + break; + + case ($action instanceof AddIndex): + $actions[$k] = new AddIndex($adapterTable, $action->getIndex()); + break; + + case ($action instanceof AddForeignKey): + $foreignKey = clone $action->getForeignKey(); + $refTable = $foreignKey->getReferencedTable(); + $refTableName = $this->getAdapterTableName($refTable->getName()); + $foreignKey->setReferencedTable(new Table($refTableName, $refTable->getOptions())); + $actions[$k] = new AddForeignKey($adapterTable, $foreignKey); + break; + + case ($action instanceof ChangeColumn): + $actions[$k] = new ChangeColumn($adapterTable, $action->getColumnName(), $action->getColumn()); + break; + + case ($action instanceof DropForeignKey): + $actions[$k] = new DropForeignKey($adapterTable, $action->getForeignKey()); + break; + + case ($action instanceof DropIndex): + $actions[$k] = new DropIndex($adapterTable, $action->getIndex()); + break; + + case ($action instanceof DropTable): + $actions[$k] = new DropTable($adapterTable); + break; + + case ($action instanceof RemoveColumn): + $actions[$k] = new RemoveColumn($adapterTable, $action->getColumn()); + break; + + case ($action instanceof RenameColumn): + $actions[$k] = new RenameColumn($adapterTable, $action->getColumn(), $action->getNewName()); + break; + + case ($action instanceof RenameTable): + $actions[$k] = new RenameTable($adapterTable, $action->getNewName()); + break; + + default: + throw new \InvalidArgumentException( + sprintf("Forgot to implement table prefixing for action: '%s'", get_class($action)) + ); + } + } + + parent::executeActions($adapterTable, $actions); + } + } diff --git a/src/Phinx/Db/Plan/AlterTable.php b/src/Phinx/Db/Plan/AlterTable.php index d8b1eb51d..bce56a93e 100644 --- a/src/Phinx/Db/Plan/AlterTable.php +++ b/src/Phinx/Db/Plan/AlterTable.php @@ -3,6 +3,7 @@ namespace Phinx\Db\Plan; use Phinx\Db\Action\Action; +use Phinx\Db\Table\Table; class AlterTable { @@ -27,6 +28,6 @@ public function getTable() public function getActions() { - return $this->actions(); + return $this->actions; } } diff --git a/src/Phinx/Db/Plan/NewTable.php b/src/Phinx/Db/Plan/NewTable.php index 4ac4cc607..5da2d2302 100644 --- a/src/Phinx/Db/Plan/NewTable.php +++ b/src/Phinx/Db/Plan/NewTable.php @@ -41,6 +41,6 @@ public function getColumns() public function getIndexes() { - return $this->indexes(); + return $this->indexes; } } diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php index 01c3ee98c..1fd271378 100644 --- a/src/Phinx/Db/Plan/Plan.php +++ b/src/Phinx/Db/Plan/Plan.php @@ -7,13 +7,14 @@ use Phinx\Db\Action\AddIndex; use Phinx\Db\Action\ChangeColumn; use Phinx\Db\Action\CreateTable; -use Phinx\Db\Action\DropColumn; use Phinx\Db\Action\DropForeignKey; +use Phinx\Db\Action\DropIndex; use Phinx\Db\Action\DropTable; use Phinx\Db\Action\RemoveColumn; use Phinx\Db\Action\RenameColumn; use Phinx\Db\Action\RenameTable; use Phinx\Db\Adapter\AdapterInterface; +use Phinx\Db\Table\Table; class Plan { @@ -30,7 +31,7 @@ class Plan public function __construct(Intent $intent) { - $this->createPlan($intent->actions); + $this->createPlan($intent->getActions()); } protected function createPlan($actions) @@ -40,6 +41,17 @@ protected function createPlan($actions) $this->gatherTableMoves($actions); $this->gatherIndexes($actions); $this->gatherConstraints($actions); + $this->resolveConflicts(); + } + + protected function updatesSequence() + { + return [ + $this->tableUpdates, + $this->constraints, + $this->indexes, + $this->tableMoves, + ]; } public function execute(AdapterInterface $executor) @@ -48,21 +60,53 @@ public function execute(AdapterInterface $executor) $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes()); } - foreach ($this->tableUpdates as $update) { - $executor->executeActions($update->getTable(), $update->getActions()); - } + collection($this->updatesSequence()) + ->unfold() + ->each(function ($updates) use ($executor) { + $executor->executeActions($updates->getTable(), $updates->getActions()); + }); + } - foreach ($this->tableMoves as $move) { - $executor->executeActions($move->getTable(), $move->getActions()); + public function executeInverse(AdapterInterface $executor) + { + collection(array_reverse($this->updatesSequence())) + ->unfold() + ->each(function ($updates) use ($executor) { + $executor->executeActions($updates->getTable(), $updates->getActions()); + }); + + foreach ($this->tableCreates as $newTable) { + $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes()); } + } - foreach ($this->constraints as $update) { - $executor->executeActions($update->getTable(), $update->getActions()); + protected function resolveConflicts() + { + $actions = collection($this->tableMoves) + ->unfold(function ($move) { + return $move->getActions(); + }); + + foreach ($actions as $action) { + if ($action instanceof DropTable) { + $this->tableUpdates = $this->forgetActions($action->getTable(), $this->tableUpdates); + $this->constraints = $this->forgetActions($action->getTable(), $this->constraints); + $this->indexes = $this->forgetActions($action->getTable(), $this->indexes); + } } + } - foreach ($this->indexes as $update) { - $executor->executeActions($update->getTable(), $update->getActions()); + protected function forgetActions(Table $table, $actions) + { + $result = []; + foreach ($actions as $action) { + if ($action->getTable()->getName() === $table->getName()) { + continue; + } + $result[] = $action; } + + return $result; } protected function gatherCreates($actions) @@ -91,7 +135,7 @@ protected function gatherCreates($actions) $table = $action->getTable(); if ($action instanceof AddColumn) { - $this->tableCreates[$table->getName()]-addColumn($action->getColumn()); + $this->tableCreates[$table->getName()]->addColumn($action->getColumn()); } if ($action instanceof AddIndex) { @@ -106,7 +150,6 @@ protected function gatherUpdates($actions) ->filter(function ($action) { return $action instanceof AddColumn || $action instanceof ChangeColumn - || $action instanceof DropColumn || $action instanceof RemoveColumn || $action instanceof RenameColumn; }) @@ -152,6 +195,11 @@ protected function gatherIndexes($actions) return $action instanceof AddIndex || $action instanceof DropIndex; }) + ->reject(function ($action) { + // Indexes for new tables are created inline + // so we don't wan't them here too + return isset($this->tableCreates[$action->getTable()->getName()]); + }) ->each(function ($action) { $table = $action->getTable(); $name = $table->getName(); diff --git a/src/Phinx/Db/Table.php b/src/Phinx/Db/Table.php index 294241ab5..6ccddf898 100644 --- a/src/Phinx/Db/Table.php +++ b/src/Phinx/Db/Table.php @@ -28,7 +28,21 @@ */ namespace Phinx\Db; +use Phinx\Db\Action\AddColumn; +use Phinx\Db\Action\AddForeignKey; +use Phinx\Db\Action\AddIndex; +use Phinx\Db\Action\ChangeColumn; +use Phinx\Db\Action\CreateTable; +use Phinx\Db\Action\DropColumn; +use Phinx\Db\Action\DropForeignKey; +use Phinx\Db\Action\DropIndex; +use Phinx\Db\Action\DropTable; +use Phinx\Db\Action\RemoveColumn; +use Phinx\Db\Action\RenameColumn; +use Phinx\Db\Action\RenameTable; use Phinx\Db\Adapter\AdapterInterface; +use Phinx\Db\Plan\Intent; +use Phinx\Db\Plan\Plan; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; @@ -41,7 +55,7 @@ class Table { /** - * @var TableValue + * @var \Phinx\Db\Table\Table */ protected $table; @@ -50,6 +64,12 @@ class Table */ protected $adapter; + + /** + * @var \Phinx\Db\Plan\Intent + */ + protected $actions; + /** * @var array */ @@ -65,6 +85,7 @@ class Table public function __construct($name, $options = [], AdapterInterface $adapter = null) { $this->table = new TableValue($name, $options); + $this->actions = new Intent(); if ($adapter !== null) { $this->setAdapter($adapter); @@ -88,7 +109,17 @@ public function getName() */ public function getOptions() { - return $this->options; + return $this->table->getOptions(); + } + + /** + * Gets the table name and options as an object + * + * @return \Phinx\Db\Table\Table + */ + public function getTable() + { + return $this->table; } /** @@ -111,6 +142,10 @@ public function setAdapter(AdapterInterface $adapter) */ public function getAdapter() { + if (!$this->adapter) { + throw new \RuntimeException('There is no database adapter set yet, cannot proceed'); + } + return $this->adapter; } @@ -131,7 +166,9 @@ public function exists() */ public function drop() { - $this->getAdapter()->dropTable($this->getName()); + $this->actions->addAction(new DropTable($this->table)); + + return $this; } /** @@ -142,23 +179,7 @@ public function drop() */ public function rename($newTableName) { - $this->getAdapter()->renameTable($this->getName(), $newTableName); - $this->setName($newTableName); - - return $this; - } - - /** - * Sets an array of columns waiting to be committed. - * Use setPendingColumns - * - * @deprecated - * @param array $columns Columns - * @return \Phinx\Db\Table - */ - public function setColumns($columns) - { - $this->setPendingColumns($columns); + $this->actions->addAction(new RenameTable($this->table, $newTableName)); return $this; } @@ -173,75 +194,6 @@ public function getColumns() return $this->getAdapter()->getColumns($this->getName()); } - /** - * Sets an array of columns waiting to be committed. - * - * @param array $columns Columns - * @return \Phinx\Db\Table - */ - public function setPendingColumns($columns) - { - $this->columns = $columns; - - return $this; - } - - /** - * Gets an array of columns waiting to be committed. - * - * @return \Phinx\Db\Table\Column[] - */ - public function getPendingColumns() - { - return $this->columns; - } - - /** - * Sets an array of columns waiting to be indexed. - * - * @param array $indexes Indexes - * @return \Phinx\Db\Table - */ - public function setIndexes($indexes) - { - $this->indexes = $indexes; - - return $this; - } - - /** - * Gets an array of indexes waiting to be committed. - * - * @return array - */ - public function getIndexes() - { - return $this->indexes; - } - - /** - * Sets an array of foreign keys waiting to be commited. - * - * @param \Phinx\Db\Table\ForeignKey[] $foreignKeys foreign keys - * @return \Phinx\Db\Table - */ - public function setForeignKeys($foreignKeys) - { - $this->foreignKeys = $foreignKeys; - - return $this; - } - - /** - * Gets an array of foreign keys waiting to be commited. - * - * @return array|\Phinx\Db\Table\ForeignKey[] - */ - public function getForeignKeys() - { - return $this->foreignKeys; - } - /** * Sets an array of data to be inserted. * @@ -272,9 +224,7 @@ public function getData() */ public function reset() { - $this->setPendingColumns([]); - $this->setIndexes([]); - $this->setForeignKeys([]); + $this->actions = new Intent(); $this->setData([]); } @@ -295,31 +245,22 @@ public function reset() */ public function addColumn($columnName, $type = null, $options = []) { - // we need an adapter set to add a column - if ($this->getAdapter() === null) { - throw new \RuntimeException('An adapter must be specified to add a column.'); - } - - // create a new column object if only strings were supplied - if (!$columnName instanceof Column) { - $column = new Column(); - $column->setName($columnName); - $column->setType($type); - $column->setOptions($options); // map options to column methods + if ($columnName instanceof Column) { + $action = new AddColumn($this->table, $columnName); } else { - $column = $columnName; + $action = AddColumn::build($this->table, $columnName, $type, $options); } // Delegate to Adapters to check column type - if (!$this->getAdapter()->isValidColumnType($column)) { + if (!$this->getAdapter()->isValidColumnType($action->getColumn())) { throw new \InvalidArgumentException(sprintf( 'An invalid column type "%s" was specified for column "%s".', - $column->getType(), - $column->getName() + $type, + $action->getColumn()->getName() )); } - $this->columns[] = $column; + $this->actions->addAction($action); return $this; } @@ -332,7 +273,8 @@ public function addColumn($columnName, $type = null, $options = []) */ public function removeColumn($columnName) { - $this->getAdapter()->dropColumn($this->getName(), $columnName); + $action = RemoveColumn::build($this->table, $columnName); + $this->actions->addAction($action); return $this; } @@ -346,7 +288,8 @@ public function removeColumn($columnName) */ public function renameColumn($oldName, $newName) { - $this->getAdapter()->renameColumn($this->getName(), $oldName, $newName); + $action = RenameColumn::build($this->table, $oldName, $newName); + $this->actions->addAction($action); return $this; } @@ -359,23 +302,14 @@ public function renameColumn($oldName, $newName) * @param array $options Options * @return \Phinx\Db\Table */ - public function changeColumn($columnName, $newColumnType, $options = []) + public function changeColumn($columnName, $newColumnType, array $options = []) { - // create a column object if one wasn't supplied - if (!$newColumnType instanceof Column) { - $newColumn = new Column(); - $newColumn->setType($newColumnType); - $newColumn->setOptions($options); + if ($newColumnType instanceof Column) { + $action = new ChangeColumn($this->table, $columnName, $newColumnType); } else { - $newColumn = $newColumnType; + $action = ChangeColumn::build($this->table, $columnName, $newColumnType, $options); } - - // if the name was omitted use the existing column name - if ($newColumn->getName() === null || strlen($newColumn->getName()) === 0) { - $newColumn->setName($columnName); - } - - $this->getAdapter()->changeColumn($this->getName(), $columnName, $newColumn); + $this->actions->addAction($action); return $this; } @@ -400,21 +334,10 @@ public function hasColumn($columnName) * @param array $options Index Options * @return \Phinx\Db\Table */ - public function addIndex($columns, $options = []) + public function addIndex($columns, array $options = []) { - // create a new index object if strings or an array of strings were supplied - if (!$columns instanceof Index) { - $index = new Index(); - if (is_string($columns)) { - $columns = [$columns]; // str to array - } - $index->setColumns($columns); - $index->setOptions($options); - } else { - $index = $columns; - } - - $this->indexes[] = $index; + $action = AddIndex::build($this->table, $columns, $options); + $this->actions->addAction($action); return $this; } @@ -425,9 +348,10 @@ public function addIndex($columns, $options = []) * @param array $columns Columns * @return \Phinx\Db\Table */ - public function removeIndex($columns) + public function removeIndex(array $columns) { - $this->getAdapter()->dropIndex($this->getName(), $columns); + $action = DropIndex::build($this->table, $columns); + $this->actions->addAction($action); return $this; } @@ -440,7 +364,8 @@ public function removeIndex($columns) */ public function removeIndexByName($name) { - $this->getAdapter()->dropIndexByName($this->getName(), $name); + $action = DropIndex::buildFromName($this->table, $name); + $this->actions->addAction($action); return $this; } @@ -481,19 +406,36 @@ public function hasIndexByName($indexName) */ public function addForeignKey($columns, $referencedTable, $referencedColumns = ['id'], $options = []) { - if (is_string($referencedColumns)) { - $referencedColumns = [$referencedColumns]; // str to array - } - $fk = new ForeignKey(); - if ($referencedTable instanceof Table) { - $fk->setReferencedTable($referencedTable); - } else { - $fk->setReferencedTable(new Table($referencedTable, [], $this->adapter)); - } - $fk->setColumns($columns) - ->setReferencedColumns($referencedColumns) - ->setOptions($options); - $this->foreignKeys[] = $fk; + $action = AddForeignKey::build($this->table, $columns, $referencedTable, $referencedColumns); + $this->actions->addAction($action); + + return $this; + } + + /** + * Add a foreign key to a database table with a given name. + * + * In $options you can specify on_delete|on_delete = cascade|no_action .., + * on_update, constraint = constraint name. + * + * @param string $name The constaint name + * @param string|array $columns Columns + * @param string|\Phinx\Db\Table $referencedTable Referenced Table + * @param string|array $referencedColumns Referenced Columns + * @param array $options Options + * @return \Phinx\Db\Table + */ + public function addForeignKeyWithName($name, $columns, $referencedTable, $referencedColumns = ['id'], $options = []) + { + $action = AddForeignKey::build( + $this->table, + $columns, + $referencedTable, + $referencedColumns, + $options, + $name + ); + $this->actions->addAction($action); return $this; } @@ -507,14 +449,8 @@ public function addForeignKey($columns, $referencedTable, $referencedColumns = [ */ public function dropForeignKey($columns, $constraint = null) { - if (is_string($columns)) { - $columns = [$columns]; - } - if ($constraint) { - $this->getAdapter()->dropForeignKey($this->getName(), [], $constraint); - } else { - $this->getAdapter()->dropForeignKey($this->getName(), $columns); - } + $action = DropForeignKey::build($this->table, $columns, $constraint); + $this->actions->addAction($action); return $this; } @@ -543,6 +479,7 @@ public function addTimestamps($createdAtColumnName = 'created_at', $updatedAtCol { $createdAtColumnName = is_null($createdAtColumnName) ? 'created_at' : $createdAtColumnName; $updatedAtColumnName = is_null($updatedAtColumnName) ? 'updated_at' : $updatedAtColumnName; + $this->addColumn($createdAtColumnName, 'timestamp', [ 'default' => 'CURRENT_TIMESTAMP', 'update' => '' @@ -589,7 +526,7 @@ public function insert($data) */ public function create() { - $this->getAdapter()->createTable($this); + $this->executeActions(false); $this->saveData(); $this->reset(); // reset pending changes } @@ -602,23 +539,7 @@ public function create() */ public function update() { - if (!$this->exists()) { - throw new \RuntimeException('Cannot update a table that doesn\'t exist!'); - } - - // update table - foreach ($this->getPendingColumns() as $column) { - $this->getAdapter()->addColumn($this, $column); - } - - foreach ($this->getIndexes() as $index) { - $this->getAdapter()->addIndex($this, $index); - } - - foreach ($this->getForeignKeys() as $foreignKey) { - $this->getAdapter()->addForeignKey($this, $foreignKey); - } - + $this->executeActions(true); $this->saveData(); $this->reset(); // reset pending changes } @@ -647,10 +568,10 @@ public function saveData() } if ($bulk) { - $this->getAdapter()->bulkinsert($this, $this->getData()); + $this->getAdapter()->bulkinsert($this->table, $this->getData()); } else { foreach ($this->getData() as $row) { - $this->getAdapter()->insert($this, $row); + $this->getAdapter()->insert($this->table, $row); } } } @@ -682,4 +603,35 @@ public function save() $this->reset(); // reset pending changes } + + /** + * Executes all the pending actions for this table + * + * @param bool $exists Whether or not the table existed prior to executing this method + * @return void + */ + protected function executeActions($exists) + { + // Renaming a table is tricky, specially when running a reversible migration + // down. We will just assume the table already exists if the user commands a + // table rename. + $renamed = collection($this->actions->getActions()) + ->filter(function ($action) { + return $action instanceof RenameTable; + }) + ->first(); + + if ($renamed) { + $exists = true; + } + + // If the table does not exist, the last command in the chain needs to be + // a CreateTable action. + if (!$exists) { + $this->actions->addAction(new CreateTable($this->table)); + } + + $plan = new Plan($this->actions); + $plan->execute($this->getAdapter()); + } } diff --git a/src/Phinx/Db/Table/ForeignKey.php b/src/Phinx/Db/Table/ForeignKey.php index d10db9c5b..d9483a41c 100644 --- a/src/Phinx/Db/Table/ForeignKey.php +++ b/src/Phinx/Db/Table/ForeignKey.php @@ -29,7 +29,7 @@ */ namespace Phinx\Db\Table; -use Phinx\Db\Table; +use Phinx\Db\Table\Table; class ForeignKey { @@ -44,7 +44,7 @@ class ForeignKey protected $columns = []; /** - * @var \Phinx\Db\Table + * @var \Phinx\Db\Table\Table */ protected $referencedTable; @@ -94,7 +94,7 @@ public function getColumns() /** * Sets the foreign key referenced table. * - * @param \Phinx\Db\Table $table + * @param \Phinx\Db\Table\Table $table * @return \Phinx\Db\Table\ForeignKey */ public function setReferencedTable(Table $table) @@ -107,7 +107,7 @@ public function setReferencedTable(Table $table) /** * Gets the foreign key referenced table. * - * @return \Phinx\Db\Table + * @return \Phinx\Db\Table\Table */ public function getReferencedTable() { diff --git a/src/Phinx/Db/Table/Table.php b/src/Phinx/Db/Table/Table.php index 5c15fca62..e0487fce8 100644 --- a/src/Phinx/Db/Table/Table.php +++ b/src/Phinx/Db/Table/Table.php @@ -13,13 +13,14 @@ class Table /** * @param string $name The table name */ - public function __construct($name) + public function __construct($name, array $options = []) { if (empty($name)) { throw new InvalidArgumentException('Cannot use an empty table name'); } $this->name = $name; + $this->options = $options; } /** @@ -44,4 +45,24 @@ public function getName() { return $this->name; } + + /** + * Gets the table options + * + * @return array + */ + public function getOptions() + { + return $this->options; + } + + /** + * Sets the table options + * + * @return array + */ + public function setOptions(array $options) + { + $this->options = $options; + } } diff --git a/src/Phinx/Db/Util/AlterInstructions.php b/src/Phinx/Db/Util/AlterInstructions.php index c5c89836a..0c91e22fb 100644 --- a/src/Phinx/Db/Util/AlterInstructions.php +++ b/src/Phinx/Db/Util/AlterInstructions.php @@ -1,6 +1,6 @@ $command->getName()], $commandLine); - $commandTester->execute($commandLine); + $res = $commandTester->execute($commandLine); + $this->assertEquals(0, $res); } public function provideSimpleTemplateGenerator() diff --git a/tests/Phinx/Db/Adapter/MysqlAdapterTest.php b/tests/Phinx/Db/Adapter/MysqlAdapterTest.php index 5e12e735a..59ff7ed2c 100644 --- a/tests/Phinx/Db/Adapter/MysqlAdapterTest.php +++ b/tests/Phinx/Db/Adapter/MysqlAdapterTest.php @@ -208,12 +208,6 @@ public function testCreateTableCustomIdColumn() $this->assertFalse($this->adapter->hasColumn('ntable', 'address')); } - public function testCreateTableWithNoOptions() - { - $this->markTestIncomplete(); - //$this->adapter->createTable('ntable', ) - } - public function testCreateTableWithNoPrimaryKey() { $options = [ @@ -381,7 +375,8 @@ public function testRenameTable() $table->save(); $this->assertTrue($this->adapter->hasTable('table1')); $this->assertFalse($this->adapter->hasTable('table2')); - $this->adapter->renameTable('table1', 'table2'); + + $table->rename('table2')->save(); $this->assertFalse($this->adapter->hasTable('table1')); $this->assertTrue($this->adapter->hasTable('table2')); } @@ -507,7 +502,9 @@ public function testRenameColumn() ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); $this->assertFalse($this->adapter->hasColumn('t', 'column2')); - $this->adapter->renameColumn('t', 'column1', 'column2'); + + + $table->renameColumn('column1', 'column2')->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); $this->assertTrue($this->adapter->hasColumn('t', 'column2')); } @@ -519,7 +516,7 @@ public function testRenamingANonExistentColumn() ->save(); try { - $this->adapter->renameColumn('t', 'column2', 'column1'); + $table->renameColumn('column2', 'column1')->save(); $this->fail('Expected the adapter to throw an exception'); } catch (\InvalidArgumentException $e) { $this->assertInstanceOf( @@ -537,14 +534,13 @@ public function testChangeColumn() $table->addColumn('column1', 'string') ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); - $newColumn1 = new \Phinx\Db\Table\Column(); - $newColumn1->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', 'string')->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); + $newColumn2 = new \Phinx\Db\Table\Column(); $newColumn2->setName('column2') ->setType('string'); - $table->changeColumn('column1', $newColumn2); + $table->changeColumn('column1', $newColumn2)->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); $this->assertTrue($this->adapter->hasColumn('t', 'column2')); } @@ -557,7 +553,7 @@ public function testChangeColumnDefaultValue() $newColumn1 = new \Phinx\Db\Table\Column(); $newColumn1->setDefault('test1') ->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('SHOW COLUMNS FROM t'); $this->assertNotNull($rows[1]['Default']); $this->assertEquals("test1", $rows[1]['Default']); @@ -571,7 +567,7 @@ public function testChangeColumnDefaultToZero() $newColumn1 = new \Phinx\Db\Table\Column(); $newColumn1->setDefault(0) ->setType('integer'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('SHOW COLUMNS FROM t'); $this->assertNotNull($rows[1]['Default']); $this->assertEquals("0", $rows[1]['Default']); @@ -585,7 +581,7 @@ public function testChangeColumnDefaultToNull() $newColumn1 = new \Phinx\Db\Table\Column(); $newColumn1->setDefault(null) ->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('SHOW COLUMNS FROM t'); $this->assertNull($rows[1]['Default']); } @@ -677,42 +673,52 @@ public function testDropColumn() $table->addColumn('column1', 'string') ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); - $this->adapter->dropColumn('t', 'column1'); + + $table->removeColumn('column1')->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); } - public function testGetColumns() + public function columnsProvider() + { + return [ + ['column1', 'string', []], + ['column2', 'integer', []], + ['column3', 'biginteger', []], + ['column4', 'text', []], + ['column5', 'float', []], + ['column6', 'decimal', []], + ['column7', 'datetime', []], + ['column8', 'time', []], + ['column9', 'timestamp', []], + ['column10', 'date', []], + ['column11', 'binary', []], + ['column12', 'boolean', []], + ['column13', 'string', ['limit' => 10]], + ['column15', 'integer', ['limit' => 10]], + ['column16', 'geometry', []], + ['column17', 'point', []], + ['column18', 'linestring', []], + ['column19', 'polygon', []], + ['column20', 'uuid', []], + ['column21', 'set', ['values' => "one, two"]], + ['column22', 'enum', ['values' => ['three', 'four']]], + ['column23', 'bit', []] + ]; + } + + /** + * + * @dataProvider columnsProvider + */ + public function testGetColumns($colName, $type, $options) { $table = new \Phinx\Db\Table('t', [], $this->adapter); - $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->addColumn('column3', 'biginteger') - ->addColumn('column4', 'text') - ->addColumn('column5', 'float') - ->addColumn('column6', 'decimal') - ->addColumn('column7', 'datetime') - ->addColumn('column8', 'time') - ->addColumn('column9', 'timestamp') - ->addColumn('column10', 'date') - ->addColumn('column11', 'binary') - ->addColumn('column12', 'boolean') - ->addColumn('column13', 'string', ['limit' => 10]) - ->addColumn('column15', 'integer', ['limit' => 10]) - ->addColumn('column16', 'geometry') - ->addColumn('column17', 'point') - ->addColumn('column18', 'linestring') - ->addColumn('column19', 'polygon') - ->addColumn('column20', 'uuid') - ->addColumn('column21', 'set', ['values' => "one, two"]) - ->addColumn('column22', 'enum', ['values' => ['three', 'four']]) - ->addColumn('column23', 'bit'); - $pendingColumns = $table->getPendingColumns(); - $table->save(); + $table->addColumn($colName, $type, $options)->save(); + $columns = $this->adapter->getColumns('t'); - $this->assertCount(count($pendingColumns) + 1, $columns); - for ($i = 0; $i++; $i < count($pendingColumns)) { - $this->assertEquals($pendingColumns[$i], $columns[$i + 1]); - } + $this->assertCount(2, $columns); + $this->assertEquals($colName, $columns[1]->getName()); + $this->assertEquals($type, $columns[1]->getType()); } public function testDescribeTable() @@ -732,35 +738,9 @@ public function testDescribeTable() public function testGetColumnsReservedTableName() { $table = new \Phinx\Db\Table('group', [], $this->adapter); - $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->addColumn('column3', 'biginteger') - ->addColumn('column4', 'text') - ->addColumn('column5', 'float') - ->addColumn('column6', 'decimal') - ->addColumn('column7', 'datetime') - ->addColumn('column8', 'time') - ->addColumn('column9', 'timestamp') - ->addColumn('column10', 'date') - ->addColumn('column11', 'binary') - ->addColumn('column12', 'boolean') - ->addColumn('column13', 'string', ['limit' => 10]) - ->addColumn('column15', 'integer', ['limit' => 10]) - ->addColumn('column16', 'geometry') - ->addColumn('column17', 'point') - ->addColumn('column18', 'linestring') - ->addColumn('column19', 'polygon') - ->addColumn('column20', 'uuid') - ->addColumn('column21', 'set', ['values' => "one, two"]) - ->addColumn('column22', 'enum', ['values' => ['three', 'four']]) - ->addColumn('column23', 'bit'); - $pendingColumns = $table->getPendingColumns(); - $table->save(); + $table->addColumn('column1', 'string')->save(); $columns = $this->adapter->getColumns('group'); - $this->assertCount(count($pendingColumns) + 1, $columns); - for ($i = 0; $i++; $i < count($pendingColumns)) { - $this->assertEquals($pendingColumns[$i], $columns[$i + 1]); - } + $this->assertCount(2, $columns); } public function testAddIndex() @@ -799,7 +779,7 @@ public function testDropIndex() ->addIndex('email') ->save(); $this->assertTrue($table->hasIndex('email')); - $this->adapter->dropIndex($table->getName(), 'email'); + $table->removeIndex(['email'])->save(); $this->assertFalse($table->hasIndex('email')); // multiple column index @@ -809,7 +789,7 @@ public function testDropIndex() ->addIndex(['fname', 'lname']) ->save(); $this->assertTrue($table2->hasIndex(['fname', 'lname'])); - $this->adapter->dropIndex($table2->getName(), ['fname', 'lname']); + $table2->removeIndex(['fname', 'lname'])->save(); $this->assertFalse($table2->hasIndex(['fname', 'lname'])); // index with name specified, but dropping it by column name @@ -818,7 +798,7 @@ public function testDropIndex() ->addIndex('email', ['name' => 'someindexname']) ->save(); $this->assertTrue($table3->hasIndex('email')); - $this->adapter->dropIndex($table3->getName(), 'email'); + $table3->removeIndex(['email'])->save(); $this->assertFalse($table3->hasIndex('email')); // multiple column index with name specified @@ -828,7 +808,7 @@ public function testDropIndex() ->addIndex(['fname', 'lname'], ['name' => 'multiname']) ->save(); $this->assertTrue($table4->hasIndex(['fname', 'lname'])); - $this->adapter->dropIndex($table4->getName(), ['fname', 'lname']); + $table4->removeIndex(['fname', 'lname'])->save(); $this->assertFalse($table4->hasIndex(['fname', 'lname'])); // don't drop multiple column index when dropping single column @@ -838,7 +818,11 @@ public function testDropIndex() ->addIndex(['fname', 'lname']) ->save(); $this->assertTrue($table2->hasIndex(['fname', 'lname'])); - $this->adapter->dropIndex($table2->getName(), ['fname']); + + try { + $table2->removeIndex(['fname'])->save(); + } catch (\InvalidArgumentException $e) { + } $this->assertTrue($table2->hasIndex(['fname', 'lname'])); // don't drop multiple column index with name specified when dropping @@ -849,7 +833,12 @@ public function testDropIndex() ->addIndex(['fname', 'lname'], ['name' => 'multiname']) ->save(); $this->assertTrue($table4->hasIndex(['fname', 'lname'])); - $this->adapter->dropIndex($table4->getName(), ['fname']); + + try { + $table4->removeIndex(['fname'])->save(); + } catch (\InvalidArgumentException $e) { + } + $this->assertTrue($table4->hasIndex(['fname', 'lname'])); } @@ -861,7 +850,7 @@ public function testDropIndexByName() ->addIndex('email', ['name' => 'myemailindex']) ->save(); $this->assertTrue($table->hasIndex('email')); - $this->adapter->dropIndexByName($table->getName(), 'myemailindex'); + $table->removeIndexByName('myemailindex')->save(); $this->assertFalse($table->hasIndex('email')); // multiple column index @@ -871,7 +860,7 @@ public function testDropIndexByName() ->addIndex(['fname', 'lname'], ['name' => 'twocolumnindex']) ->save(); $this->assertTrue($table2->hasIndex(['fname', 'lname'])); - $this->adapter->dropIndexByName($table2->getName(), 'twocolumnindex'); + $table2->removeIndexByName('twocolumnindex')->save(); $this->assertFalse($table2->hasIndex(['fname', 'lname'])); } @@ -881,14 +870,11 @@ public function testAddForeignKey() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -898,14 +884,11 @@ public function testAddForeignKeyForTableWithUnsignedPK() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer', ['signed' => false])->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer', ['signed' => false]) + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -915,15 +898,12 @@ public function testDropForeignKey() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); - $this->adapter->dropForeignKey($table->getName(), ['ref_table_id']); + $table->dropForeignKey(['ref_table_id'])->save(); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -933,15 +913,12 @@ public function testDropForeignKeyForTableWithUnsignedPK() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer', ['signed' => false])->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer', ['signed' => false]) + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); - $this->adapter->dropForeignKey($table->getName(), ['ref_table_id']); + $table->dropForeignKey(['ref_table_id'])->save(); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -951,68 +928,26 @@ public function testDropForeignKeyAsString() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); - $this->adapter->dropForeignKey($table->getName(), 'ref_table_id'); + $table->dropForeignKey('ref_table_id')->save(); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } - public function testHasForeignKey() - { - $refTable = new \Phinx\Db\Table('ref_table', [], $this->adapter); - $refTable->addColumn('field1', 'string')->save(); - - $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $this->adapter->addForeignKey($table, $fk); - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); - $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id2'])); - } - - public function testHasForeignKeyForTableWithUnsignedPK() - { - $refTable = new \Phinx\Db\Table('ref_table', ['signed' => false], $this->adapter); - $refTable->addColumn('field1', 'string')->save(); - - $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer', ['signed' => false])->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $this->adapter->addForeignKey($table, $fk); - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); - $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id2'])); - } - public function testHasForeignKeyAsString() { $refTable = new \Phinx\Db\Table('ref_table', [], $this->adapter); $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), 'ref_table_id')); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), 'ref_table_id2')); } @@ -1023,15 +958,11 @@ public function testHasForeignKeyWithConstraint() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setConstraint("my_constraint") - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKeyWithName('my_constraint', ['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'], 'my_constraint')); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'], 'my_constraint2')); } @@ -1042,15 +973,11 @@ public function testHasForeignKeyWithConstraintForTableWithUnsignedPK() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer', ['signed' => false])->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setConstraint("my_constraint") - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer', ['signed' => false]) + ->addForeignKeyWithName('my_constraint', ['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'], 'my_constraint')); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'], 'my_constraint2')); } @@ -1172,10 +1099,8 @@ public function testBulkInsertData() $table->addColumn('column1', 'string') ->addColumn('column2', 'integer') ->addColumn('column3', 'string', ['default' => 'test']) - ->insert($data); - $this->adapter->createTable($table); - $this->adapter->bulkinsert($table, $table->getData()); - $table->reset(); + ->insert($data) + ->save(); $rows = $this->adapter->fetchAll('SELECT * FROM table1'); $this->assertEquals('value1', $rows[0]['column1']); diff --git a/tests/Phinx/Db/Adapter/MysqlAdapterUnitTest.php b/tests/Phinx/Db/Adapter/MysqlAdapterUnitTest.php deleted file mode 100644 index a10426228..000000000 --- a/tests/Phinx/Db/Adapter/MysqlAdapterUnitTest.php +++ /dev/null @@ -1,1798 +0,0 @@ -connection = $connection; - } - - public function getConnection() - { - return $this->connection; - } - - // change visibility for testing - public function getDefaultValueDefinition($default) - { - return parent::getDefaultValueDefinition($default); - } - - public function getColumnSqlDefinition(Column $column) - { - return parent::getColumnSqlDefinition($column); - } - - public function getIndexSqlDefinition(Index $index) - { - return parent::getIndexSqlDefinition($index); - } - - public function getIndexes($tableName) - { - return parent::getIndexes($tableName); - } - - public function getForeignKeys($tableName) - { - return parent::getForeignKeys($tableName); - } -} - -class MysqlAdapterUnitTest extends TestCase -{ - /** - * @var MysqlAdapterTester - */ - private $adapter; - - private $conn; - - private $result; - - public function setUp() - { - if (!TESTS_PHINX_DB_ADAPTER_MYSQL_ENABLED) { - $this->markTestSkipped('Mysql tests disabled. See TESTS_PHINX_DB_ADAPTER_MYSQL_ENABLED constant.'); - } - - $this->adapter = new MysqlAdapterTester([], new ArrayInput([]), new NullOutput()); - - $this->conn = $this->getMockBuilder('PDOMock') - ->disableOriginalConstructor() - ->setMethods([ 'query', 'exec', 'quote' ]) - ->getMock(); - $this->result = $this->getMockBuilder('stdclass') - ->disableOriginalConstructor() - ->setMethods([ 'fetch' ]) - ->getMock(); - $this->adapter->setMockConnection($this->conn); - } - - // helper methods for easy mocking - private function assertExecuteSql($expected_sql) - { - $this->conn->expects($this->once()) - ->method('exec') - ->with($this->equalTo($expected_sql)); - } - - private function assertQuerySql($expectedSql, $returnValue = null) - { - $expect = $this->conn->expects($this->once()) - ->method('query') - ->with($this->equalTo($expectedSql)); - if (!is_null($returnValue)) { - $expect->will($this->returnValue($returnValue)); - } - } - - private function assertFetchRowSql($expectedSql, $returnValue) - { - $this->result->expects($this->once()) - ->method('fetch') - ->will($this->returnValue($returnValue)); - $this->assertQuerySql($expectedSql, $this->result); - } - - public function testDisconnect() - { - $this->assertNotNull($this->adapter->getConnection()); - $this->adapter->disconnect(); - $this->assertNull($this->adapter->getConnection()); - } - - // database related tests - - public function testHasDatabaseExists() - { - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue(['SCHEMA_NAME' => 'database_name'])); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'database_name'", $this->result); - - $this->assertTrue($this->adapter->hasDatabase('database_name')); - } - - public function testHasDatabaseNotExists() - { - $this->result->expects($this->once()) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'database_name2'", $this->result); - - $this->assertFalse($this->adapter->hasDatabase('database_name2')); - } - - public function testDropDatabase() - { - $this->assertExecuteSql("DROP DATABASE IF EXISTS `database_name`"); - $this->adapter->dropDatabase('database_name'); - } - - public function testCreateDatabase() - { - $this->assertExecuteSql("CREATE DATABASE `database_name` DEFAULT CHARACTER SET `utf8`"); - $this->adapter->createDatabase('database_name'); - } - - public function testCreateDatabaseWithCharset() - { - $this->assertExecuteSql("CREATE DATABASE `database_name` DEFAULT CHARACTER SET `latin1`"); - $this->adapter->createDatabase('database_name', ['charset' => 'latin1']); - } - - public function testCreateDatabaseWithCharsetAndCollation() - { - $this->assertExecuteSql("CREATE DATABASE `database_name` DEFAULT CHARACTER SET `latin1` COLLATE `latin1_swedish_ci`"); - $this->adapter->createDatabase('database_name', ['charset' => 'latin1', 'collation' => 'latin1_swedish_ci']); - } - - public function testHasTransactions() - { - $this->assertTrue($this->adapter->hasTransactions()); - } - - public function testBeginTransaction() - { - $this->assertExecuteSql("START TRANSACTION"); - $this->adapter->beginTransaction(); - } - - public function testCommitTransaction() - { - $this->assertExecuteSql("COMMIT"); - $this->adapter->commitTransaction(); - } - - public function testRollbackTransaction() - { - $this->assertExecuteSql("ROLLBACK"); - $this->adapter->rollbackTransaction(); - } - - // table related tests - - public function testDescribeTable() - { - $this->adapter->setOptions(['name' => 'database_name']); - - $expectedSql = "SELECT * - FROM information_schema.tables - WHERE table_schema = 'database_name' - AND table_name = 'table_name'"; - - $returnValue = ['TABLE_TYPE' => 'BASE_TABLE', - 'TABLE_NAME' => 'table_name', - 'TABLE_SCHEMA' => 'database_name', - 'TABLE_ROWS' => 0]; - $this->assertFetchRowSql($expectedSql, $returnValue); - - $described = $this->adapter->describeTable('table_name'); - $this->assertEquals($returnValue, $described); - } - - public function testRenameTable() - { - $this->assertExecuteSql("RENAME TABLE `old_table_name` TO `new_table_name`"); - $this->adapter->renameTable('old_table_name', 'new_table_name'); - } - - public function testDropTable() - { - $this->assertExecuteSql("DROP TABLE `table_name`"); - $this->adapter->dropTable("table_name"); - } - - public function testTruncateTable() - { - $this->assertExecuteSql("TRUNCATE TABLE `table_name`"); - $this->adapter->truncateTable("table_name"); - } - - public function testHasTableExists() - { - $this->adapter->setOptions(['name' => 'database_name']); - $this->result->expects($this->once()) - ->method('fetch') - ->will($this->returnValue(['somecontent'])); - $expectedSql = 'SELECT TABLE_NAME - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_SCHEMA = \'database_name\' AND TABLE_NAME = \'table_name\''; - $this->assertQuerySql($expectedSql, $this->result); - $this->assertTrue($this->adapter->hasTable("table_name")); - } - - public function testHasTableNotExists() - { - $this->adapter->setOptions(['name' => 'database_name']); - $this->result->expects($this->once()) - ->method('fetch') - ->will($this->returnValue([])); - $expectedSql = 'SELECT TABLE_NAME - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_SCHEMA = \'database_name\' AND TABLE_NAME = \'table_name\''; - $this->assertQuerySql($expectedSql, $this->result); - $this->assertFalse($this->adapter->hasTable("table_name")); - } - - public function testCreateTableBasic() - { - $column1 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column1->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column1->expects($this->any())->method('getType')->will($this->returnValue('string')); - $column1->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column1->expects($this->at(0))->method('getLimit')->will($this->returnValue('64')); - - $column2 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column2->expects($this->any())->method('getName')->will($this->returnValue('column_name2')); - $column2->expects($this->any())->method('getType')->will($this->returnValue('integer')); - $column2->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column2->expects($this->at(0))->method('getLimit')->will($this->returnValue('4')); - - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName', 'getOptions', 'getPendingColumns', 'getIndexes', 'getForeignKeys']) - ->getMock(); - - $table->expects($this->any())->method('getPendingColumns')->will($this->returnValue([$column1, $column2])); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - $table->expects($this->any())->method('getOptions')->will($this->returnValue([])); - $table->expects($this->any())->method('getIndexes')->will($this->returnValue([])); - $table->expects($this->any())->method('getForeignKeys')->will($this->returnValue([])); - - $expectedSql = 'CREATE TABLE `table_name` (`id` INT(11) NOT NULL AUTO_INCREMENT, `column_name` VARCHAR(255) NOT NULL, `column_name2` INT(11) NOT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;'; - $this->assertExecuteSql($expectedSql); - $this->adapter->createTable($table); - } - - public function testCreateTablePrimaryKey() - { - $column1 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column1->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column1->expects($this->any())->method('getType')->will($this->returnValue('string')); - $column1->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column1->expects($this->at(0))->method('getLimit')->will($this->returnValue('64')); - - $column2 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column2->expects($this->any())->method('getName')->will($this->returnValue('column_name2')); - $column2->expects($this->any())->method('getType')->will($this->returnValue('integer')); - $column2->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column2->expects($this->at(0))->method('getLimit')->will($this->returnValue('4')); - - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName', 'getOptions', 'getPendingColumns', 'getIndexes', 'getForeignKeys']) - ->getMock(); - - $tableOptions = ['id' => 'column_name2']; - $table->expects($this->any())->method('getPendingColumns')->will($this->returnValue([$column1, $column2])); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - $table->expects($this->any())->method('getOptions')->will($this->returnValue($tableOptions)); - $table->expects($this->any())->method('getIndexes')->will($this->returnValue([])); - $table->expects($this->any())->method('getForeignKeys')->will($this->returnValue([])); - - $expectedSql = 'CREATE TABLE `table_name` (`column_name2` INT(11) NOT NULL AUTO_INCREMENT, `column_name` VARCHAR(255) NOT NULL, `column_name2` INT(11) NOT NULL, PRIMARY KEY (`column_name2`)) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;'; - $this->assertExecuteSql($expectedSql); - $this->adapter->createTable($table); - } - - public function testCreateTableUnsignedPK() - { - $column1 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column1->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column1->expects($this->any())->method('getType')->will($this->returnValue('string')); - $column1->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column1->expects($this->at(0))->method('getLimit')->will($this->returnValue('64')); - - $column2 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column2->expects($this->any())->method('getName')->will($this->returnValue('column_name2')); - $column2->expects($this->any())->method('getType')->will($this->returnValue('integer')); - $column2->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column2->expects($this->at(0))->method('getLimit')->will($this->returnValue('4')); - - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName', 'getOptions', 'getPendingColumns', 'getIndexes', 'getForeignKeys']) - ->getMock(); - - $tableOptions = ['signed' => false]; - $table->expects($this->any())->method('getPendingColumns')->will($this->returnValue([$column1, $column2])); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - $table->expects($this->any())->method('getOptions')->will($this->returnValue($tableOptions)); - $table->expects($this->any())->method('getIndexes')->will($this->returnValue([])); - $table->expects($this->any())->method('getForeignKeys')->will($this->returnValue([])); - - $expectedSql = 'CREATE TABLE `table_name` (`id` INT(11) unsigned NOT NULL AUTO_INCREMENT, `column_name` VARCHAR(255) NOT NULL, `column_name2` INT(11) NOT NULL, PRIMARY KEY (`id`)) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;'; - $this->assertExecuteSql($expectedSql); - $this->adapter->createTable($table); - } - - public function testCreateTableAdvanced() - { - $refTable = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName', 'getOptions', 'getPendingColumns', 'getIndexes', 'getForeignKeys']) - ->getMock(); - $refTable->expects($this->any())->method('getName')->will($this->returnValue('other_table')); - - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName', 'getOptions', 'getPendingColumns', 'getIndexes', 'getForeignKeys']) - ->getMock(); - - $tableOptions = ['collation' => 'latin1_swedish_ci', - 'engine' => 'MyISAM', - 'id' => ['ref_id', 'other_table_id'], - 'primary_key' => ['ref_id', 'other_table_id'], - 'comment' => "Table Comment"]; - $this->conn->expects($this->any())->method('quote')->with('Table Comment')->will($this->returnValue('`Table Comment`')); - - $column1 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column1->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column1->expects($this->any())->method('getType')->will($this->returnValue('string')); - $column1->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column1->expects($this->at(0))->method('getLimit')->will($this->returnValue('64')); - - $column2 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column2->expects($this->any())->method('getName')->will($this->returnValue('other_table_id')); - $column2->expects($this->any())->method('getType')->will($this->returnValue('integer')); - $column2->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column2->expects($this->at(0))->method('getLimit')->will($this->returnValue('4')); - - $column3 = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column3->expects($this->any())->method('getName')->will($this->returnValue('ref_id')); - $column3->expects($this->any())->method('getType')->will($this->returnValue('integer')); - $column3->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column3->expects($this->at(0))->method('getLimit')->will($this->returnValue('11')); - - $index = $this->getMockBuilder('Phinx\Db\Table\Index') - ->disableOriginalConstructor() - ->setMethods([ 'getColumns']) - ->getMock(); - - $index->expects($this->any())->method('getColumns')->will($this->returnValue(['column_name'])); - - $foreignkey = $this->getMockBuilder('Phinx\Db\Table\ForeignKey') - ->disableOriginalConstructor() - ->setMethods([ 'getColumns', - 'getConstraint', - 'getReferencedColumns', - 'getOnDelete', - 'getOnUpdate', - 'getReferencedTable']) - ->getMock(); - - $foreignkey->expects($this->any())->method('getColumns')->will($this->returnValue(['other_table_id'])); - $foreignkey->expects($this->any())->method('getConstraint')->will($this->returnValue('fk1')); - $foreignkey->expects($this->any())->method('getReferencedColumns')->will($this->returnValue(['id'])); - $foreignkey->expects($this->any())->method('getReferencedTable')->will($this->returnValue($refTable)); - $foreignkey->expects($this->any())->method('getOnDelete')->will($this->returnValue(null)); - $foreignkey->expects($this->any())->method('getOnUpdate')->will($this->returnValue(null)); - - $table->expects($this->any())->method('getPendingColumns')->will($this->returnValue([$column1, $column2, $column3])); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - $table->expects($this->any())->method('getOptions')->will($this->returnValue($tableOptions)); - $table->expects($this->any())->method('getIndexes')->will($this->returnValue([$index])); - $table->expects($this->any())->method('getForeignKeys')->will($this->returnValue([$foreignkey])); - - $expectedSql = 'CREATE TABLE `table_name` (`column_name` VARCHAR(255) NOT NULL, `other_table_id` INT(11) NOT NULL, `ref_id` INT(11) NOT NULL, PRIMARY KEY (`ref_id`,`other_table_id`), KEY (`column_name`), CONSTRAINT `fk1` FOREIGN KEY (`other_table_id`) REFERENCES `other_table` (`id`)) ENGINE = MyISAM CHARACTER SET latin1 COLLATE latin1_swedish_ci COMMENT=`Table Comment`;'; - $this->assertExecuteSql($expectedSql); - $this->adapter->createTable($table); - } - - /** - * @todo not real unit, Column class is not mocked, improve dependency of Column removing new. Could be done calling protected newColumn() and override newColumn() in tester class - * - */ - public function testGetColumns() - { - $column1 = [ - 'Field' => 'column1', - 'Type' => 'int(15)', - 'Null' => 'NO', - 'Default' => '', - 'Key' => 'PRI', - 'Extra' => 'auto_increment' - ]; - - $column2 = [ - 'Field' => 'column2', - 'Type' => 'varchar(32)', - 'Null' => '', - 'Default' => 'NULL', - 'Key' => '', - 'Extra' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($column1)); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($column2)); - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("SHOW COLUMNS FROM `table_name`", $this->result); - - $columns = $this->adapter->getColumns("table_name"); - - $this->assertInternalType('array', $columns); - $this->assertCount(2, $columns); - - $this->assertEquals('column1', $columns[0]->getName()); - $this->assertInstanceOf('Phinx\Db\Table\Column', $columns[0]); - $this->assertEquals('15', $columns[0]->getLimit()); - $this->assertFalse($columns[0]->getNull()); - $this->assertEquals('', $columns[0]->getDefault()); - $this->assertTrue($columns[0]->getIdentity()); - - $this->assertEquals('column2', $columns[1]->getName()); - $this->assertInstanceOf('Phinx\Db\Table\Column', $columns[1]); - $this->assertEquals('32', $columns[1]->getLimit()); - $this->assertTrue($columns[1]->getNull()); - $this->assertEquals('NULL', $columns[1]->getDefault()); - $this->assertFalse($columns[1]->getIdentity()); - } - - // column related tests - - public function testHasColumnExists() - { - $column1 = [ - 'Field' => 'column1', - 'Type' => 'int(15)', - 'Null' => 'NO', - 'Default' => '', - 'Extra' => 'auto_increment' - ]; - - $column2 = [ - 'Field' => 'column2', - 'Type' => 'varchar(32)', - 'Null' => '', - 'Default' => 'NULL', - 'Extra' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($column1)); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($column2)); - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql('SHOW COLUMNS FROM `table_name`', $this->result); - - $this->assertTrue($this->adapter->hasColumn('table_name', 'column1')); - } - - public function testGetColumnSqlDefinitionInteger() - { - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column->expects($this->any())->method('getLimit')->will($this->returnValue('11')); - $column->expects($this->any())->method('getType')->will($this->returnValue('integer')); - - $this->assertEquals( - "INT(11) NOT NULL", - $this->adapter->getColumnSqlDefinition($column) - ); - } - - public function testGetColumnSqlDefinitionFloat() - { - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit', 'getScale', 'getPrecision']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getType')->will($this->returnValue('float')); - $column->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column->expects($this->any())->method('getPrecision')->will($this->returnValue('8')); - $column->expects($this->any())->method('getScale')->will($this->returnValue('3')); - - $this->assertEquals( - "FLOAT(8,3) NOT NULL", - $this->adapter->getColumnSqlDefinition($column) - ); - } - - /** - * @todo must enter in code that removes limit - */ - public function testGetColumnSqlDefinitionTextWithLimit() - { - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit', 'setLimit']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getType')->will($this->returnValue('text')); - $column->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column->expects($this->at(0))->method('getLimit')->will($this->returnValue('2048')); - $column->expects($this->at(1))->method('getLimit')->will($this->returnValue(null)); - - $this->assertEquals( - "TEXT NOT NULL", - $this->adapter->getColumnSqlDefinition($column) - ); - } - - public function testGetColumnSqlDefinitionComplete() - { - $this->conn->expects($this->once()) - ->method('quote') - ->with($this->equalTo('Custom Comment')) - ->will($this->returnValue("`Custom Comment`")); - - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', - 'getAfter', - 'getType', - 'getLimit', - 'getScale', - 'getPrecision', - 'getComment', - 'isIdentity', - 'getUpdate']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column->expects($this->any())->method('isIdentity')->will($this->returnValue(true)); - $column->expects($this->any())->method('getComment')->will($this->returnValue('Custom Comment')); - $column->expects($this->any())->method('getUpdate')->will($this->returnValue('CASCADE')); - $column->expects($this->any())->method('getLimit')->will($this->returnValue('')); - $column->expects($this->any())->method('getScale')->will($this->returnValue('2')); - $column->expects($this->any())->method('getPrecision')->will($this->returnValue('8')); - $column->expects($this->any())->method('getType')->will($this->returnValue('float')); - - $this->assertEquals( - "FLOAT(8,2) NOT NULL AUTO_INCREMENT COMMENT `Custom Comment` ON UPDATE CASCADE", - $this->adapter->getColumnSqlDefinition($column) - ); - } - - public function testHasColumnExistsCaseInsensitive() - { - $column1 = [ - 'Field' => 'column1', - 'Type' => 'int(15)', - 'Null' => 'NO', - 'Default' => '', - 'Extra' => 'auto_increment' - ]; - - $column2 = [ - 'Field' => 'column2', - 'Type' => 'varchar(32)', - 'Null' => '', - 'Default' => 'NULL', - 'Extra' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($column1)); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($column2)); - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql('SHOW COLUMNS FROM `table_name`', $this->result); - - $this->assertTrue($this->adapter->hasColumn('table_name', 'CoLumN1')); - } - - public function testHasColumnNotExists() - { - $column1 = [ - 'Field' => 'column1', - 'Type' => 'int(15)', - 'Null' => 'NO', - 'Default' => '', - 'Extra' => 'auto_increment' - ]; - - $column2 = [ - 'Field' => 'column2', - 'Type' => 'varchar(32)', - 'Null' => '', - 'Default' => 'NULL', - 'Extra' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($column1)); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($column2)); - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql('SHOW COLUMNS FROM `table_name`', $this->result); - - $this->assertFalse($this->adapter->hasColumn('table_name', 'column3')); - } - - public function testDropColumn() - { - $this->assertExecuteSql("ALTER TABLE `table_name` DROP COLUMN `column1`"); - $this->adapter->dropColumn('table_name', 'column1'); - } - - public function testAddColumn() - { - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getAfter')->will($this->returnValue(null)); - $column->expects($this->any())->method('getLimit')->will($this->returnValue('11')); - $column->expects($this->any())->method('getType')->will($this->returnValue('integer')); - - $this->assertExecuteSql('ALTER TABLE `table_name` ADD `column_name` INT(11) NOT NULL'); - $this->adapter->addColumn($table, $column); - } - - public function testAddColumnWithAfter() - { - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getAfter')->will($this->returnValue('column_name2')); - $column->expects($this->any())->method('getLimit')->will($this->returnValue('11')); - $column->expects($this->any())->method('getType')->will($this->returnValue('integer')); - - $this->assertExecuteSql('ALTER TABLE `table_name` ADD `column_name` INT(11) NOT NULL AFTER `column_name2`'); - $this->adapter->addColumn($table, $column); - } - - public function testChangeColumn() - { - $column = $this->getMockBuilder('Phinx\Db\Table\Column') - ->disableOriginalConstructor() - ->setMethods([ 'getName', 'getAfter', 'getType', 'getLimit']) - ->getMock(); - - $column->expects($this->any())->method('getName')->will($this->returnValue('column_name')); - $column->expects($this->any())->method('getLimit')->will($this->returnValue('11')); - $column->expects($this->any())->method('getType')->will($this->returnValue('integer')); - - $this->assertExecuteSql('ALTER TABLE `table_name` CHANGE `column1` `column_name` INT(11) NOT NULL'); - $this->adapter->changeColumn('table_name', 'column1', $column); - } - - public function testRenameColumnExists() - { - $column1 = [ - 'Field' => 'column_old', - 'Type' => 'int(15)', - 'Null' => 'NO', - 'Default' => '', - 'Extra' => 'auto_increment' - ]; - - $column2 = [ - 'Field' => 'column2', - 'Type' => 'varchar(32)', - 'Null' => '', - 'Default' => 'NULL', - 'Extra' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($column1)); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($column2)); - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("DESCRIBE `table_name`", $this->result); - - $this->assertExecuteSql('ALTER TABLE `table_name` CHANGE COLUMN `column_old` `column_new` int(15) NOT NULL AUTO_INCREMENT'); - $this->adapter->renameColumn('table_name', 'column_old', 'column_new'); - } - - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage The specified column doesn't exist: column_old - */ - public function testRenameColumnNotExists() - { - $column1 = [ - 'Field' => 'column1', - 'Type' => 'int(15)', - 'Null' => 'NO', - 'Default' => '', - 'Extra' => 'auto_increment' - ]; - - $column2 = [ - 'Field' => 'column2', - 'Type' => 'varchar(32)', - 'Null' => '', - 'Default' => 'NULL', - 'Extra' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($column1)); - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($column2)); - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("DESCRIBE `table_name`", $this->result); - - $this->adapter->renameColumn('table_name', 'column_old', 'column_new'); - } - - public function testGetDefaultValueDefinitionEmpty() - { - $this->assertEquals('', $this->adapter->getDefaultValueDefinition(null)); - $this->assertEquals('', $this->adapter->getDefaultValueDefinition('NULL')); - } - - public function testGetDefaultValueDefinitionBoolean() - { - $this->assertEquals( - ' DEFAULT 1', - $this->adapter->getDefaultValueDefinition(true) - ); - } - - public function testGetDefaultValueDefinitionInteger() - { - $this->assertEquals( - ' DEFAULT 5', - $this->adapter->getDefaultValueDefinition(5) - ); - } - - public function testGetDefaultValueDefinitionCurrentTimestamp() - { - $this->assertEquals( - ' DEFAULT CURRENT_TIMESTAMP', - $this->adapter->getDefaultValueDefinition('CURRENT_TIMESTAMP') - ); - } - - public function testGetDefaultValueDefinitionString() - { - $this->conn->expects($this->once()) - ->method('quote') - ->with($this->equalTo('str')) - ->will($this->returnValue("`str`")); - $this->assertEquals(' DEFAULT `str`', $this->adapter->getDefaultValueDefinition('str')); - } - - public function testGetSqlTypeExists() - { - $this->assertEquals( - ['name' => 'varchar', 'limit' => 255], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_STRING) - ); - $this->assertEquals( - ['name' => 'char', 'limit' => 255], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_CHAR, 255) - ); - - //text combinations - $this->assertEquals( - ['name' => 'text'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT) - ); - $this->assertEquals( - ['name' => 'tinytext'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_TINY) - ); - $this->assertEquals( - ['name' => 'tinytext'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_TINY + 1) - ); - $this->assertEquals( - ['name' => 'text'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_REGULAR) - ); - $this->assertEquals( - ['name' => 'text'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_REGULAR + 1) - ); - $this->assertEquals( - ['name' => 'mediumtext'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_MEDIUM) - ); - $this->assertEquals( - ['name' => 'mediumtext'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_MEDIUM + 1) - ); - $this->assertEquals( - ['name' => 'longtext'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_LONG) - ); - $this->assertEquals( - ['name' => 'longtext'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TEXT, MysqlAdapter::TEXT_LONG + 1) - ); - - //blob combinations - $this->assertEquals( - ['name' => 'blob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB) - ); - $this->assertEquals( - ['name' => 'tinyblob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_TINY) - ); - $this->assertEquals( - ['name' => 'tinyblob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_TINY + 1) - ); - $this->assertEquals( - ['name' => 'blob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_REGULAR) - ); - $this->assertEquals( - ['name' => 'blob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_REGULAR + 1) - ); - $this->assertEquals( - ['name' => 'mediumblob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_MEDIUM) - ); - $this->assertEquals( - ['name' => 'mediumblob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_MEDIUM + 1) - ); - $this->assertEquals( - ['name' => 'longblob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_LONG) - ); - $this->assertEquals( - ['name' => 'longblob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB, MysqlAdapter::BLOB_LONG + 1) - ); - - $this->assertEquals( - ['name' => 'binary', 'limit' => 255], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BINARY) - ); - $this->assertEquals( - ['name' => 'binary', 'limit' => 36], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BINARY, 36) - ); - - $this->assertEquals( - ['name' => 'varbinary', 'limit' => 255], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_VARBINARY) - ); - $this->assertEquals( - ['name' => 'varbinary', 'limit' => 16], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_VARBINARY, 16) - ); - - //int combinations - $this->assertEquals( - ['name' => 'int', 'limit' => 11], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER) - ); - $this->assertEquals( - ['name' => 'bigint', 'limit' => 20], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BIG_INTEGER) - ); - $this->assertEquals( - ['name' => 'tinyint'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_TINY) - ); - $this->assertEquals( - ['name' => 'tinyint'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_TINY + 1) - ); - $this->assertEquals( - ['name' => 'smallint'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_SMALL) - ); - $this->assertEquals( - ['name' => 'smallint'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_SMALL + 1) - ); - $this->assertEquals( - ['name' => 'mediumint'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_MEDIUM) - ); - $this->assertEquals( - ['name' => 'mediumint'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_MEDIUM + 1) - ); - $this->assertEquals( - ['name' => 'int', 'limit' => 11], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_REGULAR) - ); - $this->assertEquals( - ['name' => 'int', 'limit' => 11], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_REGULAR + 1) - ); - $this->assertEquals( - ['name' => 'bigint', 'limit' => 20], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_BIG) - ); - $this->assertEquals( - ['name' => 'bigint', 'limit' => 20], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_INTEGER, MysqlAdapter::INT_BIG + 1) - ); - - $this->assertEquals( - ['name' => 'float'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_FLOAT) - ); - $this->assertEquals( - ['name' => 'decimal'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_DECIMAL) - ); - $this->assertEquals( - ['name' => 'datetime'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_DATETIME) - ); - $this->assertEquals( - ['name' => 'timestamp'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TIMESTAMP) - ); - $this->assertEquals( - ['name' => 'date'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_DATE) - ); - $this->assertEquals( - ['name' => 'time'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_TIME) - ); - $this->assertEquals( - ['name' => 'blob'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BLOB) - ); - $this->assertEquals( - ['name' => 'tinyint', 'limit' => 1], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_BOOLEAN) - ); - $this->assertEquals( - ['name' => 'geometry'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_GEOMETRY) - ); - $this->assertEquals( - ['name' => 'linestring'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_LINESTRING) - ); - $this->assertEquals( - ['name' => 'point'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_POINT) - ); - $this->assertEquals( - ['name' => 'polygon'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_POLYGON) - ); - $this->assertEquals( - ['name' => 'enum'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_ENUM) - ); - $this->assertEquals( - ['name' => 'set'], - $this->adapter->getSqlType(MysqlAdapter::PHINX_TYPE_SET) - ); - } - - /** - * @expectedException RuntimeException - * @expectedExceptionMessage The type: "fake" is not supported. - */ - public function testGetSqlTypeNotExists() - { - $this->adapter->getSqlType('fake'); - } - - public function testPhinxTypeExistsWithoutLimit() - { - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_STRING, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('varchar') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_CHAR, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('char') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_INTEGER, 'limit' => MysqlAdapter::INT_TINY, 'precision' => null], - $this->adapter->getPhinxType('tinyint') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_INTEGER, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('int') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_INTEGER, 'limit' => MysqlAdapter::INT_SMALL, 'precision' => null], - $this->adapter->getPhinxType('smallint') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_INTEGER, 'limit' => MysqlAdapter::INT_MEDIUM, 'precision' => null], - $this->adapter->getPhinxType('mediumint') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BIG_INTEGER, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('bigint') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BINARY, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('blob') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_VARBINARY, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('varbinary') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_FLOAT, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('float') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_DECIMAL, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('decimal') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_DATETIME, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('datetime') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TIMESTAMP, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('timestamp') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_DATE, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('date') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TIME, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('time') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TEXT, 'limit' => MysqlAdapter::TEXT_TINY, 'precision' => null], - $this->adapter->getPhinxType('tinytext') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TEXT, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('text') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TEXT, 'limit' => MysqlAdapter::TEXT_MEDIUM, 'precision' => null], - $this->adapter->getPhinxType('mediumtext') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TEXT, 'limit' => MysqlAdapter::TEXT_LONG, 'precision' => null], - $this->adapter->getPhinxType('longtext') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BINARY, 'limit' => MysqlAdapter::BLOB_TINY, 'precision' => null], - $this->adapter->getPhinxType('tinyblob') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BINARY, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('blob') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BINARY, 'limit' => MysqlAdapter::BLOB_MEDIUM, 'precision' => null], - $this->adapter->getPhinxType('mediumblob') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BINARY, 'limit' => MysqlAdapter::BLOB_LONG, 'precision' => null], - $this->adapter->getPhinxType('longblob') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_POINT, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('point') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_GEOMETRY, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('geometry') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_LINESTRING, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('linestring') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_POLYGON, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('polygon') - ); - } - - public function testPhinxTypeExistsWithLimit() - { - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_STRING, 'limit' => 32, 'precision' => null], - $this->adapter->getPhinxType('varchar(32)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_CHAR, 'limit' => 32, 'precision' => null], - $this->adapter->getPhinxType('char(32)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_INTEGER, 'limit' => 12, 'precision' => null], - $this->adapter->getPhinxType('int(12)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BIG_INTEGER, 'limit' => 21, 'precision' => null], - $this->adapter->getPhinxType('bigint(21)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BINARY, 'limit' => 1024, 'precision' => null], - $this->adapter->getPhinxType('blob(1024)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_VARBINARY, 'limit' => 16, 'precision' => null], - $this->adapter->getPhinxType('varbinary(16)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_FLOAT, 'limit' => 8, 'precision' => 2], - $this->adapter->getPhinxType('float(8,2)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_DECIMAL, 'limit' => 8, 'precision' => 2], - $this->adapter->getPhinxType('decimal(8,2)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_TEXT, 'limit' => 1024, 'precision' => null], - $this->adapter->getPhinxType('text(1024)') - ); - } - - public function testPhinxTypeExistsWithLimitNull() - { - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_STRING, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('varchar(255)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_CHAR, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('char(255)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_INTEGER, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('int(11)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BIG_INTEGER, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('bigint(20)') - ); - $this->assertEquals( - ['name' => MysqlAdapter::PHINX_TYPE_BOOLEAN, 'limit' => null, 'precision' => null], - $this->adapter->getPhinxType('tinyint(1)') - ); - } - - /** - * @expectedException RuntimeException - * @expectedExceptionMessage The type: "fake" is not supported. - */ - public function testPhinxTypeNotValidType() - { - $this->adapter->getPhinxType('fake'); - } - - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Column type ?int? is not supported - */ - public function testPhinxTypeNotValidTypeRegex() - { - $this->adapter->getPhinxType('?int?'); - } - - //index related tests - - public function testGetIndexSqlDefinitionRegular() - { - $index = $this->getMockBuilder('Phinx\Db\Table\Index') - ->disableOriginalConstructor() - ->setMethods([ 'getColumns', 'getName', 'getType']) - ->getMock(); - - $index->expects($this->any())->method('getColumns')->will($this->returnValue(['column_name'])); - $index->expects($this->any())->method('getName')->will($this->returnValue('index_name')); - $index->expects($this->any())->method('getType')->will($this->returnValue(\Phinx\Db\Table\Index::INDEX)); - $this->assertEquals(' KEY `index_name` (`column_name`)', $this->adapter->getIndexSqlDefinition($index)); - } - - public function testGetIndexSqlDefinitionUnique() - { - $index = $this->getMockBuilder('Phinx\Db\Table\Index') - ->disableOriginalConstructor() - ->setMethods([ 'getColumns', 'getName', 'getType']) - ->getMock(); - - $index->expects($this->any())->method('getColumns')->will($this->returnValue(['column_name'])); - $index->expects($this->any())->method('getName')->will($this->returnValue('index_name')); - $index->expects($this->any())->method('getType')->will($this->returnValue(\Phinx\Db\Table\Index::UNIQUE)); - $this->assertEquals(' UNIQUE KEY `index_name` (`column_name`)', $this->adapter->getIndexSqlDefinition($index)); - } - - public function testGetIndexesEmpty() - { - $this->result->expects($this->once()) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("SHOW INDEXES FROM `table_name`", $this->result); - - $indexes = $this->adapter->getIndexes("table_name"); - - $this->assertEquals([], $indexes); - } - - private function prepareCaseIndexes() - { - $index1 = [ - 'Table' => 'table_name', - 'Non_unique' => '0', - 'Key_name' => 'PRIMARY', - 'Seq_in_index' => '1', - 'Column_name' => 'id', - 'Collation' => 'A', - 'Cardinality' => '0', - 'Sub_part' => 'NULL', - 'Packed' => 'NULL', - 'Null' => '', - 'Index_type' => 'BTREE', - 'Comment' => '', - 'Index_comment' => '' - ]; - - $index2 = [ - 'Table' => 'table_name', - 'Non_unique' => '0', - 'Key_name' => 'index_name', - 'Seq_in_index' => '1', - 'Column_name' => 'column_name', - 'Collation' => 'A', - 'Cardinality' => '0', - 'Sub_part' => 'NULL', - 'Packed' => 'NULL', - 'Null' => '', - 'Index_type' => 'BTREE', - 'Comment' => '', - 'Index_comment' => '' - ]; - - $index3 = [ - 'Table' => 'table_name', - 'Non_unique' => '0', - 'Key_name' => 'multiple_index_name', - 'Seq_in_index' => '1', - 'Column_name' => 'column_name', - 'Collation' => 'A', - 'Cardinality' => '0', - 'Sub_part' => 'NULL', - 'Packed' => 'NULL', - 'Null' => '', - 'Index_type' => 'BTREE', - 'Comment' => '', - 'Index_comment' => '' - ]; - - $index4 = [ - 'Table' => 'table_name', - 'Non_unique' => '0', - 'Key_name' => 'multiple_index_name', - 'Seq_in_index' => '2', - 'Column_name' => 'another_column_name', - 'Collation' => 'A', - 'Cardinality' => '0', - 'Sub_part' => 'NULL', - 'Packed' => 'NULL', - 'Null' => '', - 'Index_type' => 'BTREE', - 'Comment' => '', - 'Index_comment' => '' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($index1)); - - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($index2)); - - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue($index3)); - - $this->result->expects($this->at(3)) - ->method('fetch') - ->will($this->returnValue($index4)); - - $this->result->expects($this->at(4)) - ->method('fetch') - ->will($this->returnValue(null)); - - $this->assertQuerySql("SHOW INDEXES FROM `table_name`", $this->result); - - return [$index1, $index2, $index3, $index4]; - } - - public function testGetIndexes() - { - list($index1, $index2, $index3, $index4) = $this->prepareCaseIndexes(); - $indexes = $this->adapter->getIndexes("table_name"); - - $this->assertInternalType('array', $indexes); - $this->assertCount(3, $indexes); - $this->assertEquals(['columns' => [$index1['Column_name']]], $indexes[$index1['Key_name']]); - $this->assertEquals(['columns' => [$index2['Column_name']]], $indexes[$index2['Key_name']]); - $this->assertEquals(['columns' => [$index3['Column_name'], $index4['Column_name']]], $indexes[$index3['Key_name']]); - } - - public function testHasIndexExistsAsString() - { - $this->prepareCaseIndexes(); - $this->assertTrue($this->adapter->hasIndex("table_name", "column_name")); - } - - public function testHasIndexNotExistsAsString() - { - $this->prepareCaseIndexes(); - $this->assertFalse($this->adapter->hasIndex("table_name", "another_column_name")); - } - - public function testHasIndexExistsAsArray() - { - $this->prepareCaseIndexes(); - $this->assertTrue($this->adapter->hasIndex("table_name", ["column_name"])); - } - - public function testHasIndexNotExistsAsArray() - { - $this->prepareCaseIndexes(); - $this->assertFalse($this->adapter->hasIndex("table_name", ["another_column_name"])); - } - - public function testAddIndex() - { - list($table, $index) = $this->prepareAddIndex(['getColumns']); - - $this->assertExecuteSql('ALTER TABLE `table_name` ADD KEY (`column_name`)'); - $this->adapter->addIndex($table, $index); - } - - public function testAddIndexWithLimit() - { - list($table, $index) = $this->prepareAddIndex(['getColumns', 'getLimit']); - $index->expects($this->any())->method('getLimit')->will($this->returnValue(50)); - - $this->assertExecuteSql('ALTER TABLE `table_name` ADD KEY (`column_name`(50))'); - $this->adapter->addIndex($table, $index); - } - - /** - * @param array $methods - * @return array - */ - private function prepareAddIndex($methods) - { - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - - $index = $this->getMockBuilder('Phinx\Db\Table\Index') - ->disableOriginalConstructor() - ->setMethods($methods) - ->getMock(); - - $index->expects($this->any())->method('getColumns')->will($this->returnValue(['column_name'])); - - return [$table, $index]; - } - - public function testDropIndexAsString() - { - $this->prepareCaseIndexes(); - $this->assertExecuteSql('ALTER TABLE `table_name` DROP INDEX `index_name`'); - $this->adapter->dropIndex('table_name', 'column_name'); - } - - public function testDropIndexAsArray() - { - $this->prepareCaseIndexes(); - $this->assertExecuteSql('ALTER TABLE `table_name` DROP INDEX `index_name`'); - $this->adapter->dropIndex('table_name', ['column_name']); - } - - public function testDropIndexByName() - { - $this->prepareCaseIndexes(); - $this->assertExecuteSql('ALTER TABLE `table_name` DROP INDEX `index_name`'); - $this->adapter->dropIndexByName('table_name', 'index_name'); - } - - //foregnkey related tests - - private function prepareCaseForeignKeys() - { - $fk = [ - 'CONSTRAINT_NAME' => 'fk1', - 'TABLE_NAME' => 'table_name', - 'COLUMN_NAME' => 'other_table_id', - 'REFERENCED_TABLE_NAME' => 'other_table', - 'REFERENCED_COLUMN_NAME' => 'id' - ]; - - $fk1 = [ - 'CONSTRAINT_NAME' => 'fk2', - 'TABLE_NAME' => 'table_name', - 'COLUMN_NAME' => 'other_table_id', - 'REFERENCED_TABLE_NAME' => 'other_table', - 'REFERENCED_COLUMN_NAME' => 'id' - ]; - - $fk2 = [ - 'CONSTRAINT_NAME' => 'fk2', - 'TABLE_NAME' => 'table_name', - 'COLUMN_NAME' => 'another_table_id', - 'REFERENCED_TABLE_NAME' => 'other_table', - 'REFERENCED_COLUMN_NAME' => 'id' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($fk)); - - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue($fk1)); - - $this->result->expects($this->at(2)) - ->method('fetch') - ->will($this->returnValue($fk2)); - - $this->result->expects($this->at(3)) - ->method('fetch') - ->will($this->returnValue(null)); - - $expectedSql = 'SELECT - CONSTRAINT_NAME, - TABLE_NAME, - COLUMN_NAME, - REFERENCED_TABLE_NAME, - REFERENCED_COLUMN_NAME - FROM information_schema.KEY_COLUMN_USAGE - WHERE REFERENCED_TABLE_SCHEMA = DATABASE() - AND REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_NAME = \'table_name\' - ORDER BY POSITION_IN_UNIQUE_CONSTRAINT'; - $this->assertQuerySql($expectedSql, $this->result); - - return [$fk, $fk1, $fk2]; - } - - public function testGetForeignKeys() - { - list($fk, $fk1, $fk2) = $this->prepareCaseForeignKeys(); - $foreignkeys = $this->adapter->getForeignKeys("table_name"); - - $this->assertInternalType('array', $foreignkeys); - $this->assertCount(2, $foreignkeys); - $this->assertEquals('table_name', $foreignkeys['fk1']['table']); - $this->assertEquals(['other_table_id'], $foreignkeys['fk1']['columns']); - $this->assertEquals('other_table', $foreignkeys['fk1']['referenced_table']); - $this->assertEquals(['id'], $foreignkeys['fk1']['referenced_columns']); - } - - public function testHasForeignKeyExistsAsString() - { - $this->prepareCaseForeignKeys(); - $this->assertTrue($this->adapter->hasForeignKey("table_name", "other_table_id")); - } - - public function testHasForeignKeyExistsAsStringAndConstraint() - { - $this->prepareCaseForeignKeys(); - $this->assertTrue($this->adapter->hasForeignKey("table_name", "other_table_id", 'fk1')); - } - - public function testHasForeignKeyNotExistsAsString() - { - $this->prepareCaseForeignKeys(); - $this->assertFalse($this->adapter->hasForeignKey("table_name", "another_table_id")); - } - - public function testHasForeignKeyNotExistsAsStringAndConstraint() - { - $this->prepareCaseForeignKeys(); - $this->assertFalse($this->adapter->hasForeignKey("table_name", "other_table_id", 'fk3')); - } - - public function testHasForeignKeyExistsAsArray() - { - $this->prepareCaseForeignKeys(); - $this->assertTrue($this->adapter->hasForeignKey("table_name", ["other_table_id"])); - } - - public function testHasForeignKeyExistsAsArrayAndConstraint() - { - $this->prepareCaseForeignKeys(); - $this->assertTrue($this->adapter->hasForeignKey("table_name", ["other_table_id"], 'fk1')); - } - - public function testHasForeignKeyNotExistsAsArray() - { - $this->prepareCaseForeignKeys(); - $this->assertFalse($this->adapter->hasForeignKey("table_name", ["another_table_id"])); - } - - public function testHasForeignKeyNotExistsAsArrayAndConstraint() - { - $this->prepareCaseForeignKeys(); - $this->assertFalse($this->adapter->hasForeignKey("table_name", ["other_table_id"], 'fk3')); - } - - public function testAddForeignKeyBasic() - { - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - - $refTable = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $refTable->expects($this->any())->method('getName')->will($this->returnValue('other_table')); - - $foreignkey = $this->getMockBuilder('Phinx\Db\Table\ForeignKey') - ->disableOriginalConstructor() - ->setMethods([ 'getColumns', - 'getConstraint', - 'getReferencedColumns', - 'getOnDelete', - 'getOnUpdate', - 'getReferencedTable']) - ->getMock(); - - $foreignkey->expects($this->any())->method('getColumns')->will($this->returnValue(['other_table_id'])); - $foreignkey->expects($this->any())->method('getConstraint')->will($this->returnValue('fk1')); - $foreignkey->expects($this->any())->method('getReferencedColumns')->will($this->returnValue(['id'])); - $foreignkey->expects($this->any())->method('getReferencedTable')->will($this->returnValue($refTable)); - $foreignkey->expects($this->any())->method('getOnDelete')->will($this->returnValue(null)); - $foreignkey->expects($this->any())->method('getOnUpdate')->will($this->returnValue(null)); - - $this->assertExecuteSql('ALTER TABLE `table_name` ADD CONSTRAINT `fk1` FOREIGN KEY (`other_table_id`) REFERENCES `other_table` (`id`)'); - $this->adapter->addForeignKey($table, $foreignkey); - } - - public function testAddForeignKeyComplete() - { - $table = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $table->expects($this->any())->method('getName')->will($this->returnValue('table_name')); - - $refTable = $this->getMockBuilder('Phinx\Db\Table') - ->disableOriginalConstructor() - ->setMethods(['getName']) - ->getMock(); - $refTable->expects($this->any())->method('getName')->will($this->returnValue('other_table')); - - $foreignkey = $this->getMockBuilder('Phinx\Db\Table\ForeignKey') - ->disableOriginalConstructor() - ->setMethods([ 'getColumns', - 'getConstraint', - 'getReferencedColumns', - 'getOnDelete', - 'getOnUpdate', - 'getReferencedTable']) - ->getMock(); - - $foreignkey->expects($this->any())->method('getColumns')->will($this->returnValue(['other_table_id'])); - $foreignkey->expects($this->any())->method('getConstraint')->will($this->returnValue('fk1')); - $foreignkey->expects($this->any())->method('getReferencedColumns')->will($this->returnValue(['id'])); - $foreignkey->expects($this->any())->method('getReferencedTable')->will($this->returnValue($refTable)); - $foreignkey->expects($this->any())->method('getOnDelete')->will($this->returnValue('CASCADE')); - $foreignkey->expects($this->any())->method('getOnUpdate')->will($this->returnValue('CASCADE')); - - $this->assertExecuteSql('ALTER TABLE `table_name` ADD CONSTRAINT `fk1` FOREIGN KEY (`other_table_id`) REFERENCES `other_table` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); - $this->adapter->addForeignKey($table, $foreignkey); - } - - public function testDropForeignKeyAsString() - { - $fk = [ - 'CONSTRAINT_NAME' => 'fk1', - 'TABLE_NAME' => 'table_name', - 'COLUMN_NAME' => 'other_table_id', - 'REFERENCED_TABLE_NAME' => 'other_table', - 'REFERENCED_COLUMN_NAME' => 'id' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($fk)); - - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue(null)); - - $expectedSql = 'SELECT - CONSTRAINT_NAME - FROM information_schema.KEY_COLUMN_USAGE - WHERE REFERENCED_TABLE_SCHEMA = DATABASE() - AND REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_NAME = \'table_name\' - AND COLUMN_NAME = \'column_name\' - ORDER BY POSITION_IN_UNIQUE_CONSTRAINT'; - $this->assertQuerySql($expectedSql, $this->result); - - $this->assertExecuteSql('ALTER TABLE `table_name` DROP FOREIGN KEY fk1'); - $this->adapter->dropForeignKey('table_name', 'column_name'); - } - - public function _testDropForeignKeyAsArray() - { - $fk = [ - 'CONSTRAINT_NAME' => 'fk1', - 'TABLE_NAME' => 'table_name', - 'COLUMN_NAME' => 'other_table_id', - 'REFERENCED_TABLE_NAME' => 'other_table', - 'REFERENCED_COLUMN_NAME' => 'id' - ]; - - $this->result->expects($this->at(0)) - ->method('fetch') - ->will($this->returnValue($fk)); - - $this->result->expects($this->at(1)) - ->method('fetch') - ->will($this->returnValue(null)); - - $expectedSql = 'SELECT - CONSTRAINT_NAME - FROM information_schema.KEY_COLUMN_USAGE - WHERE REFERENCED_TABLE_SCHEMA = DATABASE() - AND REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_NAME = \'table_name\' - AND COLUMN_NAME = \'column_name\' - ORDER BY POSITION_IN_UNIQUE_CONSTRAINT'; - $this->assertQuerySql($expectedSql, $this->result); - - $this->assertExecuteSql('ALTER TABLE `table_name` DROP FOREIGN KEY fk1'); - $this->adapter->dropForeignKey('table_name', ['column_name']); - } - - public function testDropForeignKeyAsStringByConstraint() - { - $this->assertExecuteSql('ALTER TABLE `table_name` DROP FOREIGN KEY fk1'); - $this->adapter->dropForeignKey('table_name', 'column_name', 'fk1'); - } - - public function _testDropForeignKeyAsArrayByConstraint() - { - $this->assertExecuteSql('ALTER TABLE `table_name` DROP FOREIGN KEY fk1'); - $this->adapter->dropForeignKey('table_name', ['column_name'], 'fk1'); - } -} diff --git a/tests/Phinx/Db/Adapter/PostgresAdapterTest.php b/tests/Phinx/Db/Adapter/PostgresAdapterTest.php index a1571a971..66676a3e3 100644 --- a/tests/Phinx/Db/Adapter/PostgresAdapterTest.php +++ b/tests/Phinx/Db/Adapter/PostgresAdapterTest.php @@ -234,7 +234,8 @@ public function testRenameTable() $table->save(); $this->assertTrue($this->adapter->hasTable('table1')); $this->assertFalse($this->adapter->hasTable('table2')); - $this->adapter->renameTable('table1', 'table2'); + + $table->rename('table2')->save(); $this->assertFalse($this->adapter->hasTable('table1')); $this->assertTrue($this->adapter->hasTable('table2')); } @@ -432,23 +433,15 @@ public function testChangeColumn() $table->addColumn('column1', 'string') ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); - $newColumn1 = new \Phinx\Db\Table\Column(); - $newColumn1->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', 'string')->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); + $newColumn2 = new \Phinx\Db\Table\Column(); $newColumn2->setName('column2') - ->setType('string') - ->setNull(true); - $table->changeColumn('column1', $newColumn2); + ->setType('string'); + $table->changeColumn('column1', $newColumn2)->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); $this->assertTrue($this->adapter->hasColumn('t', 'column2')); - $columns = $this->adapter->getColumns('t'); - foreach ($columns as $column) { - if ($column->getName() == 'column2') { - $this->assertTrue($column->isNull()); - } - } } public function testChangeColumnWithDefault() @@ -463,7 +456,7 @@ public function testChangeColumnWithDefault() ->setNull(true); $newColumn1->setDefault('Test'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $columns = $this->adapter->getColumns('t'); foreach ($columns as $column) { @@ -491,7 +484,7 @@ public function testChangeColumnWithDropDefault() $newColumn1->setName('column1') ->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $columns = $this->adapter->getColumns('t'); foreach ($columns as $column) { @@ -507,37 +500,57 @@ public function testDropColumn() $table->addColumn('column1', 'string') ->save(); $this->assertTrue($this->adapter->hasColumn('t', 'column1')); - $this->adapter->dropColumn('t', 'column1'); + + $table->removeColumn('column1')->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); } - public function testGetColumns() + public function columnsProvider() + { + return [ + ['column1', 'string', []], + ['column2', 'integer', ['limit' => PostgresAdapter::INT_SMALL], 'smallint'], + ['column2_1', 'integer', []], + ['column3', 'biginteger', []], + ['column4', 'text', []], + ['column5', 'float', []], + ['column6', 'decimal', []], + ['column7', 'datetime', []], + ['column8', 'time', []], + ['column9', 'timestamp', [], 'datetime'], + ['column10', 'date', []], + ['column11', 'binary', []], + ['column12', 'boolean', []], + ['column13', 'string', ['limit' => 10]], + ['column16', 'interval', []], + ]; + } + + /** + * + * @dataProvider columnsProvider + */ + public function testGetColumns($colName, $type, $options, $actualType = null) { $table = new \Phinx\Db\Table('t', [], $this->adapter); - $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer', ['limit' => PostgresAdapter::INT_SMALL]) - ->addColumn('column3', 'integer') - ->addColumn('column4', 'biginteger') - ->addColumn('column5', 'text') - ->addColumn('column6', 'float') - ->addColumn('column7', 'decimal') - ->addColumn('column8', 'time') - ->addColumn('column9', 'timestamp') - ->addColumn('column10', 'date') - ->addColumn('column11', 'boolean') - ->addColumn('column12', 'datetime') - ->addColumn('column13', 'binary') - ->addColumn('column14', 'string', ['limit' => 10]) - ->addColumn('column15', 'interval'); - $pendingColumns = $table->getPendingColumns(); - $table->save(); + $table->addColumn($colName, $type, $options)->save(); + $columns = $this->adapter->getColumns('t'); - $this->assertCount(count($pendingColumns) + 1, $columns); - for ($i = 0; $i++; $i < count($pendingColumns)) { - $this->assertEquals($pendingColumns[$i], $columns[$i + 1]); + $this->assertCount(2, $columns); + $this->assertEquals($colName, $columns[1]->getName()); + + if (!$actualType) { + $actualType = $type; + } + + if (is_string($columns[1]->getType())) { + $this->assertEquals($actualType, $columns[1]->getType()); + } else { + $this->assertEquals(['name' => $actualType] + $options, $columns[1]->getType()); } } + public function testAddIndex() { $table = new \Phinx\Db\Table('table1', [], $this->adapter); @@ -632,16 +645,12 @@ public function testAddForeignKey() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']) - ->setConstraint('fk1'); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'], 'fk1')); + $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } public function testDropForeignKey() @@ -650,16 +659,12 @@ public function testDropForeignKey() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); - $this->adapter->addForeignKey($table, $fk); - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); - $this->adapter->dropForeignKey($table->getName(), ['ref_table_id']); + $table->dropForeignKey(['ref_table_id'])->save(); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -981,28 +986,36 @@ public function testTimestampWithTimezone() public function testBulkInsertData() { + $data = [ + [ + 'column1' => 'value1', + 'column2' => 1, + ], + [ + 'column1' => 'value2', + 'column2' => 2, + ], + [ + 'column1' => 'value3', + 'column2' => 3, + ] + ]; $table = new \Phinx\Db\Table('table1', [], $this->adapter); $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->insert([ - [ - 'column1' => 'value1', - 'column2' => 1 - ], - [ - 'column1' => 'value2', - 'column2' => 2 - ] - ]); - $this->adapter->createTable($table); - $this->adapter->bulkinsert($table, $table->getData()); - $table->reset(); + ->addColumn('column2', 'integer') + ->addColumn('column3', 'string', ['default' => 'test']) + ->insert($data) + ->save(); $rows = $this->adapter->fetchAll('SELECT * FROM table1'); $this->assertEquals('value1', $rows[0]['column1']); $this->assertEquals('value2', $rows[1]['column1']); + $this->assertEquals('value3', $rows[2]['column1']); $this->assertEquals(1, $rows[0]['column2']); $this->assertEquals(2, $rows[1]['column2']); + $this->assertEquals(3, $rows[2]['column2']); + $this->assertEquals('test', $rows[0]['column3']); + $this->assertEquals('test', $rows[2]['column3']); } public function testInsertData() diff --git a/tests/Phinx/Db/Adapter/ProxyAdapterTest.php b/tests/Phinx/Db/Adapter/ProxyAdapterTest.php index 02f6b678d..c88723849 100644 --- a/tests/Phinx/Db/Adapter/ProxyAdapterTest.php +++ b/tests/Phinx/Db/Adapter/ProxyAdapterTest.php @@ -21,8 +21,13 @@ public function setUp() { $stub = $this->getMockBuilder('\Phinx\Db\Adapter\PdoAdapter') ->setConstructorArgs([[]]) + ->setMethods([]) ->getMock(); + $stub->expects($this->any()) + ->method('isValidColumnType') + ->will($this->returnValue(true)); + $this->adapter = new ProxyAdapter($stub); } @@ -33,88 +38,114 @@ public function tearDown() public function testProxyAdapterCanInvertCreateTable() { - $table = new \Phinx\Db\Table('atable'); - $this->adapter->createTable($table); + $table = new \Phinx\Db\Table('atable', [], $this->adapter); + $table->addColumn('column1', 'string') + ->save(); - $commands = $this->adapter->getInvertedCommands(); - $this->assertEquals('dropTable', $commands[0]['name']); - $this->assertEquals('atable', $commands[0]['arguments'][0]); + $commands = $this->adapter->getInvertedCommands()->getActions(); + $this->assertInstanceOf('Phinx\Db\Action\DropTable', $commands[0]); + $this->assertEquals('atable', $commands[0]->getTable()->getName()); } public function testProxyAdapterCanInvertRenameTable() { - $this->adapter->renameTable('oldname', 'newname'); - - $commands = $this->adapter->getInvertedCommands(); - $this->assertEquals('renameTable', $commands[0]['name']); - $this->assertEquals('newname', $commands[0]['arguments'][0]); - $this->assertEquals('oldname', $commands[0]['arguments'][1]); + $table = new \Phinx\Db\Table('oldname', [], $this->adapter); + $table->rename('newname') + ->save(); + + $commands = $this->adapter->getInvertedCommands()->getActions(); + $this->assertInstanceOf('Phinx\Db\Action\RenameTable', $commands[0]); + $this->assertEquals('newname', $commands[0]->getTable()->getName()); + $this->assertEquals('oldname', $commands[0]->getNewName()); } public function testProxyAdapterCanInvertAddColumn() { - $table = new \Phinx\Db\Table('atable'); - $column = new \Phinx\Db\Table\Column(); - $column->setName('acolumn'); - - $this->adapter->addColumn($table, $column); - - $commands = $this->adapter->getInvertedCommands(); - $this->assertEquals('dropColumn', $commands[0]['name']); - $this->assertEquals('atable', $commands[0]['arguments'][0]); - $this->assertContains('acolumn', $commands[0]['arguments'][1]); + $this->adapter + ->getAdapter() + ->expects($this->any()) + ->method('hasTable') + ->will($this->returnValue(true)); + $table = new \Phinx\Db\Table('atable', [], $this->adapter); + $table->addColumn('acolumn', 'string') + ->save(); + + $commands = $this->adapter->getInvertedCommands()->getActions(); + $this->assertInstanceOf('Phinx\Db\Action\RemoveColumn', $commands[0]); + $this->assertEquals('atable', $commands[0]->getTable()->getName()); + $this->assertEquals('acolumn', $commands[0]->getColumn()->getName()); } public function testProxyAdapterCanInvertRenameColumn() { - $this->adapter->renameColumn('atable', 'oldname', 'newname'); - - $commands = $this->adapter->getInvertedCommands(); - $this->assertEquals('renameColumn', $commands[0]['name']); - $this->assertEquals('atable', $commands[0]['arguments'][0]); - $this->assertEquals('newname', $commands[0]['arguments'][1]); - $this->assertEquals('oldname', $commands[0]['arguments'][2]); + $this->adapter + ->getAdapter() + ->expects($this->any()) + ->method('hasTable') + ->will($this->returnValue(true)); + + $table = new \Phinx\Db\Table('atable', [], $this->adapter); + $table->renameColumn('oldname', 'newname') + ->save(); + + $commands = $this->adapter->getInvertedCommands()->getActions(); + $this->assertInstanceOf('Phinx\Db\Action\RenameColumn', $commands[0]); + $this->assertEquals('newname', $commands[0]->getColumn()->getName()); + $this->assertEquals('oldname', $commands[0]->getNewName()); } public function testProxyAdapterCanInvertAddIndex() { - $table = new \Phinx\Db\Table('atable'); - $index = new \Phinx\Db\Table\Index(); - $index->setType(\Phinx\Db\Table\Index::INDEX) - ->setColumns(['email']); - - $this->adapter->addIndex($table, $index); - - $commands = $this->adapter->getInvertedCommands(); - $this->assertEquals('dropIndex', $commands[0]['name']); - $this->assertEquals('atable', $commands[0]['arguments'][0]); - $this->assertContains('email', $commands[0]['arguments'][1]); + $this->adapter + ->getAdapter() + ->expects($this->any()) + ->method('hasTable') + ->will($this->returnValue(true)); + + $table = new \Phinx\Db\Table('atable', [], $this->adapter); + $table->addIndex(['email']) + ->save(); + + $commands = $this->adapter->getInvertedCommands()->getActions(); + $this->assertInstanceOf('Phinx\Db\Action\DropIndex', $commands[0]); + $this->assertEquals('atable', $commands[0]->getTable()->getName()); + $this->assertEquals(['email'], $commands[0]->getIndex()->getColumns()); } public function testProxyAdapterCanInvertAddForeignKey() { - $table = new \Phinx\Db\Table('atable'); - $refTable = new \Phinx\Db\Table('refTable'); - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $this->adapter->addForeignKey($table, $fk); - - $commands = $this->adapter->getInvertedCommands(); - $this->assertEquals('dropForeignKey', $commands[0]['name']); - $this->assertEquals('atable', $commands[0]['arguments'][0]); - $this->assertContains('ref_table_id', $commands[0]['arguments'][1]); + $this->adapter + ->getAdapter() + ->expects($this->any()) + ->method('hasTable') + ->will($this->returnValue(true)); + + $table = new \Phinx\Db\Table('atable', [], $this->adapter); + $table->addForeignKey(['ref_table_id'], 'refTable') + ->save(); + + $commands = $this->adapter->getInvertedCommands()->getActions(); + $this->assertInstanceOf('Phinx\Db\Action\DropForeignKey', $commands[0]); + $this->assertEquals('atable', $commands[0]->getTable()->getName()); + $this->assertEquals(['ref_table_id'], $commands[0]->getForeignKey()->getColumns()); } /** * @expectedException \Phinx\Migration\IrreversibleMigrationException - * @expectedExceptionMessage Cannot reverse a "createDatabase" command + * @expectedExceptionMessage Cannot reverse a "Phinx\Db\Action\RemoveColumn" command */ public function testGetInvertedCommandsThrowsExceptionForIrreversibleCommand() { - $this->adapter->recordCommand('createDatabase', ['testdb']); + $this->adapter + ->getAdapter() + ->expects($this->any()) + ->method('hasTable') + ->will($this->returnValue(true)); + + $table = new \Phinx\Db\Table('atable', [], $this->adapter); + $table->removeColumn('thing') + ->save(); $this->adapter->getInvertedCommands(); } + } diff --git a/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php b/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php index 74f5749ac..afdb84dfe 100644 --- a/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php +++ b/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php @@ -2,11 +2,21 @@ namespace Test\Phinx\Db\Adapter; +use PHPUnit\Framework\TestCase; +use Phinx\Db\Action\AddColumn; +use Phinx\Db\Action\AddForeignKey; +use Phinx\Db\Action\AddIndex; +use Phinx\Db\Action\ChangeColumn; +use Phinx\Db\Action\DropForeignKey; +use Phinx\Db\Action\DropIndex; +use Phinx\Db\Action\DropTable; +use Phinx\Db\Action\RemoveColumn; +use Phinx\Db\Action\RenameColumn; +use Phinx\Db\Action\RenameTable; use Phinx\Db\Adapter\TablePrefixAdapter; -use Phinx\Db\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; -use PHPUnit\Framework\TestCase; +use Phinx\Db\Table\Table; class TablePrefixAdapterTest extends TestCase { @@ -285,58 +295,6 @@ public function testDropForeignKey() $this->adapter->dropForeignKey('table', $columns, $constraint); } - public function testAddTableWithForeignKey() - { - $this->mock - ->expects($this->any()) - ->method('isValidColumnType') - ->with($this->callback( - function ($column) { - return in_array($column->getType(), ['string', 'integer']); - } - )) - ->will($this->returnValue(true)); - - $table = new Table('table', [], $this->adapter); - $table - ->addColumn('bar', 'string') - ->addColumn('relation', 'integer') - ->addForeignKey('relation', 'target_table', ['id']); - - $this->mock - ->expects($this->once()) - ->method('createTable') - ->with($this->callback( - function ($table) { - if ($table->getName() !== 'pre_table_suf') { - throw new \Exception(sprintf( - 'Table::getName was not prefixed/suffixed properly: "%s"', - $table->getName() - )); - } - $fks = $table->getForeignKeys(); - if (count($fks) !== 1) { - throw new \Exception(sprintf( - 'Table::getForeignKeys count was incorrect: %d', - count($fks) - )); - } - foreach ($fks as $fk) { - if ($fk->getReferencedTable()->getName() !== 'pre_target_table_suf') { - throw new \Exception(sprintf( - 'ForeignKey::getReferencedTable was not prefixed/suffixed properly: "%s"', - $fk->getReferencedTable->getName() - )); - } - } - - return true; - } - )); - - $table->create(); - } - public function testInsertData() { $row = ['column1' => 'value3']; @@ -351,8 +309,49 @@ function ($table) { $this->equalTo($row) )); - $table = new Table('table', [], $this->adapter); + $table = new \Phinx\Db\Table('table', [], $this->adapter); $table->insert($row) ->save(); } + + public function actionsProvider() + { + $table = new Table('my_test'); + return [ + [AddColumn::build($table, 'acolumn')], + [AddIndex::build($table, ['acolumn'])], + [AddForeignKey::build($table, ['acolumn'], 'another_table'), true], + [ChangeColumn::build($table, 'acolumn')], + [DropForeignKey::build($table, ['acolumn'])], + [DropIndex::build($table, ['acolumn'])], + [new DropTable($table)], + [RemoveColumn::build($table, 'acolumn')], + [RenameColumn::build($table, 'acolumn', 'another')], + [new RenameTable($table, 'new_name')], + ]; + } + + /** + * @dataProvider actionsProvider + */ + public function testExecuteActions($action, $checkReferecedTable = false) + { + $this->mock->expects($this->once()) + ->method('executeActions') + ->will($this->returnCallback(function ($table, $newActions) use ($action, $checkReferecedTable) { + $this->assertCount(1, $newActions); + $this->assertSame(get_class($action), get_class($newActions[0])); + $this->assertEquals('pre_my_test_suf', $newActions[0]->getTable()->getName()); + + if ($checkReferecedTable) { + $this->assertEquals( + 'pre_another_table_suf', + $newActions[0]->getForeignKey()->getReferencedTable()->getName() + ); + } + })); + + $table = new Table('my_test'); + $this->adapter->executeActions($table, [$action]); + } } diff --git a/tests/Phinx/Db/TableTest.php b/tests/Phinx/Db/TableTest.php index c31250ade..11b917f7c 100644 --- a/tests/Phinx/Db/TableTest.php +++ b/tests/Phinx/Db/TableTest.php @@ -64,9 +64,9 @@ public function testAddColumnWithColumnObject() ->setType('integer'); $table = new \Phinx\Db\Table('ntable', [], $adapter); $table->addColumn($column); - $columns = $table->getPendingColumns(); - $this->assertEquals('email', $columns[0]->getName()); - $this->assertEquals('integer', $columns[0]->getType()); + $actions = $this->getPendingActions($table); + $this->assertInstanceOf('Phinx\Db\Action\AddColumn', $actions[0]); + $this->assertSame($column, $actions[0]->getColumn()); } public function testAddColumnWithNoAdapterSpecified() @@ -81,7 +81,6 @@ public function testAddColumnWithNoAdapterSpecified() $e, 'Expected exception of type RuntimeException, got ' . get_class($e) ); - $this->assertRegExp('/An adapter must be specified to add a column./', $e->getMessage()); } } @@ -93,29 +92,6 @@ public function testAddComment() $this->assertEquals('test comment', $options['comment']); } - public function testAddForeignKey() - { - $adapter = new MysqlAdapter([]); - $table = new \Phinx\Db\Table('ntable', [], $adapter); - $table->addForeignKey('test', 'testTable', 'testRef'); - $fks = $table->getForeignKeys(); - $this->assertCount(1, $fks); - $this->assertContains('test', $fks[0]->getColumns()); - $this->assertContains('testRef', $fks[0]->getReferencedColumns()); - $this->assertEquals('testTable', $fks[0]->getReferencedTable()->getName()); - } - - public function testAddIndex() - { - $adapter = new MysqlAdapter([]); - $table = new \Phinx\Db\Table('ntable', [], $adapter); - $table->addIndex(['email'], ['unique' => true, 'name' => 'myemailindex']); - $indexes = $table->getIndexes(); - $this->assertEquals(\Phinx\Db\Table\Index::UNIQUE, $indexes[0]->getType()); - $this->assertEquals('myemailindex', $indexes[0]->getName()); - $this->assertContains('email', $indexes[0]->getColumns()); - } - public function testAddIndexWithIndexObject() { $adapter = new MysqlAdapter([]); @@ -124,19 +100,9 @@ public function testAddIndexWithIndexObject() ->setColumns(['email']); $table = new \Phinx\Db\Table('ntable', [], $adapter); $table->addIndex($index); - $indexes = $table->getIndexes(); - $this->assertEquals(\Phinx\Db\Table\Index::INDEX, $indexes[0]->getType()); - $this->assertContains('email', $indexes[0]->getColumns()); - } - - public function testAddIndexWithoutType() - { - $adapter = new MysqlAdapter([]); - $table = new \Phinx\Db\Table('ntable', [], $adapter); - $table->addIndex(['email']); - $indexes = $table->getIndexes(); - $this->assertEquals(\Phinx\Db\Table\Index::INDEX, $indexes[0]->getType()); - $this->assertContains('email', $indexes[0]->getColumns()); + $actions = $this->getPendingActions($table); + $this->assertInstanceOf('Phinx\Db\Action\AddIndex', $actions[0]); + $this->assertSame($index, $actions[0]->getIndex()); } /** @@ -152,8 +118,13 @@ public function testAddTimestamps(AdapterInterface $adapter, $createdAtColumnNam { $table = new \Phinx\Db\Table('ntable', [], $adapter); $table->addTimestamps($createdAtColumnName, $updatedAtColumnName); + $actions = $this->getPendingActions($table); - $columns = $table->getPendingColumns(); + $columns = []; + + foreach ($actions as $action) { + $columns[] = $action->getColumn(); + } $this->assertEquals($expectedCreatedAtColumnName, $columns[0]->getName()); $this->assertEquals('timestamp', $columns[0]->getType()); @@ -167,56 +138,6 @@ public function testAddTimestamps(AdapterInterface $adapter, $createdAtColumnNam $this->assertNull($columns[1]->getDefault()); } - public function testChangeColumn() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('changeColumn'); - $newColumn = new \Phinx\Db\Table\Column(); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->changeColumn('test1', $newColumn); - } - - public function testChangeColumnWithoutAColumnObject() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('changeColumn'); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->changeColumn('test1', 'text', ['null' => false]); - } - - public function testDropForeignKey() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('dropForeignKey'); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->dropForeignKey('test'); - } - - public function testGetColumns() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('getColumns'); - - $table = new \Phinx\Db\Table('table1', [], $adapterStub); - $table->getColumns(); - } - public function testInsert() { $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') @@ -260,61 +181,13 @@ public function testInsertSaveData() $adapterStub->expects($this->exactly(1)) ->method('bulkinsert') - ->with($table, [$data[0], $data[1], $moreData[0], $moreData[1]]); + ->with($table->getTable(), [$data[0], $data[1], $moreData[0], $moreData[1]]); $table->insert($data) ->insert($moreData) ->save(); } - public function testRemoveColumn() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('dropColumn'); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->removeColumn('test'); - } - - public function testRemoveIndex() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('dropIndex'); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->removeIndex(['email']); - } - - public function testRemoveIndexByName() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('dropIndexByName'); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->removeIndexByName('emailindex'); - } - - public function testRenameColumn() - { - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('renameColumn'); - $table = new \Phinx\Db\Table('ntable', [], $adapterStub); - $table->renameColumn('test1', 'test2'); - } - public function testResetAfterAddingData() { $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\MysqlAdapter') @@ -326,4 +199,11 @@ public function testResetAfterAddingData() $table->insert($columns, $data)->save(); $this->assertEquals([], $table->getData()); } + + protected function getPendingActions($table) + { + $prop = new \ReflectionProperty(get_class($table), 'actions'); + $prop->setAccessible(true); + return $prop->getValue($table)->getActions(); + } } diff --git a/tests/Phinx/Migration/AbstractMigrationTest.php b/tests/Phinx/Migration/AbstractMigrationTest.php index 230cc0922..9d35f2781 100644 --- a/tests/Phinx/Migration/AbstractMigrationTest.php +++ b/tests/Phinx/Migration/AbstractMigrationTest.php @@ -260,20 +260,4 @@ public function testTableMethod() $migrationStub->table('test_table') ); } - - public function testDropTableMethod() - { - // stub migration - $migrationStub = $this->getMockForAbstractClass('\Phinx\Migration\AbstractMigration', ['mockenv', 0]); - - // stub adapter - $adapterStub = $this->getMockBuilder('\Phinx\Db\Adapter\PdoAdapter') - ->setConstructorArgs([[]]) - ->getMock(); - $adapterStub->expects($this->once()) - ->method('dropTable'); - - $migrationStub->setAdapter($adapterStub); - $migrationStub->dropTable('test_table'); - } } diff --git a/tests/Phinx/Migration/ManagerTest.php b/tests/Phinx/Migration/ManagerTest.php index 9a0f207fb..8a3420953 100644 --- a/tests/Phinx/Migration/ManagerTest.php +++ b/tests/Phinx/Migration/ManagerTest.php @@ -5485,9 +5485,10 @@ public function testReversibleMigrationsWorkAsExpected() $this->assertFalse($adapter->hasTable('info')); $this->assertTrue($adapter->hasTable('statuses')); $this->assertTrue($adapter->hasTable('users')); - $this->assertTrue($adapter->hasTable('user_logins')); + $this->assertTrue($adapter->hasTable('just_logins')); + $this->assertFalse($adapter->hasTable('user_logins')); $this->assertTrue($adapter->hasColumn('users', 'biography')); - $this->assertTrue($adapter->hasForeignKey('user_logins', ['user_id'])); + $this->assertTrue($adapter->hasForeignKey('just_logins', ['user_id'])); $this->assertTrue($adapter->hasTable('change_direction_test')); $this->assertTrue($adapter->hasColumn('change_direction_test', 'subthing')); $this->assertEquals( @@ -5502,6 +5503,7 @@ public function testReversibleMigrationsWorkAsExpected() $this->assertTrue($adapter->hasTable('info')); $this->assertFalse($adapter->hasTable('statuses')); $this->assertFalse($adapter->hasTable('user_logins')); + $this->assertFalse($adapter->hasTable('just_logins')); $this->assertTrue($adapter->hasColumn('users', 'bio')); $this->assertFalse($adapter->hasForeignKey('user_logins', ['user_id'])); $this->assertFalse($adapter->hasTable('change_direction_test')); @@ -5576,9 +5578,10 @@ public function testReversibleMigrationsWorkAsExpectedWithMixedNamespace() $this->assertFalse($adapter->hasTable('info')); $this->assertTrue($adapter->hasTable('statuses')); $this->assertTrue($adapter->hasTable('users')); - $this->assertTrue($adapter->hasTable('user_logins')); + $this->assertFalse($adapter->hasTable('user_logins')); + $this->assertTrue($adapter->hasTable('just_logins')); $this->assertTrue($adapter->hasColumn('users', 'biography')); - $this->assertTrue($adapter->hasForeignKey('user_logins', ['user_id'])); + $this->assertTrue($adapter->hasForeignKey('just_logins', ['user_id'])); $this->assertFalse($adapter->hasTable('info_baz')); $this->assertTrue($adapter->hasTable('statuses_baz')); @@ -5601,6 +5604,7 @@ public function testReversibleMigrationsWorkAsExpectedWithMixedNamespace() $this->assertTrue($adapter->hasTable('info')); $this->assertFalse($adapter->hasTable('statuses')); $this->assertFalse($adapter->hasTable('user_logins')); + $this->assertFalse($adapter->hasTable('just_logins')); $this->assertTrue($adapter->hasColumn('users', 'bio')); $this->assertFalse($adapter->hasForeignKey('user_logins', ['user_id'])); diff --git a/tests/Phinx/Migration/_files/reversiblemigrations/20121224200649_rename_info_table_to_statuses_table.php b/tests/Phinx/Migration/_files/reversiblemigrations/20121224200649_rename_info_table_to_statuses_table.php index 58e8e5ab0..8e9a0cd04 100644 --- a/tests/Phinx/Migration/_files/reversiblemigrations/20121224200649_rename_info_table_to_statuses_table.php +++ b/tests/Phinx/Migration/_files/reversiblemigrations/20121224200649_rename_info_table_to_statuses_table.php @@ -11,7 +11,7 @@ public function change() { // users table $table = $this->table('info'); - $table->rename('statuses'); + $table->rename('statuses')->save(); } /** diff --git a/tests/Phinx/Migration/_files/reversiblemigrations/20121224200739_rename_bio_to_biography.php b/tests/Phinx/Migration/_files/reversiblemigrations/20121224200739_rename_bio_to_biography.php index f9166afb0..a666dbb30 100644 --- a/tests/Phinx/Migration/_files/reversiblemigrations/20121224200739_rename_bio_to_biography.php +++ b/tests/Phinx/Migration/_files/reversiblemigrations/20121224200739_rename_bio_to_biography.php @@ -11,7 +11,7 @@ public function change() { // users table $table = $this->table('users'); - $table->renameColumn('bio', 'biography'); + $table->renameColumn('bio', 'biography')->save(); } /** diff --git a/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200649_rename_info_table_to_statuses_table.php b/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200649_rename_info_table_to_statuses_table.php index 34e068164..b91b81078 100644 --- a/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200649_rename_info_table_to_statuses_table.php +++ b/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200649_rename_info_table_to_statuses_table.php @@ -13,7 +13,7 @@ public function change() { // users table $table = $this->table('info_baz'); - $table->rename('statuses_baz'); + $table->rename('statuses_baz')->save(); } /** diff --git a/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200739_rename_bio_to_biography.php b/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200739_rename_bio_to_biography.php index 2a60d5db9..2600d35aa 100644 --- a/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200739_rename_bio_to_biography.php +++ b/tests/Phinx/Migration/_files_baz/reversiblemigrations/20151224200739_rename_bio_to_biography.php @@ -13,7 +13,7 @@ public function change() { // users table $table = $this->table('users_baz'); - $table->renameColumn('bio', 'biography'); + $table->renameColumn('bio', 'biography')->save(); } /** diff --git a/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200649_rename_info_table_to_statuses_table.php b/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200649_rename_info_table_to_statuses_table.php index fc095d100..3bfbd9498 100644 --- a/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200649_rename_info_table_to_statuses_table.php +++ b/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200649_rename_info_table_to_statuses_table.php @@ -13,7 +13,7 @@ public function change() { // users table $table = $this->table('info_foo_bar'); - $table->rename('statuses_foo_bar'); + $table->rename('statuses_foo_bar')->save(); } /** diff --git a/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200739_rename_bio_to_biography.php b/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200739_rename_bio_to_biography.php index d76736d0e..8ebe1da82 100644 --- a/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200739_rename_bio_to_biography.php +++ b/tests/Phinx/Migration/_files_foo_bar/reversiblemigrations/20161224200739_rename_bio_to_biography.php @@ -13,7 +13,7 @@ public function change() { // users table $table = $this->table('users_foo_bar'); - $table->renameColumn('bio', 'biography'); + $table->renameColumn('bio', 'biography')->save(); } /** From 6ba3a8e8f8feb805973446b33f317bd5c5647d38 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 10:02:59 +0200 Subject: [PATCH 03/21] Fixing sqlite server adapter --- src/Phinx/Db/Adapter/PdoAdapter.php | 24 +- src/Phinx/Db/Adapter/SQLiteAdapter.php | 392 +++++++++---------- src/Phinx/Db/Util/AlterInstructions.php | 19 + tests/Phinx/Db/Adapter/SQLiteAdapterTest.php | 170 ++++---- 4 files changed, 289 insertions(+), 316 deletions(-) diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index f0f47260f..9005baf3a 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -399,23 +399,17 @@ public function castToBool($value) return (bool)$value ? 1 : 0; } + /** + * Executes all the ALTER TABLE instructions passed for the given table + * + * @param string $tableName The table name to use in the ALTER statement + * @param AlterInstructions $instructions The object containing the alter sequence + * @return void + */ protected function executeAlterSteps($tableName, AlterInstructions $instructions) { - $alterParts = $instructions->getAlterParts(); - - if ($alterParts) { - $alter = sprintf( - 'ALTER TABLE %s %s', - $this->quoteTableName($tableName), - implode(', ', $alterParts) - ); - - $this->execute($alter); - } - - foreach ($instructions->getPostSteps() as $sql) { - $this->execute($sql); - } + $alter = sprintf('ALTER TABLE %s %%s', $this->quoteTableName($tableName)); + $instructions->execute($alter, [$this, 'execute']); } /** diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index 2d5ee331f..5de304a10 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -85,6 +85,7 @@ public function connect() )); } + $db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->setConnection($db); } } @@ -307,15 +308,8 @@ protected function getAddColumnInstructions(Table $table, Column $column) return new AlterInstructions([$alter]); } - /** - * {@inheritdoc} - */ - protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName) + protected function getDeclaringSql($tableName) { - $tmpTableName = 'tmp_' . $tableName; - $instructions = new AlterInstructions(); - $instructions->addPostStep(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); - $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); $sql = ''; @@ -325,37 +319,92 @@ protected function getRenameColumnInstructions($tableName, $columnName, $newColu } } + return $sql; + } + + protected function copyDataToNewTable($tableName, $tmpTableName, $writeColumns, $selectColumns) + { + $sql = sprintf( + 'INSERT INTO %s(%s) SELECT %s FROM %s', + $this->quoteTableName($tableName), + implode(', ', $writeColumns), + implode(', ', $selectColumns), + $this->quoteTableName($tmpTableName) + ); + $this->execute($sql); + } + + protected function copyAndDropTmpTable($instructions, $tableName) + { + $instructions->addPostStep(function ($state) use ($tableName) { + $this->copyDataToNewTable( + $tableName, + $state['tmpTableName'], + $state['writeColumns'], + $state['selectColumns'] + ); + + $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($state['tmpTableName']))); + return $state; + }); + + return $instructions; + } + + protected function calculateNewTableColumns($tableName, $columnName, $newColumnName) + { $columns = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($tableName))); $selectColumns = []; $writeColumns = []; + $columnType = null; + $found = false; + foreach ($columns as $column) { $selectName = $column['name']; - $writeName = ($selectName == $columnName)? $newColumnName : $selectName; - $selectColumns[] = $this->quoteColumnName($selectName); - $writeColumns[] = $this->quoteColumnName($writeName); + $writeName = $selectName; + + if ($selectName == $columnName) { + $writeName = $newColumnName; + $found = true; + $columnType = $column['type']; + $selectName = $newColumnName === false ? $newColumnName : $selectName; + } + + $selectColumns[] = $selectName; + $writeColumns[] = $writeName; } - if (!in_array($this->quoteColumnName($columnName), $selectColumns)) { + $selectColumns = array_filter($selectColumns, 'strlen'); + $writeColumns = array_filter($writeColumns, 'strlen'); + $selectColumns = array_map([$this, 'quoteColumnName'], $selectColumns); + $writeColumns = array_map([$this, 'quoteColumnName'], $writeColumns); + + if (!$found) { throw new \InvalidArgumentException(sprintf( 'The specified column doesn\'t exist: ' . $columnName )); } - $instructions->addPostStep(str_replace( - $this->quoteColumnName($columnName), - $this->quoteColumnName($newColumnName), - $sql - )); + return compact('writeColumns', 'selectColumns', 'columnType'); + } - $instructions->addPostStep(sprintf( - 'INSERT INTO %s(%s) SELECT %s FROM %s', - $tableName, - implode(', ', $writeColumns), - implode(', ', $selectColumns), - $tmpTableName - )); + protected function beginAlterByCopyTable($tableName) + { + $instructions = new AlterInstructions(); + $instructions->addPostStep(function ($state) use ($tableName) { + $createSQL = $this->getDeclaringSql($tableName); + + $tmpTableName = 'tmp_' . $tableName; + $this->execute( + sprintf( + 'ALTER TABLE %s RENAME TO %s', + $this->quoteTableName($tableName), + $this->quoteTableName($tmpTableName) + ) + ); - $instructions->addPostStep(printf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + return compact('createSQL', 'tmpTableName') + $state; + }); return $instructions; } @@ -363,118 +412,88 @@ protected function getRenameColumnInstructions($tableName, $columnName, $newColu /** * {@inheritdoc} */ - protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn) + protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName) { - // TODO: DRY this up.... - $tmpTableName = 'tmp_' . $tableName; - $instructions = new AlterInstructions(); - $instructions->addPostStep(sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)); + $instructions = $this->beginAlterByCopyTable($tableName); + $instructions->addPostStep(function ($state) use ($columnName, $newColumnName) { + $newState = $this->calculateNewTableColumns($state['tmpTableName'], $columnName, $newColumnName); + + return $newState + $state; + }); + + $instructions->addPostStep(function ($state) use ($tableName, $columnName, $newColumnName) { + $sql = str_replace( + $this->quoteColumnName($columnName), + $this->quoteColumnName($newColumnName), + $state['createSQL'] + ); + $this->execute($sql); - $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); + return $state; + }); - $sql = ''; - foreach ($rows as $table) { - if ($table['tbl_name'] === $tableName) { - $sql = $table['sql']; - } - } + return $this->copyAndDropTmpTable($instructions, $tableName); + } - $columns = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($tableName))); - $selectColumns = []; - $writeColumns = []; - foreach ($columns as $column) { - $selectName = $column['name']; - $writeName = ($selectName === $columnName)? $newColumn->getName() : $selectName; - $selectColumns[] = $this->quoteColumnName($selectName); - $writeColumns[] = $this->quoteColumnName($writeName); - } + /** + * {@inheritdoc} + */ + protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn) + { + $instructions = $this->beginAlterByCopyTable($tableName); - if (!in_array($this->quoteColumnName($columnName), $selectColumns)) { - throw new \InvalidArgumentException(sprintf( - 'The specified column doesn\'t exist: ' . $columnName - )); - } + $newColumnName = $newColumn->getName(); + $instructions->addPostStep(function ($state) use ($columnName, $newColumnName) { + $newState = $this->calculateNewTableColumns($state['tmpTableName'], $columnName, $newColumnName); - $instructions->addPostStep(preg_replace( - sprintf("/%s(?:\/\*.*?\*\/|\([^)]+\)|'[^']*?'|[^,])+([,)])/", $this->quoteColumnName($columnName)), - sprintf('%s %s$1', $this->quoteColumnName($newColumn->getName()), $this->getColumnSqlDefinition($newColumn)), - $sql, - 1 - )); + return $newState + $state; + }); - $instructions->addPostStep(sprintf( - 'INSERT INTO %s(%s) SELECT %s FROM %s', - $tableName, - implode(', ', $writeColumns), - implode(', ', $selectColumns), - $tmpTableName - )); + $instructions->addPostStep(function ($state) use ($tableName, $columnName, $newColumn) { + $sql = preg_replace( + sprintf("/%s(?:\/\*.*?\*\/|\([^)]+\)|'[^']*?'|[^,])+([,)])/", $this->quoteColumnName($columnName)), + sprintf('%s %s$1', $this->quoteColumnName($newColumn->getName()), $this->getColumnSqlDefinition($newColumn)), + $state['createSQL'], + 1 + ); + $this->execute($sql); - $instructions->addPostStep(sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName))); + return $state; + }); - return $instructions; + return $this->copyAndDropTmpTable($instructions, $tableName); } /** * {@inheritdoc} */ - protected function getDropColumnParts($tableName, $columnName) + protected function getDropColumnInstructions($tableName, $columnName) { - // TODO: DRY this up.... - $tmpTableName = 'tmp_' . $tableName; - $alter = [sprintf('ALTER TABLE %s RENAME TO %s', $tableName, $tmpTableName)]; - $postSql = []; + $instructions = $this->beginAlterByCopyTable($tableName); - $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); + $instructions->addPostStep(function ($state) use ($columnName) { + $newState = $this->calculateNewTableColumns($state['tmpTableName'], $columnName, false); - $sql = ''; - foreach ($rows as $table) { - if ($table['tbl_name'] === $tableName) { - $sql = $table['sql']; - } - } - - $rows = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($tableName))); - $columns = []; - $columnType = null; - foreach ($rows as $row) { - if ($row['name'] !== $columnName) { - $columns[] = $row['name']; - } else { - $found = true; - $columnType = $row['type']; - } - } - - if (!isset($found)) { - throw new \InvalidArgumentException(sprintf( - 'The specified column doesn\'t exist: ' . $columnName - )); - } - - $sql = preg_replace( - sprintf("/%s\s%s.*(,\s(?!')|\)$)/U", preg_quote($this->quoteColumnName($columnName)), preg_quote($columnType)), - "", - $sql - ); + return $newState + $state; + }); - if (substr($sql, -2) === ', ') { - $sql = substr($sql, 0, -2) . ')'; - } + $instructions->addPostStep(function ($state) use ($tableName, $columnName) { + $sql = preg_replace( + sprintf("/%s\s%s.*(,\s(?!')|\)$)/U", preg_quote($this->quoteColumnName($columnName)), preg_quote($state['columnType'])), + "", + $state['createSQL'] + ); - $postSql[] = $sql; + if (substr($sql, -2) === ', ') { + $sql = substr($sql, 0, -2) . ')'; + } - $postSql[] = sprintf( - 'INSERT INTO %s(%s) SELECT %s FROM %s', - $tableName, - implode(', ', $columns), - implode(', ', $columns), - $tmpTableName - ); + $this->execute($sql); - $postSql[] = sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName)); + return $state; + }); - return [$alter, $postSql]; + return $this->copyAndDropTmpTable($instructions, $tableName); } /** @@ -542,25 +561,27 @@ public function hasIndexByName($tableName, $indexName) /** * {@inheritdoc} */ - protected function getAddIndexPart(Table $table, Index $index) + protected function getAddIndexInstructions(Table $table, Index $index) { $indexColumnArray = []; foreach ($index->getColumns() as $column) { $indexColumnArray[] = sprintf('`%s` ASC', $column); } $indexColumns = implode(',', $indexColumnArray); - return sprintf( + $sql = sprintf( 'CREATE %s ON %s (%s)', $this->getIndexSqlDefinition($table, $index), $this->quoteTableName($table->getName()), $indexColumns ); + + return new AlterInstructions([], [$sql]); } /** * {@inheritdoc} */ - protected function getDropIndexByColumnsPart($tableName, $columns) + protected function getDropIndexByColumnsInstructions($tableName, $columns) { if (is_string($columns)) { $columns = [$columns]; // str to array @@ -568,33 +589,39 @@ protected function getDropIndexByColumnsPart($tableName, $columns) $indexes = $this->getIndexes($tableName); $columns = array_map('strtolower', $columns); + $instructions = new AlterInstructions(); foreach ($indexes as $index) { $a = array_diff($columns, $index['columns']); if (empty($a)) { - return sprintf( + $instructions->addPostStep(sprintf( 'DROP INDEX %s', $this->quoteColumnName($index['index']) - ); + )); } } + + return $instructions; } /** * {@inheritdoc} */ - protected function getDropIndexByNamePart($tableName, $indexName) + protected function getDropIndexByNameInstructions($tableName, $indexName) { $indexes = $this->getIndexes($tableName); + $instructions = new AlterInstructions(); foreach ($indexes as $index) { if ($indexName === $index['index']) { - return sprintf( + $instructions->addPostStep(sprintf( 'DROP INDEX %s', $this->quoteColumnName($indexName) - ); + )); } } + + return $instructions; } /** @@ -651,49 +678,34 @@ protected function getForeignKeys($tableName) /** * {@inheritdoc} */ - protected function getAddForeignKeyParts(Table $table, ForeignKey $foreignKey) + protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey) { - // TODO: DRY this up.... - $this->execute('pragma foreign_keys = ON'); + $instructions = $this->beginAlterByCopyTable($table->getName()); - $tmpTableName = 'tmp_' . $table->getName(); - $alter = [sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($table->getName()), $tmpTableName)]; - $postSql = []; + $tableName = $table->getName(); + $instructions->addPostStep(function ($state) use ($foreignKey) { + $this->execute('pragma foreign_keys = ON'); + $sql = substr($state['createSQL'], 0, -1) . ',' . $this->getForeignKeySqlDefinition($foreignKey) . ')'; + $this->execute($sql); - $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); + return $state; + }); - $sql = ''; - foreach ($rows as $row) { - if ($row['tbl_name'] === $table->getName()) { - $sql = $row['sql']; - } - } - - $rows = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($table->getName()))); - $columns = []; - foreach ($rows as $column) { - $columns[] = $this->quoteColumnName($column['name']); - } + $instructions->addPostStep(function ($state) use ($foreignKey) { + $columns = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($state['tmpTableName']))); + $names = array_map([$this, 'quoteColumnName'], array_column($columns, 'name')); + $selectColumns = $writeColumns = $names; - $postSql[] = substr($sql, 0, -1) . ',' . $this->getForeignKeySqlDefinition($foreignKey) . ')'; + return compact('selectColumns', 'writeColumns') + $state; + }); - $postSql[] = sprintf( - 'INSERT INTO %s(%s) SELECT %s FROM %s', - $this->quoteTableName($table->getName()), - implode(', ', $columns), - implode(', ', $columns), - $this->quoteTableName($tmpTableName) - ); - - $postSql[] = sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName)); - - return [$alter, $postSql]; + return $this->copyAndDropTmpTable($instructions, $tableName); } /** * {@inheritdoc} */ - protected function getDropForeignKeyParts($tableName, $constraint) + protected function getDropForeignKeyInstructions($tableName, $constraint) { throw new \BadMethodCallException('SQLite does not have named foreign keys'); } @@ -701,64 +713,44 @@ protected function getDropForeignKeyParts($tableName, $constraint) /** * {@inheritdoc} */ - protected function getDropForeignKeyByColumnsParts($tableName, $columns) + protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) { - // TODO: DRY this up.... if (is_string($columns)) { $columns = [$columns]; // str to array } - $alter = [sprintf('ALTER TABLE %s RENAME TO %s', $this->quoteTableName($tableName), $tmpTableName)]; - $postSql = []; + $instructions = $this->beginAlterByCopyTable($tableName); - $tmpTableName = 'tmp_' . $tableName; + $instructions->addPostStep(function ($state) use ($columns) { + $newState = $this->calculateNewTableColumns($state['tmpTableName'], $columns[0], $columns[0]); - $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); - - $sql = ''; - foreach ($rows as $table) { - if ($table['tbl_name'] === $tableName) { - $sql = $table['sql']; - } - } + $selectColumns = $newState['selectColumns']; + $columns = array_map([$this, 'quoteColumnName'], $columns); + $diff = array_diff($columns, $selectColumns); - $rows = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($tableName))); - $replaceColumns = []; - foreach ($rows as $row) { - if (!in_array($row['name'], $columns)) { - $replaceColumns[] = $row['name']; - } else { - $found = true; + if (!empty($diff)) { + throw new \InvalidArgumentException(sprintf( + 'The specified columns doen\'t exist: ' . implode(', ', $diff) + )); } - } - if (!isset($found)) { - throw new \InvalidArgumentException(sprintf( - 'The specified column doesn\'t exist: ' - )); - } - - foreach ($columns as $columnName) { - $search = sprintf( - "/,[^,]*\(%s(?:,`?(.*)`?)?\) REFERENCES[^,]*\([^\)]*\)[^,)]*/", - $this->quoteColumnName($columnName) - ); - $sql = preg_replace($search, '', $sql, 1); - } - - $postSql[] = $sql; + return $newState + $state; + }); - $postSql[] = sprintf( - 'INSERT INTO %s(%s) SELECT %s FROM %s', - $tableName, - implode(', ', $columns), - implode(', ', $columns), - $tmpTableName - ); + $instructions->addPostStep(function ($state) use ($tableName, $columns) { + foreach ($columns as $columnName) { + $search = sprintf( + "/,[^,]*\(%s(?:,`?(.*)`?)?\) REFERENCES[^,]*\([^\)]*\)[^,)]*/", + $this->quoteColumnName($columnName) + ); + $sql = preg_replace($search, '', $state['createSQL'], 1); + } + $this->execute($sql); - $postSql[] = sprintf('DROP TABLE %s', $this->quoteTableName($tmpTableName)); + return $state; + }); - return [$alter, $postSql]; + return $this->copyAndDropTmpTable($instructions, $tableName); } /** diff --git a/src/Phinx/Db/Util/AlterInstructions.php b/src/Phinx/Db/Util/AlterInstructions.php index 0c91e22fb..f1ba49f2b 100644 --- a/src/Phinx/Db/Util/AlterInstructions.php +++ b/src/Phinx/Db/Util/AlterInstructions.php @@ -40,4 +40,23 @@ public function merge(AlterInstructions $other) $this->alterParts = array_merge($this->alterParts, $other->getAlterParts()); $this->postSteps = array_merge($this->postSteps, $other->getPostSteps()); } + + public function execute($alterTemplate, callable $executor) + { + if ($this->alterParts) { + $alter = sprintf($alterTemplate, implode(', ', $this->alterParts)); + $executor($alter); + } + + $state = []; + + foreach ($this->postSteps as $instruction) { + if (is_callable($instruction)) { + $state = $instruction($state); + continue; + } + + $executor($instruction); + } + } } diff --git a/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php b/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php index 93313dbb2..6c90ac35c 100644 --- a/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php +++ b/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php @@ -48,8 +48,6 @@ public function testConnection() public function testBeginTransaction() { - $this->adapter->getConnection() - ->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->adapter->beginTransaction(); $this->assertTrue(true, 'Transaction query succeeded'); @@ -110,12 +108,6 @@ public function testCreateTableCustomIdColumn() $this->assertFalse($this->adapter->hasColumn('ntable', 'address')); } - public function testCreateTableWithNoOptions() - { - $this->markTestIncomplete(); - //$this->adapter->createTable('ntable', ) - } - public function testCreateTableWithNoPrimaryKey() { $options = [ @@ -296,7 +288,7 @@ public function testChangeColumn() $newColumn2 = new \Phinx\Db\Table\Column(); $newColumn2->setName('column2') ->setType('string'); - $table->changeColumn('column1', $newColumn2); + $table->changeColumn('column1', $newColumn2)->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); $this->assertTrue($this->adapter->hasColumn('t', 'column2')); } @@ -309,7 +301,7 @@ public function testChangeColumnDefaultValue() $newColumn1 = new \Phinx\Db\Table\Column(); $newColumn1->setDefault('test1') ->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('pragma table_info(t)'); $this->assertEquals("'test1'", $rows[1]['dflt_value']); @@ -324,18 +316,14 @@ public function testChangeColumnWithForeignKey() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('another_table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $this->adapter->addForeignKey($table, $fk); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); - $table->changeColumn('ref_table_id', 'float'); + $table->changeColumn('ref_table_id', 'float')->save(); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -348,7 +336,7 @@ public function testChangeColumnDefaultToZero() $newColumn1 = new \Phinx\Db\Table\Column(); $newColumn1->setDefault(0) ->setType('integer'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('pragma table_info(t)'); $this->assertEquals("0", $rows[1]['dflt_value']); } @@ -361,7 +349,7 @@ public function testChangeColumnDefaultToNull() $newColumn1 = new \Phinx\Db\Table\Column(); $newColumn1->setDefault(null) ->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('pragma table_info(t)'); $this->assertNull($rows[1]['dflt_value']); } @@ -375,7 +363,7 @@ public function testChangeColumnWithCommasInCommentsOrDefaultValue() $newColumn1->setDefault('another default') ->setComment('another comment') ->setType('string'); - $table->changeColumn('column1', $newColumn1); + $table->changeColumn('column1', $newColumn1)->save(); $rows = $this->adapter->fetchAll('pragma table_info(t)'); $this->assertEquals("'another default'", $rows[1]['dflt_value']); } @@ -391,7 +379,7 @@ public function testDropColumn($columnCreationArgs) $table->save(); $this->assertTrue($this->adapter->hasColumn('t', $columnName)); - $this->adapter->dropColumn('t', $columnName); + $table->removeColumn($columnName)->save(); $this->assertFalse($this->adapter->hasColumn('t', $columnName)); } @@ -404,30 +392,47 @@ public function columnCreationArgumentProvider() ]; } - public function testGetColumns() + public function columnsProvider() + { + return [ + ['column1', 'string', []], + ['column2', 'integer', []], + ['column3', 'biginteger', []], + ['column4', 'text', []], + ['column5', 'float', []], + ['column6', 'decimal', []], + ['column7', 'datetime', []], + ['column8', 'time', []], + ['column9', 'timestamp', [], 'datetime'], + ['column10', 'date', []], + ['column11', 'binary', []], + ['column13', 'string', ['limit' => 10]], + ['column15', 'integer', ['limit' => 10]], + ['column22', 'enum', ['values' => ['three', 'four']]], + ]; + } + + /** + * + * @dataProvider columnsProvider + */ + public function testGetColumns($colName, $type, $options, $actualType = null) { $table = new \Phinx\Db\Table('t', [], $this->adapter); - $table->addColumn('column1', 'string') - ->addColumn('column2', 'integer') - ->addColumn('column3', 'biginteger') - ->addColumn('column4', 'text') - ->addColumn('column5', 'float') - ->addColumn('column6', 'decimal') - ->addColumn('column7', 'datetime') - ->addColumn('column8', 'time') - ->addColumn('column9', 'timestamp') - ->addColumn('column10', 'date') - ->addColumn('column11', 'binary') - ->addColumn('column12', 'boolean') - ->addColumn('column13', 'string', ['limit' => 10]) - ->addColumn('column15', 'integer', ['limit' => 10]) - ->addColumn('column16', 'enum', ['values' => ['a', 'b', 'c']]); - $pendingColumns = $table->getPendingColumns(); - $table->save(); + $table->addColumn($colName, $type, $options)->save(); + $columns = $this->adapter->getColumns('t'); - $this->assertCount(count($pendingColumns) + 1, $columns); - for ($i = 0; $i++; $i < count($pendingColumns)) { - $this->assertEquals($pendingColumns[$i], $columns[$i + 1]); + $this->assertCount(2, $columns); + $this->assertEquals($colName, $columns[1]->getName()); + + if (!$actualType) { + $actualType = $type; + } + + if (is_string($columns[1]->getType())) { + $this->assertEquals($actualType, $columns[1]->getType()); + } else { + $this->assertEquals(['name' => $actualType] + $options, $columns[1]->getType()); } } @@ -511,34 +516,10 @@ public function testAddForeignKey() $refTable->addColumn('field1', 'string')->save(); $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $this->adapter->addForeignKey($table, $fk); - - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); - } - - public function testAddForeignKeyWithPdoExceptionErrorMode() - { - $this->adapter->getConnection() - ->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $refTable = new \Phinx\Db\Table('ref_table', [], $this->adapter); - $refTable->addColumn('field1', 'string')->save(); - - $table = new \Phinx\Db\Table('table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $this->adapter->addForeignKey($table, $fk); + $table + ->addColumn('ref_table_id', 'integer') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->save(); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); } @@ -551,31 +532,23 @@ public function testDropForeignKey() ->save(); $table = new \Phinx\Db\Table('another_table', [], $this->adapter); - $table->addColumn('ref_table_id', 'integer')->addColumn('ref_table_field', 'string')->save(); - - $fk = new \Phinx\Db\Table\ForeignKey(); - $fk->setReferencedTable($refTable) - ->setColumns(['ref_table_id']) - ->setReferencedColumns(['id']); - - $secondFk = new \Phinx\Db\Table\ForeignKey(); - $secondFk->setReferencedTable($refTable) - ->setColumns(['ref_table_field']) - ->setReferencedColumns(['field1']) - ->setOptions([ - 'update' => 'CASCADE', - 'delete' => 'CASCADE' - ]); - - $this->adapter->addForeignKey($table, $fk); + $opts = [ + 'update' => 'CASCADE', + 'delete' => 'CASCADE' + ]; + $table + ->addColumn('ref_table_id', 'integer') + ->addColumn('ref_table_field', 'string') + ->addForeignKey(['ref_table_id'], 'ref_table', ['id']) + ->addForeignKey(['ref_table_field'], 'ref_table', ['field1'], $opts) + ->save(); + + $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); $this->adapter->dropForeignKey($table->getName(), ['ref_table_id']); $this->assertFalse($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); - $this->adapter->addForeignKey($table, $secondFk); - $this->adapter->addForeignKey($table, $fk); - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_field'])); $this->adapter->dropForeignKey($table->getName(), ['ref_table_field']); @@ -678,11 +651,8 @@ public function testBulkInsertData() 'column1' => '\'value4\'', 'column2' => null, ] - ); - $this->adapter->createTable($table); - $this->adapter->bulkinsert($table, $table->getData()); - $table->reset(); - + ) + ->save(); $rows = $this->adapter->fetchAll('SELECT * FROM table1'); $this->assertEquals('value1', $rows[0]['column1']); @@ -744,10 +714,8 @@ public function testBulkInsertDataEnum() ->addColumn('column3', 'enum', ['values' => ['a', 'b', 'c'], 'default' => 'c']) ->insert([ 'column1' => 'a', - ]); - $this->adapter->createTable($table); - $this->adapter->bulkinsert($table, $table->getData()); - $table->reset(); + ]) + ->save(); $rows = $this->adapter->fetchAll('SELECT * FROM table1'); From 0d81f0fabad0e8b935da4388d17f989fe65351ef Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 10:57:34 +0200 Subject: [PATCH 04/21] clening up the code a little bit --- src/Phinx/Db/Action/Action.php | 15 ++ src/Phinx/Db/Action/AddColumn.php | 7 - src/Phinx/Db/Action/AddForeignKey.php | 7 - src/Phinx/Db/Action/AddIndex.php | 8 - src/Phinx/Db/Action/ChangeColumn.php | 8 - src/Phinx/Db/Action/CreateTable.php | 7 - src/Phinx/Db/Action/DropForeignKey.php | 7 - src/Phinx/Db/Action/DropIndex.php | 7 - src/Phinx/Db/Action/DropTable.php | 5 - src/Phinx/Db/Action/RemoveColumn.php | 7 - src/Phinx/Db/Action/RenameColumn.php | 7 - src/Phinx/Db/Action/RenameTable.php | 7 - src/Phinx/Db/Adapter/AdapterInterface.php | 110 ------------- src/Phinx/Db/Adapter/AdapterWrapper.php | 96 ----------- .../Db/Adapter/DirectActionInterface.php | 151 ++++++++++++++++++ src/Phinx/Db/Adapter/PdoAdapter.php | 104 +++++++++++- src/Phinx/Db/Adapter/TablePrefixAdapter.php | 25 ++- src/Phinx/Db/Adapter/TimedOutputAdapter.php | 14 +- .../20180431121930_tricky_edge_case.php | 20 +++ 19 files changed, 311 insertions(+), 301 deletions(-) create mode 100644 src/Phinx/Db/Adapter/DirectActionInterface.php create mode 100644 tests/Phinx/Migration/_files/reversiblemigrations/20180431121930_tricky_edge_case.php diff --git a/src/Phinx/Db/Action/Action.php b/src/Phinx/Db/Action/Action.php index 96d12fdf9..158092a73 100644 --- a/src/Phinx/Db/Action/Action.php +++ b/src/Phinx/Db/Action/Action.php @@ -4,4 +4,19 @@ abstract class Action { + + /** + * @var Phinx\Db\Table\Table + */ + protected $table; + + /** + * The table this action will be applied to + * + * @return Phinx\Db\Table\Table + */ + public function getTable() + { + return $this->table; + } } diff --git a/src/Phinx/Db/Action/AddColumn.php b/src/Phinx/Db/Action/AddColumn.php index 68370ca30..06a293d7e 100644 --- a/src/Phinx/Db/Action/AddColumn.php +++ b/src/Phinx/Db/Action/AddColumn.php @@ -8,8 +8,6 @@ class AddColumn extends Action { - protected $table; - protected $column; public function __construct(Table $table, Column $column) @@ -28,11 +26,6 @@ public static function build(Table $table, $columnName, $type = null, $options = return new static($table, $column); } - public function getTable() - { - return $this->table; - } - public function getColumn() { return $this->column; diff --git a/src/Phinx/Db/Action/AddForeignKey.php b/src/Phinx/Db/Action/AddForeignKey.php index 14663d67f..30e2ae1bf 100644 --- a/src/Phinx/Db/Action/AddForeignKey.php +++ b/src/Phinx/Db/Action/AddForeignKey.php @@ -9,8 +9,6 @@ class AddForeignKey extends Action { - protected $table; - protected $foreignKey; public function __construct(Table $table, ForeignKey $fk) @@ -42,11 +40,6 @@ public static function build(Table $table, $columns, $referencedTable, $referenc return new static($table, $fk); } - public function getTable() - { - return $this->table; - } - public function getForeignKey() { return $this->foreignKey; diff --git a/src/Phinx/Db/Action/AddIndex.php b/src/Phinx/Db/Action/AddIndex.php index 9faa2e364..6847ef67c 100644 --- a/src/Phinx/Db/Action/AddIndex.php +++ b/src/Phinx/Db/Action/AddIndex.php @@ -8,9 +8,6 @@ class AddIndex extends Action { - - protected $table; - protected $index; public function __construct(Table $table, Index $index) @@ -38,11 +35,6 @@ public static function build(Table $table, $columns, array $options = []) return new static($table, $index); } - public function getTable() - { - return $this->table; - } - public function getIndex() { return $this->index; diff --git a/src/Phinx/Db/Action/ChangeColumn.php b/src/Phinx/Db/Action/ChangeColumn.php index 33701aa02..1f6e78cde 100644 --- a/src/Phinx/Db/Action/ChangeColumn.php +++ b/src/Phinx/Db/Action/ChangeColumn.php @@ -7,9 +7,6 @@ class ChangeColumn extends Action { - - protected $table; - protected $column; protected $columnName; @@ -36,11 +33,6 @@ public static function build(Table $table, $columnName, $type = null, $options = return new static($table, $columnName, $column); } - public function getTable() - { - return $this->table; - } - public function getColumnName() { return $this->columnName; diff --git a/src/Phinx/Db/Action/CreateTable.php b/src/Phinx/Db/Action/CreateTable.php index 615883d02..96caf3693 100644 --- a/src/Phinx/Db/Action/CreateTable.php +++ b/src/Phinx/Db/Action/CreateTable.php @@ -7,15 +7,8 @@ class CreateTable extends Action { - protected $table; - public function __construct(Table $table) { $this->table = $table; } - - public function getTable() - { - return $this->table; - } } diff --git a/src/Phinx/Db/Action/DropForeignKey.php b/src/Phinx/Db/Action/DropForeignKey.php index 6a52a2d3e..67d0ab6b1 100644 --- a/src/Phinx/Db/Action/DropForeignKey.php +++ b/src/Phinx/Db/Action/DropForeignKey.php @@ -9,8 +9,6 @@ class DropForeignKey extends Action { - protected $table; - protected $foreignKey; public function __construct(Table $table, ForeignKey $foreignKey) @@ -35,11 +33,6 @@ public static function build(Table $table, $columns, $constraint = null) return new static($table, $foreignKey); } - public function getTable() - { - return $this->table; - } - public function getForeignKey() { return $this->foreignKey; diff --git a/src/Phinx/Db/Action/DropIndex.php b/src/Phinx/Db/Action/DropIndex.php index d9296c7c2..73f413457 100644 --- a/src/Phinx/Db/Action/DropIndex.php +++ b/src/Phinx/Db/Action/DropIndex.php @@ -9,8 +9,6 @@ class DropIndex extends Action { - protected $table; - protected $index; public function __construct(Table $table, Index $index) @@ -35,11 +33,6 @@ public static function buildFromName(Table $table, $name) return new static($table, $index); } - public function getTable() - { - return $this->table; - } - public function getIndex() { return $this->index; diff --git a/src/Phinx/Db/Action/DropTable.php b/src/Phinx/Db/Action/DropTable.php index 5fb91f8ea..6a5abd0a6 100644 --- a/src/Phinx/Db/Action/DropTable.php +++ b/src/Phinx/Db/Action/DropTable.php @@ -13,9 +13,4 @@ public function __construct(Table $table) { $this->table = $table; } - - public function getTable() - { - return $this->table; - } } diff --git a/src/Phinx/Db/Action/RemoveColumn.php b/src/Phinx/Db/Action/RemoveColumn.php index 857754aa3..6c53db327 100644 --- a/src/Phinx/Db/Action/RemoveColumn.php +++ b/src/Phinx/Db/Action/RemoveColumn.php @@ -8,8 +8,6 @@ class RemoveColumn extends Action { - protected $table; - protected $column; public function __construct(Table $table, Column $column) @@ -25,11 +23,6 @@ public static function build(Table $table, $columnName) return new static($table, $column); } - public function getTable() - { - return $this->table; - } - public function getColumn() { return $this->column; diff --git a/src/Phinx/Db/Action/RenameColumn.php b/src/Phinx/Db/Action/RenameColumn.php index ec0283ba7..0290a095d 100644 --- a/src/Phinx/Db/Action/RenameColumn.php +++ b/src/Phinx/Db/Action/RenameColumn.php @@ -8,8 +8,6 @@ class RenameColumn extends Action { - protected $table; - protected $column; protected $newName; @@ -28,11 +26,6 @@ public static function build(Table $table, $columnName, $newName) return new static($table, $column, $newName); } - public function getTable() - { - return $this->table; - } - public function getColumn() { return $this->column; diff --git a/src/Phinx/Db/Action/RenameTable.php b/src/Phinx/Db/Action/RenameTable.php index d7df6741b..250ae3b15 100644 --- a/src/Phinx/Db/Action/RenameTable.php +++ b/src/Phinx/Db/Action/RenameTable.php @@ -7,8 +7,6 @@ class RenameTable extends Action { - protected $table; - protected $newName; public function __construct(Table $table, $newName) @@ -17,11 +15,6 @@ public function __construct(Table $table, $newName) $this->table = $table; } - public function getTable() - { - return $this->table; - } - public function getNewName() { return $this->newName; diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index 41546f9b8..aa0951396 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -257,7 +257,6 @@ public function rollbackTransaction(); */ public function execute($sql); - /** * Executes a list of migration actions for the given table * @@ -343,31 +342,6 @@ public function hasTable($tableName); */ public function createTable(Table $table, array $columns = [], array $indexes = []); - /** - * Renames the specified database table. - * - * @param string $tableName Table Name - * @param string $newName New Name - * @return void - */ - public function renameTable($tableName, $newName); - - /** - * Drops the specified database table. - * - * @param string $tableName Table Name - * @return void - */ - public function dropTable($tableName); - - /** - * Truncates the specified table - * - * @param string $tableName - * @return void - */ - public function truncateTable($tableName); - /** * Returns table columns * @@ -385,44 +359,6 @@ public function getColumns($tableName); */ public function hasColumn($tableName, $columnName); - /** - * Adds the specified column to a database table. - * - * @param \Phinx\Db\Table\Table $table Table - * @param \Phinx\Db\Table\Column $column Column - * @return void - */ - public function addColumn(Table $table, Column $column); - - /** - * Renames the specified column. - * - * @param string $tableName Table Name - * @param string $columnName Column Name - * @param string $newColumnName New Column Name - * @return void - */ - public function renameColumn($tableName, $columnName, $newColumnName); - - /** - * Change a table column type. - * - * @param string $tableName Table Name - * @param string $columnName Column Name - * @param \Phinx\Db\Table\Column $newColumn New Column - * @return \Phinx\Db\Table - */ - public function changeColumn($tableName, $columnName, Column $newColumn); - - /** - * Drops the specified column. - * - * @param string $tableName Table Name - * @param string $columnName Column Name - * @return void - */ - public function dropColumn($tableName, $columnName); - /** * Checks to see if an index exists. * @@ -441,33 +377,6 @@ public function hasIndex($tableName, $columns); */ public function hasIndexByName($tableName, $indexName); - /** - * Adds the specified index to a database table. - * - * @param \Phinx\Db\Table\Table $table Table - * @param \Phinx\Db\Table\Index $index Index - * @return void - */ - public function addIndex(Table $table, Index $index); - - /** - * Drops the specified index from a database table. - * - * @param string $tableName - * @param mixed $columns Column(s) - * @return void - */ - public function dropIndex($tableName, $columns); - - /** - * Drops the index specified by name from a database table. - * - * @param string $tableName - * @param string $indexName - * @return void - */ - public function dropIndexByName($tableName, $indexName); - /** * Checks to see if a foreign key exists. * @@ -478,25 +387,6 @@ public function dropIndexByName($tableName, $indexName); */ public function hasForeignKey($tableName, $columns, $constraint = null); - /** - * Adds the specified foreign key to a database table. - * - * @param \Phinx\Db\Table $table - * @param \Phinx\Db\Table\ForeignKey $foreignKey - * @return void - */ - public function addForeignKey(Table $table, ForeignKey $foreignKey); - - /** - * Drops the specified foreign key from a database table. - * - * @param string $tableName - * @param string[] $columns Column(s) - * @param string $constraint Constraint name - * @return void - */ - public function dropForeignKey($tableName, $columns, $constraint = null); - /** * Returns an array of the supported Phinx column types. * diff --git a/src/Phinx/Db/Adapter/AdapterWrapper.php b/src/Phinx/Db/Adapter/AdapterWrapper.php index 09dcab60d..2425ab31f 100644 --- a/src/Phinx/Db/Adapter/AdapterWrapper.php +++ b/src/Phinx/Db/Adapter/AdapterWrapper.php @@ -351,30 +351,6 @@ public function createTable(Table $table, array $columns = [], array $indexes = $this->getAdapter()->createTable($table, $columns, $indexes); } - /** - * {@inheritdoc} - */ - public function renameTable($tableName, $newTableName) - { - $this->getAdapter()->renameTable($tableName, $newTableName); - } - - /** - * {@inheritdoc} - */ - public function dropTable($tableName) - { - $this->getAdapter()->dropTable($tableName); - } - - /** - * {@inheritdoc} - */ - public function truncateTable($tableName) - { - $this->getAdapter()->truncateTable($tableName); - } - /** * {@inheritdoc} */ @@ -391,38 +367,6 @@ public function hasColumn($tableName, $columnName) return $this->getAdapter()->hasColumn($tableName, $columnName); } - /** - * {@inheritdoc} - */ - public function addColumn(Table $table, Column $column) - { - $this->getAdapter()->addColumn($table, $column); - } - - /** - * {@inheritdoc} - */ - public function renameColumn($tableName, $columnName, $newColumnName) - { - $this->getAdapter()->renameColumn($tableName, $columnName, $newColumnName); - } - - /** - * {@inheritdoc} - */ - public function changeColumn($tableName, $columnName, Column $newColumn) - { - return $this->getAdapter()->changeColumn($tableName, $columnName, $newColumn); - } - - /** - * {@inheritdoc} - */ - public function dropColumn($tableName, $columnName) - { - $this->getAdapter()->dropColumn($tableName, $columnName); - } - /** * {@inheritdoc} */ @@ -439,30 +383,6 @@ public function hasIndexByName($tableName, $indexName) return $this->getAdapter()->hasIndexByName($tableName, $indexName); } - /** - * {@inheritdoc} - */ - public function addIndex(Table $table, Index $index) - { - $this->getAdapter()->addIndex($table, $index); - } - - /** - * {@inheritdoc} - */ - public function dropIndex($tableName, $columns) - { - $this->getAdapter()->dropIndex($tableName, $columns); - } - - /** - * {@inheritdoc} - */ - public function dropIndexByName($tableName, $indexName) - { - $this->getAdapter()->dropIndexByName($tableName, $indexName); - } - /** * {@inheritdoc} */ @@ -471,22 +391,6 @@ public function hasForeignKey($tableName, $columns, $constraint = null) return $this->getAdapter()->hasForeignKey($tableName, $columns, $constraint); } - /** - * {@inheritdoc} - */ - public function addForeignKey(Table $table, ForeignKey $foreignKey) - { - $this->getAdapter()->addForeignKey($table, $foreignKey); - } - - /** - * {@inheritdoc} - */ - public function dropForeignKey($tableName, $columns, $constraint = null) - { - $this->getAdapter()->dropForeignKey($tableName, $columns, $constraint); - } - /** * {@inheritdoc} */ diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php new file mode 100644 index 000000000..e7903e518 --- /dev/null +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -0,0 +1,151 @@ + */ -abstract class PdoAdapter extends AbstractAdapter +abstract class PdoAdapter extends AbstractAdapter implements DirectActionInterface { /** * @var \PDO|null */ protected $connection; + protected function veboseLog($message) + { + if (!$this->isDryRunEnabled() || + OutputInterface::VERBOSITY_VERBOSE < $this->getOutput()->getVerbosity()) { + return; + } + + $this->getOutput()->writeln($message); + } + /** * {@inheritdoc} */ @@ -139,9 +150,9 @@ public function disconnect() */ public function execute($sql) { - if ($this->isDryRunEnabled()) { - $this->getOutput()->writeln($sql); + $this->veboseLog($sql); + if ($this->isDryRunEnabled()) { return 0; } @@ -421,6 +432,13 @@ public function addColumn(Table $table, Column $column) $this->executeAlterSteps($table, $instructions); } + /** + * Returns the instrutions to add the specified column to a database table. + * + * @param \Phinx\Db\Table\Table $table Table + * @param \Phinx\Db\Table\Column $column Column + * @return AlterInstructions + */ abstract protected function getAddColumnInstructions(Table $table, Column $column); /** @@ -432,6 +450,15 @@ public function renameColumn($tableName, $columnName, $newColumnName) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to rename the specified column. + * + * @param string $tableName Table Name + * @param string $columnName Column Name + * @param string $newColumnName New Column Name + * @return AlterInstructions:w + * + */ abstract protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName); /** @@ -443,6 +470,14 @@ public function changeColumn($tableName, $columnName, Column $newColumn) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to change a table column type. + * + * @param string $tableName Table Name + * @param string $columnName Column Name + * @param \Phinx\Db\Table\Column $newColumn New Column + * @return AlterInstructions + */ abstract protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn); /** @@ -454,6 +489,13 @@ public function dropColumn($tableName, $columnName) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to drop the specified column. + * + * @param string $tableName Table Name + * @param string $columnName Column Name + * @return AlterInstructions + */ abstract protected function getDropColumnInstructions($tableName, $columnName); /** @@ -465,6 +507,13 @@ public function addIndex(Table $table, Index $index) $this->executeAlterSteps($table->getName(), $instructions); } + /** + * Returns the instructions to add the specified index to a database table. + * + * @param \Phinx\Db\Table\Table $table Table + * @param \Phinx\Db\Table\Index $index Index + * @return AlterInstructions + */ abstract protected function getAddIndexInstructions(Table $table, Index $index); /** @@ -476,6 +525,13 @@ public function dropIndex($tableName, $columns) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to drop the specified index from a database table. + * + * @param string $tableName + * @param mixed $columns Column(s) + * @return AlterInstructions + */ abstract protected function getDropIndexByColumnsInstructions($tableName, $columns); /** @@ -487,6 +543,13 @@ public function dropIndexByName($tableName, $indexName) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to drop the index specified by name from a database table. + * + * @param string $tableName + * @param string $indexName + * @return void + */ abstract protected function getDropIndexByNameInstructions($tableName, $indexName); /** @@ -498,6 +561,13 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) $this->executeAlterSteps($table->getName(), $instructions); } + /** + * Returns the instructions to adds the specified foreign key to a database table. + * + * @param \Phinx\Db\Table $table + * @param \Phinx\Db\Table\ForeignKey $foreignKey + * @return AlterInstructions + */ abstract protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey); /** @@ -514,11 +584,24 @@ public function dropForeignKey($tableName, $columns, $constraint = null) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to drop the specified foreign key from a database table. + * + * @param string $tableName + * @param string $constraint Constraint name + * @return AlterInstructions + */ abstract protected function getDropForeignKeyInstructions($tableName, $constraint); + /** + * Returns the instructions to drop the specified foreign key from a database table. + * + * @param string $tableName + * @param array $columns The list of column names + * @return AlterInstructions + */ abstract protected function getDropForeignKeyByColumnsInstructions($tableName, $columns); - /** * {@inheritdoc} */ @@ -528,6 +611,12 @@ public function dropTable($tableName) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to drop the specified database table. + * + * @param string $tableName Table Name + * @return AlterInstructions + */ abstract protected function getDropTableInstructions($tableName); /** @@ -539,6 +628,13 @@ public function renameTable($tableName, $newTableName) $this->executeAlterSteps($tableName, $instructions); } + /** + * Returns the instructions to rename the specified database table. + * + * @param string $tableName Table Name + * @param string $newName New Name + * @return AlterInstructions + */ abstract protected function getRenameTableInstructions($tableName, $newTableName); /** diff --git a/src/Phinx/Db/Adapter/TablePrefixAdapter.php b/src/Phinx/Db/Adapter/TablePrefixAdapter.php index cfca4366a..497ddd5b0 100644 --- a/src/Phinx/Db/Adapter/TablePrefixAdapter.php +++ b/src/Phinx/Db/Adapter/TablePrefixAdapter.php @@ -50,7 +50,7 @@ * * @author Samuel Fisher */ -class TablePrefixAdapter extends AdapterWrapper +class TablePrefixAdapter extends AdapterWrapper implements DirectActionInterface { /** * {@inheritdoc} @@ -89,7 +89,7 @@ public function renameTable($tableName, $newTableName) { $adapterTableName = $this->getAdapterTableName($tableName); $adapterNewTableName = $this->getAdapterTableName($newTableName); - parent::renameTable($adapterTableName, $adapterNewTableName); + $this->getAdapter()->renameTable($adapterTableName, $adapterNewTableName); } /** @@ -98,7 +98,7 @@ public function renameTable($tableName, $newTableName) public function dropTable($tableName) { $adapterTableName = $this->getAdapterTableName($tableName); - parent::dropTable($adapterTableName); + $this->getAdapter()->dropTable($adapterTableName); } /** @@ -137,7 +137,7 @@ public function addColumn(Table $table, Column $column) { $adapterTableName = $this->getAdapterTableName($table->getName()); $adapterTable = new Table($adapterTableName, $table->getOptions()); - parent::addColumn($adapterTable, $column); + $this->getAdapter()->addColumn($adapterTable, $column); } /** @@ -146,7 +146,7 @@ public function addColumn(Table $table, Column $column) public function renameColumn($tableName, $columnName, $newColumnName) { $adapterTableName = $this->getAdapterTableName($tableName); - parent::renameColumn($adapterTableName, $columnName, $newColumnName); + $this->getAdapter()->renameColumn($adapterTableName, $columnName, $newColumnName); } /** @@ -156,7 +156,7 @@ public function changeColumn($tableName, $columnName, Column $newColumn) { $adapterTableName = $this->getAdapterTableName($tableName); - return parent::changeColumn($adapterTableName, $columnName, $newColumn); + return $this->getAdapter()->changeColumn($adapterTableName, $columnName, $newColumn); } /** @@ -165,7 +165,7 @@ public function changeColumn($tableName, $columnName, Column $newColumn) public function dropColumn($tableName, $columnName) { $adapterTableName = $this->getAdapterTableName($tableName); - parent::dropColumn($adapterTableName, $columnName); + $this->getAdapter()->dropColumn($adapterTableName, $columnName); } /** @@ -194,7 +194,7 @@ public function hasIndexByName($tableName, $indexName) public function addIndex(Table $table, Index $index) { $adapterTable = new Table($table->getName(), $table->getOptions()); - parent::addIndex($adapterTable, $index); + $this->getAdapter()->addIndex($adapterTable, $index); } /** @@ -203,7 +203,7 @@ public function addIndex(Table $table, Index $index) public function dropIndex($tableName, $columns) { $adapterTableName = $this->getAdapterTableName($tableName); - parent::dropIndex($adapterTableName, $columns); + $this->getAdapter()->dropIndex($adapterTableName, $columns); } /** @@ -212,7 +212,7 @@ public function dropIndex($tableName, $columns) public function dropIndexByName($tableName, $indexName) { $adapterTableName = $this->getAdapterTableName($tableName); - parent::dropIndexByName($adapterTableName, $indexName); + $this->getAdapter()->dropIndexByName($adapterTableName, $indexName); } /** @@ -232,7 +232,7 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) { $adapterTableName = $this->getAdapterTableName($table->getName()); $adapterTable = new Table($adapterTableName, $table->getOptions()); - parent::addForeignKey($adapterTable, $foreignKey); + $this->getAdapter()->addForeignKey($adapterTable, $foreignKey); } /** @@ -241,7 +241,7 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) public function dropForeignKey($tableName, $columns, $constraint = null) { $adapterTableName = $this->getAdapterTableName($tableName); - parent::dropForeignKey($adapterTableName, $columns, $constraint); + $this->getAdapter()->dropForeignKey($adapterTableName, $columns, $constraint); } /** @@ -358,5 +358,4 @@ public function executeActions(Table $table, array $actions) parent::executeActions($adapterTable, $actions); } - } diff --git a/src/Phinx/Db/Adapter/TimedOutputAdapter.php b/src/Phinx/Db/Adapter/TimedOutputAdapter.php index 90e867ad1..f7f8ae0cf 100644 --- a/src/Phinx/Db/Adapter/TimedOutputAdapter.php +++ b/src/Phinx/Db/Adapter/TimedOutputAdapter.php @@ -37,7 +37,7 @@ /** * Wraps any adpter to record the time spend executing its commands */ -class TimedOutputAdapter extends AdapterWrapper +class TimedOutputAdapter extends AdapterWrapper implements DirectActionInterface { /** @@ -321,4 +321,16 @@ public function dropSchema($name) parent::dropSchema($name); $end(); } + + /** + * {@inheritdoc} + */ + public function executeActions(Table $table, array $actions) + { + $end = $this->startCommandTimer(); + $this->writeCommand(sprintf('Altering table %s', $table->getName())); + $res = parent::executeActions($table, $actions); + $end(); + return $res; + } } diff --git a/tests/Phinx/Migration/_files/reversiblemigrations/20180431121930_tricky_edge_case.php b/tests/Phinx/Migration/_files/reversiblemigrations/20180431121930_tricky_edge_case.php new file mode 100644 index 000000000..c505200f5 --- /dev/null +++ b/tests/Phinx/Migration/_files/reversiblemigrations/20180431121930_tricky_edge_case.php @@ -0,0 +1,20 @@ +table('user_logins'); + $table + ->rename('just_logins') + ->addColumn('thingy', 'string', [ + 'limit' => 12, + 'null' => true, + ]) + ->addColumn('thingy2', 'integer') + ->addIndex(['thingy']) + ->save(); + } +} From 4701832267ae0823445a1fdf19ea09603008d327 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 11:06:56 +0200 Subject: [PATCH 05/21] Cosmetic changes --- src/Phinx/Db/Adapter/ProxyAdapter.php | 2 +- src/Phinx/Migration/Migration.template.php.dist | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Phinx/Db/Adapter/ProxyAdapter.php b/src/Phinx/Db/Adapter/ProxyAdapter.php index e4e7ed015..d9ebee1fd 100644 --- a/src/Phinx/Db/Adapter/ProxyAdapter.php +++ b/src/Phinx/Db/Adapter/ProxyAdapter.php @@ -91,7 +91,7 @@ public function getInvertedCommands() { $inverted = new Intent(); - foreach (array_reverse($this->commands) as $com) { + foreach (array_reverse($this->commands) as $com) { switch (true) { case $com instanceof CreateTable: $inverted->addAction(new DropTable($com->getTable())); diff --git a/src/Phinx/Migration/Migration.template.php.dist b/src/Phinx/Migration/Migration.template.php.dist index e9afb2de2..92e3424b0 100644 --- a/src/Phinx/Migration/Migration.template.php.dist +++ b/src/Phinx/Migration/Migration.template.php.dist @@ -23,8 +23,8 @@ class $className extends $baseClassName * addIndex * addForeignKey * - * Remember to call "create()" or "update()" and NOT "save()" when working - * with the Table class. + * Any other distructive changes will result in an error when trying to + * rollback the migration. */ public function change() { From eb68c215b4171556eef036c999626e5bfaa98d16 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 11:24:21 +0200 Subject: [PATCH 06/21] fixed verbose logging --- src/Phinx/Db/Adapter/PdoAdapter.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index 657ab8655..34df4b397 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -59,10 +59,10 @@ abstract class PdoAdapter extends AbstractAdapter implements DirectActionInterfa */ protected $connection; - protected function veboseLog($message) + protected function verboseLog($message) { - if (!$this->isDryRunEnabled() || - OutputInterface::VERBOSITY_VERBOSE < $this->getOutput()->getVerbosity()) { + if (!$this->isDryRunEnabled() && + $this->getOutput()->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) { return; } @@ -150,7 +150,7 @@ public function disconnect() */ public function execute($sql) { - $this->veboseLog($sql); + $this->verboseLog($sql); if ($this->isDryRunEnabled()) { return 0; @@ -240,6 +240,11 @@ public function bulkinsert(Table $table, $rows) $queries = array_fill(0, $count_vars, $query); $sql .= implode(',', $queries); + if ($this->isDryRunEnabled()) { + $this->verboseLog($sql); + return; + } + $stmt = $this->getConnection()->prepare($sql); $stmt->execute($vals); } From 345a16370604261bf9dd096af5bbd08ba502ddd6 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 12:30:52 +0200 Subject: [PATCH 07/21] Added doc blocks --- src/Phinx/Db/Action/Action.php | 24 +++++- src/Phinx/Db/Action/AddColumn.php | 24 +++++- src/Phinx/Db/Action/AddForeignKey.php | 24 +++++- src/Phinx/Db/Action/AddIndex.php | 24 +++++- src/Phinx/Db/Action/ChangeColumn.php | 24 +++++- src/Phinx/Db/Action/CreateTable.php | 24 +++++- src/Phinx/Db/Action/DropForeignKey.php | 24 +++++- src/Phinx/Db/Action/DropIndex.php | 24 +++++- src/Phinx/Db/Action/DropTable.php | 24 +++++- src/Phinx/Db/Action/RemoveColumn.php | 24 +++++- src/Phinx/Db/Action/RenameColumn.php | 24 +++++- src/Phinx/Db/Action/RenameTable.php | 24 +++++- .../Db/Adapter/DirectActionInterface.php | 3 - src/Phinx/Db/Plan/AlterTable.php | 58 +++++++++++++- src/Phinx/Db/Plan/Intent.php | 49 +++++++++++- src/Phinx/Db/Plan/NewTable.php | 75 +++++++++++++++++- src/Phinx/Db/Plan/Plan.php | 73 ++++++++++++++++- src/Phinx/Db/Util/AlterInstructions.php | 78 ++++++++++++++++++- 18 files changed, 604 insertions(+), 20 deletions(-) diff --git a/src/Phinx/Db/Action/Action.php b/src/Phinx/Db/Action/Action.php index 158092a73..556c07935 100644 --- a/src/Phinx/Db/Action/Action.php +++ b/src/Phinx/Db/Action/Action.php @@ -1,5 +1,27 @@ table = $table; } + /** + * Adds another action to the collection + * + * @param Action $action + */ public function addAction(Action $action) { $this->actions[] = $action; } + /** + * Returns the table associated to this collection + * + * @return Table + */ public function getTable() { return $this->table; } + /** + * Returns an array with all collected actions + * + * @return Action[] + */ public function getActions() { return $this->actions; diff --git a/src/Phinx/Db/Plan/Intent.php b/src/Phinx/Db/Plan/Intent.php index 5567911cc..24f09335a 100644 --- a/src/Phinx/Db/Plan/Intent.php +++ b/src/Phinx/Db/Plan/Intent.php @@ -1,24 +1,71 @@ actions[] = $action; } + /** + * Returns the full list of actions + * + * @return Action[] + */ public function getActions() { return $this->actions; } + /** + * Merges another Intent object with this one + * + * @param Intent $another + */ public function merge(Intent $another) { $this->actions = array_merge($this->actions, $another->getActions()); diff --git a/src/Phinx/Db/Plan/NewTable.php b/src/Phinx/Db/Plan/NewTable.php index 5da2d2302..1bca11638 100644 --- a/src/Phinx/Db/Plan/NewTable.php +++ b/src/Phinx/Db/Plan/NewTable.php @@ -1,44 +1,117 @@ table = $table; } + /** + * Adds a column to the collection + * + * @param Column $column + * @return void + */ public function addColumn(Column $column) { $this->columns[] = $column; } + /** + * Adds an index to the collection + * + * @param Index $index + * @return void + */ public function addIndex(Index $index) { $this->indexes[] = $index; } + /** + * Retunrns the table object associated to this collection + * + * @return Table + */ public function getTable() { return $this->table; } + /** + * Returns the columns collection + * + * @return Column[] + */ public function getColumns() { return $this->columns; } + /** + * Returns the indexes collection + * + * @return Index[] + */ public function getIndexes() { return $this->indexes; diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php index 1fd271378..571d284e7 100644 --- a/src/Phinx/Db/Plan/Plan.php +++ b/src/Phinx/Db/Plan/Plan.php @@ -1,5 +1,27 @@ createPlan($intent->getActions()); @@ -54,6 +113,12 @@ protected function updatesSequence() ]; } + /** + * Executes this plan using the given AdapterInterface + * + * @param AdapterInterface $executor + * @return void + */ public function execute(AdapterInterface $executor) { foreach ($this->tableCreates as $newTable) { @@ -67,6 +132,12 @@ public function execute(AdapterInterface $executor) }); } + /** + * Executes the inverse plan (rollback the actions) with the given AdapterInterface:w + * + * @param AdapterInterface $executor + * @return void + */ public function executeInverse(AdapterInterface $executor) { collection(array_reverse($this->updatesSequence())) diff --git a/src/Phinx/Db/Util/AlterInstructions.php b/src/Phinx/Db/Util/AlterInstructions.php index f1ba49f2b..383dcad0a 100644 --- a/src/Phinx/Db/Util/AlterInstructions.php +++ b/src/Phinx/Db/Util/AlterInstructions.php @@ -1,46 +1,122 @@ alterParts = $alterParts; $this->postSteps = $postSteps; } + /** + * Adds another parst for the single ALTER instruction + * + * @param string $part + */ public function addAlter($part) { $this->alterParts[] = $part; } + /** + * Adds a SQL command to be eecuted after the ALTER instruction. + * This method allows a callable, with will get an empty array as state + * for the first time and will pass the return value of the callable to + * the next callable, if present. + * + * This allows to keep a single state across callbacks. + * + * @param stirng|callable $sql + */ public function addPostStep($sql) { $this->postSteps[] = $sql; } + /** + * Returns the alter SQL snippets + * + * @return string[] + */ public function getAlterParts() { return $this->alterParts; } + /** + * Returns the SQL commands to run after the ALTER instrunction + * + * @return mixed[] + */ public function getPostSteps() { return $this->postSteps; } + /** + * Merges another AlterInstructions object to this one + * + * @param AlterInstructions $other + * @return void + */ public function merge(AlterInstructions $other) { $this->alterParts = array_merge($this->alterParts, $other->getAlterParts()); $this->postSteps = array_merge($this->postSteps, $other->getPostSteps()); } + /** + * Executes the ALTER instruction and all of the post steps. + * + * @param string $alterTemplate The template for the alter instruction + * @param callable $executor The function to be used to execute all instructions + * @return void + */ public function execute($alterTemplate, callable $executor) { if ($this->alterParts) { From 38a3bd00f969fb9adffb9d021a62a755446e204c Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 13:10:30 +0200 Subject: [PATCH 08/21] Fixing some errors --- composer.json | 2 +- src/Phinx/Db/Action/Action.php | 4 ++-- src/Phinx/Db/Plan/AlterTable.php | 2 +- src/Phinx/Db/Table/Table.php | 5 +++++ src/Phinx/Db/Util/AlterInstructions.php | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 786f8b40a..cec164fcc 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "symfony/yaml": "^2.8|^3.0|^4.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35|^5.7|^6.5", + "phpunit/phpunit": ">=6.5", "sebastian/comparator": ">=1.2.3", "cakephp/cakephp-codesniffer": "^3.0" }, diff --git a/src/Phinx/Db/Action/Action.php b/src/Phinx/Db/Action/Action.php index 556c07935..ad6c02875 100644 --- a/src/Phinx/Db/Action/Action.php +++ b/src/Phinx/Db/Action/Action.php @@ -28,14 +28,14 @@ abstract class Action { /** - * @var Phinx\Db\Table\Table + * @var \Phinx\Db\Table\Table */ protected $table; /** * The table this action will be applied to * - * @return Phinx\Db\Table\Table + * @return \Phinx\Db\Table\Table */ public function getTable() { diff --git a/src/Phinx/Db/Plan/AlterTable.php b/src/Phinx/Db/Plan/AlterTable.php index 303f539de..d07e60fc1 100644 --- a/src/Phinx/Db/Plan/AlterTable.php +++ b/src/Phinx/Db/Plan/AlterTable.php @@ -43,7 +43,7 @@ class AlterTable /** * The listo of actions to execute * - * @var Phinx\Db\Action\Action[] + * @var \Phinx\Db\Action\Action[] */ protected $actions = []; diff --git a/src/Phinx/Db/Table/Table.php b/src/Phinx/Db/Table/Table.php index e0487fce8..d2264b762 100644 --- a/src/Phinx/Db/Table/Table.php +++ b/src/Phinx/Db/Table/Table.php @@ -10,6 +10,11 @@ class Table */ protected $name; + /** + * @var array + */ + protected $options; + /** * @param string $name The table name */ diff --git a/src/Phinx/Db/Util/AlterInstructions.php b/src/Phinx/Db/Util/AlterInstructions.php index 383dcad0a..978dfd815 100644 --- a/src/Phinx/Db/Util/AlterInstructions.php +++ b/src/Phinx/Db/Util/AlterInstructions.php @@ -71,7 +71,7 @@ public function addAlter($part) * * This allows to keep a single state across callbacks. * - * @param stirng|callable $sql + * @param string|callable $sql */ public function addPostStep($sql) { From 77ae49e22ee0a287628ec5a903033146223baeed Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 13:10:59 +0200 Subject: [PATCH 09/21] Not more support for php <5.6 --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a16da518..49b7ce5d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,6 @@ addons: postgresql: "9.2" php: - - 5.4 - - 5.5 - 5.6 - 7.0 - 7.1 From b7de143373179e0220f222bba816669a2fb36e7c Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 13:15:28 +0200 Subject: [PATCH 10/21] More tests fixes --- composer.json | 2 +- src/Phinx/Db/Adapter/AdapterInterface.php | 2 +- src/Phinx/Db/Adapter/DirectActionInterface.php | 2 +- src/Phinx/Db/Adapter/SQLiteAdapter.php | 2 +- src/Phinx/Db/Adapter/SqlServerAdapter.php | 2 +- src/Phinx/Db/Adapter/TimedOutputAdapter.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index cec164fcc..544482d64 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ "symfony/yaml": "^2.8|^3.0|^4.0" }, "require-dev": { - "phpunit/phpunit": ">=6.5", + "phpunit/phpunit": ">=5.7", "sebastian/comparator": ">=1.2.3", "cakephp/cakephp-codesniffer": "^3.0" }, diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index aa0951396..41a8af54a 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -28,10 +28,10 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; use Phinx\Migration\MigrationInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php index 7f14ac5c1..bc8fdd185 100644 --- a/src/Phinx/Db/Adapter/DirectActionInterface.php +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -24,10 +24,10 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; use Phinx\Migration\MigrationInterface; /** diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index 5e2072681..eb282aa72 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -28,10 +28,10 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; use Phinx\Db\Util\AlterInstructions; /** diff --git a/src/Phinx/Db/Adapter/SqlServerAdapter.php b/src/Phinx/Db/Adapter/SqlServerAdapter.php index 575949cfd..3e36cf88e 100644 --- a/src/Phinx/Db/Adapter/SqlServerAdapter.php +++ b/src/Phinx/Db/Adapter/SqlServerAdapter.php @@ -28,10 +28,10 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; use Phinx\Db\Util\AlterInstructions; /** diff --git a/src/Phinx/Db/Adapter/TimedOutputAdapter.php b/src/Phinx/Db/Adapter/TimedOutputAdapter.php index f7f8ae0cf..ff12ab8b0 100644 --- a/src/Phinx/Db/Adapter/TimedOutputAdapter.php +++ b/src/Phinx/Db/Adapter/TimedOutputAdapter.php @@ -28,10 +28,10 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; use Symfony\Component\Console\Output\OutputInterface; /** From dc1248bf67a0618120985881b59dc42fd33af452 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 13:41:19 +0200 Subject: [PATCH 11/21] Fixed some errors --- src/Phinx/Db/Adapter/AdapterInterface.php | 8 +++ .../Db/Adapter/DirectActionInterface.php | 8 --- src/Phinx/Db/Adapter/PdoAdapter.php | 4 +- src/Phinx/Db/Adapter/SQLiteAdapter.php | 17 +++-- src/Phinx/Db/Adapter/SqlServerAdapter.php | 4 +- src/Phinx/Db/Adapter/TablePrefixAdapter.php | 67 ++++++++++++++++--- src/Phinx/Db/Table.php | 4 +- src/Phinx/Db/Table/ForeignKey.php | 2 +- src/Phinx/Db/Table/Table.php | 6 +- src/Phinx/Db/Util/AlterInstructions.php | 8 ++- tests/Phinx/Db/Adapter/MysqlAdapterTest.php | 1 - .../Db/Adapter/TablePrefixAdapterTest.php | 3 +- tests/Phinx/Db/TableTest.php | 1 + 13 files changed, 94 insertions(+), 39 deletions(-) diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index 41a8af54a..8abb9e2ee 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -342,6 +342,14 @@ public function hasTable($tableName); */ public function createTable(Table $table, array $columns = [], array $indexes = []); + /** + * Truncates the specified table + * + * @param string $tableName + * @return void + */ + public function truncateTable($tableName); + /** * Returns table columns * diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php index bc8fdd185..53e98f050 100644 --- a/src/Phinx/Db/Adapter/DirectActionInterface.php +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -54,14 +54,6 @@ public function renameTable($tableName, $newName); */ public function dropTable($tableName); - /** - * Truncates the specified table - * - * @param string $tableName - * @return void - */ - public function truncateTable($tableName); - /** * Adds the specified column to a database table. * diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index 34df4b397..888eeb986 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -433,7 +433,7 @@ protected function executeAlterSteps($tableName, AlterInstructions $instructions */ public function addColumn(Table $table, Column $column) { - $instructions = $this->getAddColumnInstructions($column); + $instructions = $this->getAddColumnInstructions($table, $column); $this->executeAlterSteps($table, $instructions); } @@ -553,7 +553,7 @@ public function dropIndexByName($tableName, $indexName) * * @param string $tableName * @param string $indexName - * @return void + * @return AlterInstructions */ abstract protected function getDropIndexByNameInstructions($tableName, $indexName); diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index eb282aa72..b929f3ffe 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -421,7 +421,7 @@ protected function getRenameColumnInstructions($tableName, $columnName, $newColu return $newState + $state; }); - $instructions->addPostStep(function ($state) use ($tableName, $columnName, $newColumnName) { + $instructions->addPostStep(function ($state) use ($columnName, $newColumnName) { $sql = str_replace( $this->quoteColumnName($columnName), $this->quoteColumnName($newColumnName), @@ -449,7 +449,7 @@ protected function getChangeColumnInstructions($tableName, $columnName, Column $ return $newState + $state; }); - $instructions->addPostStep(function ($state) use ($tableName, $columnName, $newColumn) { + $instructions->addPostStep(function ($state) use ($columnName, $newColumn) { $sql = preg_replace( sprintf("/%s(?:\/\*.*?\*\/|\([^)]+\)|'[^']*?'|[^,])+([,)])/", $this->quoteColumnName($columnName)), sprintf('%s %s$1', $this->quoteColumnName($newColumn->getName()), $this->getColumnSqlDefinition($newColumn)), @@ -477,7 +477,7 @@ protected function getDropColumnInstructions($tableName, $columnName) return $newState + $state; }); - $instructions->addPostStep(function ($state) use ($tableName, $columnName) { + $instructions->addPostStep(function ($state) use ($columnName) { $sql = preg_replace( sprintf("/%s\s%s.*(,\s(?!')|\)$)/U", preg_quote($this->quoteColumnName($columnName)), preg_quote($state['columnType'])), "", @@ -691,7 +691,7 @@ protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreig return $state; }); - $instructions->addPostStep(function ($state) use ($foreignKey) { + $instructions->addPostStep(function ($state) { $columns = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($state['tmpTableName']))); $names = array_map([$this, 'quoteColumnName'], array_column($columns, 'name')); $selectColumns = $writeColumns = $names; @@ -737,7 +737,9 @@ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) return $newState + $state; }); - $instructions->addPostStep(function ($state) use ($tableName, $columns) { + $instructions->addPostStep(function ($state) use ($columns) { + $sql = ''; + foreach ($columns as $columnName) { $search = sprintf( "/,[^,]*\(%s(?:,`?(.*)`?)?\) REFERENCES[^,]*\([^\)]*\)[^,)]*/", @@ -745,7 +747,10 @@ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) ); $sql = preg_replace($search, '', $state['createSQL'], 1); } - $this->execute($sql); + + if ($sql) { + $this->execute($sql); + } return $state; }); diff --git a/src/Phinx/Db/Adapter/SqlServerAdapter.php b/src/Phinx/Db/Adapter/SqlServerAdapter.php index 3e36cf88e..c540ae863 100644 --- a/src/Phinx/Db/Adapter/SqlServerAdapter.php +++ b/src/Phinx/Db/Adapter/SqlServerAdapter.php @@ -564,7 +564,7 @@ protected function getDropDefaultConstraint($tableName, $columnName) return new AlterInstructions(); } - return $this->getDropForeignKeyInstructions($tableName, $columnName, $defaultConstraint); + return $this->getDropForeignKeyInstructions($tableName, $defaultConstraint); } protected function getDefaultConstraint($tableName, $columnName) @@ -859,7 +859,7 @@ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) )); foreach ($rows as $row) { $instructions->merge( - $this->getDropForeignKeyInstructions($tableName, $columns, $row['constraint_name']) + $this->getDropForeignKeyInstructions($tableName, $row['constraint_name']) ); } } diff --git a/src/Phinx/Db/Adapter/TablePrefixAdapter.php b/src/Phinx/Db/Adapter/TablePrefixAdapter.php index 497ddd5b0..7d34d4f3b 100644 --- a/src/Phinx/Db/Adapter/TablePrefixAdapter.php +++ b/src/Phinx/Db/Adapter/TablePrefixAdapter.php @@ -87,9 +87,14 @@ public function createTable(Table $table, array $columns = [], array $indexes = */ public function renameTable($tableName, $newTableName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } + $adapterTableName = $this->getAdapterTableName($tableName); $adapterNewTableName = $this->getAdapterTableName($newTableName); - $this->getAdapter()->renameTable($adapterTableName, $adapterNewTableName); + $adapter->renameTable($adapterTableName, $adapterNewTableName); } /** @@ -97,8 +102,12 @@ public function renameTable($tableName, $newTableName) */ public function dropTable($tableName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - $this->getAdapter()->dropTable($adapterTableName); + $adapter->dropTable($adapterTableName); } /** @@ -135,9 +144,13 @@ public function hasColumn($tableName, $columnName) */ public function addColumn(Table $table, Column $column) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($table->getName()); $adapterTable = new Table($adapterTableName, $table->getOptions()); - $this->getAdapter()->addColumn($adapterTable, $column); + $adapter->addColumn($adapterTable, $column); } /** @@ -145,8 +158,12 @@ public function addColumn(Table $table, Column $column) */ public function renameColumn($tableName, $columnName, $newColumnName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - $this->getAdapter()->renameColumn($adapterTableName, $columnName, $newColumnName); + $adapter->renameColumn($adapterTableName, $columnName, $newColumnName); } /** @@ -154,9 +171,13 @@ public function renameColumn($tableName, $columnName, $newColumnName) */ public function changeColumn($tableName, $columnName, Column $newColumn) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - return $this->getAdapter()->changeColumn($adapterTableName, $columnName, $newColumn); + return $adapter->changeColumn($adapterTableName, $columnName, $newColumn); } /** @@ -164,8 +185,12 @@ public function changeColumn($tableName, $columnName, Column $newColumn) */ public function dropColumn($tableName, $columnName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - $this->getAdapter()->dropColumn($adapterTableName, $columnName); + $adapter->dropColumn($adapterTableName, $columnName); } /** @@ -193,8 +218,12 @@ public function hasIndexByName($tableName, $indexName) */ public function addIndex(Table $table, Index $index) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTable = new Table($table->getName(), $table->getOptions()); - $this->getAdapter()->addIndex($adapterTable, $index); + $adapter->addIndex($adapterTable, $index); } /** @@ -202,8 +231,12 @@ public function addIndex(Table $table, Index $index) */ public function dropIndex($tableName, $columns) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - $this->getAdapter()->dropIndex($adapterTableName, $columns); + $adapter->dropIndex($adapterTableName, $columns); } /** @@ -211,8 +244,12 @@ public function dropIndex($tableName, $columns) */ public function dropIndexByName($tableName, $indexName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - $this->getAdapter()->dropIndexByName($adapterTableName, $indexName); + $adapter->dropIndexByName($adapterTableName, $indexName); } /** @@ -230,9 +267,13 @@ public function hasForeignKey($tableName, $columns, $constraint = null) */ public function addForeignKey(Table $table, ForeignKey $foreignKey) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($table->getName()); $adapterTable = new Table($adapterTableName, $table->getOptions()); - $this->getAdapter()->addForeignKey($adapterTable, $foreignKey); + $adapter->addForeignKey($adapterTable, $foreignKey); } /** @@ -240,8 +281,12 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) */ public function dropForeignKey($tableName, $columns, $constraint = null) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); + } $adapterTableName = $this->getAdapterTableName($tableName); - $this->getAdapter()->dropForeignKey($adapterTableName, $columns, $constraint); + $adapter->dropForeignKey($adapterTableName, $columns, $constraint); } /** diff --git a/src/Phinx/Db/Table.php b/src/Phinx/Db/Table.php index 6ccddf898..c9e61e0d6 100644 --- a/src/Phinx/Db/Table.php +++ b/src/Phinx/Db/Table.php @@ -162,7 +162,7 @@ public function exists() /** * Drops the database table. * - * @return void + * @return \Phinx\Db\Table */ public function drop() { @@ -577,7 +577,7 @@ public function saveData() } /** - * Truncates the table. + * Immediately truncates the table. This operation cannot be undone * * @return void */ diff --git a/src/Phinx/Db/Table/ForeignKey.php b/src/Phinx/Db/Table/ForeignKey.php index d9483a41c..14652d4c7 100644 --- a/src/Phinx/Db/Table/ForeignKey.php +++ b/src/Phinx/Db/Table/ForeignKey.php @@ -94,7 +94,7 @@ public function getColumns() /** * Sets the foreign key referenced table. * - * @param \Phinx\Db\Table\Table $table + * @param \Phinx\Db\Table\Table $table The table this KEY is pointing to * @return \Phinx\Db\Table\ForeignKey */ public function setReferencedTable(Table $table) diff --git a/src/Phinx/Db/Table/Table.php b/src/Phinx/Db/Table/Table.php index d2264b762..78e5e3477 100644 --- a/src/Phinx/Db/Table/Table.php +++ b/src/Phinx/Db/Table/Table.php @@ -17,6 +17,7 @@ class Table /** * @param string $name The table name + * @param array $options The creation options for this table */ public function __construct($name, array $options = []) { @@ -31,7 +32,7 @@ public function __construct($name, array $options = []) /** * Sets the table name. * - * @param string $name + * @param string $name The name of the table * @return \Phinx\Db\Table\Table */ public function setName($name) @@ -64,7 +65,8 @@ public function getOptions() /** * Sets the table options * - * @return array + * @return array The options for this table to use for creating it + * @return void */ public function setOptions(array $options) { diff --git a/src/Phinx/Db/Util/AlterInstructions.php b/src/Phinx/Db/Util/AlterInstructions.php index 978dfd815..19687fdac 100644 --- a/src/Phinx/Db/Util/AlterInstructions.php +++ b/src/Phinx/Db/Util/AlterInstructions.php @@ -56,7 +56,8 @@ public function __construct(array $alterParts = [], array $postSteps = []) /** * Adds another parst for the single ALTER instruction * - * @param string $part + * @param string $part The SQL snipped to add as part of the ALTER instruction + * @return void */ public function addAlter($part) { @@ -71,7 +72,8 @@ public function addAlter($part) * * This allows to keep a single state across callbacks. * - * @param string|callable $sql + * @param string|callable $sql The SQL to run after, or a callable to execute + * @return void */ public function addPostStep($sql) { @@ -101,7 +103,7 @@ public function getPostSteps() /** * Merges another AlterInstructions object to this one * - * @param AlterInstructions $other + * @param AlterInstructions $other The other collection of instructions to merge in * @return void */ public function merge(AlterInstructions $other) diff --git a/tests/Phinx/Db/Adapter/MysqlAdapterTest.php b/tests/Phinx/Db/Adapter/MysqlAdapterTest.php index 59ff7ed2c..7eccb5c68 100644 --- a/tests/Phinx/Db/Adapter/MysqlAdapterTest.php +++ b/tests/Phinx/Db/Adapter/MysqlAdapterTest.php @@ -503,7 +503,6 @@ public function testRenameColumn() $this->assertTrue($this->adapter->hasColumn('t', 'column1')); $this->assertFalse($this->adapter->hasColumn('t', 'column2')); - $table->renameColumn('column1', 'column2')->save(); $this->assertFalse($this->adapter->hasColumn('t', 'column1')); $this->assertTrue($this->adapter->hasColumn('t', 'column2')); diff --git a/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php b/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php index afdb84dfe..7db5a8a54 100644 --- a/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php +++ b/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php @@ -317,6 +317,7 @@ function ($table) { public function actionsProvider() { $table = new Table('my_test'); + return [ [AddColumn::build($table, 'acolumn')], [AddIndex::build($table, ['acolumn'])], @@ -334,7 +335,7 @@ public function actionsProvider() /** * @dataProvider actionsProvider */ - public function testExecuteActions($action, $checkReferecedTable = false) + public function testExecuteActions($action, $checkReferecedTable = false) { $this->mock->expects($this->once()) ->method('executeActions') diff --git a/tests/Phinx/Db/TableTest.php b/tests/Phinx/Db/TableTest.php index 11b917f7c..8149d7aea 100644 --- a/tests/Phinx/Db/TableTest.php +++ b/tests/Phinx/Db/TableTest.php @@ -204,6 +204,7 @@ protected function getPendingActions($table) { $prop = new \ReflectionProperty(get_class($table), 'actions'); $prop->setAccessible(true); + return $prop->getValue($table)->getActions(); } } From 039ab173f5944626c0e7ea336015d93fabaa24df Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sat, 28 Apr 2018 13:44:06 +0200 Subject: [PATCH 12/21] Added missing method --- src/Phinx/Db/Adapter/AdapterWrapper.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Phinx/Db/Adapter/AdapterWrapper.php b/src/Phinx/Db/Adapter/AdapterWrapper.php index 2425ab31f..7630572d1 100644 --- a/src/Phinx/Db/Adapter/AdapterWrapper.php +++ b/src/Phinx/Db/Adapter/AdapterWrapper.php @@ -439,6 +439,14 @@ public function dropSchema($schemaName) $this->getAdapter()->dropSchema($schemaName); } + /** + * {@inheritdoc} + */ + public function truncateTable($tableName) + { + $this->getAdapter()->truncateTable($tableName); + } + /** * {@inheritdoc} */ From 8bbf15b8ee0d9bf07e6e2738bbb0424604db0d49 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 29 Apr 2018 10:42:03 +0200 Subject: [PATCH 13/21] Adding doc blocks and fixing coding style issues --- src/Phinx/Db/Action/Action.php | 7 +++ src/Phinx/Db/Action/AddColumn.php | 26 +++++++- src/Phinx/Db/Action/AddForeignKey.php | 18 +++++- src/Phinx/Db/Action/AddIndex.php | 26 +++++++- src/Phinx/Db/Action/ChangeColumn.php | 38 +++++++++++- src/Phinx/Db/Action/CreateTable.php | 5 -- src/Phinx/Db/Action/DropForeignKey.php | 26 +++++++- src/Phinx/Db/Action/DropIndex.php | 32 +++++++++- src/Phinx/Db/Action/DropTable.php | 7 --- src/Phinx/Db/Action/RemoveColumn.php | 25 +++++++- src/Phinx/Db/Action/RenameColumn.php | 37 ++++++++++- src/Phinx/Db/Action/RenameTable.php | 18 +++++- src/Phinx/Db/Adapter/AdapterInterface.php | 2 +- src/Phinx/Db/Adapter/AdapterWrapper.php | 2 +- .../Db/Adapter/DirectActionInterface.php | 6 +- src/Phinx/Db/Adapter/PdoAdapter.php | 21 ++++--- src/Phinx/Db/Adapter/PostgresAdapter.php | 1 + src/Phinx/Db/Adapter/SQLiteAdapter.php | 40 ++++++++++++ src/Phinx/Db/Adapter/SqlServerAdapter.php | 10 +++ src/Phinx/Db/Adapter/TablePrefixAdapter.php | 3 +- src/Phinx/Db/Adapter/TimedOutputAdapter.php | 3 +- src/Phinx/Db/Plan/AlterTable.php | 5 +- src/Phinx/Db/Plan/Intent.php | 5 +- src/Phinx/Db/Plan/NewTable.php | 4 +- src/Phinx/Db/Plan/Plan.php | 62 +++++++++++++++++-- 25 files changed, 381 insertions(+), 48 deletions(-) diff --git a/src/Phinx/Db/Action/Action.php b/src/Phinx/Db/Action/Action.php index ad6c02875..5868e09c7 100644 --- a/src/Phinx/Db/Action/Action.php +++ b/src/Phinx/Db/Action/Action.php @@ -24,6 +24,8 @@ */ namespace Phinx\Db\Action; +use \Phinx\Db\Table\Table; + abstract class Action { @@ -32,6 +34,11 @@ abstract class Action */ protected $table; + public function __construct(Table $table) + { + $this->table = $table; + } + /** * The table this action will be applied to * diff --git a/src/Phinx/Db/Action/AddColumn.php b/src/Phinx/Db/Action/AddColumn.php index 58b6ef880..d0e700d3f 100644 --- a/src/Phinx/Db/Action/AddColumn.php +++ b/src/Phinx/Db/Action/AddColumn.php @@ -30,14 +30,33 @@ class AddColumn extends Action { + /** + * The column to add + * + * @var Column + */ protected $column; + /** + * Constructo + * + * @param Table $table The table to add the column to + * @param Column $column The column to add + */ public function __construct(Table $table, Column $column) { - $this->table = $table; + parent::__construct($table); $this->column = $column; } + /** + * Returns a new AddColumn object after assembling the given commands + * + * @param Table $table The table to add the column to + * @param mixed $columnName The column name + * @param mixed $type The column type + * @param mixed $options The column options + */ public static function build(Table $table, $columnName, $type = null, $options = []) { $column = new Column(); @@ -48,6 +67,11 @@ public static function build(Table $table, $columnName, $type = null, $options = return new static($table, $column); } + /** + * Returns the column to be added + * + * @return Column + */ public function getColumn() { return $this->column; diff --git a/src/Phinx/Db/Action/AddForeignKey.php b/src/Phinx/Db/Action/AddForeignKey.php index eb92f20ce..b60d7bce2 100644 --- a/src/Phinx/Db/Action/AddForeignKey.php +++ b/src/Phinx/Db/Action/AddForeignKey.php @@ -31,11 +31,22 @@ class AddForeignKey extends Action { + /** + * The foreign key to add + * + * @var ForeignKey + */ protected $foreignKey; + /** + * Constructor + * + * @param Table $table The table to add the foreign key to + * @param ForeignKey $fk The foreign key to add + */ public function __construct(Table $table, ForeignKey $fk) { - $this->table = $table; + parent::__construct($table); $this->foreignKey = $fk; } @@ -62,6 +73,11 @@ public static function build(Table $table, $columns, $referencedTable, $referenc return new static($table, $fk); } + /** + * Returns the foreign key to be added + * + * @return ForeignKey + */ public function getForeignKey() { return $this->foreignKey; diff --git a/src/Phinx/Db/Action/AddIndex.php b/src/Phinx/Db/Action/AddIndex.php index 2192c0ef0..ae86cfd00 100644 --- a/src/Phinx/Db/Action/AddIndex.php +++ b/src/Phinx/Db/Action/AddIndex.php @@ -30,14 +30,33 @@ class AddIndex extends Action { + /** + * The index to add to the table + * + * @var Index + */ protected $index; + /** + * Constructor + * + * @param Table $table The table to add the index to + * @param Index $index The index to be added + */ public function __construct(Table $table, Index $index) { - $this->table = $table; + parent::__construct($table); $this->index = $index; } + /** + * Creates a new AddIndex object after building the index object with the + * provided arguments + * + * @param Table $table The table to add the index to + * @param mixed $columns The columns to index + * @param array $options Additional options for the index creation + */ public static function build(Table $table, $columns, array $options = []) { // create a new index object if strings or an array of strings were supplied @@ -57,6 +76,11 @@ public static function build(Table $table, $columns, array $options = []) return new static($table, $index); } + /** + * Returns the index to be added + * + * @return Index + */ public function getIndex() { return $this->index; diff --git a/src/Phinx/Db/Action/ChangeColumn.php b/src/Phinx/Db/Action/ChangeColumn.php index 62bfaf9e5..ad9ee06d7 100644 --- a/src/Phinx/Db/Action/ChangeColumn.php +++ b/src/Phinx/Db/Action/ChangeColumn.php @@ -29,13 +29,30 @@ class ChangeColumn extends Action { + /** + * The column definition + * + * @var Column + */ protected $column; + /** + * The name of the column to be changed + * + * @var string + */ protected $columnName; + /** + * Constructor + * + * @param Table $table The table to alter + * @param mixed $columnName The name fo the column to change + * @param Column $column The column definition + */ public function __construct(Table $table, $columnName, Column $column) { - $this->table = $table; + parent::__construct($table); $this->columnName = $columnName; $this->column = $column; @@ -45,6 +62,15 @@ public function __construct(Table $table, $columnName, Column $column) } } + /** + * Creates a new ChangeColumn object after building the column definition + * out of the provided arguments + * + * @param Table $table The table to alter + * @param mixed $columnName The name of the column to change + * @param mixed $type The type of the column + * @param mixed $options Addiotional options for the column + */ public static function build(Table $table, $columnName, $type = null, $options = []) { $column = new Column(); @@ -55,11 +81,21 @@ public static function build(Table $table, $columnName, $type = null, $options = return new static($table, $columnName, $column); } + /** + * Returns the name of the column to change + * + * @return string + */ public function getColumnName() { return $this->columnName; } + /** + * Returns the column definition + * + * @return Column + */ public function getColumn() { return $this->column; diff --git a/src/Phinx/Db/Action/CreateTable.php b/src/Phinx/Db/Action/CreateTable.php index 509c1c1d4..60f8b0ad2 100644 --- a/src/Phinx/Db/Action/CreateTable.php +++ b/src/Phinx/Db/Action/CreateTable.php @@ -28,9 +28,4 @@ class CreateTable extends Action { - - public function __construct(Table $table) - { - $this->table = $table; - } } diff --git a/src/Phinx/Db/Action/DropForeignKey.php b/src/Phinx/Db/Action/DropForeignKey.php index 9c14f61cc..e859a8d8a 100644 --- a/src/Phinx/Db/Action/DropForeignKey.php +++ b/src/Phinx/Db/Action/DropForeignKey.php @@ -31,14 +31,33 @@ class DropForeignKey extends Action { + /** + * The foreing key to remove + * + * @var ForeignKey + */ protected $foreignKey; + /** + * Constructor + * + * @param Table $table The table to remove the constraint from + * @param ForeignKey $foreignKey The foreign key to remove + */ public function __construct(Table $table, ForeignKey $foreignKey) { - $this->table = $table; + parent::__construct($table); $this->foreignKey = $foreignKey; } + /** + * Creates a new DropForeignKey object after building the ForeignKey + * definition out of the passed arguments. + * + * @param Table $table The table to dele the foreign key from + * @param string[] $columns The columns participating in the foreign key + * @param string|null $constraint The constraint name + */ public static function build(Table $table, $columns, $constraint = null) { if (is_string($columns)) { @@ -55,6 +74,11 @@ public static function build(Table $table, $columns, $constraint = null) return new static($table, $foreignKey); } + /** + * Returns the foreign key to remove + * + * @return ForeignKey + */ public function getForeignKey() { return $this->foreignKey; diff --git a/src/Phinx/Db/Action/DropIndex.php b/src/Phinx/Db/Action/DropIndex.php index 961a6ebe6..c570091f8 100644 --- a/src/Phinx/Db/Action/DropIndex.php +++ b/src/Phinx/Db/Action/DropIndex.php @@ -31,14 +31,32 @@ class DropIndex extends Action { + /** + * The index to drop + * + * @var Index + */ protected $index; + /** + * Constructor + * + * @param Table $table The table owning the index + * @param Index $index The index to be dropped + */ public function __construct(Table $table, Index $index) { - $this->table = $table; + parent::__construct($table); $this->index = $index; } + /** + * Creates a new DropIndex object after assembling the passed + * arguments. + * + * @param Table $table The table where the index is + * @param array $columns the indexed columns + */ public static function build(Table $table, array $columns = []) { $index = new Index(); @@ -47,6 +65,13 @@ public static function build(Table $table, array $columns = []) return new static($table, $index); } + /** + * Creates a new DropIndex when the name of the index to drop + * is knonwn. + * + * @param Table $table The table where the index is + * @param mixed $name The name of the index + */ public static function buildFromName(Table $table, $name) { $index = new Index(); @@ -55,6 +80,11 @@ public static function buildFromName(Table $table, $name) return new static($table, $index); } + /** + * Returns the index to be dropped + * + * @return Index + */ public function getIndex() { return $this->index; diff --git a/src/Phinx/Db/Action/DropTable.php b/src/Phinx/Db/Action/DropTable.php index 4e0213e52..03c3eb09e 100644 --- a/src/Phinx/Db/Action/DropTable.php +++ b/src/Phinx/Db/Action/DropTable.php @@ -28,11 +28,4 @@ class DropTable extends Action { - - protected $table; - - public function __construct(Table $table) - { - $this->table = $table; - } } diff --git a/src/Phinx/Db/Action/RemoveColumn.php b/src/Phinx/Db/Action/RemoveColumn.php index 92da2903b..e57d2e286 100644 --- a/src/Phinx/Db/Action/RemoveColumn.php +++ b/src/Phinx/Db/Action/RemoveColumn.php @@ -30,14 +30,32 @@ class RemoveColumn extends Action { + /** + * The column to be removed + * + * @var Column + */ protected $column; + /** + * Constructor + * + * @param Table $table The table where the column is + * @param Column $column The column to be removed + */ public function __construct(Table $table, Column $column) { - $this->table = $table; + parent::__construct($table); $this->column = $column; } + /** + * Creates a new RemoveColumn object after assembling the + * passed arguments. + * + * @param Table $table The table where the column is + * @param mixed $columnName The name of the column to drop + */ public static function build(Table $table, $columnName) { $column = new Column(); @@ -45,6 +63,11 @@ public static function build(Table $table, $columnName) return new static($table, $column); } + /** + * Returns the column to be dropped + * + * @return Column + */ public function getColumn() { return $this->column; diff --git a/src/Phinx/Db/Action/RenameColumn.php b/src/Phinx/Db/Action/RenameColumn.php index 07ea16dee..0146584dd 100644 --- a/src/Phinx/Db/Action/RenameColumn.php +++ b/src/Phinx/Db/Action/RenameColumn.php @@ -30,17 +30,42 @@ class RenameColumn extends Action { + /** + * The column to be renamed + * + * @var Column + */ protected $column; + /** + * The new name for the column + * + * @var string + */ protected $newName; + /** + * Constructor + * + * @param Table $table The table where the column is + * @param Column $column The column to be renamed + * @param mixed $newName The new name for the column + */ public function __construct(Table $table, Column $column, $newName) { - $this->table = $table; + parent::__construct($table); $this->newName = $newName; $this->column = $column; } + /** + * Creates a new RenameColumn object after building the passed + * arguments + * + * @param Table $table The table where the column is + * @param mixed $columnName The name of the column to be changed + * @param mixed $newName The new name for the column + */ public static function build(Table $table, $columnName, $newName) { $column = new Column(); @@ -48,11 +73,21 @@ public static function build(Table $table, $columnName, $newName) return new static($table, $column, $newName); } + /** + * Returns the column to be changed + * + * @return Column + */ public function getColumn() { return $this->column; } + /** + * Returns the new name for the column + * + * @return string + */ public function getNewName() { return $this->newName; diff --git a/src/Phinx/Db/Action/RenameTable.php b/src/Phinx/Db/Action/RenameTable.php index 7dac886ce..df3d58c20 100644 --- a/src/Phinx/Db/Action/RenameTable.php +++ b/src/Phinx/Db/Action/RenameTable.php @@ -29,14 +29,30 @@ class RenameTable extends Action { + /** + * The new name for the table + * + * @var string + */ protected $newName; + /** + * Constructor + * + * @param Table $table The table to be renamed + * @param mixed $newName The new name for the table + */ public function __construct(Table $table, $newName) { + parent::__construct($table); $this->newName = $newName; - $this->table = $table; } + /** + * Return the new name for the table + * + * @return string + */ public function getNewName() { return $this->newName; diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index 8abb9e2ee..d1e5795c2 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -262,7 +262,7 @@ public function execute($sql); * * @param Table $table The table to execute the actions for * @param Phinx\Db\Action\Action[] $table The table to execute the actions for - * @return int + * @return void */ public function executeActions(Table $table, array $actions); diff --git a/src/Phinx/Db/Adapter/AdapterWrapper.php b/src/Phinx/Db/Adapter/AdapterWrapper.php index 7630572d1..b62ce175d 100644 --- a/src/Phinx/Db/Adapter/AdapterWrapper.php +++ b/src/Phinx/Db/Adapter/AdapterWrapper.php @@ -28,10 +28,10 @@ */ namespace Phinx\Db\Adapter; -use Phinx\Db\Table\Table; use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Index; +use Phinx\Db\Table\Table; use Phinx\Migration\MigrationInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php index 53e98f050..659d88f64 100644 --- a/src/Phinx/Db/Adapter/DirectActionInterface.php +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -104,7 +104,7 @@ public function addIndex(Table $table, Index $index); /** * Drops the specified index from a database table. * - * @param string $tableName + * @param string $tableName the name of the table * @param mixed $columns Column(s) * @return void */ @@ -113,8 +113,8 @@ public function dropIndex($tableName, $columns); /** * Drops the index specified by name from a database table. * - * @param string $tableName - * @param string $indexName + * @param string $tableName The table name where the index is + * @param string $indexName The name of the index * @return void */ public function dropIndexByName($tableName, $indexName); diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index 888eeb986..bfb388630 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -59,6 +59,12 @@ abstract class PdoAdapter extends AbstractAdapter implements DirectActionInterfa */ protected $connection; + /** + * Writes a message to stdout if vebose output is on + * + * @param stirng $message The message to show + * @return void + */ protected function verboseLog($message) { if (!$this->isDryRunEnabled() && @@ -533,7 +539,7 @@ public function dropIndex($tableName, $columns) /** * Returns the instructions to drop the specified index from a database table. * - * @param string $tableName + * @param string $tableName The name of of the table where the index is * @param mixed $columns Column(s) * @return AlterInstructions */ @@ -551,8 +557,8 @@ public function dropIndexByName($tableName, $indexName) /** * Returns the instructions to drop the index specified by name from a database table. * - * @param string $tableName - * @param string $indexName + * @param string $tableName The table name whe the index is + * @param string $indexName The name of the index * @return AlterInstructions */ abstract protected function getDropIndexByNameInstructions($tableName, $indexName); @@ -569,8 +575,8 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) /** * Returns the instructions to adds the specified foreign key to a database table. * - * @param \Phinx\Db\Table $table - * @param \Phinx\Db\Table\ForeignKey $foreignKey + * @param \Phinx\Db\Table $table The table to add the constraint to + * @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add * @return AlterInstructions */ abstract protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey); @@ -592,7 +598,7 @@ public function dropForeignKey($tableName, $columns, $constraint = null) /** * Returns the instructions to drop the specified foreign key from a database table. * - * @param string $tableName + * @param string $tableName The table where the foreign key constraint is * @param string $constraint Constraint name * @return AlterInstructions */ @@ -601,7 +607,7 @@ abstract protected function getDropForeignKeyInstructions($tableName, $constrain /** * Returns the instructions to drop the specified foreign key from a database table. * - * @param string $tableName + * @param string $tableName The table where the foreign key constraint is * @param array $columns The list of column names * @return AlterInstructions */ @@ -699,7 +705,6 @@ public function executeActions(Table $table, array $actions) )); break; - case ($action instanceof DropTable): $instructions->merge($this->getDropTableInstructions( $table->getName() diff --git a/src/Phinx/Db/Adapter/PostgresAdapter.php b/src/Phinx/Db/Adapter/PostgresAdapter.php index 530dc3069..8e6ae7d8f 100644 --- a/src/Phinx/Db/Adapter/PostgresAdapter.php +++ b/src/Phinx/Db/Adapter/PostgresAdapter.php @@ -554,6 +554,7 @@ protected function getAddIndexInstructions(Table $table, Index $index) { $instructions = new AlterInstructions(); $instructions->addPostStep($this->getIndexSqlDefinition($index, $table->getName())); + return $instructions; } diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index b929f3ffe..f628b573a 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -308,6 +308,12 @@ protected function getAddColumnInstructions(Table $table, Column $column) return new AlterInstructions([$alter]); } + /** + * Returns the original CREATE statement for the give table + * + * @param string $tableName The table name to get the create statement for + * @return string + */ protected function getDeclaringSql($tableName) { $rows = $this->fetchAll('select * from sqlite_master where `type` = \'table\''); @@ -322,6 +328,15 @@ protected function getDeclaringSql($tableName) return $sql; } + /** + * Copies all the data from a tmp table to another table + * + * @param string $tableName The table name to copy the data to + * @param string $tmpTableName The tmp table name where the data is stored + * @param string[] $writeColumns The list of columns in the target table + * @param string[] $selectColumns The list of columns in the tmp table + * @return void + */ protected function copyDataToNewTable($tableName, $tmpTableName, $writeColumns, $selectColumns) { $sql = sprintf( @@ -334,6 +349,14 @@ protected function copyDataToNewTable($tableName, $tmpTableName, $writeColumns, $this->execute($sql); } + /** + * Modifies the passed instructions to copy all data from the tmp table into + * the provided table and then drops the tmp table. + * + * @param AlterInstructions $instructions The instructions to modify + * @param string $tableName The table name to copy the data to + * @return AlterInstructions + */ protected function copyAndDropTmpTable($instructions, $tableName) { $instructions->addPostStep(function ($state) use ($tableName) { @@ -345,12 +368,22 @@ protected function copyAndDropTmpTable($instructions, $tableName) ); $this->execute(sprintf('DROP TABLE %s', $this->quoteTableName($state['tmpTableName']))); + return $state; }); return $instructions; } + /** + * Returns the columns and type to use when copying a table to another in the process + * of altering a table + * + * @param string $tableName The table to modify + * @param string $columnName The column name that is about to change + * @param stirng|false $newColumnName Optionally the new name for the column + * @return AlterInstructions + */ protected function calculateNewTableColumns($tableName, $columnName, $newColumnName) { $columns = $this->fetchAll(sprintf('pragma table_info(%s)', $this->quoteTableName($tableName))); @@ -388,6 +421,13 @@ protected function calculateNewTableColumns($tableName, $columnName, $newColumnN return compact('writeColumns', 'selectColumns', 'columnType'); } + /** + * Returns the initial instructions to alter a table using the + * rename-alter-copy strategy + * + * @param string $tableName The table to modify + * @return AlterInstructions + */ protected function beginAlterByCopyTable($tableName) { $instructions = new AlterInstructions(); diff --git a/src/Phinx/Db/Adapter/SqlServerAdapter.php b/src/Phinx/Db/Adapter/SqlServerAdapter.php index c540ae863..528f4ea53 100644 --- a/src/Phinx/Db/Adapter/SqlServerAdapter.php +++ b/src/Phinx/Db/Adapter/SqlServerAdapter.php @@ -473,6 +473,13 @@ protected function getRenameColumnInstructions($tableName, $columnName, $newColu return $instructions; } + /** + * Returns the instructions to change a column default value + * + * @param string $tableName The table where the column is + * @param Column $newColumn The column to alter + * @return AlterInstructions + */ protected function getChangeDefault($tableName, Column $newColumn) { $constraintName = "DF_{$tableName}_{$newColumn->getName()}"; @@ -556,6 +563,9 @@ protected function getDropColumnInstructions($tableName, $columnName) return $instructions; } + /** + * {@inheritdoc} + */ protected function getDropDefaultConstraint($tableName, $columnName) { $defaultConstraint = $this->getDefaultConstraint($tableName, $columnName); diff --git a/src/Phinx/Db/Adapter/TablePrefixAdapter.php b/src/Phinx/Db/Adapter/TablePrefixAdapter.php index 7d34d4f3b..ee2c00a4f 100644 --- a/src/Phinx/Db/Adapter/TablePrefixAdapter.php +++ b/src/Phinx/Db/Adapter/TablePrefixAdapter.php @@ -176,8 +176,7 @@ public function changeColumn($tableName, $columnName, Column $newColumn) throw new \BadMethodCallException('The underlying adapter does not implement DirectActionInterface'); } $adapterTableName = $this->getAdapterTableName($tableName); - - return $adapter->changeColumn($adapterTableName, $columnName, $newColumn); + $adapter->changeColumn($adapterTableName, $columnName, $newColumn); } /** diff --git a/src/Phinx/Db/Adapter/TimedOutputAdapter.php b/src/Phinx/Db/Adapter/TimedOutputAdapter.php index ff12ab8b0..e13a18877 100644 --- a/src/Phinx/Db/Adapter/TimedOutputAdapter.php +++ b/src/Phinx/Db/Adapter/TimedOutputAdapter.php @@ -329,8 +329,7 @@ public function executeActions(Table $table, array $actions) { $end = $this->startCommandTimer(); $this->writeCommand(sprintf('Altering table %s', $table->getName())); - $res = parent::executeActions($table, $actions); + parent::executeActions($table, $actions); $end(); - return $res; } } diff --git a/src/Phinx/Db/Plan/AlterTable.php b/src/Phinx/Db/Plan/AlterTable.php index d07e60fc1..a52106dfc 100644 --- a/src/Phinx/Db/Plan/AlterTable.php +++ b/src/Phinx/Db/Plan/AlterTable.php @@ -50,7 +50,7 @@ class AlterTable /** * Constructor * - * @param Table $table + * @param Table $table The table to change */ public function __construct(Table $table) { @@ -60,7 +60,8 @@ public function __construct(Table $table) /** * Adds another action to the collection * - * @param Action $action + * @param Action $action The action to add + * @return void */ public function addAction(Action $action) { diff --git a/src/Phinx/Db/Plan/Intent.php b/src/Phinx/Db/Plan/Intent.php index 24f09335a..fe90e5721 100644 --- a/src/Phinx/Db/Plan/Intent.php +++ b/src/Phinx/Db/Plan/Intent.php @@ -43,7 +43,7 @@ class Intent /** * Adds a new action to the collection * - * @param Action $action + * @param Action $action The action to add * @return void */ public function addAction(Action $action) @@ -64,7 +64,8 @@ public function getActions() /** * Merges another Intent object with this one * - * @param Intent $another + * @param Intent $another The other intent to merge in + * @return void */ public function merge(Intent $another) { diff --git a/src/Phinx/Db/Plan/NewTable.php b/src/Phinx/Db/Plan/NewTable.php index 1bca11638..48a2f9b4a 100644 --- a/src/Phinx/Db/Plan/NewTable.php +++ b/src/Phinx/Db/Plan/NewTable.php @@ -68,7 +68,7 @@ public function __construct(Table $table) /** * Adds a column to the collection * - * @param Column $column + * @param Column $column The column description * @return void */ public function addColumn(Column $column) @@ -79,7 +79,7 @@ public function addColumn(Column $column) /** * Adds an index to the collection * - * @param Index $index + * @param Index $index The index description * @return void */ public function addIndex(Index $index) diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php index 571d284e7..7077034bb 100644 --- a/src/Phinx/Db/Plan/Plan.php +++ b/src/Phinx/Db/Plan/Plan.php @@ -93,6 +93,12 @@ public function __construct(Intent $intent) $this->createPlan($intent->getActions()); } + /** + * Parses the given Intent and creates the separate steps to execute + * + * @param Intent $actions + * @return void + */ protected function createPlan($actions) { $this->gatherCreates($actions); @@ -103,6 +109,11 @@ protected function createPlan($actions) $this->resolveConflicts(); } + /** + * Returns a nested list of all the steps to execute + * + * @return AlterTable[] + */ protected function updatesSequence() { return [ @@ -151,6 +162,11 @@ public function executeInverse(AdapterInterface $executor) } } + /** + * Deletes certain actions from the plan if they are found to be conflicting or redundant. + * + * @return void + */ protected function resolveConflicts() { $actions = collection($this->tableMoves) @@ -160,14 +176,22 @@ protected function resolveConflicts() foreach ($actions as $action) { if ($action instanceof DropTable) { - $this->tableUpdates = $this->forgetActions($action->getTable(), $this->tableUpdates); - $this->constraints = $this->forgetActions($action->getTable(), $this->constraints); - $this->indexes = $this->forgetActions($action->getTable(), $this->indexes); + $this->tableUpdates = $this->forgetTable($action->getTable(), $this->tableUpdates); + $this->constraints = $this->forgetTable($action->getTable(), $this->constraints); + $this->indexes = $this->forgetTable($action->getTable(), $this->indexes); } } } - protected function forgetActions(Table $table, $actions) + /** + * Deletes all actions related to the given table and keeps the + * rest + * + * @param Table $table The table to find in the list of actions + * @param AlterTable[] $actions The actions to transform + * @return AlterTable[] The list of actions without actions for the given table + */ + protected function forgetTable(Table $table, $actions) { $result = []; foreach ($actions as $action) { @@ -180,6 +204,12 @@ protected function forgetActions(Table $table, $actions) return $result; } + /** + * Collects all table creation actions from the given intent + * + * @param Action[] $actions The actions to parse + * @return void + */ protected function gatherCreates($actions) { collection($actions) @@ -215,6 +245,12 @@ protected function gatherCreates($actions) }); } + /** + * Collects all alter table actions from the given intent + * + * @param Action[] $actions The actions to parse + * @return void + */ protected function gatherUpdates($actions) { collection($actions) @@ -240,6 +276,12 @@ protected function gatherUpdates($actions) }); } + /** + * Collects all alter table drop and renames from the given intent + * + * @param Action[] $actions The actions to parse + * @return void + */ protected function gatherTableMoves($actions) { collection($actions) @@ -259,6 +301,12 @@ protected function gatherTableMoves($actions) }); } + /** + * Collects all index creation and drops from the given intent + * + * @param Action[] $actions The actions to parse + * @return void + */ protected function gatherIndexes($actions) { collection($actions) @@ -283,6 +331,12 @@ protected function gatherIndexes($actions) }); } + /** + * Collects all foreign key creation and drops from the given intent + * + * @param Action[] $actions The actions to parse + * @return void + */ protected function gatherConstraints($actions) { collection($actions) From 544d112f5880698940251c8d49ebcc6305697fcc Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 29 Apr 2018 10:52:33 +0200 Subject: [PATCH 14/21] Fixed phpstan errors --- src/Phinx/Db/Adapter/AdapterWrapper.php | 2 +- src/Phinx/Db/Adapter/DirectActionInterface.php | 6 +++--- src/Phinx/Db/Adapter/PdoAdapter.php | 2 +- src/Phinx/Db/Adapter/SQLiteAdapter.php | 2 +- src/Phinx/Db/Plan/Plan.php | 12 ++++++------ 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Phinx/Db/Adapter/AdapterWrapper.php b/src/Phinx/Db/Adapter/AdapterWrapper.php index b62ce175d..2735f400e 100644 --- a/src/Phinx/Db/Adapter/AdapterWrapper.php +++ b/src/Phinx/Db/Adapter/AdapterWrapper.php @@ -468,6 +468,6 @@ public function getConnection() */ public function executeActions(Table $table, array $actions) { - return $this->getAdapter()->executeActions($table, $actions); + $this->getAdapter()->executeActions($table, $actions); } } diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php index 659d88f64..b06f19281 100644 --- a/src/Phinx/Db/Adapter/DirectActionInterface.php +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -131,9 +131,9 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey); /** * Drops the specified foreign key from a database table. * - * @param string $tableName - * @param string[] $columns Column(s) - * @param string $constraint Constraint name + * @param string $tableName + * @param string[] $columns Column(s) + * @param string|null $constraint Constraint name * @return void */ public function dropForeignKey($tableName, $columns, $constraint = null); diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index bfb388630..ccb685e2f 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -62,7 +62,7 @@ abstract class PdoAdapter extends AbstractAdapter implements DirectActionInterfa /** * Writes a message to stdout if vebose output is on * - * @param stirng $message The message to show + * @param string $message The message to show * @return void */ protected function verboseLog($message) diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index f628b573a..5b2a33834 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -381,7 +381,7 @@ protected function copyAndDropTmpTable($instructions, $tableName) * * @param string $tableName The table to modify * @param string $columnName The column name that is about to change - * @param stirng|false $newColumnName Optionally the new name for the column + * @param string|false $newColumnName Optionally the new name for the column * @return AlterInstructions */ protected function calculateNewTableColumns($tableName, $columnName, $newColumnName) diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php index 7077034bb..c4673f54c 100644 --- a/src/Phinx/Db/Plan/Plan.php +++ b/src/Phinx/Db/Plan/Plan.php @@ -112,7 +112,7 @@ protected function createPlan($actions) /** * Returns a nested list of all the steps to execute * - * @return AlterTable[] + * @return AlterTable[][] */ protected function updatesSequence() { @@ -207,7 +207,7 @@ protected function forgetTable(Table $table, $actions) /** * Collects all table creation actions from the given intent * - * @param Action[] $actions The actions to parse + * @param \Phinx\Db\Action\Action[] $actions The actions to parse * @return void */ protected function gatherCreates($actions) @@ -248,7 +248,7 @@ protected function gatherCreates($actions) /** * Collects all alter table actions from the given intent * - * @param Action[] $actions The actions to parse + * @param \Phinx\Db\Action\Action[] $actions The actions to parse * @return void */ protected function gatherUpdates($actions) @@ -279,7 +279,7 @@ protected function gatherUpdates($actions) /** * Collects all alter table drop and renames from the given intent * - * @param Action[] $actions The actions to parse + * @param \Phinx\Db\Action\Action[] $actions The actions to parse * @return void */ protected function gatherTableMoves($actions) @@ -304,7 +304,7 @@ protected function gatherTableMoves($actions) /** * Collects all index creation and drops from the given intent * - * @param Action[] $actions The actions to parse + * @param \Phinx\Db\Action\Action[] $actions The actions to parse * @return void */ protected function gatherIndexes($actions) @@ -334,7 +334,7 @@ protected function gatherIndexes($actions) /** * Collects all foreign key creation and drops from the given intent * - * @param Action[] $actions The actions to parse + * @param \Phinx\Db\Action\Action[] $actions The actions to parse * @return void */ protected function gatherConstraints($actions) From a6451fe2e27d647e24230bbbbcddad3a802ccdc9 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 29 Apr 2018 21:24:43 +0200 Subject: [PATCH 15/21] Fixed tests --- tests/Phinx/Db/Adapter/MysqlAdapterTest.php | 8 ++++---- tests/Phinx/Db/Adapter/PostgresAdapterTest.php | 8 ++++---- tests/Phinx/Db/Adapter/SQLiteAdapterTest.php | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/Phinx/Db/Adapter/MysqlAdapterTest.php b/tests/Phinx/Db/Adapter/MysqlAdapterTest.php index 2120f3ef9..9bb610661 100644 --- a/tests/Phinx/Db/Adapter/MysqlAdapterTest.php +++ b/tests/Phinx/Db/Adapter/MysqlAdapterTest.php @@ -1266,15 +1266,15 @@ public function testDumpInsert() $consoleOutput = new BufferedOutput(); $this->adapter->setOutput($consoleOutput); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'string_col' => 'test data' ]); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'string_col' => null ]); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'int_col' => 23 ]); @@ -1310,7 +1310,7 @@ public function testDumpBulkinsert() $consoleOutput = new BufferedOutput(); $this->adapter->setOutput($consoleOutput); - $this->adapter->bulkinsert($table, [ + $this->adapter->bulkinsert($table->getTable(), [ [ 'string_col' => 'test_data1', 'int_col' => 23, diff --git a/tests/Phinx/Db/Adapter/PostgresAdapterTest.php b/tests/Phinx/Db/Adapter/PostgresAdapterTest.php index a3f0aca0f..776ee375d 100644 --- a/tests/Phinx/Db/Adapter/PostgresAdapterTest.php +++ b/tests/Phinx/Db/Adapter/PostgresAdapterTest.php @@ -1204,15 +1204,15 @@ public function testDumpInsert() $consoleOutput = new BufferedOutput(); $this->adapter->setOutput($consoleOutput); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'string_col' => 'test data' ]); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'string_col' => null ]); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'int_col' => 23 ]); @@ -1248,7 +1248,7 @@ public function testDumpBulkinsert() $consoleOutput = new BufferedOutput(); $this->adapter->setOutput($consoleOutput); - $this->adapter->bulkinsert($table, [ + $this->adapter->bulkinsert($table->getTable(), [ [ 'string_col' => 'test_data1', 'int_col' => 23, diff --git a/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php b/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php index a107c27bd..40aadf824 100644 --- a/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php +++ b/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php @@ -896,15 +896,15 @@ public function testDumpInsert() $consoleOutput = new BufferedOutput(); $this->adapter->setOutput($consoleOutput); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'string_col' => 'test data' ]); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'string_col' => null ]); - $this->adapter->insert($table, [ + $this->adapter->insert($table->getTable(), [ 'int_col' => 23 ]); @@ -940,7 +940,7 @@ public function testDumpBulkinsert() $consoleOutput = new BufferedOutput(); $this->adapter->setOutput($consoleOutput); - $this->adapter->bulkinsert($table, [ + $this->adapter->bulkinsert($table->getTable(), [ [ 'string_col' => 'test_data1', 'int_col' => 23, From b1374fa6b8f9cef0d8432dc287dc9065def4e292 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 6 May 2018 14:11:00 +0200 Subject: [PATCH 16/21] Fixed phpstan reported errors --- src/Phinx/Db/Action/DropForeignKey.php | 2 +- src/Phinx/Db/Adapter/AdapterInterface.php | 4 +- .../Db/Adapter/DirectActionInterface.php | 2 +- src/Phinx/Db/Adapter/MysqlAdapter.php | 4 -- src/Phinx/Db/Adapter/PdoAdapter.php | 10 +-- src/Phinx/Db/Adapter/SQLiteAdapter.php | 6 +- src/Phinx/Db/Adapter/TimedOutputAdapter.php | 66 +++++++++++++++---- src/Phinx/Db/Table/Index.php | 4 +- 8 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/Phinx/Db/Action/DropForeignKey.php b/src/Phinx/Db/Action/DropForeignKey.php index e859a8d8a..2be9c3078 100644 --- a/src/Phinx/Db/Action/DropForeignKey.php +++ b/src/Phinx/Db/Action/DropForeignKey.php @@ -55,7 +55,7 @@ public function __construct(Table $table, ForeignKey $foreignKey) * definition out of the passed arguments. * * @param Table $table The table to dele the foreign key from - * @param string[] $columns The columns participating in the foreign key + * @param string|string[] $columns The columns participating in the foreign key * @param string|null $constraint The constraint name */ public static function build(Table $table, $columns, $constraint = null) diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index d1e5795c2..d34dd3e90 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -260,8 +260,8 @@ public function execute($sql); /** * Executes a list of migration actions for the given table * - * @param Table $table The table to execute the actions for - * @param Phinx\Db\Action\Action[] $table The table to execute the actions for + * @param \Phinx\Db\Table\Table $table The table to execute the actions for + * @param \Phinx\Db\Action\Action[] $table The table to execute the actions for * @return void */ public function executeActions(Table $table, array $actions); diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php index b06f19281..1a7303140 100644 --- a/src/Phinx/Db/Adapter/DirectActionInterface.php +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -122,7 +122,7 @@ public function dropIndexByName($tableName, $indexName); /** * Adds the specified foreign key to a database table. * - * @param \Phinx\Db\Table $table + * @param \Phinx\Db\Table\Table $table * @param \Phinx\Db\Table\ForeignKey $foreignKey * @return void */ diff --git a/src/Phinx/Db/Adapter/MysqlAdapter.php b/src/Phinx/Db/Adapter/MysqlAdapter.php index ad9b608f7..dab4fe333 100644 --- a/src/Phinx/Db/Adapter/MysqlAdapter.php +++ b/src/Phinx/Db/Adapter/MysqlAdapter.php @@ -662,10 +662,6 @@ protected function getDropForeignKeyInstructions($tableName, $constraint) */ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) { - if (is_string($columns)) { - $columns = [$columns]; // str to array - } - $instructions = new AlterInstructions(); foreach ($columns as $column) { diff --git a/src/Phinx/Db/Adapter/PdoAdapter.php b/src/Phinx/Db/Adapter/PdoAdapter.php index cecd5e045..21c0fdcd0 100644 --- a/src/Phinx/Db/Adapter/PdoAdapter.php +++ b/src/Phinx/Db/Adapter/PdoAdapter.php @@ -444,7 +444,7 @@ public function castToBool($value) { return (bool)$value ? 1 : 0; } - + /** * Retrieve a database connection attribute * @see http://php.net/manual/en/pdo.getattribute.php @@ -456,7 +456,7 @@ public function getAttribute($attribute) { return $this->connection->getAttribute($attribute); } - + /** * Get the defintion for a `DEFAULT` statement. * @@ -473,7 +473,7 @@ protected function getDefaultValueDefinition($default, $columnType = null) } elseif ($columnType === static::PHINX_TYPE_BOOLEAN) { $default = $this->castToBool((bool)$default); } - + return isset($default) ? " DEFAULT $default" : ''; } @@ -631,7 +631,7 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) /** * Returns the instructions to adds the specified foreign key to a database table. * - * @param \Phinx\Db\Table $table The table to add the constraint to + * @param \Phinx\Db\Table\Table $table The table to add the constraint to * @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add * @return AlterInstructions */ @@ -699,7 +699,7 @@ public function renameTable($tableName, $newTableName) * Returns the instructions to rename the specified database table. * * @param string $tableName Table Name - * @param string $newName New Name + * @param string $newTableName New Name * @return AlterInstructions */ abstract protected function getRenameTableInstructions($tableName, $newTableName); diff --git a/src/Phinx/Db/Adapter/SQLiteAdapter.php b/src/Phinx/Db/Adapter/SQLiteAdapter.php index fde5a9ea5..f0c8b4bac 100644 --- a/src/Phinx/Db/Adapter/SQLiteAdapter.php +++ b/src/Phinx/Db/Adapter/SQLiteAdapter.php @@ -770,10 +770,6 @@ protected function getDropForeignKeyInstructions($tableName, $constraint) */ protected function getDropForeignKeyByColumnsInstructions($tableName, $columns) { - if (is_string($columns)) { - $columns = [$columns]; // str to array - } - $instructions = $this->beginAlterByCopyTable($tableName); $instructions->addPostStep(function ($state) use ($columns) { @@ -1015,7 +1011,7 @@ protected function getCommentDefinition(Column $column) /** * Gets the SQLite Index Definition for an Index object. * - * @param \Phinx\Db\Table $table Table + * @param \Phinx\Db\Table\Table $table Table * @param \Phinx\Db\Table\Index $index Index * @return string */ diff --git a/src/Phinx/Db/Adapter/TimedOutputAdapter.php b/src/Phinx/Db/Adapter/TimedOutputAdapter.php index e13a18877..1ee155dff 100644 --- a/src/Phinx/Db/Adapter/TimedOutputAdapter.php +++ b/src/Phinx/Db/Adapter/TimedOutputAdapter.php @@ -144,9 +144,13 @@ public function createTable(Table $table, array $columns = [], array $indexes = */ public function renameTable($tableName, $newTableName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('renameTable', [$tableName, $newTableName]); - parent::renameTable($tableName, $newTableName); + $adapter->renameTable($tableName, $newTableName); $end(); } @@ -155,9 +159,13 @@ public function renameTable($tableName, $newTableName) */ public function dropTable($tableName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('dropTable', [$tableName]); - parent::dropTable($tableName); + $adapter->dropTable($tableName); $end(); } @@ -177,6 +185,10 @@ public function truncateTable($tableName) */ public function addColumn(Table $table, Column $column) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand( 'addColumn', @@ -186,7 +198,7 @@ public function addColumn(Table $table, Column $column) $column->getType() ] ); - parent::addColumn($table, $column); + $adapter->addColumn($table, $column); $end(); } @@ -195,9 +207,13 @@ public function addColumn(Table $table, Column $column) */ public function renameColumn($tableName, $columnName, $newColumnName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('renameColumn', [$tableName, $columnName, $newColumnName]); - parent::renameColumn($tableName, $columnName, $newColumnName); + $adapter->renameColumn($tableName, $columnName, $newTableName); $end(); } @@ -206,9 +222,13 @@ public function renameColumn($tableName, $columnName, $newColumnName) */ public function changeColumn($tableName, $columnName, Column $newColumn) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('changeColumn', [$tableName, $columnName, $newColumn->getType()]); - parent::changeColumn($tableName, $columnName, $newColumn); + $adapter->changeColumn($tableName, $columnName, $newColumn); $end(); } @@ -217,9 +237,13 @@ public function changeColumn($tableName, $columnName, Column $newColumn) */ public function dropColumn($tableName, $columnName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('dropColumn', [$tableName, $columnName]); - parent::dropColumn($tableName, $columnName); + $adapter->dropColumn($tableName, $columnName); $end(); } @@ -228,9 +252,13 @@ public function dropColumn($tableName, $columnName) */ public function addIndex(Table $table, Index $index) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('addIndex', [$table->getName(), $index->getColumns()]); - parent::addIndex($table, $index); + $adapter->addIndex($table, $index); $end(); } @@ -239,9 +267,13 @@ public function addIndex(Table $table, Index $index) */ public function dropIndex($tableName, $columns) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('dropIndex', [$tableName, $columns]); - parent::dropIndex($tableName, $columns); + $adapter->dropIndex($tableName, $columnName); $end(); } @@ -250,9 +282,13 @@ public function dropIndex($tableName, $columns) */ public function dropIndexByName($tableName, $indexName) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('dropIndexByName', [$tableName, $indexName]); - parent::dropIndexByName($tableName, $indexName); + $adapter->dropIndexByName($tableName, $indexName); $end(); } @@ -261,9 +297,13 @@ public function dropIndexByName($tableName, $indexName) */ public function addForeignKey(Table $table, ForeignKey $foreignKey) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('addForeignKey', [$table->getName(), $foreignKey->getColumns()]); - parent::addForeignKey($table, $foreignKey); + $adapter->addForeignKey($table, $foreignKey); $end(); } @@ -272,9 +312,13 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey) */ public function dropForeignKey($tableName, $columns, $constraint = null) { + $adapter = $this->getAdapter(); + if (!$adapter instanceof DirectActionInterface) { + throw new \BadMethodCallException('The adapter needs to implement DirectActionInterface'); + } $end = $this->startCommandTimer(); $this->writeCommand('dropForeignKey', [$tableName, $columns]); - parent::dropForeignKey($tableName, $columns, $constraint); + $adapter->dropForeignKey($tableName, $columns, $constraint); $end(); } diff --git a/src/Phinx/Db/Table/Index.php b/src/Phinx/Db/Table/Index.php index dd3dcf543..e14367c43 100644 --- a/src/Phinx/Db/Table/Index.php +++ b/src/Phinx/Db/Table/Index.php @@ -56,7 +56,7 @@ class Index protected $type = self::INDEX; /** - * @var string + * @var string|null */ protected $name = null; @@ -127,7 +127,7 @@ public function setName($name) /** * Gets the index name. * - * @return string + * @return string|null */ public function getName() { From cb7e87129be37c108ebaffb49187dff14bd638f2 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 6 May 2018 20:11:28 +0200 Subject: [PATCH 17/21] Fixed doc blocks --- .stickler.yml | 2 ++ src/Phinx/Db/Action/Action.php | 5 +++++ src/Phinx/Db/Action/AddColumn.php | 1 + src/Phinx/Db/Action/AddForeignKey.php | 12 ++++++++++++ src/Phinx/Db/Action/AddIndex.php | 1 + src/Phinx/Db/Action/ChangeColumn.php | 1 + src/Phinx/Db/Action/DropForeignKey.php | 1 + src/Phinx/Db/Action/DropIndex.php | 2 ++ src/Phinx/Db/Action/RemoveColumn.php | 1 + src/Phinx/Db/Action/RenameColumn.php | 2 ++ src/Phinx/Db/Adapter/AdapterInterface.php | 2 +- src/Phinx/Db/Adapter/DirectActionInterface.php | 6 +++--- src/Phinx/Db/Adapter/TimedOutputAdapter.php | 4 ++-- src/Phinx/Db/Plan/NewTable.php | 2 +- src/Phinx/Db/Plan/Plan.php | 9 ++++----- src/Phinx/Db/Table/Table.php | 2 +- 16 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.stickler.yml b/.stickler.yml index b74644c99..e8e4ac23f 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -4,3 +4,5 @@ linters: files: ignore: - 'vendor/*' +fixers: + enable: true diff --git a/src/Phinx/Db/Action/Action.php b/src/Phinx/Db/Action/Action.php index 5868e09c7..d8b05eb97 100644 --- a/src/Phinx/Db/Action/Action.php +++ b/src/Phinx/Db/Action/Action.php @@ -34,6 +34,11 @@ abstract class Action */ protected $table; + /** + * Consturctor + * + * @param Table $table the Table to apply the action to + */ public function __construct(Table $table) { $this->table = $table; diff --git a/src/Phinx/Db/Action/AddColumn.php b/src/Phinx/Db/Action/AddColumn.php index d0e700d3f..2ee0d0f0e 100644 --- a/src/Phinx/Db/Action/AddColumn.php +++ b/src/Phinx/Db/Action/AddColumn.php @@ -56,6 +56,7 @@ public function __construct(Table $table, Column $column) * @param mixed $columnName The column name * @param mixed $type The column type * @param mixed $options The column options + * @return AddColumn */ public static function build(Table $table, $columnName, $type = null, $options = []) { diff --git a/src/Phinx/Db/Action/AddForeignKey.php b/src/Phinx/Db/Action/AddForeignKey.php index b60d7bce2..f33f8db72 100644 --- a/src/Phinx/Db/Action/AddForeignKey.php +++ b/src/Phinx/Db/Action/AddForeignKey.php @@ -50,6 +50,18 @@ public function __construct(Table $table, ForeignKey $fk) $this->foreignKey = $fk; } + /** + * Creats a new AddForeignKey object after building the foreign key with + * the passed attibutes + * + * @param Table $table The table object to add the foreign key to + * @param string|string[] $columns The columns for the foreign key + * @param Table|string $referencedTable The table the foreign key references + * @param string $referencedColumns The columns in the referenced table + * @param array $options Extra options for the foreign key + * @param string|null $name The name of the foreing key + * @return AddForeignKey + */ public static function build(Table $table, $columns, $referencedTable, $referencedColumns = ['id'], array $options = [], $name = null) { if (is_string($referencedColumns)) { diff --git a/src/Phinx/Db/Action/AddIndex.php b/src/Phinx/Db/Action/AddIndex.php index ae86cfd00..6db89d2a4 100644 --- a/src/Phinx/Db/Action/AddIndex.php +++ b/src/Phinx/Db/Action/AddIndex.php @@ -56,6 +56,7 @@ public function __construct(Table $table, Index $index) * @param Table $table The table to add the index to * @param mixed $columns The columns to index * @param array $options Additional options for the index creation + * @return AddIndex */ public static function build(Table $table, $columns, array $options = []) { diff --git a/src/Phinx/Db/Action/ChangeColumn.php b/src/Phinx/Db/Action/ChangeColumn.php index ad9ee06d7..82335a6e0 100644 --- a/src/Phinx/Db/Action/ChangeColumn.php +++ b/src/Phinx/Db/Action/ChangeColumn.php @@ -70,6 +70,7 @@ public function __construct(Table $table, $columnName, Column $column) * @param mixed $columnName The name of the column to change * @param mixed $type The type of the column * @param mixed $options Addiotional options for the column + * @return ChangeColumn */ public static function build(Table $table, $columnName, $type = null, $options = []) { diff --git a/src/Phinx/Db/Action/DropForeignKey.php b/src/Phinx/Db/Action/DropForeignKey.php index 2be9c3078..150657193 100644 --- a/src/Phinx/Db/Action/DropForeignKey.php +++ b/src/Phinx/Db/Action/DropForeignKey.php @@ -57,6 +57,7 @@ public function __construct(Table $table, ForeignKey $foreignKey) * @param Table $table The table to dele the foreign key from * @param string|string[] $columns The columns participating in the foreign key * @param string|null $constraint The constraint name + * @return DropForeignKey */ public static function build(Table $table, $columns, $constraint = null) { diff --git a/src/Phinx/Db/Action/DropIndex.php b/src/Phinx/Db/Action/DropIndex.php index c570091f8..8bdb52b4f 100644 --- a/src/Phinx/Db/Action/DropIndex.php +++ b/src/Phinx/Db/Action/DropIndex.php @@ -56,6 +56,7 @@ public function __construct(Table $table, Index $index) * * @param Table $table The table where the index is * @param array $columns the indexed columns + * @return DropIndex */ public static function build(Table $table, array $columns = []) { @@ -71,6 +72,7 @@ public static function build(Table $table, array $columns = []) * * @param Table $table The table where the index is * @param mixed $name The name of the index + * @return DropIndex */ public static function buildFromName(Table $table, $name) { diff --git a/src/Phinx/Db/Action/RemoveColumn.php b/src/Phinx/Db/Action/RemoveColumn.php index e57d2e286..7dad88bd1 100644 --- a/src/Phinx/Db/Action/RemoveColumn.php +++ b/src/Phinx/Db/Action/RemoveColumn.php @@ -55,6 +55,7 @@ public function __construct(Table $table, Column $column) * * @param Table $table The table where the column is * @param mixed $columnName The name of the column to drop + * @return RemoveColumn */ public static function build(Table $table, $columnName) { diff --git a/src/Phinx/Db/Action/RenameColumn.php b/src/Phinx/Db/Action/RenameColumn.php index 0146584dd..533e3c28f 100644 --- a/src/Phinx/Db/Action/RenameColumn.php +++ b/src/Phinx/Db/Action/RenameColumn.php @@ -65,11 +65,13 @@ public function __construct(Table $table, Column $column, $newName) * @param Table $table The table where the column is * @param mixed $columnName The name of the column to be changed * @param mixed $newName The new name for the column + * @return RenameColumn */ public static function build(Table $table, $columnName, $newName) { $column = new Column(); $column->setName($columnName); + return new static($table, $column, $newName); } diff --git a/src/Phinx/Db/Adapter/AdapterInterface.php b/src/Phinx/Db/Adapter/AdapterInterface.php index d34dd3e90..caa8302f9 100644 --- a/src/Phinx/Db/Adapter/AdapterInterface.php +++ b/src/Phinx/Db/Adapter/AdapterInterface.php @@ -261,7 +261,7 @@ public function execute($sql); * Executes a list of migration actions for the given table * * @param \Phinx\Db\Table\Table $table The table to execute the actions for - * @param \Phinx\Db\Action\Action[] $table The table to execute the actions for + * @param \Phinx\Db\Action\Action[] $actions The table to execute the actions for * @return void */ public function executeActions(Table $table, array $actions); diff --git a/src/Phinx/Db/Adapter/DirectActionInterface.php b/src/Phinx/Db/Adapter/DirectActionInterface.php index 1a7303140..6666b3744 100644 --- a/src/Phinx/Db/Adapter/DirectActionInterface.php +++ b/src/Phinx/Db/Adapter/DirectActionInterface.php @@ -122,8 +122,8 @@ public function dropIndexByName($tableName, $indexName); /** * Adds the specified foreign key to a database table. * - * @param \Phinx\Db\Table\Table $table - * @param \Phinx\Db\Table\ForeignKey $foreignKey + * @param \Phinx\Db\Table\Table $table The table to add the foreign key to + * @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add * @return void */ public function addForeignKey(Table $table, ForeignKey $foreignKey); @@ -131,7 +131,7 @@ public function addForeignKey(Table $table, ForeignKey $foreignKey); /** * Drops the specified foreign key from a database table. * - * @param string $tableName + * @param string $tableName The table to drop the foreign key from * @param string[] $columns Column(s) * @param string|null $constraint Constraint name * @return void diff --git a/src/Phinx/Db/Adapter/TimedOutputAdapter.php b/src/Phinx/Db/Adapter/TimedOutputAdapter.php index 1ee155dff..b0c911ccd 100644 --- a/src/Phinx/Db/Adapter/TimedOutputAdapter.php +++ b/src/Phinx/Db/Adapter/TimedOutputAdapter.php @@ -213,7 +213,7 @@ public function renameColumn($tableName, $columnName, $newColumnName) } $end = $this->startCommandTimer(); $this->writeCommand('renameColumn', [$tableName, $columnName, $newColumnName]); - $adapter->renameColumn($tableName, $columnName, $newTableName); + $adapter->renameColumn($tableName, $columnName, $newColumnName); $end(); } @@ -273,7 +273,7 @@ public function dropIndex($tableName, $columns) } $end = $this->startCommandTimer(); $this->writeCommand('dropIndex', [$tableName, $columns]); - $adapter->dropIndex($tableName, $columnName); + $adapter->dropIndex($tableName, $columns); $end(); } diff --git a/src/Phinx/Db/Plan/NewTable.php b/src/Phinx/Db/Plan/NewTable.php index 48a2f9b4a..8b8947d69 100644 --- a/src/Phinx/Db/Plan/NewTable.php +++ b/src/Phinx/Db/Plan/NewTable.php @@ -58,7 +58,7 @@ class NewTable /** * Constructor * - * @param Table $table + * @param Table $table The table to create */ public function __construct(Table $table) { diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php index c4673f54c..72645a3bf 100644 --- a/src/Phinx/Db/Plan/Plan.php +++ b/src/Phinx/Db/Plan/Plan.php @@ -96,7 +96,7 @@ public function __construct(Intent $intent) /** * Parses the given Intent and creates the separate steps to execute * - * @param Intent $actions + * @param Intent $actions The actions to use for the plan * @return void */ protected function createPlan($actions) @@ -127,7 +127,7 @@ protected function updatesSequence() /** * Executes this plan using the given AdapterInterface * - * @param AdapterInterface $executor + * @param AdapterInterface $executor The executor object for the plan * @return void */ public function execute(AdapterInterface $executor) @@ -146,7 +146,7 @@ public function execute(AdapterInterface $executor) /** * Executes the inverse plan (rollback the actions) with the given AdapterInterface:w * - * @param AdapterInterface $executor + * @param AdapterInterface $executor The executor object for the plan * @return void */ public function executeInverse(AdapterInterface $executor) @@ -217,8 +217,7 @@ protected function gatherCreates($actions) return $action instanceof CreateTable; }) ->map(function ($action) { - $table = $action->getTable(); - return [$table->getName(), new NewTable($table)]; + return [$table->getName(), new NewTable($action->getTable())]; }) ->each(function ($step) { $this->tableCreates[$step[0]] = $step[1]; diff --git a/src/Phinx/Db/Table/Table.php b/src/Phinx/Db/Table/Table.php index 78e5e3477..58e073fd5 100644 --- a/src/Phinx/Db/Table/Table.php +++ b/src/Phinx/Db/Table/Table.php @@ -65,7 +65,7 @@ public function getOptions() /** * Sets the table options * - * @return array The options for this table to use for creating it + * @param array $options The options for the table creation * @return void */ public function setOptions(array $options) From a5ee47012690ba1ad653a1183aef5ea6602a94c3 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 6 May 2018 20:22:15 +0200 Subject: [PATCH 18/21] Please, help me stickler --- .stickler.yml | 6 +++++- src/Phinx/Db/Action/RemoveColumn.php | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.stickler.yml b/.stickler.yml index e8e4ac23f..53f73a083 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -1,8 +1,12 @@ linters: phpcs: standard: CakePHP + fixer: true + files: ignore: - 'vendor/*' + fixers: - enable: true + enable: true + workflow: commit diff --git a/src/Phinx/Db/Action/RemoveColumn.php b/src/Phinx/Db/Action/RemoveColumn.php index 7dad88bd1..cc6ab64ce 100644 --- a/src/Phinx/Db/Action/RemoveColumn.php +++ b/src/Phinx/Db/Action/RemoveColumn.php @@ -61,6 +61,7 @@ public static function build(Table $table, $columnName) { $column = new Column(); $column->setName($columnName); + return new static($table, $column); } From 40fd1af8b10066edeff3e7258050a7889698e871 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 6 May 2018 18:22:38 +0000 Subject: [PATCH 19/21] Fixing style errors. --- tests/Phinx/Db/Adapter/PostgresAdapterTest.php | 1 - tests/Phinx/Db/Adapter/ProxyAdapterTest.php | 1 - tests/Phinx/Db/Adapter/SQLiteAdapterTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/tests/Phinx/Db/Adapter/PostgresAdapterTest.php b/tests/Phinx/Db/Adapter/PostgresAdapterTest.php index 776ee375d..148d14ffc 100644 --- a/tests/Phinx/Db/Adapter/PostgresAdapterTest.php +++ b/tests/Phinx/Db/Adapter/PostgresAdapterTest.php @@ -648,7 +648,6 @@ public function testGetColumns($colName, $type, $options, $actualType = null) } } - public function testAddIndex() { $table = new \Phinx\Db\Table('table1', [], $this->adapter); diff --git a/tests/Phinx/Db/Adapter/ProxyAdapterTest.php b/tests/Phinx/Db/Adapter/ProxyAdapterTest.php index c88723849..3c268a47d 100644 --- a/tests/Phinx/Db/Adapter/ProxyAdapterTest.php +++ b/tests/Phinx/Db/Adapter/ProxyAdapterTest.php @@ -147,5 +147,4 @@ public function testGetInvertedCommandsThrowsExceptionForIrreversibleCommand() ->save(); $this->adapter->getInvertedCommands(); } - } diff --git a/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php b/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php index 40aadf824..bda76516d 100644 --- a/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php +++ b/tests/Phinx/Db/Adapter/SQLiteAdapterTest.php @@ -594,7 +594,6 @@ public function testDropForeignKey() ->addForeignKey(['ref_table_field'], 'ref_table', ['field1'], $opts) ->save(); - $this->assertTrue($this->adapter->hasForeignKey($table->getName(), ['ref_table_id'])); $this->adapter->dropForeignKey($table->getName(), ['ref_table_id']); From ba43bbff13e5180bd697d59d3cda750d36626935 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 6 May 2018 20:27:01 +0200 Subject: [PATCH 20/21] Pleasing the CI --- tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php b/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php index 7db5a8a54..1cd58824b 100644 --- a/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php +++ b/tests/Phinx/Db/Adapter/TablePrefixAdapterTest.php @@ -2,7 +2,6 @@ namespace Test\Phinx\Db\Adapter; -use PHPUnit\Framework\TestCase; use Phinx\Db\Action\AddColumn; use Phinx\Db\Action\AddForeignKey; use Phinx\Db\Action\AddIndex; @@ -17,6 +16,7 @@ use Phinx\Db\Table\Column; use Phinx\Db\Table\ForeignKey; use Phinx\Db\Table\Table; +use PHPUnit\Framework\TestCase; class TablePrefixAdapterTest extends TestCase { From 831d940bf3cc6aa57739a03c1fab3c1fdd20c8e0 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 6 May 2018 20:28:59 +0200 Subject: [PATCH 21/21] Fixed regression in previous commit --- src/Phinx/Db/Plan/Plan.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Phinx/Db/Plan/Plan.php b/src/Phinx/Db/Plan/Plan.php index 72645a3bf..237e8333c 100644 --- a/src/Phinx/Db/Plan/Plan.php +++ b/src/Phinx/Db/Plan/Plan.php @@ -217,7 +217,7 @@ protected function gatherCreates($actions) return $action instanceof CreateTable; }) ->map(function ($action) { - return [$table->getName(), new NewTable($action->getTable())]; + return [$action->getTable()->getName(), new NewTable($action->getTable())]; }) ->each(function ($step) { $this->tableCreates[$step[0]] = $step[1];