diff --git a/README.md b/README.md index 1b8cb8017a6..257ea6eec53 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Available functions: * `ROUND(value, ?precision)` - Rounds the value to the specified precision (defaults to 0 precision if not specified). * `CEIL(value)` - Returns the value rounded up. * `SIGN(expr)` - Returns the sign of the argument. -* `CAST(expr as type)` - Takes an expression of any type and produces a result value of a specified type. Supported types are: `char`, `string`, `text`, `date`, `datetime`, `time`, `int`, `integer`, `bigint`, `decimal`, `boolean`, `binary`. +* `CAST(expr as type)` - Takes an expression of any type and produces a result value of a specified type. Supported types are: `char`, `string`, `text`, `date`, `datetime`, `time`, `int`, `integer`, `bigint`, `decimal`, `boolean`, `binary`, `uuid`. * `CONCAT_WS` - Concatenate all but the first argument. The first argument is used as the separator string. * `GROUP_CONCAT` - Returns a concatenated string. GROUP_CONCAT full syntax: ``` diff --git a/composer.json b/composer.json index 98a978e4203..b2fe7209735 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,9 @@ "phpunit/phpunit": "9.*", "doctrine/data-fixtures": "^1.3", "symfony/yaml": "5.*", + "symfony/cache": "5.*", "squizlabs/php_codesniffer": "3.5.*", - "doctrine/annotations": ">1.0, <2.0", - "symfony/cache": ">=v5.0.0" + "doctrine/annotations": ">1.0, <2.0" }, "autoload": { "psr-4": { diff --git a/src/Oro/ORM/Query/AST/Functions/Cast.php b/src/Oro/ORM/Query/AST/Functions/Cast.php index e161b418c14..fdd26b6572a 100644 --- a/src/Oro/ORM/Query/AST/Functions/Cast.php +++ b/src/Oro/ORM/Query/AST/Functions/Cast.php @@ -26,7 +26,8 @@ class Cast extends AbstractPlatformAwareFunctionNode 'json', 'bool', 'boolean', - 'binary' + 'binary', + 'uuid' ]; public function parse(Parser $parser) diff --git a/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php b/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php index 6b2f4685197..db7e2eeb822 100644 --- a/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php +++ b/src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php @@ -16,11 +16,15 @@ public function getSql(SqlWalker $sqlWalker): string $value = $this->parameters[DqlFunction::PARAMETER_KEY]; $type = $this->parameters[DqlFunction::TYPE_KEY]; + if ($type === 'json' && !$sqlWalker->getConnection()->getDatabasePlatform()->hasNativeJsonType()) { + $type = 'text'; + } + $type = \strtolower($type); $isBoolean = $type === 'bool' || $type === 'boolean'; if ($type === 'char') { $type = 'char(1)'; - } elseif ($type === 'string' || $type === 'text' || $type === 'json') { + } elseif ($type === 'string' || $type === 'text' || $type === 'uuid') { $type = 'char'; } elseif ($type === 'int' || $type === 'integer' || $isBoolean) { $type = 'signed'; diff --git a/tests/Oro/Tests/DBAL/Types/PercentTypeTest.php b/tests/Oro/Tests/DBAL/Types/PercentTypeTest.php index a49af471769..8959aff25f3 100644 --- a/tests/Oro/Tests/DBAL/Types/PercentTypeTest.php +++ b/tests/Oro/Tests/DBAL/Types/PercentTypeTest.php @@ -5,7 +5,6 @@ use Doctrine\DBAL\Exception; use Doctrine\DBAL\Types\Type; - use Doctrine\ORM\ORMException; use Oro\DBAL\Types\PercentType; use Oro\Tests\Connection\TestUtil; diff --git a/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php b/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php index 6a8366ff75a..6603ec782ea 100644 --- a/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php +++ b/tests/Oro/Tests/ORM/AST/Query/Functions/FunctionsTest.php @@ -5,12 +5,10 @@ use Doctrine\ORM\Configuration; use Doctrine\ORM\Query; - -use PHPUnit\Framework\Constraint\LogicalOr; -use Symfony\Component\Yaml\Yaml; - use Oro\Tests\Connection\TestUtil; use Oro\Tests\TestCase; +use PHPUnit\Framework\Constraint\LogicalOr; +use Symfony\Component\Yaml\Yaml; class FunctionsTest extends TestCase { @@ -65,11 +63,14 @@ public function functionsDataProvider(): array if (!\is_array($fileData)) { throw new \RuntimeException(\sprintf('Could not parse file %s', $file)); } - /** @noinspection SlowArrayOperationsInLoopInspection */ - $data = \array_merge($data, $fileData); + $data[] = $fileData; + } + + if (!$data) { + return []; } - return $data; + return array_merge(...$data); } protected function registerDqlFunction( diff --git a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/cast.yml b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/cast.yml index 56ab3582643..a8f9b20aba5 100644 --- a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/cast.yml +++ b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/cast.yml @@ -31,14 +31,21 @@ #CHAR - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } + dql: "SELECT CAST('56366a57-43fa-4f4e-a0a2-66f87d52b601' as uuid) FROM Oro\\Entities\\Foo f WHERE f.id = 1" + sql: "SELECT CAST('56366a57-43fa-4f4e-a0a2-66f87d52b601' AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" + expectedResult: + - '56366a57-43fa-4f4e-a0a2-66f87d52b601' + +- functions: + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST('12' as char) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('12' AS char(1)) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - 1 - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(f.createdAt as char) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS char(1)) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -46,14 +53,14 @@ #STRING - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(12 as string) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(12 AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - '12' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(f.createdAt as string) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -61,25 +68,25 @@ #TEXT - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(12 as text) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(12 AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - '12' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(f.createdAt as text) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - '2014-01-04 05:06:07' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(CONCAT('{\"a\":', f.id, '}') as json) FROM Oro\\Entities\\Foo f WHERE f.id = 1" - sql: "SELECT CAST(CONCAT('{\\\"a\\\":', t0_.id, '}') AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" + sql: "SELECT CAST(CONCAT('{\\\"a\\\":', t0_.id, '}') AS json) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - - '{"a":1}' + - '{"a": 1}' #DECIMAL - functions: @@ -98,7 +105,7 @@ #DATE - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST('2014-01-02 12:13:14' as date) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('2014-01-02 12:13:14' AS date) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -106,7 +113,7 @@ #TIME - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST('2014-01-02 12:13:14' as time) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('2014-01-02 12:13:14' AS time) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -114,14 +121,14 @@ #DATETIME - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "datetime" } dql: "SELECT CAST('2014-01-02 12:13:14' as datetime) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('2014-01-02 12:13:14' AS datetime) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - '2014-01-02 12:13:14' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "datetime" } dql: "SELECT CAST(f.createdAt as datetime) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS datetime) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: diff --git a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/timestampdiff.yml b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/timestampdiff.yml index 13c129749b6..85862a352ce 100644 --- a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/timestampdiff.yml +++ b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/mysql/timestampdiff.yml @@ -116,4 +116,3 @@ sql: SELECT TIMESTAMPDIFF(YEAR, '2016-01-01 00:00:01', '2017-01-01 00:00:00') AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1 expectedResult: - 0 - diff --git a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml index 19c8f641a97..fb86b9ce724 100644 --- a/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml +++ b/tests/Oro/Tests/ORM/AST/Query/Functions/fixtures/postgresql/cast.yml @@ -31,14 +31,21 @@ #CHAR - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } + dql: "SELECT CAST('56366a57-43fa-4f4e-a0a2-66f87d52b601' as uuid) FROM Oro\\Entities\\Foo f WHERE f.id = 1" + sql: "SELECT CAST('56366a57-43fa-4f4e-a0a2-66f87d52b601' AS uuid) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" + expectedResult: + - '56366a57-43fa-4f4e-a0a2-66f87d52b601' + +- functions: + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST('12' as char) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('12' AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - 1 - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(f.createdAt as char) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS char) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -46,14 +53,14 @@ #STRING - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(12 as string) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(12 AS varchar) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - '12' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(f.createdAt as string) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS varchar) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -61,14 +68,14 @@ #TEXT - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(12 as text) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(12 AS text) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: - '12' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST(f.createdAt as text) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST(t0_.created_at AS text) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -100,7 +107,7 @@ #DATE - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST('2014-01-02 12:13:14' as date) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('2014-01-02 12:13:14' AS date) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -108,7 +115,7 @@ #TIME - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "string" } dql: "SELECT CAST('2014-01-02 12:13:14' as time) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: "SELECT CAST('2014-01-02 12:13:14' AS time) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1" expectedResult: @@ -116,14 +123,14 @@ #DATETIME - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "datetime" } dql: "SELECT CAST('2014-01-02 12:13:14' as datetime) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: SELECT "timestamp"('2014-01-02 12:13:14') AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1 expectedResult: - '2014-01-02 12:13:14' - functions: - - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "numeric" } + - { name: "cast", className: "Oro\\ORM\\Query\\AST\\Functions\\Cast", type: "datetime" } dql: "SELECT CAST(f.createdAt as datetime) FROM Oro\\Entities\\Foo f WHERE f.id = 1" sql: SELECT "timestamp"(t0_.created_at) AS sclr_0 FROM test_foo t0_ WHERE t0_.id = 1 expectedResult: