Documentation
¶
Index ¶
- Constants
- Variables
- func AddBeforeDeleteHook(hooks ...RecordHook)
- func AddBeforeSaveHook(hooks ...RecordHook)
- func ApplyChanges(ctx context.Context, tx ReadwriteTransaction, changes *record.Changes, ...) error
- func As[T any](db DB) (value T, ok bool)
- func BeforeDelete(ctx context.Context, _ DB, key *record.Key) error
- func BeforeSave(ctx context.Context, db DB, r record.Record) error
- func ExecuteQueryAndReadAllToRecords(ctx context.Context, query Query, qe QueryExecutor, options ...ReaderOption) (records []record.Record, err error)
- func ExecuteQueryAndReadAllToRecordset(ctx context.Context, query Query, qe QueryExecutor, options ...ReaderOption) (rs recordset.Recordset, err error)
- func GetNonTransactionalContext(ctx context.Context) context.Context
- func GetRecordWithIDIntoData[K comparable, D any](ctx context.Context, s ReadSession, key *record.Key, id K, data D) (record.DataWithID[K, D], error)
- func InsertRecordWithDataAndID[K comparable, D any](ctx context.Context, s WriteSession, key *record.Key, id K, data D) (record.DataWithID[K, D], error)
- func InsertWithIdGenerator(ctx context.Context, r record.Record, generateID IDGenerator, maxAttempts int, ...) error
- func IsGroupOperator(o Operator) bool
- func NewContextWithTransaction(nonTransactionalContext context.Context, tx Transaction) context.Context
- func NewErrNotFoundByKey(key *record.Key, cause error) error
- func NewRollbackError(rollbackErr, originalErr error) error
- func Prefix(prefix string) func(options *randomStringOptions)
- func RandomLength(length int) func(options *randomStringOptions)
- func ReadAllToRecords(ctx context.Context, reader RecordsReader, options ...ReaderOption) (records []record.Record, err error)
- func RequiresEscaping(s string) bool
- func SelectAll(ctx context.Context, reader RecordsReader, addItem func(r record.Record), ...) (err error)
- func SelectAllIDs[T comparable](ctx context.Context, reader RecordsReader, options ...ReaderOption) (ids []T, err error)
- func WithAfterLoad(hook RecordDataHook) func(rd *recordData)
- func WithBeforeSave(hook RecordDataHook) func(rd *recordData)
- func WithIDGenerator(ctx context.Context, g IDGenerator) record.KeyOption
- func WithRandomStringID(options ...randomStringOption) record.KeyOption
- type Adapter
- type AggregateFunc
- type Array
- type Backend
- type Changes
- type Collection
- type CollectionGroupRef
- type CollectionNamer
- type CollectionOption
- type CollectionRef
- type Column
- func AverageAs(expression Expression, alias string) Column
- func Count() Column
- func CountAs(expression Expression, alias string) Column
- func MaxAs(expression Expression, alias string) Column
- func MinAs(expression Expression, alias string) Column
- func SumAs(expression Expression, alias string) Column
- type Comparison
- type ConcurrencyAvailable
- type ConcurrencyAware
- type Condition
- type Constant
- type Cursor
- type DB
- type DataToKeyFunc
- type DataWrapper
- type Deleter
- type EmptyReader
- type ErrDuplicateUser
- type ErrNotFoundByKey
- type Expression
- type ExtraField
- type FieldName
- type FieldRef
- type FromSource
- type Getter
- type GroupCondition
- type IDGenerator
- type IQueryBuilder
- type InsertOption
- type InsertOptions
- type Inserter
- type Item
- type JoinType
- type JoinedSource
- type KeyToFieldsFunc
- type ManyInserter
- type MultiDeleter
- type MultiGetter
- type MultiInserter
- type MultiSetter
- type MultiUpdater
- type NoConcurrency
- type Operator
- type OrderExpression
- type Precondition
- type Preconditions
- type Query
- type QueryArg
- type QueryBuilder
- func (s *QueryBuilder) Clone() IQueryBuilder
- func (s *QueryBuilder) GroupBy(expressions ...Expression) IQueryBuilder
- func (s *QueryBuilder) Having(conditions ...Condition) IQueryBuilder
- func (s *QueryBuilder) Limit(i int) IQueryBuilder
- func (s *QueryBuilder) Offset(i int) IQueryBuilder
- func (s *QueryBuilder) OrderBy(expressions ...OrderExpression) IQueryBuilder
- func (s *QueryBuilder) SelectColumns(columns ...Column) StructuredQuery
- func (s *QueryBuilder) SelectIntoRecord(into func() record.Record) StructuredQuery
- func (s *QueryBuilder) SelectIntoRecordset(options ...recordset.Option) StructuredQuery
- func (s *QueryBuilder) SelectKeysOnly(idKind reflect.Kind) StructuredQuery
- func (s *QueryBuilder) StartFrom(cursor Cursor) IQueryBuilder
- func (s *QueryBuilder) Where(conditions ...Condition) IQueryBuilder
- func (s *QueryBuilder) WhereArrayContains(name string, v any) IQueryBuilder
- func (s *QueryBuilder) WhereArrayContainsAny(name string, values any) IQueryBuilder
- func (s *QueryBuilder) WhereField(name string, operator Operator, v any) IQueryBuilder
- func (s *QueryBuilder) WhereInArrayField(name string, v any) IQueryBuilder
- type QueryExecutor
- type ROTxWorker
- type RWTxWorker
- type RandomStringOptions
- type ReadSession
- type ReadTransaction
- type ReadTransactionCoordinator
- type Reader
- type ReaderOption
- type ReaderOptions
- type ReadwriteSession
- type ReadwriteTransaction
- type ReadwriteTransactionCoordinator
- type RecordAfterLoadHook
- type RecordBeforeSaveHook
- type RecordDataHook
- type RecordDataOption
- type RecordHook
- type RecordsReader
- type RecordsetReader
- type RecordsetSource
- type Schema
- type SchemaBase
- type Setter
- type SingleSource
- type StructuredQuery
- type TextQuery
- type TimeStampAccuracy
- type Transaction
- type TransactionCoordinator
- type TransactionOption
- type TransactionOptions
- type Transform
- type TxIsolationLevel
- type Updater
- type ValidatableRecord
- type WriteSession
Constants ¶
const ( SUM = "SUM" COUNT = "COUNT" MIN = "MIN" MAX = "MAX" AVERAGE = "AVG" )
Variables ¶
var DefaultRandomStringIDLength = 16
var ErrExceedsMaxNumberOfAttempts = fmt.Errorf("exceeds maximum number of attempts")
var ErrHookFailed = errors.New("failed in dalgo hook")
ErrHookFailed indicates that error occurred during hook execution
var ErrInsertOptionNotHonored = errors.New("dal: insert option not honored: record key has no id after a successful insert")
ErrInsertOptionNotHonored is returned by Collection[K, T].Insert when the underlying WriteSession reports success but leaves the record's key without an id — i.e. the adapter ignored the InsertOption generator. It makes a generated Insert fail LOUDLY on a non-honoring adapter instead of reporting a false success under a <nil> id.
var ErrLimitReached = fmt.Errorf("%w: limit reached", ErrNoMoreRecords)
var ErrNoMoreRecords = fmt.Errorf("%w: no more errors", io.EOF)
ErrNoMoreRecords indicates there is no more records
var ErrNotImplementedYet = errors.New("not implemented yet")
ErrNotImplementedYet - return this if db name does not support requested operation yet.
var ErrNotSupported = errors.New("not supported")
ErrNotSupported - return this if db name does not support requested operation. (for example no support for transactions)
var ErrReaderClosed = errors.New("reader closed")
var ErrReaderNotStarted = errors.New("reader not started")
Functions ¶
func AddBeforeDeleteHook ¶ added in v0.64.0
func AddBeforeDeleteHook(hooks ...RecordHook)
AddBeforeDeleteHook registers hooks that the write pipeline calls before a delete reaches the storage adapter. The hook receives a record carrying only the key being deleted; there is no data to validate.
func AddBeforeSaveHook ¶ added in v0.64.0
func AddBeforeSaveHook(hooks ...RecordHook)
AddBeforeSaveHook registers hooks that the write pipeline calls before a record-bearing write reaches the storage adapter. Hooks run in registration order and the first error aborts the write, wrapped in ErrHookFailed.
The registry is process-wide, which is why it is append-only: a package registers its hooks once at init and they apply to every DB built by NewDB.
func ApplyChanges ¶ added in v0.63.1
func ApplyChanges(ctx context.Context, tx ReadwriteTransaction, changes *record.Changes, excludeKeys ...*record.Key) error
ApplyChanges applies a persistence-neutral record change set through tx. It clears changes only after every queued operation succeeds.
func As ¶ added in v0.64.0
As reports whether db — or the Backend it delegates to — implements the optional capability interface T, and returns it.
DALgo advertises optional capabilities by type assertion (dbschema.SchemaReader, ddl.SchemaModifier, ddl.TransactionalDDL, …). A DB returned by NewDB decorates its Backend, so a plain assertion on the DB would stop seeing capabilities the adapter does implement. As is what consumers should use instead.
func BeforeDelete ¶ added in v0.64.0
BeforeDelete runs the registered before-delete hooks for key. A delete has no record data, so nothing is validated; the operation still participates in the pipeline so that the write path is uniform.
func BeforeSave ¶ added in v0.2.9
BeforeSave enforces the record invariants DALgo declares for a write that carries record data: the data is validated (when it implements ValidatableRecord) and then the registered before-save hooks run.
It is the single enforcement point for those invariants. Callers do not normally invoke it: a DB built by NewDB runs it on every record-bearing write before delegating to the storage adapter.
func ExecuteQueryAndReadAllToRecords ¶ added in v0.35.1
func ExecuteQueryAndReadAllToRecords(ctx context.Context, query Query, qe QueryExecutor, options ...ReaderOption) (records []record.Record, err error)
func ExecuteQueryAndReadAllToRecordset ¶ added in v0.38.0
func ExecuteQueryAndReadAllToRecordset(ctx context.Context, query Query, qe QueryExecutor, options ...ReaderOption) (rs recordset.Recordset, err error)
func GetNonTransactionalContext ¶
GetNonTransactionalContext returns non transaction context (e.g. Parent of transactional context) TODO: This is can be dangerous if child context creates a new context with a deadline for example
func GetRecordWithIDIntoData ¶ added in v0.61.0
func GetRecordWithIDIntoData[K comparable, D any](ctx context.Context, s ReadSession, key *record.Key, id K, data D) (record.DataWithID[K, D], error)
GetRecordWithIDIntoData fetches the record at key, decoding it INTO the caller-supplied data value, and returns a typed record.DataWithID[K, D].
Unlike Collection.GetRecordWithDataAndID (which allocates new(T) and therefore needs a concrete T), this takes the data value from the caller, so D may be an interface holding a concrete pointer (the factory pattern used by frameworks whose model types are interfaces). It is a free function because Go forbids type parameters on methods, so the decoupled data type D cannot be expressed as a Collection[K, T] method.
data must be a non-nil pointer or interface referencing a struct or a map (see record.NewDataWithID, which validates it). On not-found it returns the built value together with the session's not-found error.
func InsertRecordWithDataAndID ¶ added in v0.62.0
func InsertRecordWithDataAndID[K comparable, D any](ctx context.Context, s WriteSession, key *record.Key, id K, data D) (record.DataWithID[K, D], error)
InsertRecordWithDataAndID inserts the caller-supplied data value at key (under id) and returns a typed record.DataWithID[K, D].
It is the write twin of GetRecordWithIDIntoData: data is used as-is (never new(T)), so D may be an interface holding a concrete pointer — the factory pattern used by frameworks whose model types are interfaces. It is a free function because Go forbids type parameters on methods, so the decoupled data type D cannot be expressed as a Collection[K, T] method.
data must be a non-nil pointer or interface referencing a struct or a map (see record.NewDataWithID, which validates it). On failure it returns the built value together with the session Insert error.
func InsertWithIdGenerator ¶ added in v0.20.0
func IsGroupOperator ¶ added in v0.2.6
IsGroupOperator says if an operator is a group operator
func NewContextWithTransaction ¶
func NewContextWithTransaction(nonTransactionalContext context.Context, tx Transaction) context.Context
NewContextWithTransaction stores transaction and original context intoRecord a transactional context
func NewErrNotFoundByKey ¶
NewErrNotFoundByKey creates an error that indicates that entity was not found by value
func NewRollbackError ¶
NewRollbackError creates a rollback error
func Prefix ¶ added in v0.3.3
func Prefix(prefix string) func(options *randomStringOptions)
Prefix sets prefix for a random string
func RandomLength ¶ added in v0.3.3
func RandomLength(length int) func(options *randomStringOptions)
RandomLength sets length for a random string
func ReadAllToRecords ¶ added in v0.33.0
func ReadAllToRecords(ctx context.Context, reader RecordsReader, options ...ReaderOption) (records []record.Record, err error)
ReadAllToRecords is a helper method that for a given reader returns all records as a slice.
func RequiresEscaping ¶ added in v0.2.17
func SelectAll ¶ added in v0.5.0
func SelectAll(ctx context.Context, reader RecordsReader, addItem func(r record.Record), options ...ReaderOption) (err error)
SelectAll reads records from the provided RecordsReader and converts each record.Record to T using getItem. Behavior and caveats: - Panics if reader is nil (existing behavior). - Respects WithOffset by discarding the first offset records. - If WithLimit <= 0, reads until RecordsReader.Next() returns ErrNoMoreRecords. - Ensures reader.Close() is called; if Close returns an error and no prior error occurred, that error is returned. - Any panic inside getItem will propagate to the caller.
func SelectAllIDs ¶ added in v0.2.14
func SelectAllIDs[T comparable](ctx context.Context, reader RecordsReader, options ...ReaderOption) (ids []T, err error)
SelectAllIDs is a helper method that for a given reader returns all IDs as a strongly typed slice. Note: This will panic at runtime if the underlying ID types are not assignable to T.
func WithAfterLoad ¶ added in v0.4.0
func WithAfterLoad(hook RecordDataHook) func(rd *recordData)
func WithBeforeSave ¶ added in v0.4.0
func WithBeforeSave(hook RecordDataHook) func(rd *recordData)
func WithIDGenerator ¶
func WithIDGenerator(ctx context.Context, g IDGenerator) record.KeyOption
WithIDGenerator sets ID generator for a random string (usually random)
func WithRandomStringID ¶
WithRandomStringID sets ID generator to random string
Types ¶
type Adapter ¶ added in v0.7.0
type Adapter interface {
// Name of the dalgo adapter
Name() string
// Version of the name if applicable
Version() string
}
Adapter describes adapter that provides access to data either through DB native client or direct implementation.
func NewAdapter ¶ added in v0.7.0
NewAdapter creates new client info. Former ClientInfo.
type AggregateFunc ¶ added in v0.51.0
type AggregateFunc interface {
Expression
FuncName() string
FuncArgs() []Expression
}
AggregateFunc is implemented by aggregate function expressions (SUM, COUNT, MIN, MAX, AVG) so adapters can introspect the function name and its arguments without depending on the unexported concrete type.
type Backend ¶ added in v0.64.0
type Backend interface {
// ID is an identifier provided at time of DB creation
ID() string
// Adapter provides information about underlying name to access data
Adapter() Adapter
// Schema provides schema for the DB - for example, how keys are mapped to columns
Schema() Schema
// TransactionCoordinator provides shortcut methods to work with transactions
// without opening a connection explicitly.
TransactionCoordinator
// ReadSession implements a virtual read session that opens connection/session for each read call on DB level
// TODO: consider to sacrifice some simplicity for the sake of interoperability?
ReadSession
// ConcurrencyAware reports whether this backend supports concurrent
// open connections. Drivers should embed NoConcurrency or
// ConcurrencyAvailable in their concrete type to satisfy this.
ConcurrencyAware
}
Backend is the interface a DALgo storage adapter implements. It is the shape dal.DB used to have, unchanged.
A Backend is not handed to callers directly: an adapter's constructor passes it to NewDB, which returns a DB that owns the write pipeline. That is what makes the record invariants DALgo declares (see ValidatableRecord and BeforeSave) impossible for an adapter to skip — they run before the adapter's code is entered.
func BackendOf ¶ added in v0.64.0
BackendOf returns the Backend that db delegates to, or db itself when it is not a DB produced by NewDB (a decorator, for example).
It exists for adapter internals that need their own concrete type back — the dalgo2memory branching provider recovers its *database this way. Writing through the returned Backend bypasses the framework write pipeline, so a call to BackendOf is exactly as visible and greppable as one to WithoutValidation, and should be just as rare.
type Changes ¶
type Changes struct {
// contains filtered or unexported fields
}
Changes tracks records that a DAL workflow intends to persist with Set or SetMulti. It is distinct from record.Changes, which is a declarative insert/update/delete command envelope executed by ApplyChanges.
func (*Changes) FlagAsChanged ¶
FlagAsChanged marks rec as changed and tracks it once per key.
func (*Changes) HasChanges ¶
HasChanges reports whether at least one record is tracked.
type Collection ¶ added in v0.58.0
type Collection[K comparable, T any] interface { // GetData returns the record stored at id decoded as a T. On not-found it // returns the zero T and the not-found error from the session Get call (use // record.IsNotFound to test it). GetData(ctx context.Context, s ReadSession, id K) (T, error) // Get is a deprecated alias for GetData. // // Deprecated: use GetData. Get(ctx context.Context, s ReadSession, id K) (T, error) // GetRecord returns the underlying record.Record stored at id, with its Data set to // a *T. On not-found it returns the record (Exists() == false) together with // the not-found error from the session Get call. GetRecord(ctx context.Context, s ReadSession, id K) (record.Record, error) // GetRecordWithID reads id and returns a typed record.WithID[K] (id + key + // record, no typed data). On not-found it returns the zero value and the // session's not-found error. GetRecordWithID(ctx context.Context, s ReadSession, id K) (record.WithID[K], error) // GetRecordWithDataAndID reads id and returns a record.DataWithID[K, *T] // whose Data is the decoded *T (the same pointer held by the record.Record). On // not-found it returns the zero value and the session's not-found error. GetRecordWithDataAndID(ctx context.Context, s ReadSession, id K) (record.DataWithID[K, *T], error) // All returns every record in the collection, each decoded into a freshly // allocated value so results never alias. It surfaces ErrNotSupported from // backends that cannot run the query. All(ctx context.Context, s ReadSession) ([]T, error) // Count returns the number of records in the collection. It surfaces // ErrNotSupported from backends that cannot run the underlying query rather // than a silent 0. Count(ctx context.Context, s ReadSession) (int, error) // Exists reports whether a record exists at id. A not-found result maps to // (false, nil); any other failure is returned as (false, err). Exists(ctx context.Context, s ReadSession, id K) (bool, error) // First returns the first record in the collection (an underlying limit-1 // query). An empty collection yields (zero T, false, nil); an incapable // backend surfaces ErrNotSupported. First(ctx context.Context, s ReadSession) (value T, found bool, err error) // Insert inserts value under a GENERATED id and returns the assigned key. // When opts is empty a default generator (WithRandomStringKey) is injected. // Only this terminal accepts InsertOption — generators cannot reach the // id-taking terminals. Insert(ctx context.Context, s WriteSession, value T, opts ...InsertOption) (*record.Key, error) // InsertWithID inserts value at a known id and returns the record's key. InsertWithID(ctx context.Context, s WriteSession, id K, value T) (*record.Key, error) // InsertRecord inserts a caller-built record. It is the shared primitive the // other inserts delegate to; opts carry an id generator for generated inserts. InsertRecord(ctx context.Context, s WriteSession, r record.Record, opts ...InsertOption) error // SetByID stores (upserts) value at id. SetByID(ctx context.Context, s WriteSession, id K, value T) error // Set is a deprecated alias for SetByID. // // Deprecated: use SetByID. Set(ctx context.Context, s WriteSession, id K, value T) error // SetRecord stores (upserts) a caller-built record. SetRecord(ctx context.Context, s WriteSession, r record.Record) error // UpdateByID applies field-level updates to the record at id. UpdateByID(ctx context.Context, s WriteSession, id K, updates []update.Update, preconditions ...Precondition) error // Update is a deprecated alias for UpdateByID. // // Deprecated: use UpdateByID. Update(ctx context.Context, s WriteSession, id K, updates []update.Update, preconditions ...Precondition) error // UpdateByKey applies field-level updates to the record at an explicit key. UpdateByKey(ctx context.Context, s WriteSession, k *record.Key, updates []update.Update, preconditions ...Precondition) error // DeleteByID deletes the record at id. DeleteByID(ctx context.Context, s WriteSession, id K) error // Delete is a deprecated alias for DeleteByID. // // Deprecated: use DeleteByID. Delete(ctx context.Context, s WriteSession, id K) error // DeleteByKey deletes the record at an explicit key. DeleteByKey(ctx context.Context, s WriteSession, k *record.Key) error // In returns a handle scoped under parent (one level of nesting). In(parent *record.Key) Collection[K, T] }
Collection is a session-less, generic, reusable handle to a collection of records of type T keyed by id type K. It carries only path identity (a composed CollectionRef) and the phantom types K, T — it holds no session or connection, so a single value can be declared once (e.g. a package-level var) and reused across calls.
K is the (scalar) id type — id arguments are strongly typed as K rather than any. Composite / multi-field keys are addressed through the *ByKey terminals (build a *record.Key with record.NewKeyWithFields).
Read terminals take a ReadSession; write terminals take a WriteSession. Because dal.DB satisfies ReadSession but not WriteSession, calling a write terminal with a plain DB is a compile error — writes go through a read-write transaction handle (see RunReadwriteTransaction).
func CollectionAt ¶ added in v0.58.0
func CollectionAt[K comparable, T any](name string, opts ...CollectionOption) Collection[K, T]
CollectionAt returns a Collection[K, T] with an explicit collection name.
func CollectionOf ¶ added in v0.58.0
func CollectionOf[K comparable, T CollectionNamer](opts ...CollectionOption) Collection[K, T]
CollectionOf returns a Collection[K, T] whose name is resolved from T's value-receiver CollectionName method.
type CollectionGroupRef ¶ added in v0.22.0
type CollectionGroupRef struct {
// contains filtered or unexported fields
}
func NewCollectionGroupRef ¶ added in v0.22.0
func NewCollectionGroupRef(name, alias string) CollectionGroupRef
func (CollectionGroupRef) Alias ¶ added in v0.22.0
func (v CollectionGroupRef) Alias() string
func (CollectionGroupRef) Name ¶ added in v0.22.0
func (v CollectionGroupRef) Name() string
func (CollectionGroupRef) String ¶ added in v0.22.0
func (v CollectionGroupRef) String() string
type CollectionNamer ¶ added in v0.58.0
type CollectionNamer interface {
CollectionName() string
}
CollectionNamer is implemented by a record type that knows its own collection name. The CollectionName method MUST be declared on a value receiver so that CollectionOf[K, T]() can resolve the name from the zero value of T.
type CollectionOption ¶ added in v0.60.0
type CollectionOption func(*collectionOptions)
CollectionOption configures a Collection at construction time.
func WithKeyOptions ¶ added in v0.60.0
func WithKeyOptions(keyOptions ...record.KeyOption) CollectionOption
WithKeyOptions configures KeyOptions applied to every key the collection builds from a typed id (e.g. record.WithFields for composite keys, a parent key, or a custom IDKind). The id passed to a terminal is set first; these options are applied after, so an option may augment or override the resulting key.
type CollectionRef ¶
type CollectionRef struct {
// contains filtered or unexported fields
}
CollectionRef points to a recordsetSource (e.g. table) in a database
func NewCollectionRef ¶ added in v0.2.17
func NewCollectionRef(name, alias string, parent *record.Key) (collectionRef CollectionRef)
func NewRootCollectionRef ¶ added in v0.15.0
func NewRootCollectionRef(name, alias string) CollectionRef
func (CollectionRef) Alias ¶ added in v0.2.16
func (v CollectionRef) Alias() string
func (CollectionRef) Equal ¶ added in v0.27.0
func (v CollectionRef) Equal(other CollectionRef, ignoreAlias bool) bool
func (CollectionRef) Name ¶
func (v CollectionRef) Name() string
func (CollectionRef) Parent ¶
func (v CollectionRef) Parent() *record.Key
func (CollectionRef) Path ¶
func (v CollectionRef) Path() string
func (CollectionRef) String ¶ added in v0.2.16
func (v CollectionRef) String() string
type Column ¶ added in v0.2.6
type Column struct {
Alias string `json:"Alias"`
Expression Expression `json:"expression"`
}
Column reference a column in a SELECT statement
func AverageAs ¶ added in v0.2.6
func AverageAs(expression Expression, alias string) Column
AverageAs returns average value for a given expression
func Count ¶ added in v0.51.0
func Count() Column
Count returns a COUNT(*) aggregate column counting all rows in a group regardless of nulls. Count() is the alias for COUNT(*); use the returned Column's Alias field to name the output. The existing CountAs(field, alias) keeps its field-count (skip-nulls) semantics.
func CountAs ¶ added in v0.2.6
func CountAs(expression Expression, alias string) Column
CountAs aggregate function (see SQL COUNT())
func MaxAs ¶ added in v0.2.6
func MaxAs(expression Expression, alias string) Column
MaxAs returns maximum value for a given expression
func MinAs ¶ added in v0.2.6
func MinAs(expression Expression, alias string) Column
MinAs returns minimum value for a given expression
func SumAs ¶ added in v0.2.6
func SumAs(expression Expression, alias string) Column
SumAs aggregate function (see SQL SUM())
type Comparison ¶ added in v0.2.6
type Comparison struct {
Operator Operator
Left Expression
Right Expression
}
Comparison defines a contact for a comparison
func NewComparison ¶ added in v0.2.6
func NewComparison(left Expression, o Operator, right Expression) Comparison
NewComparison creates new Comparison
func (Comparison) Equal ¶ added in v0.2.6
func (v Comparison) Equal(b Comparison) bool
func (Comparison) String ¶ added in v0.2.6
func (v Comparison) String() string
String returns string representation of a comparison
type ConcurrencyAvailable ¶ added in v0.42.0
type ConcurrencyAvailable struct{}
ConcurrencyAvailable is a zero-value embeddable struct that satisfies ConcurrencyAware by reporting that concurrent connections ARE supported. Drivers whose backend tolerates multiple concurrent connections (such as a server-side RDBMS like PostgreSQL) should embed ConcurrencyAvailable to inherit the permissive answer with no method body of their own:
type PostgresDB struct {
dal.ConcurrencyAvailable
// ...
}
See ConcurrencyAware for the full contract.
func (ConcurrencyAvailable) SupportsConcurrentConnections ¶ added in v0.42.0
func (ConcurrencyAvailable) SupportsConcurrentConnections() bool
SupportsConcurrentConnections always returns true.
type ConcurrencyAware ¶ added in v0.42.0
type ConcurrencyAware interface {
// SupportsConcurrentConnections reports whether the underlying
// backend tolerates more than one open connection from a single
// client process at the same time. See [ConcurrencyAware] for the
// stability and asymmetry contract.
SupportsConcurrentConnections() bool
}
ConcurrencyAware is implemented by DB values that can report whether the underlying backend supports multiple concurrent open connections from a single client process.
The returned value is constant from the moment a DB value is returned by its constructor until it is discarded. Drivers MUST NOT change the answer in response to reconnects, failovers, transient errors, or runtime configuration reloads against the same DB handle. Callers are entitled to memoize the value once per DB value.
The boolean intentionally does not distinguish read-vs-write concurrency. A driver like SQLite that supports concurrent readers but serializes writers collapses to false. Refining this surface (or adding a sibling) is a future change if a real consumer needs the distinction.
ConcurrencyAware is embedded into DB; every DB implementation therefore answers the question. Drivers SHOULD embed one of the reusable structs NoConcurrency or ConcurrencyAvailable rather than hand-writing the method.
type Constant ¶ added in v0.2.15
type Constant struct {
Value any `json:"value"`
}
func NewConstant ¶ added in v0.23.0
type DB ¶ added in v0.8.0
type DB interface {
Backend
// contains filtered or unexported methods
}
DB is the caller-facing database handle. It has the same shape as Backend and is additionally sealed: the unexported marker method means only this package can produce a value satisfying DB, so every DB a caller holds has been through NewDB and therefore through the framework write pipeline.
Sealing enforces provenance, not behaviour — the pipeline enforces the behaviour. Together they mean a caller cannot be handed a database that silently skips the invariants.
A decorator (a caching layer, an access-policy layer, a tracing layer) still works: embed DB in the decorating type and the marker method is promoted along with everything else the decorator does not override. See access.SecureDB in this repository, or dalgo-memcache-appengine, for worked examples.
func NewDB ¶ added in v0.64.0
NewDB wraps a storage adapter's Backend in the framework-owned write pipeline and returns the sealed, caller-facing DB.
It is the only way to obtain a DB, and it is the one line an adapter's public constructor changes:
func NewDB(options ...Option) dal.DB {
return dal.NewDB(newDatabase(options...))
}
Every read-write transaction the returned DB starts hands the worker a transaction whose writes run BeforeSave first, so record validation and before-save hooks happen before the adapter's code is entered. When the backend also supports writes outside a transaction (it implements WriteSession), the returned DB exposes those through the same pipeline.
NewDB is idempotent: a value that already satisfies DB has already been through the pipeline and is returned unchanged, so wrapping twice cannot run hooks twice.
It is named NewDB rather than New to match this package's other constructors (NewAdapter, NewInsertOptions, NewTransactionOptions) and to read unambiguously at an adapter call site, where the adapter has a NewDB of its own.
type DataToKeyFunc ¶ added in v0.25.0
DataToKeyFunc takes data retrieved from DB table/view/query and maps primary key columns to the record key.
type DataWrapper ¶ added in v0.4.0
type DataWrapper interface {
Data() any
}
DataWrapper is a wrapper for data transfer objects (DTOs). TODO: document intended usage or consider removing as it makes implementation of RecordsReader more complex.
func MakeRecordData ¶ added in v0.2.7
func MakeRecordData(data any, options ...RecordDataOption) DataWrapper
MakeRecordData creates a DataWrapper with the given data and options.
type Deleter ¶ added in v0.2.27
type Deleter interface {
// Delete deletes a single record from database by key
Delete(ctx context.Context, key *record.Key) error
}
Deleter defines a function to delete a single record from database by key
type EmptyReader ¶ added in v0.3.1
type EmptyReader struct{}
func (EmptyReader) Close ¶ added in v0.3.1
func (e EmptyReader) Close() error
func (EmptyReader) Cursor ¶ added in v0.3.1
func (e EmptyReader) Cursor() (string, error)
type ErrDuplicateUser ¶
type ErrDuplicateUser struct {
// TODO: Should it be moved out of this package to strongo/app/user?
SearchCriteria string
DuplicateUserIDs []string
}
ErrDuplicateUser indicates there is a duplicate user // TODO: move to strongo/app?
func (ErrDuplicateUser) Error ¶
func (err ErrDuplicateUser) Error() string
Error implements error interface
type ErrNotFoundByKey ¶
ErrNotFoundByKey indicates error was not found by value
type Expression ¶ added in v0.2.6
Expression represent either a FieldRef, Constant or a formula
func ID ¶ added in v0.2.6
func ID(name string, value any) Expression
ID creates an expression that compares an ID with a constant
func String ¶ added in v0.2.6
func String(v string) Expression
String creates a new Constant expression
type ExtraField ¶ added in v0.25.0
func NewExtraField ¶ added in v0.25.0
func NewExtraField(name string, value any) ExtraField
type FieldName ¶ added in v0.25.0
type FieldName string
FieldName represents a field name as string (for backward compatibility)
type FieldRef ¶ added in v0.2.6
type FieldRef struct {
// contains filtered or unexported fields
}
func Field ¶ added in v0.2.6
Field creates an unqualified FieldRef with the given name (empty source, i.e. the single From base recordset). Use NewFieldRef to qualify by source.
func NewFieldRef ¶ added in v0.25.0
NewFieldRef creates an expression that represents a FieldRef value. source qualifies the field with its recordset; an empty source denotes the single From base recordset.
type FromSource ¶ added in v0.28.0
type FromSource interface {
Base() RecordsetSource
Join(joint JoinedSource) FromSource
Joins() []JoinedSource
NewQuery() *QueryBuilder
}
func From ¶ added in v0.2.6
func From(source RecordsetSource) FromSource
From creates a new IQueryBuilder with optional conditions. We can use NewQueryBuilder() directly but this is shorter.
type Getter ¶ added in v0.2.27
type Getter interface {
// Get gets a single record from a database by key
Get(ctx context.Context, record record.Record) error
// Exists returns true if a record with the given key exists
Exists(ctx context.Context, key *record.Key) (bool, error)
}
Getter defines a method to get a single record by key or check its existence
type GroupCondition ¶ added in v0.2.15
type GroupCondition struct {
// contains filtered or unexported fields
}
func NewGroupCondition ¶ added in v0.47.0
func NewGroupCondition(operator Operator, conditions ...Condition) GroupCondition
NewGroupCondition creates a GroupCondition combining the given conditions with a group operator (e.g. And or Or). It is the public constructor for the otherwise unexported fields, enabling callers outside the dal package (such as the dtql serializer) to reconstruct group conditions.
func (GroupCondition) Conditions ¶ added in v0.2.15
func (v GroupCondition) Conditions() []Condition
func (GroupCondition) Operator ¶ added in v0.2.15
func (v GroupCondition) Operator() Operator
func (GroupCondition) String ¶ added in v0.2.15
func (v GroupCondition) String() string
type IDGenerator ¶
IDGenerator defines a contract for ID generator function
func NewIDGenerator ¶ added in v0.20.0
func NewIDGenerator(f IDGenerator, maxAttempts int) IDGenerator
type IQueryBuilder ¶ added in v0.28.0
type IQueryBuilder interface {
Clone() IQueryBuilder
Offset(int) IQueryBuilder
Limit(int) IQueryBuilder
Where(conditions ...Condition) IQueryBuilder
WhereField(name string, operator Operator, v any) IQueryBuilder
WhereInArrayField(name string, v any) IQueryBuilder
WhereArrayContains(name string, v any) IQueryBuilder
WhereArrayContainsAny(name string, values any) IQueryBuilder
GroupBy(expressions ...Expression) IQueryBuilder
Having(conditions ...Condition) IQueryBuilder
OrderBy(expressions ...OrderExpression) IQueryBuilder
SelectIntoRecord(func() record.Record) StructuredQuery
SelectIntoRecordset(options ...recordset.Option) StructuredQuery
SelectKeysOnly(idKind reflect.Kind) StructuredQuery
SelectColumns(columns ...Column) StructuredQuery
StartFrom(cursor Cursor) IQueryBuilder
}
type InsertOption ¶
type InsertOption func(options *insertOptions)
InsertOption defines a contract for an insert option
func WithAdapterGeneratedID ¶ added in v0.59.0
func WithAdapterGeneratedID() InsertOption
WithAdapterGeneratedID requests that the storage adapter generates the record ID natively (e.g. Firestore's client-side auto-generated 20-char document IDs).
Contract for adapters:
- An adapter SHOULD use its backend's native ID generation mechanism if it has one.
- An adapter that has no native mechanism MUST fall back to the default random-string generator (WithRandomStringKey(DefaultRandomStringIDLength, 5)), so this option never fails on a compliant adapter.
- If an explicit ID generator option (e.g. WithRandomStringKey) is supplied alongside this option, the explicit generator wins: adapters must check InsertOptions.IDGenerator() first and only consult InsertOptions.PreferAdapterGeneratedID() when it is nil.
Adapters introspect this option via InsertOptions.PreferAdapterGeneratedID().
func WithRandomStringKey ¶ added in v0.20.0
func WithRandomStringKey(length, maxAttempts int) InsertOption
func WithRandomStringKeyPrefixedByUnixTime ¶ added in v0.21.1
func WithRandomStringKeyPrefixedByUnixTime(randomLength, maxAttempts int) InsertOption
func WithTimeStampStringID ¶ added in v0.24.0
func WithTimeStampStringID(accuracy TimeStampAccuracy, base, maxAttempts int) InsertOption
type InsertOptions ¶
type InsertOptions interface {
IDGenerator() IDGenerator
// PreferAdapterGeneratedID reports whether WithAdapterGeneratedID was passed.
// See WithAdapterGeneratedID for the contract adapters must follow.
PreferAdapterGeneratedID() bool
}
InsertOptions defines interface for insert options
func NewInsertOptions ¶
func NewInsertOptions(opts ...InsertOption) InsertOptions
NewInsertOptions creates insert options
type Inserter ¶ added in v0.2.27
type Inserter interface {
// Insert inserts a single record intoRecord a database
Insert(ctx context.Context, record record.Record, opts ...InsertOption) error
}
Inserter defines a function to insert a single record intoRecord a database
type Item ¶ added in v0.58.0
type Item[K comparable, T any] struct { ID K Value T }
Item is a dal-native id+value pair for batch insert. Item deliberately does NOT reference the record package, so the batch API adds no dal -> record import.
type JoinType ¶ added in v0.48.0
type JoinType string
JoinType enumerates the kinds of join. JoinInner and JoinLeft are supported by executors; JoinRight, JoinFull and JoinCross are reserved for future support and rejected at execution time until implemented.
type JoinedSource ¶ added in v0.28.0
type JoinedSource struct {
RecordsetSource
// contains filtered or unexported fields
}
func NewJoinedSource ¶ added in v0.48.0
func NewJoinedSource(src RecordsetSource, joinType JoinType, on ...Condition) JoinedSource
NewJoinedSource builds a JoinedSource of the given join type over src with the supplied ON conditions. It lets callers outside the dal package construct a fully-populated join (type + ON clause).
func (JoinedSource) JoinType ¶ added in v0.48.0
func (j JoinedSource) JoinType() JoinType
JoinType returns the kind of join (INNER, LEFT, ...).
func (JoinedSource) On ¶ added in v0.28.0
func (j JoinedSource) On() []Condition
On returns the join's ON conditions. The value receiver makes a join returned by From().Joins() readable without taking its address.
type KeyToFieldsFunc ¶ added in v0.25.0
type KeyToFieldsFunc func(key *record.Key, data any) (fields []ExtraField, err error)
KeyToFieldsFunc takes key and should either populate fields on a `data` struct or return extra fields to be stored to the target table.
type ManyInserter ¶ added in v0.58.0
type ManyInserter[K comparable, T any] interface { // InsertMany inserts each item at its known id and returns the keys in // input order. InsertMany(ctx context.Context, s WriteSession, items ...Item[K, T]) (keys []*record.Key, err error) }
ManyInserter is the opt-in batch-insert interface, mirroring dalgo's Inserter/MultiInserter split. The concrete Collection[K, T] value satisfies it (obtain it via a type assertion: c.(dal.ManyInserter[K, T])).
type MultiDeleter ¶ added in v0.2.27
type MultiDeleter interface {
// DeleteMulti deletes multiple records from database by keys
DeleteMulti(ctx context.Context, keys []*record.Key) error
}
MultiDeleter defines a function to delete multiple records from database by keys
type MultiGetter ¶ added in v0.2.27
type MultiGetter interface {
// GetMulti gets multiple records from a database by keys
GetMulti(ctx context.Context, records []record.Record) error
}
MultiGetter defines method to get multiple records from a database by keys
type MultiInserter ¶ added in v0.13.0
type MultiInserter interface {
// InsertMulti inserts multiple record intoRecord a database at once if possible, or fallback to batch of single inserts
InsertMulti(ctx context.Context, records []record.Record, opts ...InsertOption) error
}
MultiInserter defines a function to insert multiple records intoRecord a database
type MultiSetter ¶ added in v0.2.27
type MultiSetter interface {
// SetMulti stores multiples records intoRecord database by keys
SetMulti(ctx context.Context, records []record.Record) error
}
MultiSetter defines a function to store multiple records intoRecord database by keys
type MultiUpdater ¶ added in v0.2.27
type MultiUpdater interface {
// UpdateMulti updates multiples records in database by keys
UpdateMulti(ctx context.Context, keys []*record.Key, updates []update.Update, preconditions ...Precondition) error
}
MultiUpdater defines a function to update multiples records in database by keys
type NoConcurrency ¶ added in v0.42.0
type NoConcurrency struct{}
NoConcurrency is a zero-value embeddable struct that satisfies ConcurrencyAware by reporting that concurrent connections are NOT supported. Drivers whose backend serializes connections (such as a single-writer SQLite, an unproven file-backed store, or a test stub) should embed NoConcurrency to inherit the conservative answer with no method body of their own:
type SQLiteDB struct {
dal.NoConcurrency
// ...
}
See ConcurrencyAware for the full contract.
func (NoConcurrency) SupportsConcurrentConnections ¶ added in v0.42.0
func (NoConcurrency) SupportsConcurrentConnections() bool
SupportsConcurrentConnections always returns false.
type Operator ¶ added in v0.2.6
type Operator string
Operator defines a Comparison operator
const ( // Equal is a Comparison operator Equal Operator = "==" // In is a Comparison operator In Operator = "In" // GreaterThen is a Comparison operator GreaterThen Operator = ">" // GreaterOrEqual is a Comparison operator GreaterOrEqual Operator = ">=" // LessThen is a Comparison operator LessThen Operator = "<" // LessOrEqual is a Comparison operator LessOrEqual Operator = "<=" // And is a Comparison operator // TODO: Is it an operator? And = "AND" // Or is a Comparison operator // TODO: Is it an operator? Or = "OR" )
type OrderExpression ¶ added in v0.2.6
type OrderExpression interface {
fmt.Stringer
Expression() Expression
Descending() bool
}
func Ascending ¶ added in v0.2.6
func Ascending(expression Expression) OrderExpression
func AscendingField ¶ added in v0.2.6
func AscendingField(name string) OrderExpression
func Descending ¶ added in v0.2.6
func Descending(expression Expression) OrderExpression
func DescendingField ¶ added in v0.2.6
func DescendingField(name string) OrderExpression
type Precondition ¶
type Precondition interface {
// contains filtered or unexported methods
}
Precondition defines precondition
func WithExistsPrecondition ¶
func WithExistsPrecondition() Precondition
WithExistsPrecondition sets exists precondition
func WithLastUpdateTimePrecondition ¶
func WithLastUpdateTimePrecondition(t time.Time) Precondition
WithLastUpdateTimePrecondition sets last update time
type Preconditions ¶
Preconditions defines preconditions
func GetPreconditions ¶
func GetPreconditions(items ...Precondition) Preconditions
GetPreconditions create Preconditions
type Query ¶ added in v0.2.6
type Query interface {
String() string
// Offset specifies the number of records to skip
Offset() int
// Limit specifies the maximum number of records to be returned
Limit() int
GetRecordsReader(ctx context.Context, qe QueryExecutor) (reader RecordsReader, err error)
GetRecordsetReader(ctx context.Context, qe QueryExecutor) (reader RecordsetReader, err error)
}
type QueryBuilder ¶ added in v0.2.11
type QueryBuilder struct {
// contains filtered or unexported fields
}
func NewQueryBuilder ¶ added in v0.15.0
func NewQueryBuilder(from FromSource) *QueryBuilder
NewQueryBuilder creates a new IQueryBuilder - it's an entry point to build a query. We can use From() directly but this is easier to remember.
func (*QueryBuilder) Clone ¶ added in v0.28.0
func (s *QueryBuilder) Clone() IQueryBuilder
func (*QueryBuilder) GroupBy ¶ added in v0.51.0
func (s *QueryBuilder) GroupBy(expressions ...Expression) IQueryBuilder
func (*QueryBuilder) Having ¶ added in v0.51.0
func (s *QueryBuilder) Having(conditions ...Condition) IQueryBuilder
func (*QueryBuilder) Limit ¶ added in v0.2.16
func (s *QueryBuilder) Limit(i int) IQueryBuilder
func (*QueryBuilder) Offset ¶ added in v0.2.16
func (s *QueryBuilder) Offset(i int) IQueryBuilder
func (*QueryBuilder) OrderBy ¶ added in v0.2.11
func (s *QueryBuilder) OrderBy(expressions ...OrderExpression) IQueryBuilder
func (*QueryBuilder) SelectColumns ¶ added in v0.50.0
func (s *QueryBuilder) SelectColumns(columns ...Column) StructuredQuery
func (*QueryBuilder) SelectIntoRecord ¶ added in v0.34.0
func (s *QueryBuilder) SelectIntoRecord(into func() record.Record) StructuredQuery
func (*QueryBuilder) SelectIntoRecordset ¶ added in v0.34.0
func (s *QueryBuilder) SelectIntoRecordset(options ...recordset.Option) StructuredQuery
func (*QueryBuilder) SelectKeysOnly ¶ added in v0.2.11
func (s *QueryBuilder) SelectKeysOnly(idKind reflect.Kind) StructuredQuery
func (*QueryBuilder) StartFrom ¶ added in v0.2.19
func (s *QueryBuilder) StartFrom(cursor Cursor) IQueryBuilder
func (*QueryBuilder) Where ¶ added in v0.2.11
func (s *QueryBuilder) Where(conditions ...Condition) IQueryBuilder
func (*QueryBuilder) WhereArrayContains ¶ added in v0.59.0
func (s *QueryBuilder) WhereArrayContains(name string, v any) IQueryBuilder
WhereArrayContains adds a condition that an array field contains the given value. Adapters translate it to the platform's array membership operator, e.g. Firestore's "array-contains". It is an alias for WhereInArrayField.
func (*QueryBuilder) WhereArrayContainsAny ¶ added in v0.59.0
func (s *QueryBuilder) WhereArrayContainsAny(name string, values any) IQueryBuilder
WhereArrayContainsAny adds a condition that an array field contains at least one element of the given values, e.g. Firestore's "array-contains-any". The values must be a dal.Array or a slice type supported by NewArray.
func (*QueryBuilder) WhereField ¶ added in v0.2.11
func (s *QueryBuilder) WhereField(name string, operator Operator, v any) IQueryBuilder
func (*QueryBuilder) WhereInArrayField ¶ added in v0.16.1
func (s *QueryBuilder) WhereInArrayField(name string, v any) IQueryBuilder
type QueryExecutor ¶ added in v0.2.14
type QueryExecutor interface {
// ExecuteQueryToRecordsReader returns a reader for the given query to read records 1 by 1 sequentially.
// The RecordsReader.Next() method returns ErrNoMoreRecords when there are no more records.
ExecuteQueryToRecordsReader(ctx context.Context, query Query) (RecordsReader, error)
// ExecuteQueryToRecordsetReader returns a RecordsetReader for the given query, allowing sequential read of records into the provided recordset.
ExecuteQueryToRecordsetReader(ctx context.Context, query Query, options ...recordset.Option) (RecordsetReader, error)
}
QueryExecutor is a query executor that returns a reader and have few helper methods.
type ROTxWorker ¶
type ROTxWorker = func(ctx context.Context, tx ReadTransaction) error
ROTxWorker defines a callback to be called to do work within a readonly transaction
type RWTxWorker ¶
type RWTxWorker = func(ctx context.Context, tx ReadwriteTransaction) error
RWTxWorker defines a callback to be called to do work within a readwrite transaction
type RandomStringOptions ¶
RandomStringOptions defines settings for random string
type ReadSession ¶
type ReadSession interface {
Getter
MultiGetter
QueryExecutor
}
ReadSession defines methods that query data from DB and does not modify it
type ReadTransaction ¶
type ReadTransaction interface {
Transaction
ReadSession
}
ReadTransaction defines an interface for a readonly transaction
type ReadTransactionCoordinator ¶
type ReadTransactionCoordinator interface {
// RunReadonlyTransaction starts readonly transaction
RunReadonlyTransaction(ctx context.Context, f ROTxWorker, options ...TransactionOption) error
}
ReadTransactionCoordinator creates a readonly transaction
type ReaderOption ¶ added in v0.5.0
type ReaderOption = func(ro *ReaderOptions)
ReaderOption configures how SelectAll reads from the RecordsReader (e.g., limit, offset).
func WithLimit ¶ added in v0.5.0
func WithLimit(limit int) ReaderOption
WithLimit sets the maximum number of items to read. If limit <= 0, SelectAll reads until ErrNoMoreRecords.
func WithOffset ¶ added in v0.5.0
func WithOffset(offset int) ReaderOption
WithOffset skips the first N records before collecting results in SelectAll. If offset <= 0, no records are skipped.
type ReaderOptions ¶ added in v0.5.0
type ReaderOptions struct {
// contains filtered or unexported fields
}
func (*ReaderOptions) Limit ¶ added in v0.5.0
func (ro *ReaderOptions) Limit() int
Limit specifies the maximum number of records to read, if 0 - unlimited
func (*ReaderOptions) Offset ¶ added in v0.5.0
func (ro *ReaderOptions) Offset() int
Offset specifies how many records to skip, if 0 - no records are skipped
type ReadwriteSession ¶
type ReadwriteSession interface {
ReadSession
WriteSession
}
ReadwriteSession defines methods that can read & modify database. Some databases allow to modify data without transaction.
type ReadwriteTransaction ¶
type ReadwriteTransaction interface {
// ID returns a unique ID of a transaction if it is supported by the underlying DB client
ID() string
Transaction
ReadwriteSession
}
ReadwriteTransaction defines an interface for a readwrite transaction
type ReadwriteTransactionCoordinator ¶
type ReadwriteTransactionCoordinator interface {
// RunReadwriteTransaction starts read-write transaction
RunReadwriteTransaction(ctx context.Context, f RWTxWorker, options ...TransactionOption) error
}
ReadwriteTransactionCoordinator creates a read-write transaction
type RecordAfterLoadHook ¶ added in v0.2.7
type RecordBeforeSaveHook ¶ added in v0.2.7
type RecordDataHook ¶ added in v0.2.9
type RecordDataOption ¶ added in v0.4.0
type RecordDataOption = func(rd *recordData)
type RecordHook ¶ added in v0.2.9
type RecordsReader ¶ added in v0.3.1
type RecordsReader interface {
Reader
// Next returns the next record for a query.
// If no more records, a nil record and ErrNoMoreRecords are returned.
Next() (record.Record, error)
}
RecordsReader reads records one by one into record.Record
func NewRecordsReader ¶ added in v0.3.2
func NewRecordsReader(records []record.Record) RecordsReader
type RecordsetReader ¶ added in v0.34.0
type RecordsetReader interface {
Reader
Recordset() recordset.Recordset
Next() (row recordset.Row, rs recordset.Recordset, err error)
}
RecordsetReader reads records one by one into recordset.Recordset
type RecordsetSource ¶ added in v0.22.0
type Schema ¶ added in v0.25.0
type Schema interface {
DataToKey(incompleteKey *record.Key, data any) (key *record.Key, err error)
KeyToFields(key *record.Key, data any) (fields []ExtraField, err error)
}
func NewSchema ¶ added in v0.25.0
func NewSchema(keyToField KeyToFieldsFunc, dataToKey DataToKeyFunc) Schema
type SchemaBase ¶ added in v0.26.0
type SchemaBase struct {
// contains filtered or unexported fields
}
SchemaBase provides rules for mapping of fields, keys and collections
func (*SchemaBase) DataToKey ¶ added in v0.26.0
DataToKey creates a *record.Key from data read from DB
func (*SchemaBase) KeyToFields ¶ added in v0.26.0
func (s *SchemaBase) KeyToFields(key *record.Key, data any) (fields []ExtraField, err error)
KeyToFields maps key intoRecord DB fields. This is needed as relational DBs usually have key column(s) that are part of the record set, while key-value DBs can have key and data separated and data would not include the key.
type Setter ¶ added in v0.2.27
type Setter interface {
// Set stores a single record intoRecord database by key
Set(ctx context.Context, record record.Record) error
}
Setter defines a function to store a single record intoRecord database by key
type SingleSource ¶ added in v0.2.6
type SingleSource interface {
Where(conditions ...Condition) IQueryBuilder
}
type StructuredQuery ¶ added in v0.27.0
type StructuredQuery interface {
Query
// From - defines target table/recordsetSource
From() FromSource
// Where defines filter condition
Where() Condition
// GroupBy defines expressions to group by
GroupBy() []Expression
// Having defines a post-aggregation filter condition
Having() Condition
// OrderBy defines expressions to order by
OrderBy() []OrderExpression
// Columns specifies columns to return
Columns() []Column
// IntoRecord provides a function that creates a record for a new row
IntoRecord() record.Record // TODO: Should this be moved into Query.GetRecordsReader ?
// IDKind defines the type of the ID
IDKind() reflect.Kind // TODO: what about composite keys?
// StartFrom specifies the startCursor/point to start from
StartFrom() Cursor
}
StructuredQuery represents a query to a recordsetSource
type TextQuery ¶ added in v0.27.0
TextQuery defines an interface to represent a query with text and associated arguments.
type TimeStampAccuracy ¶ added in v0.24.0
type TimeStampAccuracy int
const ( TimeStampAccuracyNano TimeStampAccuracy = iota TimeStampAccuracyMicrosecond TimeStampAccuracyMillisecond TimeStampAccuracySecond TimeStampAccuracyMinute TimeStampAccuracyHour TimeStampAccuracyDay )
type Transaction ¶
type Transaction interface {
// Options indicates parameters that were requested at time of transaction creation.
// The message field is mutable during execution via TransactionOptions.SetMessage();
// implementations should return options by shared reference so the update is observed.
Options() TransactionOptions
}
Transaction defines an instance of DALgo transaction
func GetTransaction ¶
func GetTransaction(ctx context.Context) Transaction
GetTransaction returns original transaction object
type TransactionCoordinator ¶
type TransactionCoordinator interface {
// ReadTransactionCoordinator can start a readonly transaction
ReadTransactionCoordinator
// ReadwriteTransactionCoordinator can start a readwrite transaction
ReadwriteTransactionCoordinator
}
TransactionCoordinator provides methods to work with transactions
type TransactionOption ¶
type TransactionOption func(options *txOptions)
TransactionOption defines contact for transaction option
func TxWithAttempts ¶
func TxWithAttempts(attempts int) TransactionOption
TxWithAttempts specifies number of attempts to execute a transaction
func TxWithCrossGroup ¶
func TxWithCrossGroup() TransactionOption
TxWithCrossGroup requires transaction that spans multiple entity groups
func TxWithIsolationLevel ¶
func TxWithIsolationLevel(isolationLevel TxIsolationLevel) TransactionOption
TxWithIsolationLevel requests transaction with required isolation level
func TxWithMessage ¶ added in v0.45.0
func TxWithMessage(message string) TransactionOption
TxWithMessage sets a human-readable message on the transaction. The message can be read back via TransactionOptions.Message() and replaced during transaction execution via TransactionOptions.SetMessage().
func TxWithReadonly ¶
func TxWithReadonly() TransactionOption
TxWithReadonly requests a readonly transaction
type TransactionOptions ¶
type TransactionOptions interface {
// Message returns an optional human-readable message describing the transaction.
// Backends may surface it (e.g. dalgo2ingitdb uses it as a git commit message)
// or include it in logs. It returns an empty string when no message was set.
Message() string
// SetMessage sets (replaces) the transaction message. It can be used at
// transaction start via TxWithMessage, or during transaction execution.
// It is available on both readonly and read-write transactions.
SetMessage(message string)
// IsolationLevel indicates requested isolation level
IsolationLevel() TxIsolationLevel
// IsReadonly indicates a readonly transaction
IsReadonly() bool
// IsCrossGroup indicates a cross-group transaction. Makes sense for Google App Engine.
IsCrossGroup() bool
// Attempts returns number of attempts to execute a transaction. This is used in Google Datastore for example.
Attempts() int
}
TransactionOptions holds transaction settings
func NewTransactionOptions ¶
func NewTransactionOptions(opts ...TransactionOption) TransactionOptions
NewTransactionOptions creates instance of TransactionOptions
type Transform ¶
type Transform interface {
// Name returns Name of a transform
Name() string
// Value returns arguments of transform
Value() any
}
Transform defines a transform operation
func ArrayUnion ¶
ArrayUnion specifies elements to be added to whatever array already exists in the server, or to create an array if no value exists.
If a value exists and it's an array, values are appended to it. Any duplicate value is ignored. If a value exists and it's not an array, the value is replaced by an array of the values in the ArrayUnion. If a value does not exist, an array of the values in the ArrayUnion is created.
ArrayUnion must be the value of a field directly; it cannot appear in array or struct values, or in any value that is itself inside an array or struct.
func IsTransform ¶
type TxIsolationLevel ¶
type TxIsolationLevel int
TxIsolationLevel defines an isolation level for a transaction
const ( // TxUnspecified indicates transaction level is not specified TxUnspecified TxIsolationLevel = iota // TxChaos - The pending changes from more highly isolated transactions cannot be overwritten. TxChaos // TxReadCommitted - Shared locks are held while the data is being read to avoid dirty reads, // but the data can be changed before the end of the transaction, // resulting in non-repeatable reads or phantom data. TxReadCommitted // TxReadUncommitted - A dirty read is possible, meaning that no shared locks are issued // and no exclusive locks are honored. TxReadUncommitted // TxRepeatableRead - Locks are placed on all data that is used in a query, // preventing other users from updating the data. // Prevents non-repeatable reads but phantom rows are still possible. TxRepeatableRead // TxSerializable - A range lock is placed on the DataSet, preventing other users // from updating or inserting rows intoRecord the dataset until the transaction is complete. TxSerializable // TxSnapshot - Reduces blocking by storing a version of data that one application can read // while another is modifying the same data. // Indicates that from one transaction you cannot see changes made in other transactions, // even if you requery. TxSnapshot )
type Updater ¶ added in v0.2.27
type Updater interface {
// Update updates a single record in a database by key
Update(ctx context.Context, key *record.Key, updates []update.Update, preconditions ...Precondition) error
// UpdateRecord updates a single record in a database.
// For example, this is useful in case if we want to put the record.Data to memcache.
// See https://github.com/dal-go/dalgo-memcache-appengine
// A regular DB adapter should call update(record.Key()) inside this method.
UpdateRecord(ctx context.Context, record record.Record, updates []update.Update, preconditions ...Precondition) error
}
Updater defines a function to update a single record in database by key
type ValidatableRecord ¶ added in v0.2.9
type ValidatableRecord interface {
Validate() error
}
ValidatableRecord is implemented by record data that can check its own invariants. The framework write pipeline (see NewDB) calls Validate before a record reaches the storage adapter, so an adapter never gets the chance to skip it.
type WriteSession ¶
type WriteSession interface {
Setter
MultiSetter
Deleter
MultiDeleter
Updater
MultiUpdater
Inserter
MultiInserter
}
WriteSession defines methods that can modify database
func WithoutValidation ¶ added in v0.64.0
func WithoutValidation(s WriteSession) WriteSession
WithoutValidation returns a write session that performs writes without validating record data. Registered hooks still run: this opts out of validation, not out of the pipeline.
It exists because some writes legitimately must skip validation — repair migrations, bulk import, writing a record that is known invalid in order to fix it later. The point is not to permit skipping but to make it visible and greppable at the call site instead of invisible inside an adapter:
if err := dal.WithoutValidation(tx).Set(ctx, rec); err != nil {
A session that is not framework-managed has no validation to skip and is returned unchanged.
Source Files
¶
- adapter.go
- batching.go
- changes.go
- collection.go
- concurrency.go
- connection.go
- data_wrapper.go
- db_database.go
- db_new.go
- errors.go
- field.go
- get_record_with_id_into_data.go
- hooks.go
- id_generator.go
- insert_record_with_data_and_id.go
- key_options.go
- precondition.go
- q_array.go
- q_builder.go
- q_collection_group_ref.go
- q_collection_ref.go
- q_column.go
- q_conditions.go
- q_constant.go
- q_expression.go
- q_field.go
- q_field_ref.go
- q_functions.go
- q_group_condition.go
- q_id.go
- q_operator.go
- q_recordset_source.go
- q_text.go
- query.go
- query_executor.go
- query_select_funcs.go
- query_struct.go
- reader.go
- reader_empty.go
- reader_read_all.go
- reader_slice_records.go
- schema.go
- schema_extra_field.go
- session.go
- transaction.go
- transform.go
- tx_deleter.go
- tx_getter.go
- tx_inserter.go
- tx_setter.go
- tx_updater.go
- unions.go
- with_hooks.go
- with_hooks_error.go
- write_pipeline.go