EOS.IO is a blockchain protocol that emulates most of the attributes of a real computer, powered by the native cryptocurrency EOS. According to the official documentation,
The EOS.IO software introduces a new blockchain architecture designed to enable vertical and horizontal scaling of decentralized applications. This is achieved by creating an operating system-like construct upon which applications can be built. The software provides accounts, authentication, databases, asynchronous communication, and the scheduling of applications across many of CPU cores or clusters. The resulting technology is a blockchain architecture that may ultimately scale to millions of transactions per second, eliminates user fees, and allows for quick and easy deployment and maintenance of decentralized applications, in the context of a governed blockchain.
In this article, we will learn the basics of building an EOSIO smart contract database by covering the following topics:
Generally, the emplace
constructor is used to create database objects.
.cpp
void test_da::create(account_name user, string title, string content)
{
require_auth( user ); // Authenticate user permissions.
das datable( _self, user); // Define a database object.
datable.emplace(user, [&]( da & d){
d.title = title;
d.content = content;
d.post_id = datable.available_primary_key();
d.poster = user;
});// Create data in a database.
}
Precautions:
payer
, namely, the account to which the database storage belongs.payer
parameter and a lamada
expression. This structure is fixed.Let's view the definition of the test_da
class.
.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){} is the constructor of the test_da
contract.create
function.create
function define data fields. Here we define the data structure da
.primary_key
function defines the primary key.primary_key
function defines a secondary key, that is, return poster
.EOSLIB_SERIALIZE
is the data structure, and the other parameters are data members in the data structure.typedef
defines the das
type, which is a database object. In this example, we define a database object containing a primary key and a secondary key..abi
abi
is very important. An incorrect abi
will cause contract execution failure.
{
"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": []
}
Publish a contract.
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","...
Create data.
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"}
Query the data table.
cleos get table eosio eosio data
{
"rows": [{
"post_id": 0,
"poster": "eosio",
"title": "first",
"content": "create a first one"
}
],
"more": false
}
The query result indicates that data has been created successfully. Will it be successful if we create data using another account?
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"}
Query the data table.
cleos get table eosio eostea data
{
"rows": [{
"post_id": 0,
"poster": "eostea",
"title": "eostea first",
"content": "eostea create a first one"
}
],
"more": false
}
Great, it works! Here we shall have no questions about data creation.
The most important function of a database is data query. If there is no query function, data in the database cannot be presented and therefore becomes meaningless. The database can be queried by primary key or secondary index.
In this document, all data is stored in one table to diversify the table data.
The preceding das datable( _self, user);
in .cpp
is replaced with das datable( _self, _self);
. In this way, all data is stored in the table under the contract account.
In this example, a method is added to query and print data.
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());
}
The .abi file is also modified accordingly.
Run the following commands:
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
Add the following code to query data by secondary index:
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());
}
Obtain the secondary index and use it to query data. In this example, only the find function is used for query.
Run 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
The data query result is as follows:
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
}
Modify data in the database.
The existing data in the database is as follows:
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
}
Use the following action
code to modify the data:
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;
});
}
The first few rows of the code have been described before. We only describe the modify
method in the code. The first parameter post is the object you have found for modification, and the second parameter user indicates the payer
.
Run the following commands:
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"}
Query the database data.
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
}
The query result indicates that the data record containing post_id=1 has been modified.
The following action
function is added to delete data:
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);
}
The erase
method is called to delete data, and the parameter is a data object. Check the command output.
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}
Query the database data.
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
}
The query result indicates that the data record containing post_id=1 has been deleted.
2,599 posts | 763 followers
FollowAlibaba Clouder - December 5, 2016
vic - August 30, 2019
Alibaba Clouder - December 6, 2016
Alibaba Clouder - November 26, 2019
Alibaba Clouder - November 21, 2018
Alibaba Cloud Community - February 16, 2024
2,599 posts | 763 followers
FollowLearn More
Cloud-based and lightweight servers that are easy to set up and manage
Learn MoreMore Posts by Alibaba Clouder
Raja_KT March 5, 2019 at 5:09 am
Hope to see its progressive use in many smart contracts