- 使用 pgx/sqlx 建立连接,从环境变量读取数据库密码 - 添加本地 PostgreSQL Compose 配置与初始迁移 - 补充 Goose 操作手册和连接串排错说明
127 lines
5.1 KiB
PL/PgSQL
127 lines
5.1 KiB
PL/PgSQL
-- 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;
|