Skip to content

Commit bf8188c

Browse files
staabmclxmstaab
andauthored
doctrine-dbal: implement fetchAllKeyValue & iterateKeyValue on Result (#215)
Co-authored-by: Markus Staab <[email protected]>
1 parent 38f0ce1 commit bf8188c

File tree

5 files changed

+40
-2
lines changed

5 files changed

+40
-2
lines changed

src/DoctrineReflection/DoctrineReflection.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ public function fetchResultType(MethodReflection $methodReflection, Type $result
2626
$usedMethod = strtolower($methodReflection->getName());
2727

2828
switch ($usedMethod) {
29+
case 'fetchallkeyvalue':
30+
case 'iteratekeyvalue':
31+
$fetchType = QueryReflector::FETCH_TYPE_KEY_VALUE;
32+
break;
2933
case 'fetchone':
3034
$fetchType = QueryReflector::FETCH_TYPE_ONE;
3135
break;
@@ -47,12 +51,25 @@ public function fetchResultType(MethodReflection $methodReflection, Type $result
4751
$fetchType = QueryReflector::FETCH_TYPE_BOTH;
4852
}
4953

50-
if ((\in_array($fetchType, [QueryReflector::FETCH_TYPE_ONE, QueryReflector::FETCH_TYPE_FIRST_COL, QueryReflector::FETCH_TYPE_NUMERIC, QueryReflector::FETCH_TYPE_ASSOC])) && $resultRowType instanceof ConstantArrayType) {
54+
if (QueryReflector::FETCH_TYPE_BOTH !== $fetchType && $resultRowType instanceof ConstantArrayType) {
5155
$builder = ConstantArrayTypeBuilder::createEmpty();
5256

5357
$keyTypes = $resultRowType->getKeyTypes();
5458
$valueTypes = $resultRowType->getValueTypes();
5559

60+
if (QueryReflector::FETCH_TYPE_KEY_VALUE === $fetchType) {
61+
// $valueType contain 'BOTH' fetched values
62+
if (\count($valueTypes) < 4) {
63+
return null;
64+
}
65+
66+
if (\in_array($usedMethod, ['fetchallkeyvalue'], true)) {
67+
return new ArrayType($valueTypes[0], $valueTypes[2]);
68+
}
69+
70+
return new GenericObjectType(Traversable::class, [$valueTypes[0], $valueTypes[2]]);
71+
}
72+
5673
foreach ($keyTypes as $i => $keyType) {
5774
if (QueryReflector::FETCH_TYPE_ONE === $fetchType) {
5875
return $valueTypes[$i];

src/Extensions/DoctrineConnectionFetchDynamicReturnTypeExtension.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,26 @@
2121

2222
final class DoctrineConnectionFetchDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
2323
{
24+
private const METHODS = [
25+
'fetchone',
26+
'fetchfirstcolumn',
27+
'fetchassociative',
28+
'fetchallassociative',
29+
'fetchnumeric',
30+
'fetchallnumeric',
31+
'iteratecolumn',
32+
'iterateassociative',
33+
'iteratenumeric',
34+
];
35+
2436
public function getClass(): string
2537
{
2638
return Connection::class;
2739
}
2840

2941
public function isMethodSupported(MethodReflection $methodReflection): bool
3042
{
31-
return \in_array(strtolower($methodReflection->getName()), ['fetchone', 'fetchfirstcolumn', 'fetchassociative', 'fetchallassociative', 'fetchnumeric', 'fetchallnumeric', 'iteratecolumn', 'iterateassociative', 'iteratenumeric'], true);
43+
return \in_array(strtolower($methodReflection->getName()), self::METHODS, true);
3244
}
3345

3446
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type

src/Extensions/DoctrineResultDynamicReturnTypeExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ final class DoctrineResultDynamicReturnTypeExtension implements DynamicMethodRet
2929
'fetchallnumeric',
3030
'fetchassociative',
3131
'fetchallassociative',
32+
'fetchallkeyvalue',
3233
'iteratenumeric',
3334
'iterateassociative',
3435
'iteratecolumn',
36+
'iteratekeyvalue',
3537
];
3638

3739
public function getClass(): string

src/QueryReflection/QueryReflector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface QueryReflector
1212
public const FETCH_TYPE_ASSOC = 3;
1313
public const FETCH_TYPE_NUMERIC = 4;
1414
public const FETCH_TYPE_BOTH = 5;
15+
public const FETCH_TYPE_KEY_VALUE = 6;
1516

1617
public function validateQueryString(string $queryString): ?Error;
1718

tests/data/doctrine-dbal.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public function foo(Connection $conn)
3434
$fetch = $result->fetchAllAssociative();
3535
assertType('array<int<0, max>, array{email: string, adaid: int<0, 4294967295>, gesperrt: int<-128, 127>, freigabe1u1: int<-128, 127>}>', $fetch);
3636

37+
$fetch = $result->fetchAllKeyValue();
38+
assertType('array<string, int<0, 4294967295>>', $fetch);
39+
3740
$fetch = $result->iterateNumeric();
3841
assertType('Traversable<int, array{string, int<0, 4294967295>, int<-128, 127>, int<-128, 127>}>', $fetch);
3942

@@ -42,6 +45,9 @@ public function foo(Connection $conn)
4245

4346
$fetch = $result->iterateColumn();
4447
assertType('Traversable<int, string>', $fetch);
48+
49+
$fetch = $result->iterateKeyValue();
50+
assertType('Traversable<string, int<0, 4294967295>>', $fetch);
4551
}
4652

4753
public function executeQuery(Connection $conn, array $types, QueryCacheProfile $qcp)

0 commit comments

Comments
 (0)