diff --git a/CHANGELOG.md b/CHANGELOG.md index 91612e8..459708e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Unreleased] + +## Added + +- It is now possible to use an empty array when using `Sign::in` in a specification + ## 5.2.0 - 2026-05-14 ### Changed diff --git a/proofs/query/where.php b/proofs/query/where.php index 4b92847..5d5473f 100644 --- a/proofs/query/where.php +++ b/proofs/query/where.php @@ -585,4 +585,25 @@ static function($assert) { static fn() => null, )); }); + + yield $prove + ->proof('Where condition with no values for an "in" sign will match nothing') + ->given( + Column::any(), + ) + ->test(static function($assert, $column) { + $specification = Property::of( + $column->name()->toString(), + Sign::in, + [], + ); + $where = Where::of($specification); + + [$sql, $parameters] = $where->normalize(Driver::mysql); + $assert->same( + "WHERE {$column->name()->sql(Driver::mysql)} IN (SELECT NULL WHERE false)", + $sql, + ); + $assert->same(0, $parameters->size()); + }); }; diff --git a/properties/Connection.php b/properties/Connection.php index 08c2210..0ae5d5a 100644 --- a/properties/Connection.php +++ b/properties/Connection.php @@ -68,6 +68,7 @@ public static function list(): array Connection\SelectWhereEndsWith::class, Connection\SelectWhereContains::class, Connection\SelectWhereIn::class, + Connection\SelectWhereInNothing::class, Connection\SelectWhereInQuery::class, Connection\SelectOffset::class, Connection\SelectLimit::class, diff --git a/properties/Connection/SelectWhereInNothing.php b/properties/Connection/SelectWhereInNothing.php new file mode 100644 index 0000000..8485f18 --- /dev/null +++ b/properties/Connection/SelectWhereInNothing.php @@ -0,0 +1,78 @@ + + */ +final class SelectWhereInNothing implements Property +{ + private string $uuid; + private string $username; + private int $number; + + public function __construct(string $uuid, string $username, int $number) + { + $this->uuid = $uuid; + $this->username = $username; + $this->number = $number; + } + + public static function any(): Set + { + return Set::compose( + static fn(...$args) => new self(...$args), + Set::uuid(), + Set::strings() + ->madeOf(Set::strings()->chars()->ascii()) + ->between(0, 255), + Set::integers(), + ); + } + + public function applicableTo(object $connection): bool + { + return true; + } + + public function ensureHeldBy(Assert $assert, object $connection): object + { + $_ = $connection(Insert::into( + Name::of('test'), + Row::of([ + 'id' => $this->uuid, + 'username' => $this->username, + 'registerNumber' => $this->number, + ]), + )); + + $select = Select::from(Name::of('test'))->where(Comparator\Property::of( + 'test.id', + Sign::in, + [], + )); + $rows = $connection($select); + + $assert->same(0, $rows->size()); + + return $connection; + } +} diff --git a/src/Query/Where.php b/src/Query/Where.php index 47ad4bc..09cf7a3 100644 --- a/src/Query/Where.php +++ b/src/Query/Where.php @@ -218,7 +218,10 @@ private function buildInSql( return \sprintf( '%s IN (%s)', $this->buildColumn($driver, $specification), - \implode(', ', $placeholders), + match ($placeholders) { + [] => 'SELECT NULL WHERE false', + default => \implode(', ', $placeholders), + }, ); }