Browse Source

Enhance error message when set character set failed

Laurent Destailleur 1 year ago
parent
commit
553776a77a
2 changed files with 64 additions and 47 deletions
  1. 49 36
      htdocs/core/db/mysqli.class.php
  2. 15 11
      htdocs/install/step1.php

+ 49 - 36
htdocs/core/db/mysqli.class.php

@@ -117,8 +117,21 @@ class DoliDBMysqli extends DoliDB
 					$clientmustbe = 'utf8';
 				}
 
-				if ($this->db->character_set_name() != $clientmustbe) {
-					$this->db->set_charset($clientmustbe); // This set charset, but with a bad collation
+				$disableforcecharset = 0;	// Set to 1 to test without charset forcing
+				if (empty($disableforcecharset) && $this->db->character_set_name() != $clientmustbe) {
+					try {
+						//print "You should set the \$dolibarr_main_db_character_set and \$dolibarr_main_db_collation for the PHP to the one of the database ".$this->db->character_set_name();
+						dol_syslog(get_class($this)."::DoliDBMysqli You should set the \$dolibarr_main_db_character_set and \$dolibarr_main_db_collation for the PHP to the one of the database ".$this->db->character_set_name(), LOG_WARNING);
+						$this->db->set_charset($clientmustbe); // This set charset, but with a bad collation
+					} catch (Exception $e) {
+						print 'Failed to force character set to '.$clientmustbe." according to setup to match the one of the server database.<br>\n";
+						print $e->getMessage();
+						print "<br>\n";
+						if ($clientmustbe != 'utf8') {
+							print 'Edit conf/conf.php file to set a charset "utf8" instead of "'.$clientmustbe.'".'."\n";
+						}
+						exit;
+					}
 
 					$collation = (empty($conf) ? 'utf8_unicode_ci' : $conf->db->dolibarr_main_db_collation);
 					if (preg_match('/latin1/', $collation)) {
@@ -137,7 +150,7 @@ class DoliDBMysqli extends DoliDB
 				dol_syslog(get_class($this)."::DoliDBMysqli : Select_db error ".$this->error, LOG_ERR);
 			}
 		} else {
-			// Pas de selection de base demandee, ok ou ko
+			// No selection of database done. We may only be connected or not (ok or ko) to the server.
 			$this->database_selected = false;
 
 			if ($this->connected) {
@@ -504,35 +517,35 @@ class DoliDBMysqli extends DoliDB
 		} else {
 			// Constants to convert a MySql error code to a generic Dolibarr error code
 			$errorcode_map = array(
-			1004 => 'DB_ERROR_CANNOT_CREATE',
-			1005 => 'DB_ERROR_CANNOT_CREATE',
-			1006 => 'DB_ERROR_CANNOT_CREATE',
-			1007 => 'DB_ERROR_ALREADY_EXISTS',
-			1008 => 'DB_ERROR_CANNOT_DROP',
-			1022 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
-			1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
-			1044 => 'DB_ERROR_ACCESSDENIED',
-			1046 => 'DB_ERROR_NODBSELECTED',
-			1048 => 'DB_ERROR_CONSTRAINT',
-			1050 => 'DB_ERROR_TABLE_ALREADY_EXISTS',
-			1051 => 'DB_ERROR_NOSUCHTABLE',
-			1054 => 'DB_ERROR_NOSUCHFIELD',
-			1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
-			1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
-			1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
-			1064 => 'DB_ERROR_SYNTAX',
-			1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
-			1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
-			1091 => 'DB_ERROR_NOSUCHFIELD',
-			1100 => 'DB_ERROR_NOT_LOCKED',
-			1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
-			1146 => 'DB_ERROR_NOSUCHTABLE',
-			1215 => 'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
-			1216 => 'DB_ERROR_NO_PARENT',
-			1217 => 'DB_ERROR_CHILD_EXISTS',
-			1396 => 'DB_ERROR_USER_ALREADY_EXISTS', // When creating a user that already existing
-			1451 => 'DB_ERROR_CHILD_EXISTS',
-			1826 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
+				1004 => 'DB_ERROR_CANNOT_CREATE',
+				1005 => 'DB_ERROR_CANNOT_CREATE',
+				1006 => 'DB_ERROR_CANNOT_CREATE',
+				1007 => 'DB_ERROR_ALREADY_EXISTS',
+				1008 => 'DB_ERROR_CANNOT_DROP',
+				1022 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
+				1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
+				1044 => 'DB_ERROR_ACCESSDENIED',
+				1046 => 'DB_ERROR_NODBSELECTED',
+				1048 => 'DB_ERROR_CONSTRAINT',
+				1050 => 'DB_ERROR_TABLE_ALREADY_EXISTS',
+				1051 => 'DB_ERROR_NOSUCHTABLE',
+				1054 => 'DB_ERROR_NOSUCHFIELD',
+				1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
+				1061 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
+				1062 => 'DB_ERROR_RECORD_ALREADY_EXISTS',
+				1064 => 'DB_ERROR_SYNTAX',
+				1068 => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
+				1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
+				1091 => 'DB_ERROR_NOSUCHFIELD',
+				1100 => 'DB_ERROR_NOT_LOCKED',
+				1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
+				1146 => 'DB_ERROR_NOSUCHTABLE',
+				1215 => 'DB_ERROR_CANNOT_ADD_FOREIGN_KEY_CONSTRAINT',
+				1216 => 'DB_ERROR_NO_PARENT',
+				1217 => 'DB_ERROR_CHILD_EXISTS',
+				1396 => 'DB_ERROR_USER_ALREADY_EXISTS', // When creating a user that already existing
+				1451 => 'DB_ERROR_CHILD_EXISTS',
+				1826 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
 			);
 
 			if (isset($errorcode_map[$this->db->errno])) {
@@ -1076,7 +1089,7 @@ class DoliDBMysqli extends DoliDB
 	 */
 	public function getDefaultCharacterSetDatabase()
 	{
-		$resql = $this->query('SHOW VARIABLES LIKE \'character_set_database\'');
+		$resql = $this->query("SHOW VARIABLES LIKE 'character_set_database'");
 		if (!$resql) {
 			// version Mysql < 4.1.1
 			return $this->forcecharset;
@@ -1119,7 +1132,7 @@ class DoliDBMysqli extends DoliDB
 	 */
 	public function getDefaultCollationDatabase()
 	{
-		$resql = $this->query('SHOW VARIABLES LIKE \'collation_database\'');
+		$resql = $this->query("SHOW VARIABLES LIKE 'collation_database'");
 		if (!$resql) {
 			// version Mysql < 4.1.1
 			return $this->forcecollate;
@@ -1162,7 +1175,7 @@ class DoliDBMysqli extends DoliDB
 	{
 		$fullpathofdump = '/pathtomysqldump/mysqldump';
 
-		$resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
+		$resql = $this->query("SHOW VARIABLES LIKE 'basedir'");
 		if ($resql) {
 			$liste = $this->fetch_array($resql);
 			$basedir = $liste['Value'];
@@ -1180,7 +1193,7 @@ class DoliDBMysqli extends DoliDB
 	{
 		$fullpathofimport = '/pathtomysql/mysql';
 
-		$resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
+		$resql = $this->query("SHOW VARIABLES LIKE 'basedir'");
 		if ($resql) {
 			$liste = $this->fetch_array($resql);
 			$basedir = $liste['Value'];

+ 15 - 11
htdocs/install/step1.php

@@ -335,12 +335,16 @@ if (!$error && $db->connected) {
 
 		$defaultCharacterSet = $db->forcecharset;
 		$defaultDBSortingCollation = $db->forcecollate;
-	} else // If already created, we take current value
-	{
+	} else { // If already created, we take current value
 		$defaultCharacterSet = $db->getDefaultCharacterSetDatabase();
 		$defaultDBSortingCollation = $db->getDefaultCollationDatabase();
 	}
 
+	// It seems some PHP driver mysqli does not support utf8mb3
+	if ($defaultCharacterSet == 'utf8mb3' || $defaultDBSortingCollation == 'utf8mb3_unicode_ci') {
+		$defaultCharacterSet = 'utf8';
+		$defaultDBSortingCollation = 'utf8_unicode_ci';
+	}
 	// Force to avoid utf8mb4 because index on field char 255 reach limit of 767 char for indexes (example with mysql 5.6.34 = mariadb 10.0.29)
 	// TODO Remove this when utf8mb4 is supported
 	if ($defaultCharacterSet == 'utf8mb4' || $defaultDBSortingCollation == 'utf8mb4_unicode_ci') {
@@ -578,14 +582,14 @@ if (!$error && $db->connected && $action == "set") {
 							print '<td><img src="../theme/eldy/img/tick.png" alt="Ok"></td></tr>';
 						} else {
 							if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS'
-							|| $db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
-							|| $db->errno() == 'DB_ERROR_USER_ALREADY_EXISTS') {
-								dolibarr_install_syslog("step1: user already exists");
-								print '<tr><td>';
-								print $langs->trans("UserCreation").' : ';
-								print $dolibarr_main_db_user;
-								print '</td>';
-								print '<td>'.$langs->trans("LoginAlreadyExists").'</td></tr>';
+								|| $db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS'
+								|| $db->errno() == 'DB_ERROR_USER_ALREADY_EXISTS') {
+									dolibarr_install_syslog("step1: user already exists");
+									print '<tr><td>';
+									print $langs->trans("UserCreation").' : ';
+									print $dolibarr_main_db_user;
+									print '</td>';
+									print '<td>'.$langs->trans("LoginAlreadyExists").'</td></tr>';
 							} else {
 								dolibarr_install_syslog("step1: failed to create user", LOG_ERR);
 								print '<tr><td>';
@@ -920,7 +924,7 @@ function write_conf_file($conffile)
 		fputs($fp, '$dolibarr_main_force_https=\''.$main_force_https.'\';');
 		fputs($fp, "\n");
 
-		fputs($fp, '$dolibarr_main_restrict_os_commands=\'mysqldump, mysql, pg_dump, pgrestore, mariadb, mariadb-dump, clamdscan, clamscan.exe\';');
+		fputs($fp, '$dolibarr_main_restrict_os_commands=\'mariadb-dump, mariadb, mysqldump, mysql, pg_dump, pgrestore, clamdscan, clamscan.exe\';');
 		fputs($fp, "\n");
 
 		fputs($fp, '$dolibarr_nocsrfcheck=\'0\';');