Files
issue-core/issue_core/backends/local/schema.sql
tegwick 99ea1fbc45 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-17:
  - update .custodian-brief.md for issue-core
2026-05-17 05:06:10 +02:00

169 lines
5.6 KiB
SQL

-- Local Issue Tracking Database Schema
-- SQLite schema for local issue storage with full referential integrity
-- Enable foreign key constraints
PRAGMA foreign_keys = ON;
-- Issues table - core issue data
CREATE TABLE IF NOT EXISTS issues (
id TEXT PRIMARY KEY,
number INTEGER UNIQUE NOT NULL,
title TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
state TEXT NOT NULL CHECK (state IN ('open', 'closed', 'in_progress', 'blocked')),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
closed_at TIMESTAMP NULL,
milestone_id TEXT,
backend_id TEXT,
backend_type TEXT DEFAULT 'local',
sync_metadata TEXT, -- JSON for sync data
FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL
);
-- Create index for issue number lookups
CREATE INDEX IF NOT EXISTS idx_issues_number ON issues(number);
CREATE INDEX IF NOT EXISTS idx_issues_state ON issues(state);
CREATE INDEX IF NOT EXISTS idx_issues_updated_at ON issues(updated_at);
CREATE INDEX IF NOT EXISTS idx_issues_backend_id ON issues(backend_id);
-- Labels table
CREATE TABLE IF NOT EXISTS labels (
id TEXT PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
color TEXT,
description TEXT,
backend_id TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Create index for label name lookups
CREATE INDEX IF NOT EXISTS idx_labels_name ON labels(name);
-- Issue-Label many-to-many relationship
CREATE TABLE IF NOT EXISTS issue_labels (
issue_id TEXT NOT NULL,
label_id TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (issue_id, label_id),
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE
);
-- Users table
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
username TEXT UNIQUE NOT NULL,
display_name TEXT,
email TEXT,
avatar_url TEXT,
backend_id TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Create index for username lookups
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
-- Issue-User assignment many-to-many relationship
CREATE TABLE IF NOT EXISTS issue_assignees (
issue_id TEXT NOT NULL,
user_id TEXT NOT NULL,
assigned_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (issue_id, user_id),
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Milestones table
CREATE TABLE IF NOT EXISTS milestones (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
description TEXT,
state TEXT NOT NULL DEFAULT 'open' CHECK (state IN ('open', 'closed')),
due_date TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
backend_id TEXT
);
-- Create index for milestone title lookups
CREATE INDEX IF NOT EXISTS idx_milestones_title ON milestones(title);
-- Comments table
CREATE TABLE IF NOT EXISTS comments (
id TEXT PRIMARY KEY,
issue_id TEXT NOT NULL,
author_id TEXT NOT NULL,
body TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP,
backend_id TEXT,
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Create index for comment lookups
CREATE INDEX IF NOT EXISTS idx_comments_issue_id ON comments(issue_id);
CREATE INDEX IF NOT EXISTS idx_comments_created_at ON comments(created_at);
-- Sync tracking table
CREATE TABLE IF NOT EXISTS sync_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
backend_type TEXT NOT NULL,
sync_timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
success BOOLEAN NOT NULL,
issues_synced INTEGER DEFAULT 0,
errors_count INTEGER DEFAULT 0,
details TEXT -- JSON for sync details
);
-- Configuration table for backend settings
CREATE TABLE IF NOT EXISTS config (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- Triggers to automatically update updated_at timestamps
CREATE TRIGGER IF NOT EXISTS update_issues_timestamp
AFTER UPDATE ON issues
BEGIN
UPDATE issues SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
END;
CREATE TRIGGER IF NOT EXISTS update_milestones_timestamp
AFTER UPDATE ON milestones
BEGIN
UPDATE milestones SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
END;
-- Views for common queries
CREATE VIEW IF NOT EXISTS issue_summary AS
SELECT
i.id,
i.number,
i.title,
i.state,
i.created_at,
i.updated_at,
i.closed_at,
m.title as milestone_title,
COUNT(c.id) as comment_count,
GROUP_CONCAT(l.name) as labels,
GROUP_CONCAT(u.username) as assignees
FROM issues i
LEFT JOIN milestones m ON i.milestone_id = m.id
LEFT JOIN comments c ON i.id = c.issue_id
LEFT JOIN issue_labels il ON i.id = il.issue_id
LEFT JOIN labels l ON il.label_id = l.id
LEFT JOIN issue_assignees ia ON i.id = ia.issue_id
LEFT JOIN users u ON ia.user_id = u.id
GROUP BY i.id, i.number, i.title, i.state, i.created_at, i.updated_at, i.closed_at, m.title;
-- Full-text search setup (optional - disabled for now due to compatibility issues)
-- Can be enabled later by creating FTS5 virtual table manually
-- CREATE VIRTUAL TABLE IF NOT EXISTS issue_search USING fts5(
-- issue_id UNINDEXED,
-- title,
-- description
-- );