metaquery

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Apr 21, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package metaquery provides runtime metadata types and a CTE-based query builder for queries generated by sqlc-go-codegen-metaquery.

A generated Query value captures the column/arg shape of a sqlc query plus its original SQL text. Wrap one with Wrap() to compose additional filters, ordering, pagination, grouping, and aggregations on top without rewriting the original SQL — the original is embedded verbatim as a CTE.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Validate

func Validate[T any](b *Builder) error

Validate checks that T's exported fields map cleanly onto b.OutputColumns(). A field matches a column by its `db` tag, falling back to snake_case of the field name. Drift in either direction (field with no column, column with no field) is an error.

Called automatically by mqpgx.Scan[T]; call directly if you want to fail fast without issuing a query.

func ValidateFilter

func ValidateFilter(q *Query, f Filter) error

ValidateFilter checks that f is a sensible filter for q: the column exists, the op is permitted for the column's Go type, and the value is type- compatible (with JSON-friendly leniency — float64 for int columns, RFC3339 strings for time columns).

Raw-expression filters (f.IsExpr()) are passed through unchecked.

Called automatically by Builder.ApplyFilter; call directly when you want to validate a filter you just deserialized from JSON without mutating a builder.

Types

type AnyCol

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

AnyCol is the fallback for column kinds we don't have dedicated typing for (arrays, enums, pgtype.UUID, pgtype.Numeric, domain types, ...). Ops take `any` — use sparingly.

func NewAnyCol

func NewAnyCol(name string) AnyCol

func (AnyCol) Asc

func (c AnyCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (AnyCol) Col

func (c AnyCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (AnyCol) Desc

func (c AnyCol) Desc() OrderBy

func (AnyCol) Eq

func (c AnyCol) Eq(v any) Filter

func (AnyCol) Ge

func (c AnyCol) Ge(v any) Filter

func (AnyCol) Gt

func (c AnyCol) Gt(v any) Filter

func (AnyCol) IsNotNull

func (c AnyCol) IsNotNull() Filter

func (AnyCol) IsNull

func (c AnyCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

func (AnyCol) Le

func (c AnyCol) Le(v any) Filter

func (AnyCol) Lt

func (c AnyCol) Lt(v any) Filter

func (AnyCol) Ne

func (c AnyCol) Ne(v any) Filter

type Arg

type Arg struct {
	Position    int    `json:"position"`
	Name        string `json:"name,omitempty"`
	GoType      string `json:"go_type,omitempty"`
	DBType      string `json:"db_type,omitempty"`
	NotNull     bool   `json:"not_null,omitempty"`
	IsArray     bool   `json:"is_array,omitempty"`
	IsSqlcSlice bool   `json:"is_sqlc_slice,omitempty"`
}

Arg describes one positional argument of the underlying query.

type BoolCol

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

BoolCol wraps bool / pgtype.Bool. IsTrue / IsFalse read nicer than Eq(true).

func NewBoolCol

func NewBoolCol(name string) BoolCol

func (BoolCol) Asc

func (c BoolCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (BoolCol) Col

func (c BoolCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (BoolCol) Desc

func (c BoolCol) Desc() OrderBy

func (BoolCol) Eq

func (c BoolCol) Eq(v bool) Filter

func (BoolCol) IsFalse

func (c BoolCol) IsFalse() Filter

func (BoolCol) IsNotNull

func (c BoolCol) IsNotNull() Filter

func (BoolCol) IsNull

func (c BoolCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

func (BoolCol) IsTrue

func (c BoolCol) IsTrue() Filter

type Builder

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

Builder composes filters, projection, grouping, aggregations, ordering, and pagination on top of a Query. Build returns the final SQL wrapping the original query as a CTE, plus the full positional argument slice.

Zero value is not usable; construct with Wrap.

func Wrap

func Wrap(q *Query, baseArgs ...any) *Builder

Wrap creates a Builder over q. baseArgs are the positional arguments for the original query ($1..$N); the Builder's own added arguments renumber to $N+1 and up.

func (*Builder) Agg

func (b *Builder) Agg(alias, expr, goType string) *Builder

Agg adds an aggregate to the projection. alias is the output column name, expr is raw SQL, goType is the Go type of the result (used when building Meta.Columns and validating Into[T] shapes).

func (*Builder) ApplyFilter

func (b *Builder) ApplyFilter(f Filter) *Builder

ApplyFilter appends a Filter to the WHERE clause. See Filter for the two valid shapes. Validates via ValidateFilter; accumulated errors surface at Build time.

func (*Builder) ApplyFilters

func (b *Builder) ApplyFilters(fs []Filter) *Builder

ApplyFilters is a convenience for applying a slice of filters.

func (*Builder) ApplyHaving

func (b *Builder) ApplyHaving(f Filter) *Builder

ApplyHaving appends a Filter to the HAVING clause. Aggregate expressions are common in HAVING so raw-expr filters are typical here; structured filters go through the same ValidateFilter check as WHERE.

func (*Builder) ApplyOrder

func (b *Builder) ApplyOrder(o OrderBy) *Builder

ApplyOrder appends an OrderBy. Exactly one of Column/Expr must be set.

func (*Builder) ApplyOrders

func (b *Builder) ApplyOrders(os []OrderBy) *Builder

ApplyOrders is a convenience for a slice of OrderBy entries.

func (*Builder) ApplyPagination

func (b *Builder) ApplyPagination(r PageRequest) *Builder

ApplyPagination drives pagination from a structured request.

func (*Builder) Avg

func (b *Builder) Avg(alias, col string) *Builder

func (*Builder) Build

func (b *Builder) Build() (string, []any, error)

Build assembles the final SQL and argument slice.

func (*Builder) BuildCount

func (b *Builder) BuildCount() (string, []any, error)

BuildCount returns a SELECT count(*) query over the same CTE + WHERE filters (but without GROUP BY / ORDER BY / LIMIT / OFFSET). Aggregation builders (groupBy non-empty) wrap the whole projection so distinct groups are counted.

func (*Builder) Count

func (b *Builder) Count(alias string) *Builder

Count adds `count(*) AS <alias>` projecting int64 NOT NULL.

func (*Builder) CountOf

func (b *Builder) CountOf(alias, col string) *Builder

CountOf adds `count(<col>) AS <alias>` projecting int64 NOT NULL. col is whitelisted.

func (*Builder) GroupBy

func (b *Builder) GroupBy(cols ...string) *Builder

GroupBy appends GROUP BY columns, whitelisted.

func (*Builder) GroupByExpr added in v1.0.0

func (b *Builder) GroupByExpr(alias, expr, goType string, args ...any) *Builder

GroupByExpr appends a raw SQL expression to the GROUP BY clause. The result is projected as `<expr> AS <alias>` in the SELECT and appears in OutputColumns with the given goType. Use ? placeholders for bound args. This is the escape hatch for grouping by computed expressions (e.g. JSON field extraction: `GroupByExpr("group_value", "context_json->>?", "string", key)`).

func (*Builder) Having

func (b *Builder) Having(expr string, args ...any) *Builder

Having appends a raw HAVING predicate.

func (*Builder) Limit

func (b *Builder) Limit(n int) *Builder

Limit sets the LIMIT value.

func (*Builder) Max

func (b *Builder) Max(alias, col string) *Builder

func (*Builder) Meta

func (b *Builder) Meta() Meta

Meta returns the envelope describing the builder's applied state. Meta does NOT include Pagination.Total — that's populated by the adapter after the count query runs.

func (*Builder) Min

func (b *Builder) Min(alias, col string) *Builder

func (*Builder) Offset

func (b *Builder) Offset(n int) *Builder

Offset sets the OFFSET value.

func (*Builder) OrderBy

func (b *Builder) OrderBy(col string, dir Direction) *Builder

OrderBy appends an ORDER BY clause, whitelisting col against q.Columns.

func (*Builder) OrderByExpr

func (b *Builder) OrderByExpr(expr string) *Builder

OrderByExpr appends a raw ORDER BY fragment (no whitelist).

func (*Builder) OutputColumns

func (b *Builder) OutputColumns() []Column

OutputColumns returns the ordered set of columns the builder's final SELECT will produce. Used for Meta and for Into[T] validation.

func (*Builder) Paginate

func (b *Builder) Paginate(page, size int) *Builder

Paginate is a convenience for Limit + Offset (and WithTotal when req.Total is set). Page is 0-indexed.

func (*Builder) Select

func (b *Builder) Select(cols ...string) *Builder

Select restricts the projection to the given columns, whitelisted. Without a Select (or GroupBy/Agg), projection defaults to *.

func (*Builder) Sum

func (b *Builder) Sum(alias, col string) *Builder

Sum, Avg, Min, Max project the same GoType as the source column but nullable (aggregates over empty groups return NULL). Use the Agg escape hatch with coalesce(...) to force NOT NULL.

func (*Builder) WantsTotal

func (b *Builder) WantsTotal() bool

WantsTotal reports whether the caller requested a total-row count (see WithTotal / ApplyPagination). Adapters use this to run a follow-up COUNT.

func (*Builder) Where

func (b *Builder) Where(col string, op Op, val any) *Builder

Where appends `<col> <op> ?`, whitelisting col against q.Columns. Prefer passing a typed Op constant (OpEq, OpILike, ...) — raw string literals still work because they're untyped constants.

func (*Builder) WhereExpr

func (b *Builder) WhereExpr(expr string, args ...any) *Builder

WhereExpr appends a raw predicate expression using ? placeholders. Caller owns the safety of expr.

func (*Builder) WithTotal

func (b *Builder) WithTotal() *Builder

WithTotal opts into running a second COUNT(*) query when the builder is executed; result populates Meta.Pagination.Total.

type BytesCol

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

BytesCol wraps []byte columns.

func NewBytesCol

func NewBytesCol(name string) BytesCol

func (BytesCol) Asc

func (c BytesCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (BytesCol) Col

func (c BytesCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (BytesCol) Desc

func (c BytesCol) Desc() OrderBy

func (BytesCol) Eq

func (c BytesCol) Eq(v []byte) Filter

func (BytesCol) IsNotNull

func (c BytesCol) IsNotNull() Filter

func (BytesCol) IsNull

func (c BytesCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

func (BytesCol) Ne

func (c BytesCol) Ne(v []byte) Filter

type Column

type Column struct {
	Name         string `json:"name"`
	OriginalName string `json:"original_name,omitempty"`
	GoType       string `json:"go_type,omitempty"`
	DBType       string `json:"db_type,omitempty"`
	NotNull      bool   `json:"not_null,omitempty"`
	IsArray      bool   `json:"is_array,omitempty"`
	Table        string `json:"table,omitempty"`
	TableAlias   string `json:"table_alias,omitempty"`
}

Column describes one result column of a query or builder projection.

type Direction

type Direction string

Direction for OrderBy.

const (
	Asc  Direction = "ASC"
	Desc Direction = "DESC"
)

type Filter

type Filter struct {
	Column string `json:"column,omitempty"`
	Op     Op     `json:"op,omitempty"`
	Value  any    `json:"value,omitempty"`
	Expr   string `json:"expr,omitempty"`
	Args   []any  `json:"args,omitempty"`
}

Filter is a predicate applied to a wrapped query. It's bidirectional: pass it into the builder via ApplyFilter to add WHERE/HAVING clauses, and read it back from Meta.Where/Meta.Having after execution to inspect what was applied (e.g. for rendering active filters in a UI).

Use exactly one of:

  • (Column, Op, Value) — structured; Column is whitelisted against the query's output columns.
  • (Expr, Args) — raw SQL fragment with ? placeholders (renumbered at Build time).

func (Filter) IsExpr

func (f Filter) IsExpr() bool

IsExpr reports whether the filter is a raw expression (no Column).

type FloatCol

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

FloatCol wraps float32/float64 and pgtype.Float4/8.

func NewFloatCol

func NewFloatCol(name string) FloatCol

func (FloatCol) Asc

func (c FloatCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (FloatCol) Between

func (c FloatCol) Between(lo, hi float64) Filter

func (FloatCol) Col

func (c FloatCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (FloatCol) Desc

func (c FloatCol) Desc() OrderBy

func (FloatCol) Eq

func (c FloatCol) Eq(v float64) Filter

func (FloatCol) Ge

func (c FloatCol) Ge(v float64) Filter

func (FloatCol) Gt

func (c FloatCol) Gt(v float64) Filter

func (FloatCol) IsNotNull

func (c FloatCol) IsNotNull() Filter

func (FloatCol) IsNull

func (c FloatCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

func (FloatCol) Le

func (c FloatCol) Le(v float64) Filter

func (FloatCol) Lt

func (c FloatCol) Lt(v float64) Filter

func (FloatCol) Ne

func (c FloatCol) Ne(v float64) Filter

type IntCol

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

IntCol wraps int/int16/int32/int64 and pgtype.Int2/4/8. Values are taken as int64; Go's untyped integer constants make callsites ergonomic (c.Id.Eq(42) compiles because 42 is untyped).

func NewIntCol

func NewIntCol(name string) IntCol

func (IntCol) Asc

func (c IntCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (IntCol) Between

func (c IntCol) Between(lo, hi int64) Filter

func (IntCol) Col

func (c IntCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (IntCol) Desc

func (c IntCol) Desc() OrderBy

func (IntCol) Eq

func (c IntCol) Eq(v int64) Filter

func (IntCol) Ge

func (c IntCol) Ge(v int64) Filter

func (IntCol) Gt

func (c IntCol) Gt(v int64) Filter

func (IntCol) In

func (c IntCol) In(vs ...int64) Filter

func (IntCol) IsNotNull

func (c IntCol) IsNotNull() Filter

func (IntCol) IsNull

func (c IntCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

func (IntCol) Le

func (c IntCol) Le(v int64) Filter

func (IntCol) Lt

func (c IntCol) Lt(v int64) Filter

func (IntCol) Ne

func (c IntCol) Ne(v int64) Filter

type Meta

type Meta struct {
	Columns    []Column    `json:"columns"`
	Pagination *Pagination `json:"pagination,omitempty"`
	Where      []Filter    `json:"where,omitempty"`
	Having     []Filter    `json:"having,omitempty"`
	GroupBy    []string    `json:"group_by,omitempty"`
	OrderBy    []OrderBy   `json:"order_by,omitempty"`
}

Meta is the envelope describing a builder's output shape and the filters that were applied. Safe to JSON-serialize as the body of an API response.

type Op

type Op string

Op is a named string type for structured filter operators. Predefined constants (OpEq, OpILike, ...) are preferred over raw strings; the typed parameter catches op typos at compile time when callers use constants. Raw string literals still work due to untyped-constant assignability.

const (
	OpEq        Op = "="
	OpNe        Op = "!="
	OpLt        Op = "<"
	OpLe        Op = "<="
	OpGt        Op = ">"
	OpGe        Op = ">="
	OpLike      Op = "LIKE"
	OpILike     Op = "ILIKE"
	OpIn        Op = "IN"
	OpIsNull    Op = "IS NULL"
	OpIsNotNull Op = "IS NOT NULL"
)

type OrderBy

type OrderBy struct {
	Column string    `json:"column,omitempty"`
	Dir    Direction `json:"dir,omitempty"`
	Expr   string    `json:"expr,omitempty"`
}

OrderBy is one ORDER BY entry. Structured form uses Column+Dir; raw form uses Expr.

type PageRequest

type PageRequest struct {
	Page  int  `json:"page,omitempty"`
	Size  int  `json:"size,omitempty"`
	Total bool `json:"total,omitempty"`
}

PageRequest describes a pagination + total-count request. Size of 0 means no LIMIT. Total=true causes a second COUNT(*) query to populate Pagination.Total when the builder is executed.

type Pagination

type Pagination struct {
	Limit  int   `json:"limit,omitempty"`
	Offset int   `json:"offset,omitempty"`
	Total  int64 `json:"total,omitempty"` // -1 if not computed
}

Pagination is the applied pagination state returned in Meta.

type Query

type Query struct {
	Name    string   `json:"name"`
	Cmd     string   `json:"cmd"`
	SQL     string   `json:"sql"`
	Source  string   `json:"source,omitempty"`
	Columns []Column `json:"columns,omitempty"`
	Args    []Arg    `json:"args,omitempty"`
	Table   *Table   `json:"table,omitempty"`
}

Query is the per-query metadata emitted alongside sqlc's generated code.

func (*Query) HasColumn

func (q *Query) HasColumn(name string) bool

HasColumn reports whether name matches any column's Name or OriginalName.

type Result

type Result struct {
	Data [][]any `json:"data"`
	Meta Meta    `json:"meta"`
}

Result is the untyped envelope from mqpgx.Run — each row is a positional []any matching Meta.Columns.

type Table

type Table struct {
	Catalog string `json:"catalog,omitempty"`
	Schema  string `json:"schema,omitempty"`
	Name    string `json:"name"`
}

Table identifies the insert target for :copyfrom queries.

type TextCol

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

TextCol wraps string / pgtype.Text / pgtype.Varchar columns.

func NewTextCol

func NewTextCol(name string) TextCol

func (TextCol) Asc

func (c TextCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (TextCol) Col

func (c TextCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (TextCol) Desc

func (c TextCol) Desc() OrderBy

func (TextCol) Eq

func (c TextCol) Eq(v string) Filter

func (TextCol) ILike

func (c TextCol) ILike(v string) Filter

func (TextCol) In

func (c TextCol) In(vs ...string) Filter

func (TextCol) IsNotNull

func (c TextCol) IsNotNull() Filter

func (TextCol) IsNull

func (c TextCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

func (TextCol) Like

func (c TextCol) Like(v string) Filter

func (TextCol) Ne

func (c TextCol) Ne(v string) Filter

type TimeCol

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

TimeCol wraps time.Time and pgtype.Timestamp/Timestamptz/Date/Time.

func NewTimeCol

func NewTimeCol(name string) TimeCol

func (TimeCol) After

func (c TimeCol) After(v time.Time) Filter

func (TimeCol) Asc

func (c TimeCol) Asc() OrderBy

Asc / Desc produce OrderBy entries for the builder's ApplyOrder method.

func (TimeCol) Before

func (c TimeCol) Before(v time.Time) Filter

func (TimeCol) Between

func (c TimeCol) Between(lo, hi time.Time) Filter

func (TimeCol) Col

func (c TimeCol) Col() string

Col returns the column name this reference points at. Useful for forwarding to GroupBy/Select which take plain strings:

b.GroupBy(db.ListAuthorsCols.Name.Col())

func (TimeCol) Desc

func (c TimeCol) Desc() OrderBy

func (TimeCol) Eq

func (c TimeCol) Eq(v time.Time) Filter

func (TimeCol) IsNotNull

func (c TimeCol) IsNotNull() Filter

func (TimeCol) IsNull

func (c TimeCol) IsNull() Filter

IsNull / IsNotNull emit a value-less WHERE/HAVING fragment via the raw-expr path (OpIsNull/OpIsNotNull on Filter renders the same, but IS NULL rarely reads as well through the structured path).

type TypedResult

type TypedResult[T any] struct {
	Data []T  `json:"data"`
	Meta Meta `json:"meta"`
}

TypedResult is the typed envelope from mqpgx.Scan[T].

Directories

Path Synopsis
mqpgx module

Jump to

Keyboard shortcuts

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