push
github
vinyl: fix handling of duplicate multikey entries in transaction write set A multikey index stores a tuple once per each entry of the indexed array field, excluding duplicates. For example, if the array field equals {1, 3, 2, 3}, the tuple will be stored three times. Currently, when a tuple with duplicate multikey entries is inserted into a transaction write set, duplicates are overwritten as if they belonged to different statements. Actually, this is pointless: we could just as well skip them without trying to add to the write set. Besides, this may break the assumptions taken by various optimizations, resulting in anomalies. Consider the following example: ```lua local s = box.schema.space.create('test', {engine = 'vinyl'}) s:create_index('primary') s:create_index('secondary', {parts = {{'[2][*]', 'unsigned'}}}) s:replace({1, {10, 10}}) s:update({1}, {{'=', 2, {10}}}) ``` It will insert the following entries to the transaction write set of the secondary index: 1. REPLACE {10, 1} [overwritten by no.2] 2. REPLACE {10, 1} [overwritten by no.3] 3. DELETE {10, 1} [turned into no-op as REPLACE + DELETE] 4. DELETE {10, 1} [overwritten by no.5] 5. REPLACE {10, 1} [turned into no-op as DELETE + REPLACE] (1-2 correspond to `replace()` and 3-5 to `delete()`) As a result, tuple {1, {10}} will be lost forever. Let's fix this issue by silently skipping duplicate multikey entries added to a transaction write set. After the fix, the example above will produce the following write set entries: 1. REPLACE{10, 1} [overwritten by no.2] 2. DELETE{10, 1} [turned into no-op as REPLACE + DELETE] 3. REPLACE{10, 1} [committed] (1 corresponds to `replace()` and 2-3 to `delete()`) Closes #10869 Closes #10870 NO_DOC=bug fix (cherry picked from commit 1869dce15)
63176 of 114409 branches covered (55.22%)
6 of 6 new or added lines in 1 file covered. (100.0%)
43 existing lines in 13 files now uncovered.94019 of 109396 relevant lines covered (85.94%)
3019965.41 hits per line