Files
multica/server/pkg/db/generated/task_message.sql.go

306 lines
9.8 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: task_message.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createTaskMessage = `-- name: CreateTaskMessage :one
INSERT INTO task_message (id, task_id, seq, type, tool, content, input, output, output_truncated, call_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING id, task_id, seq, type, tool, content, input, output, created_at, output_truncated, call_id
`
type CreateTaskMessageParams struct {
ID pgtype.UUID `json:"id"`
TaskID pgtype.UUID `json:"task_id"`
Seq int32 `json:"seq"`
Type string `json:"type"`
Tool pgtype.Text `json:"tool"`
Content pgtype.Text `json:"content"`
Input []byte `json:"input"`
Output pgtype.Text `json:"output"`
OutputTruncated pgtype.Bool `json:"output_truncated"`
CallID pgtype.Text `json:"call_id"`
}
func (q *Queries) CreateTaskMessage(ctx context.Context, arg CreateTaskMessageParams) (TaskMessage, error) {
row := q.db.QueryRow(ctx, createTaskMessage,
arg.ID,
arg.TaskID,
arg.Seq,
arg.Type,
arg.Tool,
arg.Content,
arg.Input,
arg.Output,
arg.OutputTruncated,
arg.CallID,
)
var i TaskMessage
err := row.Scan(
&i.ID,
&i.TaskID,
&i.Seq,
&i.Type,
&i.Tool,
&i.Content,
&i.Input,
&i.Output,
&i.CreatedAt,
&i.OutputTruncated,
&i.CallID,
)
return i, err
}
const createTaskMessages = `-- name: CreateTaskMessages :many
WITH incoming AS (
-- Several single-argument unnest calls in one SELECT list expand in
-- lockstep (PostgreSQL 10+ set-returning-function semantics), which is the
-- same row-wise zip the multi-argument unnest(a, b, ...) form gives — but
-- sqlc's analyzer only knows the single-argument signature, so this is the
-- shape that survives code generation.
SELECT
unnest($1::uuid[]) AS id,
unnest($2::int4[]) AS seq,
unnest($3::text[]) AS type,
unnest($4::text[]) AS tool,
unnest($5::text[]) AS call_id,
unnest($6::text[]) AS content,
unnest($7::text[]) AS input,
unnest($8::text[]) AS output,
unnest($9::text[]) AS created_at,
unnest($10::text[]) AS output_truncated
), inserted AS (
INSERT INTO task_message (id, task_id, seq, type, tool, content, input, output, created_at, output_truncated, call_id)
SELECT
m.id,
$11::uuid,
m.seq,
m.type,
NULLIF(m.tool, ''),
NULLIF(m.content, ''),
NULLIF(m.input, '')::jsonb,
NULLIF(m.output, ''),
COALESCE(NULLIF(m.created_at, '')::timestamptz, now()),
NULLIF(m.output_truncated, '')::bool,
NULLIF(m.call_id, '')
FROM incoming AS m
RETURNING id, task_id, seq, type, tool, content, input, output, created_at, output_truncated, call_id
)
SELECT id, task_id, seq, type, tool, content, input, output, created_at, output_truncated, call_id FROM inserted ORDER BY seq ASC
`
type CreateTaskMessagesParams struct {
Ids []pgtype.UUID `json:"ids"`
Seqs []int32 `json:"seqs"`
Types []string `json:"types"`
Tools []string `json:"tools"`
CallIds []string `json:"call_ids"`
Contents []string `json:"contents"`
Inputs []string `json:"inputs"`
Outputs []string `json:"outputs"`
CreatedAts []string `json:"created_ats"`
OutputTruncations []string `json:"output_truncations"`
TaskID pgtype.UUID `json:"task_id"`
}
type CreateTaskMessagesRow struct {
ID pgtype.UUID `json:"id"`
TaskID pgtype.UUID `json:"task_id"`
Seq int32 `json:"seq"`
Type string `json:"type"`
Tool pgtype.Text `json:"tool"`
Content pgtype.Text `json:"content"`
Input []byte `json:"input"`
Output pgtype.Text `json:"output"`
CreatedAt pgtype.Timestamptz `json:"created_at"`
OutputTruncated pgtype.Bool `json:"output_truncated"`
CallID pgtype.Text `json:"call_id"`
}
// Batch variant of CreateTaskMessage: persists a whole daemon-reported batch in
// ONE statement — therefore one round trip and, more importantly, one commit
// instead of one per message. Commit acknowledgement (IO:XactSync) is ~94% of
// this SQL's load in production, so the commit count is the thing being
// optimized; the round trip is a bonus.
//
// The rows arrive as parallel arrays rather than as one jsonb document, even
// though a jsonb document is the tidier Go side. content and output routinely
// carry tens of KB and occasionally megabytes, and wrapping them in JSON makes
// the server escape every byte a second time and Postgres parse the whole
// envelope back out — measured at 1.2x the old per-row insert at 128KB and
// ~1.8x at 1MB, i.e. a regression on exactly the most expensive requests, which
// are also the ones least likely to be batched. Native text[] elements are
// length-prefixed by the wire protocol, so they cost neither pass.
//
// NULLIF is what makes per-row NULL expressible through a non-nullable []string
// (the Go type sqlc gives a text[] parameter): it reproduces, exactly, the
// `pgtype.Text{Valid: x != ""}` mapping the single-row query carries — empty
// string means SQL NULL. input is passed as text and cast here for the same
// reason; it is the one column that genuinely has to be parsed as JSON, because
// it is a jsonb column. created_at also rides this transport so an older daemon
// can omit its event time and keep the database-time fallback. output_truncated
// uses the same trick because it is a genuinely tri-state boolean (NULL = the
// reporting daemon did not measure it), and a bool[] parameter becomes a Go
// []bool, which has no way to spell the third state.
//
// Callers MUST still run the Postgres text sanitizer first. A NUL anywhere in
// the batch fails the whole statement (GH #7098) — that is inherent to batching
// into one statement, not to the parameter shape.
//
// Atomicity is a deliberate side effect, not just a speedup: the per-message
// loop this replaces could persist part of a batch and then fail, leaving the
// transcript with a prefix of the batch and no way to complete it — the daemon
// does not retry this endpoint. One statement makes the batch all-or-nothing,
// which buys consistency; a batch that fails is still lost whole, so closing
// the gap for real needs a retry plus a (task_id, seq) uniqueness rule.
//
// The ORDER BY is a contract, not decoration. A bare `INSERT ... RETURNING`
// has no defined row order, and the caller republishes these rows as realtime
// events in the order they arrive — the per-row loop this replaces implicitly
// published in request order, so the ordering has to be restored explicitly or
// subscribers can see a batch out of order. seq is assigned by the daemon and
// increases within a batch, so it is the request order.
func (q *Queries) CreateTaskMessages(ctx context.Context, arg CreateTaskMessagesParams) ([]CreateTaskMessagesRow, error) {
rows, err := q.db.Query(ctx, createTaskMessages,
arg.Ids,
arg.Seqs,
arg.Types,
arg.Tools,
arg.CallIds,
arg.Contents,
arg.Inputs,
arg.Outputs,
arg.CreatedAts,
arg.OutputTruncations,
arg.TaskID,
)
if err != nil {
return nil, err
}
defer rows.Close()
items := []CreateTaskMessagesRow{}
for rows.Next() {
var i CreateTaskMessagesRow
if err := rows.Scan(
&i.ID,
&i.TaskID,
&i.Seq,
&i.Type,
&i.Tool,
&i.Content,
&i.Input,
&i.Output,
&i.CreatedAt,
&i.OutputTruncated,
&i.CallID,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const deleteTaskMessages = `-- name: DeleteTaskMessages :exec
DELETE FROM task_message
WHERE task_id = $1
`
func (q *Queries) DeleteTaskMessages(ctx context.Context, taskID pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteTaskMessages, taskID)
return err
}
const listTaskMessages = `-- name: ListTaskMessages :many
SELECT id, task_id, seq, type, tool, content, input, output, created_at, output_truncated, call_id FROM task_message
WHERE task_id = $1
ORDER BY seq ASC
`
func (q *Queries) ListTaskMessages(ctx context.Context, taskID pgtype.UUID) ([]TaskMessage, error) {
rows, err := q.db.Query(ctx, listTaskMessages, taskID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []TaskMessage{}
for rows.Next() {
var i TaskMessage
if err := rows.Scan(
&i.ID,
&i.TaskID,
&i.Seq,
&i.Type,
&i.Tool,
&i.Content,
&i.Input,
&i.Output,
&i.CreatedAt,
&i.OutputTruncated,
&i.CallID,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listTaskMessagesSince = `-- name: ListTaskMessagesSince :many
SELECT id, task_id, seq, type, tool, content, input, output, created_at, output_truncated, call_id FROM task_message
WHERE task_id = $1 AND seq > $2
ORDER BY seq ASC
`
type ListTaskMessagesSinceParams struct {
TaskID pgtype.UUID `json:"task_id"`
Seq int32 `json:"seq"`
}
func (q *Queries) ListTaskMessagesSince(ctx context.Context, arg ListTaskMessagesSinceParams) ([]TaskMessage, error) {
rows, err := q.db.Query(ctx, listTaskMessagesSince, arg.TaskID, arg.Seq)
if err != nil {
return nil, err
}
defer rows.Close()
items := []TaskMessage{}
for rows.Next() {
var i TaskMessage
if err := rows.Scan(
&i.ID,
&i.TaskID,
&i.Seq,
&i.Type,
&i.Tool,
&i.Content,
&i.Input,
&i.Output,
&i.CreatedAt,
&i.OutputTruncated,
&i.CallID,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}