Add a new SQL query to an existing domain's PostgreSQL query file and regenerate sqlc Go code
Add a new named SQL query to pkg/postgres/queries/<domain>.sql and run go tool sqlc generate to produce the corresponding Go method in pkg/postgres/db/<domain>.sql.go.
Every query needs a name and return type annotation:
| Annotation | Return type | Use case |
|---|---|---|
:one | single row struct | SELECT by ID, INSERT RETURNING, UPDATE RETURNING |
:many | []Row slice | SELECT list/filtered results |
:exec | error | DELETE/UPDATE with no return |
:execresult | pgconn.CommandTag, error | DELETE/UPDATE when you need RowsAffected |
PostgreSQL parameters use $1, $2, ... (not ?).
-- name: <QueryName> :<annotation>
SELECT ...
FROM <table>
WHERE ...;
-- name: ListUsersByName :many
SELECT * FROM users
WHERE name ILIKE '%' || $1 || '%'
ORDER BY created_at ASC;
-- name: ListUsersPaginated :many
SELECT * FROM users
ORDER BY created_at ASC
LIMIT $1 OFFSET $2;
-- name: CountUsers :one
SELECT COUNT(*) FROM users;
deleted_at column first)-- name: SoftDeleteUser :exec
UPDATE users SET deleted_at = $1 WHERE id = $2;
-- name: UpsertUser :one
INSERT INTO users (id, name, email, created_at)
VALUES ($1, $2, $3, $4)
ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name
RETURNING *;
pkg/postgres/queries/<domain>.sqlgo tool sqlc generate
make check
pkg/postgres/db/<domain>.sql.gointernal/<domain>/core/service.go via s.q.<QueryName>(ctx, ...)pkg/postgres/migrations/<domain>.sql:
ALTER TABLE <domain>s ADD COLUMN IF NOT EXISTS <field> TEXT;
Or for a fresh project, edit the CREATE TABLE directly.go tool sqlc generate to pick up schema changes.postgres.Migrate in main).- engine: "postgresql"
queries: "pkg/postgres/queries"
schema: "pkg/postgres/migrations"
gen:
go:
package: "pgdb"
out: "pkg/postgres/db"
sql_package: "pgx/v5"
overrides:
- db_type: "timestamptz"
go_type: "time.Time"
// DeleteUser with pgconn.CommandTag (no error from RowsAffected):
result, err := s.q.DeleteUser(ctx, id)
if err != nil { ... }
if result.RowsAffected() == 0 {
return ErrNotFound
}
// GetByID — use pgx.ErrNoRows not sql.ErrNoRows:
import "github.com/jackc/pgx/v5"
if errors.Is(err, pgx.ErrNoRows) {
return nil, ErrNotFound
}