Skip to content

Commit

Permalink
Add support for generating indexes (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonmccreary authored Aug 28, 2020
1 parent 62edefe commit a0d0655
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 6 deletions.
5 changes: 4 additions & 1 deletion src/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ public function execute(Blueprint $blueprint, Filesystem $files, string $draft,
$cache = $blueprint->parse($files->get('.blueprint'));
}

$tokens = $blueprint->parse($files->get($draft));
$contents = $files->get($draft);
$using_indexes = preg_match('/^\s+indexes:\R/m', $contents) !== 1;

$tokens = $blueprint->parse($contents, $using_indexes);
$tokens['cache'] = $cache['models'] ?? [];
$registry = $blueprint->analyze($tokens);

Expand Down
12 changes: 11 additions & 1 deletion src/Generators/MigrationGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,16 @@ protected function buildDefinition(Model $model)
$definition .= self::INDENT.sprintf('$table->string(\'%s\');', Str::lower($model->morphTo().'_type')).PHP_EOL;
}

foreach ($model->indexes() as $index) {
$index_definition = self::INDENT;
$index_definition .= '$table->'.$index->type();
if (count($index->columns()) > 1) {
$index_definition .= "(['".implode("', '", $index->columns())."']);".PHP_EOL;
} else {
$index_definition .= "('{$index->columns()[0]}');".PHP_EOL;
}
$definition .= $index_definition;
}
if ($model->usesTimestamps()) {
$definition .= self::INDENT.'$table->'.$model->timestampsDataType().'();'.PHP_EOL;
}
Expand Down Expand Up @@ -292,7 +302,7 @@ protected function getTablePath($tableName, Carbon $timestamp, $overwrite = fals
{
$dir = 'database/migrations/';
$name = '_create_'.$tableName.'_table.php';

$file = $overwrite ? collect($this->files->files($dir))->first(function ($file) use ($tableName) {
return str_contains($file, $tableName);
}) : false;
Expand Down
8 changes: 8 additions & 0 deletions src/Lexers/ModelLexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Blueprint\Contracts\Lexer;
use Blueprint\Models\Column;
use Blueprint\Models\Index;
use Blueprint\Models\Model;
use Illuminate\Support\Str;

Expand Down Expand Up @@ -166,6 +167,13 @@ private function buildModel(string $name, array $columns)
unset($columns['relationships']);
}

if (isset($columns['indexes'])) {
foreach ($columns['indexes'] as $index) {
$model->addIndex(new Index(key($index), array_map('trim', explode(',', current($index)))));
}
unset($columns['indexes']);
}

if (!isset($columns['id']) && $model->usesPrimaryKey()) {
$column = $this->buildColumn('id', 'id');
$model->addColumn($column);
Expand Down
25 changes: 25 additions & 0 deletions src/Models/Index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Blueprint\Models;

class Index
{
private $type;
private $columns;

public function __construct(string $type, array $columns = [])
{
$this->type = $type;
$this->columns = $columns;
}

public function type()
{
return $this->type;
}

public function columns()
{
return $this->columns;
}
}
11 changes: 11 additions & 0 deletions src/Models/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Model
private $columns = [];
private $relationships = [];
private $pivotTables = [];
private $indexes = [];

/**
* @param $name
Expand Down Expand Up @@ -159,6 +160,16 @@ public function addPivotTable(string $reference)
$this->pivotTables[] = $segments;
}

public function indexes(): array
{
return $this->indexes;
}

public function addIndex(Index $index)
{
$this->indexes[] = $index;
}

public function pivotTables(): array
{
return $this->pivotTables;
Expand Down
5 changes: 3 additions & 2 deletions tests/Feature/Generator/MigrationGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public function output_writes_migration_for_model_tree($definition, $path, $migr
$this->files->expects('put')
->with($timestamp_path, $this->fixture($migration));

$tokens = $this->blueprint->parse($this->fixture($definition));
$tokens = $this->blueprint->parse($this->fixture($definition), $definition !== 'drafts/indexes.yaml');
$tree = $this->blueprint->analyze($tokens);

$this->assertEquals(['created' => [$timestamp_path]], $this->subject->output($tree));
Expand Down Expand Up @@ -103,7 +103,7 @@ public function output_updates_migration_for_model_tree($definition, $path, $mig
$this->files->expects('put')
->with($yesterday_path, $this->fixture($migration));

$tokens = $this->blueprint->parse($this->fixture($definition));
$tokens = $this->blueprint->parse($this->fixture($definition), $definition !== 'drafts/indexes.yaml');
$tree = $this->blueprint->analyze($tokens);

$this->assertEquals(['updated' => [$yesterday_path]], $this->subject->output($tree, true));
Expand Down Expand Up @@ -746,6 +746,7 @@ public function modelTreeDataProvider()
['drafts/soft-deletes.yaml', 'database/migrations/timestamp_create_comments_table.php', 'migrations/soft-deletes.php'],
['drafts/with-timezones.yaml', 'database/migrations/timestamp_create_comments_table.php', 'migrations/with-timezones.php'],
['drafts/relationships.yaml', 'database/migrations/timestamp_create_comments_table.php', 'migrations/relationships.php'],
['drafts/indexes.yaml', 'database/migrations/timestamp_create_posts_table.php', 'migrations/indexes.php'],
['drafts/unconventional.yaml', 'database/migrations/timestamp_create_teams_table.php', 'migrations/unconventional.php'],
['drafts/optimize.yaml', 'database/migrations/timestamp_create_optimizes_table.php', 'migrations/optimize.php'],
['drafts/model-key-constraints.yaml', 'database/migrations/timestamp_create_orders_table.php', 'migrations/model-key-constraints.php'],
Expand Down
56 changes: 54 additions & 2 deletions tests/Unit/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function execute_builds_draft_content()

$blueprint = \Mockery::mock(Blueprint::class);
$blueprint->expects('parse')
->with($draft)
->with($draft, true)
->andReturn($tokens);
$blueprint->expects('analyze')
->with($tokens + ['cache' => []])
Expand Down Expand Up @@ -72,7 +72,7 @@ public function execute_uses_cache_and_remembers_models()

$blueprint = \Mockery::mock(Blueprint::class);
$blueprint->expects('parse')
->with($draft)
->with($draft, true)
->andReturn($tokens);
$blueprint->expects('parse')
->with('cached blueprint content')
Expand Down Expand Up @@ -108,4 +108,56 @@ public function execute_uses_cache_and_remembers_models()

$this->assertSame($generated, $actual);
}

/**
* @test
*/
public function execute_calls_builder_without_stripping_dashes_for_draft_file_with_indexes_defined()
{
$draft = 'models:';
$draft .= PHP_EOL . ' Post:';
$draft .= PHP_EOL . ' indexes:';
$draft .= PHP_EOL . ' - index: author_id';
$draft .= PHP_EOL . ' - index: author_id, published_at';

$tokens = [
'models' => [1, 2, 3]
];
$registry = new Tree(['registry']);
$only = [];
$skip = [];
$generated = ['created' => [1, 2], 'updated' => [3]];

$blueprint = \Mockery::mock(Blueprint::class);
$blueprint->expects('parse')
->with($draft, false)
->andReturn($tokens);
$blueprint->expects('analyze')
->with($tokens + ['cache' => []])
->andReturn($registry);
$blueprint->expects('generate')
->with($registry, $only, $skip, false)
->andReturn($generated);
$blueprint->expects('dump')
->with([
'created' => [1, 2],
'updated' => [3],
'models' => [1, 2, 3]
])
->andReturn('cacheable blueprint content');

$file = \Mockery::mock(Filesystem::class);
$file->expects('get')
->with('draft.yaml')
->andReturn($draft);
$file->expects('exists')
->with('.blueprint')
->andReturnFalse();
$file->expects('put')
->with('.blueprint', 'cacheable blueprint content');

$actual = (new Builder)->execute($blueprint, $file, 'draft.yaml');

$this->assertSame($generated, $actual);
}
}
16 changes: 16 additions & 0 deletions tests/fixtures/drafts/indexes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
models:
Post:
id: unsignedInteger
title: string
parent_post_id: id
author_id: id
published_at: timestamp nullable
word_count: integer unsigned
location: geometry
indexes:
- primary: id
- index: author_id
- index: author_id, published_at
- unique: title
- unique: title, parent_post_id
- spatialIndex: location
43 changes: 43 additions & 0 deletions tests/fixtures/migrations/indexes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->unsignedInteger('id');
$table->string('title');
$table->unsignedBigInteger('parent_post_id');
$table->unsignedBigInteger('author_id');
$table->timestamp('published_at')->nullable();
$table->unsignedInteger('word_count');
$table->geometry('location');
$table->primary('id');
$table->index('author_id');
$table->index(['author_id', 'published_at']);
$table->unique('title');
$table->unique(['title', 'parent_post_id']);
$table->spatialIndex('location');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}

0 comments on commit a0d0655

Please sign in to comment.