1717use PHPStan \Type \IntegerRangeType ;
1818use PHPStan \Type \IntegerType ;
1919use PHPStan \Type \ObjectType ;
20+ use PHPStan \Type \Type ;
2021use PHPStan \Type \TypeCombinator ;
21- use PHPStan \Type \UnionType ;
2222use PHPStan \Type \VerbosityLevel ;
2323use staabm \PHPStanDba \QueryReflection \QueryReflection ;
2424
@@ -123,8 +123,6 @@ public function processNode(Node $callLike, Scope $scope): array
123123 }
124124 $ schemaReflection = $ this ->queryReflection ->getSchemaReflection ();
125125
126- $ checkIntegerRanges = QueryReflection::getRuntimeConfiguration ()->isParameterTypeValidationStrict ();
127-
128126 $ errors = [];
129127 foreach ($ tableNames as $ tableName ) {
130128 // Table name may be escaped with backticks
@@ -173,29 +171,11 @@ public function processNode(Node $callLike, Scope $scope): array
173171 continue ;
174172 }
175173
176- $ argColumnType = $ argColumn ->getType ();
174+ $ acceptingType = $ this -> getColumnAcceptingType ( $ argColumn ->getType () );
177175 $ valueType = $ argArray ->getValueTypes ()[$ keyIndex ];
178176
179- if (false === $ checkIntegerRanges ) {
180- // Convert IntegerRangeType column types into IntegerType so
181- // that any integer value is accepted for integer columns,
182- // since it is uncommon to check integer value ranges.
183- if ($ argColumnType instanceof IntegerRangeType) {
184- $ argColumnType = new IntegerType ();
185- } elseif ($ argColumnType instanceof UnionType) {
186- $ newTypes = [];
187- foreach ($ argColumnType ->getTypes () as $ type ) {
188- if ($ type instanceof IntegerRangeType) {
189- $ type = new IntegerType ();
190- }
191- $ newTypes [] = $ type ;
192- }
193- $ argColumnType = TypeCombinator::union (...$ newTypes );
194- }
195- }
196-
197- if (! $ argColumnType ->isSuperTypeOf ($ valueType )->yes ()) {
198- $ errors [] = 'Column " ' . $ table ->getName () . '. ' . $ argColumnName . '" expects value type ' . $ argColumnType ->describe (VerbosityLevel::precise ()) . ', got type ' . $ valueType ->describe (VerbosityLevel::precise ());
177+ if (! $ acceptingType ->isSuperTypeOf ($ valueType )->yes ()) {
178+ $ errors [] = 'Column " ' . $ table ->getName () . '. ' . $ argColumnName . '" expects value type ' . $ acceptingType ->describe (VerbosityLevel::precise ()) . ', got type ' . $ valueType ->describe (VerbosityLevel::precise ());
199179 }
200180 }
201181 }
@@ -209,4 +189,33 @@ public function processNode(Node $callLike, Scope $scope): array
209189 }
210190 return $ ruleErrors ;
211191 }
192+
193+ /**
194+ * Converts the column type into the most general type that the column
195+ * will accept.
196+ */
197+ private function getColumnAcceptingType (Type $ columnType ): Type
198+ {
199+ $ checkIntegerRanges = QueryReflection::getRuntimeConfiguration ()->isParameterTypeValidationStrict ();
200+ if (false === $ checkIntegerRanges ) {
201+ // Convert IntegerRangeType column types into IntegerType so
202+ // that any integer value is accepted for integer columns,
203+ // since it is uncommon to check integer value ranges.
204+ $ containedNull = TypeCombinator::containsNull ($ columnType );
205+ $ columnType = TypeCombinator::removeNull ($ columnType );
206+ if ($ columnType instanceof IntegerRangeType) {
207+ $ columnType = new IntegerType ();
208+ }
209+ if ($ containedNull ) {
210+ $ columnType = TypeCombinator::addNull ($ columnType );
211+ }
212+ }
213+
214+ if ($ columnType ->isFloat ()->yes ()) {
215+ // Float column should also accept integer values
216+ $ columnType = TypeCombinator::union (new IntegerType (), $ columnType );
217+ }
218+
219+ return $ columnType ;
220+ }
212221}
0 commit comments