EOSIO 智能合約數據庫演練

前幾天翻譯了一篇關於EOS智能合約數據庫的內容,今天來演示一下數據庫的使用方法。數據庫

目錄

新增

新增內容每每用到emplace構造函數,來進行數據庫對象的新增。數據結構

.cpp函數

void test_da::create(account_name user, string title, string content) { require_auth( user ); //驗證權限 das datable( _self, user); //定義數據庫對象 datable.emplace(user, [&]( da & d){ d.title = title; d.content = content; d.post_id = datable.available_primary_key(); d.poster = user; }); //數據庫內容建立 }

這裏須要注意的是:post

  1. 定義數據庫對象, 其中第一個參數是合約的擁有者_self,第二個變量就是數據庫的payer,也就是數據庫是誰的,數據庫存儲在誰的帳戶下。
  2. emplace函數接收兩個參數,一個payer,和一個lamada表達式。這個結構是固定的。

那麼咱們如今來看一下咱們的test_da類是怎麼定義的。ui

.hpp spa

class test_da : public contract { public: test_da( account_name self ):contract(self){} // @abi action void create(account_name user, string title, string content); private: // @abi table data i64 struct da { uint64_t post_id; account_name poster; string title; string content; uint64_t primary_key()const { return post_id; } account_name get_poster() const { return poster; } EOSLIB_SERIALIZE(da, (post_id)(poster)(title)(content)) }; typedef eosio::multi_index<N(data), da, indexed_by<N(byposter), const_mem_fun<da, account_name, &da::get_poster>> > das; }; } /// namespace eosio
  1. 全部的智能合約都繼承自contract合約。`test_da( account_name self ):contract(self){}
    test_da`合約的構造函數。
  2. 下面是對create函數的聲明。
  3. 接下來是對數據字段的定義。這裏咱們定義了數據結構da.
  4. primary_key函數是定義主鍵的函數。 
  5. 接下來咱們定義了輔助主鍵返回poster
  6. EOSLIB_SERIALIZE宏的第一個參數是數據結構,其餘參數是數據結構中的數據成員。
  7. typedef咱們在這裏定義了一個名字爲das的類型,它用來定義數據庫對象。這裏咱們定義的是一個具備主鍵及一個輔助鍵的數據庫對象。
    .abi 

abi 很是重要,錯誤的abi會致使合約執行失敗。翻譯

{ "types": [], "structs": [{ "name": "da", "base": "", "fields": [{ "name": "post_id", "type": "uint64" },{ "name": "poster", "type": "account_name" },{ "name": "title", "type": "string" },{ "name": "content", "type": "string" } ] },{ "name": "create", "base": "", "fields": [{ "name": "user", "type": "account_name" },{ "name": "title", "type": "string" },{ "name": "content", "type": "string" } ] }} ], "actions": [{ "name": "create", "type": "create", } ], "tables": [{ "name": "data", "index_type": "i64", "key_names": [ "post_id" ], "key_types": [ "uint64" ], "type": "da" } ], "ricardian_clauses": [] }

接下來來演示一下:3d

  1. 發佈合約
cleos set contract eosio test_da Reading WAST/WASM from test_da/test_da.wasm... Using already assembled WASM... Publishing contract... executed transaction: 3d6f04278617d3807fe876a33057f1155acf9c9e5a392ac6ed8ad51e79506009 6752 bytes 24679 us # eosio <= eosio::setcode {"account":"eosio","vmtype":0,"vmversion":0,"code":"0061736d0100000001ad011a60037f7e7e0060057f7e7e7f... # eosio <= eosio::setabi {"account":"eosio","abi":{"types":[],"structs":[{"name":"da","base":"","fields":[{"name":"post_id","...
  1. 建立數據
cleos push action eosio create '{"user":"eosio","title":"first","content":"create a first one"}' -p eosio executed transaction: 830057f270fa499b1d61b82e80ad8cda1774cdc1786c1e786f558a3e0a48974c 216 bytes 17229 us # eosio <= eosio::create {"user":"eosio","title":"first","content":"create a first one"}

下面咱們來查一下數據表:code

cleos get table eosio eosio data { "rows": [{ "post_id": 0, "poster": "eosio", "title": "first", "content": "create a first one" } ], "more": false }

建立信息成功,那麼咱們用別的帳號建立會怎樣呢?對象

cleos push action eosio create '{"user":"eostea","title":"eostea first","content":"eostea create a first one"}' -p eostea executed transaction: 8542a87e563a9c62b7dbe46ae09ccf829c7821f8879167066b658096718de148 232 bytes 2243 us # eosio <= eosio::create {"user":"eostea","title":"eostea first","content":"eostea create a first one"}

查看數據表:

cleos get table eosio eostea data { "rows": [{ "post_id": 0, "poster": "eostea", "title": "eostea first", "content": "eostea create a first one" } ], "more": false }

到這裏,相信你們對建立數據已經沒有什麼疑惑了。

查詢

對於數據庫,最重要的功能就是查詢,若是沒有查詢功能,數據庫裏的數據就不能呈現,也就沒有意義。查詢數據庫主要分爲兩方面,一方面是主鍵查詢,一方面是經過二級索引查詢。
這裏爲了使表中數據多樣化我會作一些修改,將全部數據都合到一張表中。
我將以上.cpp中的das datable( _self, user);改成das datable( _self, _self);.這樣數據都存在合約帳戶的表中。

主鍵查詢

這裏我添加了一個方法來查詢數據並打印:

void test_da::getd(uint64_t post_id){ das datable(_self, _self); auto post_da = datable.find( post_id); eosio::print("Post_id: ", post_da->post_id, " Post_Tile: ", post_da->title.c_str(), " Content: ", post_da->content.c_str()); }

abi文件也作了相應的調整:

執行:

cleos push action eosio getd '{"post_id":1}' -p eosio executed transaction: ac8663235462d947c74542af848cca54a059c3991d193237025da7d4767d6725 192 bytes 1724 us # eosio <= eosio::getd {"post_id":1} >> Post_id: 1 Post_Tile: first Content: eosio create a first one

二級索引查詢

添加二級索引查詢代碼以下:

auto poster_index = datable.template get_index<N(byposter)>(); auto pos = poster_index.find( user ); for (; pos != poster_index.end(); pos++) { eosio::print("content:", pos->content.c_str(), " post_id:", pos->post_id, " title:", pos->title.c_str()); }

獲取二級索引並獲取數據,這裏我只用了find查詢,其餘查詢就不在一一介紹。

執行getd操做:

cleos push action eosio getd '{"post_id":2,"user": "eostea"}' -p eosio executed transaction: 2370e1fb1ee8a581f7321f02fb40645e51269e579d183c33ef470dba0b3afdbc 200 bytes 5403 us # eosio <= eosio::getd {"post_id":2,"user":"eostea"} >> Post_id: 2 Post_Tile: eostea first Content: eostea create a first onecontent:eostea create a first one post_id:2 title:eostea first

數據庫中數據以下:

cleos get table eosio eosio data { "rows": [{ "post_id": 0, "poster": "eosio", "title": "first", "content": "eostea create a first one" },{ "post_id": 1, "poster": "eosio", "title": "first", "content": "eostea create a first one" },{ "post_id": 2, "poster": "eostea", "title": "eostea first", "content": "eostea create a first one" } ], "more": false }

更改

更改數據庫內容。
這裏咱們先看一下目前的數據庫內容。

cleos get table eosio eosio data { "rows": [{ "post_id": 0, "poster": "eosio", "title": "first", "content": "eostea create a first one" },{ "post_id": 1, "poster": "eosio", "title": "first", "content": "eostea create a first one" },{ "post_id": 2, "poster": "eostea", "title": "eostea first", "content": "eostea create a first one" } ], "more": false }

寫一個更改數據的action代碼以下:

void test_da::change(account_name user, uint64_t post_id, string title, string content) { require_auth(user); das datable( _self, user); auto post = datable.find(post_id); eosio_assert(post->poster == user, "yonghucuowu"); datable.modify(post, user, [&](auto& p){ if (title != "") p.title = title; if (content != "") p.content = content; }); }

1. 前幾行代碼已經以前講解過,如今直接說modify方法,他的第一個參數是你查詢出的要更改的對象,第二個參數是payer,其餘的不用多說。
下面咱們執行一下命令:

cleos push action eosio change '{"user":"eosio","post_id":1,"title":"change","content":"change action"}' -p eosio executed transaction: 8cb561a712f2741560118651aefd49efd161e3d73c56f6d24cf1d699c265e2dc 224 bytes 2130 us # eosio <= eosio::change {"user":"eosio","post_id":1,"title":"change","content":"change action"}

下面咱們看一下數據庫:

cleos get table eosio eosio data { "rows": [{ "post_id": 0, "poster": "eosio", "title": "first", "content": "eostea create a first one" },{ "post_id": 1, "poster": "eosio", "title": "change", "content": "change action" },{ "post_id": 2, "poster": "eostea", "title": "eostea first", "content": "eostea create a first one" } ], "more": false }

post_id=1的記錄已經被改變,說明咱們成功了。

刪除數據

刪除數據我又加了一個action,以下所示:

void test_da::dele(account_name user, uint64_t post_id) { require_auth(user); das datable( _self, user); auto post = datable.find(post_id); eosio::print(post->title.c_str()); eosio_assert(post->poster == user, "yonghucuowu"); datable.erase(post); }

這裏調用了erase方法刪除數據,參數爲一個數據對象。下面咱們來看一下執行結果:

cleos push action eosio dele '{"user":"eosio","post_id":1}' -p eosioexecuted transaction: 3affbbbbd1da328ddcf37753f1f2f6c5ecc36cd81a0e12fea0c789e75b59714e 200 bytes 2383 us # eosio <= eosio::dele {"user":"eosio","post_id":1}

如今再來看一下咱們的數據庫:

cleos get table eosio eosio data { "rows": [{ "post_id": 0, "poster": "eosio", "title": "first", "content": "eostea create a first one" },{ "post_id": 2, "poster": "eostea", "title": "eostea first", "content": "eostea create a first one" } ], "more": false }

post_id=1的數據已經被咱們刪除。

到這裏,數據庫的增刪改查已經講解完畢。
本文內容爲原創內容,如需轉載請聯繫做者。謝謝!!!

原文連接: https://eosfans.io/topics/484

相關文章
相關標籤/搜索