2

How do I create a struct and multi_index table that allow for duplicate records? For example, I have the below struct and multi_index table that is populated via an emplace call that selects a randomly chosen account tg (account) and tgu (account).

struct tgb {
  // experimenting with Dapp-generated primary key
  // and blockchain generated primary key
  uint32_t        pkey;     // b-chain generated
  account_name    tg;
  account_name    tgu; 
  uint32_t        timestamp;

  uint32_t primary_key() const { return  breachId; }
  EOSLIB_SERIALIZE(tgb, (pkey)(tg)(tgu)(timestamp));
};

typedef eosio::multi_index<N(tgbs), tgb> tgb_table;

The table is being inserted into using the following emplace call:

tgb_table tgb(_self, _self);

tgb.emplace(tgu, [&](auto& t) {
    t.pkey                = tgb.available_primary_key();
    t.tg                  = tg;
    t.tgu                 = tgu;
    t.timestamp           = now();
  });

If a duplicate tg and tgu are called at the same second, I get an error that most likely a uniqueness constraint was violated.

Error 3030000: transaction validation exception
Ensure that your transaction satisfy the contract's constraint!
Error Details:
could not insert object, most likely a uniqueness constraint was violated:         

However, my expectation was that the "available_primary_key()" method would prevent this error by establishing uniqueness of the record. My workaround has been to create a unique ID in the client script and pass it to the action, but I was hoping that the incrementing "available_primary_key" would suffice.

Is there a way to configure the multi_index table to allow for duplicates?

  • Have you looked at the values being output by available_primary_key() in this case? Are they in fact unique? – kkurian May 22 '18 at 20:47
  • I did actually notice this after posting. They are not unique. Am I missing something on the configuration? In the meantime, I'm manually adding a random "breachId" int. Here's what the data looks like:Here's what the data looks like:{ "rows": [{ "pkey": 9893, "breachId": 3747, "tg": "mbf22", "tgu": "uvzhu", "timestamp": 1527108383 },{ "pkey": 9893, "breachId": 4574, "tg": "t3l1d", "tgu": "dhqzz", "timestamp": 1527108383 },... – Max May 23 '18 at 21:54
  • It seems the original question is answered: The multi_index is functioning as expected. The problem is duplicates from available_primary_key(). Might be worth a separate question to the community related to that. I don't have an answer to your follow-up question. – kkurian May 23 '18 at 22:24
4

I guess your problem might be that you are saving the primary key as uint32_t but it has to be a uint64_t. Because it might be that if you try to save the id (0x00000000) it will cut the last 32 bits (0x0000) and result in a 0x0000. If you try to save a new one then you would expect 0x00000001 which will also be cut to 0x0000.

The available_primary_key() function has the following notation:

public inline uint64_t available_primary_key() const

I would suggest editing your struct to the following:

  struct tgb {
    // experimenting with Dapp-generated primary key
    // and blockchain generated primary key
    uint64_t        pkey;     // b-chain generated
    account_name    tg;
    account_name    tgu; 
    uint32_t        timestamp;

    uint64_t primary_key() const { return  pKey; }
    EOSLIB_SERIALIZE(tgb, (pkey)(tg)(tgu)(timestamp));
  };

Further documentation can be found here.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.