561 lines
14 KiB
Go
561 lines
14 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: post.sql
|
|
|
|
package sqlc
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
const countPosts = `-- name: CountPosts :one
|
|
SELECT COUNT(*)
|
|
FROM posts
|
|
`
|
|
|
|
func (q *Queries) CountPosts(ctx context.Context) (int64, error) {
|
|
row := q.db.QueryRow(ctx, countPosts)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const countPublishedPosts = `-- name: CountPublishedPosts :one
|
|
SELECT COUNT(*)
|
|
FROM posts
|
|
WHERE status = 1
|
|
AND published_at < NOW()
|
|
`
|
|
|
|
func (q *Queries) CountPublishedPosts(ctx context.Context) (int64, error) {
|
|
row := q.db.QueryRow(ctx, countPublishedPosts)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const createPost = `-- name: CreatePost :one
|
|
INSERT INTO posts(title, cover_id, slug, content, summary, status, sort, published_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
RETURNING id
|
|
`
|
|
|
|
type CreatePostParams struct {
|
|
Title string `json:"title"`
|
|
CoverID *int32 `json:"cover_id"`
|
|
Slug string `json:"slug"`
|
|
Content string `json:"content"`
|
|
Summary string `json:"summary"`
|
|
Status int16 `json:"status"`
|
|
Sort *int32 `json:"sort"`
|
|
PublishedAt time.Time `json:"published_at"`
|
|
}
|
|
|
|
func (q *Queries) CreatePost(ctx context.Context, arg CreatePostParams) (int32, error) {
|
|
row := q.db.QueryRow(ctx, createPost,
|
|
arg.Title,
|
|
arg.CoverID,
|
|
arg.Slug,
|
|
arg.Content,
|
|
arg.Summary,
|
|
arg.Status,
|
|
arg.Sort,
|
|
arg.PublishedAt,
|
|
)
|
|
var id int32
|
|
err := row.Scan(&id)
|
|
return id, err
|
|
}
|
|
|
|
const deletePost = `-- name: DeletePost :execrows
|
|
DELETE
|
|
FROM posts
|
|
WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) DeletePost(ctx context.Context, id int32) (int64, error) {
|
|
result, err := q.db.Exec(ctx, deletePost, id)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|
|
|
|
const getPostByID = `-- name: GetPostByID :one
|
|
SELECT p.id, p.title, p.cover_id, p.slug, p.content, p.summary, p.status, p.sort, p.published_at, p.created_at, p.updated_at,
|
|
f.file_url AS cover,
|
|
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
|
|
FROM posts p
|
|
LEFT JOIN files f ON f.id = p.cover_id
|
|
LEFT JOIN post_category pc ON pc.post_id = p.id
|
|
LEFT JOIN categories c ON c.id = pc.category_id
|
|
LEFT JOIN post_tag pt ON pt.post_id = p.id
|
|
WHERE p.id = $1
|
|
GROUP BY p.id,
|
|
f.file_url,
|
|
c.name,
|
|
c.id
|
|
LIMIT 1
|
|
`
|
|
|
|
type GetPostByIDRow struct {
|
|
ID int32 `json:"id"`
|
|
Title string `json:"title"`
|
|
CoverID *int32 `json:"cover_id"`
|
|
Slug string `json:"slug"`
|
|
Content string `json:"content"`
|
|
Summary string `json:"summary"`
|
|
Status int16 `json:"status"`
|
|
Sort *int32 `json:"sort"`
|
|
PublishedAt time.Time `json:"published_at"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt *time.Time `json:"updated_at"`
|
|
Cover *string `json:"cover"`
|
|
CategoryName *string `json:"category_name"`
|
|
CategoryID *int32 `json:"category_id"`
|
|
Tags interface{} `json:"tags"`
|
|
}
|
|
|
|
func (q *Queries) GetPostByID(ctx context.Context, id int32) (GetPostByIDRow, error) {
|
|
row := q.db.QueryRow(ctx, getPostByID, id)
|
|
var i GetPostByIDRow
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.CoverID,
|
|
&i.Slug,
|
|
&i.Content,
|
|
&i.Summary,
|
|
&i.Status,
|
|
&i.Sort,
|
|
&i.PublishedAt,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Cover,
|
|
&i.CategoryName,
|
|
&i.CategoryID,
|
|
&i.Tags,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getPublicPostBySlug = `-- name: GetPublicPostBySlug :one
|
|
|
|
SELECT p.id, p.title, p.cover_id, p.slug, p.content, p.summary, p.status, p.sort, p.published_at, p.created_at, p.updated_at,
|
|
f.file_url AS cover,
|
|
COALESCE(ps.view, 0) AS view
|
|
FROM posts p
|
|
LEFT JOIN files f ON f.id = p.cover_id
|
|
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
|
WHERE p.slug = $1
|
|
AND p.status = 1
|
|
AND p.published_at < NOW()
|
|
LIMIT 1
|
|
`
|
|
|
|
type GetPublicPostBySlugRow struct {
|
|
ID int32 `json:"id"`
|
|
Title string `json:"title"`
|
|
CoverID *int32 `json:"cover_id"`
|
|
Slug string `json:"slug"`
|
|
Content string `json:"content"`
|
|
Summary string `json:"summary"`
|
|
Status int16 `json:"status"`
|
|
Sort *int32 `json:"sort"`
|
|
PublishedAt time.Time `json:"published_at"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt *time.Time `json:"updated_at"`
|
|
Cover *string `json:"cover"`
|
|
View int32 `json:"view"`
|
|
}
|
|
|
|
// web -------------------------------------------------------
|
|
func (q *Queries) GetPublicPostBySlug(ctx context.Context, slug string) (GetPublicPostBySlugRow, error) {
|
|
row := q.db.QueryRow(ctx, getPublicPostBySlug, slug)
|
|
var i GetPublicPostBySlugRow
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.CoverID,
|
|
&i.Slug,
|
|
&i.Content,
|
|
&i.Summary,
|
|
&i.Status,
|
|
&i.Sort,
|
|
&i.PublishedAt,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Cover,
|
|
&i.View,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listArchives = `-- 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
|
|
AND p.published_at < NOW()
|
|
ORDER BY
|
|
p.published_at DESC, p.id DESC
|
|
`
|
|
|
|
type ListArchivesRow struct {
|
|
ID int32 `json:"id"`
|
|
Slug string `json:"slug"`
|
|
Title string `json:"title"`
|
|
PublishedAt time.Time `json:"published_at"`
|
|
CategoryName *string `json:"category_name"`
|
|
}
|
|
|
|
func (q *Queries) ListArchives(ctx context.Context) ([]ListArchivesRow, error) {
|
|
rows, err := q.db.Query(ctx, listArchives)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListArchivesRow{}
|
|
for rows.Next() {
|
|
var i ListArchivesRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Slug,
|
|
&i.Title,
|
|
&i.PublishedAt,
|
|
&i.CategoryName,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listCategoryStats = `-- 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
|
|
AND p.published_at < NOW()
|
|
GROUP BY
|
|
c.id,
|
|
c.sort,
|
|
c.name
|
|
ORDER BY c.sort DESC, c.id
|
|
`
|
|
|
|
type ListCategoryStatsRow struct {
|
|
ID int32 `json:"id"`
|
|
Name string `json:"name"`
|
|
PostCount int64 `json:"post_count"`
|
|
}
|
|
|
|
func (q *Queries) ListCategoryStats(ctx context.Context) ([]ListCategoryStatsRow, error) {
|
|
rows, err := q.db.Query(ctx, listCategoryStats)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListCategoryStatsRow{}
|
|
for rows.Next() {
|
|
var i ListCategoryStatsRow
|
|
if err := rows.Scan(&i.ID, &i.Name, &i.PostCount); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPosts = `-- name: ListPosts :many
|
|
WITH paginated_posts AS (
|
|
-- 第一步:先精准查出当前页需要的文章 ID
|
|
SELECT id,
|
|
title,
|
|
cover_id,
|
|
slug,
|
|
summary,
|
|
status,
|
|
sort,
|
|
published_at,
|
|
created_at,
|
|
updated_at
|
|
FROM posts
|
|
ORDER BY sort DESC, published_at DESC, id DESC
|
|
LIMIT $1 OFFSET $2
|
|
)
|
|
SELECT p.id, p.title, p.cover_id, p.slug, p.summary, p.status, p.sort, p.published_at, p.created_at, p.updated_at,
|
|
f.file_url AS cover,
|
|
c.name AS category_name,
|
|
c.id AS category_id,
|
|
COALESCE(ps.view, 0) AS view,
|
|
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
|
|
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
|
|
LEFT JOIN categories c ON c.id = pc.category_id
|
|
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
|
LEFT JOIN post_tag pt ON pt.post_id = p.id
|
|
LEFT JOIN tags t ON t.id = pt.tag_id
|
|
GROUP BY p.id,
|
|
p.title,
|
|
p.cover_id,
|
|
p.slug,
|
|
p.summary,
|
|
p.status,
|
|
p.sort,
|
|
p.published_at,
|
|
p.created_at,
|
|
p.updated_at,
|
|
f.file_url,
|
|
c.name,
|
|
c.id,
|
|
ps.view
|
|
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC
|
|
`
|
|
|
|
type ListPostsParams struct {
|
|
Limit int32 `json:"limit"`
|
|
Offset int32 `json:"offset"`
|
|
}
|
|
|
|
type ListPostsRow struct {
|
|
ID int32 `json:"id"`
|
|
Title string `json:"title"`
|
|
CoverID *int32 `json:"cover_id"`
|
|
Slug string `json:"slug"`
|
|
Summary string `json:"summary"`
|
|
Status int16 `json:"status"`
|
|
Sort *int32 `json:"sort"`
|
|
PublishedAt time.Time `json:"published_at"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
UpdatedAt *time.Time `json:"updated_at"`
|
|
Cover *string `json:"cover"`
|
|
CategoryName *string `json:"category_name"`
|
|
CategoryID *int32 `json:"category_id"`
|
|
View int32 `json:"view"`
|
|
Tags interface{} `json:"tags"`
|
|
}
|
|
|
|
// 第二步:用这极少量的记录去进行 JOIN
|
|
func (q *Queries) ListPosts(ctx context.Context, arg ListPostsParams) ([]ListPostsRow, error) {
|
|
rows, err := q.db.Query(ctx, listPosts, arg.Limit, arg.Offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListPostsRow{}
|
|
for rows.Next() {
|
|
var i ListPostsRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.CoverID,
|
|
&i.Slug,
|
|
&i.Summary,
|
|
&i.Status,
|
|
&i.Sort,
|
|
&i.PublishedAt,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Cover,
|
|
&i.CategoryName,
|
|
&i.CategoryID,
|
|
&i.View,
|
|
&i.Tags,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listPublishedPosts = `-- name: ListPublishedPosts :many
|
|
WITH paginated_posts AS (
|
|
-- 第一步:先精准查出当前页需要的文章 ID
|
|
SELECT id,
|
|
title,
|
|
cover_id,
|
|
slug,
|
|
summary,
|
|
sort,
|
|
published_at
|
|
FROM posts
|
|
WHERE status = 1
|
|
AND published_at < NOW()
|
|
ORDER BY sort DESC, published_at DESC, id DESC
|
|
LIMIT $1 OFFSET $2)
|
|
SELECT p.id, p.title, p.cover_id, p.slug, p.summary, p.sort, p.published_at,
|
|
f.file_url AS cover,
|
|
c.name AS category_name,
|
|
c.id AS category_id,
|
|
COALESCE(ps.view, 0) AS view,
|
|
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
|
|
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
|
|
LEFT JOIN categories c ON c.id = pc.category_id
|
|
LEFT JOIN post_stats ps ON ps.post_id = p.id
|
|
LEFT JOIN post_tag pt ON pt.post_id = p.id
|
|
LEFT JOIN tags t ON t.id = pt.tag_id
|
|
GROUP BY p.id,
|
|
p.title,
|
|
p.cover_id,
|
|
p.slug,
|
|
p.summary,
|
|
p.sort,
|
|
p.published_at,
|
|
f.file_url,
|
|
c.name,
|
|
c.id,
|
|
ps.view
|
|
ORDER BY p.sort DESC, p.published_at DESC, p.id DESC
|
|
`
|
|
|
|
type ListPublishedPostsParams struct {
|
|
Limit int32 `json:"limit"`
|
|
Offset int32 `json:"offset"`
|
|
}
|
|
|
|
type ListPublishedPostsRow struct {
|
|
ID int32 `json:"id"`
|
|
Title string `json:"title"`
|
|
CoverID *int32 `json:"cover_id"`
|
|
Slug string `json:"slug"`
|
|
Summary string `json:"summary"`
|
|
Sort *int32 `json:"sort"`
|
|
PublishedAt time.Time `json:"published_at"`
|
|
Cover *string `json:"cover"`
|
|
CategoryName *string `json:"category_name"`
|
|
CategoryID *int32 `json:"category_id"`
|
|
View int32 `json:"view"`
|
|
Tags interface{} `json:"tags"`
|
|
}
|
|
|
|
func (q *Queries) ListPublishedPosts(ctx context.Context, arg ListPublishedPostsParams) ([]ListPublishedPostsRow, error) {
|
|
rows, err := q.db.Query(ctx, listPublishedPosts, arg.Limit, arg.Offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListPublishedPostsRow{}
|
|
for rows.Next() {
|
|
var i ListPublishedPostsRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.CoverID,
|
|
&i.Slug,
|
|
&i.Summary,
|
|
&i.Sort,
|
|
&i.PublishedAt,
|
|
&i.Cover,
|
|
&i.CategoryName,
|
|
&i.CategoryID,
|
|
&i.View,
|
|
&i.Tags,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const updatePost = `-- name: UpdatePost :execrows
|
|
UPDATE posts
|
|
SET title = coalesce($1, title),
|
|
cover_id = coalesce($2, cover_id),
|
|
slug = coalesce($3, slug),
|
|
content = coalesce($4, content),
|
|
summary = coalesce($5, summary),
|
|
status = coalesce($6, status),
|
|
sort = coalesce($7, sort),
|
|
published_at = coalesce($8, published_at)
|
|
WHERE id = $9
|
|
`
|
|
|
|
type UpdatePostParams struct {
|
|
Title *string `json:"title"`
|
|
CoverID *int32 `json:"cover_id"`
|
|
Slug *string `json:"slug"`
|
|
Content *string `json:"content"`
|
|
Summary *string `json:"summary"`
|
|
Status *int16 `json:"status"`
|
|
Sort *int32 `json:"sort"`
|
|
PublishedAt *time.Time `json:"published_at"`
|
|
ID int32 `json:"id"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePost(ctx context.Context, arg UpdatePostParams) (int64, error) {
|
|
result, err := q.db.Exec(ctx, updatePost,
|
|
arg.Title,
|
|
arg.CoverID,
|
|
arg.Slug,
|
|
arg.Content,
|
|
arg.Summary,
|
|
arg.Status,
|
|
arg.Sort,
|
|
arg.PublishedAt,
|
|
arg.ID,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return result.RowsAffected(), nil
|
|
}
|