EOSIO 智能合约数据库演练

简介: 前几天翻译了一篇关于EOS智能合约数据库的内容,今天来演示一下数据库的使用方法。 目录 增 查 改 删 新增 新增内容往往用到emplace构造函数,来进行数据库对象的新增

前几天翻译了一篇关于EOS智能合约数据库的内容,今天来演示一下数据库的使用方法。 目录 增 查 改 删 新增 新增内容往往用到emplace构造函数,来进行数据库对象的新增。录





新增

新增内容往往用到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;
    }); //数据库内容创建
}

这里需要注意的是:

定义数据库对象, 其中第一个参数是合约的拥有者_self,第二个变量就是数据库的payer,也就是数据库是谁的,数据库存储在谁的账户下。
emplace函数接收两个参数,一个payer,和一个lamada表达式。这个结构是固定的。
那么我们现在来看一下我们的test_da类是怎么定义的。

.hpp 

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
所有的智能合约都继承自contract合约。`test_da( account_name self ):contract(self){}
是test_da`合约的构造函数。
下面是对create函数的声明。
接下来是对数据字段的定义。这里我们定义了数据结构da.
primary_key函数是定义主键的函数。 
接下来我们定义了辅助主键返回poster。
EOSLIB_SERIALIZE宏的第一个参数是数据结构,其他参数是数据结构中的数据成员。
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": []
}
接下来来演示一下:

发布合约
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","...

创建数据
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"}

下面我们来查一下数据表:

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();
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的数据已经被我们删除。

到这里,数据库的增删改查已经讲解完毕。

目录
相关文章
|
8月前
|
关系型数据库 MySQL 数据库连接
实战演练:使用Go语言和ORM框架与数据库进行交互
【2月更文挑战第13天】本文将通过一个实战演练,展示如何使用Go语言和ORM(对象关系映射)框架与数据库进行交互。我们将选择一个流行的ORM框架,如GORM,来完成这个任务。通过实际编码,我们将演示如何连接数据库、执行CRUD操作、处理错误和异常,并展示ORM框架如何简化数据库操作过程。
|
监控 关系型数据库 MySQL
MySQL 数据库复制与集群技术及实战演练(一)
MySQL 数据库复制与集群技术及实战演练(一)
|
区块链 数据库 索引
|
1天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
11 0
|
28天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
58 3
|
28天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
70 3
|
28天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
87 2
|
1月前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
264 15
|
1月前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
1月前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。

热门文章

最新文章