Simplify post listing queries.
CI / test (pull_request) Successful in 6m17s

Use named sqlc arguments, scope vote aggregation to selected roots, join viewer votes directly, and add the indexes and drift migration required by the resulting access paths.
This commit is contained in:
2026-08-27 00:22:07 -07:00
parent fc8f286c34
commit e918e5bd1d
5 changed files with 215 additions and 55 deletions
+39 -28
View File
@@ -2,7 +2,18 @@
INSERT INTO posts (
id, parent_id, author_id, title, body, city, post_date, hidden, created_at, updated_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
VALUES (
sqlc.arg(id),
sqlc.arg(parent_id),
sqlc.arg(author_id),
sqlc.arg(title),
sqlc.arg(body),
sqlc.arg(city),
sqlc.arg(post_date),
sqlc.arg(hidden),
sqlc.arg(created_at),
sqlc.arg(updated_at)
);
-- name: GetPost :one
SELECT
@@ -10,13 +21,13 @@ SELECT
p.title, p.body, p.city, p.post_date, p.hidden, p.created_at, p.updated_at
FROM posts p
JOIN users u ON u.id = p.author_id
WHERE p.id = $1;
WHERE p.id = sqlc.arg(id);
-- name: ListPostThread :many
WITH RECURSIVE thread AS (
SELECT p.*
FROM posts p
WHERE p.id = $1 AND p.parent_id IS NULL
WHERE p.id = sqlc.arg(root_id) AND p.parent_id IS NULL
UNION ALL
@@ -35,8 +46,10 @@ ORDER BY thread.created_at, thread.id;
-- name: UpdatePost :execrows
UPDATE posts
SET body = $2, updated_at = $3
WHERE id = $1;
SET
body = sqlc.arg(body),
updated_at = sqlc.arg(updated_at)
WHERE id = sqlc.arg(id);
-- name: ListRootPosts :many
WITH RECURSIVE roots AS (
@@ -47,8 +60,9 @@ WITH RECURSIVE roots AS (
AND p.hidden = 0
),
thread AS (
SELECT roots.id AS root_id, roots.id AS post_id, roots.author_id
SELECT roots.id AS root_id, child.id AS post_id, child.author_id
FROM roots
JOIN posts child ON child.parent_id = roots.id
UNION ALL
@@ -57,15 +71,16 @@ thread AS (
JOIN posts child ON child.parent_id = thread.post_id
),
answered AS (
SELECT thread.root_id, bool_or(u.role = 'admin' AND thread.post_id <> thread.root_id) AS answered
SELECT DISTINCT thread.root_id
FROM thread
JOIN users u ON u.id = thread.author_id
GROUP BY thread.root_id
WHERE u.role = 'admin'
),
scores AS (
SELECT post_id, COALESCE(SUM(value), 0)::bigint AS score
FROM post_votes
GROUP BY post_id
SELECT votes.post_id, SUM(votes.value)::bigint AS score
FROM roots
JOIN post_votes votes ON votes.post_id = roots.id
GROUP BY votes.post_id
)
SELECT
roots.id, roots.parent_id, roots.author_id,
@@ -73,17 +88,15 @@ SELECT
roots.title, roots.body, roots.city, roots.post_date,
roots.hidden, roots.created_at, roots.updated_at,
COALESCE(scores.score, 0)::bigint AS score,
COALESCE(answered.answered, false)::bool AS answered,
COALESCE((
SELECT post_votes.value
FROM post_votes
WHERE post_votes.user_id = sqlc.arg(viewer_id)
AND post_votes.post_id = roots.id
), 0)::bigint AS user_vote
(answered.root_id IS NOT NULL)::bool AS answered,
COALESCE(viewer_vote.value, 0)::bigint AS user_vote
FROM roots
JOIN users u ON u.id = roots.author_id
LEFT JOIN scores ON scores.post_id = roots.id
LEFT JOIN answered ON answered.root_id = roots.id
LEFT JOIN post_votes viewer_vote
ON viewer_vote.user_id = sqlc.arg(viewer_id)
AND viewer_vote.post_id = roots.id
ORDER BY score DESC, roots.created_at, roots.id
LIMIT sqlc.arg(row_limit);
@@ -91,22 +104,20 @@ LIMIT sqlc.arg(row_limit);
SELECT EXISTS(
SELECT 1
FROM posts
WHERE id = $1 AND parent_id IS NULL AND hidden = 0
WHERE id = sqlc.arg(id) AND parent_id IS NULL AND hidden = 0
)::bool;
-- name: DeletePostVote :exec
DELETE FROM post_votes
WHERE user_id = $1 AND post_id = $2;
WHERE user_id = sqlc.arg(user_id)
AND post_id = sqlc.arg(post_id);
-- name: UpsertPostVoteOnVisibleRoot :execrows
INSERT INTO post_votes (user_id, post_id, value)
SELECT $1, $2, $3
SELECT sqlc.arg(user_id), sqlc.arg(post_id), sqlc.arg(value)
FROM posts p
WHERE p.id = $2 AND p.parent_id IS NULL AND p.hidden = 0
WHERE p.id = sqlc.arg(post_id)
AND p.parent_id IS NULL
AND p.hidden = 0
ON CONFLICT (user_id, post_id) DO UPDATE
SET value = excluded.value
WHERE EXISTS (
SELECT 1
FROM posts p2
WHERE p2.id = excluded.post_id AND p2.parent_id IS NULL AND p2.hidden = 0
);
SET value = excluded.value;