From 15ccf057f4c0ace4be92bb998a1c07f653245155 Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Sat, 12 Nov 2016 00:18:13 +0100 Subject: [PATCH 1/4] Make it possible to configure cacheMethodHashAlgo in DboSource --- lib/Cake/Model/Datasource/DboSource.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index a73eea8a7..32081a332 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -51,22 +51,35 @@ class DboSource extends DataSource { public $alias = 'AS '; /** - * Caches result from query parsing operations. Cached results for both DboSource::name() and - * DboSource::conditions() will be stored here. Method caching uses `md5()`. If you have - * problems with collisions, set DboSource::$cacheMethods to false. + * Caches result from query parsing operations. Cached results for both DboSource::name(), DboSource::fields() and + * DboSource::conditions() will be stored here. + * + * Method caching uses `md5` (by default) to construct cache keys. + * If you have problems with collisions, try a different hashing algorithm in DboSource::$cacheMethodHashAlgo or + * set DboSource::$cacheMethods to false. * * @var array */ public static $methodCache = array(); /** - * Whether or not to cache the results of DboSource::name() and DboSource::conditions() + * Whether or not to cache the results of DboSource::name(), DboSource::fields() and DboSource::conditions() * into the memory cache. Set to false to disable the use of the memory cache. * * @var bool */ public $cacheMethods = true; +/** + * Method caching uses `md5` (by default) to construct cache keys. If you have problems with collisions, + * try a different hashing algorithm or set DboSource::$cacheMethods to false. + * + * @var string + * @see http://php.net/manual/en/function.hash-algos.php + * @see http://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed + */ + public $cacheMethodHashAlgo = 'md5'; + /** * Flag to support nested transactions. If it is set to false, you will be able to use * the transaction methods (begin/commit/rollback), but just the global transaction will @@ -815,7 +828,7 @@ class DboSource extends DataSource { } return $data; } - $cacheKey = md5($this->startQuote . $data . $this->endQuote); + $cacheKey = hash($this->cacheMethodHashAlgo, $this->startQuote . $data . $this->endQuote); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } @@ -2533,7 +2546,7 @@ class DboSource extends DataSource { $Model->schemaName, $Model->table ); - $cacheKey = md5(serialize($cacheKey)); + $cacheKey = hash($this->cacheMethodHashAlgo, serialize($cacheKey)); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } From e186ffc6d35c70330250042a064263a87864f17a Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Mon, 14 Nov 2016 09:42:19 +0100 Subject: [PATCH 2/4] Change cacheMethodHashAlgo to be a method --- lib/Cake/Model/Datasource/DboSource.php | 42 ++++++++++++++----------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 32081a332..173afa06f 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -51,35 +51,24 @@ class DboSource extends DataSource { public $alias = 'AS '; /** - * Caches result from query parsing operations. Cached results for both DboSource::name(), DboSource::fields() and - * DboSource::conditions() will be stored here. + * Caches result from query parsing operations. Cached results for both DboSource::name() and DboSource::fields() + * will be stored here. * - * Method caching uses `md5` (by default) to construct cache keys. - * If you have problems with collisions, try a different hashing algorithm in DboSource::$cacheMethodHashAlgo or - * set DboSource::$cacheMethods to false. + * Method caching uses `md5` (by default) to construct cache keys. If you have problems with collisions, + * try a different hashing algorithm by overriding DboSource::cacheMethodHasher or set DboSource::$cacheMethods to false. * * @var array */ public static $methodCache = array(); /** - * Whether or not to cache the results of DboSource::name(), DboSource::fields() and DboSource::conditions() - * into the memory cache. Set to false to disable the use of the memory cache. + * Whether or not to cache the results of DboSource::name() and DboSource::fields() into the memory cache. + * Set to false to disable the use of the memory cache. * * @var bool */ public $cacheMethods = true; -/** - * Method caching uses `md5` (by default) to construct cache keys. If you have problems with collisions, - * try a different hashing algorithm or set DboSource::$cacheMethods to false. - * - * @var string - * @see http://php.net/manual/en/function.hash-algos.php - * @see http://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed - */ - public $cacheMethodHashAlgo = 'md5'; - /** * Flag to support nested transactions. If it is set to false, you will be able to use * the transaction methods (begin/commit/rollback), but just the global transaction will @@ -803,6 +792,21 @@ class DboSource extends DataSource { return static::$methodCache[$method][$key] = $value; } +/** + * Hashes a given value. + * + * Method caching uses `md5` (by default) to construct cache keys. If you have problems with collisions, + * try a different hashing algorithm or set DboSource::$cacheMethods to false. + * + * @param string $value Value to hash + * @return string Hashed value + * @see http://php.net/manual/en/function.hash-algos.php + * @see http://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed + */ + public function cacheMethodHasher($value) { + return md5($value); + } + /** * Returns a quoted name of $data for use in an SQL statement. * Strips fields out of SQL functions before quoting. @@ -828,7 +832,7 @@ class DboSource extends DataSource { } return $data; } - $cacheKey = hash($this->cacheMethodHashAlgo, $this->startQuote . $data . $this->endQuote); + $cacheKey = $this->cacheMethodHasher($this->startQuote . $data . $this->endQuote); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } @@ -2546,7 +2550,7 @@ class DboSource extends DataSource { $Model->schemaName, $Model->table ); - $cacheKey = hash($this->cacheMethodHashAlgo, serialize($cacheKey)); + $cacheKey = $this->cacheMethodHasher(serialize($cacheKey)); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } From 7ffb5c36008935aa92250c413e017a93386d002a Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Mon, 14 Nov 2016 10:00:47 +0100 Subject: [PATCH 3/4] Add tests for cacheMethodHasher --- .../Case/Model/Datasource/DboSourceTest.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php index 911faec5c..b55fb5088 100644 --- a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php @@ -737,6 +737,34 @@ class DboSourceTest extends CakeTestCase { $this->assertNull($result); } +/** + * Test that cacheMethodHasher uses md5 by default. + * + * @return void + */ + public function testCacheMethodHasher() { + $name = 'Model.fieldlbqndkezcoapfgirmjsh'; + $actual = $this->testDb->cacheMethodHasher($name); + $expected = '4a45dc9ed52f98c393d04ac424ee5078'; + + $this->assertEquals($expected, $actual); + } + +/** + * Test that cacheMethodHasher can be overridden to use a different hashing algorithm. + * + * @return void + */ + public function testCacheMethodHasherOverridden() { + $testDb = new DboThirdTestSource(); + + $name = 'Model.fieldlbqndkezcoapfgirmjsh'; + $actual = $testDb->cacheMethodHasher($name); + $expected = 'f4441bb8fcbe0944'; + + $this->assertEquals($expected, $actual); + } + /** * Test that rare collisions do not happen with method caching * From 5947c2346bd7232f0e4dfb105d86a3dce3c5992c Mon Sep 17 00:00:00 2001 From: Mischa ter Smitten Date: Mon, 14 Nov 2016 10:27:51 +0100 Subject: [PATCH 4/4] Fix failing test --- .../Case/Model/Datasource/DboSourceTest.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php index b55fb5088..030a8ef4c 100644 --- a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php @@ -109,6 +109,23 @@ class DboSecondTestSource extends DboSource { } +/** + * DboThirdTestSource + * + * @package Cake.Test.Case.Model.Datasource + */ +class DboThirdTestSource extends DboSource { + + public function connect($config = array()) { + $this->connected = true; + } + + public function cacheMethodHasher($value) { + return hash('sha1', $value); + } + +} + /** * DboSourceTest class * @@ -760,7 +777,7 @@ class DboSourceTest extends CakeTestCase { $name = 'Model.fieldlbqndkezcoapfgirmjsh'; $actual = $testDb->cacheMethodHasher($name); - $expected = 'f4441bb8fcbe0944'; + $expected = 'beb8b6469359285b7c2865dce0ef743feb16cb71'; $this->assertEquals($expected, $actual); }