Skip to content

Commit 629ecec

Browse files
Improve MySQL connect init time by setting all our variables in a single shot
1 parent 67a0e47 commit 629ecec

File tree

2 files changed

+45
-98
lines changed

2 files changed

+45
-98
lines changed

src/Illuminate/Database/Connectors/MySqlConnector.php

Lines changed: 41 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,10 @@ public function connect(array $config)
2424
$connection = $this->createConnection($dsn, $config, $options);
2525

2626
if (! empty($config['database'])) {
27-
$connection->exec("use `{$config['database']}`;");
27+
$connection->exec("USE `{$config['database']}`;");
2828
}
2929

30-
$this->configureIsolationLevel($connection, $config);
31-
32-
$this->configureEncoding($connection, $config);
33-
34-
// Next, we will check to see if a timezone has been specified in this config
35-
// and if it has we will issue a statement to modify the timezone with the
36-
// database. Setting this DB timezone is an optional configuration item.
37-
$this->configureTimezone($connection, $config);
38-
39-
$this->setModes($connection, $config);
30+
$this->configureConnection($connection, $config);
4031

4132
return $connection;
4233
}
@@ -48,57 +39,40 @@ public function connect(array $config)
4839
* @param array $config
4940
* @return void
5041
*/
51-
protected function configureIsolationLevel($connection, array $config)
42+
protected function configureConnection($connection, array $config)
5243
{
53-
if (! isset($config['isolation_level'])) {
54-
return;
55-
}
44+
$statements = [];
5645

57-
$connection->prepare(
58-
"SET SESSION TRANSACTION ISOLATION LEVEL {$config['isolation_level']}"
59-
)->execute();
60-
}
46+
// First, we set the transaction isolation level.
47+
if (isset($config['isolation_level'])) {
48+
$statements[] = sprintf('SESSION TRANSACTION ISOLATION LEVEL %s', $config['isolation_level']);
49+
}
6150

62-
/**
63-
* Set the connection character set and collation.
64-
*
65-
* @param \PDO $connection
66-
* @param array $config
67-
* @return void|\PDO
68-
*/
69-
protected function configureEncoding($connection, array $config)
70-
{
71-
if (! isset($config['charset'])) {
72-
return $connection;
51+
// Now, we set the charset and possibly the collation.
52+
if (isset($config['charset'])) {
53+
if (isset($config['collation'])) {
54+
$statements[] = sprintf("NAMES '%s' COLLATE '%s'", $config['charset'], $config['collation']);
55+
} else {
56+
$statements[] = sprintf("NAMES '%s'", $config['charset']);
57+
}
7358
}
7459

75-
$connection->prepare(
76-
"set names '{$config['charset']}'".$this->getCollation($config)
77-
)->execute();
78-
}
60+
// Next, we will check to see if a timezone has been specified in this config
61+
// and if it has we will issue a statement to modify the timezone with the
62+
// database. Setting this DB timezone is an optional configuration item.
63+
if (isset($config['timezone'])) {
64+
$statements[] = sprintf("time_zone='%s'", $config['timezone']);
65+
}
7966

80-
/**
81-
* Get the collation for the configuration.
82-
*
83-
* @param array $config
84-
* @return string
85-
*/
86-
protected function getCollation(array $config)
87-
{
88-
return isset($config['collation']) ? " collate '{$config['collation']}'" : '';
89-
}
67+
// Next, we set the correct sql_mode mode according to the config.
68+
$sqlMode = $this->getSqlMode($connection, $config);
69+
if (null !== $sqlMode) {
70+
$statements[] = sprintf("SESSION sql_mode='%s'", $sqlMode);
71+
}
9072

91-
/**
92-
* Set the timezone on the connection.
93-
*
94-
* @param \PDO $connection
95-
* @param array $config
96-
* @return void
97-
*/
98-
protected function configureTimezone($connection, array $config)
99-
{
100-
if (isset($config['timezone'])) {
101-
$connection->prepare('set time_zone="'.$config['timezone'].'"')->execute();
73+
// Finally, execute a single SET command with all our statements.
74+
if ([] !== $statements) {
75+
$connection->exec(sprintf('SET %s;', implode(', ', $statements)));
10276
}
10377
}
10478

@@ -155,54 +129,32 @@ protected function getHostDsn(array $config)
155129
}
156130

157131
/**
158-
* Set the modes for the connection.
132+
* Get the sql_mode value.
159133
*
160134
* @param \PDO $connection
161135
* @param array $config
162-
* @return void
136+
* @return string|null
163137
*/
164-
protected function setModes(PDO $connection, array $config)
138+
protected function getSqlMode($connection, $config)
165139
{
166140
if (isset($config['modes'])) {
167-
$this->setCustomModes($connection, $config);
168-
} elseif (isset($config['strict'])) {
169-
if ($config['strict']) {
170-
$connection->prepare($this->strictMode($connection, $config))->execute();
171-
} else {
172-
$connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();
173-
}
141+
return implode(',', $config['modes']);
174142
}
175-
}
176143

177-
/**
178-
* Set the custom modes on the connection.
179-
*
180-
* @param \PDO $connection
181-
* @param array $config
182-
* @return void
183-
*/
184-
protected function setCustomModes(PDO $connection, array $config)
185-
{
186-
$modes = implode(',', $config['modes']);
144+
if (! isset($config['strict'])) {
145+
return null;
146+
}
187147

188-
$connection->prepare("set session sql_mode='{$modes}'")->execute();
189-
}
148+
if (! $config['strict']) {
149+
return 'NO_ENGINE_SUBSTITUTION';
150+
}
190151

191-
/**
192-
* Get the query to enable strict mode.
193-
*
194-
* @param \PDO $connection
195-
* @param array $config
196-
* @return string
197-
*/
198-
protected function strictMode(PDO $connection, $config)
199-
{
200152
$version = $config['version'] ?? $connection->getAttribute(PDO::ATTR_SERVER_VERSION);
201153

202154
if (version_compare($version, '8.0.11') >= 0) {
203-
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'";
155+
return 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
204156
}
205157

206-
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'";
158+
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';
207159
}
208160
}

tests/Database/DatabaseConnectorTest.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,8 @@ public function testMySqlConnectCallsCreateConnectionWithProperArguments($dsn, $
3636
$connection = m::mock(PDO::class);
3737
$connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']);
3838
$connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection);
39-
$statement = m::mock(PDOStatement::class);
40-
$connection->shouldReceive('prepare')->once()->with('set names \'utf8\' collate \'utf8_unicode_ci\'')->andReturn($statement);
41-
$statement->shouldReceive('execute')->once();
42-
$connection->shouldReceive('exec')->zeroOrMoreTimes();
39+
$connection->shouldReceive('exec')->once()->with('USE `bar`;')->andReturn(true);
40+
$connection->shouldReceive('exec')->once()->with("SET NAMES 'utf8' COLLATE 'utf8_unicode_ci';")->andReturn(true);
4341
$result = $connector->connect($config);
4442

4543
$this->assertSame($result, $connection);
@@ -63,11 +61,8 @@ public function testMySqlConnectCallsCreateConnectionWithIsolationLevel()
6361
$connection = m::mock(PDO::class);
6462
$connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']);
6563
$connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection);
66-
$statement = m::mock(PDOStatement::class);
67-
$connection->shouldReceive('prepare')->once()->with('set names \'utf8\' collate \'utf8_unicode_ci\'')->andReturn($statement);
68-
$connection->shouldReceive('prepare')->once()->with('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ')->andReturn($statement);
69-
$statement->shouldReceive('execute')->zeroOrMoreTimes();
70-
$connection->shouldReceive('exec')->zeroOrMoreTimes();
64+
$connection->shouldReceive('exec')->once()->with('USE `bar`;')->andReturn(true);
65+
$connection->shouldReceive('exec')->once()->with("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, NAMES 'utf8' COLLATE 'utf8_unicode_ci';")->andReturn(true);
7166
$result = $connector->connect($config);
7267

7368
$this->assertSame($result, $connection);

0 commit comments

Comments
 (0)