Query Objects Overview
Learn how to use db.Query values with ListQuery, GetQuery, ValueQuery, and MapsQuery.
Query object helpers are the lower-level version of the select helpers.
Instead of passing a query string and arguments directly into db.List, db.Get, db.Value, or db.Maps, you first create a db.Query value and then execute it.
This is useful when you want to prepare a query once and pass it between functions.
Available Helpers
| Helper | Result | Use case |
|---|---|---|
db.Raw | db.Query | Create a query object from SQL/CQL and arguments |
db.ListQuery[T] | []T | Read multiple rows from a db.Query |
db.GetQuery[T] | (T, bool, error) | Read zero or one row from a db.Query |
db.ValueQuery[T] | (T, bool, error) | Read one scalar value from a db.Query |
db.MapsQuery | []map[string]any | Read map rows from a db.Query |
Basic Flow
Create a query object with db.Raw.
q, err := db.Raw(`
SELECT * FROM users
WHERE active = ?
ORDER BY created_at DESC
`, true)
if err != nil {
return nil, err
}Then pass the query object to one of the query helpers.
users, err := db.ListQuery[User](ctx, conn, q)
if err != nil {
return nil, err
}This is equivalent to:
users, err := db.List[User](ctx, conn, `
SELECT * FROM users
WHERE active = ?
ORDER BY created_at DESC
`, true)Why Use Query Objects?
Use query objects when the query is built or selected before execution.
Common use cases include:
- passing a query between application layers
- building small query helper functions
- selecting SQL from another source before execution
- using
db.Dialectbefore callingListQuery,GetQuery,ValueQuery, orMapsQuery - keeping repository functions focused on execution
- reusing the same query object in tests
Query Object Shape
A db.Query contains the SQL or CQL string and its arguments.
type Query struct {
SQL string
Args []any
Type int
}Most application code creates it through db.Raw.
q, err := db.Raw(query, args...)db.Raw validates that the query string is not empty.
If the query string is empty, it returns an error.
ListQuery
Use db.ListQuery when the query object should return multiple typed rows.
users, err := db.ListQuery[User](ctx, conn, q)
if err != nil {
return nil, err
}This is the query-object equivalent of db.List.
GetQuery
Use db.GetQuery when the query object should return zero or one typed row.
user, found, err := db.GetQuery[User](ctx, conn, q)
if err != nil {
return User{}, false, err
}
if !found {
return User{}, false, nil
}This is the query-object equivalent of db.Get.
ValueQuery
Use db.ValueQuery when the query object should return one scalar value.
total, found, err := db.ValueQuery[int64](ctx, conn, q)
if err != nil {
return 0, false, err
}This is the query-object equivalent of db.Value.
MapsQuery
Use db.MapsQuery when the query object should return dynamic map rows.
rows, err := db.MapsQuery(ctx, conn, q)
if err != nil {
return nil, err
}This is the query-object equivalent of db.Maps.
Placeholder Differences
Query objects do not change SQL placeholder syntax.
The query string must still match the selected driver.
| Driver | Placeholder style |
|---|---|
| MySQL | ? |
| Postgres | $1, $2, $3 |
| Scylla | ? |
Example MySQL query object:
q, err := db.Raw(`
SELECT * FROM users
WHERE active = ?
`, true)Example PostgreSQL query object:
q, err := db.Raw(`
SELECT * FROM users
WHERE active = $1
`, true)Query Objects and Dialect SQL
Query objects are also useful with dialect SQL.
db.Dialect selects the correct SQL or CQL string from a db.DialectSQL value and returns a db.Query.
q, err := db.Dialect(conn, queries.GetUser, id)
if err != nil {
return User{}, false, err
}
return db.GetQuery[User](ctx, conn, q)This is useful when the query comes from SQL model files and your application may run on different drivers.
Choosing the Right Helper
| Need | Use |
|---|---|
| Create a query object | db.Raw |
| Multiple typed rows from a query object | db.ListQuery[T] |
| Zero or one typed row from a query object | db.GetQuery[T] |
| One scalar value from a query object | db.ValueQuery[T] |
| Dynamic map rows from a query object | db.MapsQuery |
Select Helpers vs Query Objects
Use select helpers for direct application code.
users, err := db.List[User](ctx, conn, query, args...)Use query objects when you want a separate query creation step.
q, err := db.Raw(query, args...)
if err != nil {
return nil, err
}
users, err := db.ListQuery[User](ctx, conn, q)Next Step
Continue with the dedicated query-object pages for complete examples of:
ListQueryGetQueryValueQueryMapsQuery