Skip to content

Commit

Permalink
Add support views (#4)
Browse files Browse the repository at this point in the history
Adding support for creating views
  • Loading branch information
pvsaintpe authored and lazeevv committed Aug 1, 2019
1 parent 14d26b4 commit 0e7964e
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 0 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ php composer.phar require umbrellio/laravel-pg-extensions

- [Extended `Schema::create()`](#extended-table-creation)
- [Extended `Schema` with GIST/GIN indexes](#create-gist/gin-indexes)
- [Extended `Schema` for views](#create-views)
- [Working with unique indexes](#extended-unique-indexes-creation)
- [Working with partitions](#partitions)
- [Check existing index before manipulation](#check-existing-index)
Expand All @@ -39,6 +40,22 @@ Schema::create('table', function (Blueprint $table) {
});
```

### Create views

Example:
```php
// Facade methods:
Schema::createView('active_users', "SELECT * FROM users WHERE active = 1");
Schema::dropView('active_users')

// Schema methods:
Schema::create('users', function (Blueprint $table) {
$table
->createView('active_users', , "SELECT * FROM users WHERE active = 1")
->materialize();
});
```

### Extended unique indexes creation

Example:
Expand Down
3 changes: 3 additions & 0 deletions src/.meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Support\Fluent;
use Umbrellio\Postgres\Schema\Definitions\AttachPartitionDefinition;
use Umbrellio\Postgres\Schema\Definitions\LikeDefinition;
use Umbrellio\Postgres\Schema\Definitions\ViewDefinition;
use Umbrellio\Postgres\Schema\Definitions\UniqueDefinition;

/**
Expand All @@ -13,6 +14,8 @@
* @method LikeDefinition like(string $table)
* @method Fluent ifNotExists()
* @method UniqueDefinition uniquePartial($columns, ?string $index = null, ?string $algorithm = null)
* @method ViewDefinition createView(string $view, string $select, bool $materialize = false)
* @method Fluent dropView(string $view)
* @method Fluent gin($columns, ?string $name = null)
* @method Fluent gist($columns, ?string $name = null)
* @method ColumnDefinition numeric(string $column, ?int $precision = null, ?int $scale = null):
Expand Down
14 changes: 14 additions & 0 deletions src/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Umbrellio\Postgres\Schema\Definitions\AttachPartitionDefinition;
use Umbrellio\Postgres\Schema\Definitions\LikeDefinition;
use Umbrellio\Postgres\Schema\Definitions\UniqueDefinition;
use Umbrellio\Postgres\Schema\Definitions\ViewDefinition;

class Blueprint extends BaseBlueprint
{
Expand Down Expand Up @@ -87,6 +88,19 @@ public function hasIndex($index, bool $unique = false): bool
return array_key_exists($index, $this->getSchemaManager()->listTableIndexes($this->getTable()));
}

/**
* @return ViewDefinition|Fluent
*/
public function createView(string $view, string $select, bool $materialize = false): Fluent
{
return $this->addCommand('createView', compact('view', 'select', 'materialize'));
}

public function dropView(string $view): Fluent
{
return $this->addCommand('dropView', compact('view'));
}

/**
* Almost like 'decimal' type, but can be with variable precision (by default)
*/
Expand Down
31 changes: 31 additions & 0 deletions src/Schema/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,37 @@ class Builder extends BasePostgresBuilder
{
use Macroable;

public function createView(string $view, string $select, $materialize = false): void
{
$blueprint = $this->createBlueprint($view);
$blueprint->createView($view, $select, $materialize);
$this->build($blueprint);
}

public function dropView(string $view): void
{
$blueprint = $this->createBlueprint($view);
$blueprint->dropView($view);
$this->build($blueprint);
}

public function hasView(string $view): bool
{
return count($this->connection->selectFromWriteConnection($this->grammar->compileViewExists(), [
$this->connection->getConfig()['schema'],
$this->connection->getTablePrefix() . $view,
])) > 0;
}

public function getViewDefinition($view): string
{
$results = $this->connection->selectFromWriteConnection($this->grammar->compileViewDefinition(), [
$this->connection->getConfig()['schema'],
$this->connection->getTablePrefix() . $view,
]);
return count($results) > 0 ? $results[0]->view_definition : '';
}

/**
* @param string $table
* @param Closure|null $callback
Expand Down
14 changes: 14 additions & 0 deletions src/Schema/Definitions/ViewDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Schema\Definitions;

use Illuminate\Support\Fluent;

/**
* @method Fluent materialize(bool $value = true)
*/
class ViewDefinition extends Fluent
{
}
25 changes: 25 additions & 0 deletions src/Schema/Grammars/PostgresGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,31 @@ public function compileDetachPartition(Blueprint $blueprint, Fluent $command): s
);
}

public function compileCreateView(Blueprint $blueprint, Fluent $command): string
{
$materialize = $command->get('materialize') ? 'materialized' : '';
return implode(' ', array_filter([
'create', $materialize, 'view',
$this->wrapTable($command->get('view')),
'as', $command->get('select'),
]));
}

public function compileDropView(Blueprint $blueprint, Fluent $command): string
{
return 'drop view ' . $this->wrapTable($command->get('view'));
}

public function compileViewExists(): string
{
return 'select * from information_schema.views where table_schema = ? and table_name = ?';
}

public function compileViewDefinition(): string
{
return 'select view_definition from information_schema.views where table_schema = ? and table_name = ?';
}

public function compileUniquePartial(Blueprint $blueprint, UniquePartialBuilder $command): string
{
$constraints = $command->get('constraints');
Expand Down
63 changes: 63 additions & 0 deletions tests/Functional/ViewTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace Umbrellio\Postgres\Tests\Functional;

use Illuminate\Support\Facades\Schema;
use Umbrellio\Postgres\Schema\Blueprint;

class ViewTest extends FunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();
Schema::create('test_table', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
}

protected function tearDown(): void
{
Schema::dropIfExists('test_table');
parent::tearDown();
}

/** @test */
public function createFacadeView(): void
{
Schema::createView('test_view', 'select * from test_table where name is not null');

$this->assertSame(
strtolower(
'select test_table.id, test_table.name from test_table where (test_table.name is not null);'
),
trim(strtolower(str_replace("\n", ' ', Schema::getViewDefinition('test_view'))))
);

Schema::dropView('test_view');
$this->assertFalse(Schema::hasView('test_view'));
}

/** @test */
public function createBlueprintView(): void
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->createView('test_view', 'select * from users where name is not null');
});

$this->assertSame(
strtolower('select users.id, users.name from users where (users.name is not null);'),
trim(strtolower(str_replace("\n", ' ', Schema::getViewDefinition('test_view'))))
);

Schema::table('users', function (Blueprint $table) {
$table->dropView('test_view');
});

$this->assertFalse(Schema::hasView('test_view'));
}
}

0 comments on commit 0e7964e

Please sign in to comment.