Skip to content

Commit

Permalink
Ensure that only one typecaster is attached.
Browse files Browse the repository at this point in the history
If multiple type casters are attached we waste cycles. More importantly,
we also cause fatal errors for folks loading datetimes in non-english
locales.

Refs #8157
  • Loading branch information
markstory committed Feb 3, 2016
1 parent 0b33513 commit 0571c5c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
11 changes: 10 additions & 1 deletion src/Database/Query.php
Expand Up @@ -129,6 +129,13 @@ class Query implements ExpressionInterface, IteratorAggregate
*/
protected $_selectTypeMap;

/**
* Tracking flag to ensure only one type caster is appended.
*
* @var bool
*/
protected $_typeCastAttached = false;

/**
* Constructor.
*
Expand Down Expand Up @@ -183,8 +190,9 @@ public function execute()
$driver = $this->_connection->driver();
$typeMap = $this->selectTypeMap();

if ($typeMap->toArray()) {
if ($typeMap->toArray() && $this->_typeCastAttached === false) {
$this->decorateResults(new FieldTypeConverter($typeMap, $driver));
$this->_typeCastAttached = true;
}

$this->_iterator = $this->_decorateStatement($statement);
Expand Down Expand Up @@ -1630,6 +1638,7 @@ public function decorateResults($callback, $overwrite = false)
{
if ($overwrite) {
$this->_resultDecorators = [];
$this->_typeCastAttached = false;
}

if ($callback !== null) {
Expand Down
1 change: 0 additions & 1 deletion tests/TestCase/Database/QueryTest.php
Expand Up @@ -3547,7 +3547,6 @@ public function testSelectTypeMap()
public function testSelectTypeConversion()
{
$query = new Query($this->connection);
$time = new \DateTime('2007-03-18 10:50:00');
$query
->select(['id', 'comment', 'the_date' => 'created'])
->from('comments')
Expand Down
21 changes: 21 additions & 0 deletions tests/TestCase/ORM/QueryTest.php
Expand Up @@ -3197,4 +3197,25 @@ public function testNotMatchingNested()
];
$this->assertEquals($expected, $results->first());
}

/**
* Test that type conversion is only applied once.
*
* @return void
*/
public function testAllNoDuplicateTypeCasting()
{
$table = TableRegistry::get('Comments');
$query = $table->find()
->select(['id', 'comment', 'created']);

// Convert to an array and make the query dirty again.
$result = $query->all()->toArray();
$query->limit(99);

// Get results a second time.
$result2 = $query->all()->toArray();

$this->assertEquals(1, $query->__debugInfo()['decorators'], 'Only one typecaster should exist');
}
}

0 comments on commit 0571c5c

Please sign in to comment.