quarry

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

README

Quarry logo

CI License Go Docs

Quarry

Quarry is a SQL composition toolkit for Go.

It lets you write SQL-shaped Go, compose filters safely, bind args predictably, and scan results cleanly.

No magic ORM. No forced codegen. No string-concat sadness.

Why Quarry Exists

Quarry is for Go developers who want to keep SQL explicit without hand-rolling fragile query strings.

Use it to compose queries, add dynamic filters, map user-facing sort options safely, include raw SQL fragments with bound arguments, and scan results when you want a lightweight helper instead of a full ORM.

The API is intentionally small. Quarry stays explicit and hard to misuse. Every change must make SQL composition clearer, safer, or more reliable, not more magical.

For more detail, see:

The docs site lives under docs/.

What Quarry Does

Quarry helps you build SQL with explicit Go code instead of brittle string concatenation.

  • Fluent builders for SELECT, INSERT, UPDATE, and DELETE
  • Safe helpers for tables, columns, aliases, and sort expressions
  • Dialect-aware placeholder rendering for Postgres, MySQL, and SQLite
  • Dynamic predicates for optional filters and conditional clauses
  • Raw SQL fragments with bound arguments when you need to drop lower
  • Optional scanning and Codex helpers for lightweight result handling and reusable query recipes

What Quarry Does Not Do

Quarry is intentionally narrow. It helps compose SQL; it does not try to become your entire database layer.

Quarry has boundaries. Glorious, load-bearing boundaries.

  • Not an ORM
  • Not a code generator
  • Not a full sqlc replacement
  • Not a migration tool
  • Not a schema modeling system
  • Not a dialect abstraction for every database ever shipped

When to Use Quarry

Use Quarry when raw SQL is still the mental model, but the query needs to be assembled safely.

Good fits:

  • Dynamic filters
  • Safe user-facing sorting
  • Dialect-aware placeholders
  • Explicit SELECT, INSERT, UPDATE, and DELETE builders
  • Lightweight result scanning

Bad fits:

  • Entity tracking
  • Migrations
  • Relationship loading
  • Generated query code
  • Automatic schema modeling
  • Hiding SQL from the developer

Safety Model

Quarry keeps SQL safety boring and explicit: values are bound, identifiers are trusted, and raw SQL stays your responsibility.

  • Bind SQL values as args.
  • Treat identifiers as code, not data.
  • Never pass user-controlled identifiers directly into raw SQL.
  • Use identifier helpers for trusted tables, columns, and aliases.
  • Treat SetMap keys as trusted identifiers, not arbitrary user input.
  • Use OrderBySafe or OrderBySafeDefault for user-facing sort options.
  • Use Raw(...) only when you need to drop to SQL directly and the SQL fragment itself is trusted.
  • Do not treat Raw(...) as a sanitizer.
  • Quarry does not make arbitrary SQL fragments safe automatically.

Installation

go get github.com/sphireinc/quarry

Quick Start

package main

import "github.com/sphireinc/quarry"

func main() {
	qq := quarry.New(quarry.Postgres)

	query := qq.Select("id", "email").From("users").Where(quarry.Eq("status", "active"))

	sql, args, err := query.ToSQL()
	if err != nil {
		panic(err)
	}
}

// var:sql  = SELECT id, email FROM users WHERE status = $1
// var:args = []any{"active"}

Dynamic Filters

Use optional predicates for search forms, API filters, and any query condition that should only appear when a value is present.

type UserSearch struct {
	TenantID int
	Search   string
	Status   *string
	Page     int
	PerPage  int
}

q := qq.Select("id", "email", "created_at").
	From("users").
	Where(
		quarry.Eq("tenant_id", params.TenantID),
		quarry.Or(
			quarry.OptionalILike("email", params.Search),
			quarry.OptionalILike("name", params.Search),
		),
		quarry.OptionalEq("status", params.Status),
	).
	OrderBySafeDefault("newest", quarry.SortMap{
		"newest": "created_at DESC",
		"email":  "email ASC",
	}, "newest").
	Page(params.Page, params.PerPage)

Safe Sorting

OrderBySafe and OrderBySafeDefault map user-facing sort options to trusted SQL fragments. User input selects from the map; it never becomes SQL directly.

q := qq.Select("id", "email").
	From("users").
	OrderBySafeDefault("newest", quarry.SortMap{
		"newest": "created_at DESC",
		"email":  "email ASC",
	}, "newest")

Partial Updates

Use SetOptional and SetIf to build explicit UPDATE statements from optional values without falling back to ad hoc SQL fragments.

q := qq.Update("users").
	SetOptional("name", params.Name).
	SetOptional("email", params.Email).
	SetIf(params.Enabled != nil, "enabled", *params.Enabled).
	Where(quarry.Eq("id", params.ID))

Raw SQL Escape Hatch

When raw SQL is the clearest option, use Raw(...) and keep values bound as args.

q := qq.Select(quarry.Raw("COUNT(*) FILTER (WHERE status = ?)", "active")).
	From("users").
	Where(quarry.Raw("created_at >= ?", since))

Raw ? placeholders are rewritten for the target dialect. The placeholder scanner skips strings, comments, quoted identifiers, and dollar-quoted bodies. That scanner protects placeholder rewriting. It does not validate whether a SQL fragment is safe.

Codex Reusable Query Store

Codex is Quarry's optional registry for reusable named queries and SQL-shaped recipes.

It stays close to SQL, keeps arguments bound, and is unrelated to OpenAI Codex. Different Codex. Fewer lawyers, hopefully.

cx := codex.New()

if err := cx.AddRawNamed("users.by_id", `SELECT id, email FROM users WHERE id = :id`); err != nil {
	panic(err)
}

if err := cx.AddRecipe("users.search", codex.NewRecipe(func(qq *quarry.Quarry, p UserSearchParams) quarry.SQLer {
	return qq.Select("id", "email", "created_at").
		From("users").
		Where(
			quarry.OptionalILike("email", p.Search),
			quarry.OptionalEq("status", p.Status),
		)
})); err != nil {
	panic(err)
}

q, err := cx.MustRecipe("users.search").Build(qq, UserSearchParams{
	Search: "%bob%",
})
if err != nil {
	panic(err)
}

Scanning

Quarry includes a small optional scan package for scanning query results into Go structs, slices, and scalar values.

users, err := scan.All[User](ctx, db, q)

It supports:

  • db tags
  • json tag fallback
  • snake_case fallback
  • Pointer and nullable values
  • Forgiving handling of unknown columns

For the scan contract, see docs/scan.md.

scan keeps raw SQL visible and does not try to sanitize arbitrary query text.

For richer hydration workflows, use the standalone github.com/sphireinc/Hydra project. See docs/hydra.md for how Hydra fits alongside Quarry.

Quarry does not infer schemas, generate CRUD operations, track entities, or manage relationships.

Dialects

Quarry currently supports:

  • quarry.Postgres
  • quarry.MySQL
  • quarry.SQLite

Dialect handling includes:

  • Placeholder rendering
  • Identifier quoting
  • RETURNING behavior
  • ILIKE fallback behavior
  • Postgres-only ANY support

See docs/dialects.md for the full dialect matrix.

See docs/compatibility.md for versioning and compatibility policy, and docs/reference/packages/ for package maps and import paths.

Squirrel Migration Notes

Squirrel proved that explicit SQL composition is useful. Quarry follows that same general shape, but it is not built on Squirrel.

If you know Squirrel, Quarry should feel familiar: fluent builders, visible SQL, and predictable sql, args output.

Basic code comparison
// Squirrel:
q := sq.Select("id", "email").From("users").Where(sq.Eq{"status": "active"})

// Quarry:
q := qq.Select("id", "email").From("users").Where(quarry.Eq("status", "active"))
Area Squirrel Quarry
Core identity Fluent SQL generator SQL composition toolkit
ORM? No No
Dynamic filters Possible, but user assembles the patterns First-class optional predicates
Safe sorting Mostly user-managed OrderBySafe and OrderBySafeDefault
Dialect behavior Placeholder formats exist Explicit dialect policy and docs
Identifier safety Less central to the positioning Core part of the safety model
Raw SQL Supported through expressions and fragments Explicit escape hatch with bound args and scanner rules
Scanning Not the main thing Optional lightweight scan package
Named recipes Not the main thing Optional Codex layer
Project posture Mature ecosystem staple Newer, docs-first, safety-first toolkit

Quarry is conceptually close to Squirrel, but the differences are intentional:

  • Quarry emphasizes dialect policy and identifier safety.
  • Quarry has first-class optional predicates for dynamic filters.
  • Quarry maps user-facing sort options to trusted SQL fragments.
  • Quarry keeps raw SQL explicit and available.
  • Quarry treats scanning and Codex as optional layers, not core magic.

The point is not to pretend Quarry invented fluent SQL composition. It did not. The point is to make the safety boundaries, dialect behavior, dynamic assembly patterns, and optional helper layers clearer from the start.

For a broader comparison with raw SQL, Squirrel, sqlc, GORM, and sqlx, see docs/comparison.md.

Roadmap / Status

Quarry is useful today for explicit SQL composition, dynamic filters, safe sorting, raw SQL fragments with bound arguments, and optional scanning helpers.

See docs/status.md for the current implementation snapshot, CHANGELOG.md for release history, and ROADMAP.md for where Quarry is headed, and where it intentionally is not.

Examples

The examples in examples/ compile and show the intended API shapes:

License

Quarry is licensed under the Apache License, Version 2.0. See LICENSE for the full text.

Documentation

Overview

Package quarry provides a small, explicit Go SQL composition toolkit.

Quarry keeps SQL visible, binds values explicitly, and stays close to database/sql instead of trying to become an ORM or schema modeler.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidIdentifier reports a rejected identifier value.
	ErrInvalidIdentifier = errors.New("invalid identifier")
	// ErrUnsupportedFeature reports that the active dialect cannot render a feature.
	ErrUnsupportedFeature = errors.New("unsupported dialect feature")
	// ErrInvalidBuilderState reports a builder that cannot be rendered as configured.
	ErrInvalidBuilderState = errors.New("invalid builder state")
	// ErrPlaceholderMismatch reports a placeholder / argument count mismatch.
	ErrPlaceholderMismatch = errors.New("placeholder mismatch")
)

Functions

This section is empty.

Types

type Column

type Column struct {
	// contains filtered or unexported fields
}

Column identifies a SQL column, optionally qualified by a table.

func C

func C(name string) Column

C constructs a safe column helper without table qualification.

func Col

func Col(name string) Column

Col is a named alias for C.

func (Column) Any

func (c Column) Any(values any) Predicate

Any returns a Postgres ANY predicate for the column.

func (Column) As

func (c Column) As(alias string) Column

As returns a copy of the column with the supplied alias.

func (Column) Between

func (c Column) Between(low any, high any) Predicate

Between returns a BETWEEN predicate for the column.

func (Column) Eq

func (c Column) Eq(val any) Predicate

Eq returns a column comparison predicate using =.

func (Column) Gt

func (c Column) Gt(val any) Predicate

Gt returns a column comparison predicate using >.

func (Column) Gte

func (c Column) Gte(val any) Predicate

Gte returns a column comparison predicate using >=.

func (Column) ILike

func (c Column) ILike(val any) Predicate

ILike returns a case-insensitive LIKE predicate for the column.

func (Column) In

func (c Column) In(values ...any) Predicate

In returns an IN predicate for the column.

func (Column) IsNotNull

func (c Column) IsNotNull() Predicate

IsNotNull returns an IS NOT NULL predicate for the column.

func (Column) IsNull

func (c Column) IsNull() Predicate

IsNull returns an IS NULL predicate for the column.

func (Column) Like

func (c Column) Like(val any) Predicate

Like returns a LIKE predicate for the column.

func (Column) Lt

func (c Column) Lt(val any) Predicate

Lt returns a column comparison predicate using <.

func (Column) Lte

func (c Column) Lte(val any) Predicate

Lte returns a column comparison predicate using <=.

func (Column) Neq

func (c Column) Neq(val any) Predicate

Neq returns a column comparison predicate using <>.

func (Column) NotIn

func (c Column) NotIn(values ...any) Predicate

NotIn returns a NOT IN predicate for the column.

type DeleteBuilder

type DeleteBuilder struct {
	// contains filtered or unexported fields
}

DeleteBuilder renders DELETE statements for the active Quarry dialect.

func (*DeleteBuilder) Prefix

func (b *DeleteBuilder) Prefix(sql string, args ...any) *DeleteBuilder

Prefix appends a raw fragment before the DELETE statement.

func (*DeleteBuilder) Returning

func (b *DeleteBuilder) Returning(cols ...any) *DeleteBuilder

Returning appends RETURNING expressions.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)

	sqlText, args, err := qq.DeleteFrom("users").
		Where(quarry.Eq("id", 7)).
		Returning("id").
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
DELETE FROM "users" WHERE "id" = $1 RETURNING "id"
[7]

func (*DeleteBuilder) Suffix

func (b *DeleteBuilder) Suffix(sql string, args ...any) *DeleteBuilder

Suffix appends a raw fragment after the DELETE statement.

func (*DeleteBuilder) ToSQL

func (b *DeleteBuilder) ToSQL() (string, []any, error)

func (*DeleteBuilder) Where

func (b *DeleteBuilder) Where(preds ...Predicate) *DeleteBuilder

Where appends DELETE predicates.

func (*DeleteBuilder) WhereIf

func (b *DeleteBuilder) WhereIf(cond bool, pred Predicate) *DeleteBuilder

WhereIf appends pred only when cond is true and the predicate is non-empty.

type Dialect

type Dialect string

Dialect identifies the SQL dialect Quarry should render for.

const (
	// Postgres renders PostgreSQL placeholders and dialect-specific SQL.
	Postgres Dialect = "postgres"
	// MySQL renders MySQL-style placeholders and compatible SQL.
	MySQL Dialect = "mysql"
	// SQLite renders SQLite-style placeholders and compatible SQL.
	SQLite Dialect = "sqlite"
)

func (Dialect) Name

func (d Dialect) Name() string

Name returns the canonical dialect name.

func (Dialect) Placeholder

func (d Dialect) Placeholder(n int) string

Placeholder renders the dialect's positional placeholder token.

func (Dialect) QuoteIdent

func (d Dialect) QuoteIdent(ident string) (string, error)

QuoteIdent returns the dialect-specific quoted identifier.

func (Dialect) Supports

func (d Dialect) Supports(feature Feature) bool

Supports reports whether the dialect can render the requested feature.

type Expr

type Expr interface {
	// contains filtered or unexported methods
}

Expr is the minimal contract for SQL fragments Quarry can render.

It stays unexported in practice because only Quarry's own expression types can satisfy the interface.

type Feature

type Feature string

Feature identifies a dialect capability Quarry may need to gate.

const (
	// FeatureReturning reports whether RETURNING is supported.
	FeatureReturning Feature = "returning"
	// FeatureILike reports whether ILIKE is supported natively.
	FeatureILike Feature = "ilike"
	// FeatureAny reports whether = ANY(...) is supported.
	FeatureAny Feature = "any"
)

type Filters

type Filters []Predicate

Filters is a convenience alias for a batch of optional predicates.

type InsertBuilder

type InsertBuilder struct {
	// contains filtered or unexported fields
}

InsertBuilder renders INSERT statements for the active Quarry dialect.

func (*InsertBuilder) Columns

func (b *InsertBuilder) Columns(cols ...any) *InsertBuilder

Columns appends INSERT column expressions.

func (*InsertBuilder) Prefix

func (b *InsertBuilder) Prefix(sql string, args ...any) *InsertBuilder

Prefix appends a raw fragment before the INSERT statement.

func (*InsertBuilder) Returning

func (b *InsertBuilder) Returning(cols ...any) *InsertBuilder

Returning appends RETURNING expressions.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)

	sqlText, args, err := qq.InsertInto("users").
		Columns("email", "status").
		Values("a@example.com", "active").
		Returning("id").
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
INSERT INTO "users" ("email", "status") VALUES ($1, $2) RETURNING "id"
[a@example.com active]

func (*InsertBuilder) Rows

func (b *InsertBuilder) Rows(rows ...[]any) *InsertBuilder

Rows appends one or more explicit INSERT rows.

func (*InsertBuilder) SetMap

func (b *InsertBuilder) SetMap(values map[string]any) *InsertBuilder

SetMap converts a map into a deterministic INSERT column/value row.

Map keys are treated as trusted identifiers, validated locally, and quoted with the active dialect before rendering.

func (*InsertBuilder) Suffix

func (b *InsertBuilder) Suffix(sql string, args ...any) *InsertBuilder

Suffix appends a raw fragment after the INSERT statement.

func (*InsertBuilder) ToSQL

func (b *InsertBuilder) ToSQL() (string, []any, error)

func (*InsertBuilder) Values

func (b *InsertBuilder) Values(vals ...any) *InsertBuilder

Values appends a single INSERT row.

type Predicate

type Predicate interface {
	Expr
	// contains filtered or unexported methods
}

Predicate is a boolean SQL expression that may also be empty and therefore omitted.

func And

func And(preds ...Predicate) Predicate

And joins predicates with AND, dropping empty children.

func Any

func Any(col any, values any) Predicate

Any returns a Postgres-specific ANY predicate.

func Between

func Between(col any, low any, high any) Predicate

Between returns a BETWEEN predicate using bound low/high values.

func Eq

func Eq(col string, val any) Predicate

Eq returns a comparison predicate using =.

func Exists

func Exists(query Query) Predicate

Exists returns an EXISTS predicate for a subquery.

func Gt

func Gt(col string, val any) Predicate

Gt returns a comparison predicate using >.

func Gte

func Gte(col string, val any) Predicate

Gte returns a comparison predicate using >=.

func ILike

func ILike(col string, val any) Predicate

ILike returns a case-insensitive LIKE predicate using a bound value.

func In

func In(col any, values ...any) Predicate

In returns an IN predicate using bound values.

func IsNotNull

func IsNotNull(col string) Predicate

IsNotNull returns an IS NOT NULL predicate.

func IsNull

func IsNull(col string) Predicate

IsNull returns an IS NULL predicate.

func Like

func Like(col string, val any) Predicate

Like returns a LIKE predicate using a bound value.

func Lt

func Lt(col string, val any) Predicate

Lt returns a comparison predicate using <.

func Lte

func Lte(col string, val any) Predicate

Lte returns a comparison predicate using <=.

func Neq

func Neq(col string, val any) Predicate

Neq returns a comparison predicate using <>.

func Not

func Not(pred Predicate) Predicate

Not negates a predicate while preserving empty/no-op behavior.

func NotExists

func NotExists(query Query) Predicate

NotExists returns a NOT EXISTS predicate for a subquery.

func NotIn

func NotIn(col any, values ...any) Predicate

NotIn returns a NOT IN predicate using bound values.

func OptionalEq

func OptionalEq(col any, val any) Predicate

OptionalEq returns Eq when val is present and a no-op predicate otherwise.

func OptionalGt

func OptionalGt(col any, val any) Predicate

OptionalGt returns Gt when val is present and a no-op predicate otherwise.

func OptionalGte

func OptionalGte(col any, val any) Predicate

OptionalGte returns Gte when val is present and a no-op predicate otherwise.

func OptionalILike

func OptionalILike(col any, val any) Predicate

OptionalILike returns ILike when val is present and a no-op predicate otherwise.

func OptionalIn

func OptionalIn(col any, values ...any) Predicate

OptionalIn returns In when vals is present and a no-op predicate otherwise.

func OptionalLike

func OptionalLike(col any, val any) Predicate

OptionalLike returns Like when val is present and a no-op predicate otherwise.

func OptionalLt

func OptionalLt(col any, val any) Predicate

OptionalLt returns Lt when val is present and a no-op predicate otherwise.

func OptionalLte

func OptionalLte(col any, val any) Predicate

OptionalLte returns Lte when val is present and a no-op predicate otherwise.

func OptionalNeq

func OptionalNeq(col any, val any) Predicate

OptionalNeq returns Neq when val is present and a no-op predicate otherwise.

func Or

func Or(preds ...Predicate) Predicate

Or joins predicates with OR, dropping empty children.

func Raw

func Raw(sql string, args ...any) Predicate

Raw injects a raw SQL fragment while still binding values safely.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)

	sqlText, args, err := qq.Select(quarry.Raw("COUNT(*) FILTER (WHERE status = ?)", "active")).
		From("users").
		Where(quarry.Raw("created_at >= ?", "2024-01-01")).
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
SELECT COUNT(*) FILTER (WHERE status = $1) FROM "users" WHERE created_at >= $2
[active 2024-01-01]

func TupleIn

func TupleIn(columns []any, tuples [][]any) Predicate

TupleIn returns a composite IN predicate over multiple columns.

type Quarry

type Quarry struct {
	// contains filtered or unexported fields
}

Quarry carries the selected dialect and manufactures builders from it.

func New

func New(d Dialect) *Quarry

New creates a Quarry configured for the supplied dialect.

func (*Quarry) DeleteFrom

func (q *Quarry) DeleteFrom(table any) *DeleteBuilder

DeleteFrom starts a DELETE builder that inherits the receiver's dialect.

func (*Quarry) Dialect

func (q *Quarry) Dialect() Dialect

Dialect returns the configured dialect for the receiver.

func (*Quarry) InsertInto

func (q *Quarry) InsertInto(table any) *InsertBuilder

InsertInto starts an INSERT builder that inherits the receiver's dialect.

func (*Quarry) Select

func (q *Quarry) Select(cols ...any) *SelectBuilder

Select starts a SELECT builder that inherits the receiver's dialect.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)

	sqlText, args, err := qq.Select("id", "email").
		From("users").
		Where(quarry.Eq("status", "active")).
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
SELECT "id", "email" FROM "users" WHERE "status" = $1
[active]

func (*Quarry) Update

func (q *Quarry) Update(table any) *UpdateBuilder

Update starts an UPDATE builder that inherits the receiver's dialect.

type Query

type Query = SQLer

Query keeps the subquery-oriented API readable without adding a second contract.

type SQLer

type SQLer interface {
	ToSQL() (string, []any, error)
}

SQLer is the shared contract for anything that can render SQL and bound args.

type SelectBuilder

type SelectBuilder struct {
	// contains filtered or unexported fields
}

SelectBuilder renders SELECT statements for the active Quarry dialect.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)

	sqlText, args, err := qq.Select("id", "email", "created_at").
		From("users").
		Where(
			quarry.Eq("tenant_id", 42),
			quarry.OptionalILike("email", "%bob%"),
			quarry.OptionalEq("status", (*string)(nil)),
		).
		OrderBySafeDefault("newest", quarry.SortMap{
			"newest": "created_at DESC",
			"email":  "email ASC",
		}, "newest").
		Page(1, 25).
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
SELECT "id", "email", "created_at" FROM "users" WHERE "tenant_id" = $1 AND "email" ILIKE $2 ORDER BY created_at DESC LIMIT 25 OFFSET 0
[42 %bob%]

func (*SelectBuilder) CrossJoin

func (b *SelectBuilder) CrossJoin(expr any) *SelectBuilder

CrossJoin appends a CROSS JOIN clause.

func (*SelectBuilder) Distinct

func (b *SelectBuilder) Distinct() *SelectBuilder

Distinct toggles SELECT DISTINCT rendering.

func (*SelectBuilder) From

func (b *SelectBuilder) From(table any) *SelectBuilder

From sets the FROM clause.

func (*SelectBuilder) FullJoin

func (b *SelectBuilder) FullJoin(expr any) *SelectBuilder

FullJoin appends a FULL JOIN clause.

func (*SelectBuilder) GroupBy

func (b *SelectBuilder) GroupBy(parts ...any) *SelectBuilder

GroupBy appends GROUP BY expressions.

func (*SelectBuilder) Having

func (b *SelectBuilder) Having(preds ...Predicate) *SelectBuilder

Having appends HAVING predicates.

func (*SelectBuilder) Join

func (b *SelectBuilder) Join(expr any) *SelectBuilder

Join appends a plain JOIN clause.

func (*SelectBuilder) LeftJoin

func (b *SelectBuilder) LeftJoin(expr any) *SelectBuilder

LeftJoin appends a LEFT JOIN clause.

func (*SelectBuilder) Limit

func (b *SelectBuilder) Limit(n uint64) *SelectBuilder

Limit sets an explicit LIMIT value.

func (*SelectBuilder) LimitDefault

func (b *SelectBuilder) LimitDefault(n, fallback int) *SelectBuilder

LimitDefault applies n when it is positive, otherwise a positive fallback.

func (*SelectBuilder) Offset

func (b *SelectBuilder) Offset(n uint64) *SelectBuilder

Offset sets an explicit OFFSET value.

func (*SelectBuilder) OffsetDefault

func (b *SelectBuilder) OffsetDefault(n, fallback int) *SelectBuilder

OffsetDefault applies n when it is non-negative, otherwise a non-negative fallback.

func (*SelectBuilder) OrderBy

func (b *SelectBuilder) OrderBy(parts ...any) *SelectBuilder

OrderBy appends ORDER BY expressions or trusted fragments.

func (*SelectBuilder) OrderBySafe

func (b *SelectBuilder) OrderBySafe(input string, allowed SortMap) *SelectBuilder

OrderBySafe appends a trusted ORDER BY fragment selected from allowed.

func (*SelectBuilder) OrderBySafeDefault

func (b *SelectBuilder) OrderBySafeDefault(input string, allowed SortMap, fallback string) *SelectBuilder

OrderBySafeDefault appends the selected sort key or falls back to a trusted default.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)

	sqlText, args, err := qq.Select("id", "email").
		From("users").
		OrderBySafeDefault("newest", quarry.SortMap{
			"newest": "created_at DESC",
			"email":  "email ASC",
		}, "newest").
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
SELECT "id", "email" FROM "users" ORDER BY created_at DESC
[]

func (*SelectBuilder) Page

func (b *SelectBuilder) Page(page, perPage int) *SelectBuilder

Page applies one-based page/per-page pagination and derives LIMIT/OFFSET.

func (*SelectBuilder) Prefix

func (b *SelectBuilder) Prefix(sql string, args ...any) *SelectBuilder

Prefix appends a raw fragment before the SELECT statement.

func (*SelectBuilder) RightJoin

func (b *SelectBuilder) RightJoin(expr any) *SelectBuilder

RightJoin appends a RIGHT JOIN clause.

func (*SelectBuilder) Suffix

func (b *SelectBuilder) Suffix(sql string, args ...any) *SelectBuilder

Suffix appends a raw fragment after the SELECT statement.

func (*SelectBuilder) ToSQL

func (b *SelectBuilder) ToSQL() (string, []any, error)

func (*SelectBuilder) Where

func (b *SelectBuilder) Where(preds ...Predicate) *SelectBuilder

Where appends WHERE predicates.

func (*SelectBuilder) WhereIf

func (b *SelectBuilder) WhereIf(cond bool, pred Predicate) *SelectBuilder

WhereIf appends pred only when cond is true and the predicate is non-empty.

type SortMap

type SortMap map[string]string

SortMap maps caller-facing sort keys to trusted ORDER BY fragments.

type Table

type Table struct {
	// contains filtered or unexported fields
}

Table identifies a SQL table name and can produce qualified columns from it.

func T

func T(name string) Table

T constructs a safe table helper for SQL rendering and column qualification.

func TableName

func TableName(name string) Table

TableName is a named alias for T.

func (Table) As

func (t Table) As(alias string) Table

As returns a copy of the table with the supplied alias.

func (Table) C

func (t Table) C(name string) Column

C returns a column helper qualified by the receiver table.

func (Table) Col

func (t Table) Col(name string) Column

Col returns a column helper qualified by the receiver table (wraper).

type UpdateBuilder

type UpdateBuilder struct {
	// contains filtered or unexported fields
}

UpdateBuilder renders UPDATE statements for the active Quarry dialect.

func (*UpdateBuilder) Prefix

func (b *UpdateBuilder) Prefix(sql string, args ...any) *UpdateBuilder

Prefix appends a raw fragment before the UPDATE statement.

func (*UpdateBuilder) Returning

func (b *UpdateBuilder) Returning(cols ...any) *UpdateBuilder

Returning appends RETURNING expressions.

func (*UpdateBuilder) Set

func (b *UpdateBuilder) Set(col any, val any) *UpdateBuilder

Set appends an explicit SET clause.

func (*UpdateBuilder) SetIf

func (b *UpdateBuilder) SetIf(cond bool, col any, val any) *UpdateBuilder

SetIf appends a SET clause only when cond is true.

func (*UpdateBuilder) SetMap

func (b *UpdateBuilder) SetMap(values map[string]any) *UpdateBuilder

SetMap appends deterministic SET clauses from a map.

Map keys are treated as trusted identifiers, validated locally, and quoted with the active dialect before rendering.

func (*UpdateBuilder) SetOptional

func (b *UpdateBuilder) SetOptional(col any, val any) *UpdateBuilder

SetOptional appends a SET clause only when val is a present, non-empty value.

Example
package main

import (
	"fmt"

	quarry "github.com/sphireinc/quarry"
)

func main() {
	qq := quarry.New(quarry.Postgres)
	enabled := true

	sqlText, args, err := qq.Update("users").
		SetOptional("name", "Quarry User").
		SetOptional("email", "user@example.com").
		SetIf(enabled, "enabled", enabled).
		Where(quarry.Eq("id", 7)).
		Returning("id").
		ToSQL()
	if err != nil {
		panic(err)
	}

	fmt.Println(sqlText)
	fmt.Println(args)
}
Output:
UPDATE "users" SET "name" = $1, "email" = $2, "enabled" = $3 WHERE "id" = $4 RETURNING "id"
[Quarry User user@example.com true 7]

func (*UpdateBuilder) Suffix

func (b *UpdateBuilder) Suffix(sql string, args ...any) *UpdateBuilder

Suffix appends a raw fragment after the UPDATE statement.

func (*UpdateBuilder) ToSQL

func (b *UpdateBuilder) ToSQL() (string, []any, error)

func (*UpdateBuilder) Where

func (b *UpdateBuilder) Where(preds ...Predicate) *UpdateBuilder

Where appends UPDATE predicates.

func (*UpdateBuilder) WhereIf

func (b *UpdateBuilder) WhereIf(cond bool, pred Predicate) *UpdateBuilder

WhereIf appends pred only when cond is true and the predicate is non-empty.

Directories

Path Synopsis
Package codex provides Quarry's optional named-query and recipe registry.
Package codex provides Quarry's optional named-query and recipe registry.
examples
basic_select command
Package main prints a minimal Quarry SELECT query.
Package main prints a minimal Quarry SELECT query.
dynamic_filters command
Package main prints a Quarry query with optional filters and safe paging.
Package main prints a Quarry query with optional filters and safe paging.
partial_update command
Package main prints a Quarry UPDATE statement with optional fields.
Package main prints a Quarry UPDATE statement with optional fields.
raw_sql_codex command
Package main prints Quarry raw SQL and Codex binding examples.
Package main prints Quarry raw SQL and Codex binding examples.
scan_many command
Package main prints many Quarry rows scanned into Go structs.
Package main prints many Quarry rows scanned into Go structs.
scan_one command
Package main prints a single Quarry row scanned into a Go struct.
Package main prints a single Quarry row scanned into a Go struct.
scan_with_quarry_query command
Package main prints a Quarry query scanned into a scalar result.
Package main prints a Quarry query scanned into a scalar result.
internal
Package scan executes Quarry queries and scans rows into Go values.
Package scan executes Quarry queries and scans rows into Go values.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL