-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathDBDiffComprehensiveSQLiteTest.php
More file actions
148 lines (129 loc) · 4.8 KB
/
DBDiffComprehensiveSQLiteTest.php
File metadata and controls
148 lines (129 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php
require_once __DIR__ . '/AbstractComprehensiveTest.php';
/**
* SQLite implementation of the comprehensive test suite.
* All test methods live in AbstractComprehensiveTest.
*
* Skips automatically when pdo_sqlite is not loaded.
* No external service required; databases are temporary files in /tmp.
*
* Note: testSingleTableDiff is skipped because SQLite file paths contain
* slashes that break CLIGetter::parseInput()'s dot-notation parser.
*/
class DBDiffComprehensiveSQLiteTest extends AbstractComprehensiveTest
{
// ── Abstract method implementations ───────────────────────────────────
protected function connectAndBootstrap(): void
{
if (!extension_loaded('pdo_sqlite')) {
$this->markTestSkipped('pdo_sqlite extension not loaded — skipping SQLite comprehensive tests.');
}
// Paths MUST be dot-free (no extension) — parseInput() splits on '.'
// so 'server1./tmp/file.db' would be mis-parsed as a 3-part table input.
$this->db1 = '/tmp/dbdiff_comp_src';
$this->db2 = '/tmp/dbdiff_comp_tgt';
// Start with fresh files
foreach ([$this->db1, $this->db2] as $file) {
if (file_exists($file)) {
unlink($file);
}
}
}
protected function getVersionSuffix(): string
{
return 'sqlite';
}
protected function loadFixture(string $fixtureName): void
{
foreach (['db1' => $this->db1, 'db2' => $this->db2] as $key => $filePath) {
$sqlFile = "tests/fixtures/{$fixtureName}/{$key}-sqlite.sql";
if (!file_exists($sqlFile)) {
$this->fail("SQLite fixture not found: $sqlFile");
}
$pdo = new PDO("sqlite:$filePath");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Strip SQL comments and split on semicolons for statement-by-statement execution
$raw = file_get_contents($sqlFile);
$statements = $this->parseSqlStatements($raw);
foreach ($statements as $stmt) {
if (trim($stmt) !== '') {
$pdo->exec($stmt);
}
}
}
}
protected function driverArgs(): array
{
return ['--driver=sqlite'];
}
protected function dbInputArg(): string
{
// SQLite uses separate server handles whose "db" is the file path.
// The server handle name is arbitrary; ParamsFactory ignores it for SQLite.
return "server1.{$this->db1}:server2.{$this->db2}";
}
protected function tableInputArg(string $table): ?string
{
// File paths with '/' cannot be used in dot-notation server.db.table format.
return null;
}
protected function getServerConfig(): array
{
// SQLite needs no server credentials; omit server1/server2 from config files.
return [];
}
protected function configDefaults(): array
{
return [
'driver' => 'sqlite',
'type' => 'all',
'include' => 'all',
'nocomments' => true,
];
}
protected function tearDownDatabases(): void
{
foreach ([$this->db1, $this->db2] as $file) {
if ($file && file_exists($file)) {
unlink($file);
}
}
}
// ── Private helpers ───────────────────────────────────────────────────
/**
* Strip line comments and split SQL text into individual statements.
* Matches the approach used in End2EndSQLiteTest.
*/
private function parseSqlStatements(string $sql): array
{
$lines = explode("\n", $sql);
$stripped = [];
foreach ($lines as $line) {
$clean = preg_replace('/--.*$/', '', $line);
if (trim($clean) !== '') {
$stripped[] = $clean;
}
}
// Reassemble, then split respecting BEGIN…END blocks
$body = implode("\n", $stripped);
$statements = [];
$current = '';
$depth = 0;
foreach (preg_split('/;/', $body) as $fragment) {
$current .= ($current !== '' ? ';' : '') . $fragment;
$depth += preg_match_all('/\bBEGIN\b/i', $fragment);
$depth -= preg_match_all('/\bEND\b/i', $fragment);
if ($depth <= 0) {
if (trim($current) !== '') {
$statements[] = $current;
}
$current = '';
$depth = 0;
}
}
if (trim($current) !== '') {
$statements[] = $current;
}
return $statements;
}
}