erase
使用主键从表中删除现有对象(两种形式)
const_iterator erase( const_iterator itr )
void erase( const object_type& obj )
- 参数
itr:指向待删除对象的迭代器;
obj:待删除对象的引用。
- 返回值
使用itr查找对象时,返回被删除对象之后的对象的指针。
注:返回当前被删除对象的下个对象指针
例如:
//我们在这里定义一张表
//@abi table vec i64
struct vec{
account_name player;
uint64_t primary_key() const { return player; }
EOSLIB_SERIALIZE( vec, (player));
};
typedef eosio::multi_index< N(vec), vec> vec_index;
vec_index vecs;
typedef eosio::multi_index< N(vec), vec> vec_index;
vec_index vecs;
1):插入表两条数据
//插入数据张三
vecs.emplace(_self, [&](auto& r){
r.player = N(zhangsan1111);
});
//插入数据李四
vecs.emplace(_self, [&](auto& r){
r.player = N(lisi11111111);
});
2):查询数据(张三)
auto itr = vecs.find(zhangsan1111);
3):删除张三这条数据
itr = vecs.erase(itr);
我们现在来看itr指针指向的是那条数据?
print( itr->player );
此时输出(李四) >> lisi11111111
- 操作结果
对象从表中删除,相关的存储被回收;
表相关的二级索引被更新;
退还被删除对象的payer所支付的存储费用和相关费用。
- 异常
待删除对象不存在时、Action无权修改表数据时、给定迭代器无效时,抛出异常。
erase的使用
这里列出一个之前文章的例子:
//删除联系人
//@abi action
void remove(const account_name account) {
获取授权,如果没有授权,Action调用会中止,事务会回滚
require_auth(account);
//address_index是自己定义的eosio::multi_index
//实例化address数据表(multi_index),参数用于建立对表的访问权限
address_index addresses(_self, _self);
auto itr = addresses.find(account);
eosio_assert(itr != addresses.end(), "Address for account not found");
//删除数据
addresses.erase(itr);
}
erase源码
erase函数的源码 和上一篇文章讲的emplace函数类似,就不贴出来了,它的关键代码在这一句:
db_remove_i64( objitem.__primary_itr );
它是定义在eosiolib/db.h中的函数:
void db_remove_i64(int32_t iterator);
在wasm_interface.cpp的database_api类中实现:
void db_remove_i64( int itr ) {
context.db_remove_i64( itr );
}
调用了apply_context::db_remove_i64函数:
void apply_context::db_remove_i64( int iterator ) {
const key_value_object& obj = keyval_cache.get( iterator );
const auto& table_obj = keyval_cache.get_table( obj.t_id );
FC_ASSERT( table_obj.code == receiver, "db access violation" );
update_db_usage( obj.payer, -(obj.value.size() + config::billable_size_v<key_value_object>) );
db.modify( table_obj, [&]( auto& t ) {
--t.count;
});
db.remove( obj );
if (table_obj.count == 0) {
remove_table(table_obj);
}
keyval_cache.remove( iterator );
}
其中db是一个chainbase::database对象的引用,调用了它的modify和remove方法,对数据库进行操作。
特别鸣谢 @松果的支持