Merge pull request #5576 from istvanp/2.7

Prevent NULL value on NOT NULL column when value is an empty string
This commit is contained in:
Mark Story 2015-01-06 21:23:53 -05:00
commit c4f9727720
4 changed files with 43 additions and 10 deletions

View file

@ -584,11 +584,12 @@ class Sqlserver extends DboSource {
* *
* @param string $data String to be prepared for use in an SQL statement * @param string $data String to be prepared for use in an SQL statement
* @param string $column The column into which this data will be inserted * @param string $column The column into which this data will be inserted
* @param bool $null Column allows NULL values
* @return string Quoted and escaped data * @return string Quoted and escaped data
*/ */
public function value($data, $column = null) { public function value($data, $column = null, $null = true) {
if ($data === null || is_array($data) || is_object($data)) { if ($data === null || is_array($data) || is_object($data)) {
return parent::value($data, $column); return parent::value($data, $column, $null);
} }
if (in_array($data, array('{$__cakeID__$}', '{$__cakeForeignKey__$}'), true)) { if (in_array($data, array('{$__cakeID__$}', '{$__cakeForeignKey__$}'), true)) {
return $data; return $data;
@ -603,7 +604,7 @@ class Sqlserver extends DboSource {
case 'text': case 'text':
return 'N' . $this->_connection->quote($data, PDO::PARAM_STR); return 'N' . $this->_connection->quote($data, PDO::PARAM_STR);
default: default:
return parent::value($data, $column); return parent::value($data, $column, $null);
} }
} }

View file

@ -312,9 +312,10 @@ class DboSource extends DataSource {
* *
* @param string $data String to be prepared for use in an SQL statement * @param string $data String to be prepared for use in an SQL statement
* @param string $column The column datatype into which this data will be inserted. * @param string $column The column datatype into which this data will be inserted.
* @param bool $null Column allows NULL values
* @return string Quoted and escaped data * @return string Quoted and escaped data
*/ */
public function value($data, $column = null) { public function value($data, $column = null, $null = true) {
if (is_array($data) && !empty($data)) { if (is_array($data) && !empty($data)) {
return array_map( return array_map(
array(&$this, 'value'), array(&$this, 'value'),
@ -348,7 +349,7 @@ class DboSource extends DataSource {
return $this->_connection->quote($data, PDO::PARAM_STR); return $this->_connection->quote($data, PDO::PARAM_STR);
default: default:
if ($data === '') { if ($data === '') {
return 'NULL'; return $null ? 'NULL' : '""';
} }
if (is_float($data)) { if (is_float($data)) {
return str_replace(',', '.', strval($data)); return str_replace(',', '.', strval($data));
@ -994,7 +995,8 @@ class DboSource extends DataSource {
$count = count($fields); $count = count($fields);
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
$valueInsert[] = $this->value($values[$i], $Model->getColumnType($fields[$i])); $schema = $Model->schema();
$valueInsert[] = $this->value($values[$i], $Model->getColumnType($fields[$i]), isset($schema[$fields[$i]]) ? $schema[$fields[$i]]['null'] : true);
$fieldInsert[] = $this->name($fields[$i]); $fieldInsert[] = $this->name($fields[$i]);
if ($fields[$i] === $Model->primaryKey) { if ($fields[$i] === $Model->primaryKey) {
$id = $values[$i]; $id = $values[$i];
@ -2061,6 +2063,7 @@ class DboSource extends DataSource {
*/ */
protected function _prepareUpdateFields(Model $Model, $fields, $quoteValues = true, $alias = false) { protected function _prepareUpdateFields(Model $Model, $fields, $quoteValues = true, $alias = false) {
$quotedAlias = $this->startQuote . $Model->alias . $this->endQuote; $quotedAlias = $this->startQuote . $Model->alias . $this->endQuote;
$schema = $Model->schema();
$updates = array(); $updates = array();
foreach ($fields as $field => $value) { foreach ($fields as $field => $value) {
@ -2081,7 +2084,7 @@ class DboSource extends DataSource {
$update = $quoted . ' = '; $update = $quoted . ' = ';
if ($quoteValues) { if ($quoteValues) {
$update .= $this->value($value, $Model->getColumnType($field)); $update .= $this->value($value, $Model->getColumnType($field), isset($schema[$field]) ? $schema[$field]['null'] : true);
} elseif ($Model->getColumnType($field) === 'boolean' && (is_int($value) || is_bool($value))) { } elseif ($Model->getColumnType($field) === 'boolean' && (is_int($value) || is_bool($value))) {
$update .= $this->boolean($value, true); $update .= $this->boolean($value, true);
} elseif (!$alias) { } elseif (!$alias) {
@ -3563,4 +3566,4 @@ class DboSource extends DataSource {
} }
} }
} }

View file

@ -318,8 +318,8 @@ class PostgresTest extends CakeTestCase {
$this->assertEquals("0", $this->Dbo->value('0', 'integer')); $this->assertEquals("0", $this->Dbo->value('0', 'integer'));
$this->assertEquals('NULL', $this->Dbo->value('', 'integer')); $this->assertEquals('NULL', $this->Dbo->value('', 'integer'));
$this->assertEquals('NULL', $this->Dbo->value('', 'float')); $this->assertEquals('NULL', $this->Dbo->value('', 'float'));
$this->assertEquals("NULL", $this->Dbo->value('', 'integer', false)); $this->assertEquals('""', $this->Dbo->value('', 'integer', false));
$this->assertEquals("NULL", $this->Dbo->value('', 'float', false)); $this->assertEquals('""', $this->Dbo->value('', 'float', false));
$this->assertEquals("'0.0'", $this->Dbo->value('0.0', 'float')); $this->assertEquals("'0.0'", $this->Dbo->value('0.0', 'float'));
$this->assertEquals("'TRUE'", $this->Dbo->value('t', 'boolean')); $this->assertEquals("'TRUE'", $this->Dbo->value('t', 'boolean'));

View file

@ -784,6 +784,35 @@ class DboSourceTest extends CakeTestCase {
$this->assertTrue($result, 'Query did not return a boolean'); $this->assertTrue($result, 'Query did not return a boolean');
} }
/**
* Test NOT NULL on ENUM data type with empty string as a value
*
* @return void
*/
public function testNotNullOnEnum() {
if (!$this->db instanceof Mysql) {
$this->markTestSkipped('This test can only run on MySQL');
}
$name = $this->db->fullTableName('enum_tests');
$query = "CREATE TABLE {$name} (mood ENUM('','happy','sad','ok') NOT NULL);";
$result = $this->db->query($query);
$this->assertTrue($result);
$EnumTest = ClassRegistry::init('EnumTest');
$enumResult = $EnumTest->save(array('mood' => ''));
$query = "DROP TABLE {$name};";
$result = $this->db->query($query);
$this->assertTrue($result);
$this->assertEquals(array(
'EnumTest' => array(
'mood' => '',
'id' => '0'
)
), $enumResult);
}
/** /**
* test order to generate query order clause for virtual fields * test order to generate query order clause for virtual fields
* *