Skip to content

Commit 3ae58da

Browse files
[11.x] Improve MySQL connect init time by setting all our variables in a single shot (#50044)
* Improve MySQL connect init time by setting all our variables in a single * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent a10f616 commit 3ae58da

File tree

3 files changed

+62
-109
lines changed

3 files changed

+62
-109
lines changed

src/Illuminate/Database/Connectors/MariaDbConnector.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,26 @@
77
class MariaDbConnector extends MySqlConnector implements ConnectorInterface
88
{
99
/**
10-
* Get the query to enable strict mode.
10+
* Get the sql_mode value.
1111
*
1212
* @param \PDO $connection
1313
* @param array $config
14-
* @return string
14+
* @return string|null
1515
*/
16-
protected function strictMode(PDO $connection, $config)
16+
protected function getSqlMode(PDO $connection, array $config)
1717
{
18-
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'";
18+
if (isset($config['modes'])) {
19+
return implode(',', $config['modes']);
20+
}
21+
22+
if (! isset($config['strict'])) {
23+
return null;
24+
}
25+
26+
if (! $config['strict']) {
27+
return 'NO_ENGINE_SUBSTITUTION';
28+
}
29+
30+
return 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
1931
}
2032
}

src/Illuminate/Database/Connectors/MySqlConnector.php

Lines changed: 42 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -27,81 +27,11 @@ public function connect(array $config)
2727
$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
}
4334

44-
/**
45-
* Set the connection transaction isolation level.
46-
*
47-
* @param \PDO $connection
48-
* @param array $config
49-
* @return void
50-
*/
51-
protected function configureIsolationLevel($connection, array $config)
52-
{
53-
if (! isset($config['isolation_level'])) {
54-
return;
55-
}
56-
57-
$connection->prepare(
58-
"SET SESSION TRANSACTION ISOLATION LEVEL {$config['isolation_level']}"
59-
)->execute();
60-
}
61-
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;
73-
}
74-
75-
$connection->prepare(
76-
"set names '{$config['charset']}'".$this->getCollation($config)
77-
)->execute();
78-
}
79-
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-
}
90-
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();
102-
}
103-
}
104-
10535
/**
10636
* Create a DSN string from a configuration.
10737
*
@@ -155,54 +85,70 @@ protected function getHostDsn(array $config)
15585
}
15686

15787
/**
158-
* Set the modes for the connection.
88+
* Configure the given PDO connection.
15989
*
16090
* @param \PDO $connection
16191
* @param array $config
16292
* @return void
16393
*/
164-
protected function setModes(PDO $connection, array $config)
94+
protected function configureConnection(PDO $connection, array $config)
16595
{
166-
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();
96+
$statements = [];
97+
98+
if (isset($config['isolation_level'])) {
99+
$statements[] = sprintf('SESSION TRANSACTION ISOLATION LEVEL %s', $config['isolation_level']);
100+
}
101+
102+
if (isset($config['charset'])) {
103+
if (isset($config['collation'])) {
104+
$statements[] = sprintf("NAMES '%s' COLLATE '%s'", $config['charset'], $config['collation']);
171105
} else {
172-
$connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();
106+
$statements[] = sprintf("NAMES '%s'", $config['charset']);
173107
}
174108
}
175-
}
176109

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']);
110+
if (isset($config['timezone'])) {
111+
$statements[] = sprintf("time_zone='%s'", $config['timezone']);
112+
}
187113

188-
$connection->prepare("set session sql_mode='{$modes}'")->execute();
114+
$sqlMode = $this->getSqlMode($connection, $config);
115+
116+
if ($sqlMode !== null) {
117+
$statements[] = sprintf("SESSION sql_mode='%s'", $sqlMode);
118+
}
119+
120+
if ($statements !== []) {
121+
$connection->exec(sprintf('SET %s;', implode(', ', $statements)));
122+
}
189123
}
190124

191125
/**
192-
* Get the query to enable strict mode.
126+
* Get the sql_mode value.
193127
*
194128
* @param \PDO $connection
195129
* @param array $config
196-
* @return string
130+
* @return string|null
197131
*/
198-
protected function strictMode(PDO $connection, $config)
132+
protected function getSqlMode(PDO $connection, array $config)
199133
{
134+
if (isset($config['modes'])) {
135+
return implode(',', $config['modes']);
136+
}
137+
138+
if (! isset($config['strict'])) {
139+
return null;
140+
}
141+
142+
if (! $config['strict']) {
143+
return 'NO_ENGINE_SUBSTITUTION';
144+
}
145+
200146
$version = $config['version'] ?? $connection->getAttribute(PDO::ATTR_SERVER_VERSION);
201147

202148
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'";
149+
return 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
204150
}
205151

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'";
152+
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';
207153
}
208154
}

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)