From 874d68696485d083ded4d8e03c5d9bd89ed87ad2 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Wed, 21 May 2025 18:29:04 +0100 Subject: [PATCH 01/12] chore: test functions against a real PostgreSQL server --- .../ORM/Query/AST/Functions/JsonTestCase.php | 8 +- .../ORM/Query/AST/Functions/JsonbAggTest.php | 30 +------ .../AST/Functions/JsonbArrayElementsTest.php | 39 +++++++++ .../Functions/JsonbArrayElementsTextTest.php | 39 +++++++++ .../Query/AST/Functions/JsonbInsertTest.php | 70 ++++++++++++++++ .../AST/Functions/JsonbObjectAggTest.php | 29 +++++++ .../AST/Functions/JsonbObjectKeysTest.php | 26 ++++++ .../AST/Functions/JsonbPathQueryArrayTest.php | 79 +++++++++++++++++++ .../AST/Functions/JsonbPathQueryFirstTest.php | 78 ++++++++++++++++++ .../AST/Functions/JsonbPathQueryTest.php | 74 +++++++++++++++++ .../Query/AST/Functions/JsonbPrettyTest.php | 26 ++++++ .../Query/AST/Functions/JsonbSetLaxTest.php | 73 +++++++++++++++++ .../ORM/Query/AST/Functions/JsonbSetTest.php | 73 +++++++++++++++++ .../AST/Functions/JsonbStripNullsTest.php | 37 +++++++++ 14 files changed, 653 insertions(+), 28 deletions(-) create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectAggTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectKeysTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPrettyTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbStripNullsTest.php diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonTestCase.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonTestCase.php index f1965cd7..cad26d6d 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonTestCase.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonTestCase.php @@ -39,12 +39,18 @@ protected function insertTestDataForJsonFixture(): void { $json1 = '{"name": "John", "age": 30, "tags": ["developer", "manager"], "address": {"city": "New York"}}'; $json2 = '{"name": "Jane", "age": 25, "tags": ["designer"], "address": {"city": "Boston"}}'; + $json3 = '{"name": "Micky", "age": 30, "tags": [], "address": {"city": "New York"}}'; + $json4 = '{}'; + $json5 = '{"name": "John", "age": null, "tags": ["developer"], "address": {"city": "New York", "zip": null}}'; $sql = \sprintf(' INSERT INTO %s.containsjsons (object1, object2) VALUES (\'%s\', \'%s\'), + (\'%s\', \'%s\'), + (\'%s\', \'%s\'), + (\'%s\', \'%s\'), (\'%s\', \'%s\') - ', self::DATABASE_SCHEMA, $json1, $json1, $json2, $json2); + ', self::DATABASE_SCHEMA, $json1, $json1, $json2, $json2, $json3, $json3, $json4, $json4, $json5, $json5); $this->connection->executeStatement($sql); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php index b452e73d..8e51cbe9 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php @@ -31,35 +31,11 @@ public function test_jsonb_agg_with_single_row(): void $this->assertEqualsCanonicalizing($expected, $actual); } - public function test_jsonb_agg_with_all_rows(): void + public function test_jsonb_agg_with_multiple_rows(): void { $dql = 'SELECT JSONB_AGG(t.object1) as result - FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t'; - $result = $this->executeDqlQuery($dql); - $this->assertIsString($result[0]['result']); - $actual = \json_decode($result[0]['result'], true); - $this->assertIsArray($actual); - $expected = [ - [ - 'name' => 'John', - 'age' => 30, - 'tags' => ['developer', 'manager'], - 'address' => ['city' => 'New York'], - ], - [ - 'name' => 'Jane', - 'age' => 25, - 'tags' => ['designer'], - 'address' => ['city' => 'Boston'], - ], - ]; - $this->assertEqualsCanonicalizing($expected, $actual); - } - - public function test_jsonb_agg_with_object2_column(): void - { - $dql = 'SELECT JSONB_AGG(t.object2) as result - FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t'; + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id IN (1, 2)'; $result = $this->executeDqlQuery($dql); $this->assertIsString($result[0]['result']); $actual = \json_decode($result[0]['result'], true); diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php new file mode 100644 index 00000000..5a76f2a2 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php @@ -0,0 +1,39 @@ + JsonbArrayElements::class, + ]; + } + + public function test_jsonb_array_elements(): void + { + $dql = 'SELECT JSONB_ARRAY_ELEMENTS(t.object1) as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertCount(2, $result); + $this->assertSame('"developer"', $result[0]['result']); + $this->assertSame('"manager"', $result[1]['result']); + } + + public function test_jsonb_array_elements_with_empty_array(): void + { + $dql = 'SELECT JSONB_ARRAY_ELEMENTS(t.object1) as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 3'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertCount(0, $result); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php new file mode 100644 index 00000000..f72008cf --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php @@ -0,0 +1,39 @@ + JsonbArrayElementsText::class, + ]; + } + + public function test_jsonb_array_elements_text(): void + { + $dql = 'SELECT JSONB_ARRAY_ELEMENTS_TEXT(t.object1) as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertCount(2, $result); + $this->assertSame('developer', $result[0]['result']); + $this->assertSame('manager', $result[1]['result']); + } + + public function test_jsonb_array_elements_text_with_empty_array(): void + { + $dql = 'SELECT JSONB_ARRAY_ELEMENTS_TEXT(t.object1) as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 3'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertCount(0, $result); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php new file mode 100644 index 00000000..c47e88b3 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php @@ -0,0 +1,70 @@ + JsonbInsert::class, + ]; + } + + public function test_jsonb_insert_new_value(): void + { + $dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{email}', + 'value' => '"john@example.com"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('john@example.com', $decoded['email']); + } + + public function test_jsonb_insert_nested_path(): void + { + $dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{address,zip}', + 'value' => '"10001"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('10001', $decoded['address']['zip']); + } + + public function test_jsonb_insert_existing_path(): void + { + $this->expectException(Exception::class); + $dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $this->executeDqlQuery($dql, [ + 'path' => '{name}', + 'value' => '"John Doe"', + ]); + } + + public function test_jsonb_insert_with_insert_if_missing_true(): void + { + $this->expectException(Exception::class); + $dql = "SELECT JSONB_INSERT(t.object1, :path, :value, 'true') as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 1"; + $this->executeDqlQuery($dql, [ + 'path' => '{name}', + 'value' => '"John Doe"', + ]); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectAggTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectAggTest.php new file mode 100644 index 00000000..2c3bc35e --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectAggTest.php @@ -0,0 +1,29 @@ + JsonbObjectAgg::class, + ]; + } + + public function test_jsonb_object_agg(): void + { + $dql = "SELECT JSONB_OBJECT_AGG('key', 'value') as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertSame(['key' => 'value'], $decoded); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectKeysTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectKeysTest.php new file mode 100644 index 00000000..b37f4b28 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbObjectKeysTest.php @@ -0,0 +1,26 @@ + JsonbObjectKeys::class, + ]; + } + + public function test_jsonb_object_keys(): void + { + $dql = 'SELECT JSONB_OBJECT_KEYS(t.object1) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsString($result[0]['result']); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php new file mode 100644 index 00000000..311ecb34 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryArrayTest.php @@ -0,0 +1,79 @@ + JsonbPathQueryArray::class, + ]; + } + + public function test_jsonb_path_query_array_simple(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_ARRAY(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"a": 1, "b": 2}', + 'path' => '$.b', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertCount(1, $decoded); + $this->assertSame(2, $decoded[0]); + } + + public function test_jsonb_path_query_array_multiple_values(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_ARRAY(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [1, 2, 3]}', + 'path' => '$.items[*]', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertCount(3, $decoded); + $this->assertSame([1, 2, 3], $decoded); + } + + public function test_jsonb_path_query_array_with_filter(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_ARRAY(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [{"id": 1}, {"id": 2}, {"id": 3}]}', + 'path' => '$.items[*] ? (@.id > 1)', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertCount(2, $decoded); + $this->assertSame(['id' => 2], $decoded[0]); + $this->assertSame(['id' => 3], $decoded[1]); + } + + public function test_jsonb_path_query_array_with_column_reference(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_ARRAY(t.object1, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, ['path' => '$.tags[*]']); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertCount(2, $decoded); + $this->assertSame(['developer', 'manager'], $decoded); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php new file mode 100644 index 00000000..fd69f09b --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryFirstTest.php @@ -0,0 +1,78 @@ + JsonbPathQueryFirst::class, + ]; + } + + public function test_jsonb_path_query_first_simple(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"a": 1, "b": 2}', + 'path' => '$.b', + ]); + $this->assertIsString($result[0]['result']); + $this->assertSame('2', $result[0]['result']); + } + + public function test_jsonb_path_query_first_array(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [1, 2, 3]}', + 'path' => '$.items[*]', + ]); + $this->assertIsString($result[0]['result']); + $this->assertSame('1', $result[0]['result']); + } + + public function test_jsonb_path_query_first_with_filter(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [{"id": 1}, {"id": 2}, {"id": 3}]}', + 'path' => '$.items[*] ? (@.id > 1)', + ]); + $this->assertIsString($result[0]['result']); + $this->assertSame('{"id": 2}', $result[0]['result']); + } + + public function test_jsonb_path_query_first_with_no_match(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [{"id": 1}]}', + 'path' => '$.items[*] ? (@.id > 1)', + ]); + $this->assertNull($result[0]['result']); + } + + public function test_jsonb_path_query_first_with_column_reference(): void + { + $dql = 'SELECT JSONB_PATH_QUERY_FIRST(t.object1, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, ['path' => '$.tags[*]']); + $this->assertIsString($result[0]['result']); + $this->assertSame('"developer"', $result[0]['result']); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php new file mode 100644 index 00000000..1f02dd1d --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPathQueryTest.php @@ -0,0 +1,74 @@ + JsonbPathQuery::class, + ]; + } + + public function test_jsonb_path_query_simple(): void + { + $dql = 'SELECT JSONB_PATH_QUERY(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"a": 1, "b": 2}', + 'path' => '$.b', + ]); + $this->assertIsArray($result); + $this->assertCount(1, $result); + $this->assertSame('2', $result[0]['result']); + } + + public function test_jsonb_path_query_array(): void + { + $dql = 'SELECT JSONB_PATH_QUERY(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [1, 2, 3]}', + 'path' => '$.items[*]', + ]); + $this->assertIsArray($result); + $this->assertCount(3, $result); + $this->assertSame('1', $result[0]['result']); + $this->assertSame('2', $result[1]['result']); + $this->assertSame('3', $result[2]['result']); + } + + public function test_jsonb_path_query_with_filter(): void + { + $dql = 'SELECT JSONB_PATH_QUERY(:json, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'json' => '{"items": [{"id": 1}, {"id": 2}, {"id": 3}]}', + 'path' => '$.items[*] ? (@.id > 1)', + ]); + $this->assertIsArray($result); + $this->assertCount(2, $result); + $this->assertSame('{"id": 2}', $result[0]['result']); + $this->assertSame('{"id": 3}', $result[1]['result']); + } + + public function test_jsonb_path_query_with_column_reference(): void + { + $dql = 'SELECT JSONB_PATH_QUERY(t.object1, :path) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, ['path' => '$.tags[*]']); + $this->assertIsArray($result); + $this->assertCount(2, $result); + $this->assertSame('"developer"', $result[0]['result']); + $this->assertSame('"manager"', $result[1]['result']); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPrettyTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPrettyTest.php new file mode 100644 index 00000000..d6c1e611 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbPrettyTest.php @@ -0,0 +1,26 @@ + JsonbPretty::class, + ]; + } + + public function test_jsonb_pretty(): void + { + $dql = 'SELECT JSONB_PRETTY(t.object1) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsString($result[0]['result']); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php new file mode 100644 index 00000000..b38f2b6e --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php @@ -0,0 +1,73 @@ + JsonbSetLax::class, + ]; + } + + public function test_jsonb_set_lax_update_existing_value(): void + { + $dql = 'SELECT JSONB_SET_LAX(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{name}', + 'value' => '"John Doe"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('John Doe', $decoded['name']); + } + + public function test_jsonb_set_lax_add_new_value(): void + { + $dql = 'SELECT JSONB_SET_LAX(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{email}', + 'value' => '"john@example.com"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('john@example.com', $decoded['email']); + } + + public function test_jsonb_set_lax_nested_path(): void + { + $dql = 'SELECT JSONB_SET_LAX(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{address,zip}', + 'value' => '"10001"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('10001', $decoded['address']['zip']); + } + + public function test_jsonb_set_lax_with_invalid_path(): void + { + $dql = 'SELECT JSONB_SET_LAX(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{invalid,path}', + 'value' => '"value"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertArrayNotHasKey('invalid', $decoded); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php new file mode 100644 index 00000000..6e5c6993 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php @@ -0,0 +1,73 @@ + JsonbSet::class, + ]; + } + + public function test_jsonb_set_update_existing_value(): void + { + $dql = 'SELECT JSONB_SET(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{name}', + 'value' => '"John Doe"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('John Doe', $decoded['name']); + } + + public function test_jsonb_set_add_new_value(): void + { + $dql = 'SELECT JSONB_SET(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{email}', + 'value' => '"john@example.com"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('john@example.com', $decoded['email']); + } + + public function test_jsonb_set_nested_path(): void + { + $dql = 'SELECT JSONB_SET(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{address,zip}', + 'value' => '"10001"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertSame('10001', $decoded['address']['zip']); + } + + public function test_jsonb_set_with_create_missing_false(): void + { + $dql = "SELECT JSONB_SET(t.object1, :path, :value, 'false') as result + FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t + WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql, [ + 'path' => '{nonexistent}', + 'value' => '"value"', + ]); + $this->assertIsString($result[0]['result']); + $decoded = \json_decode($result[0]['result'], true); + $this->assertArrayNotHasKey('nonexistent', $decoded); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbStripNullsTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbStripNullsTest.php new file mode 100644 index 00000000..68be7955 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbStripNullsTest.php @@ -0,0 +1,37 @@ + JsonbStripNulls::class, + ]; + } + + public function test_jsonb_strip_nulls(): void + { + $dql = 'SELECT JSONB_STRIP_NULLS(t.object1) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsString($result[0]['result']); + } + + public function test_jsonb_strip_nulls_with_null_values(): void + { + $dql = 'SELECT JSONB_STRIP_NULLS(t.object1) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 5'; + $result = $this->executeDqlQuery($dql); + $this->assertIsString($result[0]['result']); + $this->assertStringNotContainsString('"age": null', $result[0]['result']); + $this->assertStringNotContainsString('"zip": null', $result[0]['result']); + } +} From 0924b2627eeb6d351dd581aacf0c62c0a558059f Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Wed, 21 May 2025 18:34:04 +0100 Subject: [PATCH 02/12] no message --- .../AST/Functions/JsonbArrayElementsTest.php | 39 ------------------- .../Functions/JsonbArrayElementsTextTest.php | 39 ------------------- .../Query/AST/Functions/JsonbInsertTest.php | 6 +++ .../Query/AST/Functions/JsonbSetLaxTest.php | 11 +++++- .../ORM/Query/AST/Functions/JsonbSetTest.php | 11 +++++- 5 files changed, 26 insertions(+), 80 deletions(-) delete mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php delete mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php deleted file mode 100644 index 5a76f2a2..00000000 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTest.php +++ /dev/null @@ -1,39 +0,0 @@ - JsonbArrayElements::class, - ]; - } - - public function test_jsonb_array_elements(): void - { - $dql = 'SELECT JSONB_ARRAY_ELEMENTS(t.object1) as result - FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t - WHERE t.id = 1'; - $result = $this->executeDqlQuery($dql); - $this->assertIsArray($result); - $this->assertCount(2, $result); - $this->assertSame('"developer"', $result[0]['result']); - $this->assertSame('"manager"', $result[1]['result']); - } - - public function test_jsonb_array_elements_with_empty_array(): void - { - $dql = 'SELECT JSONB_ARRAY_ELEMENTS(t.object1) as result - FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t - WHERE t.id = 3'; - $result = $this->executeDqlQuery($dql); - $this->assertIsArray($result); - $this->assertCount(0, $result); - } -} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php deleted file mode 100644 index f72008cf..00000000 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbArrayElementsTextTest.php +++ /dev/null @@ -1,39 +0,0 @@ - JsonbArrayElementsText::class, - ]; - } - - public function test_jsonb_array_elements_text(): void - { - $dql = 'SELECT JSONB_ARRAY_ELEMENTS_TEXT(t.object1) as result - FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t - WHERE t.id = 1'; - $result = $this->executeDqlQuery($dql); - $this->assertIsArray($result); - $this->assertCount(2, $result); - $this->assertSame('developer', $result[0]['result']); - $this->assertSame('manager', $result[1]['result']); - } - - public function test_jsonb_array_elements_text_with_empty_array(): void - { - $dql = 'SELECT JSONB_ARRAY_ELEMENTS_TEXT(t.object1) as result - FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t - WHERE t.id = 3'; - $result = $this->executeDqlQuery($dql); - $this->assertIsArray($result); - $this->assertCount(0, $result); - } -} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php index c47e88b3..773f989b 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php @@ -27,6 +27,8 @@ public function test_jsonb_insert_new_value(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('email', $decoded); $this->assertSame('john@example.com', $decoded['email']); } @@ -41,6 +43,10 @@ public function test_jsonb_insert_nested_path(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('address', $decoded); + $this->assertIsArray($decoded['address']); + $this->assertArrayHasKey('zip', $decoded['address']); $this->assertSame('10001', $decoded['address']['zip']); } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php index b38f2b6e..59229340 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetLaxTest.php @@ -26,6 +26,8 @@ public function test_jsonb_set_lax_update_existing_value(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('name', $decoded); $this->assertSame('John Doe', $decoded['name']); } @@ -40,6 +42,8 @@ public function test_jsonb_set_lax_add_new_value(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('email', $decoded); $this->assertSame('john@example.com', $decoded['email']); } @@ -54,6 +58,10 @@ public function test_jsonb_set_lax_nested_path(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('address', $decoded); + $this->assertIsArray($decoded['address']); + $this->assertArrayHasKey('zip', $decoded['address']); $this->assertSame('10001', $decoded['address']['zip']); } @@ -68,6 +76,7 @@ public function test_jsonb_set_lax_with_invalid_path(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); - $this->assertArrayNotHasKey('invalid', $decoded); + $this->assertIsArray($decoded); + self::assertArrayNotHasKey('invalid', $decoded); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php index 6e5c6993..c1268666 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbSetTest.php @@ -26,6 +26,8 @@ public function test_jsonb_set_update_existing_value(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('name', $decoded); $this->assertSame('John Doe', $decoded['name']); } @@ -40,6 +42,8 @@ public function test_jsonb_set_add_new_value(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('email', $decoded); $this->assertSame('john@example.com', $decoded['email']); } @@ -54,6 +58,10 @@ public function test_jsonb_set_nested_path(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); + $this->assertIsArray($decoded); + $this->assertArrayHasKey('address', $decoded); + $this->assertIsArray($decoded['address']); + $this->assertArrayHasKey('zip', $decoded['address']); $this->assertSame('10001', $decoded['address']['zip']); } @@ -68,6 +76,7 @@ public function test_jsonb_set_with_create_missing_false(): void ]); $this->assertIsString($result[0]['result']); $decoded = \json_decode($result[0]['result'], true); - $this->assertArrayNotHasKey('nonexistent', $decoded); + $this->assertIsArray($decoded); + self::assertArrayNotHasKey('nonexistent', $decoded); } } From ec954a5af8ab5cf5152f79f3da2af4556ec5385e Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Wed, 21 May 2025 19:12:29 +0100 Subject: [PATCH 03/12] no message --- .../ORM/Query/AST/Functions/JsonbInsertTest.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php index 773f989b..2b99b909 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php @@ -50,7 +50,7 @@ public function test_jsonb_insert_nested_path(): void $this->assertSame('10001', $decoded['address']['zip']); } - public function test_jsonb_insert_existing_path(): void + public function test_throws_exception_when_inserting_at_existing_object_key(): void { $this->expectException(Exception::class); $dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result @@ -62,15 +62,17 @@ public function test_jsonb_insert_existing_path(): void ]); } - public function test_jsonb_insert_with_insert_if_missing_true(): void + public function test_throws_exception_when_inserting_at_existing_nested_path(): void { $this->expectException(Exception::class); - $dql = "SELECT JSONB_INSERT(t.object1, :path, :value, 'true') as result - FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t - WHERE t.id = 1"; + + $dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result + FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t + WHERE t.id = 5'; + $this->executeDqlQuery($dql, [ - 'path' => '{name}', - 'value' => '"John Doe"', + 'path' => '{address,zip}', + 'value' => '"10001"', ]); } } From 8b2bdee709fd9a5e5f50a508d24292c37384144b Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Wed, 21 May 2025 19:22:40 +0100 Subject: [PATCH 04/12] no message --- .../Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php index 2b99b909..537ff017 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbInsertTest.php @@ -71,7 +71,7 @@ public function test_throws_exception_when_inserting_at_existing_nested_path(): WHERE t.id = 5'; $this->executeDqlQuery($dql, [ - 'path' => '{address,zip}', + 'path' => '{address,zip}', 'value' => '"10001"', ]); } From 255144dc8f2c58aa2729006062e65c9720598e31 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 00:02:46 +0100 Subject: [PATCH 05/12] feat: add support for specifying explicit range bounds --- .../ORM/Query/AST/Functions/Daterange.php | 26 +++++++++++++++---- .../ORM/Query/AST/Functions/Int4range.php | 26 +++++++++++++++---- .../ORM/Query/AST/Functions/Int8range.php | 26 +++++++++++++++---- .../ORM/Query/AST/Functions/Numrange.php | 26 +++++++++++++++---- .../ORM/Query/AST/Functions/Tsrange.php | 26 +++++++++++++++---- .../ORM/Query/AST/Functions/Tstzrange.php | 26 +++++++++++++++---- .../ORM/Query/AST/Functions/DaterangeTest.php | 6 +++-- .../ORM/Query/AST/Functions/Int4rangeTest.php | 6 +++-- .../ORM/Query/AST/Functions/Int8rangeTest.php | 6 +++-- .../ORM/Query/AST/Functions/NumrangeTest.php | 6 +++-- .../ORM/Query/AST/Functions/TsrangeTest.php | 6 +++-- .../ORM/Query/AST/Functions/TstzrangeTest.php | 6 +++-- 12 files changed, 150 insertions(+), 42 deletions(-) diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Daterange.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Daterange.php index a6c1c1de..fc7472f6 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Daterange.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Daterange.php @@ -12,12 +12,28 @@ * * @author Martin Georgiev */ -class Daterange extends BaseFunction +class Daterange extends BaseVariadicFunction { - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('daterange(%s, %s)'); - $this->addNodeMapping('StringPrimary'); - $this->addNodeMapping('StringPrimary'); + return 'daterange'; + } + + /** + * @return array + */ + protected function getNodeMappingPattern(): array + { + return ['StringPrimary']; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4range.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4range.php index 914acc27..0640aafe 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4range.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4range.php @@ -12,12 +12,28 @@ * * @author Martin Georgiev */ -class Int4range extends BaseFunction +class Int4range extends BaseVariadicFunction { - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('int4range(%s, %s)'); - $this->addNodeMapping('StringPrimary'); - $this->addNodeMapping('StringPrimary'); + return 'int4range'; + } + + /** + * @return array + */ + protected function getNodeMappingPattern(): array + { + return ['StringPrimary']; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8range.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8range.php index 17ff66e4..24ee8f91 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8range.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8range.php @@ -12,12 +12,28 @@ * * @author Martin Georgiev */ -class Int8range extends BaseFunction +class Int8range extends BaseVariadicFunction { - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('int8range(%s, %s)'); - $this->addNodeMapping('StringPrimary'); - $this->addNodeMapping('StringPrimary'); + return 'int8range'; + } + + /** + * @return array + */ + protected function getNodeMappingPattern(): array + { + return ['StringPrimary']; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php index 6c0a22c4..92ccf4b4 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Numrange.php @@ -12,12 +12,28 @@ * * @author Martin Georgiev */ -class Numrange extends BaseFunction +class Numrange extends BaseVariadicFunction { - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('numrange(%s, %s)'); - $this->addNodeMapping('StringPrimary'); - $this->addNodeMapping('StringPrimary'); + return 'numrange'; + } + + /** + * @return array + */ + protected function getNodeMappingPattern(): array + { + return ['StringPrimary']; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tsrange.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tsrange.php index 5e2e2b33..2cfd5c8d 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tsrange.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tsrange.php @@ -12,12 +12,28 @@ * * @author Martin Georgiev */ -class Tsrange extends BaseFunction +class Tsrange extends BaseVariadicFunction { - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('tsrange(%s, %s)'); - $this->addNodeMapping('StringPrimary'); - $this->addNodeMapping('StringPrimary'); + return 'tsrange'; + } + + /** + * @return array + */ + protected function getNodeMappingPattern(): array + { + return ['StringPrimary']; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } } diff --git a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tstzrange.php b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tstzrange.php index 0289dab0..f2eecef8 100644 --- a/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tstzrange.php +++ b/src/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Tstzrange.php @@ -12,12 +12,28 @@ * * @author Martin Georgiev */ -class Tstzrange extends BaseFunction +class Tstzrange extends BaseVariadicFunction { - protected function customizeFunction(): void + protected function getFunctionName(): string { - $this->setFunctionPrototype('tstzrange(%s, %s)'); - $this->addNodeMapping('StringPrimary'); - $this->addNodeMapping('StringPrimary'); + return 'tstzrange'; + } + + /** + * @return array + */ + protected function getNodeMappingPattern(): array + { + return ['StringPrimary']; + } + + protected function getMinArgumentCount(): int + { + return 2; + } + + protected function getMaxArgumentCount(): int + { + return 3; } } diff --git a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php index 5f531fe9..3893d0dd 100644 --- a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php +++ b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php @@ -19,14 +19,16 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT daterange(c0_.date1, c0_.date2) AS sclr_0 FROM ContainsDates c0_', + 'basic range with default bounds' => 'SELECT daterange(c0_.date1, c0_.date2) AS sclr_0 FROM ContainsDates c0_', + 'range with explicit bounds' => "SELECT daterange(c0_.date1, c0_.date2, '[)') AS sclr_0 FROM ContainsDates c0_", ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT DATERANGE(e.date1, e.date2) FROM %s e', ContainsDates::class), + 'basic range with default bounds' => \sprintf('SELECT DATERANGE(e.date1, e.date2) FROM %s e', ContainsDates::class), + 'range with explicit bounds' => \sprintf("SELECT DATERANGE(e.date1, e.date2, '[)') FROM %s e", ContainsDates::class), ]; } } diff --git a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php index 49de6921..036e6e83 100644 --- a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php +++ b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php @@ -19,14 +19,16 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT int4range(c0_.integer1, c0_.integer2) AS sclr_0 FROM ContainsIntegers c0_', + 'basic range with default bounds' => 'SELECT int4range(c0_.integer1, c0_.integer2) AS sclr_0 FROM ContainsIntegers c0_', + 'range with explicit bounds' => "SELECT int4range(c0_.integer1, c0_.integer2, '[)') AS sclr_0 FROM ContainsIntegers c0_", ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT INT4RANGE(e.integer1, e.integer2) FROM %s e', ContainsIntegers::class), + 'basic range with default bounds' => \sprintf('SELECT INT4RANGE(e.integer1, e.integer2) FROM %s e', ContainsIntegers::class), + 'range with explicit bounds' => \sprintf("SELECT INT4RANGE(e.integer1, e.integer2, '[)') FROM %s e", ContainsIntegers::class), ]; } } diff --git a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php index e580d0ce..0a7dab6b 100644 --- a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php +++ b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php @@ -19,14 +19,16 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT int8range(c0_.integer1, c0_.integer2) AS sclr_0 FROM ContainsIntegers c0_', + 'basic range with default bounds' => 'SELECT int8range(c0_.integer1, c0_.integer2) AS sclr_0 FROM ContainsIntegers c0_', + 'range with explicit bounds' => "SELECT int8range(c0_.integer1, c0_.integer2, '[)') AS sclr_0 FROM ContainsIntegers c0_", ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT INT8RANGE(e.integer1, e.integer2) FROM %s e', ContainsIntegers::class), + 'basic range with default bounds' => \sprintf('SELECT INT8RANGE(e.integer1, e.integer2) FROM %s e', ContainsIntegers::class), + 'range with explicit bounds' => \sprintf("SELECT INT8RANGE(e.integer1, e.integer2, '[)') FROM %s e", ContainsIntegers::class), ]; } } diff --git a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php index ea702025..c01eb56a 100644 --- a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php +++ b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php @@ -19,14 +19,16 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT numrange(c0_.decimal1, c0_.decimal2) AS sclr_0 FROM ContainsDecimals c0_', + 'basic range with default bounds' => 'SELECT numrange(c0_.decimal1, c0_.decimal2) AS sclr_0 FROM ContainsDecimals c0_', + 'range with explicit bounds' => "SELECT numrange(c0_.decimal1, c0_.decimal2, '[)') AS sclr_0 FROM ContainsDecimals c0_", ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT NUMRANGE(e.decimal1, e.decimal2) FROM %s e', ContainsDecimals::class), + 'basic range with default bounds' => \sprintf('SELECT NUMRANGE(e.decimal1, e.decimal2) FROM %s e', ContainsDecimals::class), + 'range with explicit bounds' => \sprintf("SELECT NUMRANGE(e.decimal1, e.decimal2, '[)') FROM %s e", ContainsDecimals::class), ]; } } diff --git a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php index a4b95911..8c2996bc 100644 --- a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php +++ b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php @@ -19,14 +19,16 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT tsrange(c0_.datetime1, c0_.datetime2) AS sclr_0 FROM ContainsDates c0_', + 'basic range with default bounds' => 'SELECT tsrange(c0_.datetime1, c0_.datetime2) AS sclr_0 FROM ContainsDates c0_', + 'range with explicit bounds' => "SELECT tsrange(c0_.datetime1, c0_.datetime2, '[)') AS sclr_0 FROM ContainsDates c0_", ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT TSRANGE(e.datetime1, e.datetime2) FROM %s e', ContainsDates::class), + 'basic range with default bounds' => \sprintf('SELECT TSRANGE(e.datetime1, e.datetime2) FROM %s e', ContainsDates::class), + 'range with explicit bounds' => \sprintf("SELECT TSRANGE(e.datetime1, e.datetime2, '[)') FROM %s e", ContainsDates::class), ]; } } diff --git a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php index 7abaffd3..eeb911ad 100644 --- a/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php +++ b/tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php @@ -19,14 +19,16 @@ protected function getStringFunctions(): array protected function getExpectedSqlStatements(): array { return [ - 'SELECT tstzrange(c0_.datetimetz1, c0_.datetimetz2) AS sclr_0 FROM ContainsDates c0_', + 'basic range with default bounds' => 'SELECT tstzrange(c0_.datetimetz1, c0_.datetimetz2) AS sclr_0 FROM ContainsDates c0_', + 'range with explicit bounds' => "SELECT tstzrange(c0_.datetimetz1, c0_.datetimetz2, '[)') AS sclr_0 FROM ContainsDates c0_", ]; } protected function getDqlStatements(): array { return [ - \sprintf('SELECT TSTZRANGE(e.datetimetz1, e.datetimetz2) FROM %s e', ContainsDates::class), + 'basic range with default bounds' => \sprintf('SELECT TSTZRANGE(e.datetimetz1, e.datetimetz2) FROM %s e', ContainsDates::class), + 'range with explicit bounds' => \sprintf("SELECT TSTZRANGE(e.datetimetz1, e.datetimetz2, '[)') FROM %s e", ContainsDates::class), ]; } } From 305cd32d7c22d34094f84deaa136b3e36ee3771c Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 00:24:34 +0100 Subject: [PATCH 06/12] add integration tests --- .../ORM/Query/AST/Functions/DaterangeTest.php | 37 ++++++++++++++++ .../ORM/Query/AST/Functions/Int4rangeTest.php | 43 +++++++++++++++++++ .../ORM/Query/AST/Functions/Int8rangeTest.php | 43 +++++++++++++++++++ .../ORM/Query/AST/Functions/TsrangeTest.php | 35 +++++++++++++++ .../ORM/Query/AST/Functions/TstzrangeTest.php | 26 +++++++++++ 5 files changed, 184 insertions(+) create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php new file mode 100644 index 00000000..640bfdf6 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php @@ -0,0 +1,37 @@ + Daterange::class, + ]; + } + + public function test_daterange(): void + { + $dql = "SELECT DATERANGE(t.date1, t.date2) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $actual = (string)($result[0]['result'] ?? ''); + $this->assertSame('[2023-06-15,2023-06-16)', $actual); + } + + public function test_daterange_with_bounds(): void + { + $dql = "SELECT DATERANGE(t.date1, t.date2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $actual = (string)($result[0]['result'] ?? ''); + $this->assertSame('[2023-06-15,2023-06-16)', $actual); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php new file mode 100644 index 00000000..cc225028 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php @@ -0,0 +1,43 @@ + Int4range::class, + ]; + } + + public function test_int4range(): void + { + $dql = "SELECT INT4RANGE(:start, :end) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql, [ + 'start' => 10, + 'end' => 20, + ]); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $actual = (string)($result[0]['result'] ?? ''); + $this->assertSame('[10,20)', $actual); + } + + public function test_int4range_with_bounds(): void + { + $dql = "SELECT INT4RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql, [ + 'start' => 10, + 'end' => 20, + ]); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $actual = (string)($result[0]['result'] ?? ''); + $this->assertSame('[10,20)', $actual); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php new file mode 100644 index 00000000..ec080cee --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php @@ -0,0 +1,43 @@ + Int8range::class, + ]; + } + + public function test_int8range(): void + { + $dql = "SELECT INT8RANGE(:start, :end) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql, [ + 'start' => 100, + 'end' => 200, + ]); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $actual = (string)($result[0]['result'] ?? ''); + $this->assertSame('[100,200)', $actual); + } + + public function test_int8range_with_bounds(): void + { + $dql = "SELECT INT8RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql, [ + 'start' => 1000, + 'end' => 2000, + ]); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $actual = (string)($result[0]['result'] ?? ''); + $this->assertSame('[1000,2000)', $actual); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php new file mode 100644 index 00000000..e6b2b3c3 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php @@ -0,0 +1,35 @@ + Tsrange::class, + ]; + } + + public function test_tsrange(): void + { + $dql = 'SELECT TSRANGE(t.datetime1, t.datetime2) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $this->assertSame('["2023-06-15 10:30:00","2023-06-16 11:45:00")', (string) $result[0]['result']); + } + + public function test_tsrange_with_bounds(): void + { + $dql = "SELECT TSRANGE(t.datetime1, t.datetime2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $this->assertSame('["2023-06-15 10:30:00","2023-06-16 11:45:00")', (string) $result[0]['result']); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php new file mode 100644 index 00000000..4e2cfb5a --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php @@ -0,0 +1,26 @@ + Tstzrange::class, + ]; + } + + public function test_tstzrange(): void + { + $dql = "SELECT TSTZRANGE('2024-01-01 00:00:00+00', '2024-12-31 23:59:59+00') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $this->assertSame('["2024-01-01 00:00:00+00","2024-12-31 23:59:59+00")', (string) $result[0]['result']); + } +} From 7678c617432498b0f681a146a5d13fb2198fc335 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 00:29:38 +0100 Subject: [PATCH 07/12] no message --- .../ORM/Query/AST/Functions/DaterangeTest.php | 12 ++++++------ .../ORM/Query/AST/Functions/Int4rangeTest.php | 12 ++++++------ .../ORM/Query/AST/Functions/Int8rangeTest.php | 12 ++++++------ .../Doctrine/ORM/Query/AST/Functions/TsrangeTest.php | 10 ++++++---- .../ORM/Query/AST/Functions/TstzrangeTest.php | 5 +++-- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php index 640bfdf6..ebc1a543 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php @@ -17,21 +17,21 @@ protected function getStringFunctions(): array public function test_daterange(): void { - $dql = "SELECT DATERANGE(t.date1, t.date2) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $dql = 'SELECT DATERANGE(t.date1, t.date2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $actual = (string)($result[0]['result'] ?? ''); - $this->assertSame('[2023-06-15,2023-06-16)', $actual); + $this->assertIsString($result[0]['result']); + $this->assertSame('[2023-06-15,2023-06-16)', $result[0]['result']); } public function test_daterange_with_bounds(): void { - $dql = "SELECT DATERANGE(t.date1, t.date2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $dql = 'SELECT DATERANGE(t.date1, t.date2, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $actual = (string)($result[0]['result'] ?? ''); - $this->assertSame('[2023-06-15,2023-06-16)', $actual); + $this->assertIsString($result[0]['result']); + $this->assertSame('[2023-06-15,2023-06-16)', $result[0]['result']); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php index cc225028..2691afc5 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php @@ -17,27 +17,27 @@ protected function getStringFunctions(): array public function test_int4range(): void { - $dql = "SELECT INT4RANGE(:start, :end) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $dql = 'SELECT INT4RANGE(:start, :end) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql, [ 'start' => 10, 'end' => 20, ]); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $actual = (string)($result[0]['result'] ?? ''); - $this->assertSame('[10,20)', $actual); + $this->assertIsString($result[0]['result']); + $this->assertSame('[10,20)', $result[0]['result']); } public function test_int4range_with_bounds(): void { - $dql = "SELECT INT4RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $dql = 'SELECT INT4RANGE(:start, :end, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql, [ 'start' => 10, 'end' => 20, ]); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $actual = (string)($result[0]['result'] ?? ''); - $this->assertSame('[10,20)', $actual); + $this->assertIsString($result[0]['result']); + $this->assertSame('[10,20)', $result[0]['result']); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php index ec080cee..a78800df 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php @@ -17,27 +17,27 @@ protected function getStringFunctions(): array public function test_int8range(): void { - $dql = "SELECT INT8RANGE(:start, :end) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $dql = 'SELECT INT8RANGE(:start, :end) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql, [ 'start' => 100, 'end' => 200, ]); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $actual = (string)($result[0]['result'] ?? ''); - $this->assertSame('[100,200)', $actual); + $this->assertIsString($result[0]['result']); + $this->assertSame('[100,200)', $result[0]['result']); } public function test_int8range_with_bounds(): void { - $dql = "SELECT INT8RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $dql = 'SELECT INT8RANGE(:start, :end, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql, [ 'start' => 1000, 'end' => 2000, ]); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $actual = (string)($result[0]['result'] ?? ''); - $this->assertSame('[1000,2000)', $actual); + $this->assertIsString($result[0]['result']); + $this->assertSame('[1000,2000)', $result[0]['result']); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php index e6b2b3c3..4c3f3e8d 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php @@ -17,19 +17,21 @@ protected function getStringFunctions(): array public function test_tsrange(): void { - $dql = 'SELECT TSRANGE(t.datetime1, t.datetime2) as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1'; + $dql = 'SELECT TSRANGE(t.datetime1, t.datetime2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $this->assertSame('["2023-06-15 10:30:00","2023-06-16 11:45:00")', (string) $result[0]['result']); + $this->assertIsString($result[0]['result']); + $this->assertSame('["2023-06-15 10:30:00","2023-06-16 11:45:00")', $result[0]['result']); } public function test_tsrange_with_bounds(): void { - $dql = "SELECT TSRANGE(t.datetime1, t.datetime2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $dql = 'SELECT TSRANGE(t.datetime1, t.datetime2, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $this->assertSame('["2023-06-15 10:30:00","2023-06-16 11:45:00")', (string) $result[0]['result']); + $this->assertIsString($result[0]['result']); + $this->assertSame('["2023-06-15 10:30:00","2023-06-16 11:45:00")', $result[0]['result']); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php index 4e2cfb5a..93ec2e06 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php @@ -17,10 +17,11 @@ protected function getStringFunctions(): array public function test_tstzrange(): void { - $dql = "SELECT TSTZRANGE('2024-01-01 00:00:00+00', '2024-12-31 23:59:59+00') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; + $dql = 'SELECT TSTZRANGE(\'2024-01-01 00:00:00+00\', \'2024-12-31 23:59:59+00\') as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); - $this->assertSame('["2024-01-01 00:00:00+00","2024-12-31 23:59:59+00")', (string) $result[0]['result']); + $this->assertIsString($result[0]['result']); + $this->assertSame('["2024-01-01 00:00:00+00","2024-12-31 23:59:59+00")', $result[0]['result']); } } From ba3379576050aa5a4310da8d89bb82aec7f327b1 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 00:33:31 +0100 Subject: [PATCH 08/12] no message --- .../ORM/Query/AST/Functions/NumrangeTest.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php new file mode 100644 index 00000000..83be38c4 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php @@ -0,0 +1,37 @@ + Numrange::class, + ]; + } + + public function test_numrange(): void + { + $dql = 'SELECT NUMRANGE(t.decimal1, t.decimal2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $this->assertIsString($result[0]['result']); + $this->assertSame('[10.5,20.5)', $result[0]['result']); + } + + public function test_numrange_with_bounds(): void + { + $dql = 'SELECT NUMRANGE(t.decimal1, t.decimal2, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $this->assertIsString($result[0]['result']); + $this->assertSame('[10.5,20.5)', $result[0]['result']); + } +} From 7e1316c1e069c528d2761691843617f505a46a98 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 00:39:36 +0100 Subject: [PATCH 09/12] no message --- .../Doctrine/ORM/Query/AST/Functions/DaterangeTest.php | 2 +- .../Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php | 2 +- .../Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php | 8 ++++---- .../Doctrine/ORM/Query/AST/Functions/NumrangeTest.php | 2 +- .../Doctrine/ORM/Query/AST/Functions/TsrangeTest.php | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php index ebc1a543..a2c86071 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DaterangeTest.php @@ -27,7 +27,7 @@ public function test_daterange(): void public function test_daterange_with_bounds(): void { - $dql = 'SELECT DATERANGE(t.date1, t.date2, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; + $dql = "SELECT DATERANGE(t.date1, t.date2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php index 2691afc5..05f4877f 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php @@ -30,7 +30,7 @@ public function test_int4range(): void public function test_int4range_with_bounds(): void { - $dql = 'SELECT INT4RANGE(:start, :end, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; + $dql = "SELECT INT4RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; $result = $this->executeDqlQuery($dql, [ 'start' => 10, 'end' => 20, diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php index a78800df..1227febc 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php @@ -30,14 +30,14 @@ public function test_int8range(): void public function test_int8range_with_bounds(): void { - $dql = 'SELECT INT8RANGE(:start, :end, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; + $dql = "SELECT INT8RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; $result = $this->executeDqlQuery($dql, [ - 'start' => 1000, - 'end' => 2000, + 'start' => 100, + 'end' => 200, ]); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); $this->assertIsString($result[0]['result']); - $this->assertSame('[1000,2000)', $result[0]['result']); + $this->assertSame('[100,200)', $result[0]['result']); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php index 83be38c4..86aaca22 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumrangeTest.php @@ -27,7 +27,7 @@ public function test_numrange(): void public function test_numrange_with_bounds(): void { - $dql = 'SELECT NUMRANGE(t.decimal1, t.decimal2, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1'; + $dql = "SELECT NUMRANGE(t.decimal1, t.decimal2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsNumerics t WHERE t.id = 1"; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php index 4c3f3e8d..8fa15dab 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TsrangeTest.php @@ -27,7 +27,7 @@ public function test_tsrange(): void public function test_tsrange_with_bounds(): void { - $dql = 'SELECT TSRANGE(t.datetime1, t.datetime2, "[)") as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; + $dql = "SELECT TSRANGE(t.datetime1, t.datetime2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); From 57b2413d69e4c770a053aba16bb7cf212a0404b9 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 01:41:14 +0100 Subject: [PATCH 10/12] no message --- .../ORM/Query/AST/Functions/Int4rangeTest.php | 16 ++---- .../ORM/Query/AST/Functions/Int8rangeTest.php | 20 +++----- .../Query/AST/Functions/NumericTestCase.php | 49 +++++++++++++++++++ .../ORM/Query/AST/Functions/TstzrangeTest.php | 16 ++++-- 4 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php index 05f4877f..b241c618 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int4rangeTest.php @@ -6,7 +6,7 @@ use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int4range; -class Int4rangeTest extends JsonTestCase +class Int4rangeTest extends NumericTestCase { protected function getStringFunctions(): array { @@ -17,11 +17,8 @@ protected function getStringFunctions(): array public function test_int4range(): void { - $dql = 'SELECT INT4RANGE(:start, :end) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; - $result = $this->executeDqlQuery($dql, [ - 'start' => 10, - 'end' => 20, - ]); + $dql = 'SELECT INT4RANGE(t.integer1, t.integer2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); $this->assertIsString($result[0]['result']); @@ -30,11 +27,8 @@ public function test_int4range(): void public function test_int4range_with_bounds(): void { - $dql = "SELECT INT4RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; - $result = $this->executeDqlQuery($dql, [ - 'start' => 10, - 'end' => 20, - ]); + $dql = "SELECT INT4RANGE(t.integer1, t.integer2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsNumerics t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); $this->assertIsString($result[0]['result']); diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php index 1227febc..fc36f27f 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/Int8rangeTest.php @@ -6,7 +6,7 @@ use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Int8range; -class Int8rangeTest extends JsonTestCase +class Int8rangeTest extends NumericTestCase { protected function getStringFunctions(): array { @@ -17,27 +17,21 @@ protected function getStringFunctions(): array public function test_int8range(): void { - $dql = 'SELECT INT8RANGE(:start, :end) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; - $result = $this->executeDqlQuery($dql, [ - 'start' => 100, - 'end' => 200, - ]); + $dql = 'SELECT INT8RANGE(t.bigint1, t.bigint2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsNumerics t WHERE t.id = 1'; + $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); $this->assertIsString($result[0]['result']); - $this->assertSame('[100,200)', $result[0]['result']); + $this->assertSame('[1000,2000)', $result[0]['result']); } public function test_int8range_with_bounds(): void { - $dql = "SELECT INT8RANGE(:start, :end, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t WHERE t.id = 1"; - $result = $this->executeDqlQuery($dql, [ - 'start' => 100, - 'end' => 200, - ]); + $dql = "SELECT INT8RANGE(t.bigint1, t.bigint2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsNumerics t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); $this->assertIsString($result[0]['result']); - $this->assertSame('[100,200)', $result[0]['result']); + $this->assertSame('[1000,2000)', $result[0]['result']); } } diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php new file mode 100644 index 00000000..6e5f92b3 --- /dev/null +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/NumericTestCase.php @@ -0,0 +1,49 @@ +createTestTableForNumericFixture(); + $this->insertTestDataForNumericFixture(); + } + + protected function createTestTableForNumericFixture(): void + { + $tableName = 'containsnumerics'; + + $this->createTestSchema(); + $this->dropTestTableIfItExists($tableName); + + $fullTableName = \sprintf('%s.%s', self::DATABASE_SCHEMA, $tableName); + $sql = \sprintf(' + CREATE TABLE %s ( + id SERIAL PRIMARY KEY, + integer1 INTEGER, + integer2 INTEGER, + bigint1 BIGINT, + bigint2 BIGINT, + decimal1 DECIMAL, + decimal2 DECIMAL + ) + ', $fullTableName); + + $this->connection->executeStatement($sql); + } + + protected function insertTestDataForNumericFixture(): void + { + $sql = \sprintf(' + INSERT INTO %s.containsnumerics (integer1, integer2, bigint1, bigint2, decimal1, decimal2) VALUES + (10, 20, 1000, 2000, 10.5, 20.5) + ', self::DATABASE_SCHEMA); + $this->connection->executeStatement($sql); + } +} diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php index 93ec2e06..d37c5346 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/TstzrangeTest.php @@ -6,7 +6,7 @@ use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tstzrange; -class TstzrangeTest extends JsonTestCase +class TstzrangeTest extends DateTestCase { protected function getStringFunctions(): array { @@ -17,11 +17,21 @@ protected function getStringFunctions(): array public function test_tstzrange(): void { - $dql = 'SELECT TSTZRANGE(\'2024-01-01 00:00:00+00\', \'2024-12-31 23:59:59+00\') as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t WHERE t.id = 1'; + $dql = 'SELECT TSTZRANGE(t.datetimetz1, t.datetimetz2) as result FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsDates t WHERE t.id = 1'; $result = $this->executeDqlQuery($dql); $this->assertIsArray($result); $this->assertNotEmpty($result[0]['result']); $this->assertIsString($result[0]['result']); - $this->assertSame('["2024-01-01 00:00:00+00","2024-12-31 23:59:59+00")', $result[0]['result']); + $this->assertSame('["2023-06-15 10:30:00+00","2023-06-16 11:45:00+00")', $result[0]['result']); + } + + public function test_tstzrange_with_bounds(): void + { + $dql = "SELECT TSTZRANGE(t.datetimetz1, t.datetimetz2, '[)') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsDates t WHERE t.id = 1"; + $result = $this->executeDqlQuery($dql); + $this->assertIsArray($result); + $this->assertNotEmpty($result[0]['result']); + $this->assertIsString($result[0]['result']); + $this->assertSame('["2023-06-15 10:30:00+00","2023-06-16 11:45:00+00")', $result[0]['result']); } } From 80dc9632ef9c4361fe085dddb9d5dec668cd707d Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 01:46:08 +0100 Subject: [PATCH 11/12] no message --- .../Doctrine/ORM/Query/AST/Functions/DateTestCase.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTestCase.php b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTestCase.php index 5c38ee6f..b97e46ec 100644 --- a/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTestCase.php +++ b/tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/DateTestCase.php @@ -31,7 +31,9 @@ protected function createTestTableForDateFixture(): void datetime1 TIMESTAMP, datetime2 TIMESTAMP, time1 TIME, - time2 TIME + time2 TIME, + datetimetz1 TIMESTAMPTZ, + datetimetz2 TIMESTAMPTZ ) ', $fullTableName); @@ -41,8 +43,8 @@ protected function createTestTableForDateFixture(): void protected function insertTestDataForDateFixture(): void { $sql = \sprintf(' - INSERT INTO %s.containsdates (date1, date2, datetime1, datetime2, time1, time2) VALUES - (\'2023-06-15\', \'2023-06-16\', \'2023-06-15 10:30:00\', \'2023-06-16 11:45:00\', \'10:30:00\', \'11:45:00\') + INSERT INTO %s.containsdates (date1, date2, datetime1, datetime2, time1, time2, datetimetz1, datetimetz2) VALUES + (\'2023-06-15\', \'2023-06-16\', \'2023-06-15 10:30:00\', \'2023-06-16 11:45:00\', \'10:30:00\', \'11:45:00\', \'2023-06-15 10:30:00+00\', \'2023-06-16 11:45:00+00\') ', self::DATABASE_SCHEMA); $this->connection->executeStatement($sql); } From fe42c5b0a77fca28d27ab7c90347a122113ac599 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Thu, 22 May 2025 01:49:01 +0100 Subject: [PATCH 12/12] no message --- .../Doctrine/Entity/ContainsNumerics.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 fixtures/MartinGeorgiev/Doctrine/Entity/ContainsNumerics.php diff --git a/fixtures/MartinGeorgiev/Doctrine/Entity/ContainsNumerics.php b/fixtures/MartinGeorgiev/Doctrine/Entity/ContainsNumerics.php new file mode 100644 index 00000000..c44676be --- /dev/null +++ b/fixtures/MartinGeorgiev/Doctrine/Entity/ContainsNumerics.php @@ -0,0 +1,30 @@ +