Skip to content

Commit b909331

Browse files
committed
feat(db): auto-transform drizzle-kit output for DSQL compatibility
check-dsql-compat.ts now auto-fixes: - statement-breakpoint → blank lines (runner splits on \n\n) - CREATE INDEX → CREATE INDEX ASYNC - Removes REFERENCES / FOREIGN KEY lines Still errors on unfixable patterns: ALTER COLUMN TYPE, DROP COLUMN, SERIAL.
1 parent bcaa396 commit b909331

2 files changed

Lines changed: 49 additions & 19 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ Schema changes:
6666
# 1. Edit schema
6767
# packages/db/src/schema.ts
6868

69-
# 2. Generate migration SQL + DSQL compatibility check
69+
# 2. Generate migration SQL (auto-transforms for DSQL compatibility)
7070
pnpm --filter @repo/db run generate
71+
# Auto-transforms: statement-breakpoint → blank lines, CREATE INDEX → ASYNC, FK removal
72+
# Errors on unfixable patterns: ALTER COLUMN TYPE, DROP COLUMN, SERIAL
7173

72-
# 3. Review and fix the generated SQL in packages/db/migrations/
74+
# 3. Review the generated SQL in packages/db/migrations/
7375
# - Add IF NOT EXISTS for idempotency
74-
# - Replace CREATE INDEX with CREATE INDEX ASYNC
75-
# - Replace --> statement-breakpoint with blank lines (runner splits on \n\n)
7676

7777
# 4. Apply to dev cluster
7878
pnpm --filter @repo/db run migrate
Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,66 @@
1-
// Validate migration SQL files for DSQL compatibility.
2-
// Run after drizzle-kit generate to catch incompatible DDL before commit.
1+
// Transform drizzle-kit generated SQL for DSQL compatibility, then validate.
2+
// Automatically fixes what can be fixed, errors on what cannot.
3+
//
4+
// Auto-transforms:
5+
// - "--> statement-breakpoint" → blank line (runner splits on \n\n)
6+
// - "CREATE INDEX" → "CREATE INDEX ASYNC"
7+
// - Removes REFERENCES / FOREIGN KEY clauses
8+
//
9+
// Errors (cannot auto-fix):
10+
// - ALTER COLUMN TYPE
11+
// - DROP COLUMN
12+
// - SERIAL types
313
import fs from 'node:fs';
414
import path from 'node:path';
515
import { fileURLToPath } from 'node:url';
616

717
const __dirname = path.dirname(fileURLToPath(import.meta.url));
818
const migrationsDir = path.join(__dirname, '..', 'migrations');
919

10-
const rules: { pattern: RegExp; message: string }[] = [
11-
{ pattern: /CREATE\s+INDEX\s+(?!.*ASYNC)/i, message: 'CREATE INDEX must use ASYNC keyword' },
12-
{ pattern: /REFERENCES\s+/i, message: 'FOREIGN KEY / REFERENCES not supported' },
13-
{ pattern: /FOREIGN\s+KEY/i, message: 'FOREIGN KEY not supported' },
14-
{ pattern: /ALTER\s+.*\s+TYPE\s+/i, message: 'ALTER COLUMN TYPE not supported' },
15-
{ pattern: /DROP\s+COLUMN/i, message: 'DROP COLUMN not supported' },
16-
{ pattern: /\bSERIAL\b/i, message: 'SERIAL types not supported (use UUID)' },
17-
];
18-
1920
const files = fs.readdirSync(migrationsDir).filter((f) => f.endsWith('.sql'));
21+
let transformed = 0;
2022
let errors = 0;
2123

2224
for (const file of files) {
23-
const content = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
24-
for (const { pattern, message } of rules) {
25-
if (pattern.test(content)) {
25+
const filePath = path.join(migrationsDir, file);
26+
const original = fs.readFileSync(filePath, 'utf8');
27+
let sql = original;
28+
29+
// Auto-transform: statement-breakpoint → blank line
30+
sql = sql.replace(/--> statement-breakpoint\n/g, '\n');
31+
32+
// Auto-transform: CREATE INDEX → CREATE INDEX ASYNC (skip if already ASYNC)
33+
sql = sql.replace(/CREATE\s+INDEX(?!\s+ASYNC)/gi, 'CREATE INDEX ASYNC');
34+
35+
// Auto-transform: remove lines with REFERENCES or FOREIGN KEY
36+
sql = sql
37+
.split('\n')
38+
.filter((line) => !/REFERENCES\s+/i.test(line) && !/FOREIGN\s+KEY/i.test(line))
39+
.join('\n');
40+
41+
if (sql !== original) {
42+
fs.writeFileSync(filePath, sql);
43+
console.log(`TRANSFORMED: ${file}`);
44+
transformed++;
45+
}
46+
47+
// Validate: errors that cannot be auto-fixed
48+
const unfixable: { pattern: RegExp; message: string }[] = [
49+
{ pattern: /ALTER\s+.*\s+TYPE\s+/i, message: 'ALTER COLUMN TYPE not supported' },
50+
{ pattern: /DROP\s+COLUMN/i, message: 'DROP COLUMN not supported' },
51+
{ pattern: /\bSERIAL\b/i, message: 'SERIAL types not supported (use UUID)' },
52+
];
53+
for (const { pattern, message } of unfixable) {
54+
if (pattern.test(sql)) {
2655
console.error(`ERROR: ${file}${message}`);
2756
errors++;
2857
}
2958
}
3059
}
3160

61+
if (transformed > 0) console.log(`\n${transformed} file(s) auto-transformed for DSQL compatibility.`);
3262
if (errors > 0) {
33-
console.error(`\n${errors} DSQL compatibility error(s). Fix the SQL before committing.`);
63+
console.error(`\n${errors} unfixable error(s). These require manual migration scripts.`);
3464
process.exit(1);
3565
}
3666
console.log('All migration files DSQL-compatible.');

0 commit comments

Comments
 (0)