Add the functionality to accept enum MySQL datatype storing the Integer values as String (#12715)

Fix a bug in enum MySQL datatype storing Integers when enum contains
integer string values. Now strings will always be used for enum values.
This commit is contained in:
Yaser Naderi 2018-11-30 21:27:58 -05:00 committed by Mark Story
parent fea343d67c
commit 3d224639d9
2 changed files with 53 additions and 1 deletions

View file

@ -367,6 +367,18 @@ class DboSource extends DataSource {
$column = $this->introspectType($data); $column = $this->introspectType($data);
} }
$isStringEnum = false;
if (strpos($column, "enum") === 0) {
$firstValue = null;
if (preg_match("/(enum\()(.*)(\))/i", $column, $acceptingValues)) {
$values = explode(",", $acceptingValues[2]);
$firstValue = $values[0];
}
if (is_string($firstValue)) {
$isStringEnum = true;
}
}
switch ($column) { switch ($column) {
case 'binary': case 'binary':
return $this->_connection->quote($data, PDO::PARAM_LOB); return $this->_connection->quote($data, PDO::PARAM_LOB);
@ -382,11 +394,12 @@ class DboSource extends DataSource {
if (is_float($data)) { if (is_float($data)) {
return str_replace(',', '.', strval($data)); return str_replace(',', '.', strval($data));
} }
if ((is_int($data) || $data === '0') || ( if (((is_int($data) || $data === '0') || (
is_numeric($data) && is_numeric($data) &&
strpos($data, ',') === false && strpos($data, ',') === false &&
$data[0] != '0' && $data[0] != '0' &&
strpos($data, 'e') === false) strpos($data, 'e') === false)
) && !$isStringEnum
) { ) {
return $data; return $data;
} }

View file

@ -1028,6 +1028,11 @@ class DboSourceTest extends CakeTestCase {
$this->markTestSkipped('This test can only run on MySQL'); $this->markTestSkipped('This test can only run on MySQL');
} }
$name = $this->db->fullTableName('enum_tests'); $name = $this->db->fullTableName('enum_tests');
$query = "DROP TABLE IF EXISTS {$name};";
$result = $this->db->query($query);
$this->assertTrue($result);
$query = "CREATE TABLE {$name} (mood ENUM('','happy','sad','ok') NOT NULL);"; $query = "CREATE TABLE {$name} (mood ENUM('','happy','sad','ok') NOT NULL);";
$result = $this->db->query($query); $result = $this->db->query($query);
$this->assertTrue($result); $this->assertTrue($result);
@ -1047,6 +1052,40 @@ class DboSourceTest extends CakeTestCase {
), $enumResult); ), $enumResult);
} }
/**
* Test for MySQL enum datatype for a list of Integer stored as String
*
* @return void
*/
public function testIntValueAsStringOnEnum() {
if (!$this->db instanceof Mysql) {
$this->markTestSkipped('This test can only run on MySQL');
}
$name = $this->db->fullTableName('enum_faya_tests');
$query = "DROP TABLE IF EXISTS {$name};";
$result = $this->db->query($query);
$this->assertTrue($result);
$query = "CREATE TABLE {$name} (faya enum('10','20','30','40') NOT NULL);";
$result = $this->db->query($query);
$this->assertTrue($result);
$EnumFayaTest = ClassRegistry::init('EnumFayaTest');
$enumResult = $EnumFayaTest->save(array('faya' => '10'));
$query = "DROP TABLE {$name};";
$result = $this->db->query($query);
$this->assertTrue($result);
$this->assertEquals(array(
'EnumFayaTest' => array(
'faya' => '10',
'id' => '0'
)
), $enumResult);
}
/** /**
* test order to generate query order clause for virtual fields * test order to generate query order clause for virtual fields
* *