https://github.com/go-simpler/queries
🛢️ Convenience helpers for working with SQL queries
https://github.com/go-simpler/queries
dependency-free go library query-builder sql sql-query
Last synced: 3 months ago
JSON representation
🛢️ Convenience helpers for working with SQL queries
- Host: GitHub
- URL: https://github.com/go-simpler/queries
- Owner: go-simpler
- License: mpl-2.0
- Created: 2024-04-23T16:55:50.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-06-15T09:16:09.000Z (10 months ago)
- Last Synced: 2025-09-11T16:07:02.481Z (7 months ago)
- Topics: dependency-free, go, library, query-builder, sql, sql-query
- Language: Go
- Homepage: https://go-simpler.org/queries
- Size: 66.4 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# queries
[](https://github.com/go-simpler/queries/actions/workflows/checks.yml)
[](https://pkg.go.dev/go-simpler.org/queries)
[](https://goreportcard.com/report/go-simpler.org/queries)
[](https://codecov.io/gh/go-simpler/queries)
Convenience helpers for working with SQL queries.
## 🚀 Features
- Builder: a `strings.Builder` wrapper with added support for placeholder verbs to easily build raw SQL queries conditionally.
- Scanner: `sql.DB.Query/QueryRow` wrappers that automatically scan `sql.Rows` into the given struct. Inspired by [golang/go#61637][1].
- Interceptor: a `driver.Driver` wrapper to easily add instrumentation (logs, metrics, traces) to the database layer. Similar to [gRPC interceptors][2].
## 📦 Install
Go 1.24+
```shell
go get go-simpler.org/queries
```
## 📋 Usage
### Builder
```go
columns := []string{"id", "name"}
var qb queries.Builder
qb.Appendf("SELECT %s FROM users", strings.Join(columns, ", "))
if role != nil { // "admin"
qb.Appendf(" WHERE role = %$", *role)
}
if orderBy != nil { // "name"
qb.Appendf(" ORDER BY %$", *orderBy)
}
if limit != nil { // 10
qb.Appendf(" LIMIT %$", *limit)
}
query, args := qb.Build()
db.QueryContext(ctx, query, args...)
// Query: "SELECT id, name FROM users WHERE role = $1 ORDER BY $2 LIMIT $3"
// Args: ["admin", "name", 10]
```
The following database placeholders are supported:
- `?` (used by MySQL and SQLite)
- `$1`, `$2`, ..., `$N` (used by PostgreSQL)
- `@p1`, `@p2`, ..., `@pN` (used by Microsoft SQL Server)
- `:1`, `:2`, ..., `:N` (used by Oracle Database):
### Scanner
```go
type User struct {
ID int `sql:"id"`
Name string `sql:"name"`
}
// single column, single row:
name, _ := queries.QueryRow[string](ctx, db, "SELECT name FROM users WHERE id = 1")
// single column, multiple rows:
names, _ := queries.Collect(queries.Query[string](ctx, db, "SELECT name FROM users"))
// multiple columns, single row:
user, _ := queries.QueryRow[User](ctx, db, "SELECT id, name FROM users WHERE id = 1")
// multiple columns, multiple rows:
for user, _ := range queries.Query[User](ctx, db, "SELECT id, name FROM users") {
// ...
}
```
### Interceptor
```go
interceptor := queries.Interceptor{
Driver: // database driver of your choice.
ExecContext: func(ctx context.Context, query string, args []driver.NamedValue, execer driver.ExecerContext) (driver.Result, error) {
slog.InfoContext(ctx, "ExecContext", "query", query)
return execer.ExecContext(ctx, query, args)
},
QueryContext: func(ctx context.Context, query string, args []driver.NamedValue, queryer driver.QueryerContext) (driver.Rows, error) {
slog.InfoContext(ctx, "QueryContext", "query", query)
return queryer.QueryContext(ctx, query, args)
},
}
sql.Register("interceptor", interceptor)
db, _ := sql.Open("interceptor", "dsn")
db.ExecContext(ctx, "INSERT INTO users VALUES (1, 'John Doe')")
// stderr: INFO ExecContext query="INSERT INTO users VALUES (1, 'John Doe')"
db.QueryContext(ctx, "SELECT id, name FROM users")
// stderr: INFO QueryContext query="SELECT id, name FROM users"
```
Integration tests cover the following databases and drivers:
- PostgreSQL with [lib/pq][3], [jackx/pgx][4]
- MySQL with [go-sql-driver/mysql][5]
- SQLite with [modernc.org/sqlite][6]
- Microsoft SQL Server with [microsoft/go-mssqldb][7]
- Oracle Database with [sijms/go-ora][8]
See [integration_test.go](tests/integration_test.go) for details.
[1]: https://github.com/golang/go/issues/61637
[2]: https://grpc.io/docs/guides/interceptors
[3]: https://github.com/lib/pq
[4]: https://github.com/jackc/pgx
[5]: https://github.com/go-sql-driver/mysql
[6]: https://gitlab.com/cznic/sqlite
[7]: https://github.com/microsoft/go-mssqldb
[8]: https://github.com/sijms/go-ora