From 0865c8e872b88716612428c5f7222cbacf03c918 Mon Sep 17 00:00:00 2001 From: Nathan E Date: Wed, 26 Aug 2020 18:00:05 -0400 Subject: [PATCH 1/6] chore: add test fixtures --- .../migration-with-composite-indexes.yaml | 8 ++++ .../migration-with-composite-indexes.php | 37 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/fixtures/drafts/migration-with-composite-indexes.yaml create mode 100644 tests/fixtures/migrations/migration-with-composite-indexes.php diff --git a/tests/fixtures/drafts/migration-with-composite-indexes.yaml b/tests/fixtures/drafts/migration-with-composite-indexes.yaml new file mode 100644 index 00000000..62a0a172 --- /dev/null +++ b/tests/fixtures/drafts/migration-with-composite-indexes.yaml @@ -0,0 +1,8 @@ +models: + Participation: + project_id: bigInteger + user_id: bigInteger + name: string + _unique: project_id,user_id + _index: project_id,user_id + _primary: project_id,user_id diff --git a/tests/fixtures/migrations/migration-with-composite-indexes.php b/tests/fixtures/migrations/migration-with-composite-indexes.php new file mode 100644 index 00000000..8685a1fb --- /dev/null +++ b/tests/fixtures/migrations/migration-with-composite-indexes.php @@ -0,0 +1,37 @@ +id(); + $table->bigInteger('project_id'); + $table->bigInteger('user_id'); + $table->string('name'); + $table->unique(['project_id', 'user_id']); + $table->index(['project_id', 'user_id']); + $table->primary(['project_id', 'user_id']); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('participations'); + } +} From e8c7f7bd01c62c31b869daa5f81b68a17435ca45 Mon Sep 17 00:00:00 2001 From: Nathan E Date: Wed, 26 Aug 2020 18:01:24 -0400 Subject: [PATCH 2/6] test: update migration generator test --- tests/Feature/Generator/MigrationGeneratorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Feature/Generator/MigrationGeneratorTest.php b/tests/Feature/Generator/MigrationGeneratorTest.php index 7c9cf5f8..7334df24 100644 --- a/tests/Feature/Generator/MigrationGeneratorTest.php +++ b/tests/Feature/Generator/MigrationGeneratorTest.php @@ -755,6 +755,7 @@ public function modelTreeDataProvider() ['drafts/resource-statements.yaml', 'database/migrations/timestamp_create_users_table.php', 'migrations/resource-statements.php'], ['drafts/enum-options.yaml', 'database/migrations/timestamp_create_messages_table.php', 'migrations/enum-options.php'], ['drafts/columns-with-comments.yaml', 'database/migrations/timestamp_create_professions_table.php', 'migrations/columns-with-comments.php'], + ['drafts/migration-with-composite-indexes.yaml', 'database/migrations/timestamp_create_participations_table.php', 'migrations/migration-with-composite-indexes.php'], ]; } } From 2a08800128b1b1c2159e2b65f92d7ac3206bea46 Mon Sep 17 00:00:00 2001 From: Nathan E Date: Wed, 26 Aug 2020 18:01:46 -0400 Subject: [PATCH 3/6] feat: generate composite indexes for migrations --- src/Generators/MigrationGenerator.php | 10 +++++++++- src/Lexers/ModelLexer.php | 13 ++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Generators/MigrationGenerator.php b/src/Generators/MigrationGenerator.php index f93ac779..851b8a94 100644 --- a/src/Generators/MigrationGenerator.php +++ b/src/Generators/MigrationGenerator.php @@ -11,6 +11,12 @@ class MigrationGenerator implements Generator { + const COMPOSITE_INDEXES = [ + '_index', + '_primary', + '_unique', + ]; + const INDENT = ' '; const NULLABLE_TYPES = [ @@ -129,11 +135,13 @@ protected function buildDefinition(Model $model) $column_definition .= '$table->id('; } elseif ($dataType === 'rememberToken') { $column_definition .= '$table->rememberToken('; + } elseif (in_array(mb_strtolower($column->name()), self::COMPOSITE_INDEXES)) { + $column_definition .= '$table->'.$dataType."(['".implode("', '", $column->attributes())."']"; } else { $column_definition .= '$table->'.$dataType."('{$column->name()}'"; } - if (! empty($column->attributes()) && ! in_array($column->dataType(), ['id', 'uuid'])) { + if (! empty($column->attributes()) && ! in_array($column->dataType(), ['id', 'uuid']) && ! in_array($column->name(), self::COMPOSITE_INDEXES)) { $column_definition .= ', '; if (in_array($column->dataType(), ['set', 'enum'])) { $column_definition .= json_encode($column->attributes()); diff --git a/src/Lexers/ModelLexer.php b/src/Lexers/ModelLexer.php index c1302fcc..4cd25580 100644 --- a/src/Lexers/ModelLexer.php +++ b/src/Lexers/ModelLexer.php @@ -98,6 +98,12 @@ class ModelLexer implements Lexer 'comment' => 'comment', ]; + private static $compositeIndexes = [ + '_index' => 'index', + '_primary' => 'primary', + '_unique' => 'unique', + ]; + public function analyze(array $tokens): array { $registry = [ @@ -217,7 +223,12 @@ private function buildColumn(string $name, string $definition) if (isset($parts[1])) { $attributes = [$parts[1]]; } - } elseif (isset(self::$dataTypes[strtolower($value)])) { + } + if (isset(self::$compositeIndexes[strtolower($name)])) { + $data_type = self::$compositeIndexes[strtolower($name)]; + $attributes = explode(',', $value); + } + if (isset(self::$dataTypes[strtolower($value)])) { $attributes = $parts[1] ?? null; $data_type = self::$dataTypes[strtolower($value)]; if (!empty($attributes)) { From 5e67b5a43c54b24408deba9e34cbb333405e659f Mon Sep 17 00:00:00 2001 From: Nathan E Date: Wed, 26 Aug 2020 18:55:03 -0400 Subject: [PATCH 4/6] chore: update test fixtures --- tests/fixtures/drafts/migration-with-composite-indexes.yaml | 2 +- tests/fixtures/migrations/migration-with-composite-indexes.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fixtures/drafts/migration-with-composite-indexes.yaml b/tests/fixtures/drafts/migration-with-composite-indexes.yaml index 62a0a172..94c5c4b9 100644 --- a/tests/fixtures/drafts/migration-with-composite-indexes.yaml +++ b/tests/fixtures/drafts/migration-with-composite-indexes.yaml @@ -3,6 +3,6 @@ models: project_id: bigInteger user_id: bigInteger name: string - _unique: project_id,user_id + _unique: project_id,user_id team_id,project_id _index: project_id,user_id _primary: project_id,user_id diff --git a/tests/fixtures/migrations/migration-with-composite-indexes.php b/tests/fixtures/migrations/migration-with-composite-indexes.php index 8685a1fb..1cece6da 100644 --- a/tests/fixtures/migrations/migration-with-composite-indexes.php +++ b/tests/fixtures/migrations/migration-with-composite-indexes.php @@ -19,6 +19,7 @@ public function up() $table->bigInteger('user_id'); $table->string('name'); $table->unique(['project_id', 'user_id']); + $table->unique(['team_id', 'project_id']); $table->index(['project_id', 'user_id']); $table->primary(['project_id', 'user_id']); $table->timestamps(); From 503c168e7231f2d7ad11285d4ceebfa15cf6ae3e Mon Sep 17 00:00:00 2001 From: Nathan E Date: Wed, 26 Aug 2020 19:11:58 -0400 Subject: [PATCH 5/6] support multiple definitions for the same index type --- src/Generators/MigrationGenerator.php | 14 +++++++++++--- src/Lexers/ModelLexer.php | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Generators/MigrationGenerator.php b/src/Generators/MigrationGenerator.php index 851b8a94..72781b6b 100644 --- a/src/Generators/MigrationGenerator.php +++ b/src/Generators/MigrationGenerator.php @@ -136,7 +136,11 @@ protected function buildDefinition(Model $model) } elseif ($dataType === 'rememberToken') { $column_definition .= '$table->rememberToken('; } elseif (in_array(mb_strtolower($column->name()), self::COMPOSITE_INDEXES)) { - $column_definition .= '$table->'.$dataType."(['".implode("', '", $column->attributes())."']"; + $column_definition = []; + foreach ($column->attributes() as $attributes) { + $column_definition[] = self::INDENT.'$table->'.$dataType."(['".implode("', '", $attributes)."']);"; + } + $column_definition = implode(PHP_EOL, $column_definition).PHP_EOL; } else { $column_definition .= '$table->'.$dataType."('{$column->name()}'"; } @@ -149,7 +153,9 @@ protected function buildDefinition(Model $model) $column_definition .= implode(', ', $column->attributes()); } } - $column_definition .= ')'; + if (!in_array(mb_strtolower($column->name()), self::COMPOSITE_INDEXES)) { + $column_definition .= ')'; + } $modifiers = $column->modifiers(); @@ -191,7 +197,9 @@ protected function buildDefinition(Model $model) } } - $column_definition .= ';'.PHP_EOL; + if (!in_array(mb_strtolower($column->name()), self::COMPOSITE_INDEXES)) { + $column_definition .= ';'.PHP_EOL; + } if (! empty($foreign)) { $column_definition .= $foreign.';'.PHP_EOL; } diff --git a/src/Lexers/ModelLexer.php b/src/Lexers/ModelLexer.php index 4cd25580..f3d5b624 100644 --- a/src/Lexers/ModelLexer.php +++ b/src/Lexers/ModelLexer.php @@ -226,7 +226,10 @@ private function buildColumn(string $name, string $definition) } if (isset(self::$compositeIndexes[strtolower($name)])) { $data_type = self::$compositeIndexes[strtolower($name)]; - $attributes = explode(',', $value); + $attributes = []; + foreach (explode(' ', $definition) as $attribute) { + $attributes[] = explode(',', $attribute); + } } if (isset(self::$dataTypes[strtolower($value)])) { $attributes = $parts[1] ?? null; From 56cc0cfd0696ab3a3ef67bfed8e3d79705d68172 Mon Sep 17 00:00:00 2001 From: Nathan E Date: Wed, 26 Aug 2020 20:06:31 -0400 Subject: [PATCH 6/6] refactor: remove spaces before and after a comma - supports `team_id,project_id` and `team_id, project_id` format. --- src/Blueprint.php | 2 ++ tests/Feature/BlueprintTest.php | 8 ++++---- .../fixtures/drafts/migration-with-composite-indexes.yaml | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Blueprint.php b/src/Blueprint.php index c5383017..f1c37260 100644 --- a/src/Blueprint.php +++ b/src/Blueprint.php @@ -37,6 +37,8 @@ public function parse($content, $strip_dashes = true) $content = preg_replace('/^(\s*)-\s*/m', '\1', $content); } + $content = preg_replace('/\s*,\s*/', ',', $content); + $content = preg_replace_callback('/^(\s+)(id|timestamps(Tz)?|softDeletes(Tz)?)$/mi', function ($matches) { return $matches[1].strtolower($matches[2]).': '.$matches[2]; }, $content); diff --git a/tests/Feature/BlueprintTest.php b/tests/Feature/BlueprintTest.php index 74fa2b3d..11e1848b 100644 --- a/tests/Feature/BlueprintTest.php +++ b/tests/Feature/BlueprintTest.php @@ -64,7 +64,7 @@ public function it_parses_seeders() 'user_id' => 'id', ], ], - 'seeders' => 'Post, Comment', + 'seeders' => 'Post,Comment', ], $this->subject->parse($blueprint)); } @@ -219,7 +219,7 @@ public function it_parses_the_readme_example() 'render' => 'post.index with:posts', ], 'store' => [ - 'validate' => 'title, content, author_id', + 'validate' => 'title,content,author_id', 'save' => 'post', 'send' => 'ReviewPost to:post.author.email with:post', 'dispatch' => 'SyncMedia with:post', @@ -262,7 +262,7 @@ public function it_parses_the_readme_example_with_different_platform_eols() 'render' => 'post.index with:posts', ], 'store' => [ - 'validate' => 'title, content, author_id', + 'validate' => 'title,content,author_id', 'save' => 'post', 'send' => 'ReviewPost to:post.author.email with:post', 'dispatch' => 'SyncMedia with:post', @@ -299,7 +299,7 @@ public function it_parses_yaml_with_dashed_syntax() 'render' => 'post.index with:posts', ], 'store' => [ - 'validate' => 'title, content', + 'validate' => 'title,content', 'save' => 'post', 'redirect' => 'post.index', ], diff --git a/tests/fixtures/drafts/migration-with-composite-indexes.yaml b/tests/fixtures/drafts/migration-with-composite-indexes.yaml index 94c5c4b9..c86e0ab2 100644 --- a/tests/fixtures/drafts/migration-with-composite-indexes.yaml +++ b/tests/fixtures/drafts/migration-with-composite-indexes.yaml @@ -3,6 +3,6 @@ models: project_id: bigInteger user_id: bigInteger name: string - _unique: project_id,user_id team_id,project_id - _index: project_id,user_id - _primary: project_id,user_id + _unique: project_id, user_id team_id,project_id + _index: project_id, user_id + _primary: project_id, user_id