2020-12-08 17:07:49 -05:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Illuminate\Tests\Database;
|
|
|
|
|
|
|
|
|
|
use Illuminate\Database\Connection;
|
|
|
|
|
use Illuminate\Database\Query\Processors\PostgresProcessor;
|
|
|
|
|
use Illuminate\Database\Schema\Grammars\PostgresGrammar;
|
|
|
|
|
use Illuminate\Database\Schema\PostgresBuilder;
|
|
|
|
|
use Mockery as m;
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
class DatabasePostgresBuilderTest extends TestCase
|
|
|
|
|
{
|
2021-01-13 15:20:19 +01:00
|
|
|
public function testCreateDatabase()
|
|
|
|
|
{
|
|
|
|
|
$connection = m::mock(Connection::class);
|
2025-02-12 20:00:57 +03:30
|
|
|
$grammar = new PostgresGrammar($connection);
|
|
|
|
|
|
2021-01-13 15:20:19 +01:00
|
|
|
$connection->shouldReceive('getConfig')->once()->with('charset')->andReturn('utf8');
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
|
|
|
|
$connection->shouldReceive('statement')->once()->with(
|
|
|
|
|
'create database "my_temporary_database" encoding "utf8"'
|
|
|
|
|
)->andReturn(true);
|
|
|
|
|
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
$builder->createDatabase('my_temporary_database');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDropDatabaseIfExists()
|
|
|
|
|
{
|
|
|
|
|
$connection = m::mock(Connection::class);
|
2025-02-12 20:00:57 +03:30
|
|
|
$grammar = new PostgresGrammar($connection);
|
|
|
|
|
|
2021-01-13 15:20:19 +01:00
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
|
|
|
|
$connection->shouldReceive('statement')->once()->with(
|
|
|
|
|
'drop database if exists "my_database_a"'
|
|
|
|
|
)->andReturn(true);
|
|
|
|
|
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->dropDatabaseIfExists('my_database_a');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testHasTableWhenSchemaUnqualifiedAndSearchPathMissing()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn(null);
|
2022-02-24 10:00:19 -05:00
|
|
|
$connection->shouldReceive('getConfig')->with('schema')->andReturn(null);
|
2020-12-08 17:07:49 -05:00
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2024-10-03 21:18:01 +03:30
|
|
|
$grammar->shouldReceive('compileTableExists')->andReturn('sql');
|
|
|
|
|
$connection->shouldReceive('scalar')->with('sql')->andReturn(1);
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->assertTrue($builder->hasTable('foo'));
|
|
|
|
|
$this->assertTrue($builder->hasTable('public.foo'));
|
2020-12-08 17:07:49 -05:00
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testHasTableWhenSchemaUnqualifiedAndSearchPathFilled()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('myapp,public');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2024-10-03 21:18:01 +03:30
|
|
|
$grammar->shouldReceive('compileTableExists')->andReturn('sql');
|
|
|
|
|
$connection->shouldReceive('scalar')->with('sql')->andReturn(1);
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->assertTrue($builder->hasTable('foo'));
|
|
|
|
|
$this->assertTrue($builder->hasTable('myapp.foo'));
|
2020-12-08 17:07:49 -05:00
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testHasTableWhenSchemaUnqualifiedAndSearchPathFallbackFilled()
|
|
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn(null);
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('schema')->andReturn(['myapp', 'public']);
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2024-10-03 21:18:01 +03:30
|
|
|
$grammar->shouldReceive('compileTableExists')->andReturn('sql');
|
|
|
|
|
$connection->shouldReceive('scalar')->with('sql')->andReturn(1);
|
2022-02-24 10:00:19 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->assertTrue($builder->hasTable('foo'));
|
|
|
|
|
$this->assertTrue($builder->hasTable('myapp.foo'));
|
2022-02-24 10:00:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testHasTableWhenSchemaUnqualifiedAndSearchPathIsUserVariable()
|
2020-12-11 09:16:03 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('username')->andReturn('foouser');
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('$user');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2024-10-03 21:18:01 +03:30
|
|
|
$grammar->shouldReceive('compileTableExists')->andReturn('sql');
|
|
|
|
|
$connection->shouldReceive('scalar')->with('sql')->andReturn(1);
|
2020-12-11 09:16:03 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->assertTrue($builder->hasTable('foo'));
|
|
|
|
|
$this->assertTrue($builder->hasTable('foouser.foo'));
|
2020-12-11 09:16:03 -05:00
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testHasTableWhenSchemaQualifiedAndSearchPathMismatches()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('public');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2024-10-03 21:18:01 +03:30
|
|
|
$grammar->shouldReceive('compileTableExists')->andReturn('sql');
|
|
|
|
|
$connection->shouldReceive('scalar')->with('sql')->andReturn(1);
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->assertTrue($builder->hasTable('myapp.foo'));
|
2020-12-08 17:07:49 -05:00
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testHasTableWhenDatabaseAndSchemaQualifiedAndSearchPathMismatches()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->expectException(\InvalidArgumentException::class);
|
|
|
|
|
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->hasTable('mydatabase.myapp.foo');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testGetColumnListingWhenSchemaUnqualifiedAndSearchPathMissing()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn(null);
|
2022-02-24 10:00:19 -05:00
|
|
|
$connection->shouldReceive('getConfig')->with('schema')->andReturn(null);
|
2020-12-08 17:07:49 -05:00
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2025-01-23 02:37:00 +03:30
|
|
|
$grammar->shouldReceive('compileColumns')->with(null, 'foo')->andReturn('sql');
|
2023-12-13 21:59:01 +03:30
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'some_column']]);
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
|
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
2023-10-26 21:50:57 +03:30
|
|
|
$processor->shouldReceive('processColumns')->andReturn([['name' => 'some_column']]);
|
2020-12-08 17:07:49 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->getColumnListing('foo');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testGetColumnListingWhenSchemaUnqualifiedAndSearchPathFilled()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('myapp,public');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2025-01-23 02:37:00 +03:30
|
|
|
$grammar->shouldReceive('compileColumns')->with(null, 'foo')->andReturn('sql');
|
2023-12-13 21:59:01 +03:30
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'some_column']]);
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
|
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
2023-10-26 21:50:57 +03:30
|
|
|
$processor->shouldReceive('processColumns')->andReturn([['name' => 'some_column']]);
|
2020-12-08 17:07:49 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->getColumnListing('foo');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testGetColumnListingWhenSchemaUnqualifiedAndSearchPathIsUserVariable()
|
2020-12-11 09:16:03 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('username')->andReturn('foouser');
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('$user');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2025-01-23 02:37:00 +03:30
|
|
|
$grammar->shouldReceive('compileColumns')->with(null, 'foo')->andReturn('sql');
|
2023-12-13 21:59:01 +03:30
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'some_column']]);
|
2020-12-11 09:16:03 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
|
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
2023-10-26 21:50:57 +03:30
|
|
|
$processor->shouldReceive('processColumns')->andReturn([['name' => 'some_column']]);
|
2020-12-11 09:16:03 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->getColumnListing('foo');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testGetColumnListingWhenSchemaQualifiedAndSearchPathMismatches()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('public');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2023-12-13 21:59:01 +03:30
|
|
|
$grammar->shouldReceive('compileColumns')->with('myapp', 'foo')->andReturn('sql');
|
|
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'some_column']]);
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection->shouldReceive('getTablePrefix');
|
|
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
|
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
2023-10-26 21:50:57 +03:30
|
|
|
$processor->shouldReceive('processColumns')->andReturn([['name' => 'some_column']]);
|
2020-12-08 17:07:49 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->getColumnListing('myapp.foo');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testGetColumnWhenDatabaseAndSchemaQualifiedAndSearchPathMismatches()
|
2020-12-08 17:07:49 -05:00
|
|
|
{
|
2023-12-13 21:59:01 +03:30
|
|
|
$this->expectException(\InvalidArgumentException::class);
|
|
|
|
|
|
2020-12-08 17:07:49 -05:00
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('public');
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
|
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
|
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->getColumnListing('mydatabase.myapp.foo');
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testDropAllTablesWhenSearchPathIsString()
|
2020-12-12 22:19:37 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('public');
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('dont_drop')->andReturn(['foo']);
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
2023-11-27 19:47:31 +03:30
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
2020-12-12 22:19:37 -05:00
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2023-11-27 19:47:31 +03:30
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
|
|
|
|
$grammar->shouldReceive('compileTables')->andReturn('sql');
|
2025-01-23 02:37:00 +03:30
|
|
|
$processor->shouldReceive('processTables')->once()->andReturn([['name' => 'users', 'schema' => 'public', 'schema_qualified_name' => 'public.users']]);
|
|
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'users', 'schema' => 'public', 'schema_qualified_name' => 'public.users']]);
|
2023-11-27 19:47:31 +03:30
|
|
|
$grammar->shouldReceive('compileDropAllTables')->with(['public.users'])->andReturn('drop table "public"."users" cascade');
|
2022-03-28 10:15:39 -04:00
|
|
|
$connection->shouldReceive('statement')->with('drop table "public"."users" cascade');
|
2020-12-12 22:19:37 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->dropAllTables();
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-24 10:00:19 -05:00
|
|
|
public function testDropAllTablesWhenSearchPathIsStringOfMany()
|
|
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('username')->andReturn('foouser');
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn('"$user", public, foo_bar-Baz.Áüõß');
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('dont_drop')->andReturn(['foo']);
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
2023-11-27 19:47:31 +03:30
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
2022-02-24 10:00:19 -05:00
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2023-11-27 19:47:31 +03:30
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
2025-01-23 02:37:00 +03:30
|
|
|
$processor->shouldReceive('processTables')->once()->andReturn([['name' => 'users', 'schema' => 'foouser', 'schema_qualified_name' => 'foouser.users']]);
|
2023-11-27 19:47:31 +03:30
|
|
|
$grammar->shouldReceive('compileTables')->andReturn('sql');
|
2025-01-23 02:37:00 +03:30
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'users', 'schema' => 'foouser', 'schema_qualified_name' => 'foouser.users']]);
|
2023-11-27 19:47:31 +03:30
|
|
|
$grammar->shouldReceive('compileDropAllTables')->with(['foouser.users'])->andReturn('drop table "foouser"."users" cascade');
|
2022-03-28 10:15:39 -04:00
|
|
|
$connection->shouldReceive('statement')->with('drop table "foouser"."users" cascade');
|
2022-02-24 10:00:19 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->dropAllTables();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDropAllTablesWhenSearchPathIsArrayOfMany()
|
2020-12-12 22:19:37 -05:00
|
|
|
{
|
|
|
|
|
$connection = $this->getConnection();
|
|
|
|
|
$connection->shouldReceive('getConfig')->with('username')->andReturn('foouser');
|
2022-02-24 10:00:19 -05:00
|
|
|
$connection->shouldReceive('getConfig')->with('search_path')->andReturn([
|
|
|
|
|
'$user',
|
|
|
|
|
'"dev"',
|
|
|
|
|
"'test'",
|
|
|
|
|
'spaced schema',
|
|
|
|
|
]);
|
2020-12-12 22:19:37 -05:00
|
|
|
$connection->shouldReceive('getConfig')->with('dont_drop')->andReturn(['foo']);
|
|
|
|
|
$grammar = m::mock(PostgresGrammar::class);
|
2023-11-27 19:47:31 +03:30
|
|
|
$processor = m::mock(PostgresProcessor::class);
|
2020-12-12 22:19:37 -05:00
|
|
|
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
|
2023-11-27 19:47:31 +03:30
|
|
|
$connection->shouldReceive('getPostProcessor')->andReturn($processor);
|
2025-01-23 02:37:00 +03:30
|
|
|
$processor->shouldReceive('processTables')->once()->andReturn([['name' => 'users', 'schema' => 'foouser', 'schema_qualified_name' => 'foouser.users']]);
|
2023-11-27 19:47:31 +03:30
|
|
|
$grammar->shouldReceive('compileTables')->andReturn('sql');
|
2025-01-23 02:37:00 +03:30
|
|
|
$connection->shouldReceive('selectFromWriteConnection')->with('sql')->andReturn([['name' => 'users', 'schema' => 'foouser', 'schema_qualified_name' => 'foouser.users']]);
|
2023-11-27 19:47:31 +03:30
|
|
|
$grammar->shouldReceive('compileDropAllTables')->with(['foouser.users'])->andReturn('drop table "foouser"."users" cascade');
|
2022-03-28 10:15:39 -04:00
|
|
|
$connection->shouldReceive('statement')->with('drop table "foouser"."users" cascade');
|
2020-12-12 22:19:37 -05:00
|
|
|
$builder = $this->getBuilder($connection);
|
|
|
|
|
|
|
|
|
|
$builder->dropAllTables();
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-08 17:07:49 -05:00
|
|
|
protected function getConnection()
|
|
|
|
|
{
|
|
|
|
|
return m::mock(Connection::class);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function getBuilder($connection)
|
|
|
|
|
{
|
|
|
|
|
return new PostgresBuilder($connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function getGrammar()
|
|
|
|
|
{
|
|
|
|
|
return new PostgresGrammar;
|
|
|
|
|
}
|
|
|
|
|
}
|