-- name: CreateAttachment :one
WITH inserted AS (
INSERT INTO attachment (
id, workspace_id, issue_id, comment_id, chat_session_id, task_id, source_context_id,
uploader_type, uploader_id, filename, url, content_type, size_bytes
)
VALUES (
$1, $2, sqlc.narg(issue_id), sqlc.narg(comment_id), sqlc.narg(chat_session_id), sqlc.narg(task_id), sqlc.narg(source_context_id),
$3, $4, $5, $6, $7, $8
)
RETURNING *
), bumped_issue AS (
UPDATE issue
SET revision = revision + 1
WHERE id IN (SELECT issue_id FROM inserted WHERE issue_id IS NOT NULL)
RETURNING revision
), bumped_comment AS (
UPDATE comment
SET revision = revision + 1
WHERE id IN (SELECT comment_id FROM inserted WHERE comment_id IS NOT NULL)
RETURNING revision
)
SELECT inserted.*,
COALESCE((SELECT revision FROM bumped_issue), 0)::bigint AS issue_revision,
COALESCE((SELECT revision FROM bumped_comment), 0)::bigint AS comment_revision
FROM inserted;
-- name: ListAttachmentsByIssue :many
SELECT * FROM attachment
WHERE issue_id = $1 AND workspace_id = $2
ORDER BY created_at ASC;
-- name: ListAttachmentsByComment :many
SELECT * FROM attachment
WHERE comment_id = $1 AND workspace_id = $2
ORDER BY created_at ASC;
-- name: GetAttachment :one
SELECT * FROM attachment
WHERE id = $1 AND workspace_id = $2;
-- name: GetAttachmentByIDOnly :one
-- Used by the download endpoint, which derives workspace context from the
-- attachment row itself rather than from request headers/query params. The
-- caller still has to verify the requester is a member of the returned
-- workspace_id before serving the bytes — this query is access-neutral on
-- purpose so a self-contained URL like /api/attachments/{id}/download can
-- work as a native
/