Documentation
¶
Overview ¶
Package backend defines the contract every den storage engine implements: the Backend interface, plus the supporting types passed across it (Query, LockMode, AggregateOp, etc.). Concrete backend implementations live in subpackages such as den/backend/sqlite and den/backend/postgres; they register themselves at init time via github.com/oliverandrich/den.RegisterBackend.
Most application code does not import this package directly — it works with backends through den's QuerySet and CRUD entry points. Direct imports are useful when building a custom backend, admin tooling, or migration logic that needs to dispatch on backend capabilities.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AggregateOp ¶
type AggregateOp string
AggregateOp identifies a SQL aggregate function.
const ( OpSum AggregateOp = "SUM" OpAvg AggregateOp = "AVG" OpMin AggregateOp = "MIN" OpMax AggregateOp = "MAX" OpCount AggregateOp = "COUNT" )
type Backend ¶
type Backend interface {
Get(ctx context.Context, collection, id string) ([]byte, error)
Put(ctx context.Context, collection, id string, data []byte) error
Delete(ctx context.Context, collection, id string) error
Query(ctx context.Context, collection string, q *Query) (Iterator, error)
Count(ctx context.Context, collection string, q *Query) (int64, error)
Exists(ctx context.Context, collection string, q *Query) (bool, error)
Aggregate(ctx context.Context, collection string, op AggregateOp, field string, q *Query) (*float64, error)
GroupBy(ctx context.Context, collection string, groupFields []string, aggs []GroupByAgg, q *Query) ([]GroupByRow, error)
EnsureIndex(ctx context.Context, collection string, idx IndexDefinition) error
DropIndex(ctx context.Context, collection string, name string) error
ListRecordedIndexes(ctx context.Context, collection string) ([]RecordedIndex, error)
EnsureCollection(ctx context.Context, name string, meta CollectionMeta) error
DropCollection(ctx context.Context, name string) error
Begin(ctx context.Context) (Transaction, error)
Ping(ctx context.Context) error
Close() error
}
Backend defines the contract that all storage engines must implement.
Byte-ownership contract ¶
Any []byte returned from a Backend method (Get, Iterator.Bytes, Transaction.GetForUpdate, …) MUST be caller-owned: implementations must return a fresh slice that does not alias any internal scratch buffer, and must not retain a reference to it after returning. Callers may keep the slice indefinitely and may mutate it without affecting backend state.
Conversely, any []byte argument passed INTO a Backend method (Put's data, …) is borrowed for the duration of the call only: implementations must not retain a reference past return. Callers may reuse or mutate the slice afterwards.
Den relies on these guarantees to skip defensive copies in change tracking and link hydration. Both bundled backends (SQLite via database/sql.Rows.Scan, PostgreSQL via pgx.Rows.Scan) honor the contract — Scan into a *[]byte target is documented by both libraries to allocate a fresh caller-owned slice per call.
type CollectionMeta ¶
type CollectionMeta struct {
Name string
Fields []FieldMeta
Indexes []IndexDefinition
HasSoftDelete bool
HasRevision bool
HasChangeTracking bool
}
CollectionMeta holds structural metadata for a registered collection.
HasSoftDelete is derived from the document struct: true when the type embeds document.SoftDelete (detected structurally via the `_deleted_at` JSON field). HasRevision reflects DenSettings.UseRevision — a runtime flag on the collection, not a structural property. HasChangeTracking is true when the type implements document.Trackable (typically by embedding document.Tracked); since the snapshot lives only in memory it has no persistence impact, but tooling that walks Meta can use the flag to know which collections expose IsChanged / GetChanges / Revert.
type FieldMeta ¶
type FieldMeta struct {
Name string
GoName string
Type string
Indexed bool
Unique bool
FTS bool
IsPointer bool
}
FieldMeta describes a single field within a collection.
type GroupByAgg ¶
type GroupByAgg struct {
Op AggregateOp
Field string // source field (ignored for OpCount)
}
GroupByAgg describes a single aggregate expression in a GROUP BY query.
type GroupByRow ¶
type GroupByRow struct {
Keys []string // group key values (text representation), one per group field
Values []float64 // aggregate values, matching GroupByAgg order
}
GroupByRow holds one result row from a GROUP BY query. Keys holds one entry per field passed to GroupBy (in the same order); Values holds one entry per GroupByAgg in the order they were requested.
type GroupBySortEntry ¶
type GroupBySortEntry struct {
Op AggregateOp
Field string
Dir SortDirection
}
GroupBySortEntry describes an ORDER BY entry over an aggregate expression inside a GROUP BY query. Op selects which aggregate column to order by; Field names the aggregate's source field (ignored for OpCount).
type IndexDefinition ¶
IndexDefinition describes a secondary index on a collection.
type Iterator ¶
Iterator provides sequential access to query results.
Bytes returns the current row's document bytes. The returned slice is caller-owned per the Backend byte-ownership contract — implementations must allocate a fresh slice per row (typically via Scan into a *[]byte target). Callers may retain the slice beyond the next Next() call; Next() does not invalidate or mutate previously returned slices.
type LinkFieldMeta ¶ added in v0.17.0
type LinkFieldMeta struct {
JSONName string // JSON key of the field
GoName string // Go struct field name
Slice bool // true for []Link[T], false for Link[T]
Eager bool // true when tagged den:"eager"
TargetCollection string // collection of T; "" if T is not registered
TargetType reflect.Type // T in Link[T]
}
LinkFieldMeta describes a single Link[T] / []Link[T] relation field on a document type. Link fields are not part of CollectionMeta.Fields (they reference other collections rather than storing scalar data); enumerate them with den.LinkFields to validate or allowlist expandable relations.
type LockMode ¶
type LockMode int
LockMode selects the row-locking behavior used by GetForUpdate.
const ( // LockDefault acquires the lock and blocks if another transaction holds it. LockDefault LockMode = iota // LockSkipLocked returns no row (ErrNotFound) if another transaction // already holds the lock. Mapped to FOR UPDATE SKIP LOCKED on PostgreSQL. LockSkipLocked // LockNoWait returns ErrLocked immediately if another transaction // already holds the lock. Mapped to FOR UPDATE NOWAIT on PostgreSQL. LockNoWait )
type Query ¶
type Query struct {
Collection string
Conditions []where.Condition
SortFields []SortEntry
LimitN int // 0 = no limit
SkipN int // 0 = no skip
AfterID string
BeforeID string
// Lock requests a row-level lock on every matching row (PostgreSQL
// only; SQLite ignores it because IMMEDIATE tx already serializes
// writers). nil means no lock; a non-nil pointer's value selects the
// lock mode. The pointer form rules out the previously-possible
// invalid pair of (ForUpdate=false, LockMode!=LockDefault).
Lock *LockMode
// GroupBySort carries ORDER BY entries that target aggregates in a
// GROUP BY query. SortFields are used for group-key ordering; aggregate
// ordering needs the (Op, Field) tuple because no source-field name
// identifies a synthetic aggregate column. Only consumed by GroupBy
// paths — other terminals ignore this slice.
GroupBySort []GroupBySortEntry
}
Query represents an abstract query that backends translate into their native query mechanism.
type ReadWriter ¶
type ReadWriter interface {
Get(ctx context.Context, collection, id string) ([]byte, error)
Put(ctx context.Context, collection, id string, data []byte) error
Delete(ctx context.Context, collection, id string) error
Query(ctx context.Context, collection string, q *Query) (Iterator, error)
Count(ctx context.Context, collection string, q *Query) (int64, error)
Exists(ctx context.Context, collection string, q *Query) (bool, error)
Aggregate(ctx context.Context, collection string, op AggregateOp, field string, q *Query) (*float64, error)
GroupBy(ctx context.Context, collection string, groupFields []string, aggs []GroupByAgg, q *Query) ([]GroupByRow, error)
}
ReadWriter is the common interface for both Backend and Transaction, providing the core CRUD operations that all write paths need.
type RecordedIndex ¶
RecordedIndex describes a secondary index that was previously created by Den and is tracked in the backend's metadata table. Managed indexes (such as the PostgreSQL GIN index or FTS auxiliary objects) are not recorded.
type SortDirection ¶
type SortDirection int
SortDirection specifies ascending or descending sort order.
const ( Asc SortDirection = iota Desc )
type SortEntry ¶
type SortEntry struct {
Field string
Dir SortDirection
}
SortEntry defines a single sort criterion.
type Transaction ¶
type Transaction interface {
ReadWriter
Commit() error
Rollback() error
// GetForUpdate reads a document and acquires a row-level lock that
// persists until the transaction commits or rolls back. On PostgreSQL
// this maps to SELECT ... FOR UPDATE, optionally with SKIP LOCKED or
// NOWAIT. On SQLite it is a no-op because IMMEDIATE transactions
// already serialize writers; the mode parameter is ignored.
GetForUpdate(ctx context.Context, collection, id string, mode LockMode) ([]byte, error)
// AdvisoryLock acquires an application-defined lock identified by key
// that persists until the transaction commits or rolls back. Concurrent
// transactions attempting to acquire the same key block until the holder
// ends. Unlike GetForUpdate this does not require a row to exist, so it
// is suitable for bootstrap paths like coordinating concurrent migration
// starters before any state row has been written.
//
// On PostgreSQL this maps to pg_advisory_xact_lock. On SQLite it is a
// no-op because IMMEDIATE transactions already serialize writers on the
// whole database.
AdvisoryLock(ctx context.Context, key int64) error
}
Transaction provides CRUD operations within a transaction boundary.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package postgres implements the Den backend for PostgreSQL via jackc/pgx/v5.
|
Package postgres implements the Den backend for PostgreSQL via jackc/pgx/v5. |
|
Package sqlite implements the Den backend for SQLite via modernc.org/sqlite (pure Go, no CGO).
|
Package sqlite implements the Den backend for SQLite via modernc.org/sqlite (pure Go, no CGO). |