146 lines
3.6 KiB
Python
146 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
|
|
SCHEMA = """
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
user_key TEXT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL,
|
|
updated_at TIMESTAMP NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_resources (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
app_id TEXT NOT NULL DEFAULT 'default',
|
|
project_id TEXT NOT NULL DEFAULT 'default',
|
|
session_id TEXT NOT NULL,
|
|
original_filename TEXT,
|
|
mime_type TEXT,
|
|
content_type TEXT NOT NULL,
|
|
uri TEXT NOT NULL,
|
|
uri_public BOOLEAN NOT NULL DEFAULT FALSE,
|
|
sha256 TEXT,
|
|
size_bytes INTEGER,
|
|
title TEXT,
|
|
description TEXT,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
error_message TEXT,
|
|
created_at TIMESTAMP NOT NULL,
|
|
updated_at TIMESTAMP NOT NULL,
|
|
deleted_at TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_resources_user_scope
|
|
ON user_resources (user_id, app_id, project_id, status, deleted_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_resources_session_id
|
|
ON user_resources (session_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_resources_user_id
|
|
ON user_resources (user_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS memory_attachments (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
app_id TEXT NOT NULL DEFAULT 'default',
|
|
project_id TEXT NOT NULL DEFAULT 'default',
|
|
session_id TEXT NOT NULL,
|
|
resource_id TEXT,
|
|
content_type TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
internal_uri TEXT NOT NULL,
|
|
source TEXT NOT NULL,
|
|
sha256 TEXT,
|
|
created_at TIMESTAMP NOT NULL,
|
|
deleted_at TIMESTAMP
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_attachments_unique_uri
|
|
ON memory_attachments (user_id, session_id, internal_uri);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_attachments_user_session
|
|
ON memory_attachments (user_id, session_id, deleted_at);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_attachments_resource
|
|
ON memory_attachments (resource_id, deleted_at);
|
|
|
|
INSERT OR IGNORE INTO memory_attachments (
|
|
id,
|
|
user_id,
|
|
app_id,
|
|
project_id,
|
|
session_id,
|
|
resource_id,
|
|
content_type,
|
|
name,
|
|
internal_uri,
|
|
source,
|
|
sha256,
|
|
created_at,
|
|
deleted_at
|
|
)
|
|
SELECT
|
|
'a_resource_' || id,
|
|
user_id,
|
|
app_id,
|
|
project_id,
|
|
session_id,
|
|
id,
|
|
content_type,
|
|
COALESCE(original_filename, id),
|
|
uri,
|
|
'resource_upload',
|
|
sha256,
|
|
created_at,
|
|
deleted_at
|
|
FROM user_resources;
|
|
|
|
CREATE TABLE IF NOT EXISTS memory_tombstones (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
memory_id TEXT,
|
|
session_id TEXT,
|
|
reason TEXT,
|
|
created_at TIMESTAMP NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_tombstones_user_memory
|
|
ON memory_tombstones (user_id, memory_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_tombstones_user_session
|
|
ON memory_tombstones (user_id, session_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS memory_overrides (
|
|
id TEXT PRIMARY KEY,
|
|
user_id TEXT NOT NULL,
|
|
memory_id TEXT,
|
|
session_id TEXT,
|
|
override_text TEXT NOT NULL,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMP NOT NULL,
|
|
updated_at TIMESTAMP NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_memory_overrides_user_memory_active
|
|
ON memory_overrides (user_id, memory_id, is_active);
|
|
"""
|
|
|
|
|
|
def connect(db_path: Path) -> sqlite3.Connection:
|
|
conn = sqlite3.connect(db_path)
|
|
conn.row_factory = sqlite3.Row
|
|
conn.execute("PRAGMA journal_mode=WAL")
|
|
conn.execute("PRAGMA foreign_keys=ON")
|
|
conn.execute("PRAGMA busy_timeout=5000")
|
|
return conn
|
|
|
|
|
|
def init_db(db_path: Path) -> None:
|
|
db_path.parent.mkdir(parents=True, exist_ok=True)
|
|
with connect(db_path) as conn:
|
|
conn.executescript(SCHEMA)
|