Skip to content

Commit

Permalink
Base refresh materialized view
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerych1984 committed Jan 22, 2024
1 parent ef81e8b commit 348f586
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Closure;
use Throwable;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
Expand All @@ -21,6 +22,7 @@
use function is_scalar;
use function is_string;
use function preg_replace_callback;
use function sprintf;
use function str_starts_with;
use function stream_get_contents;

Expand Down Expand Up @@ -526,6 +528,13 @@ public function upsert(
return $this->setSql($sql)->bindValues($params);
}

public function refreshMaterializedView(string $viewName, ?bool $concurrently = null, ?bool $withData = null): bool

Check warning on line 531 in src/Command/AbstractCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/AbstractCommand.php#L531

Added line #L531 was not covered by tests
{
$sql = $this->getQueryBuilder()->refreshMaterializedView($viewName, $concurrently ?? false, $withData);

Check warning on line 533 in src/Command/AbstractCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/AbstractCommand.php#L533

Added line #L533 was not covered by tests

throw new NotSupportedException(sprintf('"%s" command not supported', $sql));

Check warning on line 535 in src/Command/AbstractCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/AbstractCommand.php#L535

Added line #L535 was not covered by tests
}

/**
* @return QueryBuilderInterface The query builder instance.
*/
Expand Down
10 changes: 10 additions & 0 deletions src/Command/CommandInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -833,4 +833,14 @@ public function upsert(
bool|array $updateColumns = true,
array $params = []
): static;

/**
*
* Execute `REFRESH MATERIALIZED VIEW` command
* @param string $viewName
* @param bool|null $concurrently If `null` then auto choice from depends on DBMS
* @param bool|null $withData
* @return bool
*/
public function refreshMaterializedView(string $viewName, ?bool $concurrently = null, ?bool $withData = null): bool;
}
18 changes: 18 additions & 0 deletions src/QueryBuilder/AbstractDDLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Yiisoft\Db\Schema\SchemaInterface;

use function implode;
use function is_bool;
use function is_string;
use function preg_split;

Expand Down Expand Up @@ -302,4 +303,21 @@ public function truncateTable(string $table): string
{
return 'TRUNCATE TABLE ' . $this->quoter->quoteTableName($table);
}

public function refreshMaterializedView(string $viewName, bool $concurrently = false, ?bool $withData = null): string

Check warning on line 307 in src/QueryBuilder/AbstractDDLQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractDDLQueryBuilder.php#L307

Added line #L307 was not covered by tests
{
$sql = 'REFRESH MATERIALIZED VIEW ';

Check warning on line 309 in src/QueryBuilder/AbstractDDLQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractDDLQueryBuilder.php#L309

Added line #L309 was not covered by tests

if ($concurrently) {
$sql .= 'CONCURRENTLY ';

Check warning on line 312 in src/QueryBuilder/AbstractDDLQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractDDLQueryBuilder.php#L311-L312

Added lines #L311 - L312 were not covered by tests
}

$sql .= $this->quoter->quoteTableName($viewName);

Check warning on line 315 in src/QueryBuilder/AbstractDDLQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractDDLQueryBuilder.php#L315

Added line #L315 was not covered by tests

if (is_bool($withData)) {
$sql .= ' WITH ' . ($withData ? 'DATA' : 'NO DATA');

Check warning on line 318 in src/QueryBuilder/AbstractDDLQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractDDLQueryBuilder.php#L317-L318

Added lines #L317 - L318 were not covered by tests
}

return $sql;

Check warning on line 321 in src/QueryBuilder/AbstractDDLQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractDDLQueryBuilder.php#L321

Added line #L321 was not covered by tests
}
}
5 changes: 5 additions & 0 deletions src/QueryBuilder/AbstractQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -405,4 +405,9 @@ public function upsert(
): string {
return $this->dmlBuilder->upsert($table, $insertColumns, $updateColumns, $params);
}

public function refreshMaterializedView(string $viewName, bool $concurrently = false, ?bool $withData = null): string

Check warning on line 409 in src/QueryBuilder/AbstractQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractQueryBuilder.php#L409

Added line #L409 was not covered by tests
{
return $this->ddlBuilder->refreshMaterializedView($viewName, $concurrently, $withData);

Check warning on line 411 in src/QueryBuilder/AbstractQueryBuilder.php

View check run for this annotation

Codecov / codecov/patch

src/QueryBuilder/AbstractQueryBuilder.php#L411

Added line #L411 was not covered by tests
}
}
11 changes: 11 additions & 0 deletions src/QueryBuilder/DDLQueryBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,4 +424,15 @@ public function renameTable(string $oldName, string $newName): string;
* Note: The method will quote the `table` parameter before using it in the generated SQL.
*/
public function truncateTable(string $table): string;

/**
* Refresh materialized view
*
* @param string $viewName The name of the view to refresh.
* @param bool $concurrently Refresh the materialized view without locking out concurrent selects on the materialized view.
* @param bool|null $withData When `true` then the backing query is executed to provide the new data. Otherwise if `false` then no new data is generated and the materialized view is left in an unscannable state
*
* @return string The `REFRESH MATERIALIZED VIEW` SQL statement
*/
public function refreshMaterializedView(string $viewName, bool $concurrently = false, ?bool $withData = null): string;
}
35 changes: 35 additions & 0 deletions tests/Db/Command/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -727,4 +727,39 @@ public function testProfilerData(string $sql = null): void
);
parent::testProfilerData();
}

public static function refreshMaterializedViewDataProvider(): array
{
return [
[
'default_mt',
null,
null,
],
[
'concurrently_mt',
true,
null,
],
[
'concurrently_with_data_mt',
true,
true,
],
[
'concurrently_without_data_mt',
true,
false,
],
];
}


public function testRefreshMaterializedView(string $viewName, ?bool $concurrently, ?bool $withData): void
{
$db = $this->getConnection();
$this->expectException(NotSupportedException::class);

$db->createCommand()->refreshMaterializedView($viewName, $concurrently, $withData);
}
}
62 changes: 61 additions & 1 deletion tests/Db/QueryBuilder/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public function testGetExpressionBuilderException(): void

$this->expectException(Exception::class);

$expression = new class () implements ExpressionInterface {
$expression = new class() implements ExpressionInterface {
};
$qb = $db->getQueryBuilder();
$qb->getExpressionBuilder($expression);
Expand Down Expand Up @@ -310,4 +310,64 @@ public function testUpsertExecute(
$actualParams = [];
$actualSQL = $db->getQueryBuilder()->upsert($table, $insertColumns, $updateColumns, $actualParams);
}


public static function refreshMaterializedViewDataProvider(): array
{
return [
[
'concurrently_mt',
true,
null,
'REFRESH MATERIALIZED VIEW CONCURRENTLY [[concurrently_mt]]',
],
[
'concurrently_with_data_mt',
true,
true,
'REFRESH MATERIALIZED VIEW CONCURRENTLY [[concurrently_with_data_mt]] WITH DATA',
],
[
'concurrently_without_data_mt',
true,
false,
'REFRESH MATERIALIZED VIEW CONCURRENTLY [[concurrently_without_data_mt]] WITH NO DATA',
],
[
'not_concurrently_mt',
false,
null,
'REFRESH MATERIALIZED VIEW [[not_concurrently_mt]]',
],
[
'not_concurrently_with_data_mt',
false,
true,
'REFRESH MATERIALIZED VIEW [[not_concurrently_with_data_mt]] WITH DATA',
],
[
'not_concurrently_without_data_mt',
false,
false,
'REFRESH MATERIALIZED VIEW [[not_concurrently_without_data_mt]] WITH NO DATA',
],
];
}

/**
* @dataProvider refreshMaterializedViewDataProvider
* @param bool $concurrently
* @param bool|null $withData
* @return void
*/
public function testRefreshMaterializedView(string $viewName, bool $concurrently, ?bool $withData, string $expected): void
{
$db = $this->getConnection();
$driver = $db->getDriverName();
$sql = $db->getQueryBuilder()->refreshMaterializedView($viewName, $concurrently, $withData);
$actual = DbHelper::replaceQuotes($sql, $driver);
$expected = DbHelper::replaceQuotes($expected, $driver);

$this->assertSame($expected, $actual);
}
}

0 comments on commit 348f586

Please sign in to comment.