今天碰到一个有意思的问题,特意拿出来分享一下。
我们知道EOS账户是由 .、1-5、a-z这32个字符中组成,且长度不超过12个字符;EOS账户,本质上是一个64位无符号整型,也就是在实际转换过程中5位转换成一个字符,64 / 5 = 12(这里是整型计算),这也就是为什么账户长度为什么为12的原因,具体转换函数我们其实可以看name.hpp头文件,其实就是做了一次base32编码(这里不具体介绍)。
最初版的EOS中账户类型为account_name类型(即uint64_t类型),后来eosio.cdt中定义了name结构类型(该结构体主要变量为uint64_t类型的变量value)。
所以有时候我会选择以账户名作为多索引表的主键,准确来说是使用账户名的value变量作为主键,假设定义多索引表如下:
1 TABLE test { 2 name account; 3 uint32_t score; 4 5 uint64_t primary_key() const { return account.value; } 6 }; 7 typedef eosio::multi_index<"test"_n, test> test_t;
从以上代码中我们可以看到,主键为account.value,即账户名的value值。
这个时候,如果我通过api来查询该表格的某条数据,通过设置主键的上下限来唯一确定这条数据:
curl --request POST --url http://rpc.eosio.com/v1/chain/get_table_rows --data '{"scope":"testaccount1","code":"testaccount1","table":"test","json":"true","lower_bound":"111111111111","upper_bound":"111111111111"}'
假设test表格中确实存在账户名为111111111111的数据记录,但使用以上命令查询时却返回为空。这是为什么呢?
究其原因,当我们传入纯数字账户名时,系统会将其作为一个uint64_t类型处理,而并不是作为一个字符串类型处理。也就是会优先调用uint64_t作为传入参数的构造函数。所以如果我们在对纯数字类型账户名使用api进行索引时,需要给账户加上空格前缀或者空格后缀,实际测试中,发现非纯数字类型账户名也是可以加空格的,因此以上api命令需要修改为,前面加空格:
curl --request POST --url http://rpc.eosio.com/v1/chain/get_table_rows --data '{"scope":"testaccount1","code":"testaccount1","table":"test","json":"true","lower_bound":" 111111111111","upper_bound":" 111111111111"}'
或者后面加空格:
curl --request POST --url http://rpc.eosio.com/v1/chain/get_table_rows --data '{"scope":"testaccount1","code":"testaccount1","table":"test","json":"true","lower_bound":"111111111111 ","upper_bound":"111111111111 "}'
或者混合使用:
curl --request POST --url http://rpc.eosio.com/v1/chain/get_table_rows --data '{"scope":"testaccount1","code":"testaccount1","table":"test","json":"true","lower_bound":"111111111111 ","upper_bound":" 111111111111"}'