github.com/cosmos/cosmos-sdk@v0.50.10/x/group/internal/orm/primary_key.go (about) 1 package orm 2 3 import ( 4 "github.com/cosmos/gogoproto/proto" 5 6 storetypes "cosmossdk.io/store/types" 7 8 "github.com/cosmos/cosmos-sdk/codec" 9 ) 10 11 var ( 12 _ Indexable = &PrimaryKeyTable{} 13 _ TableExportable = &PrimaryKeyTable{} 14 ) 15 16 // PrimaryKeyTable provides simpler object style orm methods without passing database RowIDs. 17 // Entries are persisted and loaded with a reference to their unique primary key. 18 type PrimaryKeyTable struct { 19 *table 20 } 21 22 // NewPrimaryKeyTable creates a new PrimaryKeyTable. 23 func NewPrimaryKeyTable(prefixData [2]byte, model PrimaryKeyed, cdc codec.Codec) (*PrimaryKeyTable, error) { 24 table, err := newTable(prefixData, model, cdc) 25 if err != nil { 26 return nil, err 27 } 28 return &PrimaryKeyTable{ 29 table: table, 30 }, nil 31 } 32 33 // PrimaryKeyed defines an object type that is aware of its immutable primary key. 34 type PrimaryKeyed interface { 35 // PrimaryKeyFields returns the fields of the object that will make up 36 // the primary key. The PrimaryKey function will encode and concatenate 37 // the fields to build the primary key. 38 // 39 // PrimaryKey parts can be []byte, string, and uint64 types. []byte is 40 // encoded with a length prefix, strings are null-terminated, and 41 // uint64 are encoded using 8 byte big endian. 42 // 43 // IMPORTANT: []byte parts are encoded with a single byte length prefix, 44 // so cannot be longer than 255 bytes. 45 PrimaryKeyFields() []interface{} 46 proto.Message 47 } 48 49 // PrimaryKey returns the immutable and serialized primary key of this object. 50 // The primary key has to be unique within it's domain so that not two with same 51 // value can exist in the same table. This means PrimaryKeyFields() has to 52 // return a unique value for each object. 53 func PrimaryKey(obj PrimaryKeyed) []byte { 54 fields := obj.PrimaryKeyFields() 55 key, err := buildKeyFromParts(fields) 56 if err != nil { 57 panic(err) 58 } 59 return key 60 } 61 62 // Create persists the given object under their primary key. It checks if the 63 // key already exists and may return an `ErrUniqueConstraint`. 64 // 65 // Create iterates through the registered callbacks that may add secondary 66 // index keys. 67 func (a PrimaryKeyTable) Create(store storetypes.KVStore, obj PrimaryKeyed) error { 68 rowID := PrimaryKey(obj) 69 return a.table.Create(store, rowID, obj) 70 } 71 72 // Update updates the given object under the primary key. It expects the key to 73 // exists already and fails with an `ErrNotFound` otherwise. Any caller must 74 // therefore make sure that this contract is fulfilled. Parameters must not be 75 // nil. 76 // 77 // Update iterates through the registered callbacks that may add or remove 78 // secondary index keys. 79 func (a PrimaryKeyTable) Update(store storetypes.KVStore, newValue PrimaryKeyed) error { 80 return a.table.Update(store, PrimaryKey(newValue), newValue) 81 } 82 83 // Set persists the given object under the rowID key. It does not check if the 84 // key already exists and overwrites the value if it does. 85 // 86 // Set iterates through the registered callbacks that may add secondary index 87 // keys. 88 func (a PrimaryKeyTable) Set(store storetypes.KVStore, newValue PrimaryKeyed) error { 89 return a.table.Set(store, PrimaryKey(newValue), newValue) 90 } 91 92 // Delete removes the object. It expects the primary key to exists already and 93 // fails with a `ErrNotFound` otherwise. Any caller must therefore make sure 94 // that this contract is fulfilled. 95 // 96 // Delete iterates through the registered callbacks that remove secondary index 97 // keys. 98 func (a PrimaryKeyTable) Delete(store storetypes.KVStore, obj PrimaryKeyed) error { 99 return a.table.Delete(store, PrimaryKey(obj)) 100 } 101 102 // Has checks if a key exists. Always returns false on nil or empty key. 103 func (a PrimaryKeyTable) Has(store storetypes.KVStore, primaryKey RowID) bool { 104 return a.table.Has(store, primaryKey) 105 } 106 107 // Contains returns true when an object with same type and primary key is persisted in this table. 108 func (a PrimaryKeyTable) Contains(store storetypes.KVStore, obj PrimaryKeyed) bool { 109 if err := assertCorrectType(a.table.model, obj); err != nil { 110 return false 111 } 112 return a.table.Has(store, PrimaryKey(obj)) 113 } 114 115 // GetOne loads the object persisted for the given primary Key into the dest parameter. 116 // If none exists `ErrNotFound` is returned instead. Parameters must not be nil. 117 func (a PrimaryKeyTable) GetOne(store storetypes.KVStore, primKey RowID, dest proto.Message) error { 118 return a.table.GetOne(store, primKey, dest) 119 } 120 121 // PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. 122 // Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. 123 // Iterator must be closed by caller. 124 // To iterate over entire domain, use PrefixScan(nil, nil) 125 // 126 // WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose 127 // this as an endpoint to the public without further limits. 128 // Example: 129 // 130 // it, err := idx.PrefixScan(ctx, start, end) 131 // if err !=nil { 132 // return err 133 // } 134 // const defaultLimit = 20 135 // it = LimitIterator(it, defaultLimit) 136 // 137 // CONTRACT: No writes may happen within a domain while an iterator exists over it. 138 func (a PrimaryKeyTable) PrefixScan(store storetypes.KVStore, start, end []byte) (Iterator, error) { 139 return a.table.PrefixScan(store, start, end) 140 } 141 142 // ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. 143 // Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. 144 // Iterator must be closed by caller. 145 // To iterate over entire domain, use PrefixScan(nil, nil) 146 // 147 // WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose 148 // this as an endpoint to the public without further limits. See `LimitIterator` 149 // 150 // CONTRACT: No writes may happen within a domain while an iterator exists over it. 151 func (a PrimaryKeyTable) ReversePrefixScan(store storetypes.KVStore, start, end []byte) (Iterator, error) { 152 return a.table.ReversePrefixScan(store, start, end) 153 } 154 155 // Export stores all the values in the table in the passed ModelSlicePtr. 156 func (a PrimaryKeyTable) Export(store storetypes.KVStore, dest ModelSlicePtr) (uint64, error) { 157 return a.table.Export(store, dest) 158 } 159 160 // Import clears the table and initializes it from the given data interface{}. 161 // data should be a slice of structs that implement PrimaryKeyed. 162 func (a PrimaryKeyTable) Import(store storetypes.KVStore, data interface{}, seqValue uint64) error { 163 return a.table.Import(store, data, seqValue) 164 }