Skip to content

Commit

Permalink
Fixed a bug where migration failed with MySQL-5.7
Browse files Browse the repository at this point in the history
  • Loading branch information
mystralkk committed Dec 22, 2016
1 parent 87d07e6 commit 21853e3
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 8 deletions.
2 changes: 2 additions & 0 deletions public_html/admin/install/classes/installer.class.php
Expand Up @@ -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) {
Expand Down Expand Up @@ -2912,6 +2913,7 @@ private function doDatabaseUpgrades($currentGlVersion, $checkForMessage = false)
}
} else {
$this->updateDB($_SQL, $progress);
update_dateTimeColumns212();
update_addLanguage();
update_addRouting();
update_ConfValuesFor212();
Expand Down
45 changes: 37 additions & 8 deletions sql/updates/mysql_2.1.1_to_2.1.2.php
@@ -1,13 +1,5 @@
<?php

// Modify DATETIME columns with '0000-00-00 00:00:00' being the default value to DATETIME DEFAULT NULL
// to make Geeklog compatible with MySQL-5.7 with NO_ZERO_DATE in sql_mode
$_SQL[] = "ALTER TABLE {$_TABLES['blocks']} MODIFY COLUMN `rdfupdated` DATETIME DEFAULT NULL";
$_SQL[] = "ALTER TABLE {$_TABLES['stories']} MODIFY COLUMN `comment_expire` DATETIME DEFAULT NULL";
$_SQL[] = "ALTER TABLE {$_TABLES['stories']} MODIFY COLUMN `expire` DATETIME DEFAULT NULL";
$_SQL[] = "ALTER TABLE {$_TABLES['syndication']} MODIFY COLUMN `updated` DATETIME DEFAULT NULL";
$_SQL[] = "ALTER TABLE {$_TABLES['users']} MODIFY COLUMN `regdate` DATETIME DEFAULT NULL";

// Add device type to blocks table
$_SQL[] = "ALTER TABLE {$_TABLES['blocks']} ADD `device` VARCHAR( 15 ) NOT NULL DEFAULT 'all' AFTER `blockorder`";

Expand Down Expand Up @@ -122,6 +114,43 @@ function update_addRouting()
}
}

/**
* Modify DATETIME columns with '0000-00-00 00:00:00' being the default value to DATETIME DEFAULT NULL
* to make Geeklog compatible with MySQL-5.7 with NO_ZERO_DATE in sql_mode
*/
function update_dateTimeColumns212()
{
global $_TABLES;

$date = '2030-01-01 00:00:00';
$_SQL = array();

// Replace '0000-00-00 00:00:00' with a future timestamp temporarily
$_SQL[] = "UPDATE {$_TABLES['blocks']} SET `rdfupdated` = {$date} WHERE `rdfupdated` = '0000-00-00 00:00:00'";
$_SQL[] = "UPDATE {$_TABLES['stories']} SET `comment_expire` = {$date} WHERE `comment_expire` = '0000-00-00 00:00:00'";
$_SQL[] = "UPDATE {$_TABLES['stories']} SET `expire` = {$date} WHERE `expire` = '0000-00-00 00:00:00'";
$_SQL[] = "UPDATE {$_TABLES['syndication']} SET `updated` = {$date} WHERE `updated` = '0000-00-00 00:00:00'";
$_SQL[] = "UPDATE {$_TABLES['users']} SET `regdate` = {$date} WHERE `regdate` = '0000-00-00 00:00:00'";

// Alter columns to allow NULL value
$_SQL[] = "ALTER TABLE {$_TABLES['blocks']} MODIFY COLUMN `rdfupdated` DATETIME";
$_SQL[] = "ALTER TABLE {$_TABLES['stories']} MODIFY COLUMN `comment_expire` DATETIME";
$_SQL[] = "ALTER TABLE {$_TABLES['stories']} MODIFY COLUMN `expire` DATETIME";
$_SQL[] = "ALTER TABLE {$_TABLES['syndication']} MODIFY COLUMN `updated` DATETIME";
$_SQL[] = "ALTER TABLE {$_TABLES['users']} MODIFY COLUMN `regdate` DATETIME";

// Restore '0000-00-00 00:00:00' with NULL
$_SQL[] = "UPDATE {$_TABLES['blocks']} SET `rdfupdated` = NULL WHERE `rdfupdated` = '{$date}'";
$_SQL[] = "UPDATE {$_TABLES['stories']} SET `comment_expire` = NULL WHERE `comment_expire` = '{$date}'";
$_SQL[] = "UPDATE {$_TABLES['stories']} SET `expire` = NULL WHERE `expire` = '{$date}'";
$_SQL[] = "UPDATE {$_TABLES['syndication']} SET `updated` = NULL WHERE `updated` = '{$date}'";
$_SQL[] = "UPDATE {$_TABLES['users']} SET `regdate` = NULL WHERE `regdate` = '{$date}'";

foreach ($_SQL as $sql) {
DB_query($sql, 1);
}
}

/**
* Add new config options
*/
Expand Down
84 changes: 84 additions & 0 deletions system/databases/mysql.class.php
Expand Up @@ -37,6 +37,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
*/
Expand Down Expand Up @@ -97,6 +106,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
Expand Down Expand Up @@ -207,6 +221,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
*
Expand Down Expand Up @@ -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 {
Expand Down
84 changes: 84 additions & 0 deletions system/databases/mysqli.class.php
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 12 additions & 0 deletions system/lib-database.php
Expand Up @@ -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);
}
}

0 comments on commit 21853e3

Please sign in to comment.