-- Entity read + mutation queries (API paths). Aliased `e` throughout to -- avoid ambiguity with joined tables. -- name: GetEntityByID :one SELECT e.* FROM entities e WHERE e.id = $1; -- name: GetEntityBySlug :one SELECT e.* FROM entities e WHERE e.slug = $1; -- name: ListEntities :many WITH RECURSIVE tt AS ( SELECT name FROM entity_types WHERE sqlc.narg('type')::text IS NULL OR name = sqlc.narg('type') UNION SELECT et.name FROM entity_types et JOIN tt ON et.parent_type = tt.name WHERE sqlc.narg('type')::text IS NOT NULL ) SELECT e.* FROM entities e JOIN entity_types et ON et.name = e.type WHERE e.type IN (SELECT name FROM tt) AND (sqlc.narg('state')::text IS NULL OR e.state = sqlc.narg('state')) AND (sqlc.narg('domain')::text IS NULL OR et.domain = sqlc.narg('domain')) AND (sqlc.narg('layer')::text IS NULL OR et.layer = sqlc.narg('layer')) AND (sqlc.narg('q')::text IS NULL OR e.slug ILIKE '%'||sqlc.narg('q')||'%' OR e.name ILIKE '%'||sqlc.narg('q')||'%') AND (sqlc.narg('cursor')::text IS NULL OR e.slug > sqlc.narg('cursor')) ORDER BY e.slug LIMIT sqlc.arg('lim'); -- name: ListEntitiesCapped :many SELECT e.* FROM entities e ORDER BY e.slug LIMIT $1; -- name: InsertEntity :one INSERT INTO entities (id, slug, type, name, state, attributes) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *; -- name: UpdateEntity :one UPDATE entities SET name = COALESCE(sqlc.narg('name'), name), state = COALESCE(sqlc.narg('state'), state), attributes = COALESCE(sqlc.narg('attributes'), attributes), maintenance_until = CASE WHEN sqlc.arg('set_maintenance')::bool THEN sqlc.narg('maintenance_until') ELSE maintenance_until END, version = version + 1, updated_at = now() WHERE id = sqlc.arg('id') AND version = sqlc.arg('version') RETURNING *; -- blast_radius(): the recursive-CTE traversal function's TABLE return type -- is opaque to sqlc's analyzer — that one query stays hand-written pgx in -- internal/httpapi (see impl.go).