EOS源码分析2 - 从Multi-Index表删除数据,详解erase函数

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对象的引用,调用了它的modifyremove方法,对数据库进行操作。

特别鸣谢 @松果的支持

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北纬32.6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值