mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 02:04:35 +02:00
Update to add removal of incompatible sql_mode settings when used with MySQL 5.7.0 and newer, per issue processwire/processwire-issues#28
This commit is contained in:
@@ -820,6 +820,37 @@ $config->dbHost = '';
|
|||||||
*/
|
*/
|
||||||
$config->dbPort = 3306;
|
$config->dbPort = 3306;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database init command (PDO::MYSQL_ATTR_INIT_COMMAND)
|
||||||
|
*
|
||||||
|
* Note: Placeholder "{charset}" gets automatically replaced with $config->dbCharset.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$config->dbInitCommand = "SET NAMES '{charset}'";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set or adjust SQL mode per MySQL version
|
||||||
|
*
|
||||||
|
* Array indexes are minimum MySQL version mode applies to. Array values are
|
||||||
|
* the names of the mode(s) to apply. If value is preceded with "remove:" the mode will
|
||||||
|
* be removed, or if preceded with "add:" the mode will be added. If neither is present
|
||||||
|
* then the mode will be set exactly as given. To specify more than one SQL mode for the
|
||||||
|
* value, separate them by commas (CSV). To specify multiple statements for the same
|
||||||
|
* version, separate them with a slash "/".
|
||||||
|
*
|
||||||
|
* ~~~~~
|
||||||
|
* array("5.7.0" => "remove:STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY/add:NO_ZERO_DATE")
|
||||||
|
* ~~~~~
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$config->dbSqlModes = array(
|
||||||
|
"5.7.0" => "remove:STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY"
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional DB socket config for sites that need it (for most you should exclude this)
|
* Optional DB socket config for sites that need it (for most you should exclude this)
|
||||||
*
|
*
|
||||||
|
@@ -99,6 +99,8 @@
|
|||||||
* @property string $dbEngine Database engine (MyISAM or InnoDB) #pw-group-database
|
* @property string $dbEngine Database engine (MyISAM or InnoDB) #pw-group-database
|
||||||
* @property string $dbPath MySQL database exec path (Path to mysqldump) #pw-group-database
|
* @property string $dbPath MySQL database exec path (Path to mysqldump) #pw-group-database
|
||||||
* @property int $dbQueryLogMax Maximum number of queries WireDatabasePDO will log in memory, when debug mode is enabled (default=1000). #pw-group-database
|
* @property int $dbQueryLogMax Maximum number of queries WireDatabasePDO will log in memory, when debug mode is enabled (default=1000). #pw-group-database
|
||||||
|
* @property string $dbInitCommand Database init command, for PDO::MYSQL_ATTR_INIT_COMMAND. Note placeholder {charset} gets replaced with $config->dbCharset. #pw-group-database
|
||||||
|
* $property array $dbSqlModes Set, add or remove SQL mode based on MySQL version. See default in /wire/config.php for details. #pw-group-database
|
||||||
*
|
*
|
||||||
* @property array $pageList Settings specific to Page lists. #pw-group-modules
|
* @property array $pageList Settings specific to Page lists. #pw-group-modules
|
||||||
* @property array $pageEdit Settings specific to Page editors. #pw-group-modules
|
* @property array $pageEdit Settings specific to Page editors. #pw-group-modules
|
||||||
|
@@ -55,6 +55,14 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
|||||||
*/
|
*/
|
||||||
protected $pdo = null;
|
protected $pdo = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not our _init() has been called for the current $pdo connection
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $init = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PDO connection settings
|
* PDO connection settings
|
||||||
*
|
*
|
||||||
@@ -99,6 +107,8 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
|||||||
$name = $config->dbName;
|
$name = $config->dbName;
|
||||||
$socket = $config->dbSocket;
|
$socket = $config->dbSocket;
|
||||||
$charset = $config->dbCharset;
|
$charset = $config->dbCharset;
|
||||||
|
$initCommand = str_replace('{charset}', $charset, $config->dbInitCommand);
|
||||||
|
|
||||||
if($socket) {
|
if($socket) {
|
||||||
// if socket is provided ignore $host and $port and use $socket instead:
|
// if socket is provided ignore $host and $port and use $socket instead:
|
||||||
$dsn = "mysql:unix_socket=$socket;dbname=$name;";
|
$dsn = "mysql:unix_socket=$socket;dbname=$name;";
|
||||||
@@ -107,13 +117,18 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
|||||||
$port = $config->dbPort;
|
$port = $config->dbPort;
|
||||||
if($port) $dsn .= ";port=$port";
|
if($port) $dsn .= ";port=$port";
|
||||||
}
|
}
|
||||||
|
|
||||||
$driver_options = array(
|
$driver_options = array(
|
||||||
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES '$charset'",
|
|
||||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
|
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if($initCommand) $driver_options[\PDO::MYSQL_ATTR_INIT_COMMAND] = $initCommand;
|
||||||
|
|
||||||
$database = new WireDatabasePDO($dsn, $username, $password, $driver_options);
|
$database = new WireDatabasePDO($dsn, $username, $password, $driver_options);
|
||||||
$database->setDebugMode($config->debug);
|
$database->setDebugMode($config->debug);
|
||||||
$config->wire($database);
|
$config->wire($database);
|
||||||
|
$database->_init();
|
||||||
|
|
||||||
return $database;
|
return $database;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +149,37 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
|||||||
$this->pdoConfig['pass'] = $password;
|
$this->pdoConfig['pass'] = $password;
|
||||||
$this->pdoConfig['options'] = $driver_options;
|
$this->pdoConfig['options'] = $driver_options;
|
||||||
$this->pdo();
|
$this->pdo();
|
||||||
$this->queryLogMax = (int) $this->wire('config')->dbQueryLogMax;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional initialization after DB connection established and Wire instance populated
|
||||||
|
*
|
||||||
|
* #pw-internal
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function _init() {
|
||||||
|
if($this->init || !$this->isWired()) return;
|
||||||
|
$this->init = true;
|
||||||
|
$config = $this->wire('config');
|
||||||
|
$this->queryLogMax = (int) $config->dbQueryLogMax;
|
||||||
|
$sqlModes = $config->dbSqlModes;
|
||||||
|
if(is_array($sqlModes)) {
|
||||||
|
// ["5.7.0" => "remove:mode1,mode2/add:mode3"]
|
||||||
|
foreach($sqlModes as $minVersion => $commands) {
|
||||||
|
if(strpos($commands, '/') !== false) {
|
||||||
|
$commands = explode('/', $commands);
|
||||||
|
} else {
|
||||||
|
$commands = array($commands);
|
||||||
|
}
|
||||||
|
foreach($commands as $modes) {
|
||||||
|
$modes = trim($modes);
|
||||||
|
if(empty($modes)) continue;
|
||||||
|
$action = 'set';
|
||||||
|
if(strpos($modes, ':')) list($action, $modes) = explode(':', $modes);
|
||||||
|
$this->sqlMode(trim($action), trim($modes), $minVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,12 +193,16 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function pdo() {
|
public function pdo() {
|
||||||
if(!$this->pdo) $this->pdo = new \PDO(
|
if(!$this->pdo) {
|
||||||
|
$this->init = false;
|
||||||
|
$this->pdo = new \PDO(
|
||||||
$this->pdoConfig['dsn'],
|
$this->pdoConfig['dsn'],
|
||||||
$this->pdoConfig['user'],
|
$this->pdoConfig['user'],
|
||||||
$this->pdoConfig['pass'],
|
$this->pdoConfig['pass'],
|
||||||
$this->pdoConfig['options']
|
$this->pdoConfig['options']
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
if(!$this->init) $this->_init();
|
||||||
return $this->pdo;
|
return $this->pdo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,4 +780,73 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
|||||||
return $max;
|
return $max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SQL mode, set SQL mode, add to existing SQL mode, or remove from existing SQL mode
|
||||||
|
*
|
||||||
|
* #pw-group-custom
|
||||||
|
*
|
||||||
|
* ~~~~~
|
||||||
|
* // Get SQL mode
|
||||||
|
* $mode = $database->sqlMode();
|
||||||
|
*
|
||||||
|
* // Add an SQL mode
|
||||||
|
* $database->sqlMode('add', 'STRICT_TRANS_TABLES');
|
||||||
|
*
|
||||||
|
* // Remove SQL mode if version at least 5.7.0
|
||||||
|
* $database->sqlMode('remove', 'ONLY_FULL_GROUP_BY', '5.7.0');
|
||||||
|
* ~~~~~
|
||||||
|
*
|
||||||
|
* @param string $action Specify "get", "set", "add" or "remove". (default="get")
|
||||||
|
* @param string $mode Mode string or CSV string with SQL mode(s), i.e. "STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY".
|
||||||
|
* This argument should be omitted when using the "get" action.
|
||||||
|
* @param string $minVersion Make the given action only apply if MySQL version is at least $minVersion, i.e. "5.7.0".
|
||||||
|
* @return string|bool Returns string in "get" action, boolean false if required version not present, or true otherwise.
|
||||||
|
* @throws WireException If given an invalid $action
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function sqlMode($action = 'get', $mode = '', $minVersion = '') {
|
||||||
|
|
||||||
|
$result = true;
|
||||||
|
$modes = array();
|
||||||
|
|
||||||
|
if(empty($action)) $action = 'get';
|
||||||
|
|
||||||
|
if($action !== 'get' && $minVersion) {
|
||||||
|
$serverVersion = $this->getAttribute(\PDO::ATTR_SERVER_VERSION);
|
||||||
|
if(version_compare($serverVersion, $minVersion, '<')) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($mode) {
|
||||||
|
foreach(explode(',', $mode) as $m) {
|
||||||
|
$modes[] = $this->escapeStr(strtoupper($this->wire('sanitizer')->fieldName($m)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($action) {
|
||||||
|
case 'get':
|
||||||
|
$query = $this->pdo()->query("SELECT @@sql_mode");
|
||||||
|
$result = $query->fetchColumn();
|
||||||
|
$query->closeCursor();
|
||||||
|
break;
|
||||||
|
case 'set':
|
||||||
|
$modes = implode(',', $modes);
|
||||||
|
$result = $modes;
|
||||||
|
$this->pdo()->exec("SET sql_mode='$modes'");
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
foreach($modes as $m) {
|
||||||
|
$this->pdo()->exec("SET sql_mode=(SELECT CONCAT(@@sql_mode,',$m'))");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'remove':
|
||||||
|
foreach($modes as $m) {
|
||||||
|
$this->pdo()->exec("SET sql_mode=(SELECT REPLACE(@@sql_mode,'$m',''))");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new WireException("Unknown action '$action'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user