Hi Guest

More contents, please log on!

Bitmere.com 区块链技术 Content

EOS智能合约的多索引表table

西门幻雪雪vj
32 0 0
建多索引表是一种为了在RAM快速访问的方法,主要用来来缓存状态和数据。多索引表支持创建、读取、更新和删除(CRUD)业务,区块链不行(它只支持创建和读取)。
    多索引表提供了快速访问数据存储接口,是一种存储智能合同中使用的数据的实用的方法。在区块链记录交易信息,你应该使用多索引表存储应用程序数据。
    使用多索引表,因为他们支持为使用的数据建立多个索引,主索引必须是uint64_t类型和唯一的,但其他的索引,可以有重复的,你可以使用多达16个,类型可以是uint64_t,uint128_t,uint256_t,doubleorlongdouble。
    如果你想你需要使用一个字符串做索引,需要转换成一个整数型,将结果存储在随后索引的字段中。
    1.创建一个结构
    创建一个可以存储在多索引表中的结构,并在要索引的字段上定义getter。
    请记住,这些getter中必须有一个命名为primary_key(),如果没有这个,编译器eosiocpp将产生一个错误…"itcan’tfindthefieldtouseastheprimarykey"即它找不到任何一个字段被作为主键。
    如果你想要有一个以上的索引,(最多允许16个),然后为你想要索引的任何字段定义一个getter,这时这个名称就不那么重要了,因为你会把getter名称传递给typedef。
    ///@abitable
    structmystruct
    {
    uint64_tkey;
    uint64_tsecondid;
    std::stringname;
    std::stringaccount;
    uint64_tprimary_key()const{returnkey;}//getterforprimarykey
    uint64_tby_id()const{returnsecondid;}//getterforadditionalkey
    };
    这里还要注意两件事:
    1.注释:
    ///@abitable
    编译器需要使用eosiocpp来识别要通过ABI公开该表并使其在智能合约之外可见。
    2.结构名称少于12个字符,而且所有的字符都要小写字母。
    2.多索引表和定义索引
    定义多索引表将使用mystruct,告诉它要索引什么,以及如何获取正在索引的数据。主键将自动创建的,所以使用struct后,如果我想要一个只有一个主键的多索引表,我可以定义它为:
    typedefeosio::multi_indexdatastore;
    这定义了多个索引通过表名N(mystruct)和结构名mystruct。N(mystruct)会对结构名编译转换到uint64_t,使用uint64_t来标识属于多索引表的数据。
    若要添加附加索引或辅助索引,则使用indexed_by模板作为参数,因此定义变为:
    typedefeosio::multi_index>>datastore;
    注意:
    indexed_by>
    参数:
    字段的名称转换为整数,N(secondid)
    一个用户定义的密钥调用接口,const_mem_fun
    来看看有三个索引的情况。
    ///@abitable
    structmystruct
    {
    uint64_tkey;
    uint64_tsecondid;
    uint64_tanotherid;
    std::stringname;
    std::stringaccount;
    uint64_tprimary_key()const{returnkey;}
    uint64_tby_id()const{returnsecondid;}
    uint64_tby_anotherid()const{returnanotherid;}
    };
    typedefeosio::multi_index>,indexed_by>>datastore;
    更多的就不列了。
    这里要注意的一个重要事项是,结构名与表名的匹配,并且将出现在ABI文件中的名称遵循规则(12个字符,所有都是小写的字母)。如果它们没有遵循这个规则,则表不会通过ABI可见(当然可以通过编辑ABI文件来绕过这一点)。
    3.创建定义类型的局部变量
    //localinstancesofthemultiindexes
    pollstable_polls;
    votes_votes;
    现在我已经定义了一个带有两个索引的多索引表,我可以在我的智能合约中使用它。
    如下是一个智能合约使用两个索引的多索引表的例子。在这里你可以看到如何遍历表,如何在同一合约中使用两个表,我们未来将增加额外的教程,利用多索引表。
    #include
    usingnamespaceeosio;
    classyouvote:publiccontract{
    public:
    youvote(account_names):contract(s),_polls(s,s),_votes(s,s)
    {}
    //publicmethodsexposedviatheABI
    //onpollsTable
    ///@abiaction
    voidversion()
    {
    print("YouVoteversion0.01");
    };
    ///@abiaction
    voidaddpoll(account_names,std::stringpollName)
    {
    //require_auth(s);
    print("Addpoll",pollName);
    //updatethetabletoincludeanewpoll
    _polls.emplace(get_self(),[&](auto&p)
    {
    p.key=_polls.available_primary_key();
    p.pollId=_polls.available_primary_key();
    p.pollName=pollName;
    p.pollStatus=0;
    p.option="";
    p.count=0;
    });
    };
    ///@abiaction
    voidrmpoll(account_names,std::stringpollName)
    {
    //require_auth(s);
    print("Removepoll",pollName);
    std::vectorkeysForDeletion;
    //finditemswhichareforthenamedpoll
    for(auto&item:_polls)
    {
    if(item.pollName==pollName)
    {
    keysForDeletion.push_back(item.key);
    }
    }
    //nowdeleteeachitemforthatpoll
    for(uint64_tkey:keysForDeletion)
    {
    print("removefrom_polls",key);
    autoitr=_polls.find(key);
    if(itr!=_polls.end())
    {
    _polls.erase(itr);
    }
    }
    //addremovevotes...don'tneedittheactionsarepermanentlystoredontheblockchain
    std::vectorkeysForDeletionFromVotes;
    //finditemswhichareforthenamedpoll
    for(auto&item:_votes)
    {
    if(item.pollName==pollName)
    {
    keysForDeletionFromVotes.push_back(item.key);
    }
    }
    //nowdeleteeachitemforthatpoll
    for(uint64_tkey:keysForDeletionFromVotes)
    {
    print("removefrom_votes",key);
    autoitr=_votes.find(key);
    if(itr!=_votes.end())
    {
    _votes.erase(itr);
    }
    }
    };
    ///@abiaction
    voidstatus(std::stringpollName)
    {
    print("Changepollstatus",pollName);
    std::vectorkeysForModify;
    //finditemswhichareforthenamedpoll
    for(auto&item:_polls)
    {
    if(item.pollName==pollName)
    {
    keysForModify.push_back(item.key);
    }
    }
    //nowgeteachitemandmodifythestatus
    for(uint64_tkey:keysForModify)
    {
    print("modify_pollsstatus",key);
    autoitr=_polls.find(key);
    if(itr!=_polls.end())
    {
    _polls.modify(itr,get_self(),[&](auto&p)
    {
    p.pollStatus=p.pollStatus+1;
    });
    }
    }
    };
    ///@abiaction
    voidstatusreset(std::stringpollName)
    {
    print("Resetpollstatus",pollName);
    std::vectorkeysForModify;
    //findallpollitems
    for(auto&item:_polls)
    {
    if(item.pollName==pollName)
    {
    keysForModify.push_back(item.key);
    }
    }
    //updatethestatusineachpollitem
    for(uint64_tkey:keysForModify)
    {
    print("modify_pollsstatus",key);
    autoitr=_polls.find(key);
    if(itr!=_polls.end())
    {
    _polls.modify(itr,get_self(),[&](auto&p)
    {
    p.pollStatus=0;
    });
    }
    }
    };
    ///@abiaction
    voidaddpollopt(std::stringpollName,std::stringoption)
    {
    print("Addpolloption",pollName,"option",option);
    //findthepollId,from_polls,usethistoupdatethe_pollswithanewoption
    for(auto&item:_polls)
    {
    if(item.pollName==pollName)
    {
    //canonlyaddifthepollisnotstartedorfinished
    if(item.pollStatus==0)
    {
    _polls.emplace(get_self(),[&](auto&p)
    {
    p.key=_polls.available_primary_key();
    p.pollId=item.pollId;
    p.pollName=item.pollName;
    p.pollStatus=0;
    p.option=option;
    p.count=0;
    });
    }
    else
    {
    print("Cannotaddpolloption",pollName,"option",option,"Pollhasstartedorisfinished.");
    }
    break;//soyouonlyadditonce
    }
    }
    };
    ///@abiaction
    voidrmpollopt(std::stringpollName,std::stringoption)
    {
    print("Removepolloption",pollName,"option",option);
    std::vectorkeysForDeletion;
    //findandremovethenamedpoll
    for(auto&item:_polls)
    {
    if(item.pollName==pollName)
    {
    keysForDeletion.push_back(item.key);
    }
    }
    for(uint64_tkey:keysForDeletion)
    {
    print("removefrom_polls",key);
    autoitr=_polls.find(key);
    if(itr!=_polls.end())
    {
    if(itr->option==option)
    {
    _polls.erase(itr);
    }
    }
    }
    };
    ///@abiaction
    voidvote(std::stringpollName,std::stringoption,std::stringaccountName)
    {
    print("votefor",option,"inpoll",pollName,"by",accountName);
    //isthepollopen
    for(auto&item:_polls)
    {
    if(item.pollName==pollName)
    {
    if(item.pollStatus!=1)
    {
    print("Poll",pollName,"isnotopen");
    return;
    }
    break;//onlyneedtocheckstatusonce
    }
    }
    //hasaccountnamealreadyvoted?
    for(auto&vote:_votes)
    {
    if(vote.pollName==pollName&&vote.account==accountName)
    {
    print(accountName,"hasalreadyvotedinpoll",pollName);
    //eosio_assert(true,"AlreadyVoted");
    return;
    }
    }
    uint64_tpollId=99999;//getthepollIdforthe_votestable
    //findthepollandtheoptionandincrementthecount
    for(auto&item:_polls)
    {
    if(item.pollName==pollName&&item.option==option)
    {
    pollId=item.pollId;//forrecordingvoteinthispoll
    _polls.modify(item,get_self(),[&](auto&p)
    {
    p.count=p.count+1;
    });
    }
    }
    //recordthataccountNamehasvoted
    _votes.emplace(get_self(),[&](auto&pv)
    {
    pv.key=_votes.available_primary_key();
    pv.pollId=pollId;
    pv.pollName=pollName;
    pv.account=accountName;
    });
    };
    private:
    //createthemultiindextablestostorethedata
    ///@abitable
    structpoll
    {
    uint64_tkey;//primarykey
    uint64_tpollId;//secondkey,non-unique,thistablewillhaveduprowsforeachpollbecauseofoption
    std::stringpollName;//nameofpoll
    uint8_tpollStatus=0;//stauswhere0=closed,1=open,2=finished
    std::stringoption;//theitemyoucanvotefor
    uint32_tcount=0;//thenumberofvotesforeachitme--thistobepulledouttosepartetable.
    uint64_tprimary_key()const{returnkey;}
    uint64_tby_pollId()const{returnpollId;}
    };
    typedefeosio::multi_index>>pollstable;
    ///@abitable
    structpollvotes
    {
    uint64_tkey;
    uint64_tpollId;
    std::stringpollName;//nameofpoll
    std::stringaccount;//thisaccounthasvoted,usethistomakesurenoonevotes>1
    uint64_tprimary_key()const{returnkey;}
    uint64_tby_pollId()const{returnpollId;}
    };
    typedefeosio::multi_index>>votes;
    //localinstancesofthemultiindexes
    pollstable_polls;
    votes_votes;
    };
    EOSIO_ABI(youvote,(version)(addpoll)(rmpoll)(status)(statusreset)(addpollopt)(rmpollopt)(vote))
    注意EOSIO_ABI调用,它通过ABI公开函数,重要的是函数名与ABI函数名规则一定要匹配。
BitMere.com is Information release platform,just provides information storage space services.
The opinions expressed are solely those of the author,Does not constitute advice, please treat with caution.
You have to log in before you can reply Login | 立即注册

Points Rules

Write the first review

西门幻雪雪vj 小学生
  • Follow

    0

  • Following

    0

  • Articles

    8

Promoted