Skip to content

Commit

Permalink
Merge pull request #1339 from BenMorel/dqlcustomtype
Browse files Browse the repository at this point in the history
[DDC-2224] Honor convertToDatabaseValueSQL() in DQL query parameters
  • Loading branch information
Ocramius committed Mar 25, 2015
2 parents dc99ed2 + 9eb458c commit cf1ecff
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 4 deletions.
21 changes: 17 additions & 4 deletions lib/Doctrine/ORM/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ final class Query extends AbstractQuery
*/
private $_state = self::STATE_CLEAN;

/**
* A snapshot of the parameter types the query was parsed with.
*
* @var array
*/
private $_parsedTypes = array();

/**
* Cached DQL query.
*
Expand Down Expand Up @@ -234,12 +241,20 @@ protected function getResultSetMapping()
*/
private function _parse()
{
$types = array();

foreach ($this->parameters as $parameter) {
/** @var Query\Parameter $parameter */
$types[$parameter->getName()] = $parameter->getType();
}

// Return previous parser result if the query and the filter collection are both clean
if ($this->_state === self::STATE_CLEAN && $this->_em->isFiltersStateClean()) {
if ($this->_state === self::STATE_CLEAN && $this->_parsedTypes === $types && $this->_em->isFiltersStateClean()) {
return $this->_parserResult;
}

$this->_state = self::STATE_CLEAN;
$this->_parsedTypes = $types;

// Check query cache.
if ( ! ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver()))) {
Expand Down Expand Up @@ -678,8 +693,6 @@ public function getLockMode()
/**
* Generate a cache id for the query cache - reusing the Result-Cache-Id generator.
*
* The query cache
*
* @return string
*/
protected function _getQueryCacheId()
Expand All @@ -696,7 +709,7 @@ protected function _getQueryCacheId()
'&platform=' . $platform .
($this->_em->hasFilters() ? $this->_em->getFilters()->getHash() : '') .
'&firstResult=' . $this->_firstResult . '&maxResult=' . $this->_maxResults .
'&hydrationMode='.$this->_hydrationMode.'DOCTRINE_QUERY_CACHE_SALT'
'&hydrationMode=' . $this->_hydrationMode . '&types=' . serialize($this->_parsedTypes) . 'DOCTRINE_QUERY_CACHE_SALT'
);
}

Expand Down
6 changes: 6 additions & 0 deletions lib/Doctrine/ORM/Query/SqlWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -2203,6 +2203,12 @@ public function walkInputParameter($inputParam)
{
$this->parserResult->addParameterMapping($inputParam->name, $this->sqlParamIndex++);

$parameter = $this->query->getParameter($inputParam->name);

if ($parameter && Type::hasType($type = $parameter->getType())) {
return Type::getType($type)->convertToDatabaseValueSQL('?', $this->platform);
}

return '?';
}

Expand Down
88 changes: 88 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2224Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\Common\Cache\ArrayCache;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\ORM\Query;

/**
* @group DDC-2224
*/
class DDC2224Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public static function setUpBeforeClass()
{
\Doctrine\DBAL\Types\Type::addType('DDC2224Type', __NAMESPACE__ . '\DDC2224Type');
}

public function testIssue()
{
$dql = 'SELECT e FROM ' . __NAMESPACE__ . '\DDC2224Entity e WHERE e.field = :field';
$query = $this->_em->createQuery($dql);
$query->setQueryCacheDriver(new ArrayCache());

$query->setParameter('field', 'test', 'DDC2224Type');
$this->assertStringEndsWith('.field = FUNCTION(?)', $query->getSQL());

return $query;
}

/**
* @depends testIssue
*/
public function testCacheMissWhenTypeChanges(Query $query)
{
$query->setParameter('field', 'test', 'string');
$this->assertStringEndsWith('.field = ?', $query->getSQL());
}
}

class DDC2224Type extends Type
{
/**
* {@inheritdoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration);
}

public function getName()
{
return 'DDC2224Type';
}

/**
* {@inheritdoc}
*/
public function canRequireSQLConversion()
{
return true;
}

/**
* {@inheritdoc}
*/
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
{
return sprintf('FUNCTION(%s)', $sqlExpr);
}
}

/**
* @Entity
*/
class DDC2224Entity
{
/**
* @Id @GeneratedValue @Column(type="integer")
*/
public $id;

/**
* @Column(type="DDC2224Type")
*/
public $field;
}

0 comments on commit cf1ecff

Please sign in to comment.