174 lines
5.8 KiB
D
174 lines
5.8 KiB
D
auto _scheme = [
|
||
q{
|
||
-- ------------------------------------------------------------
|
||
-- Таблица snapshots
|
||
-- ------------------------------------------------------------
|
||
CREATE TABLE IF NOT EXISTS snapshots (
|
||
-- идентификатор снимка
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
-- путь к исходному файлу
|
||
file_path TEXT,
|
||
-- SHA-256 всего файла (BLOB(32))
|
||
file_sha256 BLOB NOT NULL CHECK (length(file_sha256) = 32),
|
||
-- метка/название снимка
|
||
label TEXT,
|
||
-- время создания (UTC)
|
||
created_utc TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||
-- длина исходного файла в байтах
|
||
source_length INTEGER NOT NULL,
|
||
-- FastCDC: минимальный размер чанка
|
||
algo_min INTEGER NOT NULL,
|
||
-- FastCDC: целевой размер чанка
|
||
algo_normal INTEGER NOT NULL,
|
||
-- FastCDC: максимальный размер чанка
|
||
algo_max INTEGER NOT NULL,
|
||
-- FastCDC: маска S
|
||
mask_s INTEGER NOT NULL,
|
||
-- FastCDC: маска L
|
||
mask_l INTEGER NOT NULL,
|
||
-- 0=pending, 1=ready
|
||
status INTEGER NOT NULL DEFAULT 0
|
||
CHECK (status IN (0,1))
|
||
)
|
||
},
|
||
q{
|
||
-- ------------------------------------------------------------
|
||
-- Таблица blobs
|
||
-- ------------------------------------------------------------
|
||
CREATE TABLE IF NOT EXISTS blobs (
|
||
-- SHA-256 исходного содержимого (BLOB(32))
|
||
sha256 BLOB PRIMARY KEY CHECK (length(sha256) = 32),
|
||
-- SHA-256 сжатого содержимого (BLOB(32)) или NULL
|
||
z_sha256 BLOB,
|
||
-- размер исходного содержимого, байт
|
||
size INTEGER NOT NULL,
|
||
-- размер сжатого содержимого, байт
|
||
z_size INTEGER NOT NULL,
|
||
-- байты (сжатые при zstd=1, иначе исходные)
|
||
content BLOB NOT NULL,
|
||
-- время создания записи (UTC)
|
||
created_utc TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||
-- время последней ссылки (UTC)
|
||
last_seen_utc TEXT NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||
-- число ссылок из snapshot_chunks
|
||
refcount INTEGER NOT NULL DEFAULT 0,
|
||
-- 0=нет сжатия, 1=zstd
|
||
zstd INTEGER NOT NULL DEFAULT 0
|
||
CHECK (zstd IN (0,1)),
|
||
CHECK (refcount >= 0),
|
||
CHECK (
|
||
(zstd = 1 AND length(content) = z_size) OR
|
||
(zstd = 0 AND length(content) = size)
|
||
),
|
||
CHECK (z_sha256 IS NULL OR length(z_sha256) = 32)
|
||
)
|
||
},
|
||
q{
|
||
-- ------------------------------------------------------------
|
||
-- Таблица snapshot_chunks
|
||
-- ------------------------------------------------------------
|
||
CREATE TABLE IF NOT EXISTS snapshot_chunks (
|
||
-- FK -> snapshots.id
|
||
snapshot_id INTEGER NOT NULL,
|
||
-- порядковый номер чанка в снимке
|
||
chunk_index INTEGER NOT NULL,
|
||
-- смещение чанка в исходном файле, байт
|
||
offset INTEGER,
|
||
-- FK -> blobs.sha256 (BLOB(32))
|
||
sha256 BLOB NOT NULL,
|
||
PRIMARY KEY (snapshot_id, chunk_index),
|
||
FOREIGN KEY (snapshot_id)
|
||
REFERENCES snapshots(id)
|
||
ON UPDATE CASCADE
|
||
ON DELETE CASCADE,
|
||
FOREIGN KEY (sha256)
|
||
REFERENCES blobs(sha256)
|
||
ON UPDATE RESTRICT
|
||
ON DELETE RESTRICT
|
||
)
|
||
},
|
||
q{
|
||
-- Индекс для запросов вида: WHERE file_path=? AND file_sha256=?
|
||
CREATE INDEX IF NOT EXISTS idx_snapshots_path_sha
|
||
ON snapshots(file_path, file_sha256)
|
||
},
|
||
q{
|
||
-- Индекс для обратного поиска использования blob по sha256
|
||
CREATE INDEX IF NOT EXISTS idx_snapshot_chunks_sha
|
||
ON snapshot_chunks(sha256)
|
||
},
|
||
// ------------------------------------------------------------
|
||
// Триггеры на поддержание refcount и статуса снимка
|
||
// ------------------------------------------------------------
|
||
q{
|
||
-- AFTER INSERT: увеличить refcount и обновить last_seen_utc
|
||
CREATE TRIGGER IF NOT EXISTS trg_snapshot_chunks_ai
|
||
AFTER INSERT ON snapshot_chunks
|
||
BEGIN
|
||
UPDATE blobs
|
||
SET refcount = refcount + 1,
|
||
last_seen_utc = CURRENT_TIMESTAMP
|
||
WHERE sha256 = NEW.sha256;
|
||
END
|
||
},
|
||
q{
|
||
-- AFTER DELETE: уменьшить refcount и удалить blob при refcount <= 0
|
||
CREATE TRIGGER IF NOT EXISTS trg_snapshot_chunks_ad
|
||
AFTER DELETE ON snapshot_chunks
|
||
BEGIN
|
||
UPDATE blobs
|
||
SET refcount = refcount - 1
|
||
WHERE sha256 = OLD.sha256;
|
||
|
||
DELETE FROM blobs
|
||
WHERE sha256 = OLD.sha256
|
||
AND refcount <= 0;
|
||
END
|
||
},
|
||
q{
|
||
-- AFTER UPDATE OF sha256: корректировка счётчиков при смене ссылки
|
||
CREATE TRIGGER IF NOT EXISTS trg_snapshot_chunks_au
|
||
AFTER UPDATE OF sha256 ON snapshot_chunks
|
||
FOR EACH ROW
|
||
WHEN NEW.sha256 <> OLD.sha256
|
||
BEGIN
|
||
UPDATE blobs
|
||
SET refcount = refcount - 1
|
||
WHERE sha256 = OLD.sha256;
|
||
|
||
DELETE FROM blobs
|
||
WHERE sha256 = OLD.sha256
|
||
AND refcount <= 0;
|
||
|
||
UPDATE blobs
|
||
SET refcount = refcount + 1,
|
||
last_seen_utc = CURRENT_TIMESTAMP
|
||
WHERE sha256 = NEW.sha256;
|
||
END
|
||
},
|
||
q{
|
||
-- AFTER INSERT: установить status=1 при совпадении суммы размеров с source_length
|
||
CREATE TRIGGER IF NOT EXISTS trg_snapshots_mark_ready
|
||
AFTER INSERT ON snapshot_chunks
|
||
BEGIN
|
||
UPDATE snapshots
|
||
SET status = 1
|
||
WHERE id = NEW.snapshot_id
|
||
AND (SELECT COALESCE(SUM(b.size),0)
|
||
FROM snapshot_chunks sc
|
||
JOIN blobs b ON b.sha256 = sc.sha256
|
||
WHERE sc.snapshot_id = NEW.snapshot_id)
|
||
= (SELECT source_length FROM snapshots WHERE id = NEW.snapshot_id);
|
||
END
|
||
},
|
||
q{
|
||
-- AFTER DELETE: установить status=0 для снимка, из которого удалён чанк
|
||
CREATE TRIGGER IF NOT EXISTS trg_snapshots_mark_pending
|
||
AFTER DELETE ON snapshot_chunks
|
||
BEGIN
|
||
UPDATE snapshots
|
||
SET status = 0
|
||
WHERE id = OLD.snapshot_id;
|
||
END
|
||
}
|
||
];
|