Skip to content

Commit 0a930da

Browse files
authored
Extend support for materialized views (#20)
* Extend support for materialized views (#18) * Extend support for materialized views
1 parent f8c2be8 commit 0a930da

File tree

10 files changed

+146
-7
lines changed

10 files changed

+146
-7
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,21 @@ Use `refreshMaterializedView()` to refresh a materialized view:
150150
Schema::refreshMaterializedView('active_users');
151151
```
152152

153+
Use `dropMaterializedView()` or `dropMaterializedViewIfExists()` to drop a materialized view:
154+
155+
```php
156+
Schema::dropMaterializedView('active_users');
157+
Schema::dropMaterializedViewIfExists('active_users');
158+
```
159+
160+
Use `hasMaterializedView()` to check whether a materialized view exists:
161+
162+
```php
163+
if (Schema::hasMaterializedView('active_users')) {
164+
//
165+
}
166+
```
167+
153168
## Contributing
154169

155170
Please see [CONTRIBUTING](.github/CONTRIBUTING.md) and [CODE OF CONDUCT](.github/CODE_OF_CONDUCT.md) for details.

src/Facades/Schema.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
* @method static void renameView(string $from, string $to)
2424
* @method static void dropView(string $name, bool $ifExists = false)
2525
* @method static void dropViewIfExists(string $name)
26+
* @method static void dropMaterializedView(string $name)
27+
* @method static void dropMaterializedViewIfExists(string $name)
2628
* @method static list<string> getViewColumnListing(string $name)
2729
* @method static void refreshMaterializedView(string $name)
30+
* @method static bool hasMaterializedView(string $name)
2831
*
2932
* @mixin \Illuminate\Support\Facades\Schema
3033
*/

src/Schema/Builders/ManagesViews.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Staudenmeir\LaravelMigrationViews\Schema\Builders;
44

55
use Illuminate\Support\Str;
6+
use RuntimeException;
67
use Stringable;
78

89
trait ManagesViews
@@ -123,15 +124,16 @@ public function renameView($from, $to)
123124
*
124125
* @param string $name
125126
* @param bool $ifExists
127+
* @param bool $materialized
126128
* @return void
127129
*/
128-
public function dropView($name, $ifExists = false)
130+
public function dropView($name, $ifExists = false, bool $materialized = false)
129131
{
130132
/** @var \Staudenmeir\LaravelMigrationViews\Schema\Grammars\ViewGrammar $grammar */
131133
$grammar = $this->grammar;
132134

133135
$this->connection->statement(
134-
$grammar->compileDropView($name, $ifExists)
136+
$grammar->compileDropView($name, $ifExists, $materialized)
135137
);
136138
}
137139

@@ -146,6 +148,28 @@ public function dropViewIfExists($name)
146148
$this->dropView($name, true);
147149
}
148150

151+
/**
152+
* Drop a materialized view from the schema.
153+
*
154+
* @param string $name
155+
* @return void
156+
*/
157+
public function dropMaterializedView(string $name): void
158+
{
159+
$this->dropView($name, materialized: true);
160+
}
161+
162+
/**
163+
* Drop a materialized view from the schema if it exists.
164+
*
165+
* @param string $name
166+
* @return void
167+
*/
168+
public function dropMaterializedViewIfExists(string $name): void
169+
{
170+
$this->dropView($name, ifExists: true, materialized: true);
171+
}
172+
149173
/**
150174
* Get the column listing for a given view.
151175
*
@@ -175,4 +199,15 @@ public function refreshMaterializedView(string $name): void
175199
$grammar->compileRefreshMaterializedView($name)
176200
);
177201
}
202+
203+
/**
204+
* Determine if the given materialized view exists.
205+
*
206+
* @param string $name
207+
* @return bool
208+
*/
209+
public function hasMaterializedView(string $name): bool
210+
{
211+
throw new RuntimeException('This database is not supported.'); // @codeCoverageIgnore
212+
}
178213
}

src/Schema/Builders/PostgresBuilder.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,26 @@ protected function stringifyBindings(array $bindings)
2626

2727
return $this->baseStringifyBindings($bindings);
2828
}
29+
30+
/**
31+
* Determine if the given materialized view exists.
32+
*
33+
* @param string $name
34+
* @return bool
35+
*/
36+
public function hasMaterializedView(string $name): bool
37+
{
38+
/** @var string $view */
39+
[$schema, $view] = $this->parseSchemaAndTable($name, true);
40+
41+
$view = $this->connection->getTablePrefix().$view;
42+
43+
/** @var \Staudenmeir\LaravelMigrationViews\Schema\Grammars\PostgresGrammar $grammar */
44+
$grammar = $this->grammar;
45+
46+
return (bool) $this->connection->scalar(
47+
$grammar->compileMaterializedViewExists(),
48+
[$schema, $view]
49+
);
50+
}
2951
}

src/Schema/Builders/SqlServerBuilder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ public function createView($name, $query, ?array $columns = null, $orReplace = f
3434
*
3535
* @param string $name
3636
* @param bool $ifExists
37+
* @param bool $materialized
3738
* @return void
3839
*/
39-
public function dropView($name, $ifExists = false)
40+
public function dropView($name, $ifExists = false, bool $materialized = false)
4041
{
4142
/** @var \Staudenmeir\LaravelMigrationViews\Schema\Grammars\ViewGrammar $grammar */
4243
$grammar = $this->grammar;

src/Schema/Grammars/CompilesViews.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,16 @@ public function compileCreateView($name, $query, $columns, $orReplace, bool $mat
3131
*
3232
* @param string $name
3333
* @param bool $ifExists
34+
* @param bool $materialized
3435
* @return string
3536
*/
36-
public function compileDropView($name, $ifExists)
37+
public function compileDropView($name, $ifExists, bool $materialized = false)
3738
{
3839
$ifExists = $ifExists ? 'if exists ' : '';
3940

40-
return 'drop view '.$ifExists.$this->wrapTable($name);
41+
$materializedSql = $materialized ? 'materialized ' : '';
42+
43+
return 'drop '.$materializedSql.'view '.$ifExists.$this->wrapTable($name);
4144
}
4245

4346
/**

src/Schema/Grammars/PostgresGrammar.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,20 @@
77
class PostgresGrammar extends Base implements ViewGrammar
88
{
99
use CompilesViews;
10+
11+
/**
12+
* Compile the query to determine if a materialized view exists.
13+
*
14+
* @return string
15+
*/
16+
public function compileMaterializedViewExists(): string
17+
{
18+
return <<<SQL
19+
select exists (
20+
select 1
21+
from "pg_matviews"
22+
where "schemaname" = ? and "matviewname" = ?
23+
)
24+
SQL;
25+
}
1026
}

src/Schema/Grammars/SqlServerGrammar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class SqlServerGrammar extends Base implements ViewGrammar
99
use CompilesViews;
1010

1111
/** @inheritDoc */
12-
public function compileDropView($name, $ifExists)
12+
public function compileDropView($name, $ifExists, bool $materialized = false)
1313
{
1414
$ifExists = $ifExists ? 'if exists ('.$this->compileViewExists().') ' : '';
1515

src/Schema/Grammars/ViewGrammar.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ public function compileCreateView($name, $query, $columns, $orReplace, bool $mat
2222
*
2323
* @param string $name
2424
* @param bool $ifExists
25+
* @param bool $materialized
2526
* @return string
2627
*/
27-
public function compileDropView($name, $ifExists);
28+
public function compileDropView($name, $ifExists, bool $materialized = false);
2829

2930
/**
3031
* Compile the query to refresh a materialized view.

tests/SchemaTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,33 @@ public function testDropViewIfExists()
127127
$this->assertFalse(Schema::hasView('active_users'));
128128
}
129129

130+
public function testDropMaterializedView(): void
131+
{
132+
if ($this->connection !== 'pgsql') {
133+
$this->markTestSkipped();
134+
}
135+
136+
Schema::createMaterializedView(
137+
'active_users',
138+
DB::table('users')->where('active', true)
139+
);
140+
141+
Schema::dropMaterializedView('active_users');
142+
143+
$this->assertFalse(Schema::hasMaterializedView('active_users'));
144+
}
145+
146+
public function testDropMaterializedViewIfExists(): void
147+
{
148+
if ($this->connection !== 'pgsql') {
149+
$this->markTestSkipped();
150+
}
151+
152+
Schema::dropMaterializedViewIfExists('active_users');
153+
154+
$this->assertFalse(Schema::hasMaterializedView('active_users'));
155+
}
156+
130157
public function testGetViewColumnListing()
131158
{
132159
Schema::createView('active_users', DB::table('users')->where('active', true));
@@ -154,4 +181,20 @@ public function testRefreshMaterializedView()
154181

155182
$this->assertDatabaseCount('active_users', 0);
156183
}
184+
185+
public function testHasMaterializedView(): void
186+
{
187+
if ($this->connection !== 'pgsql') {
188+
$this->markTestSkipped();
189+
}
190+
191+
$this->assertFalse(Schema::hasMaterializedView('active_users'));
192+
193+
Schema::createMaterializedView(
194+
'active_users',
195+
DB::table('users')->where('active', true)
196+
);
197+
198+
$this->assertTrue(Schema::hasMaterializedView('active_users'));
199+
}
157200
}

0 commit comments

Comments
 (0)