|
13 | 13 |
|
14 | 14 | import type { Database } from "bun:sqlite"; |
15 | 15 |
|
16 | | -export const CURRENT_SCHEMA_VERSION = 5; |
| 16 | +export const CURRENT_SCHEMA_VERSION = 6; |
17 | 17 |
|
18 | 18 | /** Environment variable to disable auto-repair */ |
19 | 19 | const NO_AUTO_REPAIR_ENV = "SENTRY_CLI_NO_AUTO_REPAIR"; |
@@ -223,6 +223,7 @@ export const TABLE_SCHEMAS: Record<string, TableSchema> = { |
223 | 223 | default: "(unixepoch() * 1000)", |
224 | 224 | }, |
225 | 225 | }, |
| 226 | + compositePrimaryKey: ["fingerprint", "idx"], |
226 | 227 | }, |
227 | 228 | }; |
228 | 229 |
|
@@ -397,47 +398,23 @@ export type RepairResult = { |
397 | 398 | failed: string[]; |
398 | 399 | }; |
399 | 400 |
|
400 | | -/** Tables that require custom DDL (not auto-generated from TABLE_SCHEMAS) */ |
401 | | -const CUSTOM_DDL_TABLES = new Set(["transaction_aliases"]); |
402 | | - |
403 | | -function repairTransactionAliasesTable( |
404 | | - db: Database, |
405 | | - result: RepairResult |
406 | | -): void { |
407 | | - if (tableExists(db, "transaction_aliases")) { |
408 | | - return; |
409 | | - } |
410 | | - try { |
411 | | - db.exec(TRANSACTION_ALIASES_DDL); |
412 | | - db.exec(TRANSACTION_ALIASES_INDEX); |
413 | | - result.fixed.push("Created table transaction_aliases"); |
414 | | - } catch (e) { |
415 | | - const msg = e instanceof Error ? e.message : String(e); |
416 | | - result.failed.push(`Failed to create table transaction_aliases: ${msg}`); |
417 | | - } |
418 | | -} |
419 | | - |
420 | 401 | function repairMissingTables(db: Database, result: RepairResult): void { |
421 | 402 | for (const [tableName, ddl] of Object.entries(EXPECTED_TABLES)) { |
422 | | - // Skip tables that need custom DDL |
423 | | - if (CUSTOM_DDL_TABLES.has(tableName)) { |
424 | | - continue; |
425 | | - } |
426 | | - |
427 | 403 | if (tableExists(db, tableName)) { |
428 | 404 | continue; |
429 | 405 | } |
430 | 406 | try { |
431 | 407 | db.exec(ddl); |
| 408 | + // Create associated indexes for tables that need them |
| 409 | + if (tableName === "transaction_aliases") { |
| 410 | + db.exec(TRANSACTION_ALIASES_INDEX); |
| 411 | + } |
432 | 412 | result.fixed.push(`Created table ${tableName}`); |
433 | 413 | } catch (e) { |
434 | 414 | const msg = e instanceof Error ? e.message : String(e); |
435 | 415 | result.failed.push(`Failed to create table ${tableName}: ${msg}`); |
436 | 416 | } |
437 | 417 | } |
438 | | - |
439 | | - // Handle tables with custom DDL |
440 | | - repairTransactionAliasesTable(db, result); |
441 | 418 | } |
442 | 419 |
|
443 | 420 | function repairMissingColumns(db: Database, result: RepairResult): void { |
@@ -592,38 +569,15 @@ export function tryRepairAndRetry<T>( |
592 | 569 | return { attempted: false }; |
593 | 570 | } |
594 | 571 |
|
595 | | -/** |
596 | | - * Custom DDL for transaction_aliases table with composite primary key. |
597 | | - * TABLE_SCHEMAS doesn't support composite primary keys, so we handle this specially. |
598 | | - */ |
599 | | -const TRANSACTION_ALIASES_DDL = ` |
600 | | - CREATE TABLE IF NOT EXISTS transaction_aliases ( |
601 | | - idx INTEGER NOT NULL, |
602 | | - alias TEXT NOT NULL, |
603 | | - transaction_name TEXT NOT NULL, |
604 | | - org_slug TEXT NOT NULL, |
605 | | - project_slug TEXT NOT NULL, |
606 | | - fingerprint TEXT NOT NULL, |
607 | | - cached_at INTEGER NOT NULL DEFAULT (unixepoch() * 1000), |
608 | | - PRIMARY KEY (fingerprint, idx) |
609 | | - ) |
610 | | -`; |
611 | | - |
| 572 | +/** Index for efficient alias lookups by alias string + fingerprint */ |
612 | 573 | const TRANSACTION_ALIASES_INDEX = ` |
613 | 574 | CREATE INDEX IF NOT EXISTS idx_txn_alias_lookup |
614 | 575 | ON transaction_aliases(alias, fingerprint) |
615 | 576 | `; |
616 | 577 |
|
617 | 578 | export function initSchema(db: Database): void { |
618 | | - // Generate combined DDL from all table schemas (except transaction_aliases which has custom DDL) |
619 | | - const ddlStatements = Object.entries(EXPECTED_TABLES) |
620 | | - .filter(([name]) => name !== "transaction_aliases") |
621 | | - .map(([, ddl]) => ddl) |
622 | | - .join(";\n\n"); |
| 579 | + const ddlStatements = Object.values(EXPECTED_TABLES).join(";\n\n"); |
623 | 580 | db.exec(ddlStatements); |
624 | | - |
625 | | - // Add transaction_aliases with composite primary key |
626 | | - db.exec(TRANSACTION_ALIASES_DDL); |
627 | 581 | db.exec(TRANSACTION_ALIASES_INDEX); |
628 | 582 |
|
629 | 583 | const versionRow = db |
@@ -682,13 +636,17 @@ export function runMigrations(db: Database): void { |
682 | 636 | db.exec(EXPECTED_TABLES.project_root_cache as string); |
683 | 637 | } |
684 | 638 |
|
685 | | - // Migration 4 -> 5: Add transaction_aliases and pagination_cursors tables |
| 639 | + // Migration 4 -> 5: Add pagination_cursors table |
686 | 640 | if (currentVersion < 5) { |
687 | | - db.exec(TRANSACTION_ALIASES_DDL); |
688 | | - db.exec(TRANSACTION_ALIASES_INDEX); |
689 | 641 | db.exec(EXPECTED_TABLES.pagination_cursors as string); |
690 | 642 | } |
691 | 643 |
|
| 644 | + // Migration 5 -> 6: Add transaction_aliases table |
| 645 | + if (currentVersion < 6) { |
| 646 | + db.exec(EXPECTED_TABLES.transaction_aliases as string); |
| 647 | + db.exec(TRANSACTION_ALIASES_INDEX); |
| 648 | + } |
| 649 | + |
692 | 650 | if (currentVersion < CURRENT_SCHEMA_VERSION) { |
693 | 651 | db.query("UPDATE schema_version SET version = ?").run( |
694 | 652 | CURRENT_SCHEMA_VERSION |
|
0 commit comments