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
This commit is contained in:
mark_story 2016-09-30 22:25:25 -04:00
parent 5e0dc218f1
commit e41ccdb701
2 changed files with 55 additions and 33 deletions

View file

@ -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. * @return mixed An integer or string representing the length of the column, or null for unknown length.
*/ */
public function length($real) { public function length($real) {
if (!preg_match_all('/([\w\s]+)(?:\((\d+)(?:,(\d+))?\))?(\sunsigned)?(\szerofill)?/', $real, $result)) { preg_match('/([\w\s]+)(?:\((.+?)\))?(\sunsigned)?/i', $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;
}
$types = array( $types = array(
'int' => 1, 'tinyint' => 1, 'smallint' => 1, 'mediumint' => 1, 'integer' => 1, 'bigint' => 1 'int' => 1, 'tinyint' => 1, 'smallint' => 1, 'mediumint' => 1, 'integer' => 1, 'bigint' => 1
); );
list($real, $type, $length, $offset, $sign) = $result; $type = $length = null;
$typeArr = $type; if (isset($result[1])) {
$type = $type[0]; $type = $result[1];
$length = $length[0]; }
$offset = $offset[0]; if (isset($result[2])) {
$length = $result[2];
}
$sign = isset($result[3]);
$isFloat = in_array($type, array('dec', 'decimal', 'float', 'numeric', 'double')); $isFloat = in_array($type, array('dec', 'decimal', 'float', 'numeric', 'double'));
if ($isFloat && $offset) { if ($isFloat && strpos($length, ',') !== false) {
return $length . ',' . $offset; return $length;
} }
if (($real[0] == $type) && (count($real) === 1)) { if ($length === null) {
return null; return null;
} }
if (isset($types[$type])) { if (isset($types[$type])) {
$length += $types[$type]; return (int)$length;
if (!empty($sign)) { }
$length--; if (in_array($type, array('enum', 'set'))) {
} $values = array_map(function($value) {
} elseif (in_array($type, array('enum', 'set'))) { return trim(trim($value), '\'"');
$length = 0; }, explode(',', $length));
foreach ($typeArr as $key => $enumValue) {
if ($key === 0) { $maxLength = 0;
continue; foreach ($values as $key => $enumValue) {
}
$tmpLength = strlen($enumValue); $tmpLength = strlen($enumValue);
if ($tmpLength > $length) { if ($tmpLength > $maxLength) {
$length = $tmpLength; $maxLength = $tmpLength;
} }
} }
return $maxLength;
} }
return (int)$length; return (int)$length;
} }

View file

@ -1826,4 +1826,35 @@ class DboSourceTest extends CakeTestCase {
$this->db->flushQueryCache(); $this->db->flushQueryCache();
$this->assertAttributeCount(0, '_queryCache', $this->db); $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);
}
} }