Client API Reference
Client wraps a *sql.DB and owns Quark configuration: dialect, logger,
SQLGuard, limits, middleware, observers, and cache store.
New
New(db *sql.DB, opts ...Option) (*Client, error)
Creates a client and pings the database.
db, err := sql.Open("postgres", "postgres://user:pass@localhost/app?sslmode=disable")
if err != nil {
return err
}
client, err := quark.New(db,
quark.WithDialect(quark.PostgreSQL()),
quark.WithLogger(slog.Default()),
)
if err != nil {
return err
}
defer client.Close()
Errors:
| Case | Error |
|---|---|
db == nil | wraps ErrConnection |
PingContext fails | wraps ErrConnection |
If WithDialect is omitted, Quark tries to detect the dialect from the driver
type. Explicit WithDialect is recommended in production.
Options
WithDialect(d Dialect) Option
Sets the SQL dialect.
client, err := quark.New(db, quark.WithDialect(quark.PostgreSQL()))
Available constructors:
| Constructor | Dialect name |
|---|---|
quark.PostgreSQL() | postgres |
quark.MySQL() | mysql |
quark.MariaDB() | mariadb |
quark.SQLite() | sqlite |
quark.MSSQL() | mssql |
quark.Oracle() | oracle |
WithLogger(l *slog.Logger) Option
Sets the structured logger.
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
client, err := quark.New(db,
quark.WithDialect(quark.PostgreSQL()),
quark.WithLogger(logger),
)
Default: slog.Default().
WithLimits(l Limits) Option
Sets security and performance limits.
limits := quark.DefaultLimits()
limits.AllowRawQueries = true
client, err := quark.New(db,
quark.WithDialect(quark.PostgreSQL()),
quark.WithLimits(limits),
)
type Limits struct {
MaxQueryLength int
MaxResults int
MaxJoins int
MaxWhereConditions int
QueryTimeout time.Duration
AllowRawQueries bool
SafeMigrations bool
}
DefaultLimits() Limits
Returns:
| Field | Default |
|---|---|
MaxQueryLength | 10 * 1024 |
MaxResults | 10000 |
MaxJoins | 5 |
MaxWhereConditions | 20 |
QueryTimeout | 30 * time.Second |
AllowRawQueries | false |
SafeMigrations | true |
WithCacheStore(s CacheStore) Option
Attaches a cache backend.
store := memory.New()
client, err := quark.New(db,
quark.WithDialect(quark.SQLite()),
quark.WithCacheStore(store),
)
WithMiddleware(m Middleware) Option
Adds middleware to the execution chain.
client, err := quark.New(db,
quark.WithDialect(quark.PostgreSQL()),
quark.WithMiddleware(quarkotel.New()),
)
WithQueryObserver(o QueryObserver) Option
Adds a post-execution observer.
client, err := quark.New(db,
quark.WithDialect(quark.PostgreSQL()),
quark.WithQueryObserver(&MetricsObserver{}),
)
For
For[T any](ctx context.Context, provider ClientProvider) *Query[T]
Creates a typed query builder for model T.
users, err := quark.For[User](ctx, client).
Where("active", "=", true).
OrderBy("created_at", "DESC").
Limit(50).
List()
provider can be a *Client or *TenantRouter.
type ClientProvider interface {
GetClient(ctx context.Context) (*Client, error)
}
If a provider cannot return a client, the returned query stores that error and will return it on execution.
RawQuery
RawQuery(ctx context.Context, query string, args ...any) (*sql.Rows, error)
Executes raw SQL that returns rows.
limits := quark.DefaultLimits()
limits.AllowRawQueries = true
client, err := quark.New(db,
quark.WithDialect(quark.PostgreSQL()),
quark.WithLimits(limits),
)
rows, err := client.RawQuery(ctx,
"SELECT id, email FROM users WHERE active = $1",
true,
)
Raw queries are disabled by default. RawQuery also asks SQLGuard to validate
that placeholders are present and that obvious injection patterns are absent.
Exec
Exec(ctx context.Context, query string, args ...any) error
Executes raw SQL that does not return rows.
err := client.Exec(ctx,
"CREATE INDEX idx_users_email ON users(email)",
)
Exec requires AllowRawQueries: true and runs raw-query validation.
Raw
Raw() *sql.DB
Returns the underlying database handle.
db := client.Raw()
stats := db.Stats()
Operations performed on Raw() bypass Quark validation, middleware, cache
invalidation, observers, and tenant routing.
Close
Close() error
Closes the underlying *sql.DB.
defer client.Close()
Dialect
Dialect() Dialect
Returns the active dialect.
if client.Dialect().Name() == "postgres" {
// PostgreSQL-specific integration
}