diff --git a/model/Database.php b/model/Database.php index 0af0b8353..dfc7d63f5 100644 --- a/model/Database.php +++ b/model/Database.php @@ -757,7 +757,19 @@ abstract class SS_Database { } return $text; } - + + /** + * Wrap a string into DB-specific quotes. MySQL, PostgreSQL and SQLite3 only need single quotes around the string. + * MSSQL will overload this and include it's own N prefix to mark the string as unicode, so characters like macrons + * are saved correctly. + * + * @param string $string String to be prepared for database query + * @return string Prepared string + */ + public function prepStringForDB($string) { + return "'" . Convert::raw2sql($string) . "'"; + } + /** * Function to return an SQL datetime expression that can be used with the adapter in use * used for querying a datetime in a certain format diff --git a/model/fieldtypes/DBField.php b/model/fieldtypes/DBField.php index 5e7d80d2c..8769099b2 100644 --- a/model/fieldtypes/DBField.php +++ b/model/fieldtypes/DBField.php @@ -143,9 +143,9 @@ abstract class DBField extends ViewableData { if($value === null || $value === "" || $value === false) { return "null"; } else { - return "'" . Convert::raw2sql($value) . "'"; + return DB::getConn()->prepStringForDB($value); } - } + } /** * Prepare the current field for usage in a diff --git a/model/fieldtypes/StringField.php b/model/fieldtypes/StringField.php index 0f843ef09..5010679ed 100644 --- a/model/fieldtypes/StringField.php +++ b/model/fieldtypes/StringField.php @@ -75,8 +75,8 @@ abstract class StringField extends DBField { * @see core/model/fieldtypes/DBField#prepValueForDB($value) */ function prepValueForDB($value) { - if ( !$this->nullifyEmpty && $value === '' ) { - return "'" . Convert::raw2sql($value) . "'"; + if(!$this->nullifyEmpty && $value === '') { + return DB::getConn()->prepStringForDB($value); } else { return parent::prepValueForDB($value); } diff --git a/tests/model/DBFieldTest.php b/tests/model/DBFieldTest.php index 16e04548a..b62988d6d 100644 --- a/tests/model/DBFieldTest.php +++ b/tests/model/DBFieldTest.php @@ -22,7 +22,8 @@ class DBFieldTest extends SapphireTest { * Test the prepValueForDB() method on DBField. */ function testPrepValueForDB() { - + $db = DB::getConn(); + /* Float behaviour, asserting we have 0 */ $this->assertEquals('0', singleton('Float')->prepValueForDB(0)); $this->assertEquals('0', singleton('Float')->prepValueForDB(null)); @@ -74,63 +75,64 @@ class DBFieldTest extends SapphireTest { $this->assertEquals("'1'", singleton('Boolean')->prepValueForDB('1')); /* Varchar behaviour */ + $this->assertEquals($db->prepStringForDB("0"), singleton('Varchar')->prepValueForDB(0)); $this->assertEquals("'0'", singleton('Varchar')->prepValueForDB(0)); $this->assertEquals("null", singleton('Varchar')->prepValueForDB(null)); $this->assertEquals("null", singleton('Varchar')->prepValueForDB(false)); $this->assertEquals("null", singleton('Varchar')->prepValueForDB('')); - $this->assertEquals("'0'", singleton('Varchar')->prepValueForDB('0')); - $this->assertEquals("'1'", singleton('Varchar')->prepValueForDB(1)); - $this->assertEquals("'1'", singleton('Varchar')->prepValueForDB(true)); - $this->assertEquals("'1'", singleton('Varchar')->prepValueForDB('1')); - $this->assertEquals("'00000'", singleton('Varchar')->prepValueForDB('00000')); - $this->assertEquals("'0'", singleton('Varchar')->prepValueForDB(0000)); - $this->assertEquals("'test'", singleton('Varchar')->prepValueForDB('test')); - $this->assertEquals("'123'", singleton('Varchar')->prepValueForDB(123)); + $this->assertEquals($db->prepStringForDB("0"), singleton('Varchar')->prepValueForDB('0')); + $this->assertEquals($db->prepStringForDB("1"), singleton('Varchar')->prepValueForDB(1)); + $this->assertEquals($db->prepStringForDB("1"), singleton('Varchar')->prepValueForDB(true)); + $this->assertEquals($db->prepStringForDB("1"), singleton('Varchar')->prepValueForDB('1')); + $this->assertEquals($db->prepStringForDB("00000"), singleton('Varchar')->prepValueForDB('00000')); + $this->assertEquals($db->prepStringForDB("0"), singleton('Varchar')->prepValueForDB(0000)); + $this->assertEquals($db->prepStringForDB("test"), singleton('Varchar')->prepValueForDB('test')); + $this->assertEquals($db->prepStringForDB("123"), singleton('Varchar')->prepValueForDB(123)); /* AllowEmpty Varchar behaviour */ $varcharField = new Varchar("testfield", 50, array("nullifyEmpty"=>false)); - $this->assertSame("'0'", $varcharField->prepValueForDB(0)); + $this->assertSame($db->prepStringForDB("0"), $varcharField->prepValueForDB(0)); $this->assertSame("null", $varcharField->prepValueForDB(null)); $this->assertSame("null", $varcharField->prepValueForDB(false)); - $this->assertSame("''", $varcharField->prepValueForDB('')); - $this->assertSame("'0'", $varcharField->prepValueForDB('0')); - $this->assertSame("'1'", $varcharField->prepValueForDB(1)); - $this->assertSame("'1'", $varcharField->prepValueForDB(true)); - $this->assertSame("'1'", $varcharField->prepValueForDB('1')); - $this->assertSame("'00000'", $varcharField->prepValueForDB('00000')); - $this->assertSame("'0'", $varcharField->prepValueForDB(0000)); - $this->assertSame("'test'", $varcharField->prepValueForDB('test')); - $this->assertSame("'123'", $varcharField->prepValueForDB(123)); + $this->assertSame($db->prepStringForDB(""), $varcharField->prepValueForDB('')); + $this->assertSame($db->prepStringForDB("0"), $varcharField->prepValueForDB('0')); + $this->assertSame($db->prepStringForDB("1"), $varcharField->prepValueForDB(1)); + $this->assertSame($db->prepStringForDB("1"), $varcharField->prepValueForDB(true)); + $this->assertSame($db->prepStringForDB("1"), $varcharField->prepValueForDB('1')); + $this->assertSame($db->prepStringForDB("00000"), $varcharField->prepValueForDB('00000')); + $this->assertSame($db->prepStringForDB("0"), $varcharField->prepValueForDB(0000)); + $this->assertSame($db->prepStringForDB("test"), $varcharField->prepValueForDB('test')); + $this->assertSame($db->prepStringForDB("123"), $varcharField->prepValueForDB(123)); unset($varcharField); /* Text behaviour */ - $this->assertEquals("'0'", singleton('Text')->prepValueForDB(0)); + $this->assertEquals($db->prepStringForDB("0"), singleton('Text')->prepValueForDB(0)); $this->assertEquals("null", singleton('Text')->prepValueForDB(null)); $this->assertEquals("null", singleton('Text')->prepValueForDB(false)); $this->assertEquals("null", singleton('Text')->prepValueForDB('')); - $this->assertEquals("'0'", singleton('Text')->prepValueForDB('0')); - $this->assertEquals("'1'", singleton('Text')->prepValueForDB(1)); - $this->assertEquals("'1'", singleton('Text')->prepValueForDB(true)); - $this->assertEquals("'1'", singleton('Text')->prepValueForDB('1')); - $this->assertEquals("'00000'", singleton('Text')->prepValueForDB('00000')); - $this->assertEquals("'0'", singleton('Text')->prepValueForDB(0000)); - $this->assertEquals("'test'", singleton('Text')->prepValueForDB('test')); - $this->assertEquals("'123'", singleton('Text')->prepValueForDB(123)); + $this->assertEquals($db->prepStringForDB("0"), singleton('Text')->prepValueForDB('0')); + $this->assertEquals($db->prepStringForDB("1"), singleton('Text')->prepValueForDB(1)); + $this->assertEquals($db->prepStringForDB("1"), singleton('Text')->prepValueForDB(true)); + $this->assertEquals($db->prepStringForDB("1"), singleton('Text')->prepValueForDB('1')); + $this->assertEquals($db->prepStringForDB("00000"), singleton('Text')->prepValueForDB('00000')); + $this->assertEquals($db->prepStringForDB("0"), singleton('Text')->prepValueForDB(0000)); + $this->assertEquals($db->prepStringForDB("test"), singleton('Text')->prepValueForDB('test')); + $this->assertEquals($db->prepStringForDB("123"), singleton('Text')->prepValueForDB(123)); /* AllowEmpty Text behaviour */ $textField = new Text("testfield", array("nullifyEmpty"=>false)); - $this->assertSame("'0'", $textField->prepValueForDB(0)); + $this->assertSame($db->prepStringForDB("0"), $textField->prepValueForDB(0)); $this->assertSame("null", $textField->prepValueForDB(null)); $this->assertSame("null", $textField->prepValueForDB(false)); - $this->assertSame("''", $textField->prepValueForDB('')); - $this->assertSame("'0'", $textField->prepValueForDB('0')); - $this->assertSame("'1'", $textField->prepValueForDB(1)); - $this->assertSame("'1'", $textField->prepValueForDB(true)); - $this->assertSame("'1'", $textField->prepValueForDB('1')); - $this->assertSame("'00000'", $textField->prepValueForDB('00000')); - $this->assertSame("'0'", $textField->prepValueForDB(0000)); - $this->assertSame("'test'", $textField->prepValueForDB('test')); - $this->assertSame("'123'", $textField->prepValueForDB(123)); + $this->assertSame($db->prepStringForDB(""), $textField->prepValueForDB('')); + $this->assertSame($db->prepStringForDB("0"), $textField->prepValueForDB('0')); + $this->assertSame($db->prepStringForDB("1"), $textField->prepValueForDB(1)); + $this->assertSame($db->prepStringForDB("1"), $textField->prepValueForDB(true)); + $this->assertSame($db->prepStringForDB("1"), $textField->prepValueForDB('1')); + $this->assertSame($db->prepStringForDB("00000"), $textField->prepValueForDB('00000')); + $this->assertSame($db->prepStringForDB("0"), $textField->prepValueForDB(0000)); + $this->assertSame($db->prepStringForDB("test"), $textField->prepValueForDB('test')); + $this->assertSame($db->prepStringForDB("123"), $textField->prepValueForDB(123)); unset($textField); /* Time behaviour */