Skip to content

Commit

Permalink
Add support gist/gin indexes (#14)
Browse files Browse the repository at this point in the history
Add support gist/gin indexes
  • Loading branch information
pvsaintpe authored and lazeevv committed Jul 15, 2019
1 parent 3de6711 commit d4e311b
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions ecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ parameters:
cache_directory: .ecs_cache
exclude_files:
- vendor/*

skip:
Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff:
- src/Schema/Blueprint.php
2 changes: 2 additions & 0 deletions src/.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
42 changes: 42 additions & 0 deletions src/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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();
Expand Down
21 changes: 21 additions & 0 deletions src/Schema/Grammars/PostgresGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
);
}
}
15 changes: 15 additions & 0 deletions tests/Functional/UniqueIndexTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
49 changes: 49 additions & 0 deletions tests/Unit/Schema/Grammars/GrammarTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Tests\Unit\Schema\Grammars;

use Mockery;
use Umbrellio\Postgres\PostgresConnection;
use Umbrellio\Postgres\Schema\Blueprint;
use Umbrellio\Postgres\Schema\Grammars\PostgresGrammar;
use Umbrellio\Postgres\Tests\TestCase;

class GrammarTest extends TestCase
{
/** @test */
public function addingGinIndex()
{
$blueprint = new Blueprint('test');
$blueprint->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();
}
}
42 changes: 42 additions & 0 deletions tests/Unit/Schema/IndexTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Unit\Schema;

use Mockery;
use Umbrellio\Postgres\Schema\Blueprint;
use Umbrellio\Postgres\Tests\TestCase;

class IndexTest extends TestCase
{
/** @var Mockery\Mock */
protected $blueprint;

protected function setUp(): void
{
parent::setUp();

$this->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');
}
}

0 comments on commit d4e311b

Please sign in to comment.