From e41ccdb701dab0c9fb9add319ffdfc1b7eaed1ef Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 30 Sep 2016 22:25:25 -0400 Subject: [PATCH 1/5] Fix enum column length detection. Use simpler code to calculate the length of fields. Include more tests for DboSource as there weren't any before. Refs #9526 --- lib/Cake/Model/Datasource/DboSource.php | 57 ++++++++----------- .../Case/Model/Datasource/DboSourceTest.php | 31 ++++++++++ 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index f37d6310e..68dd384a4 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -3097,54 +3097,45 @@ class DboSource extends DataSource { * @return mixed An integer or string representing the length of the column, or null for unknown length. */ public function length($real) { - if (!preg_match_all('/([\w\s]+)(?:\((\d+)(?:,(\d+))?\))?(\sunsigned)?(\szerofill)?/', $real, $result)) { - $col = str_replace(array(')', 'unsigned'), '', $real); - $limit = null; - - if (strpos($col, '(') !== false) { - list($col, $limit) = explode('(', $col); - } - if ($limit !== null) { - return (int)$limit; - } - return null; - } - + preg_match('/([\w\s]+)(?:\((.+?)\))?(\sunsigned)?/i', $real, $result); $types = array( 'int' => 1, 'tinyint' => 1, 'smallint' => 1, 'mediumint' => 1, 'integer' => 1, 'bigint' => 1 ); - list($real, $type, $length, $offset, $sign) = $result; - $typeArr = $type; - $type = $type[0]; - $length = $length[0]; - $offset = $offset[0]; + $type = $length = null; + if (isset($result[1])) { + $type = $result[1]; + } + if (isset($result[2])) { + $length = $result[2]; + } + $sign = isset($result[3]); $isFloat = in_array($type, array('dec', 'decimal', 'float', 'numeric', 'double')); - if ($isFloat && $offset) { - return $length . ',' . $offset; + if ($isFloat && strpos($length, ',') !== false) { + return $length; } - if (($real[0] == $type) && (count($real) === 1)) { + if ($length === null) { return null; } if (isset($types[$type])) { - $length += $types[$type]; - if (!empty($sign)) { - $length--; - } - } elseif (in_array($type, array('enum', 'set'))) { - $length = 0; - foreach ($typeArr as $key => $enumValue) { - if ($key === 0) { - continue; - } + return (int)$length; + } + if (in_array($type, array('enum', 'set'))) { + $values = array_map(function($value) { + return trim(trim($value), '\'"'); + }, explode(',', $length)); + + $maxLength = 0; + foreach ($values as $key => $enumValue) { $tmpLength = strlen($enumValue); - if ($tmpLength > $length) { - $length = $tmpLength; + if ($tmpLength > $maxLength) { + $maxLength = $tmpLength; } } + return $maxLength; } return (int)$length; } diff --git a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php index 933cd9347..911faec5c 100644 --- a/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php @@ -1826,4 +1826,35 @@ class DboSourceTest extends CakeTestCase { $this->db->flushQueryCache(); $this->assertAttributeCount(0, '_queryCache', $this->db); } + +/** + * Test length parsing. + * + * @return void + */ + public function testLength() { + $result = $this->db->length('varchar(255)'); + $this->assertEquals(255, $result); + + $result = $this->db->length('integer(11)'); + $this->assertEquals(11, $result); + + $result = $this->db->length('integer unsigned'); + $this->assertNull($result); + + $result = $this->db->length('integer(11) unsigned'); + $this->assertEquals(11, $result); + + $result = $this->db->length('integer(11) zerofill'); + $this->assertEquals(11, $result); + + $result = $this->db->length('decimal(20,3)'); + $this->assertEquals('20,3', $result); + + $result = $this->db->length('enum("one", "longer")'); + $this->assertEquals(6, $result); + + $result = $this->db->length("enum('One Value','ANOTHER ... VALUE ...')"); + $this->assertEquals(21, $result); + } } From 3587ac99762977d8666d28e86ef8dfff3b1ea816 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 2 Oct 2016 19:06:10 -0400 Subject: [PATCH 2/5] Fix PHPCS error. --- lib/Cake/Model/Datasource/DboSource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 68dd384a4..a73eea8a7 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -3124,7 +3124,7 @@ class DboSource extends DataSource { return (int)$length; } if (in_array($type, array('enum', 'set'))) { - $values = array_map(function($value) { + $values = array_map(function ($value) { return trim(trim($value), '\'"'); }, explode(',', $length)); From 3a185f9713970b45f7bfd54ef8b66bb28cc5f48c Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 2 Oct 2016 19:12:34 -0400 Subject: [PATCH 3/5] Remove incorrrect postgres implementation. It was wrong, and no longer really needs to exist as the parent method covers all the scenarios that were previously required other than the uuid one. --- lib/Cake/Model/Datasource/Database/Postgres.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index dfe5272ec..152a9b405 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,19 +727,13 @@ class Postgres extends DboSource { * @return int An integer representing the length of the column */ public function length($real) { - $col = str_replace(array(')', 'unsigned'), '', $real); - $limit = null; - if (strpos($col, '(') !== false) { list($col, $limit) = explode('(', $col); } if ($col === 'uuid') { return 36; } - if ($limit) { - return (int)$limit; - } - return null; + return parent::length($real); } /** From 689d516a9956852e0e611a1228efc6fb8da5219a Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 4 Oct 2016 21:38:26 -0400 Subject: [PATCH 4/5] Fix typo. --- lib/Cake/Model/Datasource/Database/Postgres.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 152a9b405..7c0e58278 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,10 +727,10 @@ class Postgres extends DboSource { * @return int An integer representing the length of the column */ public function length($real) { - if (strpos($col, '(') !== false) { - list($col, $limit) = explode('(', $col); + if (strpos($real, '(') !== false) { + list($real, $limit) = explode('(', $real); } - if ($col === 'uuid') { + if ($real === 'uuid') { return 36; } return parent::length($real); From 9c3b17cbc71dbfd7f936c48ecfd3c7b1f00ea5d0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 5 Oct 2016 22:28:51 -0400 Subject: [PATCH 5/5] Fix failing test in postgres. --- lib/Cake/Model/Datasource/Database/Postgres.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 7c0e58278..8673fbc5c 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,10 +727,11 @@ class Postgres extends DboSource { * @return int An integer representing the length of the column */ public function length($real) { + $col = $real; if (strpos($real, '(') !== false) { - list($real, $limit) = explode('(', $real); + list($col, $limit) = explode('(', $real); } - if ($real === 'uuid') { + if ($col === 'uuid') { return 36; } return parent::length($real);