record

package module
v0.1.5 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 7 Imported by: 74

README

record

github.com/dal-go/record defines the small, persistence-neutral vocabulary for identifying records, carrying record data, and describing changes to records.

It exists so API, rendering, command, and facade layers can depend on a stable record model without importing database sessions, queries, transactions, or an adapter. Database access belongs to DALgo: DALgo accepts these values at its boundary and executes a record.Changes envelope through dal.ApplyChanges.

The module contains two packages:

  • record for identity, data, envelopes, and change batches.
  • record/update for declarative field-update commands.

API

Every exported type and function is listed below. Links lead to its API documentation.

record
Errors
Keys and composite IDs
Record envelopes
Change envelopes and data mapping
record/update

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidStringID = errors.New("record: invalid string ID")

ErrInvalidStringID indicates that a string ID cannot be represented as one unambiguous non-empty key-path segment by EscapeID.

View Source
var ErrNoError = errors.New("no error")

ErrNoError is the internal success sentinel used by Record state.

View Source
var ErrRecordExists = errors.New("record already exists")

ErrRecordExists indicates that an insert failed because a record with the same key already exists. It is the mirror image of ErrRecordNotFound: an adapter that can reliably tell "this key is taken" from any other insert failure wraps this sentinel (e.g. with fmt.Errorf("%w: %s", ErrRecordExists, key)) so callers can distinguish the two with errors.Is or IsAlreadyExists, instead of having to treat every insert failure as a duplicate key.

View Source
var ErrRecordNotFound = errors.New("record not found")

ErrRecordNotFound indicates that a requested record does not exist.

Functions

func AnyRecordWithError

func AnyRecordWithError(records ...Record) error

AnyRecordWithError returns the first non-not-found record error.

func DataToMap

func DataToMap(data any) (map[string]any, error)

DataToMap converts record data into a map keyed by field name. A db tag takes precedence over a json tag at the top level.

func EqualKeys

func EqualKeys(k1, k2 *Key) bool

EqualKeys reports whether two key paths are equal.

func EscapeID

func EscapeID(id string) string

EscapeID escapes a record ID for use in a key path.

func IsAlreadyExists

func IsAlreadyExists(err error) bool

IsAlreadyExists reports whether err represents a record that already exists. It positively identifies a duplicate-key conflict: true means the adapter itself classified this failure as one. False is NOT proof the failure was something else — an adapter that cannot yet distinguish a duplicate key from any other insert failure never returns ErrRecordExists, so it will report false here even on an actual conflict. Callers should use this predicate to detect a confirmed conflict, and keep treating an unclassified insert failure conservatively (i.e. not assume "not a conflict") until every adapter they rely on has adopted the sentinel.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err represents a missing record.

func MapToData

func MapToData(target any, src map[string]any) error

MapToData populates target from src. A db tag takes precedence over a json tag at the top level.

func ValidateStringID

func ValidateStringID(id string) error

ValidateStringID verifies that EscapeID can represent id as one stable, unambiguous key-path segment. A literal percent sign is reserved because EscapeID uses percent-encoded substitutions; accepting it would make values such as "a/b" and "a%2Fb" serialize to the same path.

Types

type Changes

type Changes struct {
	RecordsToUpdate []*Updates
	RecordsToDelete []*Key
	// contains filtered or unexported fields
}

Changes is an in-memory envelope of record mutations to be applied by a DAL facade.

func (*Changes) QueueForInsert

func (v *Changes) QueueForInsert(records ...Record)

QueueForInsert adds records to the insert queue.

func (*Changes) RecordsToInsert

func (v *Changes) RecordsToInsert() []Record

RecordsToInsert returns a copy of the queued insert records.

func (*Changes) Reset

func (v *Changes) Reset()

Reset clears all queued changes after successful application.

type DataWithID

type DataWithID[K comparable, D any] struct {
	WithID[K]
	Data D
}

DataWithID is a typed record envelope with strongly typed data.

func NewDataWithID

func NewDataWithID[K comparable, D any](id K, key *Key, data D) DataWithID[K, D]

NewDataWithID creates a typed data envelope. data must be a non-nil pointer or interface holding a struct or map.

type FieldVal

type FieldVal struct {
	Name  string `json:"NewFieldRef"`
	Value any    `json:"value"`
}

FieldVal holds a named component of a composite key.

func (FieldVal) Validate

func (v FieldVal) Validate() error

Validate validates the field value.

type Key

type Key struct {
	ID     any
	IDKind reflect.Kind
	// contains filtered or unexported fields
}

Key represents the full identity path of a record.

func NewIncompleteKey

func NewIncompleteKey(collection string, idKind reflect.Kind, parent *Key) *Key

NewIncompleteKey creates a key whose ID will be supplied later.

func NewKeyWithFields

func NewKeyWithFields(collection string, fields ...FieldVal) *Key

NewKeyWithFields creates a key with a composite ID.

func NewKeyWithID

func NewKeyWithID[T comparable](collection string, id T) *Key

NewKeyWithID creates a key with id.

func NewKeyWithOptions

func NewKeyWithOptions(collection string, options ...KeyOption) (*Key, error)

NewKeyWithOptions creates a key configured by options.

func NewKeyWithParentAndID

func NewKeyWithParentAndID[T comparable](parent *Key, collection string, id T) *Key

NewKeyWithParentAndID creates a key below parent with id.

func (*Key) Collection

func (k *Key) Collection() string

Collection returns k's collection name.

func (*Key) CollectionPath

func (k *Key) CollectionPath() string

CollectionPath returns the collection path of k.

func (*Key) Equal

func (k *Key) Equal(other *Key) bool

Equal reports whether k and other are equal.

func (*Key) Level

func (k *Key) Level() int

Level returns the number of ancestors of k.

func (*Key) Parent

func (k *Key) Parent() *Key

Parent returns the parent key, if any.

func (*Key) String

func (k *Key) String() string

String returns the serialized path of k.

func (*Key) Validate

func (k *Key) Validate() error

Validate validates k and its ancestors.

type KeyOption

type KeyOption func(*Key) error

KeyOption configures a Key during construction.

func WithFields

func WithFields(fields []FieldVal) KeyOption

WithFields sets composite key fields during construction.

func WithIntID

func WithIntID(id int) KeyOption

WithIntID sets an integer key ID during construction.

func WithKeyID

func WithKeyID[T comparable](id T) KeyOption

WithKeyID sets a key ID during construction.

func WithParentKey

func WithParentKey(parent *Key) KeyOption

WithParentKey sets a parent key during construction.

func WithStringID

func WithStringID(id string) KeyOption

WithStringID sets a string key ID during construction.

type Record

type Record interface {
	Key() *Key
	Error() error
	Exists() bool
	SetError(error) Record
	Data() any
	HasChanged() bool
	MarkAsChanged()
}

Record is a mutable envelope for record identity, data, and retrieval state.

func NewRecord

func NewRecord(key *Key) Record

NewRecord creates an envelope with key and no data target.

func NewRecordWithData

func NewRecordWithData(key *Key, data any) Record

NewRecordWithData creates an envelope carrying data the caller already has.

The error is set to ErrNoError because the data was supplied, not retrieved: there is nothing to wait for, so Data() may be read immediately. This is the same reasoning NewRecordWithIncompleteKey already applies. Contrast NewRecord, which creates an empty envelope awaiting a load and deliberately leaves the error unset so Data() panics until a loader has said how the load went.

func NewRecordWithIncompleteKey

func NewRecordWithIncompleteKey(collection string, idKind reflect.Kind, data any) Record

NewRecordWithIncompleteKey creates an envelope for a record whose ID will be supplied later.

func NewRecordWithoutKey

func NewRecordWithoutKey(data any) Record

NewRecordWithoutKey creates an envelope for data that has no key.

type Updates

type Updates struct {
	Record  Record
	Updates []update.Update
}

Updates is a declarative update command for one record.

type WithID

type WithID[K comparable] struct {
	ID     K      `json:"id"`
	FullID string `json:"fullID,omitempty"`
	Key    *Key   `json:"-"`
	Record Record `json:"-"`
}

WithID is a record envelope with a strongly typed ID.

func NewWithID

func NewWithID[K comparable](id K, key *Key, data any) WithID[K]

NewWithID creates a typed envelope around key and data.

func (WithID[K]) String

func (v WithID[K]) String() string

Directories

Path Synopsis
Package update defines persistence-neutral field update commands.
Package update defines persistence-neutral field update commands.

Jump to

Keyboard shortcuts

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