Skip to content

Commit 0571c5c

Browse files
committed
Ensure that only one typecaster is attached.
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
1 parent 0b33513 commit 0571c5c

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

src/Database/Query.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,13 @@ class Query implements ExpressionInterface, IteratorAggregate
129129
*/
130130
protected $_selectTypeMap;
131131

132+
/**
133+
* Tracking flag to ensure only one type caster is appended.
134+
*
135+
* @var bool
136+
*/
137+
protected $_typeCastAttached = false;
138+
132139
/**
133140
* Constructor.
134141
*
@@ -183,8 +190,9 @@ public function execute()
183190
$driver = $this->_connection->driver();
184191
$typeMap = $this->selectTypeMap();
185192

186-
if ($typeMap->toArray()) {
193+
if ($typeMap->toArray() && $this->_typeCastAttached === false) {
187194
$this->decorateResults(new FieldTypeConverter($typeMap, $driver));
195+
$this->_typeCastAttached = true;
188196
}
189197

190198
$this->_iterator = $this->_decorateStatement($statement);
@@ -1630,6 +1638,7 @@ public function decorateResults($callback, $overwrite = false)
16301638
{
16311639
if ($overwrite) {
16321640
$this->_resultDecorators = [];
1641+
$this->_typeCastAttached = false;
16331642
}
16341643

16351644
if ($callback !== null) {

tests/TestCase/Database/QueryTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3547,7 +3547,6 @@ public function testSelectTypeMap()
35473547
public function testSelectTypeConversion()
35483548
{
35493549
$query = new Query($this->connection);
3550-
$time = new \DateTime('2007-03-18 10:50:00');
35513550
$query
35523551
->select(['id', 'comment', 'the_date' => 'created'])
35533552
->from('comments')

tests/TestCase/ORM/QueryTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3197,4 +3197,25 @@ public function testNotMatchingNested()
31973197
];
31983198
$this->assertEquals($expected, $results->first());
31993199
}
3200+
3201+
/**
3202+
* Test that type conversion is only applied once.
3203+
*
3204+
* @return void
3205+
*/
3206+
public function testAllNoDuplicateTypeCasting()
3207+
{
3208+
$table = TableRegistry::get('Comments');
3209+
$query = $table->find()
3210+
->select(['id', 'comment', 'created']);
3211+
3212+
// Convert to an array and make the query dirty again.
3213+
$result = $query->all()->toArray();
3214+
$query->limit(99);
3215+
3216+
// Get results a second time.
3217+
$result2 = $query->all()->toArray();
3218+
3219+
$this->assertEquals(1, $query->__debugInfo()['decorators'], 'Only one typecaster should exist');
3220+
}
32003221
}

0 commit comments

Comments
 (0)