From addb770d81a47441786e816cb8e4baed614e9bc4 Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Fri, 5 May 2017 23:03:38 +0200 Subject: [PATCH 01/20] Added bigint type to column type integer. --- mysql2phinx.php | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index d505e64..293f061 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -148,6 +148,7 @@ function getPhinxColumnType($columndata) case 'smallint': case 'int': case 'mediumint': + case 'bigint': return 'integer'; case 'timestamp': From e81f219e9f8b5abc4ea444d4354d9a6de7751090 Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Sat, 6 May 2017 14:08:03 +0200 Subject: [PATCH 02/20] Added support for decimal column type with precision and scale. --- README.md | 1 - mysql2phinx.php | 13 ++++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 012ca5e..3ade807 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ Currently **not supported**: * Column types: * [ ] `float` - * [ ] `decimal` * [ ] `time` * [ ] `binary` * [ ] `boolean` diff --git a/mysql2phinx.php b/mysql2phinx.php index 293f061..69de494 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -160,6 +160,9 @@ function getPhinxColumnType($columndata) case 'datetime': return 'datetime'; + case 'decimal': + return 'decimal'; + case 'enum': return 'enum'; @@ -242,11 +245,19 @@ function getPhinxColumnAttibutes($phinxtype, $columndata) } // unsigned - $pattern = '/\(\d+\) unsigned$/'; + $pattern = '/\(\d+(\s*,\s*\d+)?\) unsigned$/'; if (1 === preg_match($pattern, $columndata['Type'], $match)) { $attributes[] = '\'signed\' => false'; } + // decimal values + if ($phinxtype === 'decimal' + && 1 === preg_match('/decimal\((\d+)\s*,\s*(\d+)\)/i', $columndata['Type'], $decimalMatch) + ) { + $attributes[] = '\'precision\' => ' . (int) $decimalMatch[1]; + $attributes[] = '\'scale\' => ' . (int) $decimalMatch[2]; + } + // enum values if ($phinxtype === 'enum') { $attributes[] = '\'values\' => ' . str_replace('enum', 'array', $columndata['Type']); From f38b882e1ae21882cd65859d884d6fb543e5c67b Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Sat, 6 May 2017 14:18:51 +0200 Subject: [PATCH 03/20] Added mediumtext and longtext types to column type text. --- mysql2phinx.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index 69de494..4969a91 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -171,6 +171,8 @@ function getPhinxColumnType($columndata) case 'text': case 'tinytext': + case 'mediumtext': + case 'longtext': return 'text'; case 'varchar': From 42dd613749d1a5a0ace1106ff59a75499fb16e05 Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Sat, 6 May 2017 17:07:51 +0200 Subject: [PATCH 04/20] Changed the handling of host and port parameter to work as I think was intended. --- mysql2phinx.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 4969a91..5bd58f4 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -22,8 +22,8 @@ 'name' => $argv[1], 'user' => $argv[2], 'pass' => $argv[3], - 'host' => $argc === 5 ? $argv[6] : 'localhost', - 'port' => $argc === 6 ? $argv[5] : '3306' + 'host' => $argc >= 5 ? $argv[4] : 'localhost', + 'port' => $argc >= 6 ? $argv[5] : '3306' ); function createMigration($mysqli, $indent = 2) From f24eca8696936541d71f608cac1b07cca5654f6d Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Sun, 7 May 2017 20:31:15 +0200 Subject: [PATCH 05/20] Made a lot of code changes I might document piece by piece later. --- mysql2phinx.php | 272 ++++++++++++++++++++++++++++-------------------- 1 file changed, 162 insertions(+), 110 deletions(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 5bd58f4..0836f20 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -4,7 +4,7 @@ * * Commandline usage: * ``` - * $ php -f mysql2phinx [database] [user] [password] > migration.php + * $ php -f mysql2phinx.php [database] [user] [password] [host=localhost] [port=3306] > 20170507142126_initial_migration.php * ``` */ @@ -13,75 +13,117 @@ echo 'Phinx MySQL migration generator' . PHP_EOL; echo '===============================' . PHP_EOL; echo 'Usage:' . PHP_EOL; - echo 'php -f ' . $argv[0] . ' [database] [user] [password] > migration.php'; + echo "php -f {$argv[0]} [database] [user] [password] [host=localhost] [port=3306] > " . date('YmdHis') . "_initial_migration.php"; echo PHP_EOL; exit; } -$config = array( - 'name' => $argv[1], - 'user' => $argv[2], - 'pass' => $argv[3], - 'host' => $argc >= 5 ? $argv[4] : 'localhost', - 'port' => $argc >= 6 ? $argv[5] : '3306' -); +function getMysqliConnection($config) +{ + return new mysqli( + $config['host'], + $config['user'], + $config['pass'], + $config['name'], + $config['port'] + ); +} function createMigration($mysqli, $indent = 2) { - $output = array(); - foreach (getTables($mysqli) as $table) { + $tables = getTables($mysqli); + + $output = []; + $output[] = ' public function up()'; + $output[] = ' {'; + $output[] = ' // Making sure no foreign key constraints stops the creation'; + $output[] = ' $this->execute(\'SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;\');'; + $output[] = ''; + foreach ($tables as $table) { $output[] = getTableMigration($table, $mysqli, $indent); } - return implode(PHP_EOL, $output) . PHP_EOL ; -} - -function getMysqliConnection($config) -{ - $v = new mysqli($config['host'], $config['user'], $config['pass'], $config['name']); - if ($v === false) { - throw new Exception('Could not connect'); + $output[] = ' // Resetting the default foreign key check'; + $output[] = ' $this->execute(\'SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;\');'; + $output[] = ' }'; + $output[] = ''; + $output[] = ' public function down()'; + $output[] = ' {'; + $output[] = ' // Making sure no foreign key constraints stops the creation'; + $output[] = ' $this->execute(\'SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;\');'; + $output[] = ''; + foreach ($tables as $table) { + $output[] = getTableReversion($table, $mysqli, $indent); } - return $v; + $output[] = ' // Resetting the default foreign key check'; + $output[] = ' $this->execute(\'SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;\');'; + $output[] = ' }'; + + return implode(PHP_EOL, $output) . PHP_EOL ; } function getTables($mysqli) { - $res = $mysqli->query('SHOW TABLES'); - return array_map(function($a) { return $a[0]; }, $res->fetch_all()); + $tables = $mysqli->query('SHOW TABLES')->fetch_all(); + return array_column($tables, 0); } function getTableMigration($table, $mysqli, $indent) { $ind = getIndentation($indent); - $output = array(); - $output[] = $ind . '// Migration for table ' . $table; - $output[] = $ind . '$table = $this->table(\'' . $table . '\');'; - $output[] = $ind . '$table'; + $primaryColumns = []; - foreach (getColumns($table, $mysqli) as $column) { - if ($column['Field'] !== 'id') { - $output[] = getColumnMigration($column['Field'], $column, $indent + 1); + $columns = getColumns($table, $mysqli); + foreach ($columns as $column) { + if ($column['Key'] == 'PRI') { + $primaryColumns[] = $column['Field']; } } - if ($foreign_keys = getForeignKeysMigrations(getForeignKeys($table, $mysqli), $indent + 1)) { - $output[] = $foreign_keys; + $output = []; + $output[] = "{$ind}// Migration for table {$table}"; + $output[] = "{$ind}\$table = \$this->table('{$table}', " + . "['id' => false, 'primary_key' => " . (empty($primaryColumns) ? 'false' : "['" . implode("', '", $primaryColumns) . "']") . "]);"; + $output[] = $ind . '$table'; + + foreach ($columns as $column) { + $output[] = getColumnMigration($column, $indent + 1); + } + + if ($tableIndexes = getIndexMigrations(getIndexes($table, $mysqli), $indent + 1)) { + $output[] = $tableIndexes; } - $output[] = $ind . ' ->create();'; - $output[] = PHP_EOL; + if ($foreignKeys = getForeignKeysMigrations(getForeignKeys($table, $mysqli), $indent + 1)) { + $output[] = $foreignKeys; + } + + $output[] = $ind . ' ->create()'; + $output[] = $ind . ';'; + $output[] = ''; return implode(PHP_EOL, $output); } -function getColumnMigration($column, $columndata, $indent) +function getTableReversion($table, $mysqli, $indent) +{ + $ind = getIndentation($indent); + + $output = []; + $output[] = "{$ind}// Reversion for table {$table}"; + $output[] = "{$ind}\$this->dropTable('{$table}');"; + $output[] = ''; + + return implode(PHP_EOL, $output); +} + +function getColumnMigration($columndata, $indent) { $ind = getIndentation($indent); $phinxtype = getPhinxColumnType($columndata); $columnattributes = getPhinxColumnAttibutes($phinxtype, $columndata); - $output = $ind . '->addColumn(\'' . $column . '\', \'' . $phinxtype . '\', ' . $columnattributes . ')'; + $output = "{$ind}->addColumn('{$columndata['Field']}', '{$phinxtype}', {$columnattributes})"; return $output; } @@ -89,16 +131,17 @@ function getIndexMigrations($indexes, $indent) { $ind = getIndentation($indent); - $keyedindexes = array(); + $keyedindexes = []; foreach($indexes as $index) { - if ($index['Column_name'] === 'id') { + $key = $index['Key_name']; + + if ($key == 'PRIMARY') { continue; } - $key = $index['Key_name']; if (!isset($keyedindexes[$key])) { - $keyedindexes[$key] = array(); - $keyedindexes[$key]['columns'] = array(); + $keyedindexes[$key] = []; + $keyedindexes[$key]['columns'] = []; $keyedindexes[$key]['unique'] = $index['Non_unique'] !== '1'; } @@ -107,35 +150,37 @@ function getIndexMigrations($indexes, $indent) $output = []; - foreach ($keyedindexes as $index) { - $columns = 'array(\'' . implode('\', \'', $index['columns']) . '\')'; - $options = $index['unique'] ? 'array(\'unique\' => true)' : 'array()'; - $output[] = $ind . '->addIndex(' . $columns . ', ' . $options . ')'; + foreach ($keyedindexes as $indexName => $index) { + $columns = "['" . implode("', '", $index['columns']) . "']"; + $options = "['name' => '{$indexName}'"; + $options .= ($index['unique'] ? ", 'unique' => true" : ''); + $options .= ']'; + $output[] = "{$ind}->addIndex({$columns}, {$options})"; } return implode(PHP_EOL, $output); } -function getForeignKeysMigrations($foreign_keys, $indent) +function getForeignKeysMigrations($foreignKeys, $indent) { $ind = getIndentation($indent); + $output = []; - foreach ($foreign_keys as $foreign_key) { - $output[] = $ind . "->addForeignKey('" . $foreign_key['COLUMN_NAME'] . "', '" . $foreign_key['REFERENCED_TABLE_NAME'] . "', '" . $foreign_key['REFERENCED_COLUMN_NAME'] . "', array(" - . "'delete' => '" . str_replace(' ', '_', $foreign_key['DELETE_RULE']) . "'," - . "'update' => '" . str_replace(' ', '_', $foreign_key['UPDATE_RULE']) . "'" - . "))"; + + foreach ($foreignKeys as $foreignKey) { + $output[] = $ind . "->addForeignKey('{$foreignKey['COLUMN_NAME']}', '{$foreignKey['REFERENCED_TABLE_NAME']}', '{$foreignKey['REFERENCED_COLUMN_NAME']}', [" + . "'constraint' => '{$foreignKey['CONSTRAINT_NAME']}'," + . "'delete' => '" . str_replace(' ', '_', $foreignKey['DELETE_RULE']) . "'," + . "'update' => '" . str_replace(' ', '_', $foreignKey['UPDATE_RULE']) . "'" + . "])"; } + return implode(PHP_EOL, $output); } -/* ---- */ - function getMySQLColumnType($columndata) { - $type = $columndata['Type']; - $pattern = '/^[a-z]+/'; - preg_match($pattern, $type, $match); + preg_match('/^[a-z]+/', $columndata['Type'], $match); return $match[0]; } @@ -179,30 +224,31 @@ function getPhinxColumnType($columndata) return 'string'; default: - return '[' . $type . ']'; + return "[unsupported_{$type}]"; } } function getPhinxColumnAttibutes($phinxtype, $columndata) { - $attributes = array(); - - // var_dump($columndata); + $attributes = []; // has NULL if ($columndata['Null'] === 'YES') { - $attributes[] = '\'null\' => true'; + $attributes[] = "'null' => true"; } // default value if ($columndata['Default'] !== null) { - $default = is_int($columndata['Default']) ? $columndata['Default'] : '\'' . $columndata['Default'] . '\''; - $attributes[] = '\'default\' => ' . $default; + $default = (is_int($columndata['Default']) + ? $columndata['Default'] + : "'{$columndata['Default']}'" + ); + $attributes[] = "'default' => {$default}"; } // on update CURRENT_TIMESTAMP if ($columndata['Extra'] === 'on update CURRENT_TIMESTAMP') { - $attributes[] = '\'update\' => \'CURRENT_TIMESTAMP\''; + $attributes[] = "'update' => 'CURRENT_TIMESTAMP'"; } // limit / length @@ -243,75 +289,73 @@ function getPhinxColumnAttibutes($phinxtype, $columndata) } } if ($limit) { - $attributes[] = '\'limit\' => ' . $limit; + $attributes[] = "'limit' => {$limit}"; } // unsigned $pattern = '/\(\d+(\s*,\s*\d+)?\) unsigned$/'; if (1 === preg_match($pattern, $columndata['Type'], $match)) { - $attributes[] = '\'signed\' => false'; + $attributes[] = "'signed' => false"; } // decimal values if ($phinxtype === 'decimal' && 1 === preg_match('/decimal\((\d+)\s*,\s*(\d+)\)/i', $columndata['Type'], $decimalMatch) ) { - $attributes[] = '\'precision\' => ' . (int) $decimalMatch[1]; - $attributes[] = '\'scale\' => ' . (int) $decimalMatch[2]; + $attributes[] = "'precision' => " . (int) $decimalMatch[1]; + $attributes[] = "'scale' => " . (int) $decimalMatch[2]; } // enum values if ($phinxtype === 'enum') { - $attributes[] = '\'values\' => ' . str_replace('enum', 'array', $columndata['Type']); + $enumStr = preg_replace('/^enum\((.*)\)$/', '[$1]', $columndata['Type']); + $attributes[] = "'values' => {$enumStr}"; } - return 'array(' . implode(', ', $attributes) . ')'; + return '[' . implode(', ', $attributes) . ']'; } function getColumns($table, $mysqli) { - $res = $mysqli->query($query = 'SHOW COLUMNS FROM `' . $table . '`'); - if ($res === false) { - throw new Exception("Failed: $query"); - } - return $res->fetch_all(MYSQLI_ASSOC); + return $mysqli->query("SHOW COLUMNS FROM `{$table}`")->fetch_all(MYSQLI_ASSOC); } function getIndexes($table, $mysqli) { - $res = $mysqli->query('SHOW INDEXES FROM ' . $table); - return $res->fetch_all(MYSQLI_ASSOC); + return $mysqli->query("SHOW INDEXES FROM `{$table}`")->fetch_all(MYSQLI_ASSOC); } function getForeignKeys($table, $mysqli) { - $res = $mysqli->query("SELECT - cols.TABLE_NAME, - cols.COLUMN_NAME, - refs.REFERENCED_TABLE_NAME, - refs.REFERENCED_COLUMN_NAME, - cRefs.UPDATE_RULE, - cRefs.DELETE_RULE - FROM INFORMATION_SCHEMA.COLUMNS as cols - LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS refs - ON refs.TABLE_SCHEMA=cols.TABLE_SCHEMA - AND refs.REFERENCED_TABLE_SCHEMA=cols.TABLE_SCHEMA - AND refs.TABLE_NAME=cols.TABLE_NAME - AND refs.COLUMN_NAME=cols.COLUMN_NAME - LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS cons - ON cons.TABLE_SCHEMA=cols.TABLE_SCHEMA - AND cons.TABLE_NAME=cols.TABLE_NAME - AND cons.CONSTRAINT_NAME=refs.CONSTRAINT_NAME - LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS cRefs - ON cRefs.CONSTRAINT_SCHEMA=cols.TABLE_SCHEMA - AND cRefs.CONSTRAINT_NAME=refs.CONSTRAINT_NAME - WHERE - cols.TABLE_NAME = '" . $table . "' - AND cols.TABLE_SCHEMA = DATABASE() - AND refs.REFERENCED_TABLE_NAME IS NOT NULL - AND cons.CONSTRAINT_TYPE = 'FOREIGN KEY' - ;"); - return $res->fetch_all(MYSQLI_ASSOC); + return $mysqli->query( + "SELECT + cols.TABLE_NAME, + cols.COLUMN_NAME, + refs.CONSTRAINT_NAME, + refs.REFERENCED_TABLE_NAME, + refs.REFERENCED_COLUMN_NAME, + cRefs.UPDATE_RULE, + cRefs.DELETE_RULE + FROM INFORMATION_SCHEMA.COLUMNS as cols + LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS refs + ON refs.TABLE_SCHEMA=cols.TABLE_SCHEMA + AND refs.REFERENCED_TABLE_SCHEMA=cols.TABLE_SCHEMA + AND refs.TABLE_NAME=cols.TABLE_NAME + AND refs.COLUMN_NAME=cols.COLUMN_NAME + LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS cons + ON cons.TABLE_SCHEMA=cols.TABLE_SCHEMA + AND cons.TABLE_NAME=cols.TABLE_NAME + AND cons.CONSTRAINT_NAME=refs.CONSTRAINT_NAME + LEFT JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS cRefs + ON cRefs.CONSTRAINT_SCHEMA=cols.TABLE_SCHEMA + AND cRefs.CONSTRAINT_NAME=refs.CONSTRAINT_NAME + WHERE + cols.TABLE_NAME = '{$table}' + AND cols.TABLE_SCHEMA = DATABASE() + AND refs.REFERENCED_TABLE_NAME IS NOT NULL + AND cons.CONSTRAINT_TYPE = 'FOREIGN KEY' + ;" + )->fetch_all(MYSQLI_ASSOC); } function getIndentation($level) @@ -319,15 +363,23 @@ function getIndentation($level) return str_repeat(' ', $level); } +$connection = getMysqliConnection([ + 'name' => $argv[1], + 'user' => $argv[2], + 'pass' => $argv[3], + 'host' => ($argc >= 5 ? $argv[4] : 'localhost'), + 'port' => ($argc >= 6 ? $argv[5] : '3306'), +]); +if (!$connection) { + echo 'Connection to database failed.'; + exit; +} + echo ' Date: Sun, 7 May 2017 23:18:05 +0200 Subject: [PATCH 06/20] Added support for combined foreign keys --- mysql2phinx.php | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 0836f20..3466b69 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -165,10 +165,31 @@ function getForeignKeysMigrations($foreignKeys, $indent) { $ind = getIndentation($indent); - $output = []; + $groupedForeignKeys = []; foreach ($foreignKeys as $foreignKey) { - $output[] = $ind . "->addForeignKey('{$foreignKey['COLUMN_NAME']}', '{$foreignKey['REFERENCED_TABLE_NAME']}', '{$foreignKey['REFERENCED_COLUMN_NAME']}', [" + if (!isset($groupedForeignKeys[$foreignKey['CONSTRAINT_NAME']])) { + $groupedForeignKeys[$foreignKey['CONSTRAINT_NAME']] = [ + 'CONSTRAINT_NAME' => $foreignKey['CONSTRAINT_NAME'], + 'REFERENCED_TABLE_NAME' => $foreignKey['REFERENCED_TABLE_NAME'], + 'DELETE_RULE' => $foreignKey['DELETE_RULE'], + 'UPDATE_RULE' => $foreignKey['UPDATE_RULE'], + 'COLUMN_NAMES' => [], + 'REFERENCED_COLUMN_NAMES' => [], + ]; + } + $groupedForeignKeys[$foreignKey['CONSTRAINT_NAME']]['COLUMN_NAMES'][] = $foreignKey['COLUMN_NAME']; + $groupedForeignKeys[$foreignKey['CONSTRAINT_NAME']]['REFERENCED_COLUMN_NAMES'][] = $foreignKey['REFERENCED_COLUMN_NAME']; + } + + $output = []; + + foreach ($groupedForeignKeys as $foreignKey) { + $output[] = "{$ind}->addForeignKey(" + . "['" . implode("', '", $foreignKey['COLUMN_NAMES']) . "'], " + . "'{$foreignKey['REFERENCED_TABLE_NAME']}', " + . "['" . implode("', '", $foreignKey['REFERENCED_COLUMN_NAMES']) . "'], " + . "[" . "'constraint' => '{$foreignKey['CONSTRAINT_NAME']}'," . "'delete' => '" . str_replace(' ', '_', $foreignKey['DELETE_RULE']) . "'," . "'update' => '" . str_replace(' ', '_', $foreignKey['UPDATE_RULE']) . "'" From 5f6a69fadb42b4116ee15650c640738bf0bcaafe Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Mon, 8 May 2017 20:35:59 +0200 Subject: [PATCH 07/20] Added support for auto_increment column attribute. --- mysql2phinx.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index 3466b69..9755746 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -272,6 +272,11 @@ function getPhinxColumnAttibutes($phinxtype, $columndata) $attributes[] = "'update' => 'CURRENT_TIMESTAMP'"; } + // auto_increment + if ($columndata['Extra'] === 'auto_increment') { + $attributes[] = "'identity' => true"; + } + // limit / length $limit = 0; switch (getMySQLColumnType($columndata)) { From 137c38c815ecf4535bdede3a9ee0d051cf1ee2b3 Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Mon, 8 May 2017 21:26:28 +0200 Subject: [PATCH 08/20] Added support for engine and collation table information. --- mysql2phinx.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 9755746..1824fb4 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -80,10 +80,16 @@ function getTableMigration($table, $mysqli, $indent) } } + $tableInformation = getTableInformation($table, $mysqli); + $output = []; $output[] = "{$ind}// Migration for table {$table}"; $output[] = "{$ind}\$table = \$this->table('{$table}', " - . "['id' => false, 'primary_key' => " . (empty($primaryColumns) ? 'false' : "['" . implode("', '", $primaryColumns) . "']") . "]);"; + . "['id' => false" + . ", 'primary_key' => " . (empty($primaryColumns) ? 'false' : "['" . implode("', '", $primaryColumns) . "', ]") + . ", 'engine' => '{$tableInformation['Engine']}'" + . ", 'collation' => '{$tableInformation['Collation']}'" + . "]);"; $output[] = $ind . '$table'; foreach ($columns as $column) { @@ -351,6 +357,11 @@ function getIndexes($table, $mysqli) return $mysqli->query("SHOW INDEXES FROM `{$table}`")->fetch_all(MYSQLI_ASSOC); } +function getTableInformation($table, $mysqli) +{ + return $mysqli->query("SHOW TABLE STATUS WHERE Name = '{$table}'")->fetch_array(MYSQLI_ASSOC); +} + function getForeignKeys($table, $mysqli) { return $mysqli->query( From bdcd64dc3fe216370086196ed41daea7e2665067 Mon Sep 17 00:00:00 2001 From: Magnus Backhurst Date: Wed, 31 May 2017 09:03:29 +0200 Subject: [PATCH 09/20] Removed trailing comma --- mysql2phinx.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 1824fb4..d800716 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -86,7 +86,7 @@ function getTableMigration($table, $mysqli, $indent) $output[] = "{$ind}// Migration for table {$table}"; $output[] = "{$ind}\$table = \$this->table('{$table}', " . "['id' => false" - . ", 'primary_key' => " . (empty($primaryColumns) ? 'false' : "['" . implode("', '", $primaryColumns) . "', ]") + . ", 'primary_key' => " . (empty($primaryColumns) ? 'false' : "['" . implode("', '", $primaryColumns) . "']") . ", 'engine' => '{$tableInformation['Engine']}'" . ", 'collation' => '{$tableInformation['Collation']}'" . "]);"; From 9b0890890df5bb01455dc4513f215cace1a05c63 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:28:08 +0100 Subject: [PATCH 10/20] add type "blob" --- mysql2phinx.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index d800716..494c23b 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -241,6 +241,9 @@ function getPhinxColumnType($columndata) case 'char': return 'char'; + case 'blob': + return 'blob'; + case 'text': case 'tinytext': case 'mediumtext': From 224502532d209c70ff01a5cfdf605bd26bc80791 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:29:07 +0100 Subject: [PATCH 11/20] fix "no primary key" to use null --- mysql2phinx.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 494c23b..8828643 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -86,7 +86,7 @@ function getTableMigration($table, $mysqli, $indent) $output[] = "{$ind}// Migration for table {$table}"; $output[] = "{$ind}\$table = \$this->table('{$table}', " . "['id' => false" - . ", 'primary_key' => " . (empty($primaryColumns) ? 'false' : "['" . implode("', '", $primaryColumns) . "']") + . ", 'primary_key' => " . (empty($primaryColumns) ? 'null' : "['" . implode("', '", $primaryColumns) . "']") . ", 'engine' => '{$tableInformation['Engine']}'" . ", 'collation' => '{$tableInformation['Collation']}'" . "]);"; From 4499cefb7329fa766063675df6908063ebd39be1 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:30:15 +0100 Subject: [PATCH 12/20] add index type "fulltext" --- mysql2phinx.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index 8828643..7a5a305 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -149,6 +149,7 @@ function getIndexMigrations($indexes, $indent) $keyedindexes[$key] = []; $keyedindexes[$key]['columns'] = []; $keyedindexes[$key]['unique'] = $index['Non_unique'] !== '1'; + $keyedindexes[$key]['fulltext'] = $index['Index_type'] == 'FULLTEXT'; } $keyedindexes[$key]['columns'][] = $index['Column_name']; @@ -160,6 +161,7 @@ function getIndexMigrations($indexes, $indent) $columns = "['" . implode("', '", $index['columns']) . "']"; $options = "['name' => '{$indexName}'"; $options .= ($index['unique'] ? ", 'unique' => true" : ''); + $options .= ($index['fulltext'] ? ", 'type' => 'fulltext'" : ''); $options .= ']'; $output[] = "{$ind}->addIndex({$columns}, {$options})"; } From 9e165ed922888eeef8b478bc39a634085d4e4324 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:31:15 +0100 Subject: [PATCH 13/20] add "comment on columns" --- mysql2phinx.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 7a5a305..b659a56 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -349,12 +349,17 @@ function getPhinxColumnAttibutes($phinxtype, $columndata) $attributes[] = "'values' => {$enumStr}"; } + // column comments + if (!empty($columndata['Comment'])) { + $attributes[] = "'comment' => '".addcslashes($columndata['Comment'], "'\\")."'"; + } + return '[' . implode(', ', $attributes) . ']'; } function getColumns($table, $mysqli) { - return $mysqli->query("SHOW COLUMNS FROM `{$table}`")->fetch_all(MYSQLI_ASSOC); + return $mysqli->query("SHOW FULL COLUMNS FROM `{$table}`")->fetch_all(MYSQLI_ASSOC); } function getIndexes($table, $mysqli) From c451901e5b301460043adb063d1cd9cb8626f2f6 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:32:36 +0100 Subject: [PATCH 14/20] add "comment on tables" --- mysql2phinx.php | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index b659a56..4036a15 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -89,6 +89,7 @@ function getTableMigration($table, $mysqli, $indent) . ", 'primary_key' => " . (empty($primaryColumns) ? 'null' : "['" . implode("', '", $primaryColumns) . "']") . ", 'engine' => '{$tableInformation['Engine']}'" . ", 'collation' => '{$tableInformation['Collation']}'" + . (!empty($tableInformation['Comment'])?", 'comment' => '".addcslashes($tableInformation['Comment'], "'\\")."'":'') . "]);"; $output[] = $ind . '$table'; From 5af3fbf0f0413f80b8692380b00c02eebfad03e3 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:35:32 +0100 Subject: [PATCH 15/20] pass tableInformation into columnMigration context --- mysql2phinx.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index 4036a15..f33cc2f 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -94,7 +94,7 @@ function getTableMigration($table, $mysqli, $indent) $output[] = $ind . '$table'; foreach ($columns as $column) { - $output[] = getColumnMigration($column, $indent + 1); + $output[] = getColumnMigration($column, $indent + 1, $tableInformation); } if ($tableIndexes = getIndexMigrations(getIndexes($table, $mysqli), $indent + 1)) { @@ -124,12 +124,12 @@ function getTableReversion($table, $mysqli, $indent) return implode(PHP_EOL, $output); } -function getColumnMigration($columndata, $indent) +function getColumnMigration($columndata, $indent, $tableInformation) { $ind = getIndentation($indent); $phinxtype = getPhinxColumnType($columndata); - $columnattributes = getPhinxColumnAttibutes($phinxtype, $columndata); + $columnattributes = getPhinxColumnAttibutes($phinxtype, $columndata, $tableInformation); $output = "{$ind}->addColumn('{$columndata['Field']}', '{$phinxtype}', {$columnattributes})"; return $output; } @@ -261,7 +261,7 @@ function getPhinxColumnType($columndata) } } -function getPhinxColumnAttibutes($phinxtype, $columndata) +function getPhinxColumnAttibutes($phinxtype, $columndata, $tableInformation) { $attributes = []; From f90122ab12c6b594be662126893d4a7f21724edd Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:37:02 +0100 Subject: [PATCH 16/20] add "column collation != table" catch requires "pass tableInformation into columnMigration context" --- mysql2phinx.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index f33cc2f..8f1be47 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -355,6 +355,11 @@ function getPhinxColumnAttibutes($phinxtype, $columndata, $tableInformation) $attributes[] = "'comment' => '".addcslashes($columndata['Comment'], "'\\")."'"; } + // column collation + if (!empty($columndata['Collation']) && $columndata['Collation']!=$tableInformation['Collation']) { + $attributes[] = "'collation' => '".$columndata['Collation']."'"; + } + return '[' . implode(', ', $attributes) . ']'; } From b07f680ecad0486027d06cf2532b1a6d501a750a Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:40:20 +0100 Subject: [PATCH 17/20] add "row_format on tables" --- mysql2phinx.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index 8f1be47..d3bf3ca 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -90,6 +90,9 @@ function getTableMigration($table, $mysqli, $indent) . ", 'engine' => '{$tableInformation['Engine']}'" . ", 'collation' => '{$tableInformation['Collation']}'" . (!empty($tableInformation['Comment'])?", 'comment' => '".addcslashes($tableInformation['Comment'], "'\\")."'":'') + . (!empty($tableInformation['Create_options'])&&preg_match('/row_format=([^ ]+)/', $tableInformation['Create_options'], $rowFormatMatches)?( + ", 'row_format' => '".$rowFormatMatches[1]."'" + ):'') . "]);"; $output[] = $ind . '$table'; From a89f233e2dae75041da669aba0cb8d342ab37dff Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:40:58 +0100 Subject: [PATCH 18/20] extend "column limit" detection --- mysql2phinx.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql2phinx.php b/mysql2phinx.php index d3bf3ca..f019f2c 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -325,8 +325,11 @@ function getPhinxColumnAttibutes($phinxtype, $columndata, $tableInformation) default: $pattern = '/\((\d+)\)$/'; + $pattern_alt = '/\((\d+)\) (un|)signed$/'; if (1 === preg_match($pattern, $columndata['Type'], $match)) { $limit = $match[1]; + }else if (1 === preg_match($pattern_alt, $columndata['Type'], $match_alt)) { + $limit = $match_alt[1]; } } if ($limit) { From 934844be2563a2d34e5e8e76c23ec2c4367b4018 Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 05:45:30 +0100 Subject: [PATCH 19/20] add tableBlacklist for unmanaged "phinxlog" (exessive as `NOT LIKE` does not exist in `SHOW TABLES`) --- mysql2phinx.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mysql2phinx.php b/mysql2phinx.php index f019f2c..0696e5e 100644 --- a/mysql2phinx.php +++ b/mysql2phinx.php @@ -63,8 +63,20 @@ function createMigration($mysqli, $indent = 2) function getTables($mysqli) { - $tables = $mysqli->query('SHOW TABLES')->fetch_all(); - return array_column($tables, 0); + $res = $mysqli->query('SHOW TABLES'); + $blacklist = array( + 'phinxlog', + ); + $buff = array_map(function ($a) { + return $a[0]; + }, $res->fetch_all()); + $newbuff = array(); + foreach ($buff as $k => $t) { + if (in_array($t, $blacklist)) + continue; + $newbuff[] = $t; + } + return $newbuff; } function getTableMigration($table, $mysqli, $indent) From 7099d68b3f22c2b2c4fd395a764b4051471deb1b Mon Sep 17 00:00:00 2001 From: Tabakhase Date: Sun, 28 Oct 2018 10:52:14 +0100 Subject: [PATCH 20/20] update README - not supported types --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3ade807..a789b67 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,4 @@ Currently **not supported**: * [ ] `time` * [ ] `binary` * [ ] `boolean` + * [ ] `double`