Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/Illuminate/Database/Connectors/MariaDbConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,26 @@
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(PDO $connection, array $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';
}
}
138 changes: 42 additions & 96 deletions src/Illuminate/Database/Connectors/MySqlConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,81 +27,11 @@ 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.
*
* @param \PDO $connection
* @param array $config
* @return void
*/
protected function configureIsolationLevel($connection, array $config)
{
if (! isset($config['isolation_level'])) {
return;
}

$connection->prepare(
"SET SESSION TRANSACTION ISOLATION LEVEL {$config['isolation_level']}"
)->execute();
}

/**
* 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;
}

$connection->prepare(
"set names '{$config['charset']}'".$this->getCollation($config)
)->execute();
}

/**
* Get the collation for the configuration.
*
* @param array $config
* @return string
*/
protected function getCollation(array $config)
{
return isset($config['collation']) ? " collate '{$config['collation']}'" : '';
}

/**
* 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();
}
}

/**
* Create a DSN string from a configuration.
*
Expand Down Expand Up @@ -155,54 +85,70 @@ protected function getHostDsn(array $config)
}

/**
* Set the modes for the connection.
* Configure the given PDO connection.
*
* @param \PDO $connection
* @param array $config
* @return void
*/
protected function setModes(PDO $connection, array $config)
protected function configureConnection(PDO $connection, array $config)
{
if (isset($config['modes'])) {
$this->setCustomModes($connection, $config);
} elseif (isset($config['strict'])) {
if ($config['strict']) {
$connection->prepare($this->strictMode($connection, $config))->execute();
$statements = [];

if (isset($config['isolation_level'])) {
$statements[] = sprintf('SESSION TRANSACTION ISOLATION LEVEL %s', $config['isolation_level']);
}

if (isset($config['charset'])) {
if (isset($config['collation'])) {
$statements[] = sprintf("NAMES '%s' COLLATE '%s'", $config['charset'], $config['collation']);
} else {
$connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();
$statements[] = sprintf("NAMES '%s'", $config['charset']);
}
}
}

/**
* 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['timezone'])) {
$statements[] = sprintf("time_zone='%s'", $config['timezone']);
}

$connection->prepare("set session sql_mode='{$modes}'")->execute();
$sqlMode = $this->getSqlMode($connection, $config);

if ($sqlMode !== null) {
$statements[] = sprintf("SESSION sql_mode='%s'", $sqlMode);
}

if ($statements !== []) {
$connection->exec(sprintf('SET %s;', implode(', ', $statements)));
}
}

/**
* 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(PDO $connection, array $config)
{
if (isset($config['modes'])) {
return implode(',', $config['modes']);
}

if (! isset($config['strict'])) {
return null;
}

if (! $config['strict']) {
return 'NO_ENGINE_SUBSTITUTION';
}

$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';
}
}
13 changes: 4 additions & 9 deletions tests/Database/DatabaseConnectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down