github.com/cosmos/cosmos-sdk@v0.50.10/x/group/internal/orm/README.md (about) 1 # Group ORM 2 3 The orm package provides a framework for creating relational database tables with primary and secondary keys. 4 5 ## Contents 6 7 * [Table](#table) 8 * [AutoUInt64Table](#autouint64table) 9 * [PrimaryKeyTable](#primarykeytable) 10 * [PrimaryKeyed](#primarykeyed) 11 * [Key codec](#key-codec) 12 * [Secondary Index](#secondary-index) 13 * [MultiKeyIndex](#multikeyindex) 14 * [UniqueIndex](#uniqueindex) 15 * [Iterator and Pagination](#iterator-and-pagination) 16 * [Iterator](#iterator) 17 * [Pagination](#pagination) 18 19 ## Table 20 21 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. 22 23 ```go reference 24 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/table.go#L30-L36 25 ``` 26 27 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. 28 Regular CRUD operations can be performed on a table, these methods take a `sdk.KVStore` as parameter to get the table prefix store. 29 30 The `table` struct does not: 31 32 * enforce uniqueness of the `RowID` 33 * enforce prefix uniqueness of keys, i.e. not allowing one key to be a prefix of another 34 * optimize Gas usage conditions 35 36 The `table` struct is private, so that we only have custom tables built on top of it, that do satisfy these requirements. 37 38 `table` provides methods for exporting (using a [`PrefixScan` `Iterator`](03_iterator_pagination.md#iterator)) and importing genesis data. For the import to be successful, objects have to be aware of their primary key by implementing the [`PrimaryKeyed`](#primarykeyed) interface. 39 40 ### AutoUInt64Table 41 42 `AutoUInt64Table` is a table type with an auto incrementing `uint64` ID. 43 44 ```go reference 45 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/auto_uint64.go#L15-L18 46 ``` 47 48 It's based on the `Sequence` struct which is a persistent unique key generator based on a counter encoded using 8 byte big endian. 49 50 ### PrimaryKeyTable 51 52 `PrimaryKeyTable` provides simpler object style orm methods where are persisted and loaded with a reference to their unique primary key. 53 54 #### PrimaryKeyed 55 56 The model provided for creating a `PrimaryKeyTable` should implement the `PrimaryKeyed` interface: 57 58 ```go reference 59 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/primary_key.go#L30-L44 60 ``` 61 62 `PrimaryKeyFields()` method returns the list of key parts for a given object. 63 The primary key parts can be []byte, string, and `uint64` types. 64 65 #### Key codec 66 67 Key parts, except the last part, follow these rules: 68 69 * []byte is encoded with a single byte length prefix (which means the max []byte length is 255) 70 * strings are null-terminated 71 * `uint64` are encoded using 8 byte big endian. 72 73 ## Secondary Index 74 75 Secondary indexes can be used on `Indexable` [tables](01_table.md). 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. 76 77 ```go reference 78 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/types.go#L88-L93 79 ``` 80 81 ### MultiKeyIndex 82 83 A `MultiKeyIndex` is an index where multiple entries can point to the same underlying object. 84 85 ```go reference 86 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/index.go#L26-L32 87 ``` 88 89 Internally, it uses an `Indexer` that manages the persistence of the index based on searchable keys and create/update/delete operations. 90 91 ```go reference 92 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/index.go#L15-L20 93 ``` 94 95 ```go reference 96 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/indexer.go#L15-L19 97 ``` 98 99 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](01_table.md#key-codec) which defines specific encoding for those types. 100 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. 101 102 ### UniqueIndex 103 104 As opposed to `MultiKeyIndex`, `UniqueIndex` is an index where duplicate keys are prohibited. 105 106 ## Iterator and Pagination 107 108 Both [tables](01_table.md) and [secondary indexes](02_secondary_index.md) support iterating over a domain of keys, through `PrefixScan` or `ReversePrefixScan`, as well pagination. 109 110 ### Iterator 111 112 An `Iterator` allows iteration through a sequence of key value pairs. 113 114 ```go reference 115 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/types.go#L77-L85 116 ``` 117 118 Tables rely on a `typeSafeIterator` that is used by `PrefixScan` and `ReversePrefixScan` `table` methods to iterate through a range of `RowID`s. 119 120 ```go reference 121 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/table.go#L287-L291 122 ``` 123 124 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. 125 126 ```go reference 127 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/index.go#L233-L239 128 ``` 129 130 Under the hood, both use a prefix store `Iterator` (alias for tm-db `Iterator`). 131 132 ### Pagination 133 134 The `Paginate` function does pagination given an [`Iterator`](#iterator) and a `query.PageRequest`, and returns a `query.PageResponse`. 135 It unmarshals the results into the provided dest interface that should be a pointer to a slice of models. 136 137 ```go reference 138 https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/internal/orm/iterator.go#L102-L220 139 ``` 140 141 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`.