From 14dac82376d315d9007453ca93a62e36ce8ee172 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 29 Apr 2011 20:11:04 +0100 Subject: [PATCH 1/4] MDL-27325 New DB unit tests to demonstrate the problem. --- lib/dml/simpletest/testdml.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index 50dd51797ee..4c049ad1662 100644 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -1726,6 +1726,26 @@ class dml_test extends UnitTestCase { $DB->delete_records($tablename, array()); $id4 = $DB->insert_record($tablename, array('course' => 3)); $this->assertTrue($id3 < $id4); + + // Test saving a float in a CHAR column, and reading it back. + $id = $DB->insert_record($tablename, array('onechar' => 1.0)); + $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onechar' => 1e20)); + $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onechar' => 1e-4)); + $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onechar' => 1e-5)); + $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); + + // Test saving a float in a TEXT column, and reading it back. + $id = $DB->insert_record($tablename, array('onetext' => 1.0)); + $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onetext' => 1e20)); + $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onetext' => 1e-4)); + $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onetext' => 1e-5)); + $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); } public function test_import_record() { From 280a6412327a0f51bbafdcaf7fa932ef5a8c62ff Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Thu, 5 May 2011 17:42:41 +0200 Subject: [PATCH 2/4] MDL-27325 mysql: Avoid some implicit casting from float to varchar/text --- lib/dml/mysqli_native_moodle_database.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index b3c1cebdde0..243f29dbeb6 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -579,6 +579,10 @@ class mysqli_native_moodle_database extends moodle_database { if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') { $value = 0; // prevent '' problems in numeric fields } + // Any float value being stored in varchar or text field is converted to string to avoid + // any implicit conversion by MySQL + } else if (is_float($value) and ($column->meta_type == 'C' or $column->meta_type == 'X')) { + $value = "$value"; } // workaround for problem with wrong enums in mysql - TODO: Out in Moodle 2.1 if (!empty($column->enums)) { From 15516e644592741386a90f6eb55d8779cd098ae1 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Thu, 5 May 2011 18:10:10 +0200 Subject: [PATCH 3/4] MDL-27325 Now also testing update_record and set_field --- lib/dml/simpletest/testdml.php | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index 4c049ad1662..3feea0f41b5 100644 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -2118,6 +2118,27 @@ class dml_test extends UnitTestCase { $this->assertEqual($newclob, $record->onetext, 'Test "small" CLOB update (full contents output disabled)'); $this->assertEqual($newblob, $record->onebinary, 'Test "small" BLOB update (full contents output disabled)'); + // Test saving a float in a CHAR column, and reading it back. + $id = $DB->insert_record($tablename, array('onechar' => 'X')); + $DB->update_record($tablename, array('id' => $id, 'onechar' => 1.0)); + $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e20)); + $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-4)); + $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-5)); + $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); + + // Test saving a float in a TEXT column, and reading it back. + $id = $DB->insert_record($tablename, array('onetext' => 'X')); + $DB->update_record($tablename, array('id' => $id, 'onetext' => 1.0)); + $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e20)); + $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-4)); + $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-5)); + $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); } public function test_set_field() { @@ -2183,6 +2204,28 @@ class dml_test extends UnitTestCase { $this->assertEqual($e->errorcode, 'textconditionsnotallowed'); } + // Test saving a float in a CHAR column, and reading it back. + $id = $DB->insert_record($tablename, array('onechar' => 'X')); + $DB->set_field($tablename, 'onechar', 1.0, array('id' => $id)); + $this->assertEqual(1.0, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->set_field($tablename, 'onechar', 1e20, array('id' => $id)); + $this->assertEqual(1e20, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->set_field($tablename, 'onechar', 1e-4, array('id' => $id)); + $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->set_field($tablename, 'onechar', 1e-5, array('id' => $id)); + $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); + + // Test saving a float in a TEXT column, and reading it back. + $id = $DB->insert_record($tablename, array('onetext' => 'X')); + $DB->set_field($tablename, 'onetext', 1.0, array('id' => $id)); + $this->assertEqual(1.0, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->set_field($tablename, 'onetext', 1e20, array('id' => $id)); + $this->assertEqual(1e20, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->set_field($tablename, 'onetext', 1e-4, array('id' => $id)); + $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->set_field($tablename, 'onetext', 1e-5, array('id' => $id)); + $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); + // Note: All the nulls, booleans, empties, quoted and backslashes tests // go to set_field_select() because set_field() is just one wrapper over it } From 35fa620a2ee6cdf5dede8420af729bd0f566c803 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Thu, 5 May 2011 18:21:18 +0200 Subject: [PATCH 4/4] MDL-27325 Adding some extreme, but 32bits safe, float tests --- lib/dml/simpletest/testdml.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index 3feea0f41b5..6d9a0713bb8 100644 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -1736,6 +1736,10 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); $id = $DB->insert_record($tablename, array('onechar' => 1e-5)); $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onechar' => 1e-300)); + $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onechar' => 1e300)); + $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id))); // Test saving a float in a TEXT column, and reading it back. $id = $DB->insert_record($tablename, array('onetext' => 1.0)); @@ -1746,6 +1750,10 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); $id = $DB->insert_record($tablename, array('onetext' => 1e-5)); $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onetext' => 1e-300)); + $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $id = $DB->insert_record($tablename, array('onetext' => 1e300)); + $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); } public function test_import_record() { @@ -2128,6 +2136,10 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-5)); $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e-300)); + $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onechar' => 1e300)); + $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id))); // Test saving a float in a TEXT column, and reading it back. $id = $DB->insert_record($tablename, array('onetext' => 'X')); @@ -2139,6 +2151,10 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-5)); $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e-300)); + $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->update_record($tablename, array('id' => $id, 'onetext' => 1e300)); + $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); } public function test_set_field() { @@ -2214,6 +2230,10 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-4, $DB->get_field($tablename, 'onechar', array('id' => $id))); $DB->set_field($tablename, 'onechar', 1e-5, array('id' => $id)); $this->assertEqual(1e-5, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->set_field($tablename, 'onechar', 1e-300, array('id' => $id)); + $this->assertEqual(1e-300, $DB->get_field($tablename, 'onechar', array('id' => $id))); + $DB->set_field($tablename, 'onechar', 1e300, array('id' => $id)); + $this->assertEqual(1e300, $DB->get_field($tablename, 'onechar', array('id' => $id))); // Test saving a float in a TEXT column, and reading it back. $id = $DB->insert_record($tablename, array('onetext' => 'X')); @@ -2225,6 +2245,10 @@ class dml_test extends UnitTestCase { $this->assertEqual(1e-4, $DB->get_field($tablename, 'onetext', array('id' => $id))); $DB->set_field($tablename, 'onetext', 1e-5, array('id' => $id)); $this->assertEqual(1e-5, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->set_field($tablename, 'onetext', 1e-300, array('id' => $id)); + $this->assertEqual(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); + $DB->set_field($tablename, 'onetext', 1e300, array('id' => $id)); + $this->assertEqual(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); // Note: All the nulls, booleans, empties, quoted and backslashes tests // go to set_field_select() because set_field() is just one wrapper over it