Documentation
¶
Overview ¶
Package query is part of the GoFastr framework. See https://github.com/DonaldMurillo/gofastr for documentation.
Index ¶
- func IsPostgres(db *sql.DB) bool
- func MustIdent(s string) string
- func ParseDBTime(src any) (time.Time, error)
- func ParseDBTimeString(raw string) (time.Time, error)
- func ProbeSQLiteBindLayout(ctx context.Context, db *sql.DB) string
- func QuoteIdent(s string) string
- func ReservedIdent(name string) bool
- func SafeIdent(s string) (string, error)
- func SafeQuote(s string) (string, error)
- func SafeTableName(name string) bool
- func Transaction(ctx context.Context, db *sql.DB, fn func(tx *sql.Tx) error) error
- type CountBuilder
- type DeleteBuilder
- type InsertBuilder
- type QueryBuilder
- func (qb *QueryBuilder) Build() (string, []any)
- func (qb *QueryBuilder) Cursor(field string, value any, dir string) *QueryBuilder
- func (qb *QueryBuilder) From(table string) *QueryBuilder
- func (qb *QueryBuilder) Join(table, on string) *QueryBuilder
- func (qb *QueryBuilder) LeftJoin(table, on string) *QueryBuilder
- func (qb *QueryBuilder) Limit(n int) *QueryBuilder
- func (qb *QueryBuilder) Offset(n int) *QueryBuilder
- func (qb *QueryBuilder) OrWhere(condition string, args ...any) *QueryBuilder
- func (qb *QueryBuilder) Order(column string, dir string) *QueryBuilder
- func (qb *QueryBuilder) Where(condition string, args ...any) *QueryBuilder
- type UpdateBuilder
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsPostgres ¶ added in v0.86.0
IsPostgres reports whether the database behind db answers SELECT version() with a PostgreSQL banner. A driver that errors on the probe or answers with anything else (SQLite drivers either fail on version() or return a SQLite banner) reports false, so callers treat "not Postgres" as the SQLite-compatible path.
It is the canonical form of the probe formerly duplicated as core/a2a's detectSQLDialect, framework/outbox's detectDialect, and battery/queue's detectDBDialect; those now map this bool onto their local dialect enums. It is deliberately a single best-effort shot: boot-critical callers that must fail closed on an unreachable database use framework/migrate's retrying probe (detectDialectFailClosed) instead.
func MustIdent ¶
MustIdent is like SafeIdent but panics on invalid identifiers. Use in init/config-time code where the identifier is a hard-coded constant.
func ParseDBTime ¶ added in v0.86.0
ParseDBTime converts a database time-column value, as handed to Scan, into a time.Time. It accepts the shapes the Go SQL drivers produce for time columns — time.Time, non-nil *time.Time, and the text layouts SQLite drivers fall back to — and rejects everything else (including a nil *time.Time) with an error.
It replaces the package-local parsers formerly duplicated as framework/outbox's outboxTime/parseOutboxTime and battery/queue's queueTime/parseQueueTime, which differed only in their error prefixes.
func ParseDBTimeString ¶ added in v0.86.0
ParseDBTimeString parses the text layouts a SQLite driver may hand back for a time column: RFC3339 (with or without fractional seconds) and the space-separated forms mattn/go-sqlite3 writes. It is the string half of ParseDBTime, extracted for callers that already hold the stored text.
func ProbeSQLiteBindLayout ¶ added in v0.86.0
ProbeSQLiteBindLayout detects the text layout the connected SQLite driver produces when a time.Time is bound as a parameter: the pure driver binds RFC3339Nano, mattn/go-sqlite3 a space-separated form. Callers whose SQL predicates compare stored time text lexicographically use the probed layout as their canonical normalization target, and rows already in it are canonical for this host and skipped, which keeps normalization idempotent on either driver. An unrecognized probe result falls back to RFC3339Nano (a rewrite that binds time.Time values still self-corrects, because the driver formats the bound value).
It replaces the identical package-local probes formerly duplicated as framework/outbox's (Outbox).probeBindLayout and battery/queue's dead (DBQueue).probeBindLayout.
func QuoteIdent ¶
QuoteIdent wraps an identifier in double-quotes with internal quotes escaped. The caller is responsible for validating the identifier first (via SafeIdent).
QuoteIdent("users") → "users"
QuoteIdent(`weird"name`) → "weird""name"
func ReservedIdent ¶ added in v0.86.0
ReservedIdent reports whether name, case-insensitively, is a SQL reserved word or common system-table name that must not be used as a bare table name. It replaces the reserved-word checks formerly inlined in the package-local safeIdent validators of core/middleware, core/featureflag, and battery/webhook.
func SafeIdent ¶
SafeIdent validates that s is a safe SQL identifier and returns it unchanged (QuoteIdent adds the quotes). This prevents SQL injection when table or column names must be interpolated into queries (they can't be parameterized with $1 placeholders).
Returns an error if s contains characters outside [a-zA-Z0-9_.].
func SafeTableName ¶ added in v0.86.0
SafeTableName reports whether name is acceptable as a bare (single- segment) table name: it must pass SafeIdent's character class and leading-letter rule, contain no dot (schema.table is not a bare name), be at most 64 bytes, and not be ReservedIdent.
It replaces the package-local safeIdent validators formerly duplicated in core/middleware (idempotency store), core/featureflag (SQL store), and battery/webhook (subscriber/delivery/inbound stores). The webhook validator was weaker (no leading-character rule, no reserved words); all three now share this one contract.
Types ¶
type CountBuilder ¶
type CountBuilder struct {
// contains filtered or unexported fields
}
CountBuilder builds a SELECT COUNT(*) query with parameterized placeholders.
func Count ¶
func Count(table string) *CountBuilder
Count creates a new CountBuilder for the given table. wheres/args are pre-capped. See query.Select's rationale (CRUD List adds ~4-5 Where clauses per count + data builder; without the hint each grows through 1 → 2 → 4 → 8 across the request).
func (*CountBuilder) Build ¶
func (cb *CountBuilder) Build() (string, []any)
Build produces the final parameterized SQL and argument slice.
func (*CountBuilder) Where ¶
func (cb *CountBuilder) Where(condition string, args ...any) *CountBuilder
Where appends a WHERE condition (ANDed with previous conditions).
type DeleteBuilder ¶
type DeleteBuilder struct {
// contains filtered or unexported fields
}
DeleteBuilder builds a DELETE query with parameterized placeholders.
func Delete ¶
func Delete(table string) *DeleteBuilder
Delete creates a new DeleteBuilder for the given table.
func (*DeleteBuilder) Build ¶
func (db *DeleteBuilder) Build() (string, []any)
Build produces the final parameterized SQL and argument slice.
func (*DeleteBuilder) Where ¶
func (db *DeleteBuilder) Where(condition string, args ...any) *DeleteBuilder
Where appends a WHERE condition (ANDed with previous conditions).
type InsertBuilder ¶
type InsertBuilder struct {
// contains filtered or unexported fields
}
InsertBuilder builds an INSERT query with parameterized placeholders.
func Insert ¶
func Insert(table string) *InsertBuilder
Insert creates a new InsertBuilder for the given table.
func (*InsertBuilder) Build ¶
func (ib *InsertBuilder) Build() (string, []any)
Build produces the final parameterized SQL and argument slice.
func (*InsertBuilder) Columns ¶
func (ib *InsertBuilder) Columns(cols ...string) *InsertBuilder
Columns sets the columns to insert into.
func (*InsertBuilder) Returning ¶
func (ib *InsertBuilder) Returning(cols ...string) *InsertBuilder
Returning adds a RETURNING clause.
func (*InsertBuilder) Values ¶
func (ib *InsertBuilder) Values(vals ...any) *InsertBuilder
Values sets the values to insert.
type QueryBuilder ¶
type QueryBuilder struct {
// contains filtered or unexported fields
}
QueryBuilder builds a SELECT query with parameterized placeholders.
func Select ¶
func Select(columns ...string) *QueryBuilder
Select creates a new QueryBuilder selecting the given columns.
wheres/args are pre-capped (defaultWhereCap / defaultArgCap) because the CRUD List handler adds ~4-5 WHERE clauses per query × 2 queries (count + data). Starting at nil forces repeated slice growth (1 → 2 → 4 → 8) for the common case; a small capacity hint lets the runtime allocate once at the expected size.
func (*QueryBuilder) Build ¶
func (qb *QueryBuilder) Build() (string, []any)
Build produces the final parameterized SQL and argument slice. It does not mutate the QueryBuilder: safe to call multiple times.
func (*QueryBuilder) Cursor ¶
func (qb *QueryBuilder) Cursor(field string, value any, dir string) *QueryBuilder
Cursor adds keyset/cursor-based pagination. dir "forward" → WHERE field > value, dir "backward" → WHERE field < value.
func (*QueryBuilder) From ¶
func (qb *QueryBuilder) From(table string) *QueryBuilder
From sets the table to query.
func (*QueryBuilder) Join ¶
func (qb *QueryBuilder) Join(table, on string) *QueryBuilder
Join adds an INNER JOIN clause.
func (*QueryBuilder) LeftJoin ¶
func (qb *QueryBuilder) LeftJoin(table, on string) *QueryBuilder
LeftJoin adds a LEFT JOIN clause.
func (*QueryBuilder) Limit ¶
func (qb *QueryBuilder) Limit(n int) *QueryBuilder
Limit sets the LIMIT clause.
func (*QueryBuilder) Offset ¶
func (qb *QueryBuilder) Offset(n int) *QueryBuilder
Offset sets the OFFSET clause.
func (*QueryBuilder) OrWhere ¶
func (qb *QueryBuilder) OrWhere(condition string, args ...any) *QueryBuilder
OrWhere appends a WHERE condition (ORed with previous conditions).
func (*QueryBuilder) Order ¶
func (qb *QueryBuilder) Order(column string, dir string) *QueryBuilder
Order adds an ORDER BY clause.
func (*QueryBuilder) Where ¶
func (qb *QueryBuilder) Where(condition string, args ...any) *QueryBuilder
Where appends a WHERE condition (ANDed with previous conditions).
type UpdateBuilder ¶
type UpdateBuilder struct {
// contains filtered or unexported fields
}
UpdateBuilder builds an UPDATE query with parameterized placeholders.
func Update ¶
func Update(table string) *UpdateBuilder
Update creates a new UpdateBuilder for the given table.
func (*UpdateBuilder) Build ¶
func (ub *UpdateBuilder) Build() (string, []any)
Build produces the final parameterized SQL and argument slice.
func (*UpdateBuilder) Returning ¶
func (ub *UpdateBuilder) Returning(cols ...string) *UpdateBuilder
Returning adds a RETURNING clause.
func (*UpdateBuilder) Set ¶
func (ub *UpdateBuilder) Set(column string, value any) *UpdateBuilder
Set adds a column = value assignment.
func (*UpdateBuilder) Where ¶
func (ub *UpdateBuilder) Where(condition string, args ...any) *UpdateBuilder
Where appends a WHERE condition (ANDed with previous conditions).