From 21853e3f7a1aecf34d61908e9352cecbe5ea0783 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Thu, 22 Dec 2016 14:30:43 +0900 Subject: [PATCH] Fixed a bug where migration failed with MySQL-5.7 --- .../admin/install/classes/installer.class.php | 2 + sql/updates/mysql_2.1.1_to_2.1.2.php | 45 ++++++++-- system/databases/mysql.class.php | 84 +++++++++++++++++++ system/databases/mysqli.class.php | 84 +++++++++++++++++++ system/lib-database.php | 12 +++ 5 files changed, 219 insertions(+), 8 deletions(-) diff --git a/public_html/admin/install/classes/installer.class.php b/public_html/admin/install/classes/installer.class.php index 2994fb798..4bd04c5ed 100644 --- a/public_html/admin/install/classes/installer.class.php +++ b/public_html/admin/install/classes/installer.class.php @@ -2440,6 +2440,7 @@ private function doDatabaseUpgrades($currentGlVersion, $checkForMessage = false) // leaving that up to each Geeklog database driver $done = false; $progress = ''; + DB_setMysqlSqlMode(Database::MYSQL_SQL_MODE_NONE); $_SQL = array(); while (!$done) { @@ -2912,6 +2913,7 @@ private function doDatabaseUpgrades($currentGlVersion, $checkForMessage = false) } } else { $this->updateDB($_SQL, $progress); + update_dateTimeColumns212(); update_addLanguage(); update_addRouting(); update_ConfValuesFor212(); diff --git a/sql/updates/mysql_2.1.1_to_2.1.2.php b/sql/updates/mysql_2.1.1_to_2.1.2.php index 83722123e..882f8b129 100644 --- a/sql/updates/mysql_2.1.1_to_2.1.2.php +++ b/sql/updates/mysql_2.1.1_to_2.1.2.php @@ -1,13 +1,5 @@ = self::MYSQL_SQL_MODE_NONE) && ($mode <= self::MYSQL_SQL_MODE_800)) { + $this->sqlMode = $mode; + } else { + throw new InvalidArgumentException(__METHOD__ . ': bad argument was given'); + } + } + + /** + * Return sql_mode string the current MySQL server accepts + * + * @return string + */ + private function getMysqlSqlModeString() + { + $sqlModes = array( + self::MYSQL_SQL_MODE_NONE => array(), + self::MYSQL_SQL_MODE_566 => array( + 'NO_ENGINE_SUBSTITUTION' + ), + self::MYSQL_SQL_MODE_570 => array( + 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_575 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_577 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_578 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', + 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_800 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', + 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', + ), + ); + + if ($this->_mysql_version < 50606) { + $currentMode = self::MYSQL_SQL_MODE_NONE; + } elseif (($this->_mysql_version >= 50606) && ($this->_mysql_version < 50700)) { + $currentMode = self::MYSQL_SQL_MODE_566; + } elseif (($this->_mysql_version >= 50700) && ($this->_mysql_version < 50705)) { + $currentMode = self::MYSQL_SQL_MODE_570; + } elseif (($this->_mysql_version >= 50705) && ($this->_mysql_version < 50707)) { + $currentMode = self::MYSQL_SQL_MODE_575; + } elseif (($this->_mysql_version >= 50707) && ($this->_mysql_version < 50708)) { + $currentMode = self::MYSQL_SQL_MODE_577; + } elseif (($this->_mysql_version >= 50708) && ($this->_mysql_version < 80000)) { + $currentMode = self::MYSQL_SQL_MODE_578; + } else { + $currentMode = self::MYSQL_SQL_MODE_800; + } + + $allowedMode = min($this->sqlMode, $currentMode); + + return implode(', ', $sqlModes[$allowedMode]); + } + /** * Return if a given table exists in the current database * @@ -356,6 +438,8 @@ public function dbQuery($sql, $ignore_errors = 0) } // Run query + @mysql_query("SET SESSION sql_mode = '" . $this->getMysqlSqlModeString() . "'", $this->_db); + if ($ignore_errors) { $result = @mysql_query($sql, $this->_db); } else { diff --git a/system/databases/mysqli.class.php b/system/databases/mysqli.class.php index 4c004d74d..4e19e24dd 100644 --- a/system/databases/mysqli.class.php +++ b/system/databases/mysqli.class.php @@ -38,6 +38,15 @@ */ class Database { + // MySQL sql_mode constants + const MYSQL_SQL_MODE_NONE = 0; // Prior to MySQL 5.6.6 + const MYSQL_SQL_MODE_566 = 1; + const MYSQL_SQL_MODE_570 = 2; + const MYSQL_SQL_MODE_575 = 3; + const MYSQL_SQL_MODE_577 = 4; + const MYSQL_SQL_MODE_578 = 5; + const MYSQL_SQL_MODE_800 = 6; + /** * @var string */ @@ -98,6 +107,11 @@ class Database */ private $_use_innodb = false; + /** + * @var int + */ + private $sqlMode = self::MYSQL_SQL_MODE_NONE; + /** * Logs messages * Logs messages by calling the function held in $_errorlog_fn @@ -214,6 +228,74 @@ private function setCharset() return $retval; } + /** + * Set MySQL sql_mode + * + * @param int $mode one of SQL_MODE_xxx constants + */ + public function setSqlMode($mode) + { + $mode = (int) $mode; + + if (($mode >= self::MYSQL_SQL_MODE_NONE) && ($mode <= self::MYSQL_SQL_MODE_800)) { + $this->sqlMode = $mode; + } else { + throw new InvalidArgumentException(__METHOD__ . ': bad argument was given'); + } + } + + /** + * Return sql_mode string the current MySQL server accepts + * + * @return string + */ + private function getMysqlSqlModeString() + { + $sqlModes = array( + self::MYSQL_SQL_MODE_NONE => array(), + self::MYSQL_SQL_MODE_566 => array( + 'NO_ENGINE_SUBSTITUTION' + ), + self::MYSQL_SQL_MODE_570 => array( + 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_575 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_577 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_578 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', + 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', + ), + self::MYSQL_SQL_MODE_800 => array( + 'ONLY_FULL_GROUP_BY', 'STRICT_TRANS_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', + 'ERROR_FOR_DIVISION_BY_ZERO', 'NO_AUTO_CREATE_USER', 'NO_ENGINE_SUBSTITUTION', + ), + ); + + if ($this->_mysql_version < 50606) { + $currentMode = self::MYSQL_SQL_MODE_NONE; + } elseif (($this->_mysql_version >= 50606) && ($this->_mysql_version < 50700)) { + $currentMode = self::MYSQL_SQL_MODE_566; + } elseif (($this->_mysql_version >= 50700) && ($this->_mysql_version < 50705)) { + $currentMode = self::MYSQL_SQL_MODE_570; + } elseif (($this->_mysql_version >= 50705) && ($this->_mysql_version < 50707)) { + $currentMode = self::MYSQL_SQL_MODE_575; + } elseif (($this->_mysql_version >= 50707) && ($this->_mysql_version < 50708)) { + $currentMode = self::MYSQL_SQL_MODE_577; + } elseif (($this->_mysql_version >= 50708) && ($this->_mysql_version < 80000)) { + $currentMode = self::MYSQL_SQL_MODE_578; + } else { + $currentMode = self::MYSQL_SQL_MODE_800; + } + + $allowedMode = min($this->sqlMode, $currentMode); + + return implode(', ', $sqlModes[$allowedMode]); + } + /** * Return if a given table exists in the current database * @@ -366,6 +448,8 @@ public function dbQuery($sql, $ignore_errors = 0) } // Run query + @$this->_db->query("SET SESSION sql_mode = '" . $this->getMysqlSqlModeString() . "'"); + if ($ignore_errors) { $result = @$this->_db->query($sql); } else { diff --git a/system/lib-database.php b/system/lib-database.php index 191174e9f..8bbecdab4 100755 --- a/system/lib-database.php +++ b/system/lib-database.php @@ -618,3 +618,15 @@ function DB_escapeString($str) return $_DB->dbEscapeString($str); } + +/** + * @param int $mode use one of Database::MYSQL_SQL_MODE_xxx constant + */ +function DB_setMysqlSqlMode($mode) +{ + global $_DB, $_DB_dbms; + + if ($_DB_dbms === 'mysql') { + $_DB->setSqlMode($mode); + } +}