EOS智能合約中數(shù)據(jù)庫(kù)的使用與常見(jiàn)問(wèn)題

  閱讀本文前秒梳,您需要熟悉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)題:

  1. //@abi table 生成abi的時(shí)候會(huì)生成該新的數(shù)據(jù)表,不加則生成的abi中table無(wú)內(nèi)容排抬,進(jìn)行查表操作的時(shí)候顯示如下懂从。

Table cactus.db is not specified in the ABI

  1. 在對(duì)表名進(jìn)行命名是要注意,表名長(zhǎng)度需要小于13(不包括13)個(gè)字符蹲蒲,且只能包含.12345abcdefghijklmnopqrstuvwxyz這些字符番甩,否則查找的時(shí)候會(huì)提示錯(cuò)誤。
  1. 一定需要有primary_key()方法届搁。
  1. 當(dāng)//@abi table中聲明的表名包括'.'時(shí),生成abi文件時(shí)會(huì)將'.'后面的內(nèi)容忽略缘薛,可以觀察上方生成的abi文件中"name"為"cactus"而不是在代碼中所聲明的"cactus.db"。

  2. 若//@abi table后不寫(xiě)聲明表名卡睦,生成abi時(shí)表名會(huì)取結(jié)構(gòu)體的名字宴胧。

  3. 生成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):

  1. 除了主鍵函數(shù)外還需要寫(xiě)一個(gè)索引鍵值函數(shù)契沫,如get_index_id()
  2. 結(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;
      });
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市懈万,隨后出現(xiàn)的幾起案子拴清,更是在濱河造成了極大的恐慌,老刑警劉巖会通,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件口予,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡涕侈,警方通過(guò)查閱死者的電腦和手機(jī)沪停,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)裳涛,“玉大人木张,你說(shuō)我怎么就攤上這事《巳” “怎么了舷礼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)郊闯。 經(jīng)常有香客問(wèn)我且轨,道長(zhǎng),這世上最難降的妖魔是什么虚婿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任旋奢,我火速辦了婚禮,結(jié)果婚禮上然痊,老公的妹妹穿的比我還像新娘至朗。我一直安慰自己,他們只是感情好剧浸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布锹引。 她就那樣靜靜地躺著矗钟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嫌变。 梳的紋絲不亂的頭發(fā)上吨艇,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音腾啥,去河邊找鬼东涡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛倘待,可吹牛的內(nèi)容都是我干的疮跑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼凸舵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼祖娘!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起啊奄,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤渐苏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后菇夸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體整以,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年峻仇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了公黑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摄咆,死狀恐怖凡蚜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吭从,我是刑警寧澤朝蜘,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站涩金,受9級(jí)特大地震影響谱醇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜步做,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一副渴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧全度,春花似錦煮剧、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)佑颇。三九已至,卻和暖如春草娜,著一層夾襖步出監(jiān)牢的瞬間挑胸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工宰闰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茬贵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓议蟆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親萎战。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咐容,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容