From 80d1f9abb0facb096e588785b245cbbc9c8beae7 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Mon, 19 Feb 2024 21:17:14 +0000 Subject: [PATCH 1/2] Improve MySQL connect init time by setting all our variables in a single --- .../Database/Connectors/MariaDbConnector.php | 20 ++- .../Database/Connectors/MySqlConnector.php | 130 ++++++------------ tests/Database/DatabaseConnectorTest.php | 13 +- 3 files changed, 61 insertions(+), 102 deletions(-) diff --git a/src/Illuminate/Database/Connectors/MariaDbConnector.php b/src/Illuminate/Database/Connectors/MariaDbConnector.php index 50b8ac5d1055..560e31c96916 100755 --- a/src/Illuminate/Database/Connectors/MariaDbConnector.php +++ b/src/Illuminate/Database/Connectors/MariaDbConnector.php @@ -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'; } } diff --git a/src/Illuminate/Database/Connectors/MySqlConnector.php b/src/Illuminate/Database/Connectors/MySqlConnector.php index a7640859d77c..4932e8e48713 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(PDO $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(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(); - } 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); From 61114d83bfccbf03cfd95e8a63eca1b87a1f345e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 21 Feb 2024 14:06:20 -0600 Subject: [PATCH 2/2] formatting --- .../Database/Connectors/MySqlConnector.php | 82 +++++++++---------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/src/Illuminate/Database/Connectors/MySqlConnector.php b/src/Illuminate/Database/Connectors/MySqlConnector.php index 4932e8e48713..51b6a79ca135 100755 --- a/src/Illuminate/Database/Connectors/MySqlConnector.php +++ b/src/Illuminate/Database/Connectors/MySqlConnector.php @@ -32,50 +32,6 @@ public function connect(array $config) return $connection; } - /** - * Configure the connection. - * - * @param \PDO $connection - * @param array $config - * @return void - */ - protected function configureConnection(PDO $connection, array $config) - { - $statements = []; - - // First, we set the transaction isolation level. - if (isset($config['isolation_level'])) { - $statements[] = sprintf('SESSION TRANSACTION ISOLATION LEVEL %s', $config['isolation_level']); - } - - // 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']); - } - } - - // 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']); - } - - // 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); - } - - // Finally, execute a single SET command with all our statements. - if ([] !== $statements) { - $connection->exec(sprintf('SET %s;', implode(', ', $statements))); - } - } - /** * Create a DSN string from a configuration. * @@ -128,6 +84,44 @@ protected function getHostDsn(array $config) : "mysql:host={$host};dbname={$database}"; } + /** + * Configure the given PDO connection. + * + * @param \PDO $connection + * @param array $config + * @return void + */ + protected function configureConnection(PDO $connection, array $config) + { + $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 { + $statements[] = sprintf("NAMES '%s'", $config['charset']); + } + } + + if (isset($config['timezone'])) { + $statements[] = sprintf("time_zone='%s'", $config['timezone']); + } + + $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 sql_mode value. *