public function getCreateTableSQL($xmldb_table) {
// First find out if want some special db engine.
$engine = $this->mdb->get_dbengine();
+ // Do we know collation?
+ $collation = $this->mdb->get_dbcollation();
+
$sqlarr = parent::getCreateTableSQL($xmldb_table);
// Let's inject the extra MySQL tweaks.
if ($engine) {
$sqlarr[$i] .= " ENGINE = $engine";
}
+ if ($collation) {
+ if (strpos($collation, 'utf8_') === 0) {
+ $sqlarr[$i] .= " DEFAULT CHARACTER SET utf8";
+ }
+ $sqlarr[$i] .= " DEFAULT COLLATE = $collation";
+ }
}
}
* @return array of sql statements
*/
public function getCreateTempTableSQL($xmldb_table) {
+ // Do we know collation?
+ $collation = $this->mdb->get_dbcollation();
$this->temptables->add_temptable($xmldb_table->getName());
- $sqlarr = parent::getCreateTableSQL($xmldb_table); // we do not want the engine hack included in create table SQL
- $sqlarr = preg_replace('/^CREATE TABLE (.*)/s', 'CREATE TEMPORARY TABLE $1', $sqlarr);
+
+ $sqlarr = parent::getCreateTableSQL($xmldb_table);
+
+ // Let's inject the extra MySQL tweaks.
+ foreach ($sqlarr as $i=>$sql) {
+ if (strpos($sql, 'CREATE TABLE ') === 0) {
+ // We do not want the engine hack included in create table SQL.
+ $sqlarr[$i] = preg_replace('/^CREATE TABLE (.*)/s', 'CREATE TEMPORARY TABLE $1', $sql);
+ if ($collation) {
+ if (strpos($collation, 'utf8_') === 0) {
+ $sqlarr[$i] .= " DEFAULT CHARACTER SET utf8";
+ }
+ $sqlarr[$i] .= " DEFAULT COLLATE $collation";
+ }
+ }
+ }
+
return $sqlarr;
}
$xmldb_length='255';
}
$dbtype .= '(' . $xmldb_length . ')';
+ if ($collation = $this->mdb->get_dbcollation()) {
+ if (strpos($collation, 'utf8_') === 0) {
+ $dbtype .= " CHARACTER SET utf8";
+ }
+ $dbtype .= " COLLATE $collation";
+ }
break;
case XMLDB_TYPE_TEXT:
$dbtype = 'LONGTEXT';
+ if ($collation = $this->mdb->get_dbcollation()) {
+ if (strpos($collation, 'utf8_') === 0) {
+ $dbtype .= " CHARACTER SET utf8";
+ }
+ $dbtype .= " COLLATE $collation";
+ }
break;
case XMLDB_TYPE_BINARY:
$dbtype = 'LONGBLOB';
throw new dml_connection_exception($dberr);
}
- $result = $conn->query("CREATE DATABASE $dbname DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci");
+ if (isset($dboptions['dbcollation']) and strpos($dboptions['dbcollation'], 'utf8_') === 0) {
+ $collation = $dboptions['dbcollation'];
+ } else {
+ $collation = 'utf8_unicode_ci';
+ }
+
+ $result = $conn->query("CREATE DATABASE $dbname DEFAULT CHARACTER SET utf8 DEFAULT COLLATE ".$collation);
$conn->close();
return $engine;
}
+ /**
+ * Returns the current MySQL db collation.
+ *
+ * This is an ugly workaround for MySQL default collation problems.
+ *
+ * @return string or null MySQL collation name
+ */
+ public function get_dbcollation() {
+ if (isset($this->dboptions['dbcollation'])) {
+ return $this->dboptions['dbcollation'];
+ }
+ if ($this->external) {
+ return null;
+ }
+
+ $collation = null;
+
+ // Look for current collation of our config table (the first table that gets created),
+ // so that we create all tables with the same collation.
+ $sql = "SELECT collation_name
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE table_schema = DATABASE() AND table_name = '{$this->prefix}config' AND column_name = 'value'";
+ $this->query_start($sql, NULL, SQL_QUERY_AUX);
+ $result = $this->mysqli->query($sql);
+ $this->query_end($result);
+ if ($rec = $result->fetch_assoc()) {
+ $collation = $rec['collation_name'];
+ }
+ $result->close();
+
+ if (!$collation) {
+ // Get the default database collation, but only if using UTF-8.
+ $sql = "SELECT @@collation_database";
+ $this->query_start($sql, NULL, SQL_QUERY_AUX);
+ $result = $this->mysqli->query($sql);
+ $this->query_end($result);
+ if ($rec = $result->fetch_assoc()) {
+ if (strpos($rec['@@collation_database'], 'utf8_') === 0) {
+ $collation = $rec['@@collation_database'];
+ }
+ }
+ $result->close();
+ }
+
+ if (!$collation) {
+ // We want only utf8 compatible collations.
+ $collation = null;
+ $sql = "SHOW COLLATION WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'";
+ $this->query_start($sql, NULL, SQL_QUERY_AUX);
+ $result = $this->mysqli->query($sql);
+ $this->query_end($result);
+ while ($res = $result->fetch_assoc()) {
+ $collation = $res['Collation'];
+ if (strtoupper($res['Default']) === 'YES') {
+ $collation = $res['Collation'];
+ break;
+ }
+ }
+ $result->close();
+ }
+
+ // Cache the result to improve performance.
+ $this->dboptions['dbcollation'] = $collation;
+ return $collation;
+ }
+
/**
* Returns localised database type name
* Note: can be used before connect()