<HTML><BODY><div id="composeWebView_editable_content" data-mailruapp-compose-id="composeWebView_editable_content" style="text-align: left;"><div>Sergey, thanks for the patch, LGTM,</div><div><br></div><div id="mail-app-auto-default-signature"><br><br>Отправлено из мобильной Почты Mail.ru<br></div><br><br>четверг, 19 марта 2020 г., 13:25 +0300 от Sergey Bronnikov  <sergeyb@tarantool.org>:<br><div id="composeWebView_previouse_content" data-mailruapp-compose-id="composeWebView_previouse_content"><blockquote id="mail-app-auto-quote" style="border-left-width: 1px; border-left-style: solid; border-left-color: rgb(0, 95, 249); margin: 10px 0px 10px 5px; padding: 0px 0px 0px 10px; display: inherit;"><div class="js-helper js-readmsg-msg">
        <style type="text/css"></style>
        <div>
                <base target="_self" href="https://e.mail.ru/">
                
            <div id="style_15846135020497582278_BODY">Splitted single hash.test.lua to a set of small independent tests.<br>
<br>
GitHub branch: <a href="https://github.com/tarantool/tarantool/tree/ligurio/hash_test_split" target="_blank">https://github.com/tarantool/tarantool/tree/ligurio/hash_test_split</a><br>
<br>
---<br>
 test/box/hash.result                  | 873 --------------------------<br>
 test/box/hash.test.lua                | 364 -----------<br>
 test/box/hash_32bit_delete.result     |  70 +++<br>
 test/box/hash_32bit_delete.test.lua   |  29 +<br>
 test/box/hash_32bit_insert.result     |  38 ++<br>
 test/box/hash_32bit_insert.test.lua   |  16 +<br>
 test/box/hash_32bit_replace.result    |  56 ++<br>
 test/box/hash_32bit_replace.test.lua  |  25 +<br>
 test/box/hash_32bit_select.result     |  70 +++<br>
 test/box/hash_32bit_select.test.lua   |  29 +<br>
 test/box/hash_64bit_delete.result     | 111 ++++<br>
 test/box/hash_64bit_delete.test.lua   |  42 ++<br>
 test/box/hash_64bit_insert.result     |  54 ++<br>
 test/box/hash_64bit_insert.test.lua   |  20 +<br>
 test/box/hash_64bit_replace.result    |  68 ++<br>
 test/box/hash_64bit_replace.test.lua  |  28 +<br>
 test/box/hash_64bit_select.result     |  94 +++<br>
 test/box/hash_64bit_select.test.lua   |  37 ++<br>
 test/box/hash_collation.result        |  62 ++<br>
 test/box/hash_collation.test.lua      |  22 +<br>
 test/box/hash_gh-1467.result          |  17 +<br>
 test/box/hash_gh-1467.test.lua        |   6 +<br>
 test/box/hash_gh-3907.result          |  48 ++<br>
 test/box/hash_gh-3907.test.lua        |  15 +<br>
 test/box/hash_gh-616.result           |  17 +<br>
 test/box/hash_gh-616.test.lua         |   7 +<br>
 test/box/hash_iterate.result          |  21 +<br>
 test/box/hash_iterate.test.lua        |   6 +<br>
 test/box/hash_multipart.result        |   7 -<br>
 test/box/hash_multipart.test.lua      |   2 -<br>
 test/box/hash_not_a_multikey.result   |  17 +<br>
 test/box/hash_not_a_multikey.test.lua |   6 +<br>
 test/box/hash_replace.result          | 256 ++++++++<br>
 test/box/hash_replace.test.lua        |  88 +++<br>
 test/box/hash_string_delete.result    |  62 ++<br>
 test/box/hash_string_delete.test.lua  |  24 +<br>
 test/box/hash_string_insert.result    |  32 +<br>
 test/box/hash_string_insert.test.lua  |  13 +<br>
 test/box/hash_string_replace.result   |  47 ++<br>
 test/box/hash_string_replace.test.lua |  19 +<br>
 test/box/hash_string_select.result    |  63 ++<br>
 test/box/hash_string_select.test.lua  |  25 +<br>
 test/box/hash_with_function.result    |  26 +<br>
 test/box/hash_with_function.test.lua  |   9 +<br>
 44 files changed, 1695 insertions(+), 1246 deletions(-)<br>
 delete mode 100644 test/box/hash.result<br>
 delete mode 100644 test/box/hash.test.lua<br>
 create mode 100644 test/box/hash_32bit_delete.result<br>
 create mode 100644 test/box/hash_32bit_delete.test.lua<br>
 create mode 100644 test/box/hash_32bit_insert.result<br>
 create mode 100644 test/box/hash_32bit_insert.test.lua<br>
 create mode 100644 test/box/hash_32bit_replace.result<br>
 create mode 100644 test/box/hash_32bit_replace.test.lua<br>
 create mode 100644 test/box/hash_32bit_select.result<br>
 create mode 100644 test/box/hash_32bit_select.test.lua<br>
 create mode 100644 test/box/hash_64bit_delete.result<br>
 create mode 100644 test/box/hash_64bit_delete.test.lua<br>
 create mode 100644 test/box/hash_64bit_insert.result<br>
 create mode 100644 test/box/hash_64bit_insert.test.lua<br>
 create mode 100644 test/box/hash_64bit_replace.result<br>
 create mode 100644 test/box/hash_64bit_replace.test.lua<br>
 create mode 100644 test/box/hash_64bit_select.result<br>
 create mode 100644 test/box/hash_64bit_select.test.lua<br>
 create mode 100644 test/box/hash_collation.result<br>
 create mode 100644 test/box/hash_collation.test.lua<br>
 create mode 100644 test/box/hash_gh-1467.result<br>
 create mode 100644 test/box/hash_gh-1467.test.lua<br>
 create mode 100644 test/box/hash_gh-3907.result<br>
 create mode 100644 test/box/hash_gh-3907.test.lua<br>
 create mode 100644 test/box/hash_gh-616.result<br>
 create mode 100644 test/box/hash_gh-616.test.lua<br>
 create mode 100644 test/box/hash_iterate.result<br>
 create mode 100644 test/box/hash_iterate.test.lua<br>
 create mode 100644 test/box/hash_not_a_multikey.result<br>
 create mode 100644 test/box/hash_not_a_multikey.test.lua<br>
 create mode 100644 test/box/hash_replace.result<br>
 create mode 100644 test/box/hash_replace.test.lua<br>
 create mode 100644 test/box/hash_string_delete.result<br>
 create mode 100644 test/box/hash_string_delete.test.lua<br>
 create mode 100644 test/box/hash_string_insert.result<br>
 create mode 100644 test/box/hash_string_insert.test.lua<br>
 create mode 100644 test/box/hash_string_replace.result<br>
 create mode 100644 test/box/hash_string_replace.test.lua<br>
 create mode 100644 test/box/hash_string_select.result<br>
 create mode 100644 test/box/hash_string_select.test.lua<br>
 create mode 100644 test/box/hash_with_function.result<br>
 create mode 100644 test/box/hash_with_function.test.lua<br>
<br>
diff --git a/test/box/hash.result b/test/box/hash.result<br>
deleted file mode 100644<br>
index 5e1441ecc..000000000<br>
--- a/test/box/hash.result<br>
+++ /dev/null<br>
@@ -1,873 +0,0 @@<br>
---=============================================================================<br>
--- 32-bit hash tests<br>
---=============================================================================<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash insert fields tests<br>
--------------------------------------------------------------------------------<br>
-hash = box.schema.space.create('tweedledum')<br>
----<br>
-...<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
----<br>
-...<br>
-bsize = tmp:bsize()<br>
----<br>
-...<br>
--- Insert valid fields<br>
-hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [1, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [2, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [3, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-tmp:bsize() > bsize<br>
----<br>
-- true<br>
-...<br>
--- Insert invalid fields<br>
-hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash replace fields tests<br>
--------------------------------------------------------------------------------<br>
--- Replace valid fields<br>
-hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
--- Replace invalid fields<br>
-hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash select fields test<br>
--------------------------------------------------------------------------------<br>
--- select by valid keys<br>
-hash.index['primary']:get{0}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash.index['primary']:get{1}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash.index['primary']:get{2}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash.index['primary']:get{3}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash.index['primary']:get{4}<br>
----<br>
-...<br>
-hash.index['primary']:get{5}<br>
----<br>
-...<br>
--- select by invalid keys<br>
-hash.index['primary']:get{'invalid key'}<br>
----<br>
-- error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
-...<br>
-hash.index['primary']:get{1, 2}<br>
----<br>
-- error: Invalid key part count in an exact match (expected 1, got 2)<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash delete fields test<br>
--------------------------------------------------------------------------------<br>
--- delete by valid keys<br>
-hash:delete{0}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{1}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:delete{2}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash:delete{3}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:delete{4}<br>
----<br>
-...<br>
-hash:delete{5}<br>
----<br>
-...<br>
--- delete by invalid keys<br>
-hash:delete{'invalid key'}<br>
----<br>
-- error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
-...<br>
-hash:delete{1, 2}<br>
----<br>
-- error: Invalid key part count in an exact match (expected 1, got 2)<br>
-...<br>
-hash:truncate()<br>
----<br>
-...<br>
---=============================================================================<br>
--- 64-bit hash tests<br>
---=============================================================================<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash inset fields tests<br>
--------------------------------------------------------------------------------<br>
--- Insert valid fields<br>
-hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [1, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [2, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [3, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
--- Insert invalid fields<br>
-hash:insert{100, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [100, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{101, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [101, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{102, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [102, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{103, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [103, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash replace fields tests<br>
--------------------------------------------------------------------------------<br>
--- Replace valid fields<br>
-hash:replace{3ULL, 'value1 v1.31', 'value2 1.12'}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:replace{1ULL, 'value1 v1.32', 'value2 1.72'}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:replace{2ULL, 'value1 v1.43', 'value2 1.92'}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
--- Replace invalid fields<br>
-hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash select fields test<br>
--------------------------------------------------------------------------------<br>
--- select by valid keys<br>
-hash.index['primary']:get{0ULL}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash.index['primary']:get{1ULL}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash.index['primary']:get{2ULL}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash.index['primary']:get{3ULL}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash.index['primary']:get{4ULL}<br>
----<br>
-...<br>
-hash.index['primary']:get{5ULL}<br>
----<br>
-...<br>
--- select by valid NUM keys<br>
-hash.index['primary']:get{0}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash.index['primary']:get{1}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash.index['primary']:get{2}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash.index['primary']:get{3}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash.index['primary']:get{4}<br>
----<br>
-...<br>
-hash.index['primary']:get{5}<br>
----<br>
-...<br>
--- select by invalid keys<br>
-hash.index['primary']:get{'invalid key'}<br>
----<br>
-- error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
-...<br>
-hash.index['primary']:get{'00000001', '00000002'}<br>
----<br>
-- error: Invalid key part count in an exact match (expected 1, got 2)<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash delete fields test<br>
--------------------------------------------------------------------------------<br>
--- delete by valid keys<br>
-hash:delete{0ULL}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{1ULL}<br>
----<br>
-- [1, 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:delete{2ULL}<br>
----<br>
-- [2, 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash:delete{3ULL}<br>
----<br>
-- [3, 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:delete{4ULL}<br>
----<br>
-...<br>
-hash:delete{5ULL}<br>
----<br>
-...<br>
-hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [1, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [2, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- [3, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
--- delete by valid NUM keys<br>
-hash:delete{0}<br>
----<br>
-- [0, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{1}<br>
----<br>
-- [1, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{2}<br>
----<br>
-- [2, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{3}<br>
----<br>
-- [3, 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{4}<br>
----<br>
-...<br>
-hash:delete{5}<br>
----<br>
-...<br>
--- delete by invalid keys<br>
-hash:delete{'invalid key'}<br>
----<br>
-- error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
-...<br>
-hash:delete{'00000001', '00000002'}<br>
----<br>
-- error: Invalid key part count in an exact match (expected 1, got 2)<br>
-...<br>
-hash:truncate()<br>
----<br>
-...<br>
---=============================================================================<br>
--- String hash tests<br>
---=============================================================================<br>
--------------------------------------------------------------------------------<br>
--- String hash inset fields tests<br>
--------------------------------------------------------------------------------<br>
-hash.index['primary']:drop()<br>
----<br>
-...<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
----<br>
-...<br>
--- Insert valid fields<br>
-hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
----<br>
-- ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- String hash replace fields tests<br>
--------------------------------------------------------------------------------<br>
--- Replace valid fields<br>
-hash:replace{'key 3', 'value1 v1.31', 'value2 1.12'}<br>
----<br>
-- ['key 3', 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:replace{'key 1', 'value1 v1.32', 'value2 1.72'}<br>
----<br>
-- ['key 1', 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:replace{'key 2', 'value1 v1.43', 'value2 1.92'}<br>
----<br>
-- ['key 2', 'value1 v1.43', 'value2 1.92']<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- String hash select fields test<br>
--------------------------------------------------------------------------------<br>
--- select by valid keys<br>
-hash.index['primary']:get{'key 0'}<br>
----<br>
-- ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash.index['primary']:get{'key 1'}<br>
----<br>
-- ['key 1', 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash.index['primary']:get{'key 2'}<br>
----<br>
-- ['key 2', 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash.index['primary']:get{'key 3'}<br>
----<br>
-- ['key 3', 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash.index['primary']:get{'key 4'}<br>
----<br>
-...<br>
-hash.index['primary']:get{'key 5'}<br>
----<br>
-...<br>
--- select by invalid keys<br>
-hash.index['primary']:get{'key 1', 'key 2'}<br>
----<br>
-- error: Invalid key part count in an exact match (expected 1, got 2)<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- String hash delete fields test<br>
--------------------------------------------------------------------------------<br>
--- delete by valid keys<br>
-hash:delete{'key 0'}<br>
----<br>
-- ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
-...<br>
-hash:delete{'key 1'}<br>
----<br>
-- ['key 1', 'value1 v1.32', 'value2 1.72']<br>
-...<br>
-hash:delete{'key 2'}<br>
----<br>
-- ['key 2', 'value1 v1.43', 'value2 1.92']<br>
-...<br>
-hash:delete{'key 3'}<br>
----<br>
-- ['key 3', 'value1 v1.31', 'value2 1.12']<br>
-...<br>
-hash:delete{'key 4'}<br>
----<br>
-...<br>
-hash:delete{'key 5'}<br>
----<br>
-...<br>
--- delete by invalid keys<br>
-hash:delete{'key 1', 'key 2'}<br>
----<br>
-- error: Invalid key part count in an exact match (expected 1, got 2)<br>
-...<br>
-hash:truncate()<br>
----<br>
-...<br>
--------------------------------------------------------------------------------<br>
--- Collation test<br>
--------------------------------------------------------------------------------<br>
-hash.index['primary']:drop()<br>
----<br>
-...<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {{1, 'string', collation = 'unicode_ci'}}, unique = true})<br>
----<br>
-...<br>
-tmp = hash:create_index('secondary', { type = 'hash', parts = {{2, 'scalar', collation = 'unicode_ci'}}, unique = true})<br>
----<br>
-...<br>
-hash:insert{'Ёж', 'Hedgehog'}<br>
----<br>
-- ['Ёж', 'Hedgehog']<br>
-...<br>
-hash:insert{'Ёлка', 'Spruce'}<br>
----<br>
-- ['Ёлка', 'Spruce']<br>
-...<br>
-hash:insert{'Jogurt', 'Йогурт'}<br>
----<br>
-- ['Jogurt', 'Йогурт']<br>
-...<br>
-hash:insert{'Один', 1}<br>
----<br>
-- ['Один', 1]<br>
-...<br>
-hash.index.primary:get('ёж')<br>
----<br>
-- ['Ёж', 'Hedgehog']<br>
-...<br>
-hash.index.primary:get('елка')<br>
----<br>
-- ['Ёлка', 'Spruce']<br>
-...<br>
-hash.index.secondary:get('spruce')<br>
----<br>
-- ['Ёлка', 'Spruce']<br>
-...<br>
-hash.index.secondary:get('йогурт')<br>
----<br>
-- ['Jogurt', 'Йогурт']<br>
-...<br>
-hash.index.secondary:get(1)<br>
----<br>
-- ['Один', 1]<br>
-...<br>
-hash.index.secondary:get('иогурт')<br>
----<br>
-...<br>
-hash.index.secondary:get(2)<br>
----<br>
-...<br>
-------------------------<br>
--- hash::replace tests<br>
-------------------------<br>
-hash.index['secondary']:drop()<br>
----<br>
-...<br>
-hash.index['primary']:drop()<br>
----<br>
-...<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
----<br>
-...<br>
-tmp = hash:create_index('field1', { type = 'hash', parts = {2, 'unsigned'}, unique = true })<br>
----<br>
-...<br>
-tmp = hash:create_index('field2', { type = 'hash', parts = {3, 'unsigned'}, unique = true })<br>
----<br>
-...<br>
-tmp = hash:create_index('field3', { type = 'hash', parts = {4, 'unsigned'}, unique = true })<br>
----<br>
-...<br>
-hash:insert{0, 0, 0, 0}<br>
----<br>
-- [0, 0, 0, 0]<br>
-...<br>
-hash:insert{1, 1, 1, 1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
-hash:insert{2, 2, 2, 2}<br>
----<br>
-- [2, 2, 2, 2]<br>
-...<br>
--- OK<br>
-hash:replace{1, 1, 1, 1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
-hash.index['primary']:get{10}<br>
----<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-...<br>
-hash.index['primary']:get{1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
-hash.index['field1']:get{1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
-hash.index['field2']:get{1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
-hash.index['field3']:get{1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
--- OK<br>
-hash:insert{10, 10, 10, 10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash:delete{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['primary']:get{10}<br>
----<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-...<br>
--- TupleFound (primary key)<br>
-hash:insert{1, 10, 10, 10}<br>
----<br>
-- error: Duplicate key exists in unique index 'primary' in space 'tweedledum'<br>
-...<br>
-hash.index['primary']:get{10}<br>
----<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-...<br>
-hash.index['primary']:get{1}<br>
----<br>
-- [1, 1, 1, 1]<br>
-...<br>
--- TupleNotFound (primary key)<br>
-hash:replace{10, 10, 10, 10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['primary']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
--- TupleFound (key --1)<br>
-hash:insert{10, 0, 10, 10}<br>
----<br>
-- error: Duplicate key exists in unique index 'primary' in space 'tweedledum'<br>
-...<br>
-hash.index['primary']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{0}<br>
----<br>
-- [0, 0, 0, 0]<br>
-...<br>
--- TupleFound (key --1)<br>
--- hash:replace_if_exists(2, 0, 10, 10)<br>
-hash.index['primary']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{0}<br>
----<br>
-- [0, 0, 0, 0]<br>
-...<br>
--- TupleFound (key --3)<br>
-hash:insert{10, 10, 10, 0}<br>
----<br>
-- error: Duplicate key exists in unique index 'primary' in space 'tweedledum'<br>
-...<br>
-hash.index['primary']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{0}<br>
----<br>
-- [0, 0, 0, 0]<br>
-...<br>
--- TupleFound (key --3)<br>
--- hash:replace_if_exists(2, 10, 10, 0)<br>
-hash.index['primary']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field1']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field2']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{10}<br>
----<br>
-- [10, 10, 10, 10]<br>
-...<br>
-hash.index['field3']:get{0}<br>
----<br>
-- [0, 0, 0, 0]<br>
-...<br>
-hash:drop()<br>
----<br>
-...<br>
-hash = box.schema.space.create('tweedledum')<br>
----<br>
-...<br>
-hi = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
----<br>
-...<br>
-hash:insert{0}<br>
----<br>
-- [0]<br>
-...<br>
-hash:insert{16}<br>
----<br>
-- [16]<br>
-...<br>
-for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end<br>
----<br>
-...<br>
-hash:drop()<br>
----<br>
-...<br>
--- <br>
--- gh-616 "1-based indexing and 0-based error message<br>
---<br>
-_ = box.schema.create_space('test')<br>
----<br>
-...<br>
-_ = box.space.test:create_index('i',{parts={1,'string'}})<br>
----<br>
-...<br>
-box.space.test:insert{1}<br>
----<br>
-- error: 'Tuple field 1 type does not match one required by operation: expected string'<br>
-...<br>
-box.space.test:drop()<br>
----<br>
-...<br>
--- gh-1467: invalid iterator type<br>
-space = box.schema.space.create('test')<br>
----<br>
-...<br>
-index = space:create_index('primary', { type = 'hash' })<br>
----<br>
-...<br>
-space:select({1}, {iterator = 'BITS_ALL_SET' } )<br>
----<br>
-- error: Index 'primary' (HASH) of space 'test' (memtx) does not support requested<br>
-    iterator type<br>
-...<br>
-space:drop()<br>
----<br>
-...<br>
--- gh-3907: check that integer numbers stored as MP_FLOAT/MP_DOUBLE<br>
--- are hashed as MP_INT/MP_UINT.<br>
-ffi = require('ffi')<br>
----<br>
-...<br>
-s = box.schema.space.create('test')<br>
----<br>
-...<br>
-_ = s:create_index('primary', {type = 'hash', parts = {1, 'number'}})<br>
----<br>
-...<br>
-s:insert{ffi.new('double', 0)}<br>
----<br>
-- [0]<br>
-...<br>
-s:insert{ffi.new('double', -1)}<br>
----<br>
-- [-1]<br>
-...<br>
-s:insert{ffi.new('double', 9007199254740992)}<br>
----<br>
-- [9007199254740992]<br>
-...<br>
-s:insert{ffi.new('double', -9007199254740994)}<br>
----<br>
-- [-9007199254740994]<br>
-...<br>
-s:get(0LL)<br>
----<br>
-- [0]<br>
-...<br>
-s:get(-1LL)<br>
----<br>
-- [-1]<br>
-...<br>
-s:get(9007199254740992LL)<br>
----<br>
-- [9007199254740992]<br>
-...<br>
-s:get(-9007199254740994LL)<br>
----<br>
-- [-9007199254740994]<br>
-...<br>
-s:drop()<br>
----<br>
-...<br>
--- Hash index cannot be multikey.<br>
-s = box.schema.space.create('test')<br>
----<br>
-...<br>
-_ = s:create_index('primary')<br>
----<br>
-...<br>
-_ = s:create_index('hash', {type = 'hash', parts = {{'[2][*]', 'unsigned'}}})<br>
----<br>
-- error: 'Can''t create or modify index ''hash'' in space ''test'': HASH index cannot<br>
-    be multikey'<br>
-...<br>
-s:drop()<br>
----<br>
-...<br>
--- Hash index can not use function.<br>
-s = box.schema.space.create('withdata')<br>
----<br>
-...<br>
-lua_code = [[function(tuple) return tuple[1] + tuple[2] end]]<br>
----<br>
-...<br>
-box.schema.func.create('s', {body = lua_code, is_deterministic = true, is_sandboxed = true})<br>
----<br>
-...<br>
-_ = s:create_index('pk')<br>
----<br>
-...<br>
-_ = s:create_index('idx', {type = 'hash', func = box.func.s.id, parts = {{1, 'unsigned'}}})<br>
----<br>
-- error: 'Can''t create or modify index ''idx'' in space ''withdata'': HASH index<br>
-    can not use a function'<br>
-...<br>
-s:drop()<br>
----<br>
-...<br>
-box.schema.func.drop('s')<br>
----<br>
-...<br>
diff --git a/test/box/hash.test.lua b/test/box/hash.test.lua<br>
deleted file mode 100644<br>
index 78c831f77..000000000<br>
--- a/test/box/hash.test.lua<br>
+++ /dev/null<br>
@@ -1,364 +0,0 @@<br>
---=============================================================================<br>
--- 32-bit hash tests<br>
---=============================================================================<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash insert fields tests<br>
--------------------------------------------------------------------------------<br>
-hash = box.schema.space.create('tweedledum')<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
-<br>
-bsize = tmp:bsize()<br>
-<br>
--- Insert valid fields<br>
-hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
-tmp:bsize() > bsize<br>
-<br>
--- Insert invalid fields<br>
-hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash replace fields tests<br>
--------------------------------------------------------------------------------<br>
-<br>
--- Replace valid fields<br>
-hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
-hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
-hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
-<br>
--- Replace invalid fields<br>
-hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash select fields test<br>
--------------------------------------------------------------------------------<br>
-<br>
--- select by valid keys<br>
-hash.index['primary']:get{0}<br>
-hash.index['primary']:get{1}<br>
-hash.index['primary']:get{2}<br>
-hash.index['primary']:get{3}<br>
-hash.index['primary']:get{4}<br>
-hash.index['primary']:get{5}<br>
-<br>
--- select by invalid keys<br>
-hash.index['primary']:get{'invalid key'}<br>
-hash.index['primary']:get{1, 2}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- 32-bit hash delete fields test<br>
--------------------------------------------------------------------------------<br>
-<br>
--- delete by valid keys<br>
-hash:delete{0}<br>
-hash:delete{1}<br>
-hash:delete{2}<br>
-hash:delete{3}<br>
-hash:delete{4}<br>
-hash:delete{5}<br>
-<br>
--- delete by invalid keys<br>
-hash:delete{'invalid key'}<br>
-hash:delete{1, 2}<br>
-<br>
-hash:truncate()<br>
-<br>
---=============================================================================<br>
--- 64-bit hash tests<br>
---=============================================================================<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash inset fields tests<br>
--------------------------------------------------------------------------------<br>
-<br>
--- Insert valid fields<br>
-hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--- Insert invalid fields<br>
-hash:insert{100, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{101, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{102, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{103, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash replace fields tests<br>
--------------------------------------------------------------------------------<br>
-<br>
--- Replace valid fields<br>
-hash:replace{3ULL, 'value1 v1.31', 'value2 1.12'}<br>
-hash:replace{1ULL, 'value1 v1.32', 'value2 1.72'}<br>
-hash:replace{2ULL, 'value1 v1.43', 'value2 1.92'}<br>
-<br>
--- Replace invalid fields<br>
-hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
-hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
-hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
-hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash select fields test<br>
--------------------------------------------------------------------------------<br>
-<br>
--- select by valid keys<br>
-hash.index['primary']:get{0ULL}<br>
-hash.index['primary']:get{1ULL}<br>
-hash.index['primary']:get{2ULL}<br>
-hash.index['primary']:get{3ULL}<br>
-hash.index['primary']:get{4ULL}<br>
-hash.index['primary']:get{5ULL}<br>
-<br>
--- select by valid NUM keys<br>
-hash.index['primary']:get{0}<br>
-hash.index['primary']:get{1}<br>
-hash.index['primary']:get{2}<br>
-hash.index['primary']:get{3}<br>
-hash.index['primary']:get{4}<br>
-hash.index['primary']:get{5}<br>
-<br>
--- select by invalid keys<br>
-hash.index['primary']:get{'invalid key'}<br>
-hash.index['primary']:get{'00000001', '00000002'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- 64-bit hash delete fields test<br>
--------------------------------------------------------------------------------<br>
-<br>
--- delete by valid keys<br>
-hash:delete{0ULL}<br>
-hash:delete{1ULL}<br>
-hash:delete{2ULL}<br>
-hash:delete{3ULL}<br>
-hash:delete{4ULL}<br>
-hash:delete{5ULL}<br>
-<br>
-hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--- delete by valid NUM keys<br>
-hash:delete{0}<br>
-hash:delete{1}<br>
-hash:delete{2}<br>
-hash:delete{3}<br>
-hash:delete{4}<br>
-hash:delete{5}<br>
-<br>
--- delete by invalid keys<br>
-hash:delete{'invalid key'}<br>
-hash:delete{'00000001', '00000002'}<br>
-hash:truncate()<br>
-<br>
---=============================================================================<br>
--- String hash tests<br>
---=============================================================================<br>
--------------------------------------------------------------------------------<br>
--- String hash inset fields tests<br>
--------------------------------------------------------------------------------<br>
-hash.index['primary']:drop()<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
-<br>
--- Insert valid fields<br>
-hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
-hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- String hash replace fields tests<br>
--------------------------------------------------------------------------------<br>
-<br>
--- Replace valid fields<br>
-hash:replace{'key 3', 'value1 v1.31', 'value2 1.12'}<br>
-hash:replace{'key 1', 'value1 v1.32', 'value2 1.72'}<br>
-hash:replace{'key 2', 'value1 v1.43', 'value2 1.92'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- String hash select fields test<br>
--------------------------------------------------------------------------------<br>
-<br>
--- select by valid keys<br>
-hash.index['primary']:get{'key 0'}<br>
-hash.index['primary']:get{'key 1'}<br>
-hash.index['primary']:get{'key 2'}<br>
-hash.index['primary']:get{'key 3'}<br>
-hash.index['primary']:get{'key 4'}<br>
-hash.index['primary']:get{'key 5'}<br>
-<br>
--- select by invalid keys<br>
-hash.index['primary']:get{'key 1', 'key 2'}<br>
-<br>
--------------------------------------------------------------------------------<br>
--- String hash delete fields test<br>
--------------------------------------------------------------------------------<br>
-<br>
--- delete by valid keys<br>
-hash:delete{'key 0'}<br>
-hash:delete{'key 1'}<br>
-hash:delete{'key 2'}<br>
-hash:delete{'key 3'}<br>
-hash:delete{'key 4'}<br>
-hash:delete{'key 5'}<br>
-<br>
--- delete by invalid keys<br>
-hash:delete{'key 1', 'key 2'}<br>
-hash:truncate()<br>
-<br>
--------------------------------------------------------------------------------<br>
--- Collation test<br>
--------------------------------------------------------------------------------<br>
-hash.index['primary']:drop()<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {{1, 'string', collation = 'unicode_ci'}}, unique = true})<br>
-tmp = hash:create_index('secondary', { type = 'hash', parts = {{2, 'scalar', collation = 'unicode_ci'}}, unique = true})<br>
-<br>
-hash:insert{'Ёж', 'Hedgehog'}<br>
-hash:insert{'Ёлка', 'Spruce'}<br>
-hash:insert{'Jogurt', 'Йогурт'}<br>
-hash:insert{'Один', 1}<br>
-<br>
-hash.index.primary:get('ёж')<br>
-hash.index.primary:get('елка')<br>
-hash.index.secondary:get('spruce')<br>
-hash.index.secondary:get('йогурт')<br>
-hash.index.secondary:get(1)<br>
-hash.index.secondary:get('иогурт')<br>
-hash.index.secondary:get(2)<br>
-<br>
-------------------------<br>
--- hash::replace tests<br>
-------------------------<br>
-hash.index['secondary']:drop()<br>
-hash.index['primary']:drop()<br>
-tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
-tmp = hash:create_index('field1', { type = 'hash', parts = {2, 'unsigned'}, unique = true })<br>
-tmp = hash:create_index('field2', { type = 'hash', parts = {3, 'unsigned'}, unique = true })<br>
-tmp = hash:create_index('field3', { type = 'hash', parts = {4, 'unsigned'}, unique = true })<br>
-<br>
-hash:insert{0, 0, 0, 0}<br>
-hash:insert{1, 1, 1, 1}<br>
-hash:insert{2, 2, 2, 2}<br>
-<br>
--- OK<br>
-hash:replace{1, 1, 1, 1}<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-hash.index['primary']:get{1}<br>
-hash.index['field1']:get{1}<br>
-hash.index['field2']:get{1}<br>
-hash.index['field3']:get{1}<br>
-<br>
--- OK<br>
-hash:insert{10, 10, 10, 10}<br>
-hash:delete{10}<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-<br>
--- TupleFound (primary key)<br>
-hash:insert{1, 10, 10, 10}<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-hash.index['primary']:get{1}<br>
-<br>
--- TupleNotFound (primary key)<br>
-hash:replace{10, 10, 10, 10}<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-<br>
--- TupleFound (key --1)<br>
-hash:insert{10, 0, 10, 10}<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-hash.index['field1']:get{0}<br>
-<br>
--- TupleFound (key --1)<br>
--- hash:replace_if_exists(2, 0, 10, 10)<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-hash.index['field1']:get{0}<br>
-<br>
--- TupleFound (key --3)<br>
-hash:insert{10, 10, 10, 0}<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-hash.index['field3']:get{0}<br>
-<br>
--- TupleFound (key --3)<br>
--- hash:replace_if_exists(2, 10, 10, 0)<br>
-hash.index['primary']:get{10}<br>
-hash.index['field1']:get{10}<br>
-hash.index['field2']:get{10}<br>
-hash.index['field3']:get{10}<br>
-hash.index['field3']:get{0}<br>
-<br>
-hash:drop()<br>
-<br>
-hash = box.schema.space.create('tweedledum')<br>
-hi = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
-hash:insert{0}<br>
-hash:insert{16}<br>
-for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end<br>
-hash:drop()<br>
-<br>
--- <br>
--- gh-616 "1-based indexing and 0-based error message<br>
---<br>
-_ = box.schema.create_space('test')<br>
-_ = box.space.test:create_index('i',{parts={1,'string'}})<br>
-box.space.test:insert{1}<br>
-box.space.test:drop()<br>
-<br>
--- gh-1467: invalid iterator type<br>
-space = box.schema.space.create('test')<br>
-index = space:create_index('primary', { type = 'hash' })<br>
-space:select({1}, {iterator = 'BITS_ALL_SET' } )<br>
-space:drop()<br>
-<br>
--- gh-3907: check that integer numbers stored as MP_FLOAT/MP_DOUBLE<br>
--- are hashed as MP_INT/MP_UINT.<br>
-ffi = require('ffi')<br>
-s = box.schema.space.create('test')<br>
-_ = s:create_index('primary', {type = 'hash', parts = {1, 'number'}})<br>
-s:insert{ffi.new('double', 0)}<br>
-s:insert{ffi.new('double', -1)}<br>
-s:insert{ffi.new('double', 9007199254740992)}<br>
-s:insert{ffi.new('double', -9007199254740994)}<br>
-s:get(0LL)<br>
-s:get(-1LL)<br>
-s:get(9007199254740992LL)<br>
-s:get(-9007199254740994LL)<br>
-s:drop()<br>
-<br>
--- Hash index cannot be multikey.<br>
-s = box.schema.space.create('test')<br>
-_ = s:create_index('primary')<br>
-_ = s:create_index('hash', {type = 'hash', parts = {{'[2][*]', 'unsigned'}}})<br>
-s:drop()<br>
-<br>
--- Hash index can not use function.<br>
-s = box.schema.space.create('withdata')<br>
-lua_code = [[function(tuple) return tuple[1] + tuple[2] end]]<br>
-box.schema.func.create('s', {body = lua_code, is_deterministic = true, is_sandboxed = true})<br>
-_ = s:create_index('pk')<br>
-_ = s:create_index('idx', {type = 'hash', func = box.func.s.id, parts = {{1, 'unsigned'}}})<br>
-s:drop()<br>
-box.schema.func.drop('s')<br>
diff --git a/test/box/hash_32bit_delete.result b/test/box/hash_32bit_delete.result<br>
new file mode 100644<br>
index 000000000..b35143b10<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_delete.result<br>
@@ -0,0 +1,70 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash delete fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- delete by valid keys<br>
+hash:delete{0}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{1}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{2}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{3}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{4}<br>
+ | ---<br>
+ | ...<br>
+hash:delete{5}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- delete by invalid keys<br>
+hash:delete{'invalid key'}<br>
+ | ---<br>
+ | - error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
+ | ...<br>
+hash:delete{1, 2}<br>
+ | ---<br>
+ | - error: Invalid key part count in an exact match (expected 1, got 2)<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_32bit_delete.test.lua b/test/box/hash_32bit_delete.test.lua<br>
new file mode 100644<br>
index 000000000..682e0bc96<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_delete.test.lua<br>
@@ -0,0 +1,29 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash delete fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- delete by valid keys<br>
+hash:delete{0}<br>
+hash:delete{1}<br>
+hash:delete{2}<br>
+hash:delete{3}<br>
+hash:delete{4}<br>
+hash:delete{5}<br>
+<br>
+-- delete by invalid keys<br>
+hash:delete{'invalid key'}<br>
+hash:delete{1, 2}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_32bit_insert.result b/test/box/hash_32bit_insert.result<br>
new file mode 100644<br>
index 000000000..72c7c4842<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_insert.result<br>
@@ -0,0 +1,38 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-- Insert invalid fields<br>
+hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_32bit_insert.test.lua b/test/box/hash_32bit_insert.test.lua<br>
new file mode 100644<br>
index 000000000..308b27d3e<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_insert.test.lua<br>
@@ -0,0 +1,16 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-- Insert invalid fields<br>
+hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_32bit_replace.result b/test/box/hash_32bit_replace.result<br>
new file mode 100644<br>
index 000000000..a1feba851<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_replace.result<br>
@@ -0,0 +1,56 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash replace fields tests<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- Replace valid fields<br>
+hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.31', 'value2 1.12']<br>
+ | ...<br>
+hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.32', 'value2 1.72']<br>
+ | ...<br>
+hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.43', 'value2 1.92']<br>
+ | ...<br>
+<br>
+-- Replace invalid fields<br>
+hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_32bit_replace.test.lua b/test/box/hash_32bit_replace.test.lua<br>
new file mode 100644<br>
index 000000000..a00b02185<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_replace.test.lua<br>
@@ -0,0 +1,25 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash replace fields tests<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- Replace valid fields<br>
+hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
+hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
+hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
+<br>
+-- Replace invalid fields<br>
+hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_32bit_select.result b/test/box/hash_32bit_select.result<br>
new file mode 100644<br>
index 000000000..f80df9bbd<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_select.result<br>
@@ -0,0 +1,70 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash select fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- select by valid keys<br>
+hash.index['primary']:get{0}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{1}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{2}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{3}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{4}<br>
+ | ---<br>
+ | ...<br>
+hash.index['primary']:get{5}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- select by invalid keys<br>
+hash.index['primary']:get{'invalid key'}<br>
+ | ---<br>
+ | - error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
+ | ...<br>
+hash.index['primary']:get{1, 2}<br>
+ | ---<br>
+ | - error: Invalid key part count in an exact match (expected 1, got 2)<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_32bit_select.test.lua b/test/box/hash_32bit_select.test.lua<br>
new file mode 100644<br>
index 000000000..e077cc48d<br>
--- /dev/null<br>
+++ b/test/box/hash_32bit_select.test.lua<br>
@@ -0,0 +1,29 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 32-bit hash select fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- select by valid keys<br>
+hash.index['primary']:get{0}<br>
+hash.index['primary']:get{1}<br>
+hash.index['primary']:get{2}<br>
+hash.index['primary']:get{3}<br>
+hash.index['primary']:get{4}<br>
+hash.index['primary']:get{5}<br>
+<br>
+-- select by invalid keys<br>
+hash.index['primary']:get{'invalid key'}<br>
+hash.index['primary']:get{1, 2}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_64bit_delete.result b/test/box/hash_64bit_delete.result<br>
new file mode 100644<br>
index 000000000..88079e6f2<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_delete.result<br>
@@ -0,0 +1,111 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash delete fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- delete by valid keys<br>
+hash:delete{0ULL}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{1ULL}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{2ULL}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{3ULL}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{4ULL}<br>
+ | ---<br>
+ | ...<br>
+hash:delete{5ULL}<br>
+ | ---<br>
+ | ...<br>
+<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-- delete by valid NUM keys<br>
+hash:delete{0}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{1}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{2}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{3}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{4}<br>
+ | ---<br>
+ | ...<br>
+hash:delete{5}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- delete by invalid keys<br>
+hash:delete{'invalid key'}<br>
+ | ---<br>
+ | - error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
+ | ...<br>
+hash:delete{'00000001', '00000002'}<br>
+ | ---<br>
+ | - error: Invalid key part count in an exact match (expected 1, got 2)<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_64bit_delete.test.lua b/test/box/hash_64bit_delete.test.lua<br>
new file mode 100644<br>
index 000000000..75675381f<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_delete.test.lua<br>
@@ -0,0 +1,42 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash delete fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- delete by valid keys<br>
+hash:delete{0ULL}<br>
+hash:delete{1ULL}<br>
+hash:delete{2ULL}<br>
+hash:delete{3ULL}<br>
+hash:delete{4ULL}<br>
+hash:delete{5ULL}<br>
+<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-- delete by valid NUM keys<br>
+hash:delete{0}<br>
+hash:delete{1}<br>
+hash:delete{2}<br>
+hash:delete{3}<br>
+hash:delete{4}<br>
+hash:delete{5}<br>
+<br>
+-- delete by invalid keys<br>
+hash:delete{'invalid key'}<br>
+hash:delete{'00000001', '00000002'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_64bit_insert.result b/test/box/hash_64bit_insert.result<br>
new file mode 100644<br>
index 000000000..3f1275576<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_insert.result<br>
@@ -0,0 +1,54 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-- Insert invalid fields<br>
+hash:insert{100, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [100, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{101, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [101, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{102, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [102, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{103, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [103, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_64bit_insert.test.lua b/test/box/hash_64bit_insert.test.lua<br>
new file mode 100644<br>
index 000000000..c69214b4e<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_insert.test.lua<br>
@@ -0,0 +1,20 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-- Insert invalid fields<br>
+hash:insert{100, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{101, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{102, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{103, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_64bit_replace.result b/test/box/hash_64bit_replace.result<br>
new file mode 100644<br>
index 000000000..0bf900818<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_replace.result<br>
@@ -0,0 +1,68 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash replace fields tests<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- Replace valid fields<br>
+hash:replace{3ULL, 'value1 v1.31', 'value2 1.12'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.31', 'value2 1.12']<br>
+ | ...<br>
+hash:replace{1ULL, 'value1 v1.32', 'value2 1.72'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.32', 'value2 1.72']<br>
+ | ...<br>
+hash:replace{2ULL, 'value1 v1.43', 'value2 1.92'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.43', 'value2 1.92']<br>
+ | ...<br>
+<br>
+-- Replace invalid fields<br>
+hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.31', 'value2 1.12']<br>
+ | ...<br>
+hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.32', 'value2 1.72']<br>
+ | ...<br>
+hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.43', 'value2 1.92']<br>
+ | ...<br>
+hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - error: 'Tuple field 1 type does not match one required by operation: expected unsigned'<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_64bit_replace.test.lua b/test/box/hash_64bit_replace.test.lua<br>
new file mode 100644<br>
index 000000000..4213110bc<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_replace.test.lua<br>
@@ -0,0 +1,28 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash replace fields tests<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- Replace valid fields<br>
+hash:replace{3ULL, 'value1 v1.31', 'value2 1.12'}<br>
+hash:replace{1ULL, 'value1 v1.32', 'value2 1.72'}<br>
+hash:replace{2ULL, 'value1 v1.43', 'value2 1.92'}<br>
+<br>
+-- Replace invalid fields<br>
+hash:replace{3, 'value1 v1.31', 'value2 1.12'}<br>
+hash:replace{1, 'value1 v1.32', 'value2 1.72'}<br>
+hash:replace{2, 'value1 v1.43', 'value2 1.92'}<br>
+hash:replace{'invalid key', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_64bit_select.result b/test/box/hash_64bit_select.result<br>
new file mode 100644<br>
index 000000000..74dd56727<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_select.result<br>
@@ -0,0 +1,94 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash select fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- select by valid keys<br>
+hash.index['primary']:get{0ULL}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{1ULL}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{2ULL}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{3ULL}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{4ULL}<br>
+ | ---<br>
+ | ...<br>
+hash.index['primary']:get{5ULL}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- select by valid NUM keys<br>
+hash.index['primary']:get{0}<br>
+ | ---<br>
+ | - [0, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{1}<br>
+ | ---<br>
+ | - [1, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{2}<br>
+ | ---<br>
+ | - [2, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{3}<br>
+ | ---<br>
+ | - [3, 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{4}<br>
+ | ---<br>
+ | ...<br>
+hash.index['primary']:get{5}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- select by invalid keys<br>
+hash.index['primary']:get{'invalid key'}<br>
+ | ---<br>
+ | - error: 'Supplied key type of part 0 does not match index part type: expected unsigned'<br>
+ | ...<br>
+hash.index['primary']:get{'00000001', '00000002'}<br>
+ | ---<br>
+ | - error: Invalid key part count in an exact match (expected 1, got 2)<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_64bit_select.test.lua b/test/box/hash_64bit_select.test.lua<br>
new file mode 100644<br>
index 000000000..724fb24be<br>
--- /dev/null<br>
+++ b/test/box/hash_64bit_select.test.lua<br>
@@ -0,0 +1,37 @@<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash insert fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{0ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{1ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{2ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{3ULL, 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- 64-bit hash select fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- select by valid keys<br>
+hash.index['primary']:get{0ULL}<br>
+hash.index['primary']:get{1ULL}<br>
+hash.index['primary']:get{2ULL}<br>
+hash.index['primary']:get{3ULL}<br>
+hash.index['primary']:get{4ULL}<br>
+hash.index['primary']:get{5ULL}<br>
+<br>
+-- select by valid NUM keys<br>
+hash.index['primary']:get{0}<br>
+hash.index['primary']:get{1}<br>
+hash.index['primary']:get{2}<br>
+hash.index['primary']:get{3}<br>
+hash.index['primary']:get{4}<br>
+hash.index['primary']:get{5}<br>
+<br>
+-- select by invalid keys<br>
+hash.index['primary']:get{'invalid key'}<br>
+hash.index['primary']:get{'00000001', '00000002'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_collation.result b/test/box/hash_collation.result<br>
new file mode 100644<br>
index 000000000..ea80b577d<br>
--- /dev/null<br>
+++ b/test/box/hash_collation.result<br>
@@ -0,0 +1,62 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- Collation test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {{1, 'string', collation = 'unicode_ci'}}, unique = true})<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('secondary', { type = 'hash', parts = {{2, 'scalar', collation = 'unicode_ci'}}, unique = true})<br>
+ | ---<br>
+ | ...<br>
+<br>
+hash:insert{'Ёж', 'Hedgehog'}<br>
+ | ---<br>
+ | - ['Ёж', 'Hedgehog']<br>
+ | ...<br>
+hash:insert{'Ёлка', 'Spruce'}<br>
+ | ---<br>
+ | - ['Ёлка', 'Spruce']<br>
+ | ...<br>
+hash:insert{'Jogurt', 'Йогурт'}<br>
+ | ---<br>
+ | - ['Jogurt', 'Йогурт']<br>
+ | ...<br>
+hash:insert{'Один', 1}<br>
+ | ---<br>
+ | - ['Один', 1]<br>
+ | ...<br>
+<br>
+hash.index.primary:get('ёж')<br>
+ | ---<br>
+ | - ['Ёж', 'Hedgehog']<br>
+ | ...<br>
+hash.index.primary:get('елка')<br>
+ | ---<br>
+ | - ['Ёлка', 'Spruce']<br>
+ | ...<br>
+hash.index.secondary:get('spruce')<br>
+ | ---<br>
+ | - ['Ёлка', 'Spruce']<br>
+ | ...<br>
+hash.index.secondary:get('йогурт')<br>
+ | ---<br>
+ | - ['Jogurt', 'Йогурт']<br>
+ | ...<br>
+hash.index.secondary:get(1)<br>
+ | ---<br>
+ | - ['Один', 1]<br>
+ | ...<br>
+hash.index.secondary:get('иогурт')<br>
+ | ---<br>
+ | ...<br>
+hash.index.secondary:get(2)<br>
+ | ---<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_collation.test.lua b/test/box/hash_collation.test.lua<br>
new file mode 100644<br>
index 000000000..f9bca79f6<br>
--- /dev/null<br>
+++ b/test/box/hash_collation.test.lua<br>
@@ -0,0 +1,22 @@<br>
+-------------------------------------------------------------------------------<br>
+-- Collation test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {{1, 'string', collation = 'unicode_ci'}}, unique = true})<br>
+tmp = hash:create_index('secondary', { type = 'hash', parts = {{2, 'scalar', collation = 'unicode_ci'}}, unique = true})<br>
+<br>
+hash:insert{'Ёж', 'Hedgehog'}<br>
+hash:insert{'Ёлка', 'Spruce'}<br>
+hash:insert{'Jogurt', 'Йогурт'}<br>
+hash:insert{'Один', 1}<br>
+<br>
+hash.index.primary:get('ёж')<br>
+hash.index.primary:get('елка')<br>
+hash.index.secondary:get('spruce')<br>
+hash.index.secondary:get('йогурт')<br>
+hash.index.secondary:get(1)<br>
+hash.index.secondary:get('иогурт')<br>
+hash.index.secondary:get(2)<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_gh-1467.result b/test/box/hash_gh-1467.result<br>
new file mode 100644<br>
index 000000000..a2c736a11<br>
--- /dev/null<br>
+++ b/test/box/hash_gh-1467.result<br>
@@ -0,0 +1,17 @@<br>
+-- test-run result file version 2<br>
+-- gh-1467: invalid iterator type<br>
+<br>
+space = box.schema.space.create('test')<br>
+ | ---<br>
+ | ...<br>
+index = space:create_index('primary', { type = 'hash' })<br>
+ | ---<br>
+ | ...<br>
+space:select({1}, {iterator = 'BITS_ALL_SET' } )<br>
+ | ---<br>
+ | - error: Index 'primary' (HASH) of space 'test' (memtx) does not support requested<br>
+ |     iterator type<br>
+ | ...<br>
+space:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_gh-1467.test.lua b/test/box/hash_gh-1467.test.lua<br>
new file mode 100644<br>
index 000000000..d98c31734<br>
--- /dev/null<br>
+++ b/test/box/hash_gh-1467.test.lua<br>
@@ -0,0 +1,6 @@<br>
+-- gh-1467: invalid iterator type<br>
+<br>
+space = box.schema.space.create('test')<br>
+index = space:create_index('primary', { type = 'hash' })<br>
+space:select({1}, {iterator = 'BITS_ALL_SET' } )<br>
+space:drop()<br>
diff --git a/test/box/hash_gh-3907.result b/test/box/hash_gh-3907.result<br>
new file mode 100644<br>
index 000000000..4ce7e40f4<br>
--- /dev/null<br>
+++ b/test/box/hash_gh-3907.result<br>
@@ -0,0 +1,48 @@<br>
+-- test-run result file version 2<br>
+-- gh-3907: check that integer numbers stored as MP_FLOAT/MP_DOUBLE<br>
+-- are hashed as MP_INT/MP_UINT.<br>
+<br>
+ffi = require('ffi')<br>
+ | ---<br>
+ | ...<br>
+s = box.schema.space.create('test')<br>
+ | ---<br>
+ | ...<br>
+_ = s:create_index('primary', {type = 'hash', parts = {1, 'number'}})<br>
+ | ---<br>
+ | ...<br>
+s:insert{ffi.new('double', 0)}<br>
+ | ---<br>
+ | - [0]<br>
+ | ...<br>
+s:insert{ffi.new('double', -1)}<br>
+ | ---<br>
+ | - [-1]<br>
+ | ...<br>
+s:insert{ffi.new('double', 9007199254740992)}<br>
+ | ---<br>
+ | - [9007199254740992]<br>
+ | ...<br>
+s:insert{ffi.new('double', -9007199254740994)}<br>
+ | ---<br>
+ | - [-9007199254740994]<br>
+ | ...<br>
+s:get(0LL)<br>
+ | ---<br>
+ | - [0]<br>
+ | ...<br>
+s:get(-1LL)<br>
+ | ---<br>
+ | - [-1]<br>
+ | ...<br>
+s:get(9007199254740992LL)<br>
+ | ---<br>
+ | - [9007199254740992]<br>
+ | ...<br>
+s:get(-9007199254740994LL)<br>
+ | ---<br>
+ | - [-9007199254740994]<br>
+ | ...<br>
+s:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_gh-3907.test.lua b/test/box/hash_gh-3907.test.lua<br>
new file mode 100644<br>
index 000000000..2bef03b0d<br>
--- /dev/null<br>
+++ b/test/box/hash_gh-3907.test.lua<br>
@@ -0,0 +1,15 @@<br>
+-- gh-3907: check that integer numbers stored as MP_FLOAT/MP_DOUBLE<br>
+-- are hashed as MP_INT/MP_UINT.<br>
+<br>
+ffi = require('ffi')<br>
+s = box.schema.space.create('test')<br>
+_ = s:create_index('primary', {type = 'hash', parts = {1, 'number'}})<br>
+s:insert{ffi.new('double', 0)}<br>
+s:insert{ffi.new('double', -1)}<br>
+s:insert{ffi.new('double', 9007199254740992)}<br>
+s:insert{ffi.new('double', -9007199254740994)}<br>
+s:get(0LL)<br>
+s:get(-1LL)<br>
+s:get(9007199254740992LL)<br>
+s:get(-9007199254740994LL)<br>
+s:drop()<br>
diff --git a/test/box/hash_gh-616.result b/test/box/hash_gh-616.result<br>
new file mode 100644<br>
index 000000000..d5ee1eed9<br>
--- /dev/null<br>
+++ b/test/box/hash_gh-616.result<br>
@@ -0,0 +1,17 @@<br>
+-- test-run result file version 2<br>
+-- <br>
+-- gh-616 "1-based indexing and 0-based error message<br>
+--<br>
+_ = box.schema.create_space('test')<br>
+ | ---<br>
+ | ...<br>
+_ = box.space.test:create_index('i',{parts={1,'string'}})<br>
+ | ---<br>
+ | ...<br>
+box.space.test:insert{1}<br>
+ | ---<br>
+ | - error: 'Tuple field 1 type does not match one required by operation: expected string'<br>
+ | ...<br>
+box.space.test:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_gh-616.test.lua b/test/box/hash_gh-616.test.lua<br>
new file mode 100644<br>
index 000000000..8ea5f725a<br>
--- /dev/null<br>
+++ b/test/box/hash_gh-616.test.lua<br>
@@ -0,0 +1,7 @@<br>
+-- <br>
+-- gh-616 "1-based indexing and 0-based error message<br>
+--<br>
+_ = box.schema.create_space('test')<br>
+_ = box.space.test:create_index('i',{parts={1,'string'}})<br>
+box.space.test:insert{1}<br>
+box.space.test:drop()<br>
diff --git a/test/box/hash_iterate.result b/test/box/hash_iterate.result<br>
new file mode 100644<br>
index 000000000..64660ad6d<br>
--- /dev/null<br>
+++ b/test/box/hash_iterate.result<br>
@@ -0,0 +1,21 @@<br>
+-- test-run result file version 2<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+hi = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+hash:insert{0}<br>
+ | ---<br>
+ | - [0]<br>
+ | ...<br>
+hash:insert{16}<br>
+ | ---<br>
+ | - [16]<br>
+ | ...<br>
+for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end<br>
+ | ---<br>
+ | ...<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_iterate.test.lua b/test/box/hash_iterate.test.lua<br>
new file mode 100644<br>
index 000000000..1ee758a66<br>
--- /dev/null<br>
+++ b/test/box/hash_iterate.test.lua<br>
@@ -0,0 +1,6 @@<br>
+hash = box.schema.space.create('tweedledum')<br>
+hi = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+hash:insert{0}<br>
+hash:insert{16}<br>
+for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end<br>
+hash:drop()<br>
diff --git a/test/box/hash_multipart.result b/test/box/hash_multipart.result<br>
index 3de8ee3be..e94313b62 100644<br>
--- a/test/box/hash_multipart.result<br>
+++ b/test/box/hash_multipart.result<br>
@@ -131,13 +131,6 @@ hash.index['unique']:select{1, 'baz'}<br>
 - error: 'Supplied key type of part 1 does not match index part type: expected unsigned'<br>
 ...<br>
 -- cleanup<br>
-hash:truncate()<br>
----<br>
-...<br>
-hash:len()<br>
----<br>
-- 0<br>
-...<br>
 hash:drop()<br>
 ---<br>
 ...<br>
diff --git a/test/box/hash_multipart.test.lua b/test/box/hash_multipart.test.lua<br>
index 8b40504b1..c0a871bee 100644<br>
--- a/test/box/hash_multipart.test.lua<br>
+++ b/test/box/hash_multipart.test.lua<br>
@@ -53,6 +53,4 @@ hash.index['unique']:get{1}<br>
 hash.index['unique']:select{1, 'baz'}<br>
 <br>
 -- cleanup<br>
-hash:truncate()<br>
-hash:len()<br>
 hash:drop()<br>
diff --git a/test/box/hash_not_a_multikey.result b/test/box/hash_not_a_multikey.result<br>
new file mode 100644<br>
index 000000000..334aa676d<br>
--- /dev/null<br>
+++ b/test/box/hash_not_a_multikey.result<br>
@@ -0,0 +1,17 @@<br>
+-- test-run result file version 2<br>
+-- Hash index cannot be multikey.<br>
+<br>
+s = box.schema.space.create('test')<br>
+ | ---<br>
+ | ...<br>
+_ = s:create_index('primary')<br>
+ | ---<br>
+ | ...<br>
+_ = s:create_index('hash', {type = 'hash', parts = {{'[2][*]', 'unsigned'}}})<br>
+ | ---<br>
+ | - error: 'Can''t create or modify index ''hash'' in space ''test'': HASH index cannot<br>
+ |     be multikey'<br>
+ | ...<br>
+s:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_not_a_multikey.test.lua b/test/box/hash_not_a_multikey.test.lua<br>
new file mode 100644<br>
index 000000000..bd82dfb83<br>
--- /dev/null<br>
+++ b/test/box/hash_not_a_multikey.test.lua<br>
@@ -0,0 +1,6 @@<br>
+-- Hash index cannot be multikey.<br>
+<br>
+s = box.schema.space.create('test')<br>
+_ = s:create_index('primary')<br>
+_ = s:create_index('hash', {type = 'hash', parts = {{'[2][*]', 'unsigned'}}})<br>
+s:drop()<br>
diff --git a/test/box/hash_replace.result b/test/box/hash_replace.result<br>
new file mode 100644<br>
index 000000000..1b45f7914<br>
--- /dev/null<br>
+++ b/test/box/hash_replace.result<br>
@@ -0,0 +1,256 @@<br>
+-- test-run result file version 2<br>
+------------------------<br>
+-- hash::replace tests<br>
+------------------------<br>
+<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('field1', { type = 'hash', parts = {2, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('field2', { type = 'hash', parts = {3, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('field3', { type = 'hash', parts = {4, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+hash:insert{0, 0, 0, 0}<br>
+ | ---<br>
+ | - [0, 0, 0, 0]<br>
+ | ...<br>
+hash:insert{1, 1, 1, 1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+hash:insert{2, 2, 2, 2}<br>
+ | ---<br>
+ | - [2, 2, 2, 2]<br>
+ | ...<br>
+<br>
+-- OK<br>
+hash:replace{1, 1, 1, 1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['primary']:get{1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+hash.index['field1']:get{1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+hash.index['field2']:get{1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+hash.index['field3']:get{1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+<br>
+-- OK<br>
+hash:insert{10, 10, 10, 10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash:delete{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- TupleFound (primary key)<br>
+hash:insert{1, 10, 10, 10}<br>
+ | ---<br>
+ | - error: Duplicate key exists in unique index 'primary' in space 'tweedledum'<br>
+ | ...<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | ...<br>
+hash.index['primary']:get{1}<br>
+ | ---<br>
+ | - [1, 1, 1, 1]<br>
+ | ...<br>
+<br>
+-- TupleNotFound (primary key)<br>
+hash:replace{10, 10, 10, 10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+<br>
+-- TupleFound (key --1)<br>
+hash:insert{10, 0, 10, 10}<br>
+ | ---<br>
+ | - error: Duplicate key exists in unique index 'primary' in space 'tweedledum'<br>
+ | ...<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{0}<br>
+ | ---<br>
+ | - [0, 0, 0, 0]<br>
+ | ...<br>
+<br>
+-- TupleFound (key --1)<br>
+-- hash:replace_if_exists(2, 0, 10, 10)<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{0}<br>
+ | ---<br>
+ | - [0, 0, 0, 0]<br>
+ | ...<br>
+<br>
+-- TupleFound (key --3)<br>
+hash:insert{10, 10, 10, 0}<br>
+ | ---<br>
+ | - error: Duplicate key exists in unique index 'primary' in space 'tweedledum'<br>
+ | ...<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{0}<br>
+ | ---<br>
+ | - [0, 0, 0, 0]<br>
+ | ...<br>
+<br>
+-- TupleFound (key --3)<br>
+-- hash:replace_if_exists(2, 10, 10, 0)<br>
+hash.index['primary']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field1']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field2']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{10}<br>
+ | ---<br>
+ | - [10, 10, 10, 10]<br>
+ | ...<br>
+hash.index['field3']:get{0}<br>
+ | ---<br>
+ | - [0, 0, 0, 0]<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
+<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+hi = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+hash:insert{0}<br>
+ | ---<br>
+ | - [0]<br>
+ | ...<br>
+hash:insert{16}<br>
+ | ---<br>
+ | - [16]<br>
+ | ...<br>
+for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end<br>
+ | ---<br>
+ | ...<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_replace.test.lua b/test/box/hash_replace.test.lua<br>
new file mode 100644<br>
index 000000000..d876f1f12<br>
--- /dev/null<br>
+++ b/test/box/hash_replace.test.lua<br>
@@ -0,0 +1,88 @@<br>
+------------------------<br>
+-- hash::replace tests<br>
+------------------------<br>
+<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+tmp = hash:create_index('field1', { type = 'hash', parts = {2, 'unsigned'}, unique = true })<br>
+tmp = hash:create_index('field2', { type = 'hash', parts = {3, 'unsigned'}, unique = true })<br>
+tmp = hash:create_index('field3', { type = 'hash', parts = {4, 'unsigned'}, unique = true })<br>
+<br>
+hash:insert{0, 0, 0, 0}<br>
+hash:insert{1, 1, 1, 1}<br>
+hash:insert{2, 2, 2, 2}<br>
+<br>
+-- OK<br>
+hash:replace{1, 1, 1, 1}<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+hash.index['primary']:get{1}<br>
+hash.index['field1']:get{1}<br>
+hash.index['field2']:get{1}<br>
+hash.index['field3']:get{1}<br>
+<br>
+-- OK<br>
+hash:insert{10, 10, 10, 10}<br>
+hash:delete{10}<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+<br>
+-- TupleFound (primary key)<br>
+hash:insert{1, 10, 10, 10}<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+hash.index['primary']:get{1}<br>
+<br>
+-- TupleNotFound (primary key)<br>
+hash:replace{10, 10, 10, 10}<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+<br>
+-- TupleFound (key --1)<br>
+hash:insert{10, 0, 10, 10}<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+hash.index['field1']:get{0}<br>
+<br>
+-- TupleFound (key --1)<br>
+-- hash:replace_if_exists(2, 0, 10, 10)<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+hash.index['field1']:get{0}<br>
+<br>
+-- TupleFound (key --3)<br>
+hash:insert{10, 10, 10, 0}<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+hash.index['field3']:get{0}<br>
+<br>
+-- TupleFound (key --3)<br>
+-- hash:replace_if_exists(2, 10, 10, 0)<br>
+hash.index['primary']:get{10}<br>
+hash.index['field1']:get{10}<br>
+hash.index['field2']:get{10}<br>
+hash.index['field3']:get{10}<br>
+hash.index['field3']:get{0}<br>
+<br>
+hash:drop()<br>
+<br>
+hash = box.schema.space.create('tweedledum')<br>
+hi = hash:create_index('primary', { type = 'hash', parts = {1, 'unsigned'}, unique = true })<br>
+hash:insert{0}<br>
+hash:insert{16}<br>
+for _, tuple in hi:pairs(nil, {iterator = box.index.ALL}) do hash:delete{tuple[1]} end<br>
+hash:drop()<br>
diff --git a/test/box/hash_string_delete.result b/test/box/hash_string_delete.result<br>
new file mode 100644<br>
index 000000000..3458f3c68<br>
--- /dev/null<br>
+++ b/test/box/hash_string_delete.result<br>
@@ -0,0 +1,62 @@<br>
+-- test-run result file version 2<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- String hash delete fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- delete by valid keys<br>
+hash:delete{'key 0'}<br>
+ | ---<br>
+ | - ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{'key 1'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{'key 2'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{'key 3'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:delete{'key 4'}<br>
+ | ---<br>
+ | ...<br>
+hash:delete{'key 5'}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- delete by invalid keys<br>
+hash:delete{'key 1', 'key 2'}<br>
+ | ---<br>
+ | - error: Invalid key part count in an exact match (expected 1, got 2)<br>
+ | ...<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_string_delete.test.lua b/test/box/hash_string_delete.test.lua<br>
new file mode 100644<br>
index 000000000..612217ec9<br>
--- /dev/null<br>
+++ b/test/box/hash_string_delete.test.lua<br>
@@ -0,0 +1,24 @@<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- String hash delete fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- delete by valid keys<br>
+hash:delete{'key 0'}<br>
+hash:delete{'key 1'}<br>
+hash:delete{'key 2'}<br>
+hash:delete{'key 3'}<br>
+hash:delete{'key 4'}<br>
+hash:delete{'key 5'}<br>
+<br>
+-- delete by invalid keys<br>
+hash:delete{'key 1', 'key 2'}<br>
+hash:drop()<br>
diff --git a/test/box/hash_string_insert.result b/test/box/hash_string_insert.result<br>
new file mode 100644<br>
index 000000000..50a52b6a8<br>
--- /dev/null<br>
+++ b/test/box/hash_string_insert.result<br>
@@ -0,0 +1,32 @@<br>
+-- test-run result file version 2<br>
+-------------------------------------------------------------------------------<br>
+-- String hash inset fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_string_insert.test.lua b/test/box/hash_string_insert.test.lua<br>
new file mode 100644<br>
index 000000000..9788abc0d<br>
--- /dev/null<br>
+++ b/test/box/hash_string_insert.test.lua<br>
@@ -0,0 +1,13 @@<br>
+-------------------------------------------------------------------------------<br>
+-- String hash inset fields tests<br>
+-------------------------------------------------------------------------------<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_string_replace.result b/test/box/hash_string_replace.result<br>
new file mode 100644<br>
index 000000000..1fb525d71<br>
--- /dev/null<br>
+++ b/test/box/hash_string_replace.result<br>
@@ -0,0 +1,47 @@<br>
+-- test-run result file version 2<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- String hash replace fields tests<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- Replace valid fields<br>
+hash:replace{'key 3', 'value1 v1.31', 'value2 1.12'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.31', 'value2 1.12']<br>
+ | ...<br>
+hash:replace{'key 1', 'value1 v1.32', 'value2 1.72'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.32', 'value2 1.72']<br>
+ | ...<br>
+hash:replace{'key 2', 'value1 v1.43', 'value2 1.92'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.43', 'value2 1.92']<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_string_replace.test.lua b/test/box/hash_string_replace.test.lua<br>
new file mode 100644<br>
index 000000000..db5cfa93e<br>
--- /dev/null<br>
+++ b/test/box/hash_string_replace.test.lua<br>
@@ -0,0 +1,19 @@<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- String hash replace fields tests<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- Replace valid fields<br>
+hash:replace{'key 3', 'value1 v1.31', 'value2 1.12'}<br>
+hash:replace{'key 1', 'value1 v1.32', 'value2 1.72'}<br>
+hash:replace{'key 2', 'value1 v1.43', 'value2 1.92'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_string_select.result b/test/box/hash_string_select.result<br>
new file mode 100644<br>
index 000000000..16cb22d3c<br>
--- /dev/null<br>
+++ b/test/box/hash_string_select.result<br>
@@ -0,0 +1,63 @@<br>
+-- test-run result file version 2<br>
+hash = box.schema.space.create('tweedledum')<br>
+ | ---<br>
+ | ...<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- String hash select fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- select by valid keys<br>
+hash.index['primary']:get{'key 0'}<br>
+ | ---<br>
+ | - ['key 0', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{'key 1'}<br>
+ | ---<br>
+ | - ['key 1', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{'key 2'}<br>
+ | ---<br>
+ | - ['key 2', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{'key 3'}<br>
+ | ---<br>
+ | - ['key 3', 'value1 v1.0', 'value2 v1.0']<br>
+ | ...<br>
+hash.index['primary']:get{'key 4'}<br>
+ | ---<br>
+ | ...<br>
+hash.index['primary']:get{'key 5'}<br>
+ | ---<br>
+ | ...<br>
+<br>
+-- select by invalid keys<br>
+hash.index['primary']:get{'key 1', 'key 2'}<br>
+ | ---<br>
+ | - error: Invalid key part count in an exact match (expected 1, got 2)<br>
+ | ...<br>
+<br>
+hash:drop()<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_string_select.test.lua b/test/box/hash_string_select.test.lua<br>
new file mode 100644<br>
index 000000000..ef3f10018<br>
--- /dev/null<br>
+++ b/test/box/hash_string_select.test.lua<br>
@@ -0,0 +1,25 @@<br>
+hash = box.schema.space.create('tweedledum')<br>
+tmp = hash:create_index('primary', { type = 'hash', parts = {1, 'string'}, unique = true })<br>
+<br>
+-- Insert valid fields<br>
+hash:insert{'key 0', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 1', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 2', 'value1 v1.0', 'value2 v1.0'}<br>
+hash:insert{'key 3', 'value1 v1.0', 'value2 v1.0'}<br>
+<br>
+-------------------------------------------------------------------------------<br>
+-- String hash select fields test<br>
+-------------------------------------------------------------------------------<br>
+<br>
+-- select by valid keys<br>
+hash.index['primary']:get{'key 0'}<br>
+hash.index['primary']:get{'key 1'}<br>
+hash.index['primary']:get{'key 2'}<br>
+hash.index['primary']:get{'key 3'}<br>
+hash.index['primary']:get{'key 4'}<br>
+hash.index['primary']:get{'key 5'}<br>
+<br>
+-- select by invalid keys<br>
+hash.index['primary']:get{'key 1', 'key 2'}<br>
+<br>
+hash:drop()<br>
diff --git a/test/box/hash_with_function.result b/test/box/hash_with_function.result<br>
new file mode 100644<br>
index 000000000..cac268281<br>
--- /dev/null<br>
+++ b/test/box/hash_with_function.result<br>
@@ -0,0 +1,26 @@<br>
+-- test-run result file version 2<br>
+-- Hash index can not use function.<br>
+<br>
+s = box.schema.space.create('withdata')<br>
+ | ---<br>
+ | ...<br>
+lua_code = [[function(tuple) return tuple[1] + tuple[2] end]]<br>
+ | ---<br>
+ | ...<br>
+box.schema.func.create('s', {body = lua_code, is_deterministic = true, is_sandboxed = true})<br>
+ | ---<br>
+ | ...<br>
+_ = s:create_index('pk')<br>
+ | ---<br>
+ | ...<br>
+_ = s:create_index('idx', {type = 'hash', func = box.func.s.id, parts = {{1, 'unsigned'}}})<br>
+ | ---<br>
+ | - error: 'Can''t create or modify index ''idx'' in space ''withdata'': HASH index<br>
+ |     can not use a function'<br>
+ | ...<br>
+s:drop()<br>
+ | ---<br>
+ | ...<br>
+box.schema.func.drop('s')<br>
+ | ---<br>
+ | ...<br>
diff --git a/test/box/hash_with_function.test.lua b/test/box/hash_with_function.test.lua<br>
new file mode 100644<br>
index 000000000..9653de68e<br>
--- /dev/null<br>
+++ b/test/box/hash_with_function.test.lua<br>
@@ -0,0 +1,9 @@<br>
+-- Hash index can not use function.<br>
+<br>
+s = box.schema.space.create('withdata')<br>
+lua_code = [[function(tuple) return tuple[1] + tuple[2] end]]<br>
+box.schema.func.create('s', {body = lua_code, is_deterministic = true, is_sandboxed = true})<br>
+_ = s:create_index('pk')<br>
+_ = s:create_index('idx', {type = 'hash', func = box.func.s.id, parts = {{1, 'unsigned'}}})<br>
+s:drop()<br>
+box.schema.func.drop('s')<br>
-- <br>
2.23.0<br>
<br>
<br>
-- <br>
sergeyb@<br>
</div>
            
        
                <base target="_self" href="https://e.mail.ru/">
        </div>

        
</div></blockquote></div></div></BODY></HTML>