Skip to content

Commit 09d479f

Browse files
chore: test functions against a real PostgreSQL server (#379)
1 parent b653dce commit 09d479f

12 files changed

+601
-28
lines changed

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonTestCase.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,18 @@ protected function insertTestDataForJsonFixture(): void
3939
{
4040
$json1 = '{"name": "John", "age": 30, "tags": ["developer", "manager"], "address": {"city": "New York"}}';
4141
$json2 = '{"name": "Jane", "age": 25, "tags": ["designer"], "address": {"city": "Boston"}}';
42+
$json3 = '{"name": "Micky", "age": 30, "tags": [], "address": {"city": "New York"}}';
43+
$json4 = '{}';
44+
$json5 = '{"name": "John", "age": null, "tags": ["developer"], "address": {"city": "New York", "zip": null}}';
4245

4346
$sql = \sprintf('
4447
INSERT INTO %s.containsjsons (object1, object2) VALUES
4548
(\'%s\', \'%s\'),
49+
(\'%s\', \'%s\'),
50+
(\'%s\', \'%s\'),
51+
(\'%s\', \'%s\'),
4652
(\'%s\', \'%s\')
47-
', self::DATABASE_SCHEMA, $json1, $json1, $json2, $json2);
53+
', self::DATABASE_SCHEMA, $json1, $json1, $json2, $json2, $json3, $json3, $json4, $json4, $json5, $json5);
4854
$this->connection->executeStatement($sql);
4955
}
5056
}

tests/Integration/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/JsonbAggTest.php

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,11 @@ public function test_jsonb_agg_with_single_row(): void
3131
$this->assertEqualsCanonicalizing($expected, $actual);
3232
}
3333

34-
public function test_jsonb_agg_with_all_rows(): void
34+
public function test_jsonb_agg_with_multiple_rows(): void
3535
{
3636
$dql = 'SELECT JSONB_AGG(t.object1) as result
37-
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t';
38-
$result = $this->executeDqlQuery($dql);
39-
$this->assertIsString($result[0]['result']);
40-
$actual = \json_decode($result[0]['result'], true);
41-
$this->assertIsArray($actual);
42-
$expected = [
43-
[
44-
'name' => 'John',
45-
'age' => 30,
46-
'tags' => ['developer', 'manager'],
47-
'address' => ['city' => 'New York'],
48-
],
49-
[
50-
'name' => 'Jane',
51-
'age' => 25,
52-
'tags' => ['designer'],
53-
'address' => ['city' => 'Boston'],
54-
],
55-
];
56-
$this->assertEqualsCanonicalizing($expected, $actual);
57-
}
58-
59-
public function test_jsonb_agg_with_object2_column(): void
60-
{
61-
$dql = 'SELECT JSONB_AGG(t.object2) as result
62-
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t';
37+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
38+
WHERE t.id IN (1, 2)';
6339
$result = $this->executeDqlQuery($dql);
6440
$this->assertIsString($result[0]['result']);
6541
$actual = \json_decode($result[0]['result'], true);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Integration\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use Doctrine\DBAL\Exception;
8+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbInsert;
9+
10+
class JsonbInsertTest extends JsonTestCase
11+
{
12+
protected function getStringFunctions(): array
13+
{
14+
return [
15+
'JSONB_INSERT' => JsonbInsert::class,
16+
];
17+
}
18+
19+
public function test_jsonb_insert_new_value(): void
20+
{
21+
$dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result
22+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
23+
WHERE t.id = 1';
24+
$result = $this->executeDqlQuery($dql, [
25+
'path' => '{email}',
26+
'value' => '"john@example.com"',
27+
]);
28+
$this->assertIsString($result[0]['result']);
29+
$decoded = \json_decode($result[0]['result'], true);
30+
$this->assertIsArray($decoded);
31+
$this->assertArrayHasKey('email', $decoded);
32+
$this->assertSame('john@example.com', $decoded['email']);
33+
}
34+
35+
public function test_jsonb_insert_nested_path(): void
36+
{
37+
$dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result
38+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
39+
WHERE t.id = 1';
40+
$result = $this->executeDqlQuery($dql, [
41+
'path' => '{address,zip}',
42+
'value' => '"10001"',
43+
]);
44+
$this->assertIsString($result[0]['result']);
45+
$decoded = \json_decode($result[0]['result'], true);
46+
$this->assertIsArray($decoded);
47+
$this->assertArrayHasKey('address', $decoded);
48+
$this->assertIsArray($decoded['address']);
49+
$this->assertArrayHasKey('zip', $decoded['address']);
50+
$this->assertSame('10001', $decoded['address']['zip']);
51+
}
52+
53+
public function test_throws_exception_when_inserting_at_existing_object_key(): void
54+
{
55+
$this->expectException(Exception::class);
56+
$dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result
57+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
58+
WHERE t.id = 1';
59+
$this->executeDqlQuery($dql, [
60+
'path' => '{name}',
61+
'value' => '"John Doe"',
62+
]);
63+
}
64+
65+
public function test_throws_exception_when_inserting_at_existing_nested_path(): void
66+
{
67+
$this->expectException(Exception::class);
68+
69+
$dql = 'SELECT JSONB_INSERT(t.object1, :path, :value) as result
70+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
71+
WHERE t.id = 5';
72+
73+
$this->executeDqlQuery($dql, [
74+
'path' => '{address,zip}',
75+
'value' => '"10001"',
76+
]);
77+
}
78+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Integration\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbObjectAgg;
8+
9+
class JsonbObjectAggTest extends JsonTestCase
10+
{
11+
protected function getStringFunctions(): array
12+
{
13+
return [
14+
'JSONB_OBJECT_AGG' => JsonbObjectAgg::class,
15+
];
16+
}
17+
18+
public function test_jsonb_object_agg(): void
19+
{
20+
$dql = "SELECT JSONB_OBJECT_AGG('key', 'value') as result
21+
FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsJsons t
22+
WHERE t.id = 1";
23+
$result = $this->executeDqlQuery($dql);
24+
$this->assertIsString($result[0]['result']);
25+
$decoded = \json_decode($result[0]['result'], true);
26+
$this->assertIsArray($decoded);
27+
$this->assertSame(['key' => 'value'], $decoded);
28+
}
29+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Integration\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbObjectKeys;
8+
9+
class JsonbObjectKeysTest extends JsonTestCase
10+
{
11+
protected function getStringFunctions(): array
12+
{
13+
return [
14+
'JSONB_OBJECT_KEYS' => JsonbObjectKeys::class,
15+
];
16+
}
17+
18+
public function test_jsonb_object_keys(): void
19+
{
20+
$dql = 'SELECT JSONB_OBJECT_KEYS(t.object1) as result
21+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
22+
WHERE t.id = 1';
23+
$result = $this->executeDqlQuery($dql);
24+
$this->assertIsString($result[0]['result']);
25+
}
26+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Integration\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryArray;
8+
9+
class JsonbPathQueryArrayTest extends JsonTestCase
10+
{
11+
protected function getStringFunctions(): array
12+
{
13+
return [
14+
'JSONB_PATH_QUERY_ARRAY' => JsonbPathQueryArray::class,
15+
];
16+
}
17+
18+
public function test_jsonb_path_query_array_simple(): void
19+
{
20+
$dql = 'SELECT JSONB_PATH_QUERY_ARRAY(:json, :path) as result
21+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
22+
WHERE t.id = 1';
23+
$result = $this->executeDqlQuery($dql, [
24+
'json' => '{"a": 1, "b": 2}',
25+
'path' => '$.b',
26+
]);
27+
$this->assertIsString($result[0]['result']);
28+
$decoded = \json_decode($result[0]['result'], true);
29+
$this->assertIsArray($decoded);
30+
$this->assertCount(1, $decoded);
31+
$this->assertSame(2, $decoded[0]);
32+
}
33+
34+
public function test_jsonb_path_query_array_multiple_values(): void
35+
{
36+
$dql = 'SELECT JSONB_PATH_QUERY_ARRAY(:json, :path) as result
37+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
38+
WHERE t.id = 1';
39+
$result = $this->executeDqlQuery($dql, [
40+
'json' => '{"items": [1, 2, 3]}',
41+
'path' => '$.items[*]',
42+
]);
43+
$this->assertIsString($result[0]['result']);
44+
$decoded = \json_decode($result[0]['result'], true);
45+
$this->assertIsArray($decoded);
46+
$this->assertCount(3, $decoded);
47+
$this->assertSame([1, 2, 3], $decoded);
48+
}
49+
50+
public function test_jsonb_path_query_array_with_filter(): void
51+
{
52+
$dql = 'SELECT JSONB_PATH_QUERY_ARRAY(:json, :path) as result
53+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
54+
WHERE t.id = 1';
55+
$result = $this->executeDqlQuery($dql, [
56+
'json' => '{"items": [{"id": 1}, {"id": 2}, {"id": 3}]}',
57+
'path' => '$.items[*] ? (@.id > 1)',
58+
]);
59+
$this->assertIsString($result[0]['result']);
60+
$decoded = \json_decode($result[0]['result'], true);
61+
$this->assertIsArray($decoded);
62+
$this->assertCount(2, $decoded);
63+
$this->assertSame(['id' => 2], $decoded[0]);
64+
$this->assertSame(['id' => 3], $decoded[1]);
65+
}
66+
67+
public function test_jsonb_path_query_array_with_column_reference(): void
68+
{
69+
$dql = 'SELECT JSONB_PATH_QUERY_ARRAY(t.object1, :path) as result
70+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
71+
WHERE t.id = 1';
72+
$result = $this->executeDqlQuery($dql, ['path' => '$.tags[*]']);
73+
$this->assertIsString($result[0]['result']);
74+
$decoded = \json_decode($result[0]['result'], true);
75+
$this->assertIsArray($decoded);
76+
$this->assertCount(2, $decoded);
77+
$this->assertSame(['developer', 'manager'], $decoded);
78+
}
79+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Integration\MartinGeorgiev\Doctrine\ORM\Query\AST\Functions;
6+
7+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonbPathQueryFirst;
8+
9+
class JsonbPathQueryFirstTest extends JsonTestCase
10+
{
11+
protected function getStringFunctions(): array
12+
{
13+
return [
14+
'JSONB_PATH_QUERY_FIRST' => JsonbPathQueryFirst::class,
15+
];
16+
}
17+
18+
public function test_jsonb_path_query_first_simple(): void
19+
{
20+
$dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result
21+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
22+
WHERE t.id = 1';
23+
$result = $this->executeDqlQuery($dql, [
24+
'json' => '{"a": 1, "b": 2}',
25+
'path' => '$.b',
26+
]);
27+
$this->assertIsString($result[0]['result']);
28+
$this->assertSame('2', $result[0]['result']);
29+
}
30+
31+
public function test_jsonb_path_query_first_array(): void
32+
{
33+
$dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result
34+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
35+
WHERE t.id = 1';
36+
$result = $this->executeDqlQuery($dql, [
37+
'json' => '{"items": [1, 2, 3]}',
38+
'path' => '$.items[*]',
39+
]);
40+
$this->assertIsString($result[0]['result']);
41+
$this->assertSame('1', $result[0]['result']);
42+
}
43+
44+
public function test_jsonb_path_query_first_with_filter(): void
45+
{
46+
$dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result
47+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
48+
WHERE t.id = 1';
49+
$result = $this->executeDqlQuery($dql, [
50+
'json' => '{"items": [{"id": 1}, {"id": 2}, {"id": 3}]}',
51+
'path' => '$.items[*] ? (@.id > 1)',
52+
]);
53+
$this->assertIsString($result[0]['result']);
54+
$this->assertSame('{"id": 2}', $result[0]['result']);
55+
}
56+
57+
public function test_jsonb_path_query_first_with_no_match(): void
58+
{
59+
$dql = 'SELECT JSONB_PATH_QUERY_FIRST(:json, :path) as result
60+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
61+
WHERE t.id = 1';
62+
$result = $this->executeDqlQuery($dql, [
63+
'json' => '{"items": [{"id": 1}]}',
64+
'path' => '$.items[*] ? (@.id > 1)',
65+
]);
66+
$this->assertNull($result[0]['result']);
67+
}
68+
69+
public function test_jsonb_path_query_first_with_column_reference(): void
70+
{
71+
$dql = 'SELECT JSONB_PATH_QUERY_FIRST(t.object1, :path) as result
72+
FROM Fixtures\MartinGeorgiev\Doctrine\Entity\ContainsJsons t
73+
WHERE t.id = 1';
74+
$result = $this->executeDqlQuery($dql, ['path' => '$.tags[*]']);
75+
$this->assertIsString($result[0]['result']);
76+
$this->assertSame('"developer"', $result[0]['result']);
77+
}
78+
}

0 commit comments

Comments
 (0)