38
38
use PHPStan \Type \IntersectionType ;
39
39
use PHPStan \Type \MixedType ;
40
40
use PHPStan \Type \NeverType ;
41
+ use PHPStan \Type \NullType ;
41
42
use PHPStan \Type \ObjectType ;
42
43
use PHPStan \Type \StringType ;
43
44
use PHPStan \Type \Type ;
@@ -434,10 +435,10 @@ public function walkFunction($function): string
434
435
$ exprType = $ this ->generalizeLiteralType ($ exprType , false );
435
436
436
437
$ exprTypeNoNull = TypeCombinator::removeNull ($ exprType );
437
- $ nullable = TypeCombinator:: containsNull ($ exprType );
438
+ $ nullable = $ this -> canBeNull ($ exprType );
438
439
439
440
if ($ exprTypeNoNull ->isInteger ()->yes ()) {
440
- $ positiveInt = TypeCombinator:: containsNull ($ exprType )
441
+ $ positiveInt = $ this -> canBeNull ($ exprType )
441
442
? TypeCombinator::addNull (IntegerRangeType::fromInterval (0 , null ))
442
443
: IntegerRangeType::fromInterval (0 , null );
443
444
return $ this ->marshalType ($ positiveInt );
@@ -459,20 +460,18 @@ public function walkFunction($function): string
459
460
$ secondExprType = $ this ->unmarshalType ($ function ->secondArithmetic ->dispatch ($ this ));
460
461
461
462
$ type = IntegerRangeType::fromInterval (0 , null );
462
- if (TypeCombinator:: containsNull ($ firstExprType ) || TypeCombinator:: containsNull ($ secondExprType )) {
463
+ if ($ this -> canBeNull ($ firstExprType ) || $ this -> canBeNull ($ secondExprType )) {
463
464
$ type = TypeCombinator::addNull ($ type );
464
465
}
465
466
466
- // TODO invalid usages
467
-
468
467
return $ this ->marshalType ($ type );
469
468
470
469
case $ function instanceof AST \Functions \ConcatFunction:
471
470
$ hasNull = false ;
472
471
473
472
foreach ($ function ->concatExpressions as $ expr ) {
474
473
$ type = $ this ->unmarshalType ($ expr ->dispatch ($ this ));
475
- $ hasNull = $ hasNull || TypeCombinator:: containsNull ($ type );
474
+ $ hasNull = $ hasNull || $ this -> canBeNull ($ type );
476
475
}
477
476
478
477
$ type = new StringType ();
@@ -493,7 +492,7 @@ public function walkFunction($function): string
493
492
$ intervalExprType = $ this ->unmarshalType ($ function ->intervalExpression ->dispatch ($ this ));
494
493
495
494
$ type = new StringType ();
496
- if (TypeCombinator:: containsNull ($ dateExprType ) || TypeCombinator:: containsNull ($ intervalExprType )) {
495
+ if ($ this -> canBeNull ($ dateExprType ) || $ this -> canBeNull ($ intervalExprType )) {
497
496
$ type = TypeCombinator::addNull ($ type );
498
497
}
499
498
@@ -511,7 +510,7 @@ public function walkFunction($function): string
511
510
$ type = new IntegerType ();
512
511
}
513
512
514
- if (TypeCombinator:: containsNull ($ date1ExprType ) || TypeCombinator:: containsNull ($ date2ExprType )) {
513
+ if ($ this -> canBeNull ($ date1ExprType ) || $ this -> canBeNull ($ date2ExprType )) {
515
514
$ type = TypeCombinator::addNull ($ type );
516
515
}
517
516
@@ -521,7 +520,7 @@ public function walkFunction($function): string
521
520
$ stringPrimaryType = $ this ->unmarshalType ($ function ->stringPrimary ->dispatch ($ this ));
522
521
523
522
$ type = IntegerRangeType::fromInterval (0 , null );
524
- if (TypeCombinator:: containsNull ($ stringPrimaryType )) {
523
+ if ($ this -> canBeNull ($ stringPrimaryType )) {
525
524
$ type = TypeCombinator::addNull ($ type );
526
525
}
527
526
@@ -532,7 +531,7 @@ public function walkFunction($function): string
532
531
$ secondExprType = $ this ->unmarshalType ($ this ->walkStringPrimary ($ function ->secondStringPrimary ));
533
532
534
533
$ type = IntegerRangeType::fromInterval (0 , null );
535
- if (TypeCombinator:: containsNull ($ firstExprType ) || TypeCombinator:: containsNull ($ secondExprType )) {
534
+ if ($ this -> canBeNull ($ firstExprType ) || $ this -> canBeNull ($ secondExprType )) {
536
535
$ type = TypeCombinator::addNull ($ type );
537
536
}
538
537
@@ -544,7 +543,7 @@ public function walkFunction($function): string
544
543
$ stringPrimaryType = $ this ->unmarshalType ($ function ->stringPrimary ->dispatch ($ this ));
545
544
546
545
$ type = new StringType ();
547
- if (TypeCombinator:: containsNull ($ stringPrimaryType )) {
546
+ if ($ this -> canBeNull ($ stringPrimaryType )) {
548
547
$ type = TypeCombinator::addNull ($ type );
549
548
}
550
549
@@ -574,7 +573,7 @@ public function walkFunction($function): string
574
573
575
574
$ type = IntegerRangeType::fromInterval (0 , null );
576
575
577
- if (TypeCombinator:: containsNull ($ firstExprType ) || TypeCombinator:: containsNull ($ secondExprType )) {
576
+ if ($ this -> canBeNull ($ firstExprType ) || $ this -> canBeNull ($ secondExprType )) {
578
577
$ type = TypeCombinator::addNull ($ type );
579
578
}
580
579
@@ -633,7 +632,7 @@ public function walkFunction($function): string
633
632
$ type = new MixedType ();
634
633
}
635
634
636
- if (TypeCombinator:: containsNull ($ exprType )) {
635
+ if ($ this -> canBeNull ($ exprType )) {
637
636
$ type = TypeCombinator::addNull ($ type );
638
637
}
639
638
@@ -650,7 +649,7 @@ public function walkFunction($function): string
650
649
}
651
650
652
651
$ type = new StringType ();
653
- if (TypeCombinator:: containsNull ($ stringType ) || TypeCombinator:: containsNull ($ firstExprType ) || TypeCombinator:: containsNull ($ secondExprType )) {
652
+ if ($ this -> canBeNull ($ stringType ) || $ this -> canBeNull ($ firstExprType ) || $ this -> canBeNull ($ secondExprType )) {
654
653
$ type = TypeCombinator::addNull ($ type );
655
654
}
656
655
@@ -731,7 +730,7 @@ private function inferAvgFunction(AST\Functions\AvgFunction $function): Type
731
730
732
731
$ exprType = $ this ->unmarshalType ($ function ->getSql ($ this ));
733
732
$ exprTypeNoNull = TypeCombinator::removeNull ($ exprType );
734
- $ nullable = TypeCombinator:: containsNull ($ exprType ) || $ this ->hasAggregateWithoutGroupBy ();
733
+ $ nullable = $ this -> canBeNull ($ exprType ) || $ this ->hasAggregateWithoutGroupBy ();
735
734
736
735
$ driver = $ this ->em ->getConnection ()->getDriver ();
737
736
@@ -777,7 +776,7 @@ private function inferSumFunction(AST\Functions\SumFunction $function): Type
777
776
778
777
$ exprType = $ this ->unmarshalType ($ function ->getSql ($ this ));
779
778
$ exprTypeNoNull = TypeCombinator::removeNull ($ exprType );
780
- $ nullable = TypeCombinator:: containsNull ($ exprType ) || $ this ->hasAggregateWithoutGroupBy ();
779
+ $ nullable = $ this -> canBeNull ($ exprType ) || $ this ->hasAggregateWithoutGroupBy ();
781
780
782
781
$ driver = $ this ->em ->getConnection ()->getDriver ();
783
782
@@ -854,7 +853,7 @@ private function containsOnlyTypes(
854
853
*/
855
854
private function generalizeLiteralType (Type $ type , bool $ makeNullable ): Type
856
855
{
857
- $ containsNull = TypeCombinator:: containsNull ($ type );
856
+ $ containsNull = $ this -> canBeNull ($ type );
858
857
$ typeNoNull = TypeCombinator::removeNull ($ type );
859
858
860
859
if (!$ typeNoNull ->isConstantScalarValue ()->yes ()) {
@@ -941,7 +940,7 @@ public function walkCoalesceExpression($coalesceExpression): string
941
940
}
942
941
943
942
$ type = $ this ->unmarshalType ($ expression ->dispatch ($ this ));
944
- $ allTypesContainNull = $ allTypesContainNull && TypeCombinator:: containsNull ($ type );
943
+ $ allTypesContainNull = $ allTypesContainNull && $ this -> canBeNull ($ type );
945
944
946
945
$ expressionTypes [] = $ type ;
947
946
}
@@ -1123,7 +1122,7 @@ public function walkSelectExpression($selectExpression): string
1123
1122
if ($ expr instanceof TypedExpression) {
1124
1123
$ type = TypeCombinator::intersect ( // e.g. count is typed as int, but we infer int<0, max>
1125
1124
$ type ,
1126
- $ this ->resolveDoctrineType (DbalType::lookupName ($ expr ->getReturnType ()), null , TypeCombinator:: containsNull ($ type ))
1125
+ $ this ->resolveDoctrineType (DbalType::lookupName ($ expr ->getReturnType ()), null , $ this -> canBeNull ($ type ))
1127
1126
);
1128
1127
} else {
1129
1128
// Expressions default to Doctrine's StringType, whose
@@ -1642,15 +1641,17 @@ private function inferPlusMinusTimesType(array $termTypes): Type
1642
1641
}
1643
1642
1644
1643
$ union = TypeCombinator::union (...$ types );
1645
- $ nullable = TypeCombinator:: containsNull ($ union );
1644
+ $ nullable = $ this -> canBeNull ($ union );
1646
1645
$ unionWithoutNull = TypeCombinator::removeNull ($ union );
1647
1646
1648
1647
if ($ unionWithoutNull ->isInteger ()->yes ()) {
1649
1648
return $ this ->createInteger ($ nullable );
1650
1649
}
1651
1650
1652
1651
if ($ driver instanceof PdoPgSQLDriver) {
1653
- return $ this ->createNumericString ($ nullable );
1652
+ if ($ this ->containsOnlyTypes ($ unionWithoutNull , [new IntegerType (), new FloatType (), $ this ->createNumericString (false )])) {
1653
+ return $ this ->createNumericString ($ nullable );
1654
+ }
1654
1655
}
1655
1656
1656
1657
if ($ driver instanceof SQLite3Driver || $ driver instanceof PdoSqliteDriver) {
@@ -1725,7 +1726,7 @@ private function inferDivisionType(array $termTypes): Type
1725
1726
}
1726
1727
1727
1728
$ union = TypeCombinator::union (...$ types );
1728
- $ nullable = TypeCombinator:: containsNull ($ union );
1729
+ $ nullable = $ this -> canBeNull ($ union );
1729
1730
$ unionWithoutNull = TypeCombinator::removeNull ($ union );
1730
1731
1731
1732
if ($ unionWithoutNull ->isInteger ()->yes ()) {
@@ -1739,7 +1740,9 @@ private function inferDivisionType(array $termTypes): Type
1739
1740
}
1740
1741
1741
1742
if ($ driver instanceof PdoPgSQLDriver) {
1742
- return $ this ->createNumericString ($ nullable );
1743
+ if ($ this ->containsOnlyTypes ($ unionWithoutNull , [new IntegerType (), new FloatType (), $ this ->createNumericString (false )])) {
1744
+ return $ this ->createNumericString ($ nullable );
1745
+ }
1743
1746
}
1744
1747
1745
1748
if ($ driver instanceof SQLite3Driver || $ driver instanceof PdoSqliteDriver) {
@@ -1937,6 +1940,11 @@ private function resolveDatabaseInternalType(string $typeName, ?string $enumType
1937
1940
return $ type ;
1938
1941
}
1939
1942
1943
+ private function canBeNull (Type $ type ): bool
1944
+ {
1945
+ return !$ type ->accepts (new NullType (), true )->no ();
1946
+ }
1947
+
1940
1948
/**
1941
1949
* Returns whether the query has aggregate function and no group by clause
1942
1950
*
@@ -2041,24 +2049,10 @@ private function shouldStringifyExpressions(Type $type): TrinaryLogic
2041
2049
}
2042
2050
}
2043
2051
2044
- if ($ driver instanceof PgSQLDriver) {
2045
- if ($ type ->isBoolean ()->yes ()) {
2046
- return TrinaryLogic::createNo ();
2047
- } elseif ($ type ->isFloat ()->yes ()) {
2048
- return TrinaryLogic::createNo (); // AVG(col_float) is not, but 0.1 is
2049
- } elseif ($ type ->isInteger ()->yes ()) {
2050
- return TrinaryLogic::createNo ();
2051
- }
2052
- }
2053
-
2054
- if ($ driver instanceof SQLite3Driver) {
2052
+ if ($ driver instanceof PgSQLDriver || $ driver instanceof SQLite3Driver || $ driver instanceof MysqliDriver) {
2055
2053
return TrinaryLogic::createNo ();
2056
2054
}
2057
2055
2058
- if ($ driver instanceof MysqliDriver) {
2059
- return TrinaryLogic::createNo (); // DECIMAL / FLOAT already decided in walkLiteral
2060
- }
2061
-
2062
2056
return TrinaryLogic::createMaybe ();
2063
2057
}
2064
2058
0 commit comments