Skip to content

Commit fa19afa

Browse files
committed
round
1 parent 9925ef2 commit fa19afa

File tree

4 files changed

+355
-0
lines changed

4 files changed

+355
-0
lines changed

src/ParserExtension/QueryScope.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function __construct(Table $fromTable, array $joinedTables)
5656
new AvgReturnTypeExtension(),
5757
new IsNullReturnTypeExtension(),
5858
new AbsReturnTypeExtension(),
59+
new RoundReturnTypeExtension(),
5960
];
6061
}
6162

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace staabm\PHPStanDba\ParserExtension;
6+
7+
use PHPStan\Type\FloatType;
8+
use PHPStan\Type\IntegerRangeType;
9+
use PHPStan\Type\IntegerType;
10+
use PHPStan\Type\NullType;
11+
use PHPStan\Type\Type;
12+
use PHPStan\Type\TypeCombinator;
13+
use PHPStan\Type\UnionType;
14+
use SqlFtw\Sql\Expression\BuiltInFunction;
15+
use SqlFtw\Sql\Expression\ExpressionNode;
16+
use SqlFtw\Sql\Expression\FunctionCall;
17+
18+
/**
19+
* @implements QueryExpressionReturnTypeExtension<FunctionCall>
20+
*/
21+
final class RoundReturnTypeExtension implements QueryExpressionReturnTypeExtension
22+
{
23+
public function isExpressionSupported(ExpressionNode $expression): bool
24+
{
25+
return
26+
$expression instanceof FunctionCall
27+
&& \in_array($expression->getFunction()->getName(), [BuiltInFunction::ROUND], true);
28+
}
29+
30+
public function getTypeFromExpression(ExpressionNode $expression, QueryScope $scope): ?Type
31+
{
32+
$args = $expression->getArguments();
33+
34+
if (\count($args) < 1) {
35+
return null;
36+
}
37+
38+
$argType = $scope->getType($args[0]);
39+
if ($argType->isNull()->yes()) {
40+
return new NullType();
41+
}
42+
43+
$containedNull = TypeCombinator::containsNull($argType);
44+
$argType = TypeCombinator::removeNull($argType);
45+
46+
if (1 === \count($args)) {
47+
if (!$argType instanceof IntegerRangeType) {
48+
$argType = new IntegerType();
49+
}
50+
} else {
51+
$argType = new UnionType([
52+
new IntegerType(),
53+
new FloatType(),
54+
]);
55+
}
56+
57+
if ($containedNull) {
58+
$argType = TypeCombinator::addNull($argType);
59+
}
60+
61+
return $argType;
62+
}
63+
}

tests/default/config/.phpunit-phpstan-dba-mysqli.cache

Lines changed: 279 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/default/data/sql-ast-narrowing.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,16 @@ public function abs(PDO $pdo): void
207207
$stmt = $pdo->query('SELECT abs(eladaid) as abs from ak');
208208
assertType('PDOStatement<array{abs: int<0, 2147483647>|null, 0: int<0, 2147483647>|null}>', $stmt);
209209
}
210+
211+
public function round(PDO $pdo): void
212+
{
213+
$stmt = $pdo->query('SELECT round(null) as abs from ada');
214+
assertType('PDOStatement<array{abs: null, 0: null}>', $stmt);
215+
216+
$stmt = $pdo->query('SELECT round(freigabe1u1) as abs from ada');
217+
assertType('PDOStatement<array{abs: int<-128, 127>, 0: int<-128, 127>}>', $stmt);
218+
219+
$stmt = $pdo->query('SELECT round(1.12, 1) as abs from ak');
220+
assertType('PDOStatement<array{abs: float|int, 0: float|int}>', $stmt);
221+
}
210222
}

0 commit comments

Comments
 (0)