diff --git a/README.md b/README.md index 3e41703..3a739e0 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ php composer.phar require umbrellio/laravel-pg-extensions ## Features - [Extended `Schema::create()`](#extended-table-creation) + - [Extended `Schema` with GIST/GIN indexes](#create-gist/gin-indexes) - [Working with unique indexes](#extended-unique-indexes-creation) - [Working with partitions](#partitions) - [Check existing index before manipulation](#check-existing-index) @@ -29,6 +30,15 @@ Schema::create('table', function (Blueprint $table) { }); ``` +### Create gist/gin indexes + +```php +Schema::create('table', function (Blueprint $table) { + $table->gist(['column1', 'column2']); + $table->gin('column1'); +}); +``` + ### Extended unique indexes creation Example: diff --git a/ecs.yml b/ecs.yml index 69f949a..768e555 100644 --- a/ecs.yml +++ b/ecs.yml @@ -10,3 +10,7 @@ parameters: cache_directory: .ecs_cache exclude_files: - vendor/* + + skip: + Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff: + - src/Schema/Blueprint.php diff --git a/src/.meta.php b/src/.meta.php index 32053d7..1fdb06a 100644 --- a/src/.meta.php +++ b/src/.meta.php @@ -13,6 +13,8 @@ * @method LikeDefinition like(string $table) * @method Fluent ifNotExists() * @method UniqueDefinition uniquePartial($columns, ?string $index = null, ?string $algorithm = null) + * @method Fluent gin($columns, ?string $name = null) + * @method Fluent gist($columns, ?string $name = null) */ class Blueprint { diff --git a/src/Schema/Blueprint.php b/src/Schema/Blueprint.php index 9611832..f2d37ed 100644 --- a/src/Schema/Blueprint.php +++ b/src/Schema/Blueprint.php @@ -57,6 +57,26 @@ public function uniquePartial($columns, ?string $index = null, ?string $algorith ); } + /** + * Specify an index for the table. + * @param string|array $columns + * @return Fluent + */ + public function gin($columns, ?string $name = null) + { + return $this->indexCommand('gin', $columns, $name); + } + + /** + * Specify a gist index for the table. + * @param string|array $columns + * @return Fluent + */ + public function gist($columns, ?string $name = null) + { + return $this->indexCommand('gist', $columns, $name); + } + public function hasIndex($index, bool $unique = false): bool { if (is_array($index)) { @@ -66,6 +86,28 @@ public function hasIndex($index, bool $unique = false): bool return array_key_exists($index, $this->getSchemaManager()->listTableIndexes($this->getTable())); } + protected function addFluentIndexes(): void + { + foreach ($this->columns as $column) { + foreach (['primary', 'unique', 'index', 'gin', 'gist', 'spatialIndex'] as $index) { + // If the index has been specified on the given column, but is simply + // equal to "true" (boolean), no name has been specified for this + // index, so we will simply call the index methods without one. + if ($column->{$index} === true) { + $this->{$index}($column->name); + continue 2; + } + // If the index has been specified on the column and it is something + // other than boolean true, we will assume a name was provided on + // the index specification, and pass in the name to the method. + elseif (isset($column->{$index})) { + $this->{$index}($column->name, $column->{$index}); + continue 2; + } + } + } + } + protected function getSchemaManager() { return Schema::getConnection()->getDoctrineSchemaManager(); diff --git a/src/Schema/Grammars/PostgresGrammar.php b/src/Schema/Grammars/PostgresGrammar.php index 473e4b8..088a14e 100644 --- a/src/Schema/Grammars/PostgresGrammar.php +++ b/src/Schema/Grammars/PostgresGrammar.php @@ -49,4 +49,25 @@ public function compileUniquePartial(Blueprint $blueprint, UniquePartialBuilder } return $this->compileUnique($blueprint, $command); } + + public function compileGin(Blueprint $blueprint, Fluent $command): string + { + return sprintf( + 'CREATE INDEX %s ON %s USING GIN(%s)', + $command->index, + $this->wrapTable($blueprint), + $this->columnize($command->columns) + ); + } + + + public function compileGist(Blueprint $blueprint, Fluent $command): string + { + return sprintf( + 'CREATE INDEX %s ON %s USING GIST(%s)', + $command->index, + $this->wrapTable($blueprint), + $this->columnize($command->columns) + ); + } } diff --git a/tests/Functional/UniqueIndexTest.php b/tests/Functional/UniqueIndexTest.php index 9a0dbd8..8de9265 100644 --- a/tests/Functional/UniqueIndexTest.php +++ b/tests/Functional/UniqueIndexTest.php @@ -36,6 +36,21 @@ public function createPartialUniqueWithNull($expected, $callback): void $this->assertSame($this->getDummyIndex() . $expected, $indexes->indexdef); } + /** @test */ + public function createSpecifyIndex(): void + { + Schema::create('test_table', function (Blueprint $table) { + $table->string('name')->index('specify_index_name'); + }); + + $this->assertTrue(Schema::hasTable('test_table')); + + $this->assertSame( + 'CREATE INDEX specify_index_name ON public.test_table USING btree (name)', + $this->getIndexByName('specify_index_name')->indexdef + ); + } + public function provideIndexes(): Generator { yield ['', function (Blueprint $table) { diff --git a/tests/Unit/Schema/Grammars/GrammarTest.php b/tests/Unit/Schema/Grammars/GrammarTest.php new file mode 100644 index 0000000..8ba667e --- /dev/null +++ b/tests/Unit/Schema/Grammars/GrammarTest.php @@ -0,0 +1,49 @@ +gin('foo'); + $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); + $this->assertCount(1, $statements); + $this->assertStringContainsString('CREATE INDEX', $statements[0]); + $this->assertStringContainsString('GIN("foo")', $statements[0]); + } + + /** @test */ + public function addingGistIndex() + { + $blueprint = new Blueprint('test'); + $blueprint->gist('foo'); + $statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()); + $this->assertCount(1, $statements); + $this->assertStringContainsString('CREATE INDEX', $statements[0]); + $this->assertStringContainsString('GIST("foo")', $statements[0]); + } + + /** + * @return PostgresConnection + */ + protected function getConnection() + { + return Mockery::mock(PostgresConnection::class); + } + + protected function getGrammar() + { + return new PostgresGrammar(); + } +} diff --git a/tests/Unit/Schema/IndexTest.php b/tests/Unit/Schema/IndexTest.php new file mode 100644 index 0000000..1b05de6 --- /dev/null +++ b/tests/Unit/Schema/IndexTest.php @@ -0,0 +1,42 @@ +blueprint = Mockery::mock(Blueprint::class) + ->makePartial() + ->shouldAllowMockingProtectedMethods(); + } + + /** @test */ + public function ginIndex() + { + $this->blueprint + ->shouldReceive('indexCommand') + ->with('gin', 'col', 'myName'); + $this->blueprint->gin('col', 'myName'); + } + + /** @test */ + public function gistIndex() + { + $this->blueprint + ->shouldReceive('indexCommand') + ->with('gist', 'col', 'myName'); + $this->blueprint->gist('col', 'myName'); + } +}