From dc9af65105d735a24321697eaf82f1e247cf3756 Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 4 Aug 2022 06:43:54 -0700 Subject: [PATCH] [9.x] Alternative database name in Postgres DSN, allow pgbouncer aliased databases to continue working on 9.x (#43542) * feat: allow creating a Postgres DSN string with a different database name than is used for information_schema queries See https://github.com/laravel/framework/discussions/43536 * formatting Co-authored-by: Taylor Otwell --- .../Database/Connectors/PostgresConnector.php | 5 +++++ tests/Database/DatabaseConnectorTest.php | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index 6331bc2d786b..c54163f9b89f 100755 --- a/src/Illuminate/Database/Connectors/PostgresConnector.php +++ b/src/Illuminate/Database/Connectors/PostgresConnector.php @@ -163,6 +163,11 @@ protected function getDsn(array $config) $host = isset($host) ? "host={$host};" : ''; + // Sometimes - users may need to connect to a database that has a different + // name than the database used for "information_schema" queries. This is + // typically the case if using "pgbouncer" type software when pooling. + $database = $connect_via_database ?? $database; + $dsn = "pgsql:{$host}dbname='{$database}'"; // If a port was specified, we will add it to this Postgres DSN connections diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index 221223619552..bda58cafb569 100755 --- a/tests/Database/DatabaseConnectorTest.php +++ b/tests/Database/DatabaseConnectorTest.php @@ -216,6 +216,22 @@ public function testPostgresApplicationNameIsSet() $this->assertSame($result, $connection); } + public function testPostgresApplicationUseAlternativeDatabaseName() + { + $dsn = 'pgsql:dbname=\'baz\''; + $config = ['database' => 'bar', 'connect_via_database' => 'baz']; + $connector = $this->getMockBuilder(PostgresConnector::class)->onlyMethods(['createConnection', 'getOptions'])->getMock(); + $connection = m::mock(stdClass::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')->zeroOrMoreTimes()->andReturn($statement); + $statement->shouldReceive('execute')->zeroOrMoreTimes(); + $result = $connector->connect($config); + + $this->assertSame($result, $connection); + } + public function testPostgresConnectorReadsIsolationLevelFromConfig() { $dsn = 'pgsql:host=foo;dbname=\'bar\';port=111';