diff --git a/src/Illuminate/Database/Connectors/MariaDbConnector.php b/src/Illuminate/Database/Connectors/MariaDbConnector.php index 50b8ac5d1055..8d7042851f2c 100755 --- a/src/Illuminate/Database/Connectors/MariaDbConnector.php +++ b/src/Illuminate/Database/Connectors/MariaDbConnector.php @@ -6,15 +6,28 @@ class MariaDbConnector extends MySqlConnector implements ConnectorInterface { + /** - * Get the query to enable strict mode. + * Get the sql_mode value. * * @param \PDO $connection * @param array $config - * @return string + * @return string|null */ - protected function strictMode(PDO $connection, $config) + protected function getSqlMode($connection, $config) { - return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'"; + if (isset($config['modes'])) { + return implode(',', $config['modes']); + } + + if (! isset($config['strict'])) { + return null; + } + + if (! $config['strict']) { + return 'NO_ENGINE_SUBSTITUTION'; + } + + return 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; } } diff --git a/src/Illuminate/Database/Connectors/MySqlConnector.php b/src/Illuminate/Database/Connectors/MySqlConnector.php index a7640859d77c..8e529ef5b0af 100755 --- a/src/Illuminate/Database/Connectors/MySqlConnector.php +++ b/src/Illuminate/Database/Connectors/MySqlConnector.php @@ -27,78 +27,52 @@ public function connect(array $config) $connection->exec("use `{$config['database']}`;"); } - $this->configureIsolationLevel($connection, $config); - - $this->configureEncoding($connection, $config); - - // Next, we will check to see if a timezone has been specified in this config - // and if it has we will issue a statement to modify the timezone with the - // database. Setting this DB timezone is an optional configuration item. - $this->configureTimezone($connection, $config); - - $this->setModes($connection, $config); + $this->configureConnection($connection, $config); return $connection; } /** - * Set the connection transaction isolation level. + * Configure the connection. * * @param \PDO $connection * @param array $config * @return void */ - protected function configureIsolationLevel($connection, array $config) + protected function configureConnection($connection, array $config) { - if (! isset($config['isolation_level'])) { - return; - } + $statements = []; - $connection->prepare( - "SET SESSION TRANSACTION ISOLATION LEVEL {$config['isolation_level']}" - )->execute(); - } + // First, we set the transaction isolation level. + if (isset($config['isolation_level'])) { + $statements[] = sprintf('SESSION TRANSACTION ISOLATION LEVEL %s', $config['isolation_level']); + } - /** - * Set the connection character set and collation. - * - * @param \PDO $connection - * @param array $config - * @return void|\PDO - */ - protected function configureEncoding($connection, array $config) - { - if (! isset($config['charset'])) { - return $connection; + // Now, we set the charset and possibly the collation. + if (isset($config['charset'])) { + if (isset($config['collation'])) { + $statements[] = sprintf("NAMES '%s' COLLATE '%s'", $config['charset'], $config['collation']); + } else { + $statements[] = sprintf("NAMES '%s'", $config['charset']); + } } - $connection->prepare( - "set names '{$config['charset']}'".$this->getCollation($config) - )->execute(); - } + // Next, we will check to see if a timezone has been specified in this config + // and if it has we will issue a statement to modify the timezone with the + // database. Setting this DB timezone is an optional configuration item. + if (isset($config['timezone'])) { + $statements[] = sprintf("time_zone='%s'", $config['timezone']); + } - /** - * Get the collation for the configuration. - * - * @param array $config - * @return string - */ - protected function getCollation(array $config) - { - return isset($config['collation']) ? " collate '{$config['collation']}'" : ''; - } + // Next, we set the correct sql_mode mode according to the config. + $sqlMode = $this->getSqlMode($connection, $config); + if (null !== $sqlMode) { + $statements[] = sprintf("SESSION sql_mode='%s'", $sqlMode); + } - /** - * Set the timezone on the connection. - * - * @param \PDO $connection - * @param array $config - * @return void - */ - protected function configureTimezone($connection, array $config) - { - if (isset($config['timezone'])) { - $connection->prepare('set time_zone="'.$config['timezone'].'"')->execute(); + // Finally, execute a single SET command with all our statements. + if ([] !== $statements) { + $connection->exec(sprintf('SET %s;', implode(', ', $statements))); } } @@ -155,54 +129,32 @@ protected function getHostDsn(array $config) } /** - * Set the modes for the connection. + * Get the sql_mode value. * * @param \PDO $connection * @param array $config - * @return void + * @return string|null */ - protected function setModes(PDO $connection, array $config) + protected function getSqlMode($connection, $config) { if (isset($config['modes'])) { - $this->setCustomModes($connection, $config); - } elseif (isset($config['strict'])) { - if ($config['strict']) { - $connection->prepare($this->strictMode($connection, $config))->execute(); - } else { - $connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute(); - } + return implode(',', $config['modes']); } - } - /** - * Set the custom modes on the connection. - * - * @param \PDO $connection - * @param array $config - * @return void - */ - protected function setCustomModes(PDO $connection, array $config) - { - $modes = implode(',', $config['modes']); + if (! isset($config['strict'])) { + return null; + } - $connection->prepare("set session sql_mode='{$modes}'")->execute(); - } + if (! $config['strict']) { + return 'NO_ENGINE_SUBSTITUTION'; + } - /** - * Get the query to enable strict mode. - * - * @param \PDO $connection - * @param array $config - * @return string - */ - protected function strictMode(PDO $connection, $config) - { $version = $config['version'] ?? $connection->getAttribute(PDO::ATTR_SERVER_VERSION); if (version_compare($version, '8.0.11') >= 0) { - return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'"; + return 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; } - return "set session sql_mode='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'"; + return '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'; } } diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index 7ada98829e8a..4774b6caff73 100755 --- a/tests/Database/DatabaseConnectorTest.php +++ b/tests/Database/DatabaseConnectorTest.php @@ -36,10 +36,8 @@ public function testMySqlConnectCallsCreateConnectionWithProperArguments($dsn, $ $connection = m::mock(PDO::class); $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']); $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection); - $statement = m::mock(PDOStatement::class); - $connection->shouldReceive('prepare')->once()->with('set names \'utf8\' collate \'utf8_unicode_ci\'')->andReturn($statement); - $statement->shouldReceive('execute')->once(); - $connection->shouldReceive('exec')->zeroOrMoreTimes(); + $connection->shouldReceive('exec')->once()->with('use `bar`;')->andReturn(true); + $connection->shouldReceive('exec')->once()->with("SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';")->andReturn(true); $result = $connector->connect($config); $this->assertSame($result, $connection); @@ -63,11 +61,8 @@ public function testMySqlConnectCallsCreateConnectionWithIsolationLevel() $connection = m::mock(PDO::class); $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']); $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection); - $statement = m::mock(PDOStatement::class); - $connection->shouldReceive('prepare')->once()->with('set names \'utf8\' collate \'utf8_unicode_ci\'')->andReturn($statement); - $connection->shouldReceive('prepare')->once()->with('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ')->andReturn($statement); - $statement->shouldReceive('execute')->zeroOrMoreTimes(); - $connection->shouldReceive('exec')->zeroOrMoreTimes(); + $connection->shouldReceive('exec')->once()->with('use `bar`;')->andReturn(true); + $connection->shouldReceive('exec')->once()->with("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, NAMES 'utf8' COLLATE 'utf8_unicode_ci';")->andReturn(true); $result = $connector->connect($config); $this->assertSame($result, $connection);