ENHANCEMENT Introduce Database::prepStringForDB(), used by

DBField::prepValueForDB() and StringField::prepValueForDB() to ensure
the field value is escaped correctly for the database. This means
databases like MSSQL can introduce an "N" prefix (marking text as
unicode to be saved correctly) by overloading the
prepStringForDB method. MySQL, PostgreSQL and SQLite3
operate as usual.
This commit is contained in:
Sean Harvey 2012-03-20 21:20:35 +13:00
parent fea3a4eea0
commit 02c8019bb8
4 changed files with 57 additions and 43 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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 */