增删查改是一个系统中最基本的四项功能,本文介绍如何实现在Webase平台中利用Table库完成增删查改的智能合约编写。文章中的主要代码示例来源于Fisco Bcos官方文档,但由于官方文档缺乏注释,为了使大家能够理解代码中每个变量的意思以及使用方法,本文将从Table库本身以及增、查两个例子进行介绍。此文章仅为个人理解,有问题还请指正。
一.Table库介绍
在使用Table库时,我们需要新建Table.sol文件,在Table.sol文件下写入以下代码,不要使用官方文档里的!用装系统内置的,如下:
contract TableFactory {
function openTable(string memory) public view returns (Table){};
function createTable(string memory,string memory,string memory) public returns(int256){};
}
// 查询条件
contract Condition {
//等于
function EQ(string memory, int256) public view{}
function EQ(string memory, string memory) public view{}
//不等于
function NE(string memory, int256)public view{}
function NE(string memory, string memory) public view{}
//大于
function GT(string memory, int256) public view{}
//大于或等于
function GE(string memory, int256)public view{}
//小于
function LT(string memory, int256) public view{}
//小于或等于
function LE(string memory, int256) public view{}
//限制返回记录条数
function limit(int256) public view{}
function limit(int256,int256) public view{}
}
// 单条数据记录
contract Entry {
function getInt(string memory) public view returns(int256){}
function getUInt(string memory) public view returns(uint256){}
function getAddress(string memory) public view returns(address){}
function getBytes64(string memory) public view returns(bytes1[64] memory){}
function getBytes32(string memory) public view returns(bytes32){}
function getString(string memory) public view returns(string memory){}
function set(string memory, int256) public{}
function set(string memory, uint256) public{}
function set(string memory, string memory) public{}
function set(string memory, address) public{}
}
// 数据记录集
contract Entries {
function get(int256) public view returns(Entry){}
function size() public view returns(int256){}
}
// Table主类
contract Table {
function select(string memory, Condition) public view returns(Entries){}
function insert(string memory, Entry) public returns(int256){}
function update(string memory, Entry, Condition) public returns(int256){}
function remove(string memory, Condition) public returns(int256){}
function newEntry() public view returns(Entry){}
function newCondition() public view returns(Condition){}
}
contract KVTableFactory{
function openTable(string memory) public view returns (bool,Entry){}
function createTable(string memory,string memory,string memory)public returns(int256){}
}
contract KVTable{
function get(string memory) public view returns (bool,Entry){}
function set(string memory,Entry) public returns (int256){}
function newEntry() public view returns (Entry){}
}
其中,Table合约的insert、remove、update和select函数中key的类型为string,其长度最大支持255字符。Entry的get/set接口的key的类型为string,其长度最大支持255字符,value支持的类型有int256(int)、address和string,其中string的长度不能超过16MB。
二.构造函数
在编写.sol文件时,在最开头,我们需要加上运用的solidity版本以及ABi,导入的库:
pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
import "./Table.sol";
其中Table.sol就是我们上述所新建的Table库。在编写构造函数之前,我们需要一个TableFactory类型的变量用于构造并为其命名:
TableFactory tableFactory;
string constant TABLE_NAME = "t_test";
然后,我们需提前声明所要进行的事件,如增加和查找:
event AddResult(int256 count);
event SearchResult(string value1,string value2);
event DeleteResult(int256 count);
event UpdateResult(int256 count);
接下来便是构造函数的编写,creatTable接收三个变量,一般是Table名,关键字id以及值,其中关键字id可以用来查找,值可以有多个:
constructor() public {
tableFactory = TableFactory(0x1001); //The fixed address is 0x1001 for TableFactory
// the parameters of createTable are tableName,keyField,"vlaueFiled1,vlaueFiled2,vlaueFiled3,..."
tableFactory.createTable(TABLE_NAME, "id", "value1,value2");
}
三. 增
在编写增函数时,具体思路就是先创建用于传参的变量entry,打开一个表,设置主键然后传参,释放事件。首先,我们需要为其准备在构造函数中creatTable所需的参数,如id,value1,value2。
function add(string memory id,string memory value,string memory value2)
public
returns (int256)
{
Table table = tablefactory.openTable(TABLE_NAME);
Entry entry = table.newEntry();
entry.set("id",id);
entry.set("value1",value1);
entry.set("value2",value2);
int256 count = table.insert(id,entry);
emit AddResult(count);
return count
}
首先,我们打开我们刚刚创建的Table,然后创建一个临时变量entry,将输入的参数传入,然后创建用于返回的count参数,传入用于查找的id(主键)以及entry后释放add事件,返回count。
注意:若客户端需要调用转换为Java文件的合约代码,需要将TableTest.sol和Table.sol放入控制台的contracts/solidity目录下,通过控制台的编译脚本sol2java.sh生成TableTest.java。
四.查
编写查函数时,我们需要首先打开创建好的表Table,然后设定condition条件,这里我们可以设定成查找id等于表中的id(主键),然后创建临时变量,返回满足条件的表中的值。table.select相当于根据condition条件进行查找。在有多个参数时,可尝试使用数组进行存储,也可以分为多个函数,否则会报错Stack too deep!(最多四个变量)returns里只需要写变量类型。
functino get(string memory id)
public
returns(string memory,string memory)
{
Table table =tableFactory.openTable(TABLE_NAME);
Condition condition = table.newCondition();
condition.EQ("id",id);
Entries entries = table.select(id,condition);
require(entries.size()>0,"no exist");
Entry entry = entries.get(0);
string memory value1= entry.getString("value1");
string memory value2= entry.gestString("value2");
emit GetResult(value1,value2);
return (value1,value2);
}
五.删
编写删函数时,还是先打开表,然后创建删除条件,寻找符合条件的字表进行删除,然后释放事件。
function remove(string memory name, int256 item_id) public returns (int256) {
Table table = tableFactory.openTable(TABLE_NAME);
Condition condition = table.newCondition();
condition.EQ("name", name);
condition.EQ("item_id", item_id);
int256 count = table.remove(name, condition);
emit DeleteResult(count);
return count;
}
六.改
进行改操作需要传入搜索的主键和需要更改的参数,然后打开表,创建新子表,判断条件然后调用table.update更新。
function update(string memory name, int256 item_id, string memory item_name)
public
returns (int256)
{
Table table = tableFactory.openTable(TABLE_NAME);
Entry entry = table.newEntry();
entry.set("item_name", item_name);
Condition condition = table.newCondition();
condition.EQ("name", name);
condition.EQ("item_id", item_id);
int256 count = table.update(name, entry, condition);
emit UpdateResult(count);
return count;
}