feat: update template
This commit is contained in:
16
internal/db/query/access_logs.sql
Normal file
16
internal/db/query/access_logs.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- name: CreateAccessLog :exec
|
||||
INSERT INTO access_logs(request_id, user_id, ip, user_agent, request_method, request_path, referer, status_code,
|
||||
response_time_ms, started_at, message)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);
|
||||
|
||||
-- name: ListAccessLogs :many
|
||||
SELECT a.*, u.username
|
||||
FROM access_logs a
|
||||
LEFT JOIN sys_users u
|
||||
ON u.id = a.user_id
|
||||
ORDER BY a.started_at DESC, a.id
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountAccessLogs :one
|
||||
SELECT COUNT(*)
|
||||
FROM access_logs;
|
||||
10
internal/db/query/file_image_metadata.sql
Normal file
10
internal/db/query/file_image_metadata.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
-- name: CreateFileImageMetadata :exec
|
||||
INSERT INTO file_image_metadata(file_id, width, height, format)
|
||||
VALUES ($1, $2, $3, $4);
|
||||
|
||||
-- name: CopyFileImageMetadata :copyfrom
|
||||
INSERT INTO file_image_metadata(file_id, width, height, format)
|
||||
VALUES ($1, $2, $3, $4);
|
||||
|
||||
-- name: TruncateFileImageMetadata :exec
|
||||
TRUNCATE TABLE file_image_metadata;
|
||||
@@ -1,14 +1,29 @@
|
||||
-- name: CreateFile :one
|
||||
INSERT INTO files(file_name, file_path, original_name, folder_name, mime_type, file_size, file_url)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING id,file_url,file_name;
|
||||
RETURNING id,file_url,file_name,file_size;
|
||||
|
||||
-- name: ListFiles :many
|
||||
SELECT *
|
||||
FROM files
|
||||
ORDER BY id
|
||||
SELECT f.*,
|
||||
CASE
|
||||
WHEN m.file_id IS NULL THEN NULL
|
||||
ELSE jsonb_build_object(
|
||||
'width', m.width,
|
||||
'height', m.height,
|
||||
'format', m.format
|
||||
)
|
||||
END AS metadata
|
||||
FROM files f
|
||||
LEFT JOIN file_image_metadata m
|
||||
ON f.id = m.file_id
|
||||
ORDER BY f.id DESC
|
||||
LIMIT $1 OFFSET $2;
|
||||
|
||||
-- name: CountFiles :one
|
||||
SELECT COUNT(*)
|
||||
FROM files;
|
||||
|
||||
-- name: ListImageFiles :many
|
||||
SELECT id, file_path
|
||||
FROM files
|
||||
WHERE mime_type LIKE 'image/%';
|
||||
@@ -18,25 +18,25 @@ WITH paginated_posts AS (
|
||||
updated_at
|
||||
FROM posts
|
||||
ORDER BY sort DESC, published_at DESC, id DESC
|
||||
LIMIT $1 OFFSET $2
|
||||
)
|
||||
LIMIT $1 OFFSET $2)
|
||||
-- 第二步:用这极少量的记录去进行 JOIN
|
||||
SELECT p.*,
|
||||
f.file_url AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view, 0) AS view,
|
||||
f.file_url AS cover,
|
||||
f.file_size AS cover_size,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view_count, 0) AS view_count,
|
||||
COALESCE(
|
||||
jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'id', t.id,
|
||||
'name', t.name,
|
||||
'code', t.code
|
||||
)
|
||||
ORDER BY t.sort DESC, t.id
|
||||
) FILTER (WHERE t.id IS NOT NULL),
|
||||
'[]'::jsonb
|
||||
) AS tags
|
||||
jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'id', t.id,
|
||||
'name', t.name,
|
||||
'code', t.code
|
||||
)
|
||||
ORDER BY t.sort DESC, t.id
|
||||
) FILTER (WHERE t.id IS NOT NULL),
|
||||
'[]'::jsonb
|
||||
) AS tags
|
||||
FROM paginated_posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
@@ -55,9 +55,10 @@ GROUP BY p.id,
|
||||
p.created_at,
|
||||
p.updated_at,
|
||||
f.file_url,
|
||||
f.file_size,
|
||||
c.name,
|
||||
c.id,
|
||||
ps.view
|
||||
ps.view_count
|
||||
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC;
|
||||
|
||||
-- name: CountPosts :one
|
||||
@@ -66,13 +67,14 @@ FROM posts;
|
||||
|
||||
-- name: GetPostByID :one
|
||||
SELECT p.*,
|
||||
f.file_url AS cover,
|
||||
f.file_url AS cover,
|
||||
f.file_size AS cover_size,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(
|
||||
array_agg(pt.tag_id ORDER BY pt.tag_id) FILTER (WHERE pt.tag_id IS NOT NULL),
|
||||
ARRAY[]::integer[]
|
||||
) AS tags
|
||||
array_agg(pt.tag_id ORDER BY pt.tag_id) FILTER (WHERE pt.tag_id IS NOT NULL),
|
||||
ARRAY []::integer[]
|
||||
) AS tags
|
||||
FROM posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
@@ -81,6 +83,7 @@ FROM posts p
|
||||
WHERE p.id = $1
|
||||
GROUP BY p.id,
|
||||
f.file_url,
|
||||
f.file_size,
|
||||
c.name,
|
||||
c.id
|
||||
LIMIT 1;
|
||||
@@ -88,7 +91,7 @@ LIMIT 1;
|
||||
-- name: UpdatePost :execrows
|
||||
UPDATE posts
|
||||
SET title = coalesce(sqlc.narg('title'), title),
|
||||
cover_id = coalesce(sqlc.narg('cover_id'), cover_id),
|
||||
cover_id = CASE WHEN @update_cover_id::boolean THEN @cover_id ELSE cover_id END,
|
||||
slug = coalesce(sqlc.narg('slug'), slug),
|
||||
content = coalesce(sqlc.narg('content'), content),
|
||||
summary = coalesce(sqlc.narg('summary'), summary),
|
||||
@@ -105,12 +108,30 @@ WHERE id = $1;
|
||||
-- web -------------------------------------------------------
|
||||
|
||||
-- name: GetPublicPostBySlug :one
|
||||
SELECT p.*,
|
||||
f.file_url AS cover,
|
||||
COALESCE(ps.view, 0) AS view
|
||||
SELECT p.id,
|
||||
p.title,
|
||||
p.slug,
|
||||
p.content,
|
||||
p.summary,
|
||||
p.published_at,
|
||||
f.file_url AS cover,
|
||||
COALESCE(ps.view_count, 0) AS view_count,
|
||||
c.code AS category_code,
|
||||
c.name AS category_name,
|
||||
COALESCE(t.tags, '[]') AS tags
|
||||
FROM posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON pc.category_id = c.id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT jsonb_agg(
|
||||
jsonb_build_object('name', tag.name, 'code', tag.code)
|
||||
) AS tags
|
||||
FROM post_tag pt
|
||||
JOIN tags tag ON tag.id = pt.tag_id
|
||||
WHERE pt.post_id = p.id
|
||||
) t ON true
|
||||
WHERE p.slug = $1
|
||||
AND p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
@@ -132,21 +153,22 @@ WITH paginated_posts AS (
|
||||
ORDER BY sort DESC, published_at DESC, id DESC
|
||||
LIMIT $1 OFFSET $2)
|
||||
SELECT p.*,
|
||||
f.file_url AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
COALESCE(ps.view, 0) AS view,
|
||||
f.file_url AS cover,
|
||||
c.name AS category_name,
|
||||
c.id AS category_id,
|
||||
c.code AS category_code,
|
||||
COALESCE(ps.view_count, 0) AS view_count,
|
||||
COALESCE(
|
||||
jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'id', t.id,
|
||||
'name', t.name,
|
||||
'code', t.code
|
||||
)
|
||||
ORDER BY t.sort DESC, t.id
|
||||
) FILTER (WHERE t.id IS NOT NULL),
|
||||
'[]'::jsonb
|
||||
) AS tags
|
||||
jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'id', t.id,
|
||||
'name', t.name,
|
||||
'code', t.code
|
||||
)
|
||||
ORDER BY t.sort DESC, t.id
|
||||
) FILTER (WHERE t.id IS NOT NULL),
|
||||
'[]'::jsonb
|
||||
) AS tags
|
||||
FROM paginated_posts p
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
@@ -164,7 +186,8 @@ GROUP BY p.id,
|
||||
f.file_url,
|
||||
c.name,
|
||||
c.id,
|
||||
ps.view
|
||||
c.code,
|
||||
ps.view_count
|
||||
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC;
|
||||
|
||||
-- name: CountPublishedPosts :one
|
||||
@@ -174,35 +197,90 @@ WHERE status = 1
|
||||
AND published_at < NOW();
|
||||
|
||||
-- name: ListArchives :many
|
||||
SELECT
|
||||
p.id,
|
||||
p.slug,
|
||||
p.title,
|
||||
p.published_at,
|
||||
c."name" AS category_name
|
||||
FROM
|
||||
posts p
|
||||
LEFT JOIN post_category pc ON p.id = pc.post_id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
WHERE
|
||||
p.status = 1
|
||||
SELECT p.id,
|
||||
p.slug,
|
||||
p.title,
|
||||
p.published_at,
|
||||
c."name" AS category_name
|
||||
FROM posts p
|
||||
LEFT JOIN post_category pc ON p.id = pc.post_id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
WHERE p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
ORDER BY
|
||||
p.published_at DESC, p.id DESC;
|
||||
ORDER BY p.published_at DESC, p.id DESC;
|
||||
|
||||
-- name: ListCategoryStats :many
|
||||
SELECT
|
||||
c.id,
|
||||
c.name,
|
||||
COUNT(p.id) AS post_count
|
||||
FROM
|
||||
categories c
|
||||
LEFT JOIN post_category pc ON c.id = pc.category_id
|
||||
LEFT JOIN posts p ON p.id = pc.post_id
|
||||
AND p.status = 1
|
||||
SELECT c.id,
|
||||
c.name,
|
||||
c.code,
|
||||
COUNT(p.id) AS post_count
|
||||
FROM categories c
|
||||
LEFT JOIN post_category pc ON c.id = pc.category_id
|
||||
LEFT JOIN posts p ON p.id = pc.post_id
|
||||
AND p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
GROUP BY c.id,
|
||||
c.sort,
|
||||
c.name,
|
||||
c.code
|
||||
ORDER BY c.sort DESC, c.id;
|
||||
|
||||
-- name: ListPublishedPostsWithFilters :many
|
||||
SELECT p.id,
|
||||
p.title,
|
||||
p.slug,
|
||||
p.summary,
|
||||
p.sort,
|
||||
p.published_at,
|
||||
f.file_url AS cover,
|
||||
c."name" AS category_name,
|
||||
c.code AS category_code,
|
||||
COALESCE(t.tags, '[]') AS tags,
|
||||
COALESCE(ps."view_count", 0) AS view_count
|
||||
FROM posts p
|
||||
LEFT JOIN post_category pc ON pc.post_id = p.id
|
||||
LEFT JOIN categories c ON c.id = pc.category_id
|
||||
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
||||
LEFT JOIN files f ON f.id = p.cover_id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT jsonb_agg(
|
||||
jsonb_build_object('name', tag.name, 'code', tag.code)
|
||||
) AS tags
|
||||
FROM post_tag pt
|
||||
JOIN tags tag ON tag.id = pt.tag_id
|
||||
WHERE pt.post_id = p.id
|
||||
) t ON true
|
||||
WHERE
|
||||
-- 只显示已发布的文章
|
||||
p.status = 1
|
||||
AND p.published_at < NOW()
|
||||
GROUP BY
|
||||
c.id,
|
||||
c.sort,
|
||||
c.name
|
||||
ORDER BY c.sort DESC, c.id;
|
||||
AND
|
||||
-- category code 过滤(NULL 或空字符串时不过滤)
|
||||
(
|
||||
COALESCE(sqlc.narg('category_code')::text, '') = ''
|
||||
OR EXISTS (SELECT 1
|
||||
FROM post_category pc2
|
||||
JOIN categories c2 ON c2.id = pc2.category_id
|
||||
WHERE pc2.post_id = p.id
|
||||
AND c2.code = sqlc.narg('category_code')::text)
|
||||
)
|
||||
AND
|
||||
-- tag code 过滤(NULL 或空字符串时不过滤)
|
||||
(
|
||||
COALESCE(sqlc.narg('tag_code')::text, '') = ''
|
||||
OR EXISTS (SELECT 1
|
||||
FROM post_tag pt2
|
||||
JOIN tags t2 ON t2.id = pt2.tag_id
|
||||
WHERE pt2.post_id = p.id
|
||||
AND t2.code = sqlc.narg('tag_code')::text)
|
||||
)
|
||||
ORDER BY p.sort DESC,
|
||||
p.published_at DESC,
|
||||
p.id DESC;
|
||||
|
||||
-- name: GetPostsForSitemap :many
|
||||
SELECT slug, created_at, updated_at
|
||||
FROM posts
|
||||
WHERE status = 1
|
||||
AND published_at < NOW()
|
||||
ORDER BY sort DESC, published_at DESC, id DESC;
|
||||
@@ -18,7 +18,7 @@ WITH visitor AS (
|
||||
)
|
||||
INSERT INTO post_stats (
|
||||
post_id,
|
||||
view
|
||||
view_count
|
||||
)
|
||||
SELECT
|
||||
post_id,
|
||||
@@ -26,4 +26,4 @@ SELECT
|
||||
FROM visitor
|
||||
ON CONFLICT (post_id)
|
||||
DO UPDATE
|
||||
SET view = post_stats.view + 1;
|
||||
SET view_count = post_stats.view_count + 1;
|
||||
@@ -2,27 +2,13 @@
|
||||
INSERT INTO sys_users (account, username, password_hash, status, avatar_id)
|
||||
VALUES ($1, $2, $3, $4, $5);
|
||||
|
||||
-- name: GetActiveUserByID :one
|
||||
-- 场景:用户登录、获取个人信息、刷新 Token(严格校验 status = 1)
|
||||
SELECT id, account, username, status
|
||||
-- name: GetUserAuthState :one
|
||||
SELECT status,
|
||||
token_version
|
||||
FROM sys_users
|
||||
WHERE id = $1
|
||||
AND status = 1;
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: GetUserByID :one
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
u.avatar_id,
|
||||
u.status,
|
||||
f.file_url AS avatar_url,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
WHERE u.id = $1;
|
||||
|
||||
-- name: GetUserByAccount :one
|
||||
-- name: GetUser :one
|
||||
SELECT u.id,
|
||||
u.account,
|
||||
u.username,
|
||||
@@ -30,11 +16,13 @@ SELECT u.id,
|
||||
u.status,
|
||||
u.avatar_id,
|
||||
f.file_url AS avatar_url,
|
||||
u.token_version,
|
||||
u.created_at,
|
||||
u.updated_at
|
||||
FROM sys_users u
|
||||
LEFT JOIN files f ON u.avatar_id = f.id
|
||||
WHERE u.account = $1;
|
||||
WHERE u.id = $1
|
||||
OR u.account = $2;
|
||||
|
||||
-- name: ListUsers :many
|
||||
SELECT u.id,
|
||||
@@ -63,6 +51,15 @@ SET username = coalesce(sqlc.narg('username'), username),
|
||||
avatar_id = CASE WHEN @update_avatar_id::boolean THEN @avatar_id ELSE avatar_id END
|
||||
WHERE id = sqlc.arg('id');
|
||||
|
||||
-- name: IncrementUserTokenVersion :exec
|
||||
UPDATE sys_users
|
||||
SET token_version = token_version + 1
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: IncrementTokenVersionForAllUsers :exec
|
||||
UPDATE sys_users
|
||||
SET token_version = token_version + 1;
|
||||
|
||||
-- name: UpdateUserPassword :execrows
|
||||
UPDATE sys_users
|
||||
SET password_hash = $2
|
||||
|
||||
Reference in New Issue
Block a user