diff --git a/internal/storage/sqlite/schema.go b/internal/storage/sqlite/schema.go index 90eab4f5..74167ceb 100644 --- a/internal/storage/sqlite/schema.go +++ b/internal/storage/sqlite/schema.go @@ -72,6 +72,12 @@ CREATE TABLE IF NOT EXISTS config ( value TEXT NOT NULL ); +-- Metadata table (for storing internal state like import hashes) +CREATE TABLE IF NOT EXISTS metadata ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL +); + -- Dirty issues table (for incremental JSONL export) -- Tracks which issues have changed since last export CREATE TABLE IF NOT EXISTS dirty_issues ( diff --git a/internal/storage/sqlite/sqlite.go b/internal/storage/sqlite/sqlite.go index b35ea233..18d567ae 100644 --- a/internal/storage/sqlite/sqlite.go +++ b/internal/storage/sqlite/sqlite.go @@ -662,6 +662,25 @@ func (s *SQLiteStorage) GetConfig(ctx context.Context, key string) (string, erro return value, err } +// SetMetadata sets a metadata value (for internal state like import hashes) +func (s *SQLiteStorage) SetMetadata(ctx context.Context, key, value string) error { + _, err := s.db.ExecContext(ctx, ` + INSERT INTO metadata (key, value) VALUES (?, ?) + ON CONFLICT (key) DO UPDATE SET value = excluded.value + `, key, value) + return err +} + +// GetMetadata gets a metadata value (for internal state like import hashes) +func (s *SQLiteStorage) GetMetadata(ctx context.Context, key string) (string, error) { + var value string + err := s.db.QueryRowContext(ctx, `SELECT value FROM metadata WHERE key = ?`, key).Scan(&value) + if err == sql.ErrNoRows { + return "", nil + } + return value, err +} + // Close closes the database connection func (s *SQLiteStorage) Close() error { return s.db.Close() diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 1b3b4c96..54dc504c 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -52,6 +52,10 @@ type Storage interface { SetConfig(ctx context.Context, key, value string) error GetConfig(ctx context.Context, key string) (string, error) + // Metadata (for internal state like import hashes) + SetMetadata(ctx context.Context, key, value string) error + GetMetadata(ctx context.Context, key string) (string, error) + // Lifecycle Close() error }