Skip to content

Commit

Permalink
Fluent: INSERT-SELECT non-string columns require an alias, CS
Browse files Browse the repository at this point in the history
  • Loading branch information
forrest79 committed Mar 13, 2024
1 parent b154bcf commit f76de64
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
7 changes: 7 additions & 0 deletions src/Fluent/Exceptions/QueryBuilderException.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class QueryBuilderException extends Exception
public const ON_CONFLICT_NO_DO = 13;
public const ON_CONFLICT_DO_WITHOUT_DEFINITION = 14;
public const ON_CONFLICT_DO_UPDATE_SET_SINGLE_COLUMN_CAN_BE_ONLY_STRING = 15;
public const MISSING_COLUMN_ALIAS = 16;


public static function badQueryType(string $type): self
Expand Down Expand Up @@ -113,4 +114,10 @@ public static function onConflictDoUpdateSetSingleColumnCanBeOnlyString(): self
return new self('ON CONFLICT UPDATE SET array value without alias (string key) must be only string.', self::ON_CONFLICT_DO_UPDATE_SET_SINGLE_COLUMN_CAN_BE_ONLY_STRING);
}


public static function missingColumnAlias(): self
{
return new self('Non-string columns for INSERT-SELECT must have an alias.', self::MISSING_COLUMN_ALIAS);
}

}
18 changes: 14 additions & 4 deletions src/Fluent/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected function prepareSqlQuery(string $sql, array $params): Db\Sql\Query
/**
* @param array<string, mixed> $queryParams
* @param list<mixed> $params
* @param array<string>|NULL $insertSelectColumnNames
* @param list<string>|NULL $insertSelectColumnNames
* @throws Exceptions\QueryBuilderException
* @phpstan-param QueryParams $queryParams
*/
Expand Down Expand Up @@ -158,6 +158,8 @@ private function createInsert(array $queryParams, array &$params): string
$selectColumns = [];
$data = ' ' . $this->createSelect($queryParams, $params, $selectColumns);
if ($columns === []) {
\assert($selectColumns !== NULL);

if ((\count($selectColumns) > 1) && \in_array('*', $selectColumns, TRUE)) {
throw Exceptions\QueryBuilderException::selectAllColumnsCantBeCombinedWithConcreteColumnForInsertSelectWithColumnDetection();
}
Expand Down Expand Up @@ -449,16 +451,24 @@ private function getSelectColumns(array $queryParams, array &$params, array|NULL

$columns = [];
foreach ($queryParams[Query::PARAM_SELECT] as $key => $value) {
if ($columnNames !== NULL) {
if (\is_int($key) && !\is_string($value)) {
throw Exceptions\QueryBuilderException::missingColumnAlias();
}

\assert(\is_string($key) || \is_string($value));

$columnNames[] = \is_int($key) ? $value : $key;
}

if ($value instanceof Db\Sql) {
$params[] = $value;
$value = '(?)';
} else if ($value instanceof Query) {
$params[] = $value->createSqlQuery();
$value = '(?)';
}
if ($columnNames !== NULL) {
$columnNames[] = \is_int($key) ? $value : $key;
}

$columns[] = (($value instanceof \BackedEnum) ? $value->value : $value) . (\is_int($key) ? '' : (' AS "' . $key . '"'));
}

Expand Down
32 changes: 32 additions & 0 deletions tests/Unit/FluentQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,38 @@ public function testInsertSelectAllColumns(): void
}


public function testInsertSelectNoColumn(): void
{
Tester\Assert::exception(function (): void {
$this->query()
->insert('table1')
->select([])
->from('table2')
->createSqlQuery();
}, Fluent\Exceptions\QueryBuilderException::class, NULL, Fluent\Exceptions\QueryBuilderException::NO_DATA_TO_INSERT);
}


public function testInsertSelectMissingColumnAlias(): void
{
Tester\Assert::exception(function (): void {
$this->query()
->insert('table1')
->select([1])
->from('table2')
->createSqlQuery();
}, Fluent\Exceptions\QueryBuilderException::class, NULL, Fluent\Exceptions\QueryBuilderException::MISSING_COLUMN_ALIAS);

Tester\Assert::exception(function (): void {
$this->query()
->insert('table1')
->select([Tests\TestEnum::One])
->from('table2')
->createSqlQuery();
}, Fluent\Exceptions\QueryBuilderException::class, NULL, Fluent\Exceptions\QueryBuilderException::MISSING_COLUMN_ALIAS);
}


public function testInsertOnConflictDoUpdate(): void
{
$query = $this->query()
Expand Down

0 comments on commit f76de64

Please sign in to comment.