The last post about smart contract action mentioned the data that is transferred to action exists only in the moment the smart contract runs. Thus, in order to save and share, another type of saving method is necessary. This is called “table” in EOS terms. This is data that needs to exist even when the smart contract ends, so it is managed using the Persistence API.



#include <eosiolib/print.hpp>

using namespace eosio;

class hello : public eosio::contract {

public:

using contract::contract;

///

void hi( account_name user ) {

print( "Hello, World", name{user} );

}

};

EOSIO_ABI( hello, (hi) ) #include #include using namespace eosio;class hello : public eosio::contract {public:using contract::contract;/// @abi actionvoid hi( account_name user ) {print( "Hello, World", name{user} );};EOSIO_ABI( hello, (hi) )

First, let’s write the basic code. This is the basic structure of receiving hi action’s account type as data.

To use table, you first need to declare the data structure to be saved as a class or structure. In this example, we are going to use structure to save to whom was hi sent to.

Unlike the previous example, you may feel this is difficult because it contains non-intuitive C++ syntax and DB structure. Thinking of it as “it has this type of form” is an easier way to approach this.



struct ttab

{

account_name to;

uint64_t primary_key() const {return to;} /// @abi table ttab i64struct ttabaccount_name to;uint64_t primary_key() const {return to;} EOSLIB_SERIALIZE(ttab,(to))

};

Define structure for the data structure. If you take a look at this line-by-line

“/// @abi table ttab i64” uses “eosiocpp -g” to create abi that is necessary for annotation. The basic code of /// @abi action is the annotation for action.

Then declare and define a structure with struct ttab {};. The content of structure is

“Account_name to;” is a structure with a value of one to in the account information type

. The remaining 2 lines are functions and macro to manage the eos table.

Set the primary key for saving the “uint64_t primary_Key() const {return to;}” table. Tables must have primary keys. Because the data field that will be saved onto the table in this example is one “to,” this to will be specified as the primary key.

This is the macro for calling data from within a “EOSLIB_SERIALIZE(ttab,(to)) smart contract.

typedef multi_index<N(ttab),ttab> _ttab;

Declare the structure declared above as a Multi_index form. Multi_index is a form provided in a form that has easy-to-use data structures in the Boost Library. You can think of it as “the ttab structure declared above’s name of ttab is used to declare the form being used as _ttab” in this example.



void hi(account_name user)

{

_ttab ttabs(_self,_self);



auto iter=ttabs.find(user);

if(iter==ttabs.end())

{

print("need insert\t");

ttabs.emplace(_self,[&](auto& ttab)

{

ttab.to = user;

});

}

else

{

print("data already exist\t");

}

print("hello, world : ", name{user});

} /// @abi actionvoid hi(account_name user)_ttab ttabs(_self,_self);auto iter=ttabs.find(user);if(iter==ttabs.end())print("need insert\t");ttabs.emplace(_self,[&](auto& ttab)ttab.to = user;});elseprint("data already exist\t");print("hello, world : ", name{user});

In a typical example, in order to retrieve information from a table,

Use the parameter of (_self,_self) on “_ttab ttabs(_self,_self);” _ttab’s ttabs variables to reset (instance constructor). The “_self” used in the parameter refers to the account under which the smart contract is executed.

The first parameter of the ttabs constructor represents the account that will own the generated table.

The second parameter can be thought of as an account to use ttabs.

Find the user data that was transferred as “auto iter=ttabs.find(user);” action’s data in ttab. The data found from ttab will be used as an “iterator” form. It is beyond the scope of this article to describe the iterator in detail, but to briefly explain the above example,

if you compare the “if(iter==ttabs.end())” info found above with the last ttab, and if it is the same, this means that the user transferred to action is not in the table. In this case, insert the data. If not and user info is in the table, it is the structure of printing the message without doing anything.

If there is no “ttabs.emplace(_self,[&](auto& ttab)” user table, use the emplace function provided by multi_index and insert the data.

The first parameter is the account information about who will pay for storing the data.In this example, the smart contract account pays for the cost, but you must consider the design in order to use this info on an actual server.

The second is the Lambda form of ttab, which should also refer to C++, but in this example, it should be okay to think of it as cycling the passed data structure.

In this example, many of the detailed concepts have been omitted so that even beginners can easily follow it. Also, there are many conceptual orders for analogy. Therefore, this should be only for tutorials and not be applied to code.

This tutorial demonstrates how to use tables with ease in a smart contract.

#include <eosiolib/eosio.hpp>

#include <eosiolib/print.hpp> using namespace eosio; class hello : public eosio::contract

{

public:

using contract::contract;

struct ttab

{

account_name to;

uint64_t primary_key() const {return to;} /// @abi table ttab i64struct ttabaccount_name to;uint64_t primary_key() const {return to;} EOSLIB_SERIALIZE(ttab,(to))

}; typedef multi_index<N(ttab),ttab> _ttab;

void hi(account_name user)

{

_ttab ttabs(_self,_self);



auto iter=ttabs.find(user);

if(iter==ttabs.end())

{

print("need insert\t");

ttabs.emplace(_self,[&](auto& ttab)

{

ttab.to = user;

});

}

else

{

print("data already exist\t");

}

print("hello, world : ", name{user}, " 6");

}

}; /// @abi actionvoid hi(account_name user)_ttab ttabs(_self,_self);auto iter=ttabs.find(user);if(iter==ttabs.end())print("need insert\t");ttabs.emplace(_self,[&](auto& ttab)ttab.to = user;});elseprint("data already exist\t");print("hello, world : ", name{user}, " 6");}; EOSIO_ABI(hello,(hi))

If the entire code is the same as above, compile and upload the source.

#eosiocpp -o tbsample.wast tbsample.cpp #eosiocpp -g tbsample.abi tbsample.cpp

After compiling, upload the contract and execute.

# cleos set contract usersc /root/sc/tbsample

Give the “testuser” data to the hi action and execute.

# cleos push action usersc hi ‘[“testuser”]’ -p usersc

Because this is the first “testuser” inserted, show and insert “need insert” to the table.

If you take “testuser” as data and execute the contract again,

# cleos push action usersc hi ‘[“testuser”]’ -p usersc

you can see that the data already exists as above.

With cleos, you can search a user’s table. If you insert the below and search usersc’s ttab table,

#cleos get table usersc usersc ttab

you can confirm that the testuser entered in the above example, including the other data entered for the test, exists.

In this post, we looked over smart contract’s table.