diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index dfe5272ec..8673fbc5c 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -727,19 +727,14 @@ 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); + $col = $real; + if (strpos($real, '(') !== false) { + list($col, $limit) = explode('(', $real); } if ($col === 'uuid') { return 36; } - if ($limit) { - return (int)$limit; - } - return null; + return parent::length($real); } /** diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index f37d6310e..a73eea8a7 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); + } }