database

package
v1.2.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2023 License: MIT Imports: 2 Imported by: 0

README

Heirarchical Caching Data Model

The goals of the record package and the model generator are:

  1. Explicitly define a conceptual data model
  2. Generate types that mirror the conceptual data model
  3. Move caching into the data model

Conceptual Data Model

Entities

An entity is a record that is composed of a set of attributes. There are two basic categories of attributes: complex and simple. A complex attribute is one that itself has attributes, such as an entity or a chain. A simple attribute represents a single value or a simple collection of values. Since an attribute can be an entity, which itself has attributes, the data model is heirarchical.

Simple Attributes

Simple attributes are state or index attributes. A state attribute is considered to be part of the proper state of the entity, whereas index attributes exist soley to index other records.

Simple attributes can be atomic values, sets, or lists. Atomic values may themselves be structured, but they are persisted atomically so they are considered to be a single value by the CDM. Sets and lists are ordered and unordered collections of values, respectively.

Parameterized Attributes

An attribute of an entity may be parameterized. A parameterized attribute is effectively a map or dictionary where the key is a tuple of the parameters. For example, the root entity in a personnel database may have an attribute, Person, with the a string parameter, Name. accessed as model.Person(name).

Implementation

The generator produces a struct type for every entity, with a method for every attribute. The return type for a complex attribute is the corresponding entity struct type. The return type for a simple attribute is one of the simple attribute types defined in the record package. Parameterized attributes are backed by a map and single-valued attributes are backed by a simple field. The first time an attribute is accessed, an object of the appropriate type is created. Subsequent accesses will return the same object.

Example

The following is an example of a data model that could be used to track personnel.

- name: Model
  type: entity
  root: true
  attributes:
    - name: Person
      type: entity
      parameters:
        - name: Surname
          type: string
        - name: GivenName
          type: string
      attributes:
        - name: State
          type: state
          dataType: PersonState
          pointer: true
        - name: Dependents
          type: state
          dataType: string
          collection: set
type Model struct{...}

func (*Model) Person(surname, givenName string) *ModelPerson

type ModelPerson struct{...}

func (*ModelPerson) State() *record.Value[*PersonState]
func (*ModelPerson) Dependents() *record.Set[string]

Documentation

Overview

Package database defines the interfaces used for data storage.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Key

type Key = record.Key

A Key is the key for a record.

func NewKey

func NewKey(v ...any) *Key

type Record

type Record interface {
	// Key returns the record's key.
	Key() *Key

	// Resolve resolves the record or a child record.
	Resolve(key *Key) (Record, *Key, error)

	// IsDirty returns true if the record has been modified.
	IsDirty() bool

	// Commit writes any modifications to the store.
	Commit() error

	// Walk walks the record.
	//
	// If the record is clean and opts.Changes is set, Walk returns immediately,
	// without calling the callback or recursing. Otherwise if the record is
	// terminal (not composite), Walk calls the callback on the record. The
	// behavior of Walk for a composite record depends on opts.Values, though
	// the first condition (return immediately if clean and opts.Changes is set)
	// still holds. If opts.Values is set, Walk calls the callback for every
	// component of the record but not for the composite record itself. If
	// opts.Values is not set, Walk calls the callback on the composite record.
	// If the callback returns skip = true, Walk returns immediately. Otherwise,
	// Walk calls the callback for every component of the record.
	Walk(opts WalkOptions, fn WalkFunc) error
}

A Record is a component of a data model.

type Store

type Store interface {
	// GetValue loads the value from the underlying store and writes it. Byte
	// stores call LoadBytes(data) and value stores call LoadValue(v, false).
	GetValue(key *record.Key, value Value) error

	// PutValue gets the value from the reader and stores it. A byte store
	// marshals the value and stores the bytes. A value store finds the
	// appropriate value and calls LoadValue(v, true).
	PutValue(key *record.Key, value Value) error
}

A Store loads and stores values.

type Value

type Value interface {
	Record

	// GetValue returns the value.
	GetValue() (value encoding.BinaryValue, version int, err error)

	// LoadValue stores the value of the reader into the receiver.
	LoadValue(value Value, put bool) error

	// LoadBytes unmarshals a value from bytes into the receiver.
	LoadBytes(data []byte, put bool) error
}

A Value is a terminal record value.

type WalkFunc

type WalkFunc = func(Record) (skip bool, err error)

type WalkOptions

type WalkOptions struct {
	// Values indicates the callback should only be called for values, not
	// composite records.
	Values bool

	// Modified skips records that have not been modified.
	Modified bool

	// IgnoreIndices skips index records.
	IgnoreIndices bool
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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