From 144d67bd725e01ae9736e5632dc89cf9ffe87e0a Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Thu, 11 Mar 2021 22:59:36 -0500 Subject: [PATCH] Add code generation into the mix --- psalm-baseline.xml | 99 ++++++++++--------- src/DataIntegrity.php | 4 +- src/Parser/ShowParser.php | 1 - src/Processor/CreateProcessor.php | 2 +- src/Processor/Expression/Evaluator.php | 10 +- .../Expression/FunctionEvaluator.php | 8 +- src/Processor/JoinProcessor.php | 2 +- src/Processor/SelectProcessor.php | 4 +- src/Processor/ShowIndexProcessor.php | 5 +- src/Schema/Column.php | 23 ++++- src/Schema/Column/Blob.php | 9 ++ src/Schema/Column/Char.php | 5 - src/Schema/Column/CharacterColumn.php | 23 +++++ src/Schema/Column/Date.php | 1 + src/Schema/Column/DateTime.php | 1 + src/Schema/Column/DecimalPointColumn.php | 10 ++ src/Schema/Column/Defaultable.php | 5 +- src/Schema/Column/EmptyConstructorTrait.php | 22 +++++ src/Schema/Column/Enum.php | 28 +----- src/Schema/Column/HasOptionsTrait.php | 44 +++++++++ src/Schema/Column/IntegerColumn.php | 8 +- src/Schema/Column/IntegerColumnTrait.php | 27 ++++- src/Schema/Column/LongBlob.php | 9 ++ src/Schema/Column/LongText.php | 1 + src/Schema/Column/MediumBlob.php | 9 ++ src/Schema/Column/MediumText.php | 1 + src/Schema/Column/MySqlDefaultTrait.php | 6 +- src/Schema/Column/NullColumn.php | 2 + src/Schema/Column/NumberColumn.php | 3 +- src/Schema/Column/Set.php | 28 +----- src/Schema/Column/Text.php | 1 + src/Schema/Column/TextTrait.php | 12 +++ src/Schema/Column/Time.php | 1 + src/Schema/Column/Timestamp.php | 1 + src/Schema/Column/TinyBlob.php | 9 ++ src/Schema/Column/TinyText.php | 1 + src/Schema/Column/Varbinary.php | 8 ++ src/Schema/Column/Varchar.php | 5 - src/Schema/Column/Year.php | 1 + src/Schema/TableDefinition.php | 31 ++++++ tests/CreateTableParseTest.php | 32 ++++++ tests/EndToEndTest.php | 1 + tests/ShowIndexParseTest.php | 1 - 43 files changed, 365 insertions(+), 139 deletions(-) create mode 100644 src/Schema/Column/EmptyConstructorTrait.php create mode 100644 src/Schema/Column/HasOptionsTrait.php create mode 100644 tests/CreateTableParseTest.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 31eda778..10081529 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + $value @@ -7,16 +7,8 @@ $column_default - - $existing_row[$field] - $existing_row[$key] - $new_row[$key] - $new_row[$key] - $new_row[$key] - - + $column_default - $key $row[$column_name] $value @@ -162,14 +154,6 @@ - - \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_OFFSET_CAPTURE - - - $tokens - $tokens - $tokens - $tokens @@ -178,24 +162,6 @@ $next === null - - $cache - - - self::$cache - - - self::$cache[$sql] - - - self::$cache[$sql] - - - SelectQuery|InsertQuery|UpdateQuery|TruncateQuery|DeleteQuery|DropTableQuery|ShowTablesQuery - - - self::$cache[$sql] - $out array<int, Token> @@ -206,11 +172,6 @@ $type - - - $token === null - - $token === null @@ -231,9 +192,7 @@ $stmt->values $stmt->values - - $conn->getDatabaseName() - $conn->getDatabaseName() + $stmt->decimals $stmt->length $stmt->length @@ -671,11 +630,20 @@ $values + + + $this->getDefault() + + - - $character_set - $collation - + + $this->getDefault() + + + + + $this->getDefault() + @@ -685,11 +653,36 @@ getDefault + + + $this->getDefault() + + + + + $this->getDefault() + + $mysql_default + + + $this->getDefault() + + + + + $this->getDefault() + + + + + $this->getDefault() + + $mysql_default @@ -700,6 +693,16 @@ $mysql_default + + + $this->getDefault() + + + + + $this->getDefault() + + $autoIncrementOffsets diff --git a/src/DataIntegrity.php b/src/DataIntegrity.php index fd1b09b4..035e0eb5 100644 --- a/src/DataIntegrity.php +++ b/src/DataIntegrity.php @@ -63,7 +63,7 @@ public static function ensureColumnsPresent( ) { foreach ($table_definition->columns as $column_name => $column) { $php_type = $column->getPhpType(); - $column_nullable = $column->isNullable; + $column_nullable = $column->isNullable(); $column_default = $column instanceof Schema\Column\Defaultable ? $column->getDefault() : null; @@ -151,7 +151,7 @@ public static function coerceValueToColumn( ) { $php_type = $column->getPhpType(); - if ($column->isNullable && $value === null) { + if ($column->isNullable() && $value === null) { return null; } diff --git a/src/Parser/ShowParser.php b/src/Parser/ShowParser.php index 881d5bf0..15d7eb95 100644 --- a/src/Parser/ShowParser.php +++ b/src/Parser/ShowParser.php @@ -57,7 +57,6 @@ public function parse() default: throw new ParserException("Parser error: expected SHOW TABLES"); } - } private function parseShowTables(): ShowTablesQuery diff --git a/src/Processor/CreateProcessor.php b/src/Processor/CreateProcessor.php index b0ba087b..14c6343a 100644 --- a/src/Processor/CreateProcessor.php +++ b/src/Processor/CreateProcessor.php @@ -67,7 +67,7 @@ public static function makeTableDefinition( foreach ($stmt->fields as $field) { $definition_columns[$field->name] = $column = self::getDefinitionColumn($field->type); - $column->isNullable = (bool) $field->type->null; + $column->setNullable((bool) $field->type->null); if ($field->auto_increment && $column instanceof Column\IntegerColumn) { $column->autoIncrement(); diff --git a/src/Processor/Expression/Evaluator.php b/src/Processor/Expression/Evaluator.php index c9651779..ba832799 100644 --- a/src/Processor/Expression/Evaluator.php +++ b/src/Processor/Expression/Evaluator.php @@ -290,13 +290,13 @@ public static function combineColumnTypes(array $types) : Column if ($type_0_null) { $type = clone $types[1]; - $type->isNullable = true; + $type->setNullable(true); return $type; } if ($type_1_null) { $type = clone $types[0]; - $type->isNullable = true; + $type->setNullable(true); return $type; } } @@ -311,7 +311,7 @@ public static function combineColumnTypes(array $types) : Column $non_null_types = []; foreach ($types as $type) { - if ($type->isNullable) { + if ($type->isNullable()) { $is_nullable = true; } @@ -326,7 +326,7 @@ public static function combineColumnTypes(array $types) : Column if (count($non_null_types) === 1) { $type = clone $non_null_types[0]; - $type->isNullable = true; + $type->setNullable(true); return $type; } @@ -357,7 +357,7 @@ public static function combineColumnTypes(array $types) : Column } if ($is_nullable) { - $column->isNullable = true; + $column->setNullable(true); } return $column; diff --git a/src/Processor/Expression/FunctionEvaluator.php b/src/Processor/Expression/FunctionEvaluator.php index b4c3f0e0..3d0c64a4 100644 --- a/src/Processor/Expression/FunctionEvaluator.php +++ b/src/Processor/Expression/FunctionEvaluator.php @@ -121,7 +121,7 @@ public static function getColumnSchema( $column = new Column\BigInt(false, 10); } - $column->isNullable = true; + $column->setNullable(true); return $column; case 'MOD': @@ -148,7 +148,7 @@ public static function getColumnSchema( } $if = clone $if; - $if->isNullable = false; + $if->setNullable(false); if ($if->getPhpType() === 'string') { return $if; @@ -209,8 +209,8 @@ public static function getColumnSchema( $date = new Column\Date(); - if ($arg->isNullable) { - $date->isNullable = true; + if ($arg->isNullable()) { + $date->setNullable(true); } return $date; diff --git a/src/Processor/JoinProcessor.php b/src/Processor/JoinProcessor.php index 63be5f88..d69a0664 100644 --- a/src/Processor/JoinProcessor.php +++ b/src/Processor/JoinProcessor.php @@ -63,7 +63,7 @@ public static function process( $parts = explode('.%.', $name); $null_placeholder[$right_table_name . '.%.' . end($parts)] = null; $column = clone $column; - $column->isNullable = true; + $column->setNullable(true); $right_result->columns[$name] = $column; } diff --git a/src/Processor/SelectProcessor.php b/src/Processor/SelectProcessor.php index a5735fa5..0acd71e3 100644 --- a/src/Processor/SelectProcessor.php +++ b/src/Processor/SelectProcessor.php @@ -512,7 +512,7 @@ private static function getSelectSchema( $use_cache ); - $columns[$expr->name]->isNullable = true; + $columns[$expr->name]->setNullable(true); } } } @@ -622,7 +622,7 @@ function ($col) { if (isset($subquery_result->columns[$column_name]) && (\get_class($subquery_result->columns[$column_name]) !== \get_class($column) - || $subquery_result->columns[$column_name]->isNullable !== $column->isNullable) + || $subquery_result->columns[$column_name]->isNullable() !== $column->isNullable()) ) { $columns[$column_name] = Expression\Evaluator::combineColumnTypes([ $subquery_result->columns[$column_name], diff --git a/src/Processor/ShowIndexProcessor.php b/src/Processor/ShowIndexProcessor.php index 308a7666..df9aaaaa 100644 --- a/src/Processor/ShowIndexProcessor.php +++ b/src/Processor/ShowIndexProcessor.php @@ -3,7 +3,6 @@ namespace Vimeo\MysqlEngine\Processor; - use Vimeo\MysqlEngine\FakePdoInterface; use Vimeo\MysqlEngine\Query\ShowIndexQuery; use Vimeo\MysqlEngine\Schema\Column; @@ -59,7 +58,7 @@ public static function process( 'Sub_part' => null, // because PACK_KEYS is not implemented 'Packed' => null, - 'Null' => $table_definition->columns[$column]->isNullable ? 'YES' : '', + 'Null' => $table_definition->columns[$column]->isNullable() ? 'YES' : '', // because Index does not have $mode (in the CreateIndex) 'Index_type' => null, // because DISABLE KEYS is not implemented @@ -72,4 +71,4 @@ public static function process( $result = self::applyWhere($conn, $scope, $stmt->whereClause, new QueryResult($rows, $columns)); return new QueryResult(array_merge($result->rows), $result->columns); } -} \ No newline at end of file +} diff --git a/src/Schema/Column.php b/src/Schema/Column.php index 52ceb113..4247d08b 100644 --- a/src/Schema/Column.php +++ b/src/Schema/Column.php @@ -6,10 +6,31 @@ abstract class Column /** * @var bool */ - public $isNullable = true; + private $isNullable = true; + + public function isNullable() : bool + { + return $this->isNullable; + } + + /** + * @return static + */ + public function setNullable(bool $is_nullable) + { + $this->isNullable = $is_nullable; + return $this; + } + + public function getNullablePhp() : string + { + return '->setNullable(' . ($this->isNullable() ? 'true' : 'false') . ')'; + } /** * @return 'int'|'string'|'float'|'null' */ abstract public function getPhpType() : string; + + abstract public function getPhpCode() : string; } diff --git a/src/Schema/Column/Blob.php b/src/Schema/Column/Blob.php index 842bb1c8..66cb476c 100644 --- a/src/Schema/Column/Blob.php +++ b/src/Schema/Column/Blob.php @@ -9,4 +9,13 @@ public function __construct() { parent::__construct(65535, 'binary', '_bin'); } + + public function getPhpCode() : string + { + $default = $this->getDefault() !== null ? '\'' . $this->getDefault() . '\'' : 'null'; + + return '(new \\' . static::class . '())' + . ($this->hasDefault() ? '->setDefault(' . $default . ')' : '') + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/Char.php b/src/Schema/Column/Char.php index ea1963b1..c7797a01 100644 --- a/src/Schema/Column/Char.php +++ b/src/Schema/Column/Char.php @@ -6,9 +6,4 @@ class Char extends CharacterColumn implements StringColumn, Defaultable { use MySqlDefaultTrait; - - public function __construct(int $max_string_length, ?string $character_set = null, ?string $collation = null) - { - parent::__construct($max_string_length, $character_set, $collation); - } } diff --git a/src/Schema/Column/CharacterColumn.php b/src/Schema/Column/CharacterColumn.php index cd13710a..54533640 100644 --- a/src/Schema/Column/CharacterColumn.php +++ b/src/Schema/Column/CharacterColumn.php @@ -54,4 +54,27 @@ public function getPhpType() : string { return 'string'; } + + public function getPhpCode() : string + { + $default = ''; + + if ($this instanceof Defaultable && $this->hasDefault()) { + if ($this->getDefault() === null) { + $default = '->setDefault(null)'; + } else { + $use_quotes = $this->getPhpType() === 'string'; + $default = '->setDefault(\'' . $this->getDefault() . '\')'; + } + } + + return '(new \\' . static::class . '(' + . $this->max_string_length + . ($this->character_set !== null && $this->collation !== null + ? ', \'' . $this->character_set . '\'' . ', \'' . $this->collation . '\'' + : '') + . '))' + . $default + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/Date.php b/src/Schema/Column/Date.php index 5737cd11..b71aee76 100644 --- a/src/Schema/Column/Date.php +++ b/src/Schema/Column/Date.php @@ -4,6 +4,7 @@ class Date extends \Vimeo\MysqlEngine\Schema\Column implements ChronologicalColumn, Defaultable { use MySqlDefaultTrait; + use EmptyConstructorTrait; public function getPhpType() : string { diff --git a/src/Schema/Column/DateTime.php b/src/Schema/Column/DateTime.php index b8845742..5b24342e 100644 --- a/src/Schema/Column/DateTime.php +++ b/src/Schema/Column/DateTime.php @@ -4,6 +4,7 @@ class DateTime extends \Vimeo\MysqlEngine\Schema\Column implements ChronologicalColumn, Defaultable { use MySqlDefaultTrait; + use EmptyConstructorTrait; public function getPhpType() : string { diff --git a/src/Schema/Column/DecimalPointColumn.php b/src/Schema/Column/DecimalPointColumn.php index 94bb0c21..46d14714 100644 --- a/src/Schema/Column/DecimalPointColumn.php +++ b/src/Schema/Column/DecimalPointColumn.php @@ -46,4 +46,14 @@ public function getPhpType() : string { return 'float'; } + + public function getPhpCode() : string + { + return '(new \\' . static::class . '(' + . $this->precision + . ', ' . $this->scale + . '))' + . ($this->hasDefault() ? '->setDefault(\'' . $this->getDefault() . '\')' : '') + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/Defaultable.php b/src/Schema/Column/Defaultable.php index 687e4b09..833e8ca1 100644 --- a/src/Schema/Column/Defaultable.php +++ b/src/Schema/Column/Defaultable.php @@ -3,7 +3,10 @@ interface Defaultable { - public function setDefault($mysql_default) : void; + /** + * @return static + */ + public function setDefault($mysql_default); public function hasDefault() : bool; diff --git a/src/Schema/Column/EmptyConstructorTrait.php b/src/Schema/Column/EmptyConstructorTrait.php new file mode 100644 index 00000000..41b30833 --- /dev/null +++ b/src/Schema/Column/EmptyConstructorTrait.php @@ -0,0 +1,22 @@ +hasDefault()) { + if ($this->getDefault() === null) { + $default = '->setDefault(null)'; + } else { + $default = '->setDefault(\'' . $this->getDefault() . '\')'; + } + } + + return '(new \\' . static::class . '())' + . $default + . $this->getNullablePhp(); + } +} diff --git a/src/Schema/Column/Enum.php b/src/Schema/Column/Enum.php index f9692d26..895aaf01 100644 --- a/src/Schema/Column/Enum.php +++ b/src/Schema/Column/Enum.php @@ -4,31 +4,5 @@ class Enum extends \Vimeo\MysqlEngine\Schema\Column implements Defaultable { use MySqlDefaultTrait; - - /** - * @var string[] - */ - protected $options = []; - - /** - * @param string[] $options - */ - public function __construct(array $options) - { - $this->options = $options; - } - - /** - * @return string[] - * @psalm-return array - */ - public function getOptions() : array - { - return $this->options; - } - - public function getPhpType() : string - { - return 'string'; - } + use HasOptionsTrait; } diff --git a/src/Schema/Column/HasOptionsTrait.php b/src/Schema/Column/HasOptionsTrait.php new file mode 100644 index 00000000..6a026c78 --- /dev/null +++ b/src/Schema/Column/HasOptionsTrait.php @@ -0,0 +1,44 @@ +options = $options; + } + + /** + * @return string[] + * @psalm-return array + */ + public function getOptions() : array + { + return $this->options; + } + + /** + * @return 'int'|'string'|'float'|'null' + */ + public function getPhpType() : string + { + return 'string'; + } + + public function getPhpCode() : string + { + $default = $this->getDefault() !== null ? '\'' . $this->getDefault() . '\'' : 'null'; + + return '(new \\' . static::class . '([\'' . \implode('\', \'', $this->options) . '\']))' + . ($this->hasDefault() ? '->setDefault(' . $default . ')' : '') + . $this->getNullablePhp(); + } +} diff --git a/src/Schema/Column/IntegerColumn.php b/src/Schema/Column/IntegerColumn.php index 675bd188..5c840204 100644 --- a/src/Schema/Column/IntegerColumn.php +++ b/src/Schema/Column/IntegerColumn.php @@ -3,9 +3,13 @@ interface IntegerColumn { - public function setDefault($mysql_default) : void; + /** @return static */ + public function setDefault($mysql_default); - public function autoIncrement() : void; + /** + * @return static + */ + public function autoIncrement(); public function isAutoIncrement() : bool; diff --git a/src/Schema/Column/IntegerColumnTrait.php b/src/Schema/Column/IntegerColumnTrait.php index fd189efb..655b2384 100644 --- a/src/Schema/Column/IntegerColumnTrait.php +++ b/src/Schema/Column/IntegerColumnTrait.php @@ -29,9 +29,13 @@ public function getDisplayWidth() : int return $this->integer_display_width; } - public function autoIncrement() : void + /** + * @return static + */ + public function autoIncrement() { $this->auto_increment = true; + return $this; } public function isAutoIncrement() : bool @@ -51,4 +55,25 @@ public function getPhpType() : string { return 'int'; } + + public function getPhpCode() : string + { + $default = ''; + + if ($this instanceof Defaultable && $this->hasDefault()) { + $default = '->setDefault(' + . ($this->getDefault() === null + ? 'null' + : '\'' . $this->getDefault() . '\'') + . ')'; + } + + return '(new \\' . static::class . '(' + . ($this->unsigned ? 'true' : 'false') + . ', ' . $this->integer_display_width + . '))' + . $default + . $this->getNullablePhp() + . ($this->isAutoIncrement() ? '->autoIncrement()' : ''); + } } diff --git a/src/Schema/Column/LongBlob.php b/src/Schema/Column/LongBlob.php index 1af211a6..3eb6d0cd 100644 --- a/src/Schema/Column/LongBlob.php +++ b/src/Schema/Column/LongBlob.php @@ -9,4 +9,13 @@ public function __construct() { parent::__construct(4294967295, 'binary', '_bin'); } + + public function getPhpCode() : string + { + $default = $this->getDefault() !== null ? '\'' . $this->getDefault() . '\'' : 'null'; + + return '(new \\' . static::class . '())' + . ($this->hasDefault() ? '->setDefault(' . $default . ')' : '') + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/LongText.php b/src/Schema/Column/LongText.php index 24fdee05..d3b97206 100644 --- a/src/Schema/Column/LongText.php +++ b/src/Schema/Column/LongText.php @@ -6,6 +6,7 @@ class LongText extends CharacterColumn implements StringColumn { use TextTrait; + use MySqlDefaultTrait; /** * @var string diff --git a/src/Schema/Column/MediumBlob.php b/src/Schema/Column/MediumBlob.php index ee5c077f..1e17f1b2 100644 --- a/src/Schema/Column/MediumBlob.php +++ b/src/Schema/Column/MediumBlob.php @@ -9,4 +9,13 @@ public function __construct() { parent::__construct(16777215, 'binary', '_bin'); } + + public function getPhpCode() : string + { + $default = $this->getDefault() !== null ? '\'' . $this->getDefault() . '\'' : 'null'; + + return '(new \\' . static::class . '())' + . ($this->hasDefault() ? '->setDefault(' . $default . ')' : '') + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/MediumText.php b/src/Schema/Column/MediumText.php index 2ae61c95..60fbf632 100644 --- a/src/Schema/Column/MediumText.php +++ b/src/Schema/Column/MediumText.php @@ -6,6 +6,7 @@ class MediumText extends CharacterColumn { use TextTrait; + use MySqlDefaultTrait; /** * @var string diff --git a/src/Schema/Column/MySqlDefaultTrait.php b/src/Schema/Column/MySqlDefaultTrait.php index 6902f65f..75071c01 100644 --- a/src/Schema/Column/MySqlDefaultTrait.php +++ b/src/Schema/Column/MySqlDefaultTrait.php @@ -13,10 +13,14 @@ trait MySqlDefaultTrait */ protected $has_mysql_default = false; - public function setDefault($mysql_default) : void + /** + * @return static + */ + public function setDefault($mysql_default) { $this->mysql_default = $mysql_default; $this->has_mysql_default = true; + return $this; } public function hasDefault() : bool diff --git a/src/Schema/Column/NullColumn.php b/src/Schema/Column/NullColumn.php index 4ce8bdbd..cb787982 100644 --- a/src/Schema/Column/NullColumn.php +++ b/src/Schema/Column/NullColumn.php @@ -6,6 +6,8 @@ */ class NullColumn extends \Vimeo\MysqlEngine\Schema\Column { + use EmptyConstructorTrait; + public function getPhpType() : string { return 'null'; diff --git a/src/Schema/Column/NumberColumn.php b/src/Schema/Column/NumberColumn.php index 5ddf5288..c4912477 100644 --- a/src/Schema/Column/NumberColumn.php +++ b/src/Schema/Column/NumberColumn.php @@ -13,5 +13,6 @@ public function getMaxValue(); */ public function getMinValue(); - public function setDefault($mysql_default) : void; + /** @return static */ + public function setDefault($mysql_default); } diff --git a/src/Schema/Column/Set.php b/src/Schema/Column/Set.php index 311bc397..ec5c64ce 100644 --- a/src/Schema/Column/Set.php +++ b/src/Schema/Column/Set.php @@ -4,31 +4,5 @@ class Set extends \Vimeo\MysqlEngine\Schema\Column implements Defaultable { use MySqlDefaultTrait; - - /** - * @var string[] - */ - protected $options = []; - - /** - * @param string[] $options - */ - public function __construct(array $options) - { - $this->options = $options; - } - - /** - * @return string[] - * @psalm-return array - */ - public function getOptions() : array - { - return $this->options; - } - - public function getPhpType() : string - { - return 'string'; - } + use HasOptionsTrait; } diff --git a/src/Schema/Column/Text.php b/src/Schema/Column/Text.php index f5f8e634..0e101085 100644 --- a/src/Schema/Column/Text.php +++ b/src/Schema/Column/Text.php @@ -6,6 +6,7 @@ class Text extends CharacterColumn implements StringColumn { use TextTrait; + use MySqlDefaultTrait; public function __construct(?string $character_set = null, ?string $collation = null) { diff --git a/src/Schema/Column/TextTrait.php b/src/Schema/Column/TextTrait.php index ff4173db..a9c0635e 100644 --- a/src/Schema/Column/TextTrait.php +++ b/src/Schema/Column/TextTrait.php @@ -5,4 +5,16 @@ trait TextTrait { + public function getPhpCode() : string + { + $default = $this->getDefault() !== null ? '\'' . $this->getDefault() . '\'' : 'null'; + + return '(new \\' . static::class . '(' + . ($this->character_set !== null && $this->collation !== null + ? ', \'' . $this->character_set . '\'' . ', \'' . $this->collation . '\'' + : '') + . '))' + . ($this->hasDefault() ? '->setDefault(' . $default . ')' : '') + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/Time.php b/src/Schema/Column/Time.php index d6760018..a6d39d26 100644 --- a/src/Schema/Column/Time.php +++ b/src/Schema/Column/Time.php @@ -4,6 +4,7 @@ class Time extends \Vimeo\MysqlEngine\Schema\Column implements ChronologicalColumn, Defaultable { use MySqlDefaultTrait; + use EmptyConstructorTrait; public function getPhpType() : string { diff --git a/src/Schema/Column/Timestamp.php b/src/Schema/Column/Timestamp.php index 788f174c..07e93018 100644 --- a/src/Schema/Column/Timestamp.php +++ b/src/Schema/Column/Timestamp.php @@ -4,6 +4,7 @@ class Timestamp extends \Vimeo\MysqlEngine\Schema\Column implements ChronologicalColumn, Defaultable { use MySqlDefaultTrait; + use EmptyConstructorTrait; public function getPhpType() : string { diff --git a/src/Schema/Column/TinyBlob.php b/src/Schema/Column/TinyBlob.php index 554b5e33..6794f27e 100644 --- a/src/Schema/Column/TinyBlob.php +++ b/src/Schema/Column/TinyBlob.php @@ -9,4 +9,13 @@ public function __construct() { parent::__construct(255, 'binary', '_bin'); } + + public function getPhpCode() : string + { + $default = $this->getDefault() !== null ? '\'' . $this->getDefault() . '\'' : 'null'; + + return '(new \\' . static::class . '())' + . ($this->hasDefault() ? '->setDefault(' . $default . ')' : '') + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/TinyText.php b/src/Schema/Column/TinyText.php index e850d4f1..25abc220 100644 --- a/src/Schema/Column/TinyText.php +++ b/src/Schema/Column/TinyText.php @@ -6,6 +6,7 @@ class TinyText extends CharacterColumn implements StringColumn { use TextTrait; + use MySqlDefaultTrait; public function __construct(?string $character_set = null, ?string $collation = null) { diff --git a/src/Schema/Column/Varbinary.php b/src/Schema/Column/Varbinary.php index 21113fc3..e889a856 100644 --- a/src/Schema/Column/Varbinary.php +++ b/src/Schema/Column/Varbinary.php @@ -9,4 +9,12 @@ public function __construct(int $max_string_length) { parent::__construct($max_string_length, 'binary', '_bin'); } + + public function getPhpCode() : string + { + return '(new \\' . static::class . '(' + . $this->max_string_length + . '))' + . $this->getNullablePhp(); + } } diff --git a/src/Schema/Column/Varchar.php b/src/Schema/Column/Varchar.php index 9c421ed8..1e22aece 100644 --- a/src/Schema/Column/Varchar.php +++ b/src/Schema/Column/Varchar.php @@ -7,9 +7,4 @@ class Varchar extends CharacterColumn implements StringColumn, Defaultable { use StringColumnTrait; use MySqlDefaultTrait; - - public function __construct(int $max_string_length, ?string $character_set = null, ?string $collation = null) - { - parent::__construct($max_string_length, $character_set, $collation); - } } diff --git a/src/Schema/Column/Year.php b/src/Schema/Column/Year.php index 6adbeda3..de263fd8 100644 --- a/src/Schema/Column/Year.php +++ b/src/Schema/Column/Year.php @@ -4,6 +4,7 @@ class Year extends \Vimeo\MysqlEngine\Schema\Column implements ChronologicalColumn, Defaultable { use MySqlDefaultTrait; + use EmptyConstructorTrait; public function getPhpType() : string { diff --git a/src/Schema/TableDefinition.php b/src/Schema/TableDefinition.php index 25c157ff..9f0cc033 100644 --- a/src/Schema/TableDefinition.php +++ b/src/Schema/TableDefinition.php @@ -44,6 +44,7 @@ class TableDefinition public $autoIncrementOffsets = []; /** + * @param array $columns * @param array $indexes */ public function __construct( @@ -65,4 +66,34 @@ public function __construct( $this->indexes = $indexes; $this->autoIncrementOffsets = $autoIncrementOffsets; } + + public function getPhpCode() : string + { + $columns = []; + + foreach ($this->columns as $name => $column) { + $columns[] = '\'' . $name . '\' => ' . $column->getPhpCode(); + } + + $indexes = []; + + foreach ($this->indexes as $name => $index) { + $indexes[] = '\'' . $name . '\' => new \\' + . \get_class($index) . '(\'' . $index->type + . '\', [\'' . \implode('\', \'', $index->columns) . '\'])'; + } + + return 'new \\' . self::class . '(' + . '\'' . $this->name . '\'' + . ', \'' . $this->databaseName . '\'' + . ', [' . \implode(', ', $columns) . ']' + . ', \'' . $this->defaultCharacterSet . '\'' + . ', \'' . $this->defaultCollation . '\'' + . ', [' + . ($this->primaryKeyColumns ? '\'' . \implode('\', \'', $this->primaryKeyColumns) . '\'' : '') + . ']' + . ', [' . \implode(', ', $indexes) . ']' + . ', ' . \var_export($this->autoIncrementOffsets, true) + . ')'; + } } diff --git a/tests/CreateTableParseTest.php b/tests/CreateTableParseTest.php new file mode 100644 index 00000000..643538fd --- /dev/null +++ b/tests/CreateTableParseTest.php @@ -0,0 +1,32 @@ +parse($query); + + $this->assertCount(4, $create_queries); + + foreach ($create_queries as $create_query) { + $table = \Vimeo\MysqlEngine\Processor\CreateProcessor::makeTableDefinition( + $create_query, + 'foo' + ); + + $new_table_php_code = $table->getPhpCode(); + + $new_table = eval('return ' . $new_table_php_code . ';'); + + $this->assertSame(\var_export($table, true), \var_export($new_table, true)); + } + } +} diff --git a/tests/EndToEndTest.php b/tests/EndToEndTest.php index 47d54466..aa045107 100644 --- a/tests/EndToEndTest.php +++ b/tests/EndToEndTest.php @@ -148,6 +148,7 @@ public function testAliasWithType() $pdo = self::getConnectionToFullDB(false); $query = $pdo->prepare("SELECT SUM(`a`) FROM (SELECT `id` as `a` FROM `video_game_characters`) `foo`"); + $query->bindValue(':id', 14); $query->execute(); diff --git a/tests/ShowIndexParseTest.php b/tests/ShowIndexParseTest.php index 9546e17a..d4ad3a6f 100644 --- a/tests/ShowIndexParseTest.php +++ b/tests/ShowIndexParseTest.php @@ -59,5 +59,4 @@ public function testWhereParse() $this->assertInstanceOf(ShowIndexQuery::class, $show_query); $this->assertSame('foo', $show_query->table); } - }