From acd7dee0a6920078c52deaf34b7fa8d04e3748bb Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sat, 22 Jun 2024 18:29:49 +0700 Subject: [PATCH 01/10] Create overlap condition --- .../Condition/AbstractOverlapCondition.php | 83 +++++++++++++++++++ .../Condition/ArrayOverlapCondition.php | 12 +++ .../Interface/OverlapConditionInterface.php | 21 +++++ .../Condition/JsonOverlapCondition.php | 12 +++ 4 files changed, 128 insertions(+) create mode 100644 src/QueryBuilder/Condition/AbstractOverlapCondition.php create mode 100644 src/QueryBuilder/Condition/ArrayOverlapCondition.php create mode 100644 src/QueryBuilder/Condition/Interface/OverlapConditionInterface.php create mode 100644 src/QueryBuilder/Condition/JsonOverlapCondition.php diff --git a/src/QueryBuilder/Condition/AbstractOverlapCondition.php b/src/QueryBuilder/Condition/AbstractOverlapCondition.php new file mode 100644 index 000000000..59786f212 --- /dev/null +++ b/src/QueryBuilder/Condition/AbstractOverlapCondition.php @@ -0,0 +1,83 @@ +column; + } + + public function getValues(): iterable|ExpressionInterface + { + return $this->values; + } + + /** + * Creates a condition based on the given operator and operands. + * + * @throws InvalidArgumentException If the number of operands isn't 2. + */ + public static function fromArrayDefinition(string $operator, array $operands): self + { + if (!isset($operands[0], $operands[1])) { + throw new InvalidArgumentException("Operator '$operator' requires three operands."); + } + + return new static( + self::validateColumn($operator, $operands[0]), + self::validateValues($operator, $operands[1]) + ); + } + + /** + * Validates the given column to be string or `ExpressionInterface`. + * + * @throws InvalidArgumentException If the column isn't a string or `ExpressionInterface`. + */ + private static function validateColumn(string $operator, mixed $column): string|ExpressionInterface + { + if (is_string($column) || $column instanceof ExpressionInterface) { + return $column; + } + + throw new InvalidArgumentException( + "Operator '$operator' requires column to be string or ExpressionInterface." + ); + } + + /** + * Validates the given values to be `iterable` or `ExpressionInterface`. + * + * @throws InvalidArgumentException If the values aren't an `iterable` or `ExpressionInterface`. + */ + private static function validateValues(string $operator, mixed $values): iterable|ExpressionInterface + { + if (is_iterable($values) || $values instanceof ExpressionInterface) { + return $values; + } + + throw new InvalidArgumentException( + "Operator '$operator' requires values to be iterable or ExpressionInterface." + ); + } +} diff --git a/src/QueryBuilder/Condition/ArrayOverlapCondition.php b/src/QueryBuilder/Condition/ArrayOverlapCondition.php new file mode 100644 index 000000000..7ed26030e --- /dev/null +++ b/src/QueryBuilder/Condition/ArrayOverlapCondition.php @@ -0,0 +1,12 @@ + Date: Sat, 29 Jun 2024 14:49:45 +0700 Subject: [PATCH 02/10] Add array and json overlaps conditions --- src/QueryBuilder/AbstractDQLQueryBuilder.php | 2 ++ ...tion.php => AbstractOverlapsCondition.php} | 6 ++-- .../Condition/ArrayOverlapCondition.php | 12 -------- .../Condition/ArrayOverlapsCondition.php | 12 ++++++++ .../AbstractOverlapsConditionBuilder.php | 28 +++++++++++++++++++ ...ace.php => OverlapsConditionInterface.php} | 5 +++- .../Condition/JsonOverlapCondition.php | 12 -------- .../Condition/JsonOverlapsCondition.php | 12 ++++++++ tests/Provider/QueryBuilderProvider.php | 23 +++++++++++++++ 9 files changed, 84 insertions(+), 28 deletions(-) rename src/QueryBuilder/Condition/{AbstractOverlapCondition.php => AbstractOverlapsCondition.php} (90%) delete mode 100644 src/QueryBuilder/Condition/ArrayOverlapCondition.php create mode 100644 src/QueryBuilder/Condition/ArrayOverlapsCondition.php create mode 100644 src/QueryBuilder/Condition/Builder/AbstractOverlapsConditionBuilder.php rename src/QueryBuilder/Condition/Interface/{OverlapConditionInterface.php => OverlapsConditionInterface.php} (81%) delete mode 100644 src/QueryBuilder/Condition/JsonOverlapCondition.php create mode 100644 src/QueryBuilder/Condition/JsonOverlapsCondition.php diff --git a/src/QueryBuilder/AbstractDQLQueryBuilder.php b/src/QueryBuilder/AbstractDQLQueryBuilder.php index 9119ffa7d..d423bc317 100644 --- a/src/QueryBuilder/AbstractDQLQueryBuilder.php +++ b/src/QueryBuilder/AbstractDQLQueryBuilder.php @@ -496,6 +496,8 @@ protected function defaultConditionClasses(): array 'OR NOT LIKE' => Condition\LikeCondition::class, 'EXISTS' => Condition\ExistsCondition::class, 'NOT EXISTS' => Condition\ExistsCondition::class, + 'ARRAY OVERLAPS' => Condition\ArrayOverlapsCondition::class, + 'JSON OVERLAPS' => Condition\JsonOverlapsCondition::class, ]; } diff --git a/src/QueryBuilder/Condition/AbstractOverlapCondition.php b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php similarity index 90% rename from src/QueryBuilder/Condition/AbstractOverlapCondition.php rename to src/QueryBuilder/Condition/AbstractOverlapsCondition.php index 59786f212..9748626a3 100644 --- a/src/QueryBuilder/Condition/AbstractOverlapCondition.php +++ b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php @@ -6,15 +6,15 @@ use Yiisoft\Db\Exception\InvalidArgumentException; use Yiisoft\Db\Expression\ExpressionInterface; -use Yiisoft\Db\QueryBuilder\Condition\Interface\OverlapConditionInterface; +use Yiisoft\Db\QueryBuilder\Condition\Interface\OverlapsConditionInterface; use function is_iterable; use function is_string; /** - * Condition that's represented `OVERLAP` operator is used to check if a value is between two values. + * The base class for classes representing the array and JSON overlaps conditions. */ -abstract class AbstractOverlapCondition implements OverlapConditionInterface +abstract class AbstractOverlapsCondition implements OverlapsConditionInterface { public function __construct( private string|ExpressionInterface $column, diff --git a/src/QueryBuilder/Condition/ArrayOverlapCondition.php b/src/QueryBuilder/Condition/ArrayOverlapCondition.php deleted file mode 100644 index 7ed26030e..000000000 --- a/src/QueryBuilder/Condition/ArrayOverlapCondition.php +++ /dev/null @@ -1,12 +0,0 @@ -queryBuilder->buildExpression($column); + } + + return $this->queryBuilder->quoter()->quoteColumnName($column); + } +} diff --git a/src/QueryBuilder/Condition/Interface/OverlapConditionInterface.php b/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php similarity index 81% rename from src/QueryBuilder/Condition/Interface/OverlapConditionInterface.php rename to src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php index 8150be752..09f61958e 100644 --- a/src/QueryBuilder/Condition/Interface/OverlapConditionInterface.php +++ b/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php @@ -6,7 +6,10 @@ use Yiisoft\Db\Expression\ExpressionInterface; -interface OverlapConditionInterface extends ConditionInterface +/** + * Represents array and JSON overlaps conditions. + */ +interface OverlapsConditionInterface extends ConditionInterface { /** * @return ExpressionInterface|string The column name. If it's an array, a composite `IN` condition will be diff --git a/src/QueryBuilder/Condition/JsonOverlapCondition.php b/src/QueryBuilder/Condition/JsonOverlapCondition.php deleted file mode 100644 index 625db6d96..000000000 --- a/src/QueryBuilder/Condition/JsonOverlapCondition.php +++ /dev/null @@ -1,12 +0,0 @@ - [[null], 1], + 'expression' => [new Expression("'[0,1,2,7]'"), 1], + 'json expression' => [new JsonExpression([0,1,2,7]), 1], + 'query expression' => [(new Query(static::getDb()))->select(new JsonExpression([0,1,2,7])), 1], + ]; + } } From 3bbdddd86c6cc448e11a4f4210372d7ee3655cae Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Sat, 29 Jun 2024 07:50:09 +0000 Subject: [PATCH 03/10] Apply fixes from StyleCI --- .../Condition/Interface/OverlapsConditionInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php b/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php index 09f61958e..3055aec5f 100644 --- a/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php +++ b/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php @@ -18,7 +18,7 @@ interface OverlapsConditionInterface extends ConditionInterface public function getColumn(): string|ExpressionInterface; /** - * @return iterable|ExpressionInterface An array of values that {@see columns} value should overlap. + * @return ExpressionInterface|iterable An array of values that {@see columns} value should overlap. */ public function getValues(): iterable|ExpressionInterface; } From fe8f61ca25a9005eab7e86fc97104b512a3d3b73 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sat, 29 Jun 2024 14:59:40 +0700 Subject: [PATCH 04/10] Fix psalm issue --- src/QueryBuilder/Condition/AbstractOverlapsCondition.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/QueryBuilder/Condition/AbstractOverlapsCondition.php b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php index 9748626a3..7aa1a4b35 100644 --- a/src/QueryBuilder/Condition/AbstractOverlapsCondition.php +++ b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php @@ -37,12 +37,13 @@ public function getValues(): iterable|ExpressionInterface * * @throws InvalidArgumentException If the number of operands isn't 2. */ - public static function fromArrayDefinition(string $operator, array $operands): self + public static function fromArrayDefinition(string $operator, array $operands): static { if (!isset($operands[0], $operands[1])) { throw new InvalidArgumentException("Operator '$operator' requires three operands."); } + /** @psalm-suppress UnsafeInstantiation */ return new static( self::validateColumn($operator, $operands[0]), self::validateValues($operator, $operands[1]) From eeecf8292ddfb601d8a0450085dbb31d7cac815d Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sat, 29 Jun 2024 16:41:30 +0700 Subject: [PATCH 05/10] Add tests --- .../Condition/AbstractOverlapsCondition.php | 6 +-- tests/AbstractQueryBuilderTest.php | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/QueryBuilder/Condition/AbstractOverlapsCondition.php b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php index 7aa1a4b35..68f2182f3 100644 --- a/src/QueryBuilder/Condition/AbstractOverlapsCondition.php +++ b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php @@ -40,7 +40,7 @@ public function getValues(): iterable|ExpressionInterface public static function fromArrayDefinition(string $operator, array $operands): static { if (!isset($operands[0], $operands[1])) { - throw new InvalidArgumentException("Operator '$operator' requires three operands."); + throw new InvalidArgumentException("Operator \"$operator\" requires three operands."); } /** @psalm-suppress UnsafeInstantiation */ @@ -62,7 +62,7 @@ private static function validateColumn(string $operator, mixed $column): string| } throw new InvalidArgumentException( - "Operator '$operator' requires column to be string or ExpressionInterface." + "Operator \"$operator\" requires column to be string or ExpressionInterface." ); } @@ -78,7 +78,7 @@ private static function validateValues(string $operator, mixed $values): iterabl } throw new InvalidArgumentException( - "Operator '$operator' requires values to be iterable or ExpressionInterface." + "Operator \"$operator\" requires values to be iterable or ExpressionInterface." ); } } diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php index 98ec04e0a..45804d30e 100644 --- a/tests/AbstractQueryBuilderTest.php +++ b/tests/AbstractQueryBuilderTest.php @@ -20,6 +20,8 @@ use Yiisoft\Db\Expression\ExpressionInterface; use Yiisoft\Db\Query\Query; use Yiisoft\Db\Query\QueryInterface; +use Yiisoft\Db\QueryBuilder\Condition\ArrayOverlapsCondition; +use Yiisoft\Db\QueryBuilder\Condition\JsonOverlapsCondition; use Yiisoft\Db\QueryBuilder\Condition\SimpleCondition; use Yiisoft\Db\Schema\Builder\ColumnInterface; use Yiisoft\Db\Schema\QuoterInterface; @@ -1545,6 +1547,57 @@ public function testsCreateConditionFromArray(): void ); } + public function testCreateOverlapsConditionFromArray(): void + { + $db = $this->getConnection(); + $qb = $db->getQueryBuilder(); + + $condition = $qb->createConditionFromArray(['array overlaps', 'column', [1, 2, 3]]); + + $this->assertInstanceOf(ArrayOverlapsCondition::class, $condition); + $this->assertSame('column', $condition->getColumn()); + $this->assertSame([1, 2, 3], $condition->getValues()); + + $condition = $qb->createConditionFromArray(['json overlaps', 'column', [1, 2, 3]]); + + $this->assertInstanceOf(JsonOverlapsCondition::class, $condition); + $this->assertSame('column', $condition->getColumn()); + $this->assertSame([1, 2, 3], $condition->getValues()); + } + + public function testCreateOverlapsConditionFromArrayWithInvalidOperandsCount(): void + { + $db = $this->getConnection(); + $qb = $db->getQueryBuilder(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Operator "JSON OVERLAPS" requires three operands.'); + + $qb->createConditionFromArray(['json overlaps', 'column']); + } + + public function testCreateOverlapsConditionFromArrayWithInvalidColumn(): void + { + $db = $this->getConnection(); + $qb = $db->getQueryBuilder(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Operator "JSON OVERLAPS" requires column to be string or ExpressionInterface.'); + + $qb->createConditionFromArray(['json overlaps', ['column'], [1, 2, 3]]); + } + + public function testCreateOverlapsConditionFromArrayWithInvalidValues(): void + { + $db = $this->getConnection(); + $qb = $db->getQueryBuilder(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Operator "JSON OVERLAPS" requires values to be iterable or ExpressionInterface.'); + + $qb->createConditionFromArray(['json overlaps', 'column', 1]); + } + /** * @dataProvider \Yiisoft\Db\Tests\Provider\QueryBuilderProvider::createIndex */ From a7597292c849d0bc40cd3cbe7cdbd842414b21a3 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sat, 29 Jun 2024 17:11:30 +0700 Subject: [PATCH 06/10] Add line to CHANGELOG.md [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e751ee24..4a919bbce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - Chg #846: Remove `SchemaInterface::isReadQuery()` and `AbstractSchema::isReadQuery()` methods (@Tigrov) - Chg #847: Remove `SchemaInterface::getRawTableName()` and `AbstractSchema::getRawTableName()` methods (@Tigrov) - Enh #852: Add method chaining for column classes (@Tigrov) +- Enh #855: Add array and json overlaps conditions (@Tigrov) ## 1.3.0 March 21, 2024 From 4b9ed55d814cd61df5b2f0d2540c68992a2c0700 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sat, 29 Jun 2024 17:42:27 +0700 Subject: [PATCH 07/10] Add doc [skip ci] --- docs/guide/en/query/where.md | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/guide/en/query/where.md b/docs/guide/en/query/where.md index d351cd0de..13877ca01 100644 --- a/docs/guide/en/query/where.md +++ b/docs/guide/en/query/where.md @@ -211,7 +211,7 @@ Similar to the `not like` operator except that `OR` is used to concatenate the ` Requires one operand which must be an instance of `Yiisoft\Db\Query\Query` representing the sub-query. It will build an `EXISTS` (sub-query) expression. -## not exists +### not exists Similar to the `exists` operator and builds a `NOT EXISTS` (sub-query) expression. @@ -237,6 +237,28 @@ $query->where(['=', $column, $value]); // $value is safe, but $column name won't be encoded! ``` +### array overlaps + +Requires two operands: + +- Operator 1 should be a column name of an array type or DB expression representing an array; +- Operator 2 should be an array, iterator or DB expression representing an array. + +Checks if the first array contains at least one element from the second array. Currently supported only by PostgreSQL +and equals to `&&` operator. + +For example, `['array overlaps', 'ids', [1, 2, 3]]` will generate `"ids"::text[] && ARRAY[1,2,3]::text[]`. + +### json overlaps + +Requires two operands: + +- Operator 1 should be a column name of a json type or DB expression representing a json; +- Operator 2 should be an array, iterator or DB expression representing an array. + +Checks if the json contains at least one element from the array. Currently supported only by PostgreSQL, MySQL and +SQLite. + ## Object format Object format is most powerful yet the most complex way to define conditions. @@ -272,10 +294,12 @@ Conversion from operator format into object format is performed according to `Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder::conditionClasses` property that maps operator names to representative class names. -- `AND`, `OR` => `Yiisoft\Db\QueryBuilder\Condition\ConjunctionCondition`. -- `NOT` => `Yiisoft\Db\QueryBuilder\Condition\NotCondition`. -- `IN`, `NOT IN` => `Yiisoft\Db\QueryBuilder\Condition\InCondition`. -- `BETWEEN`, `NOT BETWEEN` => `Yiisoft\Db\QueryBuilder\Condition\BetweenCondition`. +- `AND`, `OR` => `Yiisoft\Db\QueryBuilder\Condition\ConjunctionCondition`; +- `NOT` => `Yiisoft\Db\QueryBuilder\Condition\NotCondition`; +- `IN`, `NOT IN` => `Yiisoft\Db\QueryBuilder\Condition\InCondition`; +- `BETWEEN`, `NOT BETWEEN` => `Yiisoft\Db\QueryBuilder\Condition\BetweenCondition`; +- `ARRAY OVERLAPS` => `Yiisoft\Db\QueryBuilder\Condition\ArrayOverlapsCondition`; +- `JSON OVERLAPS` => `Yiisoft\Db\QueryBuilder\Condition\JsonOverlapsCondition`. ## Appending conditions From a9a82c89a328f6284e654e03a4517e57994b8e1f Mon Sep 17 00:00:00 2001 From: Sergei Tigrov Date: Mon, 1 Jul 2024 16:03:56 +0700 Subject: [PATCH 08/10] Apply suggestions from code review Co-authored-by: Alexander Makarov --- CHANGELOG.md | 2 +- docs/guide/en/query/where.md | 12 ++++++------ .../Condition/AbstractOverlapsCondition.php | 2 +- src/QueryBuilder/Condition/JsonOverlapsCondition.php | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a919bbce..677a5e190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ - Chg #846: Remove `SchemaInterface::isReadQuery()` and `AbstractSchema::isReadQuery()` methods (@Tigrov) - Chg #847: Remove `SchemaInterface::getRawTableName()` and `AbstractSchema::getRawTableName()` methods (@Tigrov) - Enh #852: Add method chaining for column classes (@Tigrov) -- Enh #855: Add array and json overlaps conditions (@Tigrov) +- Enh #855: Add array and JSON overlaps conditions (@Tigrov) ## 1.3.0 March 21, 2024 diff --git a/docs/guide/en/query/where.md b/docs/guide/en/query/where.md index 13877ca01..b73bb366a 100644 --- a/docs/guide/en/query/where.md +++ b/docs/guide/en/query/where.md @@ -241,22 +241,22 @@ $query->where(['=', $column, $value]); Requires two operands: -- Operator 1 should be a column name of an array type or DB expression representing an array; -- Operator 2 should be an array, iterator or DB expression representing an array. +- Operator 1 should be a column name of an array type or DB expression returning an array; +- Operator 2 should be an array, iterator or DB expression returning an array. Checks if the first array contains at least one element from the second array. Currently supported only by PostgreSQL and equals to `&&` operator. For example, `['array overlaps', 'ids', [1, 2, 3]]` will generate `"ids"::text[] && ARRAY[1,2,3]::text[]`. -### json overlaps +### JSON overlaps Requires two operands: -- Operator 1 should be a column name of a json type or DB expression representing a json; -- Operator 2 should be an array, iterator or DB expression representing an array. +- Operator 1 should be a column name of a JSON type or DB expression returning a JSON; +- Operator 2 should be an array, iterator or DB expression returning an array. -Checks if the json contains at least one element from the array. Currently supported only by PostgreSQL, MySQL and +Checks if the JSON contains at least one element from the array. Currently supported only by PostgreSQL, MySQL and SQLite. ## Object format diff --git a/src/QueryBuilder/Condition/AbstractOverlapsCondition.php b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php index 68f2182f3..ffa6e474a 100644 --- a/src/QueryBuilder/Condition/AbstractOverlapsCondition.php +++ b/src/QueryBuilder/Condition/AbstractOverlapsCondition.php @@ -40,7 +40,7 @@ public function getValues(): iterable|ExpressionInterface public static function fromArrayDefinition(string $operator, array $operands): static { if (!isset($operands[0], $operands[1])) { - throw new InvalidArgumentException("Operator \"$operator\" requires three operands."); + throw new InvalidArgumentException("Operator \"$operator\" requires two operands."); } /** @psalm-suppress UnsafeInstantiation */ diff --git a/src/QueryBuilder/Condition/JsonOverlapsCondition.php b/src/QueryBuilder/Condition/JsonOverlapsCondition.php index 16abbc39b..de6a47403 100644 --- a/src/QueryBuilder/Condition/JsonOverlapsCondition.php +++ b/src/QueryBuilder/Condition/JsonOverlapsCondition.php @@ -5,7 +5,7 @@ namespace Yiisoft\Db\QueryBuilder\Condition; /** - * Condition that represents `JSON OVERLAPS` operator and is used to check if a column of json type overlaps an array. + * Condition that represents `JSON OVERLAPS` operator and is used to check if a column of JSON type overlaps an array. */ final class JsonOverlapsCondition extends AbstractOverlapsCondition { From 952395e511aef3e02683ecac2c9a6bbb2e96cb2e Mon Sep 17 00:00:00 2001 From: Tigrov Date: Mon, 1 Jul 2024 16:16:06 +0700 Subject: [PATCH 09/10] Update doc --- docs/guide/en/query/where.md | 12 ++++++------ tests/AbstractQueryBuilderTest.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/guide/en/query/where.md b/docs/guide/en/query/where.md index b73bb366a..a2812097a 100644 --- a/docs/guide/en/query/where.md +++ b/docs/guide/en/query/where.md @@ -239,26 +239,26 @@ $query->where(['=', $column, $value]); ### array overlaps +Checks if the first array contains at least one element from the second array. Currently supported only by PostgreSQL +and equals to `&&` operator. + Requires two operands: - Operator 1 should be a column name of an array type or DB expression returning an array; - Operator 2 should be an array, iterator or DB expression returning an array. -Checks if the first array contains at least one element from the second array. Currently supported only by PostgreSQL -and equals to `&&` operator. - For example, `['array overlaps', 'ids', [1, 2, 3]]` will generate `"ids"::text[] && ARRAY[1,2,3]::text[]`. ### JSON overlaps +Checks if the JSON contains at least one element from the array. Currently supported only by PostgreSQL, MySQL and +SQLite. + Requires two operands: - Operator 1 should be a column name of a JSON type or DB expression returning a JSON; - Operator 2 should be an array, iterator or DB expression returning an array. -Checks if the JSON contains at least one element from the array. Currently supported only by PostgreSQL, MySQL and -SQLite. - ## Object format Object format is most powerful yet the most complex way to define conditions. diff --git a/tests/AbstractQueryBuilderTest.php b/tests/AbstractQueryBuilderTest.php index 45804d30e..647c3a444 100644 --- a/tests/AbstractQueryBuilderTest.php +++ b/tests/AbstractQueryBuilderTest.php @@ -1571,7 +1571,7 @@ public function testCreateOverlapsConditionFromArrayWithInvalidOperandsCount(): $qb = $db->getQueryBuilder(); $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Operator "JSON OVERLAPS" requires three operands.'); + $this->expectExceptionMessage('Operator "JSON OVERLAPS" requires two operands.'); $qb->createConditionFromArray(['json overlaps', 'column']); } From f5a63c9e1a7dafab90a99f3c031319a324de46f4 Mon Sep 17 00:00:00 2001 From: Tigrov Date: Mon, 1 Jul 2024 16:20:23 +0700 Subject: [PATCH 10/10] Fix doc [skip ci] --- .../Condition/Interface/OverlapsConditionInterface.php | 3 +-- .../Condition/Interface/SimpleConditionInterface.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php b/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php index 3055aec5f..e110a428f 100644 --- a/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php +++ b/src/QueryBuilder/Condition/Interface/OverlapsConditionInterface.php @@ -12,8 +12,7 @@ interface OverlapsConditionInterface extends ConditionInterface { /** - * @return ExpressionInterface|string The column name. If it's an array, a composite `IN` condition will be - * generated. + * @return ExpressionInterface|string The column name or an Expression. */ public function getColumn(): string|ExpressionInterface; diff --git a/src/QueryBuilder/Condition/Interface/SimpleConditionInterface.php b/src/QueryBuilder/Condition/Interface/SimpleConditionInterface.php index c4f1ece92..fb7e9133d 100644 --- a/src/QueryBuilder/Condition/Interface/SimpleConditionInterface.php +++ b/src/QueryBuilder/Condition/Interface/SimpleConditionInterface.php @@ -12,8 +12,7 @@ interface SimpleConditionInterface extends ConditionInterface { /** - * @return ExpressionInterface|string The column name. If it's an array, a composite `IN` condition will be - * generated. + * @return ExpressionInterface|string The column name or an Expression. */ public function getColumn(): string|ExpressionInterface;