Skip to content

Commit

Permalink
Add IDENTITY() type inference support
Browse files Browse the repository at this point in the history
Supports IDENTITY(a.assoc) or IDENTITY(a.assoc, 'id_field') where
'id_field' is the name of one of the id fields of the target class.

Does not support IDENTITY(a.assoc) when the target id field is also an
association.
  • Loading branch information
arnaud-lb authored and ondrejmirtes committed Jan 28, 2022
1 parent 46256c9 commit c49475b
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/Type/Doctrine/Query/QueryResultTypeWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,55 @@ public function walkFunction($function)

return $this->marshalType($type);

case $function instanceof AST\Functions\IdentityFunction:
$dqlAlias = $function->pathExpression->identificationVariable;
$assocField = $function->pathExpression->field;
$queryComp = $this->queryComponents[$dqlAlias];
$class = $queryComp['metadata'];
$assoc = $class->associationMappings[$assocField];
$targetClass = $this->em->getClassMetadata($assoc['targetEntity']);

if ($function->fieldMapping === null) {
$identifierFieldNames = $targetClass->getIdentifierFieldNames();
if (count($identifierFieldNames) === 0) {
throw new ShouldNotHappenException();
}

$targetFieldName = $identifierFieldNames[0];
} else {
$targetFieldName = $function->fieldMapping;
}

$typeName = $targetClass->getTypeOfField($targetFieldName);
if ($typeName === null) {
return $this->marshalType(new MixedType());
}

$fieldMapping = $targetClass->fieldMappings[$targetFieldName] ?? null;
if ($fieldMapping === null) {
return $this->marshalType(new MixedType());
}

$joinColumn = null;

foreach ($assoc['joinColumns'] as $item) {
if ($item['referencedColumnName'] === $fieldMapping['columnName']) {
$joinColumn = $item;
break;
}
}

if ($joinColumn === null) {
return $this->marshalType(new MixedType());
}

$nullable = (bool) ($joinColumn['nullable'] ?? true)
|| $this->hasAggregateWithoutGroupBy();

$fieldType = $this->resolveDatabaseInternalType($typeName, $nullable);

return $this->marshalType($fieldType);

default:
return $this->marshalType(new MixedType());
}
Expand Down
23 changes: 23 additions & 0 deletions tests/Type/Doctrine/Query/QueryResultTypeWalkerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,29 @@ public function getTestData(): array
FROM QueryResult\Entities\Many m
',
],
'identity function' => [
$this->constantArray([
[new ConstantIntegerType(1), TypeCombinator::addNull($this->numericStringOrInt())],
[new ConstantIntegerType(2), $this->numericStringOrInt()],
[new ConstantIntegerType(3), TypeCombinator::addNull($this->numericStringOrInt())],
[new ConstantIntegerType(4), TypeCombinator::addNull(new StringType())],
[new ConstantIntegerType(5), TypeCombinator::addNull(new StringType())],
[new ConstantIntegerType(6), TypeCombinator::addNull($this->numericStringOrInt())],
[new ConstantIntegerType(7), TypeCombinator::addNull(new MixedType())],
[new ConstantIntegerType(8), TypeCombinator::addNull($this->numericStringOrInt())],
]),
'
SELECT IDENTITY(m.oneNull),
IDENTITY(m.one),
IDENTITY(m.oneDefaultNullability),
IDENTITY(m.compoundPk),
IDENTITY(m.compoundPk, \'id\'),
IDENTITY(m.compoundPk, \'version\'),
IDENTITY(m.compoundPkAssoc),
IDENTITY(m.compoundPkAssoc, \'version\')
FROM QueryResult\Entities\Many m
',
],
'select nullable association' => [
$this->constantArray([
[new ConstantIntegerType(1), TypeCombinator::addNull($this->numericStringOrInt())],
Expand Down
35 changes: 35 additions & 0 deletions tests/Type/Doctrine/data/QueryResult/Entities/CompoundPk.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);

namespace QueryResult\Entities;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Embedded as ORMEmbedded;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use QueryResult\Entities\One;

/**
* @Entity
*/
class CompoundPk
{
/**
* @Column(type="string")
* @Id
*
* @var string
*/
public $id;

/**
* @Column(type="integer")
* @Id
*
* @var int
*/
public $version;
}
36 changes: 36 additions & 0 deletions tests/Type/Doctrine/data/QueryResult/Entities/CompoundPkAssoc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php declare(strict_types=1);

namespace QueryResult\Entities;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Embedded as ORMEmbedded;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use QueryResult\Entities\One;

/**
* @Entity
*/
class CompoundPkAssoc
{
/**
* @ManyToOne(targetEntity="QueryResult\Entities\One")
* @JoinColumn(nullable=false)
* @Id
*
* @var One
*/
public $one;

/**
* @Column(type="integer")
* @Id
*
* @var int
*/
public $version;
}
23 changes: 23 additions & 0 deletions tests/Type/Doctrine/data/QueryResult/Entities/Many.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\JoinColumns;
use Doctrine\ORM\Mapping\ManyToOne;

/**
Expand Down Expand Up @@ -78,4 +79,26 @@ class Many
* @var One|null
*/
public $oneDefaultNullability;

/**
* @ManyToOne(targetEntity="QueryResult\Entities\CompoundPk")
* @JoinColumns({
* @JoinColumn(name="compoundPk_id", referencedColumnName="id"),
* @JoinColumn(name="compoundPk_version", referencedColumnName="version")
* })
*
* @var CompoundPk|null
*/
public $compoundPk;

/**
* @ManyToOne(targetEntity="QueryResult\Entities\CompoundPkAssoc")
* @JoinColumns({
* @JoinColumn(name="compoundPk_one", referencedColumnName="one_id"),
* @JoinColumn(name="compoundPk_version", referencedColumnName="version")
* })
*
* @var CompoundPkAssoc|null
*/
public $compoundPkAssoc;
}

0 comments on commit c49475b

Please sign in to comment.