feat(lyra): 添加 PostgreSQL 初始化示例
- 定义用户、分类和链接表,包含密码哈希字段 - 添加数据约束、索引及更新时间触发器
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
-- Polaris 导航站 PostgreSQL 新库初始化示例(非幂等,仅执行一次)。
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- updated_at 维护函数
|
||||
CREATE FUNCTION public.set_updated_at()
|
||||
RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW.updated_at := now();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- 用户表
|
||||
CREATE TABLE public.users (
|
||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
account text NOT NULL UNIQUE,
|
||||
password_hash text NOT NULL,
|
||||
display_name text NOT NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
CONSTRAINT users_account_not_empty CHECK (btrim(account) <> ''),
|
||||
CONSTRAINT users_display_name_not_empty CHECK (btrim(display_name) <> '')
|
||||
);
|
||||
|
||||
COMMENT ON TABLE public.users IS '后台管理用户表';
|
||||
COMMENT ON COLUMN public.users.id IS '用户 ID';
|
||||
COMMENT ON COLUMN public.users.account IS '登录账号,当前大小写敏感';
|
||||
COMMENT ON COLUMN public.users.password_hash IS '密码哈希';
|
||||
COMMENT ON COLUMN public.users.display_name IS '展示昵称';
|
||||
COMMENT ON COLUMN public.users.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN public.users.updated_at IS '更新时间,触发器自动刷新';
|
||||
|
||||
-- 分类表
|
||||
CREATE TABLE public.categories (
|
||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
slug text NOT NULL UNIQUE,
|
||||
title text NOT NULL,
|
||||
description text NOT NULL DEFAULT '',
|
||||
icon text NOT NULL,
|
||||
sort integer NOT NULL DEFAULT 0,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
CONSTRAINT categories_slug_format CHECK (slug ~ '^[a-z0-9]+(-[a-z0-9]+)*$'),
|
||||
CONSTRAINT categories_title_not_empty CHECK (btrim(title) <> '')
|
||||
);
|
||||
|
||||
COMMENT ON TABLE public.categories IS '链接分类表';
|
||||
COMMENT ON COLUMN public.categories.id IS '分类 ID,内部关联用';
|
||||
COMMENT ON COLUMN public.categories.slug IS '页面地址(路由)标识';
|
||||
COMMENT ON COLUMN public.categories.title IS '分类标题';
|
||||
COMMENT ON COLUMN public.categories.description IS '分类描述';
|
||||
COMMENT ON COLUMN public.categories.icon IS '分类图标标识';
|
||||
COMMENT ON COLUMN public.categories.sort IS '分类排序,越小越靠前';
|
||||
COMMENT ON COLUMN public.categories.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN public.categories.updated_at IS '更新时间,触发器自动刷新';
|
||||
|
||||
-- 链接表
|
||||
CREATE TABLE public.links (
|
||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
category_id bigint NOT NULL,
|
||||
title text NOT NULL,
|
||||
description text NOT NULL DEFAULT '',
|
||||
url text NOT NULL,
|
||||
icon text,
|
||||
keywords text[] NOT NULL DEFAULT ARRAY[]::text[],
|
||||
sort integer NOT NULL DEFAULT 0,
|
||||
pinned boolean NOT NULL DEFAULT false,
|
||||
pinned_sort integer,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
CONSTRAINT links_category_fk
|
||||
FOREIGN KEY (category_id) REFERENCES public.categories (id)
|
||||
ON DELETE RESTRICT,
|
||||
CONSTRAINT links_title_not_empty CHECK (btrim(title) <> ''),
|
||||
CONSTRAINT links_url_not_empty CHECK (btrim(url) <> ''),
|
||||
CONSTRAINT links_pinned_sort_consistent CHECK (pinned = (pinned_sort IS NOT NULL)),
|
||||
CONSTRAINT links_keywords_one_dimension
|
||||
CHECK (cardinality(keywords) = 0 OR array_ndims(keywords) = 1),
|
||||
CONSTRAINT links_keywords_no_null_elements
|
||||
CHECK (array_position(keywords, NULL) IS NULL)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE public.links IS '链接表,归属分类';
|
||||
COMMENT ON COLUMN public.links.id IS '链接 ID';
|
||||
COMMENT ON COLUMN public.links.category_id IS '所属分类 ID,删分类前需先处理链接';
|
||||
COMMENT ON COLUMN public.links.title IS '链接标题';
|
||||
COMMENT ON COLUMN public.links.description IS '链接描述';
|
||||
COMMENT ON COLUMN public.links.url IS '链接地址,应用层校验,去尾斜杠后全局唯一';
|
||||
COMMENT ON COLUMN public.links.icon IS '链接图标,可空,前端回退';
|
||||
COMMENT ON COLUMN public.links.keywords IS '搜索关键词数组,供本地搜索匹配';
|
||||
COMMENT ON COLUMN public.links.sort IS '分类内排序,越小越靠前';
|
||||
COMMENT ON COLUMN public.links.pinned IS '首页快捷入口(手动固定),非点击排行';
|
||||
COMMENT ON COLUMN public.links.pinned_sort IS '首页快捷入口顺序,越小越靠前';
|
||||
COMMENT ON COLUMN public.links.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN public.links.updated_at IS '更新时间,触发器自动刷新';
|
||||
|
||||
-- 索引
|
||||
CREATE INDEX categories_order_idx
|
||||
ON public.categories (sort, id);
|
||||
|
||||
CREATE INDEX links_category_order_idx
|
||||
ON public.links (category_id, sort, id);
|
||||
|
||||
CREATE INDEX links_pinned_order_idx
|
||||
ON public.links (pinned_sort, id)
|
||||
WHERE pinned;
|
||||
|
||||
CREATE UNIQUE INDEX links_normalized_url_unique
|
||||
ON public.links (rtrim(url, '/'));
|
||||
|
||||
-- 触发器
|
||||
CREATE TRIGGER users_set_updated_at
|
||||
BEFORE UPDATE ON public.users
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_updated_at();
|
||||
|
||||
CREATE TRIGGER categories_set_updated_at
|
||||
BEFORE UPDATE ON public.categories
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_updated_at();
|
||||
|
||||
CREATE TRIGGER links_set_updated_at
|
||||
BEFORE UPDATE ON public.links
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.set_updated_at();
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user