Documentation
¶
Overview ¶
Package orm is a small SQL-first ORM built on database/sql and sqlx.
It keeps SQL visible, supports MySQL and PostgreSQL, enforces tenant scope for models that declare a tenant field, and wires gcosid for primary keys.
Index ¶
- Variables
- func SchemaSQL(model *Model, dialect Dialect) (string, error)
- type Cond
- func Eq(column string, value any) Cond
- func Gt(column string, value any) Cond
- func In(column string, values ...any) Cond
- func IsNull(column string) Cond
- func Like(column, pattern string) Cond
- func Lt(column string, value any) Cond
- func Ne(column string, value any) Cond
- func Raw(where string, args ...any) Cond
- type DB
- type Dialect
- type Field
- type Model
- type Query
- func (q *Query[T]) All(ctx context.Context) ([]T, error)
- func (q *Query[T]) Count(ctx context.Context) (int64, error)
- func (q *Query[T]) First(ctx context.Context) (*T, error)
- func (q *Query[T]) Limit(limit int) *Query[T]
- func (q *Query[T]) Offset(offset int) *Query[T]
- func (q *Query[T]) OrderBy(column string, desc bool) *Query[T]
- func (q *Query[T]) Page(number, size int) *Query[T]
- func (q *Query[T]) Preload(name string, related relationLoader) *Query[T]
- func (q *Query[T]) Unscoped() *Query[T]
- func (q *Query[T]) Where(conds ...Cond) *Query[T]
- type Relation
- type RelationKind
- type Repo
- func (r *Repo[T]) Create(ctx context.Context, entity *T) error
- func (r *Repo[T]) Delete(ctx context.Context, id int64) error
- func (r *Repo[T]) Get(ctx context.Context, id int64) (*T, error)
- func (r *Repo[T]) Model() *Model
- func (r *Repo[T]) Purge(ctx context.Context, id int64) error
- func (r *Repo[T]) Query() *Query[T]
- func (r *Repo[T]) Restore(ctx context.Context, id int64) error
- func (r *Repo[T]) Unscoped() *Query[T]
- func (r *Repo[T]) Update(ctx context.Context, entity *T) error
- type RepoOption
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotFound = gableerrors.New("orm_not_found", "record not found").WithStatus(404) ErrTenantMismatch = gableerrors.New("orm_tenant_mismatch", "record tenant does not match the context").WithStatus(400) ErrIDRequired = gableerrors.New("orm_id_required", "primary key is required").WithStatus(400) ErrInvalidModel = gableerrors.New("orm_invalid_model", "invalid model").WithStatus(500) )
Framework errors.
Functions ¶
Types ¶
type Cond ¶
type Cond struct {
// contains filtered or unexported fields
}
Cond is one WHERE condition. Raw bypasses column validation and is the caller's responsibility.
type DB ¶
DB wraps sqlx with a dialect.
func Open ¶
Open connects to a database and selects its dialect.
The driver may name a dialect rather than a registered database/sql driver: PostgreSQL is reached through pgx, whose stdlib adapter registers itself as "pgx", so "postgres", "postgresql" and "pg" all open the same driver.
func (*DB) AutoMigrate ¶
AutoMigrate creates missing tables. It never alters or drops an existing table; schema evolution belongs to explicit migrations.
type Dialect ¶
type Dialect interface {
Name() string
Placeholder(index int) string
Quote(identifier string) string
Pagination(limit, offset int) string
Returning() bool
}
Dialect renders SQL for one database engine.
func DialectFor ¶
DialectFor returns the dialect for a database/sql driver name.
type Field ¶
type Field struct {
GoName string
Column string
Type reflect.Type
PK bool
Auto bool
Tenant bool
AutoCreate bool
AutoUpdate bool
Unique bool
SoftDelete bool
Retain bool
Text bool
Size int
}
Field is one mapped struct field.
type Model ¶
type Model struct {
Table string
Type reflect.Type
Fields []Field
Relations []Relation
PK *Field
Tenant *Field
AutoCreate *Field
AutoUpdate *Field
// SoftDelete and Retain are the two supported ways of hiding a deleted row:
// a timestamp column that stops being NULL, or a flag that flips. Both are
// excluded by default and reachable only through Unscoped.
SoftDelete *Field
Retain *Field
}
Model is the table metadata inferred from a Go struct.
type Query ¶
type Query[T any] struct { // contains filtered or unexported fields }
Query is a typed query builder. Conditions are ANDed.
func (*Query[T]) Preload ¶
Preload loads a relation for the rows this query returns, in one extra query per relation rather than one per row.
The name is the struct field; the repository passed in is the related model's. A relation declared on the entity but not asked for here stays empty, and a name that does not exist is a query error instead of a silently skipped load. The related rows obey the same tenant and soft-delete guards as this query, including Unscoped.
type Relation ¶
type Relation struct {
// Name is the struct field.
Name string
Kind RelationKind
// Table is the related table.
Table string
// ForeignKey is the column that carries the key, wherever it lives: on the related
// table for HasMany, on this table for BelongsTo.
ForeignKey string
// Many reports whether the field holds a slice.
Many bool
}
Relation is a struct field that Preload fills.
A relation is metadata, not a column: the field is never part of a SELECT list, and loading it is always an explicit Preload on the query that asked for it — there is no lazy loading, so a handler cannot accidentally issue a query per row.
type RelationKind ¶
type RelationKind string
RelationKind is the direction of a relation.
const ( // HasMany links one row of this model to many rows of another: the other table // carries the foreign key. HasMany RelationKind = "has_many" // BelongsTo links this row to one row of another: this table carries the foreign key. BelongsTo RelationKind = "belongs_to" )
type Repo ¶
type Repo[T any] struct { // contains filtered or unexported fields }
Repo binds a model to a database and optional id generator.
func (*Repo[T]) Create ¶
Create inserts the row. A zero primary key is filled by the id generator (or by the database when the field is tagged auto). A tenant field is filled from the context and a conflicting value is rejected.
func (*Repo[T]) Delete ¶
Delete removes the row, or hides it when the model declares soft_delete or retain.
Both spellings mean the same thing to callers: the row stops appearing in scoped queries. Use Purge to remove it for good.
func (*Repo[T]) Purge ¶
Purge removes the row for good, ignoring soft_delete and retain. It is the explicit escape hatch for retention jobs and for tests; ordinary code should call Delete.
type RepoOption ¶
type RepoOption func(*repoOptions)
RepoOption configures a Repo.
func WithIDGenerator ¶
func WithIDGenerator(ids gcosid.Generator) RepoOption
WithIDGenerator sets the primary key generator used when the key is zero.