UPDATE: Add support for user defined charset and collation

This commit is contained in:
Oliver Shaw 2015-09-05 12:50:26 +12:00 committed by Daniel Hensby
parent 17b42a3f89
commit ec647ed007
9 changed files with 73 additions and 21 deletions

View File

@ -5,7 +5,12 @@ Upload:
# Replace an existing file rather than renaming the new one.
replaceFile: false
MySQLDatabase:
# You are advised to backup your tables if changing settings on an existing database
# `connection_charset` and `charset` should be equal, similarly so should `connection_collation` and `collation`
connection_charset: utf8
connection_collation: utf8_general_ci
charset: utf8
collation: utf8_general_ci
HTTP:
cache_control:
max-age: 0

View File

@ -31,6 +31,13 @@ class MySQLDatabase extends SS_Database {
$parameters['charset'] = $charset;
}
// Set collation
if( empty($parameters['collation'])
&& ($collation = Config::inst()->get('MySQLDatabase', 'connection_collation'))
) {
$parameters['collation'] = $collation;
}
// Notify connector of parameters
$this->connector->connect($parameters);
@ -159,18 +166,20 @@ class MySQLDatabase extends SS_Database {
$baseClasses[$class] = '"' . $class . '"';
}
$charset = Config::inst()->get('MySQLDatabase', 'charset');
// Make column selection lists
$select = array(
'SiteTree' => array(
"ClassName", "$baseClasses[SiteTree].\"ID\"", "ParentID",
"Title", "MenuTitle", "URLSegment", "Content",
"LastEdited", "Created",
"Filename" => "_utf8''", "Name" => "_utf8''",
"Filename" => "_{$charset}''", "Name" => "_{$charset}''",
"Relevance" => $relevance['SiteTree'], "CanViewType"
),
'File' => array(
"ClassName", "$baseClasses[File].\"ID\"", "ParentID" => "_utf8''",
"Title", "MenuTitle" => "_utf8''", "URLSegment" => "_utf8''", "Content",
"ClassName", "$baseClasses[File].\"ID\"", "ParentID" => "_{$charset}''",
"Title", "MenuTitle" => "_{$charset}''", "URLSegment" => "_{$charset}''", "Content",
"LastEdited", "Created",
"Filename", "Name",
"Relevance" => $relevance['File'], "CanViewType" => "NULL"

View File

@ -194,7 +194,9 @@ class MySQLSchemaManager extends DBSchemaManager {
}
public function createDatabase($name) {
$this->query("CREATE DATABASE \"$name\" DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci");
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
$this->query("CREATE DATABASE \"$name\" DEFAULT CHARACTER SET {$charset} DEFAULT COLLATE {$collation}");
}
public function dropDatabase($name) {
@ -433,7 +435,9 @@ class MySQLSchemaManager extends DBSchemaManager {
//DB::requireField($this->tableName, $this->name, "enum('" . implode("','", $this->enum) . "') character set
// utf8 collate utf8_general_ci default '{$this->default}'");
$valuesString = implode(",", Convert::raw2sql($values['enums'], true));
return "enum($valuesString) character set utf8 collate utf8_general_ci" . $this->defaultClause($values);
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
return "enum($valuesString) character set {$charset} collate {$collation}" . $this->defaultClause($values);
}
/**
@ -449,7 +453,9 @@ class MySQLSchemaManager extends DBSchemaManager {
//DB::requireField($this->tableName, $this->name, "enum('" . implode("','", $this->enum) . "') character set
//utf8 collate utf8_general_ci default '{$this->default}'");
$valuesString = implode(",", Convert::raw2sql($values['enums'], true));
return "set($valuesString) character set utf8 collate utf8_general_ci" . $this->defaultClause($values);
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
return "set($valuesString) character set {$charset} collate {$collation}" . $this->defaultClause($values);
}
/**
@ -503,7 +509,9 @@ class MySQLSchemaManager extends DBSchemaManager {
//For reference, this is what typically gets passed to this function:
//$parts=Array('datatype'=>'mediumtext', 'character set'=>'utf8', 'collate'=>'utf8_general_ci');
//DB::requireField($this->tableName, $this->name, "mediumtext character set utf8 collate utf8_general_ci");
return 'mediumtext character set utf8 collate utf8_general_ci' . $this->defaultClause($values);
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
return 'mediumtext character set ' . $charset . ' collate ' . $collation . $this->defaultClause($values);
}
/**
@ -533,7 +541,9 @@ class MySQLSchemaManager extends DBSchemaManager {
//DB::requireField($this->tableName, $this->name, "varchar($this->size) character set utf8 collate
// utf8_general_ci");
$default = $this->defaultClause($values);
return "varchar({$values['precision']}) character set utf8 collate utf8_general_ci$default";
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
return "varchar({$values['precision']}) character set {$charset} collate {$collation}{$default}";
}
/*

View File

@ -56,6 +56,10 @@ class MySQLiConnector extends DBConnector {
// Normally $selectDB is set to false by the MySQLDatabase controller, as per convention
$selectedDB = ($selectDB && !empty($parameters['database'])) ? $parameters['database'] : null;
// Connection charset and collation
$connCharset = Config::inst()->get('MySQLDatabase', 'connection_charset');
$connCollation = Config::inst()->get('MySQLDatabase', 'connection_collation');
if(!empty($parameters['port'])) {
$this->dbConn = new MySQLi(
$parameters['server'],
@ -77,11 +81,18 @@ class MySQLiConnector extends DBConnector {
$this->databaseError("Couldn't connect to MySQL database | " . $this->dbConn->connect_error);
}
// Set charset if given and not null. Can explicitly set to empty string to omit
// Set charset and collation if given and not null. Can explicitly set to empty string to omit
$charset = isset($parameters['charset'])
? $parameters['charset']
: 'utf8';
: $connCharset;
if (!empty($charset)) $this->dbConn->set_charset($charset);
$collation = isset($parameters['collation'])
? $parameters['collation']
: $connCollation;
if (!empty($collation)) $this->dbConn->query("SET collation_connection = {$collation}");
}
public function __destruct() {

View File

@ -134,17 +134,24 @@ class PDOConnector extends DBConnector {
}
}
// Connection charset and collation
$connCharset = Config::inst()->get('MySQLDatabase', 'connection_charset');
$connCollation = Config::inst()->get('MySQLDatabase', 'connection_collation');
// Set charset if given and not null. Can explicitly set to empty string to omit
if($parameters['driver'] !== 'sqlsrv') {
$charset = isset($parameters['charset'])
? $parameters['charset']
: 'utf8';
: $connCharset;
if (!empty($charset)) $dsn[] = "charset=$charset";
}
// Connection commands to be run on every re-connection
if(!isset($charset)) {
$charset = $connCharset;
}
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $charset . ' COLLATE ' . $connCollation
);
if(self::is_emulate_prepare()) {
$options[PDO::ATTR_EMULATE_PREPARES] = true;

View File

@ -65,11 +65,14 @@ class Enum extends StringField {
* @return void
*/
public function requireField() {
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
$parts = array(
'datatype' => 'enum',
'enums' => $this->enum,
'character set' => 'utf8',
'collate' => 'utf8_general_ci',
'character set' => $charset,
'collate' => $collation,
'default' => $this->default,
'table' => $this->tableName,
'arrayValue' => $this->arrayValue

View File

@ -31,13 +31,14 @@ class MultiEnum extends Enum {
}
public function requireField(){
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
$values=array(
'type'=>'set',
'parts'=>array(
'enums'=>$this->enum,
'character set'=>'utf8',
'collate'=> 'utf8_general_ci',
'character set'=> $charset,
'collate'=> $collation,
'default'=> $this->default,
'table'=>$this->tableName,
'arrayValue'=>$this->arrayValue

View File

@ -37,10 +37,13 @@ class Text extends StringField {
* @see DBField::requireField()
*/
public function requireField() {
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
$parts = array(
'datatype' => 'mediumtext',
'character set' => 'utf8',
'collate' => 'utf8_general_ci',
'character set' => $charset,
'collate' => $collation,
'arrayValue' => $this->arrayValue
);

View File

@ -50,11 +50,14 @@ class Varchar extends StringField {
* @see DBField::requireField()
*/
public function requireField() {
$charset = Config::inst()->get('MySQLDatabase', 'charset');
$collation = Config::inst()->get('MySQLDatabase', 'collation');
$parts = array(
'datatype'=>'varchar',
'precision'=>$this->size,
'character set'=>'utf8',
'collate'=>'utf8_general_ci',
'character set'=> $charset,
'collate'=> $collation,
'arrayValue'=>$this->arrayValue
);