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`.