orm

package
v0.0.0-...-a6871c7 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2024 License: Apache-2.0 Imports: 15 Imported by: 0

README

Group ORM

The orm package provides a framework for creating relational database tables with primary and secondary keys.

Contents

Table

A table can be built given a codec.ProtoMarshaler model type, a prefix to access the underlying prefix store used to store table data as well as a Codec for marshalling/unmarshalling.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/table.go#L30-L36

In the prefix store, entities should be stored by an unique identifier called RowID which can be based either on an uint64 auto-increment counter, string or dynamic size bytes. Regular CRUD operations can be performed on a table, these methods take a sdk.KVStore as parameter to get the table prefix store.

The table struct does not:

  • enforce uniqueness of the RowID
  • enforce prefix uniqueness of keys, i.e. not allowing one key to be a prefix of another
  • optimize Gas usage conditions

The table struct is private, so that we only have custom tables built on top of it, that do satisfy these requirements.

table provides methods for exporting (using a PrefixScan Iterator) and importing genesis data. For the import to be successful, objects have to be aware of their primary key by implementing the PrimaryKeyed interface.

AutoUInt64Table

AutoUInt64Table is a table type with an auto incrementing uint64 ID.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/auto_uint64.go#L15-L18

It's based on the Sequence struct which is a persistent unique key generator based on a counter encoded using 8 byte big endian.

PrimaryKeyTable

PrimaryKeyTable provides simpler object style orm methods where are persisted and loaded with a reference to their unique primary key.

PrimaryKeyed

The model provided for creating a PrimaryKeyTable should implement the PrimaryKeyed interface:

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/primary_key.go#L30-L44

PrimaryKeyFields() method returns the list of key parts for a given object. The primary key parts can be []byte, string, and uint64 types.

Key codec

Key parts, except the last part, follow these rules:

  • []byte is encoded with a single byte length prefix (which means the max []byte length is 255)
  • strings are null-terminated
  • uint64 are encoded using 8 byte big endian.

Secondary Index

Secondary indexes can be used on Indexable tables. Indeed, those tables implement the Indexable interface that provides a set of functions that can be called by indexes to register and interact with the tables, like callback functions that are called on entries creation, update or deletion to create, update or remove corresponding entries in the table secondary indexes.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/types.go#L88-L93
MultiKeyIndex

A MultiKeyIndex is an index where multiple entries can point to the same underlying object.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/index.go#L26-L32

Internally, it uses an Indexer that manages the persistence of the index based on searchable keys and create/update/delete operations.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/index.go#L15-L20
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/indexer.go#L15-L19

The currently used implementation of an indexer, Indexer, relies on an IndexerFunc that should be provided when instantiating the index. Based on the source object, this function returns one or multiple index keys as []interface{}. Such secondary index keys should be bytes, string or uint64 in order to be handled properly by the key codec which defines specific encoding for those types. In the index prefix store, the keys are built based on the source object's RowID and its secondary index key(s) using the key codec and the values are set as empty bytes.

UniqueIndex

As opposed to MultiKeyIndex, UniqueIndex is an index where duplicate keys are prohibited.

Iterator and Pagination

Both tables and secondary indexes support iterating over a domain of keys, through PrefixScan or ReversePrefixScan, as well pagination.

Iterator

An Iterator allows iteration through a sequence of key value pairs.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/types.go#L77-L85

Tables rely on a typeSafeIterator that is used by PrefixScan and ReversePrefixScan table methods to iterate through a range of RowIDs.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/table.go#L287-L291

Secondary indexes rely on an indexIterator that can strip the RowID from the full index key in order to get the underlying value in the table prefix store.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/index.go#L233-L239

Under the hood, both use a prefix store Iterator (alias for tm-db Iterator).

Pagination

The Paginate function does pagination given an Iterator and a query.PageRequest, and returns a query.PageResponse. It unmarshals the results into the provided dest interface that should be a pointer to a slice of models.

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/iterator.go#L102-L220

Secondary indexes have a GetPaginated method that returns an Iterator for the given searched secondary index key, starting from the query.PageRequest key if provided. It's important to note that this query.PageRequest key should be a RowID (that could have been returned by a previous paginated request). The returned Iterator can then be used with the Paginate function and the same query.PageRequest.

Documentation

Overview

Package orm is a convenient object to data store mapper.

Index

Constants

View Source
const EncodedSeqLength = 8

EncodedSeqLength number of bytes used for the binary representation of a sequence value.

View Source
const MaxBytesLen = 255

MaxBytesLen is the maximum allowed length for a key part of type []byte

Variables

This section is empty.

Functions

func AddLengthPrefix

func AddLengthPrefix(bytes []byte) []byte

AddLengthPrefix prefixes the byte array with its length as 8 bytes. The function will panic if the bytes length is bigger than 255.

func DecodeSequence

func DecodeSequence(bz []byte) uint64

DecodeSequence converts the binary representation into an Uint64 value.

func EncodeSequence

func EncodeSequence(val uint64) []byte

EncodeSequence converts the sequence value into the binary representation.

func NullTerminatedBytes

func NullTerminatedBytes(s string) []byte

NullTerminatedBytes converts string to byte array and null terminate it

func Paginate

func Paginate(
	it Iterator,
	pageRequest *query.PageRequest,
	dest ModelSlicePtr,
) (*query.PageResponse, error)

Paginate does pagination with a given Iterator based on the provided PageRequest and unmarshals the results into the dest interface that must be an non-nil pointer to a slice.

If pageRequest is nil, then we will use these default values:

  • Offset: 0
  • Key: nil
  • Limit: 100
  • CountTotal: true

If pageRequest.Key was provided, it got used beforehand to instantiate the Iterator, using for instance UInt64Index.GetPaginated method. Only one of pageRequest.Offset or pageRequest.Key should be set. Using pageRequest.Key is more efficient for querying the next page.

If pageRequest.CountTotal is set, we'll visit all iterators elements. pageRequest.CountTotal is only respected when offset is used.

This function will call it.Close().

func PrefixRange

func PrefixRange(prefix []byte) ([]byte, []byte)

PrefixRange turns a prefix into a (start, end) range. The start is the given prefix value and the end is calculated by adding 1 bit to the start value. Nil is not allowed as prefix.

Example: []byte{1, 3, 4} becomes []byte{1, 3, 5}
		 []byte{15, 42, 255, 255} becomes []byte{15, 43, 0, 0}

In case of an overflow the end is set to nil.

Example: []byte{255, 255, 255, 255} becomes nil

func PrimaryKey

func PrimaryKey(obj PrimaryKeyed, addressCodec address.Codec) []byte

PrimaryKey returns the immutable and serialized primary key of this object. The primary key has to be unique within it's domain so that not two with same value can exist in the same table. This means PrimaryKeyFields() has to return a unique value for each object.

Types

type AfterDeleteInterceptor

type AfterDeleteInterceptor func(store storetypes.KVStore, rowID RowID, value proto.Message) error

AfterDeleteInterceptor defines a callback function to be called on Delete operations.

type AfterSetInterceptor

type AfterSetInterceptor func(store storetypes.KVStore, rowID RowID, newValue, oldValue proto.Message) error

AfterSetInterceptor defines a callback function to be called on Create + Update.

type AutoUInt64Table

type AutoUInt64Table struct {
	// contains filtered or unexported fields
}

AutoUInt64Table is the table type with an auto incrementing ID.

func NewAutoUInt64Table

func NewAutoUInt64Table(prefixData [2]byte, prefixSeq byte, model proto.Message, cdc codec.Codec, addressCodec address.Codec) (*AutoUInt64Table, error)

NewAutoUInt64Table creates a new AutoUInt64Table.

func (AutoUInt64Table) AddAfterDeleteInterceptor

func (a AutoUInt64Table) AddAfterDeleteInterceptor(interceptor AfterDeleteInterceptor)

AddAfterDeleteInterceptor can be used to register a callback function that is executed after an object is deleted.

func (AutoUInt64Table) AddAfterSetInterceptor

func (a AutoUInt64Table) AddAfterSetInterceptor(interceptor AfterSetInterceptor)

AddAfterSetInterceptor can be used to register a callback function that is executed after an object is created and/or updated.

func (AutoUInt64Table) Create

func (a AutoUInt64Table) Create(store storetypes.KVStore, obj proto.Message) (uint64, error)

Create a new persistent object with an auto generated uint64 primary key. The key is returned.

Create iterates through the registered callbacks that may add secondary index keys.

func (AutoUInt64Table) Delete

func (a AutoUInt64Table) Delete(store storetypes.KVStore, rowID uint64) error

Delete removes the object under the rowID key. It expects the key to exists already and fails with a `ErrNotFound` otherwise. Any caller must therefore make sure that this contract is fulfilled.

Delete iterates though the registered callbacks and removes secondary index keys by them.

func (AutoUInt64Table) Export

func (a AutoUInt64Table) Export(store storetypes.KVStore, dest ModelSlicePtr) (uint64, error)

Export stores all the values in the table in the passed ModelSlicePtr and returns the current value of the associated sequence.

func (AutoUInt64Table) GetOne

func (a AutoUInt64Table) GetOne(store storetypes.KVStore, rowID uint64, dest proto.Message) (RowID, error)

GetOne load the object persisted for the given RowID into the dest parameter. If none exists `ErrNotFound` is returned instead. Parameters must not be nil.

func (AutoUInt64Table) Has

func (a AutoUInt64Table) Has(store storetypes.KVStore, rowID uint64) bool

Has checks if a rowID exists.

func (AutoUInt64Table) Import

func (a AutoUInt64Table) Import(store storetypes.KVStore, data interface{}, seqValue uint64) error

Import clears the table and initializes it from the given data interface{}. data should be a slice of structs that implement PrimaryKeyed.

func (AutoUInt64Table) PrefixScan

func (a AutoUInt64Table) PrefixScan(store storetypes.KVStore, start, end uint64) (Iterator, error)

PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. Iterator must be closed by caller. To iterate over entire domain, use PrefixScan(1, math.MaxUint64)

WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose this as an endpoint to the public without further limits. Example:

it, err := idx.PrefixScan(ctx, start, end)
if err !=nil {
	return err
}
const defaultLimit = 20
it = LimitIterator(it, defaultLimit)

CONTRACT: No writes may happen within a domain while an iterator exists over it.

func (AutoUInt64Table) ReversePrefixScan

func (a AutoUInt64Table) ReversePrefixScan(store storetypes.KVStore, start, end uint64) (Iterator, error)

ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. Iterator must be closed by caller. To iterate over entire domain, use PrefixScan(1, math.MaxUint64)

WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose this as an endpoint to the public without further limits. See `LimitIterator`

CONTRACT: No writes may happen within a domain while an iterator exists over it.

func (AutoUInt64Table) RowGetter

func (a AutoUInt64Table) RowGetter() RowGetter

RowGetter returns a type safe RowGetter.

func (AutoUInt64Table) Sequence

func (a AutoUInt64Table) Sequence() Sequence

Sequence returns the sequence used by this table

func (AutoUInt64Table) Set

func (a AutoUInt64Table) Set(store storetypes.KVStore, rowID RowID, newValue proto.Message) error

Set persists the given object under the rowID key. It does not check if the key already exists and overwrites the value if it does.

Set iterates through the registered callbacks that may add secondary index keys.

func (AutoUInt64Table) Update

func (a AutoUInt64Table) Update(store storetypes.KVStore, rowID uint64, newValue proto.Message) error

Update updates the given object under the rowID key. It expects the key to exists already and fails with an `ErrNotFound` otherwise. Any caller must therefore make sure that this contract is fulfilled. Parameters must not be nil.

Update iterates through the registered callbacks that may add or remove secondary index keys.

type Index

type Index interface {
	// Has checks if a key exists. Panics on nil key.
	Has(store storetypes.KVStore, key interface{}) (bool, error)

	// Get returns a result iterator for the searchKey.
	// searchKey must not be nil.
	Get(store storetypes.KVStore, searchKey interface{}) (Iterator, error)

	// GetPaginated returns a result iterator for the searchKey and optional pageRequest.
	// searchKey must not be nil.
	GetPaginated(store storetypes.KVStore, searchKey interface{}, pageRequest *query.PageRequest) (Iterator, error)

	// PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive.
	// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned.
	// Iterator must be closed by caller.
	// To iterate over entire domain, use PrefixScan(nil, nil)
	//
	// WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose
	// this as an endpoint to the public without further limits.
	// Example:
	//			it, err := idx.PrefixScan(ctx, start, end)
	//			if err !=nil {
	//				return err
	//			}
	//			const defaultLimit = 20
	//			it = LimitIterator(it, defaultLimit)
	//
	// CONTRACT: No writes may happen within a domain while an iterator exists over it.
	PrefixScan(store storetypes.KVStore, startI, endI interface{}) (Iterator, error)

	// ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive.
	// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid  and error is returned.
	// Iterator must be closed by caller.
	// To iterate over entire domain, use PrefixScan(nil, nil)
	//
	// WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose
	// this as an endpoint to the public without further limits. See `LimitIterator`
	//
	// CONTRACT: No writes may happen within a domain while an iterator exists over it.
	ReversePrefixScan(store storetypes.KVStore, startI, endI interface{}) (Iterator, error)
}

Index allows efficient prefix scans is stored as key = concat(indexKeyBytes, rowIDUint64) with value empty so that the row PrimaryKey is allows a fixed with 8 byte integer. This allows the MultiKeyIndex key bytes to be variable length and scanned iteratively.

type Indexable

type Indexable interface {
	RowGetter() RowGetter
	AddAfterSetInterceptor(interceptor AfterSetInterceptor)
	AddAfterDeleteInterceptor(interceptor AfterDeleteInterceptor)
}

Indexable types are used to setup new tables. This interface provides a set of functions that can be called by indexes to register and interact with the tables.

type Indexer

type Indexer struct {
	// contains filtered or unexported fields
}

Indexer manages the persistence of an Index based on searchable keys and operations.

func NewIndexer

func NewIndexer(indexerFunc IndexerFunc) (*Indexer, error)

NewIndexer returns an indexer that supports multiple reference keys for an entity.

func NewUniqueIndexer

func NewUniqueIndexer(f UniqueIndexerFunc) (*Indexer, error)

NewUniqueIndexer returns an indexer that requires exactly one reference keys for an entity.

func (Indexer) IndexerFunc

func (i Indexer) IndexerFunc() IndexerFunc

IndexerFunc returns the indexer IndexerFunc, ensuring it has been prune from empty keys.

func (Indexer) OnCreate

func (i Indexer) OnCreate(store storetypes.KVStore, rowID RowID, value interface{}) error

OnCreate persists the secondary index entries for the new object.

func (Indexer) OnDelete

func (i Indexer) OnDelete(store storetypes.KVStore, rowID RowID, value interface{}) error

OnDelete removes the secondary index entries for the deleted object.

func (Indexer) OnUpdate

func (i Indexer) OnUpdate(store storetypes.KVStore, rowID RowID, newValue, oldValue interface{}) error

OnUpdate rebuilds the secondary index entries for the updated object.

type IndexerFunc

type IndexerFunc func(value interface{}) ([]interface{}, error)

IndexerFunc creates one or multiple index keys for the source object.

type Iterator

type Iterator interface {
	// LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there
	// are no more items the ErrORMIteratorDone error is returned
	// The key is the rowID.
	LoadNext(dest proto.Message) (RowID, error)
	// Close releases the iterator and should be called at the end of iteration
	io.Closer
}

Iterator allows iteration through a sequence of key value pairs

func NewInvalidIterator

func NewInvalidIterator() Iterator

Iterator that return ErrORMInvalidIterator only.

func NewSingleValueIterator

func NewSingleValueIterator(rowID RowID, val []byte) Iterator

type IteratorFunc

type IteratorFunc func(dest proto.Message) (RowID, error)

IteratorFunc is a function type that satisfies the Iterator interface The passed function is called on LoadNext operations.

func (IteratorFunc) Close

func (i IteratorFunc) Close() error

Close always returns nil

func (IteratorFunc) LoadNext

func (i IteratorFunc) LoadNext(dest proto.Message) (RowID, error)

LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there are no more items the errors.ErrORMIteratorDone error is returned The key is the rowID and not any MultiKeyIndex key.

type LimitedIterator

type LimitedIterator struct {
	// contains filtered or unexported fields
}

LimitedIterator returns up to defined maximum number of elements.

func LimitIterator

func LimitIterator(parent Iterator, max int) (*LimitedIterator, error)

LimitIterator returns a new iterator that returns max number of elements. The parent iterator must not be nil max can be 0 or any positive number

func (LimitedIterator) Close

func (i LimitedIterator) Close() error

Close releases the iterator and should be called at the end of iteration

func (*LimitedIterator) LoadNext

func (i *LimitedIterator) LoadNext(dest proto.Message) (RowID, error)

LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there are no more items or the defined max number of elements was returned the `errors.ErrORMIteratorDone` error is returned The key is the rowID and not any MultiKeyIndex key.

type ModelSlicePtr

type ModelSlicePtr interface{}

ModelSlicePtr represents a pointer to a slice of models. Think of it as *[]Model Because of Go's type system, using []Model type would not work for us. Instead we use a placeholder type and the validation is done during the runtime.

type MultiKeyIndex

type MultiKeyIndex struct {
	// contains filtered or unexported fields
}

MultiKeyIndex is an index where multiple entries can point to the same underlying object as opposite to a unique index where only one entry is allowed.

func NewIndex

func NewIndex(tb Indexable, prefix byte, indexerF IndexerFunc, indexKey interface{}) (MultiKeyIndex, error)

NewIndex builds a MultiKeyIndex. Only single-field indexes are supported and `indexKey` represents such a field value, which can be []byte, string or uint64.

func (MultiKeyIndex) Get

func (i MultiKeyIndex) Get(store storetypes.KVStore, searchKey interface{}) (Iterator, error)

Get returns a result iterator for the searchKey. Parameters must not be nil.

func (MultiKeyIndex) GetPaginated

func (i MultiKeyIndex) GetPaginated(store storetypes.KVStore, searchKey interface{}, pageRequest *query.PageRequest) (Iterator, error)

GetPaginated creates an iterator for the searchKey starting from pageRequest.Key if provided. The pageRequest.Key is the rowID while searchKey is a MultiKeyIndex key.

func (MultiKeyIndex) Has

func (i MultiKeyIndex) Has(store storetypes.KVStore, key interface{}) (bool, error)

Has checks if a key exists. Returns an error on nil key.

func (MultiKeyIndex) PrefixScan

func (i MultiKeyIndex) PrefixScan(store storetypes.KVStore, startI, endI interface{}) (Iterator, error)

PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. Iterator must be closed by caller. To iterate over entire domain, use PrefixScan(nil, nil)

WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose this as an endpoint to the public without further limits. Example:

it, err := idx.PrefixScan(ctx, start, end)
if err !=nil {
	return err
}
const defaultLimit = 20
it = LimitIterator(it, defaultLimit)

CONTRACT: No writes may happen within a domain while an iterator exists over it.

func (MultiKeyIndex) ReversePrefixScan

func (i MultiKeyIndex) ReversePrefixScan(store storetypes.KVStore, startI, endI interface{}) (Iterator, error)

ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. Iterator must be closed by caller. To iterate over entire domain, use PrefixScan(nil, nil)

WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose this as an endpoint to the public without further limits. See `LimitIterator`

CONTRACT: No writes may happen within a domain while an iterator exists over it.

type PrimaryKeyTable

type PrimaryKeyTable struct {
	// contains filtered or unexported fields
}

PrimaryKeyTable provides simpler object style orm methods without passing database RowIDs. Entries are persisted and loaded with a reference to their unique primary key.

func NewPrimaryKeyTable

func NewPrimaryKeyTable(prefixData [2]byte, model PrimaryKeyed, cdc codec.Codec, addressCodec address.Codec) (*PrimaryKeyTable, error)

NewPrimaryKeyTable creates a new PrimaryKeyTable.

func (PrimaryKeyTable) AddAfterDeleteInterceptor

func (a PrimaryKeyTable) AddAfterDeleteInterceptor(interceptor AfterDeleteInterceptor)

AddAfterDeleteInterceptor can be used to register a callback function that is executed after an object is deleted.

func (PrimaryKeyTable) AddAfterSetInterceptor

func (a PrimaryKeyTable) AddAfterSetInterceptor(interceptor AfterSetInterceptor)

AddAfterSetInterceptor can be used to register a callback function that is executed after an object is created and/or updated.

func (PrimaryKeyTable) Contains

func (a PrimaryKeyTable) Contains(store storetypes.KVStore, obj PrimaryKeyed) bool

Contains returns true when an object with same type and primary key is persisted in this table.

func (PrimaryKeyTable) Create

func (a PrimaryKeyTable) Create(store storetypes.KVStore, obj PrimaryKeyed) error

Create persists the given object under their primary key. It checks if the key already exists and may return an `ErrUniqueConstraint`.

Create iterates through the registered callbacks that may add secondary index keys.

func (PrimaryKeyTable) Delete

func (a PrimaryKeyTable) Delete(store storetypes.KVStore, obj PrimaryKeyed) error

Delete removes the object. It expects the primary key to exists already and fails with a `ErrNotFound` otherwise. Any caller must therefore make sure that this contract is fulfilled.

Delete iterates through the registered callbacks that remove secondary index keys.

func (PrimaryKeyTable) Export

func (a PrimaryKeyTable) Export(store storetypes.KVStore, dest ModelSlicePtr) (uint64, error)

Export stores all the values in the table in the passed ModelSlicePtr.

func (PrimaryKeyTable) GetOne

func (a PrimaryKeyTable) GetOne(store storetypes.KVStore, primKey RowID, dest proto.Message) error

GetOne loads the object persisted for the given primary Key into the dest parameter. If none exists `ErrNotFound` is returned instead. Parameters must not be nil.

func (PrimaryKeyTable) Has

func (a PrimaryKeyTable) Has(store storetypes.KVStore, primaryKey RowID) bool

Has checks if a key exists. Always returns false on nil or empty key.

func (PrimaryKeyTable) Import

func (a PrimaryKeyTable) Import(store storetypes.KVStore, data interface{}, seqValue uint64) error

Import clears the table and initializes it from the given data interface{}. data should be a slice of structs that implement PrimaryKeyed.

func (PrimaryKeyTable) PrefixScan

func (a PrimaryKeyTable) PrefixScan(store storetypes.KVStore, start, end []byte) (Iterator, error)

PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. Iterator must be closed by caller. To iterate over entire domain, use PrefixScan(nil, nil)

WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose this as an endpoint to the public without further limits. Example:

it, err := idx.PrefixScan(ctx, start, end)
if err !=nil {
	return err
}
const defaultLimit = 20
it = LimitIterator(it, defaultLimit)

CONTRACT: No writes may happen within a domain while an iterator exists over it.

func (PrimaryKeyTable) ReversePrefixScan

func (a PrimaryKeyTable) ReversePrefixScan(store storetypes.KVStore, start, end []byte) (Iterator, error)

ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. Iterator must be closed by caller. To iterate over entire domain, use PrefixScan(nil, nil)

WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose this as an endpoint to the public without further limits. See `LimitIterator`

CONTRACT: No writes may happen within a domain while an iterator exists over it.

func (PrimaryKeyTable) RowGetter

func (a PrimaryKeyTable) RowGetter() RowGetter

RowGetter returns a type safe RowGetter.

func (PrimaryKeyTable) Set

func (a PrimaryKeyTable) Set(store storetypes.KVStore, newValue PrimaryKeyed) error

Set persists the given object under the rowID key. It does not check if the key already exists and overwrites the value if it does.

Set iterates through the registered callbacks that may add secondary index keys.

func (PrimaryKeyTable) Update

func (a PrimaryKeyTable) Update(store storetypes.KVStore, newValue PrimaryKeyed) error

Update updates the given object under the primary key. It expects the key to exists already and fails with an `ErrNotFound` otherwise. Any caller must therefore make sure that this contract is fulfilled. Parameters must not be nil.

Update iterates through the registered callbacks that may add or remove secondary index keys.

type PrimaryKeyed

type PrimaryKeyed interface {
	// PrimaryKeyFields returns the fields of the object that will make up
	// the primary key. The PrimaryKey function will encode and concatenate
	// the fields to build the primary key.
	//
	// PrimaryKey parts can be []byte, string, and uint64 types. []byte is
	// encoded with a length prefix, strings are null-terminated, and
	// uint64 are encoded using 8 byte big endian.
	//
	// IMPORTANT: []byte parts are encoded with a single byte length prefix,
	// so cannot be longer than 255 bytes.
	PrimaryKeyFields(address.Codec) ([]interface{}, error)
	proto.Message
}

PrimaryKeyed defines an object type that is aware of its immutable primary key.

type RowGetter

type RowGetter func(store storetypes.KVStore, rowID RowID, dest proto.Message) error

RowGetter loads a persistent object by row ID into the destination object. The dest parameter must therefore be a pointer. Any implementation must return `sdkerrors.ErrNotFound` when no object for the rowID exists

func NewTypeSafeRowGetter

func NewTypeSafeRowGetter(prefixKey [2]byte, model reflect.Type, cdc codec.Codec) RowGetter

NewTypeSafeRowGetter returns a `RowGetter` with type check on the dest parameter.

type RowID

type RowID []byte

Unique identifier of a persistent table.

func First

func First(it Iterator, dest proto.Message) (RowID, error)

First loads the first element into the given destination type and closes the iterator. When the iterator is closed or has no elements the according error is passed as return value.

func ReadAll

func ReadAll(it Iterator, dest ModelSlicePtr) ([]RowID, error)

ReadAll consumes all values for the iterator and stores them in a new slice at the passed ModelSlicePtr. The slice can be empty when the iterator does not return any values but not nil. The iterator is closed afterwards. Example:

var loaded []testdata.GroupInfo
rowIDs, err := ReadAll(it, &loaded)
require.NoError(t, err)

func (RowID) Bytes

func (r RowID) Bytes() []byte

Bytes returns raw bytes.

type Sequence

type Sequence struct {
	// contains filtered or unexported fields
}

sequence is a persistent unique key generator based on a counter.

func NewSequence

func NewSequence(prefix byte) Sequence

func (Sequence) CurVal

func (s Sequence) CurVal(store storetypes.KVStore) uint64

CurVal returns the last value used. 0 if none.

func (Sequence) InitVal

func (s Sequence) InitVal(store storetypes.KVStore, seq uint64) error

InitVal sets the start value for the sequence. It must be called only once on an empty DB. Otherwise an error is returned when the key exists. The given start value is stored as current value.

It is recommended to call this method only for a sequence start value other than `1` as the method consumes unnecessary gas otherwise. A scenario would be an import from genesis.

func (Sequence) NextVal

func (s Sequence) NextVal(store storetypes.KVStore) uint64

NextVal increments and persists the counter by one and returns the value.

func (Sequence) PeekNextVal

func (s Sequence) PeekNextVal(store storetypes.KVStore) uint64

PeekNextVal returns the CurVal + increment step. Not persistent.

type TableExportable

type TableExportable interface {
	// Export stores all the values in the table in the passed
	// ModelSlicePtr. If the table has an associated sequence, then its
	// current value is returned, otherwise 0 is returned by default.
	Export(store storetypes.KVStore, dest ModelSlicePtr) (uint64, error)

	// Import clears the table and initializes it from the given data
	// interface{}. data should be a slice of structs that implement
	// PrimaryKeyed. The seqValue is optional and only
	// used with tables that have an associated sequence.
	Import(store storetypes.KVStore, data interface{}, seqValue uint64) error
}

TableExportable defines the methods to import and export a table.

type UniqueIndex

type UniqueIndex struct {
	MultiKeyIndex
}

func NewUniqueIndex

func NewUniqueIndex(tb Indexable, prefix byte, uniqueIndexerFunc UniqueIndexerFunc, indexKey interface{}) (UniqueIndex, error)

NewUniqueIndex create a new Index object where duplicate keys are prohibited.

type UniqueIndexerFunc

type UniqueIndexerFunc func(value interface{}) (interface{}, error)

IndexerFunc creates exactly one index key for the source object.

type Validateable

type Validateable interface {
	// ValidateBasic is a sanity check on the data. Any error returned prevents create or updates.
	ValidateBasic() error
}

Validateable is an interface that ProtoMarshaler types can implement and is called on any orm save or update operation.

Directories

Path Synopsis
Package prefixstore provides a store that prefixes all keys with a given prefix.
Package prefixstore provides a store that prefixes all keys with a given prefix.

Jump to

Keyboard shortcuts

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