Skip to content

Commit be9fc1f

Browse files
authored
Remove use of Mysqli stub and generic mysqli result type (#698)
1 parent 195fe82 commit be9fc1f

File tree

10 files changed

+113
-38
lines changed

10 files changed

+113
-38
lines changed

config/Mysqli.stub

Lines changed: 0 additions & 18 deletions
This file was deleted.

config/stubFiles.neon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,3 @@ parameters:
22
stubFiles:
33
- DoctrineDbal.stub
44
- PdoStatement.stub
5-
- Mysqli.stub

src/DbSchema/SchemaHasherMysql.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public function hashDb(): string
8181

8282
try {
8383
$result = $this->connection->query($query);
84-
if ($result instanceof \mysqli_result) {
84+
if ($result instanceof \mysqli_result) { // @phpstan-ignore-line
8585
$row = $result->fetch_assoc();
8686
$hash = $row['dbsignature'] ?? '';
8787
}

src/Extensions/MysqliQueryDynamicReturnTypeExtension.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,25 @@ private function inferResultType(Expr $queryExpr, Scope $scope): ?Type
121121
$queryReflection = new QueryReflection();
122122
$queryStrings = $queryReflection->resolveQueryStrings($queryExpr, $scope);
123123

124-
$genericObjects = [];
124+
$objects = [];
125125
foreach ($queryStrings as $queryString) {
126126
$resultType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_ASSOC);
127127

128128
if (null === $resultType) {
129129
return null;
130130
}
131131

132-
$genericObjects[] = new MysqliResultObjectType($resultType);
132+
$resultObjectType = new MysqliResultObjectType(\mysqli_result::class);
133+
$resultObjectType->setRowType($resultType);
134+
135+
$objects[] = $resultObjectType;
133136
}
134137

135-
if (0 === \count($genericObjects)) {
138+
if (0 === \count($objects)) {
136139
return null;
137140
}
138141

139-
$resultType = TypeCombinator::union(...$genericObjects);
142+
$resultType = TypeCombinator::union(...$objects);
140143

141144
if (! QueryReflection::getRuntimeConfiguration()->throwsMysqliExceptions($this->phpVersion)) {
142145
return TypeCombinator::union(

src/MysqliReflection/MysqliResultObjectType.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@
44

55
namespace staabm\PHPStanDba\MysqliReflection;
66

7-
use mysqli_result;
8-
use PHPStan\Type\Generic\GenericObjectType;
7+
use PHPStan\ShouldNotHappenException;
8+
use PHPStan\Type\ObjectType;
99
use PHPStan\Type\Type;
1010

11-
final class MysqliResultObjectType extends GenericObjectType
11+
final class MysqliResultObjectType extends ObjectType
1212
{
13-
public function __construct(Type $rowType)
13+
private ?Type $rowType;
14+
15+
public function setRowType(Type $rowType): void {
16+
$this->rowType = $rowType;
17+
}
18+
19+
public function getIterableValueType(): \PHPStan\Type\Type
1420
{
15-
parent::__construct(mysqli_result::class, [$rowType]);
21+
if($this->rowType !== null) {
22+
return $this->rowType;
23+
}
24+
25+
return parent::getIterableValueType();
1626
}
1727
}

tests/default/data/mysqli-escape.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,28 @@ public function escape(mysqli $mysqli, int $i, float $f, $n, string $s, $nonE, s
3737
public function quotedArguments(mysqli $mysqli, int $i, float $f, $n, string $s, $nonE, string $numericString)
3838
{
3939
$result = $mysqli->query('SELECT email, adaid FROM ada WHERE adaid='.$mysqli->real_escape_string((string) $i));
40-
assertType('mysqli_result<array{email: string, adaid: int<-32768, 32767>}>', $result);
40+
foreach ($result as $row) {
41+
assertType('int<-32768, 32767>', $row['adaid']);
42+
assertType('string', $row['email']);
43+
}
4144

4245
$result = $mysqli->query('SELECT email, adaid FROM ada WHERE adaid='.$mysqli->real_escape_string((string) $f));
43-
assertType('mysqli_result<array{email: string, adaid: int<-32768, 32767>}>', $result);
46+
foreach ($result as $row) {
47+
assertType('int<-32768, 32767>', $row['adaid']);
48+
assertType('string', $row['email']);
49+
}
4450

4551
$result = $mysqli->query('SELECT email, adaid FROM ada WHERE adaid='.$mysqli->real_escape_string((string) $n));
46-
assertType('mysqli_result<array{email: string, adaid: int<-32768, 32767>}>', $result);
52+
foreach ($result as $row) {
53+
assertType('int<-32768, 32767>', $row['adaid']);
54+
assertType('string', $row['email']);
55+
}
4756

4857
$result = $mysqli->query('SELECT email, adaid FROM ada WHERE adaid='.$mysqli->real_escape_string($numericString));
49-
assertType('mysqli_result<array{email: string, adaid: int<-32768, 32767>}>', $result);
58+
foreach ($result as $row) {
59+
assertType('int<-32768, 32767>', $row['adaid']);
60+
assertType('string', $row['email']);
61+
}
5062

5163
// when quote() cannot return a numeric-string, we can't infer the precise result-type
5264
$result = $mysqli->query('SELECT email, adaid FROM ada WHERE adaid='.$mysqli->real_escape_string($s));

tests/default/data/mysqli-union-result.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ public function doBar(mysqli $mysqli)
1313

1414
foreach ($queries as $query) {
1515
$result = $mysqli->query($query);
16-
assertType('mysqli_result<array{adaid: int<-32768, 32767>}>|mysqli_result<array{email: string}>', $result);
16+
17+
foreach ($result as $row) {
18+
assertType('int<-32768, 32767>', $row['adaid']);
19+
assertType('string', $row['email']);
20+
}
1721
}
1822
}
1923
}

tests/default/data/mysqli.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ class Foo
1010
public function ooQuerySelected(mysqli $mysqli)
1111
{
1212
$result = $mysqli->query('SELECT email, adaid FROM ada');
13-
assertType('mysqli_result<array{email: string, adaid: int<-32768, 32767>}>', $result);
1413

1514
$field = 'email';
1615
if (rand(0, 1)) {
@@ -33,7 +32,6 @@ public function ooQuery(mysqli $mysqli, string $query)
3332
public function fnQuerySelected(mysqli $mysqli)
3433
{
3534
$result = mysqli_query($mysqli, 'SELECT email, adaid FROM ada');
36-
assertType('mysqli_result<array{email: string, adaid: int<-32768, 32767>}>', $result);
3735

3836
foreach ($result as $row) {
3937
assertType('int<-32768, 32767>', $row['adaid']);

tests/default/data/typemix-mysql.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,50 @@ class TypemixMysql
1313
public function typemixMysqli(mysqli $mysqli)
1414
{
1515
$result = mysqli_query($mysqli, 'SELECT * FROM typemix');
16-
assertType('mysqli_result<' . self::MYSQL_DATATYPES . '>', $result);
16+
17+
foreach($result as $value) {
18+
assertType('int<0, 4294967295>', $value['pid']);
19+
assertType('string', $value['c_char5']);
20+
assertType('string', $value['c_varchar255']);
21+
assertType('string|null', $value['c_varchar25']);
22+
assertType('string', $value['c_varbinary255']);
23+
assertType('string|null', $value['c_varbinary25']);
24+
assertType('string|null', $value['c_date']);
25+
assertType('string|null', $value['c_time']);
26+
assertType('string|null', $value['c_datetime']);
27+
assertType('string|null', $value['c_timestamp']);
28+
assertType('int<0, 2155>|null', $value['c_year']);
29+
assertType('string|null', $value['c_tiny_text']);
30+
assertType('string|null', $value['c_medium_text']);
31+
assertType('string|null', $value['c_text']);
32+
assertType('string|null', $value['c_long_text']);
33+
assertType('string', $value['c_enum']);
34+
assertType('string', $value['c_set']);
35+
assertType('int|null', $value['c_bit']);
36+
assertType('int<-2147483648, 2147483647>', $value['c_int']);
37+
assertType('int<-128, 127>', $value['c_tinyint']);
38+
assertType('int<-128, 127>|null', $value['c_nullable_tinyint']);
39+
assertType('int<-32768, 32767>', $value['c_smallint']);
40+
assertType('int<-8388608, 8388607>', $value['c_mediumint']);
41+
assertType('int', $value['c_bigint']);
42+
assertType('float', $value['c_double']);
43+
assertType('float', $value['c_real']);
44+
assertType('float', $value['c_float']);
45+
assertType('int<-128, 127>', $value['c_boolean']);
46+
assertType('string', $value['c_blob']);
47+
assertType('string', $value['c_tinyblob']);
48+
assertType('string', $value['c_mediumblog']);
49+
assertType('string', $value['c_longblob']);
50+
assertType('int<0, 255>', $value['c_unsigned_tinyint']);
51+
assertType('int<0, 4294967295>', $value['c_unsigned_int']);
52+
assertType('int<0, 65535>', $value['c_unsigned_smallint']);
53+
assertType('int<0, 16777215>', $value['c_unsigned_mediumint']);
54+
assertType('int<0, max>', $value['c_unsigned_bigint']);
55+
assertType('string|null', $value['c_json']);
56+
assertType('string', $value['c_json_not_null']);
57+
assertType('numeric-string|null', $value['c_decimal']);
58+
assertType('numeric-string', $value['c_decimal_not_null']);
59+
}
1760
}
1861

1962
public function typemixPdoMysql(PDO $pdo)

tests/default/data/typemix-pgsql.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,31 @@ class TypemixPgsql
1313
public function typemixMysqli(mysqli $mysqli)
1414
{
1515
$result = mysqli_query($mysqli, 'SELECT * FROM typemix');
16-
assertType('mysqli_result<' . self::PGSQL_DATATYPES . '>', $result);
16+
17+
foreach($result as $value) {
18+
assertType('int<1, 2147483647>', $value['pid']);
19+
assertType('string', $value['c_varchar5']);
20+
assertType('string|null', $value['c_varchar25']);
21+
assertType('string', $value['c_varchar255']);
22+
assertType('string|null', $value['c_date']);
23+
assertType('string|null', $value['c_time']);
24+
assertType('string|null', $value['c_datetime']);
25+
assertType('string|null', $value['c_timestamp']);
26+
assertType('string|null', $value['c_text']);
27+
assertType('mixed', $value['c_enum']);
28+
assertType('int', $value['c_bit255']);
29+
assertType('int|null', $value['c_bit25']);
30+
assertType('int|null', $value['c_bit']);
31+
assertType('int<-2147483648, 2147483647>', $value['c_int']);
32+
assertType('int<-32768, 32767>', $value['c_smallint']);
33+
assertType('int', $value['c_bigint']);
34+
assertType('float', $value['c_float']);
35+
assertType('bool', $value['c_boolean']);
36+
assertType('string', $value['c_json']);
37+
assertType('string|null', $value['c_json_nullable']);
38+
assertType('string', $value['c_jsonb']);
39+
assertType('string|null', $value['c_jsonb_nullable']);
40+
}
1741
}
1842

1943
public function typemixPdoPgsql(PDO $pdo)

0 commit comments

Comments
 (0)