74 lines
3.1 KiB
MySQL
74 lines
3.1 KiB
MySQL
|
|
-- 161_manual_module.sql
|
||
|
|
-- Manual module: articles, steps and contextual relations
|
||
|
|
|
||
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS manual_articles (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
title VARCHAR(255) NOT NULL,
|
||
|
|
slug VARCHAR(255) NOT NULL UNIQUE,
|
||
|
|
content TEXT NOT NULL,
|
||
|
|
summary TEXT,
|
||
|
|
module VARCHAR(80) NOT NULL,
|
||
|
|
tags JSONB NOT NULL DEFAULT '[]'::jsonb,
|
||
|
|
difficulty VARCHAR(20) NOT NULL DEFAULT 'beginner' CHECK (difficulty IN ('beginner', 'advanced')),
|
||
|
|
use_count INTEGER NOT NULL DEFAULT 0,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
deleted_at TIMESTAMP WITH TIME ZONE DEFAULT NULL
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS manual_steps (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
manual_id UUID NOT NULL REFERENCES manual_articles(id) ON DELETE CASCADE,
|
||
|
|
step_number INTEGER NOT NULL CHECK (step_number > 0),
|
||
|
|
title VARCHAR(255) NOT NULL,
|
||
|
|
content TEXT NOT NULL,
|
||
|
|
image_url TEXT,
|
||
|
|
video_url TEXT,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
UNIQUE (manual_id, step_number)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS manual_relations (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
manual_id UUID NOT NULL REFERENCES manual_articles(id) ON DELETE CASCADE,
|
||
|
|
related_module VARCHAR(80),
|
||
|
|
related_tag VARCHAR(120),
|
||
|
|
related_sag_type VARCHAR(120),
|
||
|
|
related_manual_id UUID REFERENCES manual_articles(id) ON DELETE SET NULL,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_module ON manual_articles(module);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_difficulty ON manual_articles(difficulty);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_deleted_at ON manual_articles(deleted_at);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_articles_use_count ON manual_articles(use_count DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_steps_manual_id_step ON manual_steps(manual_id, step_number);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_manual_id ON manual_relations(manual_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_related_module ON manual_relations(related_module);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_related_tag ON manual_relations(related_tag);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_manual_relations_related_sag_type ON manual_relations(related_sag_type);
|
||
|
|
|
||
|
|
-- Keep article updated_at fresh on content changes.
|
||
|
|
CREATE OR REPLACE FUNCTION bump_manual_article_updated_at()
|
||
|
|
RETURNS TRIGGER AS $$
|
||
|
|
BEGIN
|
||
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
||
|
|
RETURN NEW;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
DROP TRIGGER IF EXISTS trg_manual_articles_updated_at ON manual_articles;
|
||
|
|
CREATE TRIGGER trg_manual_articles_updated_at
|
||
|
|
BEFORE UPDATE ON manual_articles
|
||
|
|
FOR EACH ROW
|
||
|
|
EXECUTE FUNCTION bump_manual_article_updated_at();
|
||
|
|
|
||
|
|
DROP TRIGGER IF EXISTS trg_manual_steps_updated_at ON manual_steps;
|
||
|
|
CREATE TRIGGER trg_manual_steps_updated_at
|
||
|
|
BEFORE UPDATE ON manual_steps
|
||
|
|
FOR EACH ROW
|
||
|
|
EXECUTE FUNCTION bump_manual_article_updated_at();
|