Skip to content

Commit 5dfa0ca

Browse files
committed
Postgre: fix even literal inferring
1 parent fffa94f commit 5dfa0ca

File tree

3 files changed

+72
-55
lines changed

3 files changed

+72
-55
lines changed

src/Type/Doctrine/Query/QueryResultTypeWalker.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Doctrine\ORM\Query\SqlWalker;
1515
use PHPStan\ShouldNotHappenException;
1616
use PHPStan\Type\BooleanType;
17+
use PHPStan\Type\Constant\ConstantBooleanType;
1718
use PHPStan\Type\Constant\ConstantFloatType;
1819
use PHPStan\Type\Constant\ConstantIntegerType;
1920
use PHPStan\Type\Constant\ConstantStringType;
@@ -1113,8 +1114,11 @@ public function walkLiteral($literal): string
11131114
break;
11141115

11151116
case AST\Literal::BOOLEAN:
1116-
$value = strtolower($literal->value) === 'true' ? 1 : 0;
1117-
$type = new ConstantIntegerType($value);
1117+
$value = strtolower($literal->value) === 'true';
1118+
$type = TypeCombinator::union(
1119+
new ConstantIntegerType($value ? 1 : 0),
1120+
new ConstantBooleanType($value)
1121+
);
11181122
break;
11191123

11201124
case AST\Literal::NUMERIC:

tests/Platform/QueryResultTypeWalkerFetchTypeMatrixTest.php

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -180,60 +180,61 @@ public function provideCases(): iterable
180180
// Notes:
181181
// - Any direct column fetch uses the type declared in entity, but when passed to a function, the driver decides the type
182182

183-
$testData = [ // mysql, sqlite, pdo_pgsql, pgsql, stringified, stringifiedOldPostgre
183+
$testData = [ // mysql, sqlite, pdo_pgsql, pgsql, stringified, stringifiedOldPostgre
184184
// bool-ish
185-
't.col_bool' => ['bool', 'bool', 'bool', 'bool', 'bool', 'bool'],
186-
'COALESCE(t.col_bool, TRUE)' => ['int', 'int', 'bool', 'bool', 'string', 'bool'],
185+
'(TRUE)' => ['int', 'int', 'bool', 'bool', 'string', 'bool'],
186+
't.col_bool' => ['bool', 'bool', 'bool', 'bool', 'bool', 'bool'],
187+
'COALESCE(t.col_bool, TRUE)' => ['int', 'int', 'bool', 'bool', 'string', 'bool'],
187188

188189
// float-ish
189-
't.col_float' => ['float', 'float', 'float', 'float', 'float', 'float'],
190-
'AVG(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
191-
'SUM(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
192-
'MIN(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
193-
'MAX(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
194-
'SQRT(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
195-
'ABS(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
190+
't.col_float' => ['float', 'float', 'float', 'float', 'float', 'float'],
191+
'AVG(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
192+
'SUM(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
193+
'MIN(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
194+
'MAX(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
195+
'SQRT(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
196+
'ABS(t.col_float)' => ['float', 'float', 'string', 'float', 'string', 'string'],
196197

197198
// decimal-ish
198-
't.col_decimal' => ['string', 'string', 'string', 'string', 'string', 'string'],
199-
'0.1' => ['string', 'float', 'string', 'string', 'string', 'string'],
200-
'0.125e0' => ['float', 'float', 'string', 'string', 'string', 'string'],
201-
'AVG(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
202-
'AVG(t.col_int)' => ['string', 'float', 'string', 'string', 'string', 'string'],
203-
'AVG(t.col_bigint)' => ['string', 'float', 'string', 'string', 'string', 'string'],
204-
'SUM(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
205-
'MIN(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
206-
'MAX(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
207-
'SQRT(t.col_decimal)' => ['float', 'float', 'string', 'string', 'string', 'string'],
208-
'SQRT(t.col_int)' => ['float', 'float', 'string', 'float', 'string', 'string'],
209-
'SQRT(t.col_bigint)' => ['float', null, 'string', 'float', null, null], // sqlite3 returns float, but pdo_sqlite returns NULL
210-
'ABS(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
199+
't.col_decimal' => ['string', 'string', 'string', 'string', 'string', 'string'],
200+
'0.1' => ['string', 'float', 'string', 'string', 'string', 'string'],
201+
'0.125e0' => ['float', 'float', 'string', 'string', 'string', 'string'],
202+
'AVG(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
203+
'AVG(t.col_int)' => ['string', 'float', 'string', 'string', 'string', 'string'],
204+
'AVG(t.col_bigint)' => ['string', 'float', 'string', 'string', 'string', 'string'],
205+
'SUM(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
206+
'MIN(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
207+
'MAX(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
208+
'SQRT(t.col_decimal)' => ['float', 'float', 'string', 'string', 'string', 'string'],
209+
'SQRT(t.col_int)' => ['float', 'float', 'string', 'float', 'string', 'string'],
210+
'SQRT(t.col_bigint)' => ['float', null, 'string', 'float', null, null], // sqlite3 returns float, but pdo_sqlite returns NULL
211+
'ABS(t.col_decimal)' => ['string', 'float', 'string', 'string', 'string', 'string'],
211212

212213
// int-ish
213-
'1' => ['int', 'int', 'int', 'int', 'string', 'string'],
214-
'2147483648' => ['int', 'int', 'int', 'int', 'string', 'string'],
215-
't.col_int' => ['int', 'int', 'int', 'int', 'int', 'int'],
216-
't.col_bigint' => ['string', 'string', 'string', 'string', 'string', 'string'],
217-
'SUM(t.col_int)' => ['string', 'int', 'int', 'int', 'string', 'string'],
218-
'SUM(t.col_bigint)' => ['string', 'int', 'string', 'string', 'string', 'string'],
219-
"LENGTH('')" => ['int', 'int', 'int', 'int', 'int', 'int'],
220-
'COUNT(t)' => ['int', 'int', 'int', 'int', 'int', 'int'],
221-
'COUNT(1)' => ['int', 'int', 'int', 'int', 'int', 'int'],
222-
'COUNT(t.col_int)' => ['int', 'int', 'int', 'int', 'int', 'int'],
223-
'MIN(t.col_int)' => ['int', 'int', 'int', 'int', 'string', 'string'],
224-
'MIN(t.col_bigint)' => ['int', 'int', 'int', 'int', 'string', 'string'],
225-
'MAX(t.col_int)' => ['int', 'int', 'int', 'int', 'string', 'string'],
226-
'MAX(t.col_bigint)' => ['int', 'int', 'int', 'int', 'string', 'string'],
227-
'MOD(t.col_int, 2)' => ['int', 'int', 'int', 'int', 'string', 'string'],
228-
'MOD(t.col_bigint, 2)' => ['int', 'int', 'int', 'int', 'string', 'string'],
229-
'ABS(t.col_int)' => ['int', 'int', 'int', 'int', 'string', 'string'],
230-
'ABS(t.col_bigint)' => ['int', 'int', 'int', 'int', 'string', 'string'],
214+
'1' => ['int', 'int', 'int', 'int', 'string', 'string'],
215+
'2147483648' => ['int', 'int', 'int', 'int', 'string', 'string'],
216+
't.col_int' => ['int', 'int', 'int', 'int', 'int', 'int'],
217+
't.col_bigint' => ['string', 'string', 'string', 'string', 'string', 'string'],
218+
'SUM(t.col_int)' => ['string', 'int', 'int', 'int', 'string', 'string'],
219+
'SUM(t.col_bigint)' => ['string', 'int', 'string', 'string', 'string', 'string'],
220+
"LENGTH('')" => ['int', 'int', 'int', 'int', 'int', 'int'],
221+
'COUNT(t)' => ['int', 'int', 'int', 'int', 'int', 'int'],
222+
'COUNT(1)' => ['int', 'int', 'int', 'int', 'int', 'int'],
223+
'COUNT(t.col_int)' => ['int', 'int', 'int', 'int', 'int', 'int'],
224+
'MIN(t.col_int)' => ['int', 'int', 'int', 'int', 'string', 'string'],
225+
'MIN(t.col_bigint)' => ['int', 'int', 'int', 'int', 'string', 'string'],
226+
'MAX(t.col_int)' => ['int', 'int', 'int', 'int', 'string', 'string'],
227+
'MAX(t.col_bigint)' => ['int', 'int', 'int', 'int', 'string', 'string'],
228+
'MOD(t.col_int, 2)' => ['int', 'int', 'int', 'int', 'string', 'string'],
229+
'MOD(t.col_bigint, 2)' => ['int', 'int', 'int', 'int', 'string', 'string'],
230+
'ABS(t.col_int)' => ['int', 'int', 'int', 'int', 'string', 'string'],
231+
'ABS(t.col_bigint)' => ['int', 'int', 'int', 'int', 'string', 'string'],
231232

232233
// string
233-
't.col_string' => ['string', 'string', 'string', 'string', 'string', 'string'],
234-
'LOWER(t.col_string)' => ['string', 'string', 'string', 'string', 'string', 'string'],
235-
'UPPER(t.col_string)' => ['string', 'string', 'string', 'string', 'string', 'string'],
236-
'TRIM(t.col_string)' => ['string', 'string', 'string', 'string', 'string', 'string'],
234+
't.col_string' => ['string', 'string', 'string', 'string', 'string', 'string'],
235+
'LOWER(t.col_string)' => ['string', 'string', 'string', 'string', 'string', 'string'],
236+
'UPPER(t.col_string)' => ['string', 'string', 'string', 'string', 'string', 'string'],
237+
'TRIM(t.col_string)' => ['string', 'string', 'string', 'string', 'string', 'string'],
237238
];
238239

239240
$selects = array_keys($testData);

tests/Type/Doctrine/Query/QueryResultTypeWalkerTest.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
use Doctrine\ORM\Tools\SchemaTool;
1414
use PHPStan\Testing\PHPStanTestCase;
1515
use PHPStan\Type\Accessory\AccessoryNumericStringType;
16+
use PHPStan\Type\BooleanType;
1617
use PHPStan\Type\Constant\ConstantArrayTypeBuilder;
18+
use PHPStan\Type\Constant\ConstantBooleanType;
1719
use PHPStan\Type\Constant\ConstantIntegerType;
1820
use PHPStan\Type\Constant\ConstantStringType;
1921
use PHPStan\Type\ConstantTypeHelper;
@@ -794,7 +796,8 @@ public function getTestData(): iterable
794796
TypeCombinator::union(
795797
new ConstantIntegerType(1),
796798
new ConstantStringType('1'),
797-
new NullType()
799+
new NullType(),
800+
new ConstantBooleanType(true)
798801
),
799802
],
800803
]),
@@ -810,7 +813,8 @@ public function getTestData(): iterable
810813
new ConstantIntegerType(1),
811814
TypeCombinator::union(
812815
new StringType(),
813-
new IntegerType()
816+
new IntegerType(),
817+
new ConstantBooleanType(false)
814818
),
815819
],
816820
[
@@ -839,6 +843,7 @@ public function getTestData(): iterable
839843
new ConstantIntegerType(1),
840844
TypeCombinator::union(
841845
new StringType(),
846+
new ConstantBooleanType(false),
842847
new ConstantIntegerType(0)
843848
),
844849
],
@@ -859,6 +864,7 @@ public function getTestData(): iterable
859864
new ConstantIntegerType(1),
860865
TypeCombinator::union(
861866
new StringType(),
867+
new ConstantBooleanType(false),
862868
new ConstantIntegerType(0)
863869
),
864870
],
@@ -881,7 +887,8 @@ public function getTestData(): iterable
881887
new ConstantIntegerType(0),
882888
new ConstantIntegerType(1),
883889
new ConstantStringType('0'),
884-
new ConstantStringType('1')
890+
new ConstantStringType('1'),
891+
new BooleanType()
885892
),
886893
],
887894
]),
@@ -902,7 +909,8 @@ public function getTestData(): iterable
902909
new ConstantIntegerType(0),
903910
new ConstantIntegerType(1),
904911
new ConstantStringType('0'),
905-
new ConstantStringType('1')
912+
new ConstantStringType('1'),
913+
new BooleanType()
906914
),
907915
],
908916
]),
@@ -921,28 +929,32 @@ public function getTestData(): iterable
921929
new ConstantIntegerType(1),
922930
TypeCombinator::union(
923931
new ConstantIntegerType(1),
924-
new ConstantStringType('1')
932+
new ConstantStringType('1'),
933+
new ConstantBooleanType(true)
925934
),
926935
],
927936
[
928937
new ConstantIntegerType(2),
929938
TypeCombinator::union(
930939
new ConstantIntegerType(0),
931-
new ConstantStringType('0')
940+
new ConstantStringType('0'),
941+
new ConstantBooleanType(false)
932942
),
933943
],
934944
[
935945
new ConstantIntegerType(3),
936946
TypeCombinator::union(
937947
new ConstantIntegerType(1),
938-
new ConstantStringType('1')
948+
new ConstantStringType('1'),
949+
new ConstantBooleanType(true)
939950
),
940951
],
941952
[
942953
new ConstantIntegerType(4),
943954
TypeCombinator::union(
944955
new ConstantIntegerType(0),
945-
new ConstantStringType('0')
956+
new ConstantStringType('0'),
957+
new ConstantBooleanType(false)
946958
),
947959
],
948960
]),

0 commit comments

Comments
 (0)