閱讀本文前秒梳,您需要熟悉eos節(jié)點(diǎn)的操作流程贺待,熟悉cleos客戶端基礎(chǔ)指令悬而,并且對(duì)自定義合約的開(kāi)發(fā)有著一定的了解函喉。
操作系統(tǒng):MAC OS 10.13.x避归,EOSIO版本號(hào):1.1.3
背景
在EOS自定義合約開(kāi)發(fā)過(guò)程中有持久化存儲(chǔ)的需求,則需要?jiǎng)?chuàng)建一個(gè)用作持久化存儲(chǔ)的數(shù)據(jù)庫(kù)管呵。EOS中的數(shù)據(jù)庫(kù)是通過(guò)multi_index來(lái)完成交互與訪問(wèn)槐脏。
下面通過(guò)我們先創(chuàng)建數(shù)據(jù)表,并進(jìn)行數(shù)據(jù)表進(jìn)行增刪改查撇寞。
1 創(chuàng)建數(shù)據(jù)表
- 創(chuàng)建智能合約
在創(chuàng)建數(shù)據(jù)表前顿天,我們首先需要?jiǎng)?chuàng)建智能合約,關(guān)于智能合約的創(chuàng)建蔑担,網(wǎng)上有很多這樣的教程牌废,文本不再贅述。
可以參考EOSIO3.0 hello world 從 0 到 1
- 創(chuàng)建數(shù)據(jù)表結(jié)構(gòu)
//@abi table cactus.db i64
struct cts_db {
uint64_t id;
string store_content;
uint64_t primary_key() const { return id; }
EOSLIB_SERIALIZE(cts_db, (id)(store_content))
};
typedef multi_index<N(cactus), cts_db> cactus_db_index;
//@abi table cactus.db i64 表示生成abi的時(shí)候生成name為cactus.db index_type為i64 的表啤握。下面是生成的abi中的表結(jié)構(gòu)鸟缕。
"tables": [{
"name": "cactus",
"index_type": "i64",
"key_names": [
"id"
],
"key_types": [
"uint64"
],
"type": "cts_db"
}
]
其中有幾點(diǎn)注意事項(xiàng)以及可能會(huì)由此導(dǎo)致的問(wèn)題:
- //@abi table 生成abi的時(shí)候會(huì)生成該新的數(shù)據(jù)表,不加則生成的abi中table無(wú)內(nèi)容排抬,進(jìn)行查表操作的時(shí)候顯示如下懂从。
Table cactus.db is not specified in the ABI
- 在對(duì)表名進(jìn)行命名是要注意,表名長(zhǎng)度需要小于13(不包括13)個(gè)字符蹲蒲,且只能包含.12345abcdefghijklmnopqrstuvwxyz這些字符番甩,否則查找的時(shí)候會(huì)提示錯(cuò)誤。
- 一定需要有primary_key()方法届搁。
當(dāng)//@abi table中聲明的表名包括'.'時(shí),生成abi文件時(shí)會(huì)將'.'后面的內(nèi)容忽略缘薛,可以觀察上方生成的abi文件中"name"為"cactus"而不是在代碼中所聲明的"cactus.db"。
若//@abi table后不寫(xiě)聲明表名卡睦,生成abi時(shí)表名會(huì)取結(jié)構(gòu)體的名字宴胧。
生成multi_index對(duì)象時(shí),multi_index<table_name, record>時(shí)表锻,table_name需要與上面所聲明的table_name一致恕齐,否則會(huì)造成查表的時(shí)候內(nèi)容為空的情況。
cactus-MacBook-Pro:cactus_db huid$ cleos get table cactus huid cactus
{
"rows": [],
"more": false
}
2 操作簡(jiǎn)單數(shù)據(jù)表
- 獲取數(shù)據(jù)表信息
cleos get table code scope table_name
這里的code與scope與創(chuàng)建實(shí)例對(duì)象時(shí)multi_index(code, scope)的參數(shù)相對(duì)應(yīng)瞬逊,否則獲取的時(shí)候雖然不會(huì)報(bào)錯(cuò)显歧,但是沒(méi)有內(nèi)容补胚。
- 數(shù)據(jù)表插入方法使用
///@abi action
void ctsstore(account_name user){
cactus_db_index ctsdb( _self, user );
ctsdb.emplace( user, [&]( auto& a) {
a.id = ctsdb.available_primary_key();
a.store_content = store_content;
});
}
其中available_primary_key()是一個(gè)實(shí)用的方法,可以提供主鍵自增長(zhǎng)功能追迟。
執(zhí)行并獲取表信息。
cleos push action cactus ctsstore '{"user":"huid", "store_content":"cactus"}' -p huid@active
cleos push action cactus ctsstore '{"user":"huid", "store_content":"cactus"}' -p huid@active
cleos get table cactus huid cactus
{
"rows": [{
"id": 0,
"user_name": "cactus"
},{
"id": 1,
"user_name": "cactus"
}
],
"more": false
}
- 數(shù)據(jù)表查找方法使用
cactus_db_index ctsdb( _self, user );
auto& itr = ctsdb.get( id , "data not found" );
- 數(shù)據(jù)表修改方法使用
///@abi action
void ctsmodify( uint64_t id, account_name user, string store_content ){
cactus_db_index ctsdb( _self, user );
auto& itr = ctsdb.get( id , "data not found" );
ctsdb.modify( itr, user, [&]( auto& a ) {
a.store_content = store_content;
});
}
執(zhí)行并獲取表信息骚腥。
cleos push action cactus ctsmodify '{"id":1, "user":"huid", "store_content":"db"}' -p huid@active
cleos get table cactus huid cactus
{
"rows": [{
"id": 0,
"user_name": "cactus"
},{
"id": 1,
"user_name": "db"
}
],
"more": false
}
- 數(shù)據(jù)表刪除方法使用
///@abi action
void ctserase( uint64_t id, account_name user ){
cactus_db_index ctsdb( _self, user );
auto &itr = ctsdb.get( id , "data not found" );
ctsdb.erase( itr );
}
執(zhí)行并獲取表信息敦间。
cleos push action cactus ctserase '{"id":1, "user":"huid"}' -p huid@active
cleos get table cactus huid cactus
{
"rows": [{
"id": 0,
"user_name": "cactus"
}
],
"more": false
}
- 源代碼
#include <eosiolib/eosio.hpp>
using namespace eosio;
using namespace std;
class cactus_db : public contract {
public:
using contract::contract;
///@abi action
void ctsstore( account_name user, string store_content ){
cactus_db_index ctsdb( _self, user );
ctsdb.emplace( user, [&]( auto& a ) {
a.id = ctsdb.available_primary_key();
a.store_content = store_content;
});
}
///@abi action
void ctsmodify( uint64_t id, account_name user, string store_content ){
cactus_db_index ctsdb( _self, user );
auto& itr = ctsdb.get( id , "data not found" );
ctsdb.modify( itr, user, [&]( auto& a ) {
a.store_content = store_content;
});
}
///@abi action
void ctserase( uint64_t id, account_name user){
cactus_db_index ctsdb( _self, user );
auto &itr = ctsdb.get( id , "data not found" );
ctsdb.erase( itr );
}
private:
//@abi table cactus.db i64
struct cts_db {
uint64_t id;
string store_content;
uint64_t primary_key() const { return id; }
EOSLIB_SERIALIZE(cts_db, (id)(store_content))
};
typedef multi_index<N(cactus), cts_db> cactus_db_index;
};
EOSIO_ABI(cactus_db, (ctsstore)(ctsmodify)(ctserase))
3 多索引數(shù)據(jù)表
多索引表數(shù)據(jù)表和簡(jiǎn)單數(shù)據(jù)表在定義的時(shí)候不同。
簡(jiǎn)單數(shù)據(jù)表: multi_index <N(table_name), record>
多索引數(shù)據(jù)表: multi_index <N(table_name), record,
indexed_by<index_name, index_func>,
indexed_by<index_name_1, index_func_1>,
….>>
多索引數(shù)據(jù)表較簡(jiǎn)單數(shù)據(jù)表多了一個(gè)indexed_by束铭,<索引名, 索引鍵值函數(shù)>廓块, 以下具體說(shuō)明。
- 創(chuàng)建多索引數(shù)據(jù)表
private:
//@abi table cactus.db i64
struct cts_db {
uint64_t id;
uint64_t index_id;
string store_content;
uint64_t primary_key() const { return id; }
uint64_t get_index_id() const { return index_id; }
EOSLIB_SERIALIZE(cts_db, (id)(index_id)(store_content))
};
typedef multi_index< N(cactus), cts_db, indexed_by< N(index_id),
const_mem_fun< cts_db, uint64_t, &cts_db::get_index_id > > > cactus_db_index;
};
注意點(diǎn):
- 除了主鍵函數(shù)外還需要寫(xiě)一個(gè)索引鍵值函數(shù)契沫,如get_index_id()
- 結(jié)構(gòu)中的<>注意成對(duì)带猴。
- 多索引數(shù)據(jù)表查找并修改
cactus_db_index ctsdb( _self, user );
auto idx = ctsdb.template get_index<N(index_id)>();
auto itr = idx.find(mtrans::get_index_id(index_id));
if ( itr == ctsdb.end() ) { print("don't find"); }
else{
ctsdb.modify( itr, user, [&](auto &a ){
a.store_content = store_content;
});
}