Skip to content

Commit

Permalink
Add ExpressionInterface as alias type and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Sep 28, 2023
1 parent fb6bc5d commit c8e431d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/Query/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ public function where(array|string|ExpressionInterface|null $condition, array $p
return $this;
}

public function withQuery(QueryInterface|string $query, string $alias, bool $recursive = false): static
public function withQuery(QueryInterface|string $query, ExpressionInterface|string $alias, bool $recursive = false): static
{
$this->withQueries[] = ['query' => $query, 'alias' => $alias, 'recursive' => $recursive];
return $this;
Expand Down
5 changes: 3 additions & 2 deletions src/Query/QueryPartsInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -645,10 +645,11 @@ public function where(array|string|ExpressionInterface|null $condition, array $p
* Prepends an SQL statement using `WITH` syntax.
*
* @param QueryInterface|string $query The SQL statement to append using `UNION`.
* @param string $alias The query alias in `WITH` construction.
* @param ExpressionInterface|string $alias The query alias in `WITH` construction.
* To specify the alias in plain SQL, you may pass an instance of {@see ExpressionInterface}.
* @param bool $recursive Its `true` if using `WITH RECURSIVE` and `false` if using `WITH`.
*/
public function withQuery(QueryInterface|string $query, string $alias, bool $recursive = false): static;
public function withQuery(QueryInterface|string $query, ExpressionInterface|string $alias, bool $recursive = false): static;

/**
* Specifies the `WITH` query clause for the query.
Expand Down
21 changes: 9 additions & 12 deletions src/QueryBuilder/AbstractDQLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -616,12 +616,16 @@ private function quoteTableNames(array $tables, array &$params): array
/**
* Quotes an alias of Common Table Expressions (CTE)
*
* @param string $name The alias name with or without column names to quote.
* @param ExpressionInterface|string $name The alias name with or without column names to quote.
*
* @return string The quoted alias.
*/
private function quoteCteAlias(string $name): string
private function quoteCteAlias(ExpressionInterface|string $name): string
{
if ($name instanceof ExpressionInterface) {
return $this->buildExpression($name);
}

if (!str_contains($name, '(')) {
return $this->quoter->quoteTableName($name);
}
Expand All @@ -631,16 +635,9 @@ private function quoteCteAlias(string $name): string
}

/** @psalm-suppress PossiblyUndefinedArrayOffset */
[$name, $columnNames] = explode('(', substr($name, 0, -1), 2);

$quotedName = $this->quoter->quoteTableName(trim($name));
$columnNames = explode(',', $columnNames);
$quotedColumnNames = [];

foreach ($columnNames as $columnName) {
$quotedColumnNames[] = $this->quoter->quoteColumnName(trim($columnName));
}
[$name, $columns] = explode('(', substr($name, 0, -1), 2);
$name = trim($name);

return $quotedName . '(' . implode(', ', $quotedColumnNames) . ')';
return $this->quoter->quoteTableName($name) . '(' . $this->buildColumns($columns) . ')';
}
}
22 changes: 7 additions & 15 deletions tests/AbstractQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1172,29 +1172,21 @@ public function testBuildWithQueryRecursive(): void
$this->assertSame([], $params);
}
public function testBuildWithQueryRecursiveWithColumns()
/** @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::cteAliases */
public function testBuildWithQueryAlias($alias, $expected)
{
$db = $this->getConnection();
$qb = $db->getQueryBuilder();
$withQuery = (new Query($db))->select(['id', 'name'])->from('user')->where(['status' => 1]);
$query = (new Query($db))->withQuery($withQuery, 'u(id, name)', true)->from('account');
[$sql, $params] = $qb->build($query);
$withQuery = (new Query($db))->from('t');
$query = (new Query($db))->withQuery($withQuery, $alias)->from('t');
$expected = DbHelper::replaceQuotes(
<<<SQL
WITH RECURSIVE [[u]]([[id]], [[name]]) AS (SELECT [[id]], [[name]] FROM [[user]] WHERE [[status]]=:qp0) SELECT * FROM [[account]]
SQL,
$db->getDriverName(),
);
[$sql, $params] = $qb->build($query);
if (in_array($db->getDriverName(), ['oci', 'sqlsrv'], true)) {
$expected = str_replace('WITH RECURSIVE ', 'WITH ', $expected);
}
$expected = DbHelper::replaceQuotes($expected, $db->getDriverName());
$this->assertSame($expected, $sql);
$this->assertSame([':qp0' => 1], $params);
$this->assertSame([], $params);
}
/**
Expand Down
36 changes: 36 additions & 0 deletions tests/Provider/QueryBuilderProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -1231,4 +1231,40 @@ public static function upsert(): array
],
];
}

public static function cteAliases(): array
{
return [
'simple' => [
'a',
<<<SQL
WITH [[a]] AS (SELECT * FROM [[t]]) SELECT * FROM [[t]]
SQL,
],
'with one column' => [
'a(b)',
<<<SQL
WITH [[a]]([[b]]) AS (SELECT * FROM [[t]]) SELECT * FROM [[t]]
SQL,
],
'with columns' => [
'a(b,c,d)',
<<<SQL
WITH [[a]]([[b]], [[c]], [[d]]) AS (SELECT * FROM [[t]]) SELECT * FROM [[t]]
SQL,
],
'with extra space' => [
'a(b,c,d) ',
<<<SQL
WITH a(b,c,d) AS (SELECT * FROM [[t]]) SELECT * FROM [[t]]
SQL,
],
'expression' => [
new Expression('a(b,c,d)'),
<<<SQL
WITH a(b,c,d) AS (SELECT * FROM [[t]]) SELECT * FROM [[t]]
SQL,
],
];
}
}

0 comments on commit c8e431d

Please sign in to comment.