diff --git a/CHANGELOG.md b/CHANGELOG.md index fb4d1dd..d8c25cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,7 @@ - Enh #350: Adapt to `Like` changes in `yiisoft/db` package (@vjik) - Enh #352: Support column's collation (@Tigrov) - New #358: Add `Connection::getColumnBuilderClass()` method (@Tigrov) -- New #357: Implement `ArrayMergeBuilder`, `LongestBuilder` and `ShortestBuilder` classes (@Tigrov) +- New #357, #363: Implement `ArrayMergeBuilder`, `LongestBuilder` and `ShortestBuilder` classes (@Tigrov) - Enh #360: Refactor `DMLQueryBuilder::upsert()` method (@Tigrov) ## 1.3.0 March 21, 2024 diff --git a/src/Builder/ArrayMergeBuilder.php b/src/Builder/ArrayMergeBuilder.php index 22883d1..d877fff 100644 --- a/src/Builder/ArrayMergeBuilder.php +++ b/src/Builder/ArrayMergeBuilder.php @@ -49,7 +49,10 @@ protected function buildFromExpression(MultiOperandFunction $expression, array & $selects[] = "SELECT value FROM JSON_TABLE($builtOperand, '$[*]' COLUMNS(value $operandType PATH '$'))"; } - return '(SELECT JSON_ARRAYAGG(value) AS value FROM (' . implode(' UNION ', $selects) . '))'; + $orderBy = $expression->getOrdered() ? ' ORDER BY value' : ''; + $unions = implode(' UNION ', $selects); + + return "(SELECT JSON_ARRAYAGG(value$orderBy) AS value FROM ($unions))"; } private function buildOperandType(string|ColumnInterface $type): string diff --git a/src/Column/DateTimeColumn.php b/src/Column/DateTimeColumn.php index d33a680..26bf497 100644 --- a/src/Column/DateTimeColumn.php +++ b/src/Column/DateTimeColumn.php @@ -31,7 +31,7 @@ */ final class DateTimeColumn extends \Yiisoft\Db\Schema\Column\DateTimeColumn { - public function dbTypecast(mixed $value): string|ExpressionInterface|null + public function dbTypecast(mixed $value): float|int|string|ExpressionInterface|null { $value = parent::dbTypecast($value); diff --git a/tests/QueryBuilderTest.php b/tests/QueryBuilderTest.php index d9174f8..974a8da 100644 --- a/tests/QueryBuilderTest.php +++ b/tests/QueryBuilderTest.php @@ -26,11 +26,6 @@ use Yiisoft\Db\Tests\Common\CommonQueryBuilderTest; use Yiisoft\Db\Tests\Support\Assert; -use function json_decode; -use function sort; - -use const SORT_NUMERIC; - /** * @group oracle */ @@ -622,9 +617,9 @@ public function testMultiOperandFunctionBuilderWithoutOperands(string $class): v #[TestWith(['int[]', 'int', '[1,2,3,4,5,6,7,9,10]'])] #[TestWith([new IntegerColumn(), 'number(10)', '[1,2,3,4,5,6,7,9,10]'])] - #[TestWith([new ArrayColumn(), '', '["1","2","3","4","5","6","7","9","10"]'])] + #[TestWith([new ArrayColumn(), '', '["1","10","2","3","4","5","6","7","9"]'])] #[TestWith([new ArrayColumn(column: new IntegerColumn()), 'number(10)', '[1,2,3,4,5,6,7,9,10]'])] - public function testMultiOperandFunctionBuilderWithType( + public function testArrayMergeWithTypeWithOrdering( string|ColumnInterface $type, string $operandType, string $expectedResult, @@ -632,18 +627,18 @@ public function testMultiOperandFunctionBuilderWithType( $db = $this->getConnection(); $qb = $db->getQueryBuilder(); - $stringParam = new Param('[3,4,5]', DataType::STRING); + $stringParam = new Param('[4,3,5]', DataType::STRING); $arrayMerge = (new ArrayMerge( - "'[1,2,3]'", - [5, 6, 7], + "'[2,1,3]'", + [6, 5, 7], $stringParam, - self::getDb()->select(new ArrayExpression([9, 10])), - ))->type($type); + self::getDb()->select(new ArrayExpression([10, 9])), + ))->type($type)->ordered(); $params = []; $this->assertSame( - '(SELECT JSON_ARRAYAGG(value) AS value FROM (' - . "SELECT value FROM JSON_TABLE('[1,2,3]', '$[*]' COLUMNS(value $operandType PATH '$'))" + '(SELECT JSON_ARRAYAGG(value ORDER BY value) AS value FROM (' + . "SELECT value FROM JSON_TABLE('[2,1,3]', '$[*]' COLUMNS(value $operandType PATH '$'))" . " UNION SELECT value FROM JSON_TABLE(:qp0, '$[*]' COLUMNS(value $operandType PATH '$'))" . " UNION SELECT value FROM JSON_TABLE(:qp1, '$[*]' COLUMNS(value $operandType PATH '$'))" . " UNION SELECT value FROM JSON_TABLE((SELECT :qp2 FROM DUAL), '$[*]' COLUMNS(value $operandType PATH '$'))" @@ -652,17 +647,14 @@ public function testMultiOperandFunctionBuilderWithType( ); Assert::arraysEquals( [ - ':qp0' => new Param('[5,6,7]', DataType::STRING), + ':qp0' => new Param('[6,5,7]', DataType::STRING), ':qp1' => $stringParam, - ':qp2' => new Param('[9,10]', DataType::STRING), + ':qp2' => new Param('[10,9]', DataType::STRING), ], $params, ); $result = $db->select($arrayMerge)->scalar(); - $result = json_decode($result); - sort($result, SORT_NUMERIC); - $expectedResult = json_decode($expectedResult); $this->assertSame($expectedResult, $result); }