按主键查找表中记录的RPC接口
现在的EOS有命令行方式显示合约中表的数据的命令,而且显示的是全表记录,默认最多只能显示10条,这个可以通过cleos get table命令的–limit参数临时修改。EOS没有按条件查找记录的命令,也没有对应的RPC接口。
RPC接口调用的函数源码:
// rpc参数对应的结构体
struct table_record_params {
string contract_account; // 部署了合约的账号
string table; // 表名
string data; // 查找条件,如:id=xidx
};
fc::variant query_table(const table_record_params& str_params){
const auto& c_plugin = _app.get_plugin<chain_plugin>();
const auto& db = c_plugin.chain().db();
const auto& code_account = db.get<account_object, by_name>( eosio::string_to_name(str_params.contract_account.c_str()) );
const fc::microseconds abi_serializer_max_time(10 * 1000);
vector<fc::variant> rows;
abi_def abi;
if( abi_serializer::to_abi(code_account.abi, abi) ) {
abi_serializer abis( abi, abi_serializer_max_time );
// make_tupl的3个参数,按顺序分别为:部署了操作表数据合约的账号(比如插入记录、删除记录合约)、表域(即表的scope)、表名
const auto* t_id = db.find<chain::table_id_object, chain::by_code_scope_table>(boost::make_tuple( eosio::string_to_name(str_params.contract_account.c_str()), N(tbsp), eosio::string_to_name(str_params.table.c_str()) ));
if (t_id != nullptr) {
const auto &idx = db.get_index<key_value_index, by_scope_primary>();
vector<string> vec_con;
boost::split( vec_con, str_params.data , boost::is_any_of( "=" ), boost::token_compress_on );
string str_data = vec_con.size() >= 2 ? vec_con[1] : vec_con[0];
// make_tuple的第2个参数为要查询记录的主键值
auto it = idx.find(boost::make_tuple( t_id->id, eosio::string_to_name(str_data.c_str()) ));
if ( it != idx.end() ) {
vector<char> data;
eosio::chain_apis::read_only::copy_inline_row(*it, data);
rows.emplace_back(abis.binary_to_variant(abis.get_table_type(eosio::string_to_name(str_params.table.c_str())), data, abi_serializer_max_time));
}
}
}
return fc::variant(rows);
}
实现的函数体不长,但研究出来也是耗费了一番功夫,我的思路是通过查看cleos get account和cleos get table两个命令的代码,整理出来主键记录查找逻辑。因为,get account是查询特定一个记录,而get table是查询全表记录,一个是有条件查询,一个是无条件查询,正好概括了查找的全部场景,所以,从这里面肯定能找出一些端倪。
改进的地方:现在只能由主键来查,所以只能查询一条记录,可以增强按非主键的字段来查询,这样便能实现查询多条记录。从EOS对table的支持来看,有二级索引的功能,有这个支持,实现按非主键查询也是可能的。但目前业务上按主键查询,能满足要求,暂时就不花精力研究二级索引查询了,转去下一个难点攻克,待以后增加了再来更新文章也不迟。
【本章完】