Skip to content

Commit 6230d56

Browse files
authored
Set application_name and character set as DSN string. (#51985)
1 parent fc70c5e commit 6230d56

File tree

2 files changed

+21
-52
lines changed

2 files changed

+21
-52
lines changed

src/Illuminate/Database/Connectors/PostgresConnector.php

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,13 @@ public function connect(array $config)
3838

3939
$this->configureIsolationLevel($connection, $config);
4040

41-
$this->configureEncoding($connection, $config);
42-
4341
// Next, we will check to see if a timezone has been specified in this config
4442
// and if it has we will issue a statement to modify the timezone with the
4543
// database. Setting this DB timezone is an optional configuration item.
4644
$this->configureTimezone($connection, $config);
4745

4846
$this->configureSearchPath($connection, $config);
4947

50-
// Postgres allows an application_name to be set by the user and this name is
51-
// used to when monitoring the application with pg_stat_activity. So we'll
52-
// determine if the option has been specified and run a statement if so.
53-
$this->configureApplicationName($connection, $config);
54-
5548
$this->configureSynchronousCommit($connection, $config);
5649

5750
return $connection;
@@ -71,22 +64,6 @@ protected function configureIsolationLevel($connection, array $config)
7164
}
7265
}
7366

74-
/**
75-
* Set the connection character set and collation.
76-
*
77-
* @param \PDO $connection
78-
* @param array $config
79-
* @return void
80-
*/
81-
protected function configureEncoding($connection, $config)
82-
{
83-
if (! isset($config['charset'])) {
84-
return;
85-
}
86-
87-
$connection->prepare("set names '{$config['charset']}'")->execute();
88-
}
89-
9067
/**
9168
* Set the timezone on the connection.
9269
*
@@ -132,22 +109,6 @@ protected function quoteSearchPath($searchPath)
132109
return count($searchPath) === 1 ? '"'.$searchPath[0].'"' : '"'.implode('", "', $searchPath).'"';
133110
}
134111

135-
/**
136-
* Set the application name on the connection.
137-
*
138-
* @param \PDO $connection
139-
* @param array $config
140-
* @return void
141-
*/
142-
protected function configureApplicationName($connection, $config)
143-
{
144-
if (isset($config['application_name'])) {
145-
$applicationName = $config['application_name'];
146-
147-
$connection->prepare("set application_name to '$applicationName'")->execute();
148-
}
149-
}
150-
151112
/**
152113
* Create a DSN string from a configuration.
153114
*
@@ -178,6 +139,17 @@ protected function getDsn(array $config)
178139
$dsn .= ";port={$port}";
179140
}
180141

142+
if (isset($charset)) {
143+
$dsn .= ";client_encoding='{$charset}'";
144+
}
145+
146+
// Postgres allows an application_name to be set by the user and this name is
147+
// used to when monitoring the application with pg_stat_activity. So we'll
148+
// determine if the option has been specified and run a statement if so.
149+
if (isset($application_name)) {
150+
$dsn .= ";application_name='".str_replace("'", "\'", $application_name)."'";
151+
}
152+
181153
return $this->addSslOptions($dsn, $config);
182154
}
183155

tests/Database/DatabaseConnectorTest.php

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ public function testMySqlConnectCallsCreateConnectionWithIsolationLevel()
7575

7676
public function testPostgresConnectCallsCreateConnectionWithProperArguments()
7777
{
78-
$dsn = 'pgsql:host=foo;dbname=\'bar\';port=111';
78+
$dsn = 'pgsql:host=foo;dbname=\'bar\';port=111;client_encoding=\'utf8\'';
7979
$config = ['host' => 'foo', 'database' => 'bar', 'port' => 111, 'charset' => 'utf8'];
8080
$connector = $this->getMockBuilder(PostgresConnector::class)->onlyMethods(['createConnection', 'getOptions'])->getMock();
8181
$connection = m::mock(stdClass::class);
8282
$connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']);
8383
$connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection);
8484
$statement = m::mock(PDOStatement::class);
85-
$connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($statement);
86-
$statement->shouldReceive('execute')->once();
85+
$connection->shouldReceive('prepare')->zeroOrMoreTimes()->andReturn($statement);
86+
$statement->shouldReceive('execute')->zeroOrMoreTimes();
8787
$result = $connector->connect($config);
8888

8989
$this->assertSame($result, $connection);
@@ -97,16 +97,15 @@ public function testPostgresConnectCallsCreateConnectionWithProperArguments()
9797
*/
9898
public function testPostgresSearchPathIsSet($searchPath, $expectedSql)
9999
{
100-
$dsn = 'pgsql:host=foo;dbname=\'bar\'';
100+
$dsn = 'pgsql:host=foo;dbname=\'bar\';client_encoding=\'utf8\'';
101101
$config = ['host' => 'foo', 'database' => 'bar', 'search_path' => $searchPath, 'charset' => 'utf8'];
102102
$connector = $this->getMockBuilder(PostgresConnector::class)->onlyMethods(['createConnection', 'getOptions'])->getMock();
103103
$connection = m::mock(stdClass::class);
104104
$connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']);
105105
$connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection);
106106
$statement = m::mock(PDOStatement::class);
107-
$connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($statement);
108107
$connection->shouldReceive('prepare')->once()->with($expectedSql)->andReturn($statement);
109-
$statement->shouldReceive('execute')->twice();
108+
$statement->shouldReceive('execute')->once();
110109
$result = $connector->connect($config);
111110

112111
$this->assertSame($result, $connection);
@@ -184,33 +183,31 @@ public static function provideSearchPaths()
184183

185184
public function testPostgresSearchPathFallbackToConfigKeySchema()
186185
{
187-
$dsn = 'pgsql:host=foo;dbname=\'bar\'';
186+
$dsn = 'pgsql:host=foo;dbname=\'bar\';client_encoding=\'utf8\'';
188187
$config = ['host' => 'foo', 'database' => 'bar', 'schema' => ['public', '"user"'], 'charset' => 'utf8'];
189188
$connector = $this->getMockBuilder(PostgresConnector::class)->onlyMethods(['createConnection', 'getOptions'])->getMock();
190189
$connection = m::mock(stdClass::class);
191190
$connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']);
192191
$connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection);
193192
$statement = m::mock(PDOStatement::class);
194-
$connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($statement);
195193
$connection->shouldReceive('prepare')->once()->with('set search_path to "public", "user"')->andReturn($statement);
196-
$statement->shouldReceive('execute')->twice();
194+
$statement->shouldReceive('execute')->once();
197195
$result = $connector->connect($config);
198196

199197
$this->assertSame($result, $connection);
200198
}
201199

202200
public function testPostgresApplicationNameIsSet()
203201
{
204-
$dsn = 'pgsql:host=foo;dbname=\'bar\'';
202+
$dsn = 'pgsql:host=foo;dbname=\'bar\';client_encoding=\'utf8\';application_name=\'Laravel App\'';
205203
$config = ['host' => 'foo', 'database' => 'bar', 'charset' => 'utf8', 'application_name' => 'Laravel App'];
206204
$connector = $this->getMockBuilder(PostgresConnector::class)->onlyMethods(['createConnection', 'getOptions'])->getMock();
207205
$connection = m::mock(stdClass::class);
208206
$connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->willReturn(['options']);
209207
$connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->willReturn($connection);
210208
$statement = m::mock(PDOStatement::class);
211-
$connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($statement);
212-
$connection->shouldReceive('prepare')->once()->with('set application_name to \'Laravel App\'')->andReturn($statement);
213-
$statement->shouldReceive('execute')->twice();
209+
$connection->shouldReceive('prepare')->zeroOrMoreTimes()->andReturn($statement);
210+
$statement->shouldReceive('execute')->zeroOrMoreTimes();
214211
$result = $connector->connect($config);
215212

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

0 commit comments

Comments
 (0)