diff --git a/.travis.yml b/.travis.yml
index 818381ed40fb3..799bd5d9f5014 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -134,11 +134,13 @@ before_script:
sed -i \
-e "s%= 'pgsql'%= 'mysqli'%" \
-e "s%= 'username'%= 'travis'%" \
+ -e "s%=> 'utf8mb4_unicode_ci'%=> 'utf8mb4_bin'%" \
config.php;
mysql -u root -e 'SET GLOBAL innodb_file_format=barracuda;' ;
mysql -u root -e 'SET GLOBAL innodb_file_per_table=ON;' ;
- mysql -e 'CREATE DATABASE travis_ci_test DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_bin;' ;
+ mysql -u root -e 'SET GLOBAL innodb_large_prefix=ON;' ;
+ mysql -e 'CREATE DATABASE travis_ci_test DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_bin;' ;
fi
fi
diff --git a/admin/cli/mysql_collation.php b/admin/cli/mysql_collation.php
index 131b8f42788c9..adaadbba6c722 100644
--- a/admin/cli/mysql_collation.php
+++ b/admin/cli/mysql_collation.php
@@ -64,6 +64,71 @@
cli_error("Error: collation '$collation' is not available on this server!");
}
+ $collationinfo = explode('_', $collation);
+ $charset = reset($collationinfo);
+
+ $engine = strtolower($DB->get_dbengine());
+
+ // Do checks for utf8mb4.
+ if (strpos($collation, 'utf8mb4') === 0) {
+ // Do we have the right engine?
+ if ($engine !== 'innodb' && $engine !== 'xtradb') {
+ cli_error("Error: '$collation' requires InnoDB or XtraDB set as the engine.");
+ }
+ // Are we using Barracuda?
+ if ($DB->get_row_format() != 'Barracuda') {
+ // Try setting it here.
+ try {
+ $DB->execute("SET GLOBAL innodb_file_format=Barracuda");
+ } catch (dml_exception $e) {
+ cli_error("Error: '$collation' requires the file format to be set to Barracuda.
+ An attempt was made to change the format, but it failed. Please try doing this manually.");
+ }
+ echo "GLOBAL SETTING: innodb_file_format changed to Barracuda\n";
+ }
+ // Is one file per table being used?
+ if (!$DB->is_file_per_table_enabled()) {
+ try {
+ $DB->execute("SET GLOBAL innodb_file_per_table=1");
+ } catch (dml_exception $e) {
+ cli_error("Error: '$collation' requires the setting 'innodb_file_per_table' be set to 'ON'.
+ An attempt was made to change the format, but it failed. Please try doing this manually.");
+ }
+ echo "GLOBAL SETTING: innodb_file_per_table changed to 1\n";
+ }
+ // Is large prefix set?
+ if (!$DB->is_large_prefix_enabled()) {
+ try {
+ $DB->execute("SET GLOBAL innodb_large_prefix=1");
+ } catch (dml_exception $e) {
+ cli_error("Error: '$collation' requires the setting 'innodb_large_prefix' be set to 'ON'.
+ An attempt was made to change the format, but it failed. Please try doing this manually.");
+ }
+ echo "GLOBAL SETTING: innodb_large_prefix changed to 1\n";
+ }
+ }
+
+ $sql = "SHOW VARIABLES LIKE 'collation_database'";
+ if (!$dbcollation = $DB->get_record_sql($sql)) {
+ cli_error("Error: Could not access collation information on the database.");
+ }
+ $sql = "SHOW VARIABLES LIKE 'character_set_database'";
+ if (!$dbcharset = $DB->get_record_sql($sql)) {
+ cli_error("Error: Could not access character set information on the database.");
+ }
+ if ($dbcollation->value !== $collation || $dbcharset->value !== $charset) {
+ // Try to convert the DB.
+ echo "Converting database to '$collation' for $CFG->wwwroot:\n";
+ $sql = "ALTER DATABASE $CFG->dbname DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation";
+ try {
+ $DB->change_database_structure($sql);
+ } catch (exception $e) {
+ cli_error("Error: Tried to alter the database with no success. Please try manually changing the database
+ to the new collation and character set and then run this script again.");
+ }
+ echo "DATABASE CONVERTED\n";
+ }
+
echo "Converting tables and columns to '$collation' for $CFG->wwwroot:\n";
$prefix = $DB->get_prefix();
$prefix = str_replace('_', '\\_', $prefix);
@@ -80,7 +145,7 @@
$skipped++;
} else {
- $DB->change_database_structure("ALTER TABLE $table->name DEFAULT COLLATE = $collation");
+ $DB->change_database_structure("ALTER TABLE $table->name DEFAULT CHARACTER SET $charset DEFAULT COLLATE = $collation");
echo "CONVERTED\n";
$converted++;
}
@@ -96,18 +161,32 @@
continue;
}
+ // Check for utf8mb4 collation.
+ $rowformat = $DB->get_row_format_sql($engine, $collation);
+
if ($column->type === 'tinytext' or $column->type === 'mediumtext' or $column->type === 'text' or $column->type === 'longtext') {
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
$default = (!is_null($column->default) and $column->default !== '') ? "DEFAULT '$column->default'" : '';
// primary, unique and inc are not supported for texts
- $sql = "ALTER TABLE $table->name MODIFY COLUMN $column->field $column->type COLLATE $collation $notnull $default";
+ $sql = "ALTER TABLE $table->name
+ MODIFY COLUMN $column->field $column->type
+ CHARACTER SET $charset
+ COLLATE $collation $notnull $default";
$DB->change_database_structure($sql);
} else if (strpos($column->type, 'varchar') === 0) {
$notnull = ($column->null === 'NO') ? 'NOT NULL' : 'NULL';
$default = !is_null($column->default) ? "DEFAULT '$column->default'" : '';
- // primary, unique and inc are not supported for texts
- $sql = "ALTER TABLE $table->name MODIFY COLUMN $column->field $column->type COLLATE $collation $notnull $default";
+
+ if ($rowformat != '') {
+ $sql = "ALTER TABLE $table->name $rowformat";
+ $DB->change_database_structure($sql);
+ }
+
+ $sql = "ALTER TABLE $table->name
+ MODIFY COLUMN $column->field $column->type
+ CHARACTER SET $charset
+ COLLATE $collation $notnull $default";
$DB->change_database_structure($sql);
} else {
echo "ERROR (unknown column type: $column->type)\n";
@@ -180,7 +259,9 @@ function mysql_get_collations() {
global $DB;
$collations = array();
- $sql = "SHOW COLLATION WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'";
+ $sql = "SHOW COLLATION
+ WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'
+ OR Collation LIKE 'utf8mb4\_%' AND Charset = 'utf8mb4'";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $collation) {
$collations[$collation->collation] = $collation->collation;
diff --git a/admin/environment.xml b/admin/environment.xml
index 55502ee3c7135..38207edf1c25b 100644
--- a/admin/environment.xml
+++ b/admin/environment.xml
@@ -1723,6 +1723,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1873,6 +1888,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config-dist.php b/config-dist.php
index d7f19adfa47f9..ef817b05d2b6d 100644
--- a/config-dist.php
+++ b/config-dist.php
@@ -63,6 +63,13 @@
// support advanced options on connection.
// If you set those in the database then
// the advanced settings will not be sent.
+ 'dbcollation' => 'utf8mb4_unicode_ci', // MySQL has partial and full UTF-8
+ // support. If you wish to use partial UTF-8
+ // (three bytes) then set this option to
+ // 'utf8_unicode_ci', otherwise this option
+ // can be removed for MySQL (by default it will
+ // use 'utf8mb4_unicode_ci'. This option should
+ // be removed for all other databases.
);
diff --git a/lang/en/admin.php b/lang/en/admin.php
index c188ff6d5003a..1a80be9de3f45 100644
--- a/lang/en/admin.php
+++ b/lang/en/admin.php
@@ -596,6 +596,7 @@
$string['http'] = 'HTTP';
$string['httpsecurity'] = 'HTTP security';
$string['hubs'] = 'Hubs';
+$string['incompleteunicodesupport'] = 'The current setup of MySQL or MariaDB is using \'utf8\'. This character set does not support four byte characters which include some emoji. Trying to use these characters will result in an error when updating a record, and any information being sent to the database will be lost. Please consider changing your settings to \'utf8mb4\'. See the documentation for full details.';
$string['change'] = 'change';
$string['checkboxno'] = 'No';
$string['checkboxyes'] = 'Yes';
@@ -1133,6 +1134,9 @@
$string['unoconvwarning'] = 'The version of unoconv you have installed is not supported. Moodle\'s assignment grading feature requires version 0.7 or higher.';
$string['unsettheme'] = 'Unset theme';
$string['unsupported'] = 'Unsupported';
+$string['unsupporteddbfileformat'] = 'Your database has tables using Antelope as the file format. Full UTF-8 support in MySQL and MariaDB requires the Barracuda file format. Please convert the tables to the Barracuda file format. See the documentation Administration via command line for details of a tool for converting InnoDB tables to Barracuda.';
+$string['unsupporteddbfilepertable'] = 'For full support of UTF-8 both MySQL and MariaDB require you to change your MySQL setting \'innodb_file_per_table\' to \'ON\'. See the documentation for further details.';
+$string['unsupporteddblargeprefix'] = 'For full support of UTF-8 both MySQL and MariaDB require you to change your MySQL setting \'innodb_large_prefix\' to \'ON\'. See the documentation for further details.';
$string['unsupporteddbstorageengine'] = 'The database storage engine being used is no longer supported.';
$string['unsupporteddbtablerowformat'] = 'Your database has tables using Antelope as the file format. You are recommended to convert the tables to the Barracuda file format. See the documentation Administration via command line for details of a tool for converting InnoDB tables to Barracuda.';
$string['unsupportedphpversion7'] = 'PHP version 7 is not supported.';
diff --git a/lib/ddl/mysql_sql_generator.php b/lib/ddl/mysql_sql_generator.php
index 084d2e82ce2b4..b3ecee8a12a4e 100644
--- a/lib/ddl/mysql_sql_generator.php
+++ b/lib/ddl/mysql_sql_generator.php
@@ -218,6 +218,9 @@ public function getCreateTableSQL($xmldb_table) {
}
}
+ $utf8mb4rowformat = $this->mdb->get_row_format_sql($engine, $collation);
+ $rowformat = ($utf8mb4rowformat == '') ? $rowformat : $utf8mb4rowformat;
+
$sqlarr = parent::getCreateTableSQL($xmldb_table);
// This is a very nasty hack that tries to use just one query per created table
@@ -238,7 +241,7 @@ public function getCreateTableSQL($xmldb_table) {
if (strpos($collation, 'utf8_') === 0) {
$sql .= "\n DEFAULT CHARACTER SET utf8";
}
- $sql .= "\n DEFAULT COLLATE = $collation";
+ $sql .= "\n DEFAULT COLLATE = $collation ";
}
if ($rowformat) {
$sql .= $rowformat;
@@ -326,10 +329,13 @@ public function getAddFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = N
* @return array of sql statements
*/
public function getCreateTempTableSQL($xmldb_table) {
+ $engine = $this->mdb->get_dbengine();
// Do we know collation?
$collation = $this->mdb->get_dbcollation();
$this->temptables->add_temptable($xmldb_table->getName());
+ $rowformat = $this->mdb->get_row_format_sql($engine, $collation);
+
$sqlarr = parent::getCreateTableSQL($xmldb_table);
// Let's inject the extra MySQL tweaks.
@@ -341,7 +347,7 @@ public function getCreateTempTableSQL($xmldb_table) {
if (strpos($collation, 'utf8_') === 0) {
$sqlarr[$i] .= " DEFAULT CHARACTER SET utf8";
}
- $sqlarr[$i] .= " DEFAULT COLLATE $collation";
+ $sqlarr[$i] .= " DEFAULT COLLATE $collation $rowformat";
}
}
}
diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php
index ea7676affd9d3..89a18d00eea66 100644
--- a/lib/dml/mysqli_native_moodle_database.php
+++ b/lib/dml/mysqli_native_moodle_database.php
@@ -85,13 +85,19 @@ public function create_database($dbhost, $dbuser, $dbpass, $dbname, array $dbopt
throw new dml_connection_exception($dberr);
}
- if (isset($dboptions['dbcollation']) and strpos($dboptions['dbcollation'], 'utf8_') === 0) {
+ // Normally a check would be done before setting utf8mb4, but the database can be created
+ // before the enviroment checks are done. We'll proceed with creating the database and then do checks next.
+ $charset = 'utf8mb4';
+ if (isset($dboptions['dbcollation']) and (strpos($dboptions['dbcollation'], 'utf8_') === 0
+ || strpos($dboptions['dbcollation'], 'utf8mb4_') === 0)) {
$collation = $dboptions['dbcollation'];
+ $collationinfo = explode('_', $dboptions['dbcollation']);
+ $charset = reset($collationinfo);
} else {
- $collation = 'utf8_unicode_ci';
+ $collation = 'utf8mb4_unicode_ci';
}
- $result = $conn->query("CREATE DATABASE $dbname DEFAULT CHARACTER SET utf8 DEFAULT COLLATE ".$collation);
+ $result = $conn->query("CREATE DATABASE $dbname DEFAULT CHARACTER SET $charset DEFAULT COLLATE ".$collation);
$conn->close();
@@ -246,6 +252,7 @@ public function get_dbcollation() {
}
$result->close();
+
if (!$collation) {
// Get the default database collation, but only if using UTF-8.
$sql = "SELECT @@collation_database";
@@ -253,7 +260,7 @@ public function get_dbcollation() {
$result = $this->mysqli->query($sql);
$this->query_end($result);
if ($rec = $result->fetch_assoc()) {
- if (strpos($rec['@@collation_database'], 'utf8_') === 0) {
+ if (strpos($rec['@@collation_database'], 'utf8_') === 0 || strpos($rec['@@collation_database'], 'utf8mb4_') === 0) {
$collation = $rec['@@collation_database'];
}
}
@@ -263,7 +270,7 @@ public function get_dbcollation() {
if (!$collation) {
// We want only utf8 compatible collations.
$collation = null;
- $sql = "SHOW COLLATION WHERE Collation LIKE 'utf8\_%' AND Charset = 'utf8'";
+ $sql = "SHOW COLLATION WHERE Collation LIKE 'utf8mb4\_%' AND Charset = 'utf8mb4'";
$this->query_start($sql, NULL, SQL_QUERY_AUX);
$result = $this->mysqli->query($sql);
$this->query_end($result);
@@ -288,17 +295,25 @@ public function get_dbcollation() {
* @param string $table
* @return string row_format name or null if not known or table does not exist.
*/
- public function get_row_format($table) {
+ public function get_row_format($table = null) {
$rowformat = null;
- $table = $this->mysqli->real_escape_string($table);
- $sql = "SELECT row_format
- FROM INFORMATION_SCHEMA.TABLES
- WHERE table_schema = DATABASE() AND table_name = '{$this->prefix}$table'";
+ if (isset($table)) {
+ $table = $this->mysqli->real_escape_string($table);
+ $sql = "SELECT row_format
+ FROM INFORMATION_SCHEMA.TABLES
+ WHERE table_schema = DATABASE() AND table_name = '{$this->prefix}$table'";
+ } else {
+ $sql = "SHOW VARIABLES LIKE 'innodb_file_format'";
+ }
$this->query_start($sql, NULL, SQL_QUERY_AUX);
$result = $this->mysqli->query($sql);
$this->query_end($result);
if ($rec = $result->fetch_assoc()) {
- $rowformat = $rec['row_format'];
+ if (isset($table)) {
+ $rowformat = $rec['row_format'];
+ } else {
+ $rowformat = $rec['Value'];
+ }
}
$result->close();
@@ -329,16 +344,10 @@ public function is_compressed_row_format_supported($cached = true) {
// Other engines are not supported, most probably not compatible.
$this->compressedrowformatsupported = false;
- } else if (!$filepertable = $this->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_per_table'")) {
+ } else if (!$this->is_file_per_table_enabled()) {
$this->compressedrowformatsupported = false;
- } else if ($filepertable->value !== 'ON') {
- $this->compressedrowformatsupported = false;
-
- } else if (!$fileformat = $this->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_format'")) {
- $this->compressedrowformatsupported = false;
-
- } else if ($fileformat->value !== 'Barracuda') {
+ } else if ($this->get_row_format() !== 'Barracuda') {
$this->compressedrowformatsupported = false;
} else {
@@ -349,6 +358,67 @@ public function is_compressed_row_format_supported($cached = true) {
return $this->compressedrowformatsupported;
}
+ /**
+ * Check the database to see if innodb_file_per_table is on.
+ *
+ * @return bool True if on otherwise false.
+ */
+ public function is_file_per_table_enabled() {
+ if ($filepertable = $this->get_record_sql("SHOW VARIABLES LIKE 'innodb_file_per_table'")) {
+ if ($filepertable->value == 'ON') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check the database to see if innodb_large_prefix is on.
+ *
+ * @return bool True if on otherwise false.
+ */
+ public function is_large_prefix_enabled() {
+ if ($largeprefix = $this->get_record_sql("SHOW VARIABLES LIKE 'innodb_large_prefix'")) {
+ if ($largeprefix->value == 'ON') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determine if the row format should be set to compressed, dynamic, or default.
+ *
+ * Terrible kludge. If we're using utf8mb4 AND we're using InnoDB, we need to specify row format to
+ * be either dynamic or compressed (default is compact) in order to allow for bigger indexes (MySQL
+ * errors #1709 and #1071).
+ *
+ * @param string $engine The database engine being used. Will be looked up if not supplied.
+ * @param string $collation The database collation to use. Will look up the current collation if not supplied.
+ * @return string An sql fragment to add to sql statements.
+ */
+ public function get_row_format_sql($engine = null, $collation = null) {
+
+ if (!isset($engine)) {
+ $engine = $this->get_dbengine();
+ }
+ $engine = strtolower($engine);
+
+ if (!isset($collation)) {
+ $collation = $this->get_dbcollation();
+ }
+
+ $rowformat = '';
+ if (($engine === 'innodb' || $engine === 'xtradb') && strpos($collation, 'utf8mb4_') === 0) {
+ if ($this->is_compressed_row_format_supported()) {
+ $rowformat = "ROW_FORMAT=Compressed";
+ } else {
+ $rowformat = "ROW_FORMAT=Dynamic";
+ }
+ }
+ return $rowformat;
+ }
+
/**
* Returns localised database type name
* Note: can be used before connect()
@@ -449,11 +519,19 @@ public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dbop
throw new dml_connection_exception($dberr);
}
+ if (isset($dboptions['dbcollation'])) {
+ $collationinfo = explode('_', $dboptions['dbcollation']);
+ $this->dboptions['dbcollation'] = $dboptions['dbcollation'];
+ } else {
+ $collationinfo = explode('_', $this->get_dbcollation());
+ }
+ $charset = reset($collationinfo);
+
// Disable logging until we are fully setup.
$this->query_log_prevent();
$this->query_start("--set_charset()", null, SQL_QUERY_AUX);
- $this->mysqli->set_charset('utf8');
+ $this->mysqli->set_charset($charset);
$this->query_end(true);
// If available, enforce strict mode for the session. That guaranties
@@ -885,7 +963,10 @@ public function setup_is_unicodedb() {
// if config table already exists it has this collation too.
$collation = $this->get_dbcollation();
- $sql = "SHOW COLLATION WHERE Collation ='$collation' AND Charset = 'utf8'";
+ $collationinfo = explode('_', $collation);
+ $charset = reset($collationinfo);
+
+ $sql = "SHOW COLLATION WHERE Collation ='$collation' AND Charset = '$charset'";
$this->query_start($sql, NULL, SQL_QUERY_AUX);
$result = $this->mysqli->query($sql);
$this->query_end($result);
@@ -1519,17 +1600,23 @@ public function sql_cast_char2real($fieldname, $text=false) {
public function sql_equal($fieldname, $param, $casesensitive = true, $accentsensitive = true, $notequal = false) {
$equalop = $notequal ? '<>' : '=';
+
+ $collationinfo = explode('_', $this->get_dbcollation());
+ $bincollate = reset($collationinfo) . '_bin';
+
if ($casesensitive) {
// Current MySQL versions do not support case sensitive and accent insensitive.
- return "$fieldname COLLATE utf8_bin $equalop $param";
+ return "$fieldname COLLATE $bincollate $equalop $param";
} else if ($accentsensitive) {
// Case insensitive and accent sensitive, we can force a binary comparison once all texts are using the same case.
- return "LOWER($fieldname) COLLATE utf8_bin $equalop LOWER($param)";
+ return "LOWER($fieldname) COLLATE $bincollate $equalop LOWER($param)";
} else {
// Case insensitive and accent insensitive. All collations are that way, but utf8_bin.
$collation = '';
if ($this->get_dbcollation() == 'utf8_bin') {
$collation = 'COLLATE utf8_unicode_ci';
+ } else if ($this->get_dbcollation() == 'utf8mb4_bin') {
+ $collation = 'COLLATE utf8mb4_unicode_ci';
}
return "$fieldname $collation $equalop $param";
}
@@ -1555,15 +1642,18 @@ public function sql_like($fieldname, $param, $casesensitive = true, $accentsensi
}
$escapechar = $this->mysqli->real_escape_string($escapechar); // prevents problems with C-style escapes of enclosing '\'
+ $collationinfo = explode('_', $this->get_dbcollation());
+ $bincollate = reset($collationinfo) . '_bin';
+
$LIKE = $notlike ? 'NOT LIKE' : 'LIKE';
if ($casesensitive) {
// Current MySQL versions do not support case sensitive and accent insensitive.
- return "$fieldname $LIKE $param COLLATE utf8_bin ESCAPE '$escapechar'";
+ return "$fieldname $LIKE $param COLLATE $bincollate ESCAPE '$escapechar'";
} else if ($accentsensitive) {
// Case insensitive and accent sensitive, we can force a binary comparison once all texts are using the same case.
- return "LOWER($fieldname) $LIKE LOWER($param) COLLATE utf8_bin ESCAPE '$escapechar'";
+ return "LOWER($fieldname) $LIKE LOWER($param) COLLATE $bincollate ESCAPE '$escapechar'";
} else {
// Case insensitive and accent insensitive.
@@ -1571,6 +1661,9 @@ public function sql_like($fieldname, $param, $casesensitive = true, $accentsensi
if ($this->get_dbcollation() == 'utf8_bin') {
// Force a case insensitive comparison if using utf8_bin.
$collation = 'COLLATE utf8_unicode_ci';
+ } else if ($this->get_dbcollation() == 'utf8mb4_bin') {
+ // Force a case insensitive comparison if using utf8mb4_bin.
+ $collation = 'COLLATE utf8mb4_unicode_ci';
}
return "$fieldname $LIKE $param $collation ESCAPE '$escapechar'";
diff --git a/lib/upgradelib.php b/lib/upgradelib.php
index 0a61cfa3c7164..7fe339b75c92d 100644
--- a/lib/upgradelib.php
+++ b/lib/upgradelib.php
@@ -2148,6 +2148,104 @@ function check_database_tables_row_format(environment_results $result) {
return null;
}
+/**
+ * This function verfies that the database has tables using InnoDB Antelope row format.
+ *
+ * @param environment_results $result
+ * @return environment_results|null updated results object, or null if no Antelope table has been found.
+ */
+function check_mysql_file_format(environment_results $result) {
+ global $DB;
+
+ if ($DB->get_dbfamily() == 'mysql') {
+ $collation = $DB->get_dbcollation();
+ $collationinfo = explode('_', $collation);
+ $charset = reset($collationinfo);
+
+ if ($charset == 'utf8mb4') {
+ if ($DB->get_row_format() !== "Barracuda") {
+ $result->setInfo('mysql_full_unicode_support#File_format');
+ $result->setStatus(false);
+ return $result;
+ }
+ }
+ }
+ return null;
+}
+
+/**
+ * This function verfies that the database has a setting of one file per table. This is required for 'utf8mb4'.
+ *
+ * @param environment_results $result
+ * @return environment_results|null updated results object, or null if innodb_file_per_table = 1.
+ */
+function check_mysql_file_per_table(environment_results $result) {
+ global $DB;
+
+ if ($DB->get_dbfamily() == 'mysql') {
+ $collation = $DB->get_dbcollation();
+ $collationinfo = explode('_', $collation);
+ $charset = reset($collationinfo);
+
+ if ($charset == 'utf8mb4') {
+ if (!$DB->is_file_per_table_enabled()) {
+ $result->setInfo('mysql_full_unicode_support#File_per_table');
+ $result->setStatus(false);
+ return $result;
+ }
+ }
+ }
+ return null;
+}
+
+/**
+ * This function verfies that the database has the setting of large prefix enabled. This is required for 'utf8mb4'.
+ *
+ * @param environment_results $result
+ * @return environment_results|null updated results object, or null if innodb_large_prefix = 1.
+ */
+function check_mysql_large_prefix(environment_results $result) {
+ global $DB;
+
+ if ($DB->get_dbfamily() == 'mysql') {
+ $collation = $DB->get_dbcollation();
+ $collationinfo = explode('_', $collation);
+ $charset = reset($collationinfo);
+
+ if ($charset == 'utf8mb4') {
+ if (!$DB->is_large_prefix_enabled()) {
+ $result->setInfo('mysql_full_unicode_support#Large_prefix');
+ $result->setStatus(false);
+ return $result;
+ }
+ }
+ }
+ return null;
+}
+
+/**
+ * This function checks the database to see if it is using incomplete unicode support.
+ *
+ * @param environment_results $result $result
+ * @return environment_results|null updated results object, or null if unicode is fully supported.
+ */
+function check_mysql_incomplete_unicode_support(environment_results $result) {
+ global $DB;
+
+ if ($DB->get_dbfamily() == 'mysql') {
+ $collation = $DB->get_dbcollation();
+ $collationinfo = explode('_', $collation);
+ $charset = reset($collationinfo);
+
+ if ($charset == 'utf8') {
+ $result->setInfo('mysql_full_unicode_support');
+ $result->setStatus(false);
+ return $result;
+ }
+ }
+ return null;
+}
+
/**
* Upgrade the minmaxgrade setting.
*