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方法,对数据库进行操作。

特别鸣谢 @松果的支持

猜你喜欢

转载自blog.csdn.net/weixin_39842528/article/details/90608762