diff --git a/src/Illuminate/Database/Connectors/PostgresConnector.php b/src/Illuminate/Database/Connectors/PostgresConnector.php index a3ca25e96323..113039f763c7 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,38 +85,40 @@ 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'])) { + $searchPath = $this->formatSearchPath($config['search_path']); - $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)) { + $searchPath = '"'.implode('", "', $searchPath).'"'; } - return '"'.$schema.'"'; + 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/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)]; diff --git a/tests/Database/DatabaseConnectorTest.php b/tests/Database/DatabaseConnectorTest.php index 5aacf2f1f64d..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']); @@ -117,6 +117,38 @@ public function testPostgresSearchPathArraySupported() $this->assertSame($result, $connection); } + public function testPostgresSearchPathCommaSeparatedValueSupported() + { + $dsn = 'pgsql:host=foo;dbname=bar'; + $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'])); + $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 testPostgresSearchPathVariablesSupported() + { + $dsn = 'pgsql:host=foo;dbname=bar'; + $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'])); + $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';