Skip to main content

Secondary Index

Overview

This guide provides instructions to define a secondary index for a multi-index table.

Procedure

Complete the following steps to define a secondary index for the multi-index table datatable.

1. Extend The Multi-Index Data Structure

Add a second data member secondary, of type inery::name, to the data_structure data structure that defines the datatable data.

  struct [[inery::table]] data_structure {
// this data member stores a name for each row of the multi-index table
name test_primary;
+ name secondary;
// additional data stored in table row
uint64_t datum;
// mandatory definition for primary key getter
uint64_t primary_key( ) const { return test_primary.value; }
};

2. Add The Secondary Index Method

Add by_secondary() method, which is the index accessor method to the new data member added. The secondary index, that will be added in the next step, will index this new data structure data member.

  struct [[inery::table]] data_structure {
// this data member stores a name for each row of the multi-index table
name test_primary;
name secondary;
// additional data stored in table row
uint64_t datum;
// mandatory definition for primary key getter
uint64_t primary_key( ) const { return test_primary.value; }
+ uint64_t by_secondary( ) const { return secondary.value; }
};

3. Define The Secondary Index

In the data_structure_t type definition, add the definition of the secondary index with the use of the inery::indexed_by template. inery::index_by needs two parameters: the name of the index, "secid"_n, and a function call operator which extracts the value from the secondary data member as an index key. The function call operator is defined with the use of inery::const_mem_fun template which receives two parameters: the data structure data_structure and the reference to the getter function member by_secondary.

-  typedef inery::multi_index<"datatable"_n, data_structure> data_structure_t;
+ typedef inery::multi_index<"datatable"_n, data_structure, inery::indexed_by<"secid"_n, inery::const_mem_fun<data_structure, uint64_t, &data_structure::by_secondary>>> data_structure_t;

For reference see below the full contract definition code with all the changes described above.

multi_index_example.hpp

#include <inery/inery.hpp>
using namespace inery;

// multi-index example contract class
class [[inery::contract]] multi_index_example : public contract {
public:
using contract::contract;

// contract class constructor
multi_index_example( name receiver, name code, datastream<const char*> ds ) :
// contract base class contructor
contract(receiver, code, ds),
// instantiate multi-index instance as data member (find it defined below)
datatable(receiver, receiver.value)
{ }

struct [[inery::table]] data_structure {
// this data member stores a name for each row of the multi-index table
name test_primary;
name secondary;
// additional data stored in table row
uint64_t datum;
// mandatory definition for primary key getter
uint64_t primary_key( ) const { return test_primary.value; }
uint64_t by_secondary( ) const { return secondary.value; }
};

// the multi-index type definition, for ease of use a type alias `data_structure_t` is defined,
// based on the multi_index template type, parametarized with a random name, the
// data_structure data structure, and the secondary index
typedef inery::multi_index<"datatable"_n, data_structure, inery::indexed_by<"secid"_n, inery::const_mem_fun<data_structure, uint64_t, &data_structure::by_secondary>>> data_structure_t;

// the multi-index table instance declared as a data member of type data_structure_t
data_structure_t datatable;

[[inery::action]] void set( name user );
[[inery::action]] void print( name user );

};

Now you have instantiated the datatable as a multi-index table which has a primary index defined for its test_primary data member and a secondary index for its secondary data member.

Summary

In conclusion, the above instructions show how to define a secondary index for a multi-index table.