Skip to content

Commit 4799f71

Browse files
committed
New testcases, partially fix numeric-string literal issue
1 parent 9f71423 commit 4799f71

File tree

3 files changed

+911
-49
lines changed

3 files changed

+911
-49
lines changed

src/Type/Doctrine/Query/QueryResultTypeWalker.php

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
use function get_class;
5555
use function gettype;
5656
use function is_int;
57+
use function is_numeric;
5758
use function is_object;
5859
use function is_string;
5960
use function method_exists;
@@ -566,14 +567,14 @@ public function walkFunction($function): string
566567
$type = $firstExprType;
567568
$typeNoNull = TypeCombinator::removeNull($type);
568569

569-
// TODO simplify?
570-
571-
if ($typeNoNull->isInteger()->yes()) {
572-
$type = TypeCombinator::containsNull($type)
573-
? TypeCombinator::addNull(IntegerRangeType::fromInterval(0, null))
574-
: IntegerRangeType::fromInterval(0, null);
570+
if (!$typeNoNull->isInteger()->yes()) {
571+
return $this->marshalType(new MixedType()); // dont try to deal with non-integer chaos
575572
}
576573

574+
$type = TypeCombinator::containsNull($type)
575+
? TypeCombinator::addNull(IntegerRangeType::fromInterval(0, null))
576+
: IntegerRangeType::fromInterval(0, null);
577+
577578
if (TypeCombinator::containsNull($firstExprType) || TypeCombinator::containsNull($secondExprType)) {
578579
$type = TypeCombinator::addNull($type);
579580
}
@@ -586,8 +587,6 @@ public function walkFunction($function): string
586587
$type = TypeCombinator::addNull($type);
587588
}
588589

589-
// TODO more invalid usages
590-
591590
return $this->marshalType($this->generalizeLiteralType($type, false));
592591

593592
case $function instanceof AST\Functions\SqrtFunction:
@@ -746,6 +745,10 @@ private function inferAvgFunction(AST\Functions\AvgFunction $function): Type
746745
return $this->createNumericString($nullable);
747746
}
748747

748+
if ($exprTypeNoNull->isString()->yes() && !$exprTypeNoNull->isNumericString()->yes()) {
749+
return $this->createFloat($nullable);
750+
}
751+
749752
return $this->generalizeLiteralType($exprType, $nullable);
750753
}
751754

@@ -780,6 +783,10 @@ private function inferSumFunction(AST\Functions\SumFunction $function): Type
780783
$driver = $this->em->getConnection()->getDriver();
781784

782785
if ($driver instanceof Sqlite3Driver || $driver instanceof PdoSqliteDriver) {
786+
if ($exprTypeNoNull->isString()->yes() && !$exprTypeNoNull->isNumericString()->yes()) {
787+
return $this->createFloat($nullable);
788+
}
789+
783790
return $this->generalizeLiteralType($exprType, $nullable);
784791
}
785792

@@ -788,6 +795,10 @@ private function inferSumFunction(AST\Functions\SumFunction $function): Type
788795
return $this->createNumericString($nullable);
789796
}
790797

798+
if ($exprTypeNoNull->isString()->yes() && !$exprTypeNoNull->isNumericString()->yes()) {
799+
return $this->createFloat($nullable);
800+
}
801+
791802
return $this->generalizeLiteralType($exprType, $nullable);
792803
}
793804

@@ -1382,12 +1393,21 @@ public function walkInParameter($inParam): string
13821393
public function walkLiteral($literal): string
13831394
{
13841395
$driver = $this->em->getConnection()->getDriver();
1396+
$isMysql = $driver instanceof MysqliDriver || $driver instanceof PdoMysqlDriver;
13851397

13861398
switch ($literal->type) {
13871399
case AST\Literal::STRING:
13881400
$value = $literal->value;
13891401
assert(is_string($value));
1390-
$type = new ConstantStringType($value);
1402+
if (is_numeric($value)) {
1403+
if (strpos($value, '.') === false && strpos($value, 'e') === false && !$isMysql) {
1404+
$type = new ConstantIntegerType((int) $value);
1405+
} else {
1406+
$type = new ConstantFloatType((float) $value);
1407+
}
1408+
} else {
1409+
$type = new ConstantStringType($value);
1410+
}
13911411
break;
13921412

13931413
case AST\Literal::BOOLEAN:
@@ -1678,27 +1698,41 @@ private function inferDivisionType(array $termTypes): Type
16781698
return new MixedType();
16791699
}
16801700

1681-
if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), new FloatType(), $this->createNumericString(false)])) {
1682-
if ($driver instanceof PdoPgSQLDriver) {
1683-
return $this->createNumericString($nullable);
1701+
if ($driver instanceof PdoPgSQLDriver) {
1702+
return $this->createNumericString($nullable);
1703+
}
1704+
1705+
if ($driver instanceof SQLite3Driver || $driver instanceof PdoSqliteDriver) {
1706+
if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), new FloatType()])) {
1707+
return $this->createFloat($nullable);
1708+
}
1709+
if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), new StringType()])) {
1710+
return $this->createInteger(true);
16841711
}
1685-
if ($driver instanceof SQLite3Driver || $driver instanceof PdoSqliteDriver) {
1712+
if ($this->containsOnlyTypes($unionWithoutNull, [new FloatType(), new StringType()])) {
1713+
return $this->createFloat(true);
1714+
}
1715+
}
1716+
1717+
if ($driver instanceof MysqliDriver || $driver instanceof PdoMysqlDriver || $driver instanceof PgSQLDriver) {
1718+
if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), new FloatType()])) {
16861719
return $this->createFloat($nullable);
16871720
}
1688-
if ($driver instanceof MysqliDriver || $driver instanceof PdoMysqlDriver || $driver instanceof PgSQLDriver) {
1689-
return TypeCombinator::union( // float vs decimal
1690-
$this->createNumericString($nullable),
1691-
$this->createFloat($nullable)
1692-
);
1721+
1722+
if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), $this->createNumericString(false)])) {
1723+
return $this->createNumericString($nullable);
1724+
}
1725+
1726+
if ($this->containsOnlyTypes($unionWithoutNull, [new IntegerType(), new StringType()])) {
1727+
return $this->createFloat(true);
1728+
}
1729+
1730+
if ($this->containsOnlyTypes($unionWithoutNull, [new FloatType(), new StringType()])) {
1731+
return $this->createFloat(true);
16931732
}
16941733
}
16951734

1696-
// incompatible types, not trying to be precise here, very chaotic behaviour + postgre fails
1697-
return TypeCombinator::union(
1698-
$this->createNumericString(true),
1699-
$this->createFloat(true),
1700-
$this->createInteger(true)
1701-
);
1735+
return new MixedType();
17021736
}
17031737

17041738
/**

0 commit comments

Comments
 (0)