runMigrations applies idempotent data migrations after the schema exists.
(ctx context.Context, db *sql.DB)
| 418 | |
| 419 | // runMigrations applies idempotent data migrations after the schema exists. |
| 420 | func (s *Store) runMigrations(ctx context.Context, db *sql.DB) error { |
| 421 | if _, err := db.ExecContext(ctx, migrationMetaSQL); err != nil { |
| 422 | return fmt.Errorf("migration meta: %w", err) |
| 423 | } |
| 424 | migrations := []struct { |
| 425 | id string |
| 426 | run func(context.Context, *sql.DB) error |
| 427 | }{ |
| 428 | {id: "prompt_to_instruction", run: s.migratePromptToInstruction}, |
| 429 | } |
| 430 | for _, migration := range migrations { |
| 431 | var applied int |
| 432 | if err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM migration_meta WHERE id = ?`, migration.id).Scan(&applied); err != nil { |
| 433 | return fmt.Errorf("migration check %s: %w", migration.id, err) |
| 434 | } |
| 435 | if applied > 0 { |
| 436 | continue |
| 437 | } |
| 438 | if err := migration.run(ctx, db); err != nil { |
| 439 | return fmt.Errorf("migration %s: %w", migration.id, err) |
| 440 | } |
| 441 | if _, err := db.ExecContext(ctx, `INSERT INTO migration_meta(id, applied_at) VALUES(?, ?)`, migration.id, timeNow()); err != nil { |
| 442 | return fmt.Errorf("migration record %s: %w", migration.id, err) |
| 443 | } |
| 444 | } |
| 445 | return nil |
| 446 | } |
| 447 | |
| 448 | func (s *Store) migratePromptToInstruction(ctx context.Context, db *sql.DB) error { |
| 449 | for _, table := range []string{"metadata_items", "metadata_sources"} { |
no test coverage detected