Move Table

During the update of the contract, if the Table data structure is changed, the data in the old structure cannot be modified and accessed. You can upgrade the contract table by following the steps below.

1、Create New Table

The newly created Table type needs to be compatible with the old Table type. First add a new Table type to the contract and keep the old Table type.

class movetable : public contract
{
  public:
    movetable(uint64_t id)
        : contract(id),accounts(_self,_self),accountnews(_self,_self){}

    //@abi action
    void setstat(bool states){
        ...
        auto itor = stats.find(0);
        if(itor == stats.end()){
            stats.emplace(_self,[&](auto &o) {
                o.id = stats.available_primary_key();;
                o.isable = states;
            });
        }else{
            stats.modify(_self,itor,[&](auto &o) {
                o.id = stats.available_primary_key();;
                o.isable = states;
            });
        }
        ...
    }
    //@abi action
    void add(std::string name){
        accounts.emplace(_self, [&](auto &o) {
            o.id = accounts.available_primary_key();;
            o.name = name;
        });
    }
  private:
    //@abi table stat i64
    struct stat {
        uint64_t id;
        uint64_t isable;
        uint64_t primary_key() const { return id; }
        GRAPHENE_SERIALIZE(stat, (id)(isable))
    };
    typedef graphene::multi_index<N(stat), stat> stat_index;
    stat_index stats;

    // Old Table
    //@abi table account i64
    struct account {
        uint64_t id;
        std::string name;
        uint64_t primary_key() const { return id; }
        GRAPHENE_SERIALIZE(account, (id)(name))
    };
    typedef graphene::multi_index<N(account), account> account_index;
    account_index accounts;

    // New Table
    //@abi table accountnew i64
    struct accountnew {
        uint64_t id;
        std::string name;
        uint64_t age;
        uint64_t primary_key() const { return id; }
        GRAPHENE_SERIALIZE(accountnew, (id)(name)(age))
    };
    typedef graphene::multi_index<N(accountnew), accountnew> accountnew_index;
    accountnew_index accountnews;
};

2、Copy the data

Before migrating data, you need to set the parameter isable to FALSE to prohibit inserting data into the old Table. Then add the move function to copy the data from the old Table to the new Table.

class movetable : public contract
{
  public:
    movetable(uint64_t id)
        : contract(id),accounts(_self,_self),accountnews(_self,_self){}
    ...
    //@abi action
    void add(std::string name){
        auto itor = stats.find(0);
        graphene_assert(itor->isable, "now can't add data to table");
        accounts.emplace(_self, [&](auto &o) {
            o.id = accounts.available_primary_key();
            o.name = name;
        });
    }
    //@abi action
    void move(){
        auto itor = stats.find(0);
        stats.modify(_self,itor, [&](auto &o) {
            o.isable = FALSE;
        });
        for(auto i =accounts.begin(); i!=accounts.end(); i++){
            accountnews.emplace(_self, [&](auto &o) {
                o.id = i->id;
                o.name = i->name;
                o.age = 0;
            });
        }
    }
  private:
    ...
    accountnew_index accountnews;
};

3、Delete Old Table

After the data migration is completed, you need to verify whether the data in the new table is consistent with the data in the old table. If they are consistent, the old Table data is deleted, and the new data is inserted into the new Table. Modify the contract status stat to TRUE, modify the add interface, and add the delete interface. The sample code is as follows:

class movetable : public contract
{
  public:
    movetable(uint64_t id)
        : contract(id),accounts(_self,_self),accountnews(_self,_self){}
    ...
    //@abi action
    void add(std::string name){
        auto itor = stats.find(0);
        graphene_assert(itor->isable, "now can't add data to table");
        accountnews.emplace(_self, [&](auto &o) {
            o.id = accountnews.available_primary_key();
            o.name = name;
        });
    }
    ...
    //@abi action
    void delete(){
        for(auto i =accounts.begin(); i!=accounts.end(); i++){
            accounts.erase(i);
        }
    }
  private:
    ...
    accountnew_index accountnews;
};
Last Updated: 7/12/2019, 7:05:51 PM