From 20b91b9eb21f6e50a9ca3652e52a3c0343070f6e Mon Sep 17 00:00:00 2001 From: poppabear8883 Date: Sat, 16 Dec 2017 14:39:07 -0500 Subject: [PATCH 1/5] Fix terminology in respect to 'schema' vs 'search_path' --- .../Database/Connectors/PostgresConnector.php | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index a3ca25e96323..af56644ef3fa 100755 --- a/src/Illuminate/Database/Connectors/PostgresConnector.php +++ b/src/Illuminate/Database/Connectors/PostgresConnector.php @@ -40,7 +40,7 @@ public function connect(array $config) // database. Setting this DB timezone is an optional configuration item. $this->configureTimezone($connection, $config); - $this->configureSchema($connection, $config); + $this->configureSearchPath($connection, $config); // Postgres allows an application_name to be set by the user and this name is // used to when monitoring the application with pg_stat_activity. So we'll @@ -85,34 +85,34 @@ protected function configureTimezone($connection, array $config) } /** - * Set the schema on the connection. + * Set the search_path on the connection. * * @param \PDO $connection * @param array $config * @return void */ - protected function configureSchema($connection, $config) + protected function configureSearchPath($connection, $config) { - if (isset($config['schema'])) { - $schema = $this->formatSchema($config['schema']); + if (isset($config['search_path']) || isset($config['schema'])) { + $searchPath = $this->formatSearchPath($config['search_path'] ?? $config['schema']); - $connection->prepare("set search_path to {$schema}")->execute(); + $connection->prepare("set search_path to {$searchPath}")->execute(); } } /** - * Format the schema for the DSN. + * Format the search path for the DSN. * - * @param array|string $schema + * @param array|string $searchPath * @return string */ - protected function formatSchema($schema) + protected function formatSearchPath($searchPath) { - if (is_array($schema)) { - return '"'.implode('", "', $schema).'"'; + if (is_array($searchPath)) { + return '"'.implode('", "', $searchPath).'"'; } - return '"'.$schema.'"'; + return '"'.$searchPath.'"'; } /** From b8e1aca17477f190063000e62b258bc98967d664 Mon Sep 17 00:00:00 2001 From: poppabear8883 Date: Sat, 16 Dec 2017 15:10:38 -0500 Subject: [PATCH 2/5] Added support for Comma separated search paths with added test --- .../Database/Connectors/PostgresConnector.php | 3 ++- tests/Database/DatabaseConnectorTest.php | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index af56644ef3fa..d41c65febca7 100755 --- a/src/Illuminate/Database/Connectors/PostgresConnector.php +++ b/src/Illuminate/Database/Connectors/PostgresConnector.php @@ -112,7 +112,8 @@ protected function formatSearchPath($searchPath) return '"'.implode('", "', $searchPath).'"'; } - return '"'.$searchPath.'"'; + preg_match_all('/[a-zA-z0-9]{1,}/i', $searchPath, $matches); + return '"'.implode('", "', $matches[0]).'"'; } /** diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index 5aacf2f1f64d..e1d2fc4be224 100755 --- a/tests/Database/DatabaseConnectorTest.php +++ b/tests/Database/DatabaseConnectorTest.php @@ -117,6 +117,22 @@ public function testPostgresSearchPathArraySupported() $this->assertSame($result, $connection); } + public function testPostgresSearchPathCommaSeparatedValueSupported() + { + $dsn = 'pgsql:host=foo;dbname=bar'; + $config = ['host' => 'foo', 'database' => 'bar', 'schema' => 'public, user', 'charset' => 'utf8']; + $connector = $this->getMockBuilder('Illuminate\Database\Connectors\PostgresConnector')->setMethods(['createConnection', 'getOptions'])->getMock(); + $connection = m::mock('stdClass'); + $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->will($this->returnValue(['options'])); + $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->will($this->returnValue($connection)); + $connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($connection); + $connection->shouldReceive('prepare')->once()->with('set search_path to "public", "user"')->andReturn($connection); + $connection->shouldReceive('execute')->twice(); + $result = $connector->connect($config); + + $this->assertSame($result, $connection); + } + public function testPostgresApplicationNameIsSet() { $dsn = 'pgsql:host=foo;dbname=bar'; From 54c3fd30a9a8eb17ee39a38367e92bf38fd058da Mon Sep 17 00:00:00 2001 From: poppabear8883 Date: Sat, 16 Dec 2017 15:45:47 -0500 Subject: [PATCH 3/5] Added support for Postgres Variables in search paths with added test --- .../Database/Connectors/PostgresConnector.php | 2 +- tests/Database/DatabaseConnectorTest.php | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index d41c65febca7..1abd0e859ff3 100755 --- a/src/Illuminate/Database/Connectors/PostgresConnector.php +++ b/src/Illuminate/Database/Connectors/PostgresConnector.php @@ -112,7 +112,7 @@ protected function formatSearchPath($searchPath) return '"'.implode('", "', $searchPath).'"'; } - preg_match_all('/[a-zA-z0-9]{1,}/i', $searchPath, $matches); + preg_match_all('/[a-zA-z0-9$]{1,}/i', $searchPath, $matches); return '"'.implode('", "', $matches[0]).'"'; } diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index e1d2fc4be224..6ba8666ce11c 100755 --- a/tests/Database/DatabaseConnectorTest.php +++ b/tests/Database/DatabaseConnectorTest.php @@ -133,6 +133,22 @@ public function testPostgresSearchPathCommaSeparatedValueSupported() $this->assertSame($result, $connection); } + public function testPostgresSearchPathVariablesSupported() + { + $dsn = 'pgsql:host=foo;dbname=bar'; + $config = ['host' => 'foo', 'database' => 'bar', 'schema' => '$user, public, user', 'charset' => 'utf8']; + $connector = $this->getMockBuilder('Illuminate\Database\Connectors\PostgresConnector')->setMethods(['createConnection', 'getOptions'])->getMock(); + $connection = m::mock('stdClass'); + $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->will($this->returnValue(['options'])); + $connector->expects($this->once())->method('createConnection')->with($this->equalTo($dsn), $this->equalTo($config), $this->equalTo(['options']))->will($this->returnValue($connection)); + $connection->shouldReceive('prepare')->once()->with('set names \'utf8\'')->andReturn($connection); + $connection->shouldReceive('prepare')->once()->with('set search_path to "$user", "public", "user"')->andReturn($connection); + $connection->shouldReceive('execute')->twice(); + $result = $connector->connect($config); + + $this->assertSame($result, $connection); + } + public function testPostgresApplicationNameIsSet() { $dsn = 'pgsql:host=foo;dbname=bar'; From 354784f3e7ccf65a6d453c198701792629056404 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Wed, 2 Dec 2020 14:53:06 -0500 Subject: [PATCH 4/5] Fix schema quoting issue and update tests to verify behavior More specifically, fix issue whereby individual schema paths in an array were quoted twice. Also, update arguments in tests to verify schema name parsing with vs. without quotes, for both string and array notations. --- src/Illuminate/Database/Connectors/PostgresConnector.php | 9 +++++---- tests/Database/DatabaseConnectorTest.php | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index 1abd0e859ff3..113039f763c7 100755 --- a/src/Illuminate/Database/Connectors/PostgresConnector.php +++ b/src/Illuminate/Database/Connectors/PostgresConnector.php @@ -93,8 +93,8 @@ protected function configureTimezone($connection, array $config) */ protected function configureSearchPath($connection, $config) { - if (isset($config['search_path']) || isset($config['schema'])) { - $searchPath = $this->formatSearchPath($config['search_path'] ?? $config['schema']); + if (isset($config['search_path'])) { + $searchPath = $this->formatSearchPath($config['search_path']); $connection->prepare("set search_path to {$searchPath}")->execute(); } @@ -109,15 +109,16 @@ protected function configureSearchPath($connection, $config) protected function formatSearchPath($searchPath) { if (is_array($searchPath)) { - return '"'.implode('", "', $searchPath).'"'; + $searchPath = '"'.implode('", "', $searchPath).'"'; } preg_match_all('/[a-zA-z0-9$]{1,}/i', $searchPath, $matches); + return '"'.implode('", "', $matches[0]).'"'; } /** - * Set the schema on the connection. + * Set the application name on the connection. * * @param \PDO $connection * @param array $config diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index 6ba8666ce11c..6ffebc28ba50 100755 --- a/tests/Database/DatabaseConnectorTest.php +++ b/tests/Database/DatabaseConnectorTest.php @@ -88,7 +88,7 @@ public function testPostgresConnectCallsCreateConnectionWithProperArguments() public function testPostgresSearchPathIsSet() { $dsn = 'pgsql:host=foo;dbname=bar'; - $config = ['host' => 'foo', 'database' => 'bar', 'schema' => 'public', 'charset' => 'utf8']; + $config = ['host' => 'foo', 'database' => 'bar', 'search_path' => 'public', 'charset' => 'utf8']; $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']); @@ -104,7 +104,7 @@ public function testPostgresSearchPathIsSet() public function testPostgresSearchPathArraySupported() { $dsn = 'pgsql:host=foo;dbname=bar'; - $config = ['host' => 'foo', 'database' => 'bar', 'schema' => ['public', 'user'], 'charset' => 'utf8']; + $config = ['host' => 'foo', 'database' => 'bar', 'search_path' => ['public', '"user"'], 'charset' => 'utf8']; $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']); @@ -120,7 +120,7 @@ public function testPostgresSearchPathArraySupported() public function testPostgresSearchPathCommaSeparatedValueSupported() { $dsn = 'pgsql:host=foo;dbname=bar'; - $config = ['host' => 'foo', 'database' => 'bar', 'schema' => 'public, user', 'charset' => 'utf8']; + $config = ['host' => 'foo', 'database' => 'bar', 'search_path' => 'public, "user"', 'charset' => 'utf8']; $connector = $this->getMockBuilder('Illuminate\Database\Connectors\PostgresConnector')->setMethods(['createConnection', 'getOptions'])->getMock(); $connection = m::mock('stdClass'); $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->will($this->returnValue(['options'])); @@ -136,7 +136,7 @@ public function testPostgresSearchPathCommaSeparatedValueSupported() public function testPostgresSearchPathVariablesSupported() { $dsn = 'pgsql:host=foo;dbname=bar'; - $config = ['host' => 'foo', 'database' => 'bar', 'schema' => '$user, public, user', 'charset' => 'utf8']; + $config = ['host' => 'foo', 'database' => 'bar', 'search_path' => '"$user", public, user', 'charset' => 'utf8']; $connector = $this->getMockBuilder('Illuminate\Database\Connectors\PostgresConnector')->setMethods(['createConnection', 'getOptions'])->getMock(); $connection = m::mock('stdClass'); $connector->expects($this->once())->method('getOptions')->with($this->equalTo($config))->will($this->returnValue(['options'])); From 380650d461952fc5855aa8785a4e59c02b35d786 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Thu, 3 Dec 2020 22:16:56 -0500 Subject: [PATCH 5/5] Update method to use new "search_path" config key name --- src/Illuminate/Database/Schema/PostgresBuilder.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Database/Schema/PostgresBuilder.php b/src/Illuminate/Database/Schema/PostgresBuilder.php index 76673a719a41..9d10e9077ec9 100755 --- a/src/Illuminate/Database/Schema/PostgresBuilder.php +++ b/src/Illuminate/Database/Schema/PostgresBuilder.php @@ -164,12 +164,12 @@ protected function parseSchemaAndTable($table) { $table = explode('.', $table); - if (is_array($schema = $this->connection->getConfig('schema'))) { - if (in_array($table[0], $schema)) { + if (is_array($searchPath = $this->connection->getConfig('search_path'))) { + if (in_array($table[0], $searchPath)) { return [array_shift($table), implode('.', $table)]; } - $schema = head($schema); + $schema = head($searchPath); } return [$schema ?: 'public', implode('.', $table)];