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  }