Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Docs/larryk85 kv fixes #1007

Merged
merged 12 commits into from
Dec 2, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ This how-to procedure demonstrates how to define and use a `Key-Value Table` (`k

To accomplish this task, define the user type which will be stored in the `kv table`, and extend the `eosio::kv::table` template class with a specialized definition based on the user defined type.

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

## Prerequisites

* The EOSIO development environment, for details consult the [Get Started](https://developers.eos.io/welcome/latest/getting-started/development-environment/introduction) Guide.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ This how-to procedure provides instructions to create the following indexes on a

The `KV_NAMED_INDEX` macro and the `eosio::kv::table::index` template class are provided by the KV API.

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

## Prerequisites

Before you begin, complete the following prerequisites:
Expand Down Expand Up @@ -107,10 +110,10 @@ class [[eosio::contract]] smrtcontract : public contract {
### Define a non-unique index on property first_name using the macro KV_NAMED_INDEX

1. Use the `KV_NAMED_INDEX` with two parameters.
2. Pass the name of the index as the first parameter. The parameter must be a qualified `eosio:name`. See documentation for the [eosio name restrictions](https://developers.eos.io/welcome/latest/glossary/index#account-name).
2. Pass the name of the index as the first parameter. The parameter must be a qualified `eosio::name`. See documentation for the [eosio name restrictions](https://developers.eos.io/welcome/latest/glossary/index#account-name).
3. Pass the name of the property for which the index is defined as the second parameter.

The property used for the second parameter must be of template type `eosio::non_unique`. The first parameter of the template type must be the type of a property name which is unique. In our case the type `eosio::name` is used because property`account_name` is unique. And the second parameter must be the type of the property indexed non-uniquely, in our case the type `std::string` is used because `first_name` is the property indexed non-uniquely. It is important to mention that multiple properties can be indexed non-uniquely, thus after the first parameter type is specified multiple parameter types can follow, corresponding to more than one properties being indexed, not just one, like in your case.
The property used for the second parameter must be of template type `std::tuple`. The first parameter must be the type of the property indexed non-uniquely, in our case the type `std::string` is used because `first_name` is the property indexed non-uniquely. And the last parameter of the tuple type must be the type of a property name which is unique. In our case the type `eosio::name` is used because property `account_name` is unique. Multiple properties can be indexed non-uniquely as well. In this case the first parameters types correspond to the properties being indexed. And, as previously already mentioned, the last parameter correspond to the type of a property name which is unique.

Refer to the following possible implementation of a non-unique index on property `account_name` using macro `KV_NAMED_INDEX`:

Expand All @@ -119,7 +122,7 @@ Refer to the following possible implementation of a non-unique index on property
```cpp
struct person {
eosio::name account_name;
eosio::non_unique<eosio::name, std::string> first_name;
std::tuple<std::string, eosio::name> first_name;
std::string last_name;
std::string personal_id;
};
Expand All @@ -144,7 +147,7 @@ class [[eosio::contract]] smrtcontract : public contract {
2. Pass as the first parameter the name of the index. It must be a qualified `eosio:name`, see documentation for the [eosio name restrictions](https://developers.eos.io/welcome/latest/glossary/index#account-name).
3. Pass the reference to the property for which the index is defined, `&person::last_name`, as the second parameter.

The property used for the second parameter must be of template type `eosio::non_unique`. The first parameter of the template type must be the type of a property name which is unique. In our case the type `eosio::name` is used because property`account_name` is unique. And the second parameter must be the type of the property indexed non-uniquely, in our case the type `std::string` is used because `last_name` is the property indexed non-uniquely. It is important to mention that multiple properties can be indexed non-uniquely, thus after the first parameter type is specified multiple parameter types can follow, corresponding to more than one properties being indexed, not just one, like in your case.
The property used for the second parameter must be of template type `std::tuple`. The first parameter must be the type of the property indexed non-uniquely, in our case the type `std::string` is used because `first_name` is the property indexed non-uniquely. And the last parameter of the tuple type must be the type of a property name which is unique. In our case the type `eosio::name` is used because property `account_name` is unique. Multiple properties can be indexed non-uniquely as well. In this case the first parameters types correspond to the properties being indexed. And, as previously already mentioned, the last parameter correspond to the type of a property name which is unique.

Refer to the following possible implementation of a non-unique index on property `last_name` using `eosio::kv::table::index` template class:

Expand All @@ -154,14 +157,14 @@ Refer to the following possible implementation of a non-unique index on property
struct person {
eosio::name account_name;
std::string first_name;
eosio::non_unique<eosio::name, std::string> last_name;
std::tuple<std::string, eosio::name> last_name;
std::string personal_id;
};

class [[eosio::contract]] smrtcontract : public contract {
struct [[eosio::table]] address_table : eosio::kv::table<person, "kvaddrbook"_n> {

index<non_unique<name, string>> last_name_idx {
index<std::tuple<name, string>> last_name_idx {
name{"persid"_n},
&person::last_name};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ link_text: "How-To Upsert Into Key-Value Table"

This how-to procedure provides instructions to upsert into `Key-Value Table` (`kv table`).

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the method `put` defined by the `eosio::kv::table` type to accomplish this task.

## Prerequisites
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ link_text: "How-To Delete from Key-Value Table"

## Summary

This how-to procedure provides instructions to delete an object from a `Key-Value Table` (`kv table’).
This how-to procedure provides instructions to delete an object from a `Key-Value Table` (`kv table`).

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the method `erase` defined by the `eosio::kv::table` type to accomplish this task.

Expand Down
4 changes: 3 additions & 1 deletion docs/06_how-to-guides/30_key-value-api/50_how-to-iterate.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ link_text: "How-To Iterate Through Key-Value Table"

This how-to procedure provides instructions to iterate through a `Key-Value Table` (`kv table`) and read values from it.

Use the `iterator` defined by the `eosio::kv::table::index` class to accomplish this task.
[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the `iterator` defined by the `eosio::kv::table::index` class to accomplish this task.

## Prerequisites

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ link_text: "How-To Check a Record in a Key-Value Table"

This how-to procedure provides instructions to check if a specific object exists in a `Key-Value Table` (`kv table`).

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the method `exists` defined by the `eosio::kv::table::index` class to accomplish this task.

## Prerequisites
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ link_text: "How-To Find in Key-Value Table"

This how-to procedure provides instructions to find a specific object in a `Key-Value Table` (`kv table`).

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the method `find()` defined by the `eosio::kv::table::index` class to accomplish this task.

## Prerequisites
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ link_text: "How-To Query Range in Key-Value Table"

This how-to procedure provides instructions to retrieve a list of values, from a `Key-Value Table` (`kv table`) index, which share a particular commonality.

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the method `range` defined by the `eosio::kv::table::index` class to accomplish this task.

## Prerequisites
Expand Down Expand Up @@ -44,7 +47,7 @@ class [[eosio::contract]] smrtcontract : public contract {
name{"accname"_n},
&person::account_name };

index<non_unique<name, string>> last_name_idx {
index<std::tuple<name, string>> last_name_idx {
name{"lastname"_n},
&person::last_name};

Expand Down Expand Up @@ -79,7 +82,7 @@ class [[eosio::contract]] smrtcontract : public contract {
name{"accname"_n},
&person::account_name };

index<non_unique<name, string>> last_name_idx {
index<std::tuple<name, string>> last_name_idx {
name{"lastname"_n},
&person::last_name};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ link_text: "How-To Allow Users to Pay for Key-Value Table Resources"

This how-to procedure provides instructions to allow users to pay for the resources needed to store data in a `Key-Value Table` (`kv table`).

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

Use the method `put` defined by the `eosio::kv::table` type to accomplish this task and provide as the second parameter the account name which is the payer for the resources needed.

## Prerequisites
Expand Down
3 changes: 3 additions & 0 deletions docs/06_how-to-guides/30_key-value-api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ link_text: "Key-Value API"

The Key-Value API provides a set of C++ classes and structures which facilitates the creation of datastore key value tables on-chain. It is meant to provide the same functionality the multi-index provides in a `simpler` and more `flexible` API with comparable performance.

[[caution | Alpha version]]
| `Key-Value Table` is designated as `alpha` and should not be used in production code.

## Concept

The Key-Value API, or KV API, is a new option for developers to create datastore key value tables on-chain. KV API is more flexible than multi-index and allows developers to search the table in a more human-readable way, unlike multi-index tables where search is over 64-bit values.
Expand Down
121 changes: 52 additions & 69 deletions examples/kv_addr_book/include/kv_addr_book.hpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,30 @@
#include <eosio/eosio.hpp>
#include <eosio/table.hpp>


using namespace eosio;
using namespace std;

using fullname_t = std::tuple<std::string, std::string, eosio::name>;
using address_t = std::tuple<std::string, std::string, std::string, std::string, eosio::name>;
using country_personal_id_t = std::pair<std::string, std::string>;

// this structure defines the data stored in the kv::table
struct person {
eosio::name account_name;
std::tuple<eosio::name, std::string> first_name;
std::tuple<eosio::name, std::string> last_name;
std::tuple<eosio::name, std::string, std::string, std::string, std::string> street_city_state_cntry;
std::tuple<eosio::name, std::string> personal_id;
std::pair<std::string, std::string> country_personal_id;

eosio::name get_account_name() const {
return account_name;
}
std::string get_first_name() const {
// from the tuple we extract the value with key 1, the first name
return std::get<1>(first_name);
}
std::string get_last_name() const {
// from the tuple we extract the value with key 1, the last name
return std::get<1>(last_name);
}
std::string get_street() const {
// from the tuple we extract the value with key 1, the street
return std::get<1>(street_city_state_cntry);
}
std::string get_city() const {
// from the tuple we extract the value with key 2, the city
return std::get<2>(street_city_state_cntry);
}
std::string get_state() const {
// from the tuple we extract the value with key 3, the state
return std::get<3>(street_city_state_cntry);
}
std::string get_country() const {
// from the tuple we extract the value with key 4, the country
return std::get<4>(street_city_state_cntry);
}
std::string get_personal_id() const {
// from the tuple we extract the value with key 1, the personal id
return std::get<1>(personal_id);
}
std::string first_name;
std::string last_name;
std::string street;
std::string city;
std::string state;
std::string country;
std::string personal_id;

// data members supporting the indexes built for this structure
fullname_t full_name_first_last;
fullname_t full_name_last_first;
address_t address;
country_personal_id_t country_personal_id;
};

// helper factory to easily build person objects
Expand All @@ -56,11 +40,17 @@ struct person_factory {
std::string personal_id) {
return person {
.account_name = account_name,
.first_name = {account_name, first_name},
.last_name = {account_name, last_name},
.street_city_state_cntry = {account_name, street, city, state, country},
.personal_id = {account_name, personal_id},
.country_personal_id = {country, personal_id}
.first_name = first_name,
.last_name = last_name,
.street = street,
.city = city,
.state = state,
.country = country,
.personal_id = personal_id,
.full_name_first_last = {first_name, last_name, account_name},
.full_name_last_first = {last_name, first_name, account_name},
.address = {street, city, state, country, account_name},
.country_personal_id = {country, personal_id},
};
}
};
Expand All @@ -73,43 +63,37 @@ class [[eosio::contract]] kv_addr_book : public eosio::contract {
// 2. unique indexes for multiple properties of the kv::table parameter type
// are defined with the help of a pair or a tuple; a pair if the index has
// two properties or a tuple in case of more than two
index<eosio::name> account_name_uidx {
eosio::name{"accname"_n},
index<name> account_name_uidx {
name{"accname"_n},
&person::account_name };
index<std::pair<std::string, std::string>> country_personal_id_uidx {
eosio::name{"cntrypersid"_n},
index<country_personal_id_t> country_personal_id_uidx {
name{"cntrypersid"_n},
&person::country_personal_id };

// non-unique indexes definitions
// 1. non unique indexes need to be defined for at least two properties,
// 2. the first one needs to be a property that stores unique values, because
// 2. first properties, besides the last, are the ones wanted to be indexed non-uniquely
// 3. the last one needs to be a property that stores unique values, because
// under the hood every index (non-unique or unique) is stored as an unique
// index, and by providing as the first property one that has unique values
// index, and by providing as the last property one that has unique values
// it ensures the uniques of the values combined (including non-unique ones)
// 3. the rest of the properties are the ones wanted to be indexed non-uniquely
index<std::tuple<eosio::name, std::string>> first_name_idx {
eosio::name{"firstname"_n},
&person::first_name};
index<std::tuple<eosio::name, std::string>> last_name_idx {
eosio::name{"lastname"_n},
&person::last_name};
index<std::tuple<eosio::name, std::string>> personal_id_idx {
eosio::name{"persid"_n},
&person::personal_id};
// non-unique index defined using the KV_NAMED_INDEX macro
// note: you can not name your index like you were able to do before (ending in `_idx`),
// instead when using the macro you have to pass the name of the data member which
// is indexed and that will give the name of the index as well
KV_NAMED_INDEX("address"_n, street_city_state_cntry)
index<fullname_t> full_name_first_last_idx {
name{"frstnameidx"_n},
&person::full_name_first_last};
index<fullname_t> full_name_last_first_idx {
name{"lastnameidx"_n},
&person::full_name_last_first};
index<address_t> address_idx {
name{"addressidx"_n},
&person::address};

address_table(eosio::name contract_name) {
init(contract_name,
account_name_uidx,
country_personal_id_uidx,
first_name_idx,
last_name_idx,
personal_id_idx,
street_city_state_cntry);
full_name_first_last_idx,
full_name_last_first_idx,
address_idx);
}
};

Expand All @@ -130,7 +114,6 @@ class [[eosio::contract]] kv_addr_book : public eosio::contract {
[[eosio::action]]
std::vector<person> getbylastname(std::string last_name);

// retrieves list of persons with the same address
[[eosio::action]]
std::vector<person> getbyaddress(
std::string street,
Expand Down Expand Up @@ -172,6 +155,6 @@ class [[eosio::contract]] kv_addr_book : public eosio::contract {
using iterate_action = eosio::action_wrapper<"iterate"_n, &kv_addr_book::iterate>;

private:
void print_person(const person& person);
void print_person(const person& person, bool new_line = true);
address_table addresses{"kvaddrbook"_n};
};
Loading