Skip to content

Commit aa42814

Browse files
Schema dumps (#30)
* CockroachSchemaState - add dump/load cache schema Signed-off-by: Kamil Michalak <[email protected]> * wip * Adds fleshed out functionality for schema dumps * Fix PHP styling * Fix broken CI * CI fixes * Fix tests of older Laravel versions * Fix breaking tests * Fixes for CI * Fix PHP styling * Another CI fix * Fix PHPStan --------- Signed-off-by: Kamil Michalak <[email protected]> Co-authored-by: Kamil Michalak <[email protected]> Co-authored-by: peterfox <[email protected]>
1 parent f3383bb commit aa42814

15 files changed

+299
-43
lines changed

.github/workflows/coverage.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ jobs:
1717
- name: Run CockroachDB Service
1818
run: docker-compose up -d
1919
env:
20-
VERSION: v22.1.7
20+
VERSION: v23.1.13
2121

2222
- name: Setup PHP
2323
uses: shivammathur/setup-php@v2
2424
with:
25-
php-version: 8.2
25+
php-version: 8.3
2626
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql
2727
tools: composer:v2
2828
coverage: pcov

.github/workflows/phpstan.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
paths:
66
- '**.php'
77
- 'phpstan.neon.dist'
8+
pull_request:
9+
branches: [ main ]
810

911
jobs:
1012
phpstan:
@@ -16,7 +18,7 @@ jobs:
1618
- name: Setup PHP
1719
uses: shivammathur/setup-php@v2
1820
with:
19-
php-version: 8.2
21+
php-version: 8.3
2022
coverage: none
2123

2224
- name: Install composer dependencies

.github/workflows/run-tests.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ jobs:
1515
fail-fast: false
1616
matrix:
1717
os: [ ubuntu-latest ]
18-
php: [ 8.0, 8.1, 8.2 ]
19-
laravel: [ 10.*, 9.*, 8.* ]
18+
php: [ 8.1, 8.2, 8.3 ]
19+
laravel: [ 10.*, 9.* ]
2020
cockroachdb: [ v22.2.17, v23.1.13 ]
2121
dependencies: [ stable, lowest ]
2222
include:
2323
- laravel: 10.*
2424
testbench: ^8.0
2525
- laravel: 9.*
2626
testbench: ^7.0
27-
- laravel: 8.*
28-
testbench: ^6.24
2927
- php: 8.2
3028
dependencies: lowest
3129
dotenv: ^5.5.0
3230
carbon: ^2.62.1
33-
exclude:
34-
- laravel: 10.*
35-
php: 8.0
31+
- php: 8.3
32+
dependencies: lowest
33+
dotenv: ^5.5.0
34+
carbon: ^2.62.1
35+
3636

3737
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependencies }} - crdb.${{ matrix.cockroachdb }} ${{ matrix.os }}
3838

@@ -65,7 +65,7 @@ jobs:
6565
--no-interaction --no-update
6666
6767
- name: Require Minimum Packages for version
68-
if: ${{ matrix.php == '8.2' && matrix.dependencies == 'lowest' }}
68+
if: ${{ (matrix.php == '8.2' || matrix.php == '8.3') && matrix.dependencies == 'lowest' }}
6969
run: >
7070
composer require
7171
"vlucas/phpdotenv:${{ matrix.dotenv }}" "nesbot/carbon:${{ matrix.carbon }}"

README.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
[![Total Downloads](https://img.shields.io/packagist/dt/ylsideas/cockroachdb-laravel.svg?style=flat-square)](https://packagist.org/packages/ylsideas/cockroachdb-laravel)
77
[![codecov](https://codecov.io/github/ylsideas/cockroachdb-laravel/branch/main/graph/badge.svg?token=GCCY3KZHXQ)](https://codecov.io/github/ylsideas/cockroachdb-laravel)
88
[![Help Fund](https://img.shields.io/github/sponsors/peterfox?style=flat-square)](https://github.com/sponsors/peterfox)
9+
[![License](http://poser.pugx.org/ylsideas/cockroachdb-laravel/license)](https://packagist.org/packages/ylsideas/cockroachdb-laravel)
10+
[![PHP Version Require](http://poser.pugx.org/ylsideas/cockroachdb-laravel/require/php)](https://packagist.org/packages/ylsideas/cockroachdb-laravel)
911

1012
A driver/grammar for Laravel that works with CockroachDB. While CockroachDB is compatible with Postgresql, this support
1113
is not 1 to 1 meaning you may run into issues, this driver hopes to resolve those problems as much as possible.
1214

13-
Laravel 8 through to Laravel 10 is supported and tested against CockroachDB 2.5.
15+
Laravel 9 through to Laravel 10 is supported and tested against CockroachDB 22 & 23.
1416

1517
### Supporting Open Source
1618

@@ -84,6 +86,10 @@ Cockroach Serverless requires you to provide a cluster with connection.
8486
Laravel doesn't provide this out of the box, so, it's being implemented as an extra `cluster` parameter in the
8587
database config. Just pass the cluster identification from CockroachDB Serverless.
8688

89+
### Schema Dumps
90+
You may use schema dumps. I'm not 100% sure the functionality is correct in line with other drivers.
91+
Please raise an issue if it isn't working as expect for you.
92+
8793
```php
8894
'crdb' => [
8995
'driver' => 'crdb',
@@ -125,7 +131,7 @@ docker-composer up -d
125131
If you need to you may run the docker compose file with different cockroachdb
126132
versions
127133
```shell
128-
VERSION=v21.2.15 docker-compose up -d
134+
VERSION=v23.1.13 docker-compose up -d
129135
```
130136

131137
Then run the following PHP script to create a test database and user

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
}
1818
],
1919
"require": {
20-
"php": "^8.0",
20+
"php": "^8.1",
2121
"spatie/laravel-package-tools": "^1.9.2",
2222
"illuminate/contracts": "10.*|9.*|8.*"
2323
},

src/CockroachDbConnection.php

+32-22
Original file line numberDiff line numberDiff line change
@@ -3,72 +3,70 @@
33
namespace YlsIdeas\CockroachDb;
44

55
use Illuminate\Database\ConnectionInterface;
6-
use Illuminate\Database\Grammar;
6+
use Illuminate\Database\Grammar as BaseGrammar;
77
use Illuminate\Database\PDO\PostgresDriver;
88
use Illuminate\Database\PostgresConnection;
9-
use Illuminate\Database\Schema\PostgresSchemaState;
109
use Illuminate\Filesystem\Filesystem;
11-
use YlsIdeas\CockroachDb\Builder\CockroachDbBuilder;
12-
use YlsIdeas\CockroachDb\Processor\CockroachDbProcessor;
10+
use YlsIdeas\CockroachDb\Builder\CockroachDbBuilder as DbBuilder;
11+
use YlsIdeas\CockroachDb\Processor\CockroachDbProcessor as DbProcessor;
1312
use YlsIdeas\CockroachDb\Query\CockroachGrammar as QueryGrammar;
1413
use YlsIdeas\CockroachDb\Schema\CockroachGrammar as SchemaGrammar;
14+
use YlsIdeas\CockroachDb\Schema\CockroachSchemaState as SchemaState;
1515

1616
class CockroachDbConnection extends PostgresConnection implements ConnectionInterface
1717
{
1818
/**
1919
* Get the default query grammar instance.
2020
*
21-
* @return Grammar
21+
* @return BaseGrammar
2222
*/
23-
protected function getDefaultQueryGrammar()
23+
protected function getDefaultQueryGrammar(): BaseGrammar
2424
{
25-
return $this->withTablePrefix(new QueryGrammar());
25+
return $this->withTablePrefix($this->setConnection(new QueryGrammar()));
2626
}
2727

2828
/**
2929
* Get a schema builder instance for the connection.
3030
*
31-
* @return \Illuminate\Database\Schema\PostgresBuilder
31+
* @return DbBuilder
3232
*/
33-
public function getSchemaBuilder()
33+
public function getSchemaBuilder(): DbBuilder
3434
{
3535
if ($this->schemaGrammar === null) {
3636
$this->useDefaultSchemaGrammar();
3737
}
3838

39-
return new CockroachDbBuilder($this);
39+
return new DbBuilder($this);
4040
}
4141

4242
/**
4343
* Get the default schema grammar instance.
4444
*
45-
* @return Grammar
45+
* @return BaseGrammar
4646
*/
47-
protected function getDefaultSchemaGrammar(): Grammar
47+
protected function getDefaultSchemaGrammar(): BaseGrammar
4848
{
49-
return $this->withTablePrefix(new SchemaGrammar());
49+
return $this->withTablePrefix($this->setConnection(new SchemaGrammar()));
5050
}
5151

5252
/**
5353
* Get the schema state for the connection.
54-
*
55-
* @param \Illuminate\Filesystem\Filesystem|null $files
56-
* @param callable|null $processFactory
57-
* @return \Illuminate\Database\Schema\PostgresSchemaState
54+
* @return SchemaState
55+
* @phpstan-ignore-next-line base class has fixed type that we can't correct
5856
*/
59-
public function getSchemaState(Filesystem $files = null, callable $processFactory = null): PostgresSchemaState
57+
public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
6058
{
61-
return new PostgresSchemaState($this, $files, $processFactory);
59+
return new SchemaState($this, $files, $processFactory);
6260
}
6361

6462
/**
6563
* Get the default post processor instance.
6664
*
67-
* @return CockroachDbProcessor
65+
* @return DbProcessor
6866
*/
69-
protected function getDefaultPostProcessor(): CockroachDbProcessor
67+
protected function getDefaultPostProcessor(): DbProcessor
7068
{
71-
return new CockroachDbProcessor();
69+
return new DbProcessor();
7270
}
7371

7472
/**
@@ -80,4 +78,16 @@ protected function getDoctrineDriver()
8078
{
8179
return new PostgresDriver();
8280
}
81+
82+
/**
83+
* Required to set the connection. This isn't compatible with older Laravel versions
84+
*/
85+
protected function setConnection(BaseGrammar $grammar): BaseGrammar
86+
{
87+
if (method_exists($grammar, 'setConnection')) {
88+
return $grammar->setConnection($this);
89+
}
90+
91+
return $grammar;
92+
}
8393
}

src/Schema/CockroachSchemaState.php

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace YlsIdeas\CockroachDb\Schema;
4+
5+
use Illuminate\Contracts\Filesystem\FileNotFoundException;
6+
use Illuminate\Database\Connection;
7+
use Illuminate\Database\Schema\SchemaState;
8+
9+
class CockroachSchemaState extends SchemaState
10+
{
11+
/**
12+
* Dump the database's schema into a file.
13+
*
14+
* @param \Illuminate\Database\Connection $connection
15+
* @param string $path
16+
* @return void
17+
*/
18+
public function dump(Connection $connection, $path): void
19+
{
20+
$query = $connection->getPdo()->query('SHOW CREATE ALL TABLES');
21+
$query->execute();
22+
23+
$file = collect($query->fetchAll(\PDO::FETCH_COLUMN))->join(PHP_EOL);
24+
25+
$migrationRows = $connection
26+
->table($this->migrationTable)
27+
->get()
28+
->map(fn (\stdClass $row) => (array) $row);
29+
30+
$statements = $connection->pretend(function (Connection $connection) use ($migrationRows) {
31+
$connection->table($this->migrationTable)
32+
->insert($migrationRows->all());
33+
});
34+
35+
if ($statements !== []) {
36+
$file .= PHP_EOL . $statements[0]['query'];
37+
}
38+
39+
$this->files->put($path, $file);
40+
}
41+
42+
/**
43+
* Load the given schema file into the database.
44+
*
45+
* @param string $path
46+
* @return void
47+
* @throws FileNotFoundException
48+
*/
49+
public function load($path): void
50+
{
51+
$fileContents = $this->files->get($path);
52+
if ($fileContents === '') {
53+
throw new \RuntimeException(sprintf('file %s is empty', $path));
54+
}
55+
56+
$pdo = $this->connection->getPdo();
57+
$pdo->exec($fileContents);
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
namespace YlsIdeas\CockroachDb\Tests\Integration\Database;
4+
5+
use Illuminate\Support\Facades\File;
6+
7+
class DumpAndLoadSchemaTest extends DatabaseTestCase
8+
{
9+
protected function setUp(): void
10+
{
11+
parent::setUp();
12+
}
13+
14+
public function test_exporting_an_sql_dump()
15+
{
16+
File::ensureDirectoryExists(database_path('schema-test'));
17+
18+
if ($this->app['config']->get('database.default') !== 'testing') {
19+
$this->artisan('db:wipe', ['--drop-views' => true]);
20+
}
21+
22+
$options = [
23+
'--path' => realpath(__DIR__.'/stubs/schema-dump-migrations'),
24+
'--realpath' => true,
25+
];
26+
27+
$this->artisan('migrate', $options);
28+
29+
$this->beforeApplicationDestroyed(function () use ($options) {
30+
File::delete(database_path('schema-test/crdb-schema.sql'));
31+
32+
$this->artisan('migrate:rollback', $options);
33+
});
34+
35+
$this->artisan('schema:dump', [
36+
'--database' => 'crdb',
37+
'--path' => database_path('schema-test/crdb-schema.sql'),
38+
])
39+
->assertSuccessful();
40+
41+
$this->assertFileExists(database_path('schema-test/crdb-schema.sql'));
42+
}
43+
44+
public function test_importing_an_sql_dump()
45+
{
46+
// Make sure the schema direct exists first
47+
File::ensureDirectoryExists(database_path('schema-test'));
48+
File::copy(__DIR__ . '/stubs/schema-dump.sql', database_path('schema-test/crdb-schema.sql'));
49+
50+
if ($this->app['config']->get('database.default') !== 'testing') {
51+
$this->artisan('db:wipe', ['--drop-views' => true]);
52+
}
53+
54+
$options = [
55+
'--path' => realpath(__DIR__.'/stubs/schema-dump-migrations'),
56+
'--realpath' => true,
57+
];
58+
59+
$this->beforeApplicationDestroyed(function () use ($options) {
60+
File::delete(database_path('schema/crdb-schema.sql'));
61+
62+
$this->artisan('migrate:rollback', $options);
63+
});
64+
65+
$this->artisan('migrate', [
66+
...$options,
67+
...['--schema-path' => database_path('schema-test/crdb-schema.sql')],
68+
]);
69+
70+
$this->assertDatabaseCount('migrations', 2);
71+
72+
$this->assertDatabaseHas('migrations', [
73+
'migration' => '2014_10_12_000000_create_members_table',
74+
]);
75+
76+
$this->assertDatabaseHas('migrations', [
77+
'migration' => '2014_10_12_000000_create_users_table',
78+
]);
79+
80+
$this->assertDatabaseCount('users', 0);
81+
$this->assertDatabaseCount('members', 0);
82+
}
83+
}

tests/Integration/Database/MigrateWithRealpathTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ protected function setUp(): void
1717
}
1818

1919
$options = [
20-
'--path' => realpath(__DIR__.'/stubs/'),
20+
'--path' => realpath(__DIR__.'/stubs/simple-migrations'),
2121
'--realpath' => true,
2222
];
2323

tests/Integration/Database/MigratorEventsTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class MigratorEventsTest extends TestCase
1717
protected function migrateOptions()
1818
{
1919
return [
20-
'--path' => realpath(__DIR__.'/stubs/'),
20+
'--path' => realpath(__DIR__.'/stubs/simple-migrations'),
2121
'--realpath' => true,
2222
];
2323
}

0 commit comments

Comments
 (0)