Skip to content

Commit bd65551

Browse files
committed
fix: db wipe support for materialized views and timescale (resolves #104)
1 parent e655933 commit bd65551

File tree

4 files changed

+103
-0
lines changed

4 files changed

+103
-0
lines changed

src/Schema/Builder.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Builder extends PostgresBuilder
1414
use BuilderExtension;
1515
use BuilderFunction;
1616
use BuilderView;
17+
use BuilderWipe;
1718

1819
/**
1920
* Get the database connection instance.

src/Schema/BuilderWipe.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tpetry\PostgresqlEnhanced\Schema;
6+
7+
trait BuilderWipe
8+
{
9+
public function dropAllContinuousAggregates(): void
10+
{
11+
$continuousAggregates = rescue(
12+
callback: fn () => $this->getConnection()->table('timescaledb_information.continuous_aggregates')->select(['view_schema', 'view_name'])->whereIn('view_schema', $this->getActiveSchemas())->get(),
13+
rescue: [],
14+
report: false,
15+
);
16+
foreach ($continuousAggregates as $continuousAggregate) {
17+
$name = "{$continuousAggregate->view_schema}.{$continuousAggregate->view_name}";
18+
if (!\in_array($name, $this->connection->getConfig('dont_drop') ?? [])) {
19+
$this->connection->statement("drop materialized view if exists {$this->grammar->wrap($name)} cascade");
20+
}
21+
}
22+
}
23+
24+
public function dropAllHypertables(): void
25+
{
26+
$hypertables = rescue(
27+
callback: fn () => $this->getConnection()->table('timescaledb_information.hypertables')->select(['hypertable_schema', 'hypertable_name'])->whereIn('hypertable_schema', $this->getActiveSchemas())->get(),
28+
rescue: [],
29+
report: false,
30+
);
31+
foreach ($hypertables as $hypertable) {
32+
$name = "{$hypertable->hypertable_schema}.{$hypertable->hypertable_name}";
33+
if (!\in_array($name, $this->connection->getConfig('dont_drop') ?? [])) {
34+
$this->connection->statement("drop table if exists {$this->grammar->wrap($name)} cascade");
35+
}
36+
}
37+
}
38+
39+
public function dropAllMaterializedViews(): void
40+
{
41+
$materializedViews = $this->getConnection()->table('pg_matviews')->select(['schemaname', 'matviewname'])->whereIn('schemaname', $this->getActiveSchemas())->get();
42+
foreach ($materializedViews as $materializedView) {
43+
$name = "{$materializedView->schemaname}.{$materializedView->matviewname}";
44+
if (!\in_array($name, $this->connection->getConfig('dont_drop') ?? [])) {
45+
$this->connection->statement("drop materialized view if exists {$this->grammar->wrap($name)} cascade");
46+
}
47+
}
48+
}
49+
50+
public function dropAllTables(): void
51+
{
52+
$this->dropAllHypertables();
53+
parent::dropAllTables();
54+
}
55+
56+
public function dropAllViews(): void
57+
{
58+
$this->dropAllContinuousAggregates();
59+
$this->dropAllMaterializedViews();
60+
parent::dropAllViews();
61+
}
62+
63+
/**
64+
* @return string[]
65+
*/
66+
private function getActiveSchemas(): array
67+
{
68+
return rescue(
69+
callback: fn () => $this->getCurrentSchemaListing(), // Laravel >= 12.x
70+
rescue: [$this->connection->getConfig('schema') ?? 'public'], // Laravel < 12.x
71+
report: false,
72+
);
73+
}
74+
}

tests/Migration/ExtensionTimescaleTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use DateTimeImmutable;
88
use DateTimeZone;
9+
use Illuminate\Support\Facades\Artisan;
910
use Tpetry\PostgresqlEnhanced\Schema\Blueprint;
1011
use Tpetry\PostgresqlEnhanced\Schema\Grammars\Grammar;
1112
use Tpetry\PostgresqlEnhanced\Schema\Timescale\Actions\Action;
@@ -341,6 +342,23 @@ public function testCreateContinuousAggregate(): void
341342
], array_column($queries, 'query'));
342343
}
343344

345+
public function testDbWipeWillRemoveAllTimescaleStuff(): void
346+
{
347+
Schema::create('hypertbl', function (Blueprint $table): void {
348+
$table->text('tenant_id');
349+
$table->timestampsTz();
350+
$table->timescale(new CreateHypertable('created_at', '14 days'));
351+
});
352+
Schema::continuousAggregate('hypertbl_agg', function (CaggBlueprint $table): void {
353+
$table->as("select time_bucket('1 day', created_at) bucket, tenant_id, count(*) from hypertbl group by bucket, tenant_id");
354+
});
355+
356+
Artisan::call('db:wipe --drop-views');
357+
358+
$this->assertEquals(0, $this->getConnection()->table('timescaledb_information.hypertables')->count());
359+
$this->assertEquals(0, $this->getConnection()->table('timescaledb_information.continuous_aggregates')->count());
360+
}
361+
344362
public function testDropContinuousAggregate(): void
345363
{
346364
$this->getConnection()->statement('create table hypertbl(time timestamptz)');

tests/Migration/ViewTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Tpetry\PostgresqlEnhanced\Tests\Migration;
66

7+
use Illuminate\Support\Facades\Artisan;
78
use Illuminate\Support\Facades\DB;
89
use Tpetry\PostgresqlEnhanced\Support\Facades\Schema;
910
use Tpetry\PostgresqlEnhanced\Tests\TestCase;
@@ -82,6 +83,15 @@ public function testCreateViewWithColumns(): void
8283
$this->assertEquals(['create view "test_787483" ("column_275665") as select random()'], array_column($queries, 'query'));
8384
}
8485

86+
public function testDbWipeWillRemoveMaterializedViews(): void
87+
{
88+
DB::statement('CREATE MATERIALIZED VIEW test_585504 AS SELECT random() as column_954390');
89+
90+
Artisan::call('db:wipe --drop-views');
91+
92+
$this->assertEmpty($this->getConnection()->select('select * from pg_matviews'));
93+
}
94+
8595
public function testDropView(): void
8696
{
8797
DB::statement('CREATE VIEW test_125382 AS SELECT random() as column_298864');

0 commit comments

Comments
 (0)