Has anyone implemented a CRUD (create, read, update, and delete) for global storage using Move?
I want to port some code from EOS that uses upsert.
Has anyone implemented a CRUD (create, read, update, and delete) for global storage using Move?
I want to port some code from EOS that uses upsert.
Can you give some example in EOS?
Sure, This my favorite blockchain class and #2 reason I like EOS. The #1 is no gas required!. Class below is .cpp, includes DBMS upsert.
#include <eosiolib/eosio.hpp>
using namespace eosio;
class [[eosio::contract]] addressbook : public eosio::contract {
public:
using contract::contract;
addressbook(name receiver, name code, datastream<const char*> ds): contract(receiver, code, ds) {}
[[eosio::action]]
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
require_auth( user );
address_index addresses(_code, _code.value);
auto iterator = addresses.find(user.value);
if( iterator == addresses.end() )
{
addresses.emplace(user, [&]( auto& row ) {
row.key = user;
row.first_name = first_name;
row.last_name = last_name;
row.street = street;
row.city = city;
row.state = state;
});
}
else {
std::string changes;
addresses.modify(iterator, user, [&]( auto& row ) {
row.key = user;
row.first_name = first_name;
row.last_name = last_name;
row.street = street;
row.city = city;
row.state = state;
});
}
}
[[eosio::action]]
void erase(name user) {
// require_auth(user);
address_index addresses(_self, _code.value);
auto iterator = addresses.find(user.value);
eosio_assert(iterator != addresses.end(), "Record does not exist");
addresses.erase(iterator);
}
private:
struct [[eosio::table]] person {
name key;
std::string first_name;
std::string last_name;
std::string street;
std::string city;
std::string state;
uint64_t primary_key() const { return key.value; }
};
typedef eosio::multi_index<“people”_n, person> address_index;
};
EOSIO_DISPATCH( addressbook, (upsert)(erase))
I try to write a Move contract but Move did not support collection currently, so an account just can keep one address record. I just implement upsert function, because Libra did not support query function like eth.
code: https://github.com/jolestar/libra/blob/hack/client/move/address_book.mvir
Execute with my libra fork client:
hack execute 0 $libra_project_dir/libra/client/move/address_book.mvir 74657374 c759e60f58b4543763580278736d929d6a779afd3edd9bfbee2d43f6f3d1d6e1 6265696a696e67
modules:
module Addressbook {
//Move not support collection currently,
//If Move support collection, this resource should use a collection to contain address data.
resource T {
name: bytearray,
addr: address,
city: bytearray,
}
public upsert(name: bytearray, addr:address, city: bytearray){
let sender:address;
let entry: R#Self.T;
let entry_exists: bool;
sender = get_txn_sender();
entry_exists = exists<T>(copy(sender));
if (move(entry_exists)) {
entry = move_from<T>(move(sender));
} else {
entry = T{ name:move(name), addr:move(addr), city:move(city) };
}
move_to_sender<T>(move(entry));
return;
}
}
script:
import Transaction.Addressbook;
main(name:bytearray, addr:address, city:bytearray){
Addressbook.upsert(move(name), move(addr), move(city));
return;
}
This is excellent first start. You saved me a lot of time. Bravo!
Collections may be minor in beginning. May rely more on primary key
if I can use UnsignedInt64.
Question: The key for the record would be T which =
name ∪ addr ∪ city
Any advice how to handle “erase” … pursuant to EOS example?
the key would be name or addr.
Any advice how to handle “erase” … pursuant to EOS example?
just move_from the resource and release(T) it.
Sorry new to Move, are you suggesting use of releaseref(entry) ?
just use release(entry)
release only can release ref, if you want to delete Resource, can move it out then expand filed to consume it.
public delete(){
let sender: address;
let name: bytearray;
let addr: address;
let city: bytearray;
let entry_exists: bool;
let entry: R#Self.T;
sender = get_txn_sender();
entry_exists = exists<T>(copy(sender));
if (move(entry_exists)) {
entry = move_from<T>(move(sender));
T{name,addr,city} = move(entry);
}
return;
}