123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- /*
- * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <LibSQL/HashIndex.h>
- #include <LibSQL/Heap.h>
- #include <LibSQL/Meta.h>
- #include <LibSQL/Tuple.h>
- #include <LibSQL/Value.h>
- #include <LibTest/TestCase.h>
- #include <unistd.h>
- constexpr static int keys[] = {
- 39,
- 87,
- 77,
- 42,
- 98,
- 40,
- 53,
- 8,
- 37,
- 12,
- 90,
- 72,
- 73,
- 11,
- 88,
- 22,
- 10,
- 82,
- 25,
- 61,
- 97,
- 18,
- 60,
- 68,
- 21,
- 3,
- 58,
- 29,
- 13,
- 17,
- 89,
- 81,
- 16,
- 64,
- 5,
- 41,
- 36,
- 91,
- 38,
- 24,
- 32,
- 50,
- 34,
- 94,
- 49,
- 47,
- 1,
- 6,
- 44,
- 76,
- };
- constexpr static u32 pointers[] = {
- 92,
- 4,
- 50,
- 47,
- 68,
- 73,
- 24,
- 28,
- 50,
- 93,
- 60,
- 36,
- 92,
- 72,
- 53,
- 26,
- 91,
- 84,
- 25,
- 43,
- 88,
- 12,
- 62,
- 35,
- 96,
- 27,
- 96,
- 27,
- 99,
- 30,
- 21,
- 89,
- 54,
- 60,
- 37,
- 68,
- 35,
- 55,
- 80,
- 2,
- 33,
- 26,
- 93,
- 70,
- 45,
- 44,
- 3,
- 66,
- 75,
- 4,
- };
- NonnullRefPtr<SQL::HashIndex> setup_hash_index(SQL::Serializer&);
- void insert_and_get_to_and_from_hash_index(int);
- void insert_into_and_scan_hash_index(int);
- NonnullRefPtr<SQL::HashIndex> setup_hash_index(SQL::Serializer& serializer)
- {
- NonnullRefPtr<SQL::TupleDescriptor> tuple_descriptor = adopt_ref(*new SQL::TupleDescriptor);
- tuple_descriptor->append({ "schema", "table", "key_value", SQL::SQLType::Integer, SQL::Order::Ascending });
- tuple_descriptor->append({ "schema", "table", "text_value", SQL::SQLType::Text, SQL::Order::Ascending });
- auto directory_pointer = serializer.heap().user_value(0);
- if (!directory_pointer) {
- directory_pointer = serializer.heap().new_record_pointer();
- serializer.heap().set_user_value(0, directory_pointer);
- }
- auto hash_index = SQL::HashIndex::construct(serializer, tuple_descriptor, directory_pointer);
- return hash_index;
- }
- void insert_and_get_to_and_from_hash_index(int num_keys)
- {
- ScopeGuard guard([]() { unlink("/tmp/test.db"); });
- {
- auto heap = SQL::Heap::construct("/tmp/test.db");
- EXPECT(!heap->open().is_error());
- SQL::Serializer serializer(heap);
- auto hash_index = setup_hash_index(serializer);
- for (auto ix = 0; ix < num_keys; ix++) {
- SQL::Key k(hash_index->descriptor());
- k[0] = keys[ix];
- k[1] = String::formatted("The key value is {} and the pointer is {}", keys[ix], pointers[ix]);
- k.set_pointer(pointers[ix]);
- hash_index->insert(k);
- }
- #ifdef LIST_HASH_INDEX
- hash_index->list_hash();
- #endif
- }
- {
- auto heap = SQL::Heap::construct("/tmp/test.db");
- EXPECT(!heap->open().is_error());
- SQL::Serializer serializer(heap);
- auto hash_index = setup_hash_index(serializer);
- for (auto ix = 0; ix < num_keys; ix++) {
- SQL::Key k(hash_index->descriptor());
- k[0] = keys[ix];
- k[1] = String::formatted("The key value is {} and the pointer is {}", keys[ix], pointers[ix]);
- auto pointer_opt = hash_index->get(k);
- VERIFY(pointer_opt.has_value());
- EXPECT_EQ(pointer_opt.value(), pointers[ix]);
- }
- }
- }
- TEST_CASE(hash_index_one_key)
- {
- insert_and_get_to_and_from_hash_index(1);
- }
- TEST_CASE(hash_index_four_keys)
- {
- insert_and_get_to_and_from_hash_index(4);
- }
- TEST_CASE(hash_index_five_keys)
- {
- insert_and_get_to_and_from_hash_index(5);
- }
- TEST_CASE(hash_index_10_keys)
- {
- insert_and_get_to_and_from_hash_index(10);
- }
- TEST_CASE(hash_index_13_keys)
- {
- insert_and_get_to_and_from_hash_index(13);
- }
- TEST_CASE(hash_index_20_keys)
- {
- insert_and_get_to_and_from_hash_index(20);
- }
- TEST_CASE(hash_index_25_keys)
- {
- insert_and_get_to_and_from_hash_index(25);
- }
- TEST_CASE(hash_index_30_keys)
- {
- insert_and_get_to_and_from_hash_index(30);
- }
- TEST_CASE(hash_index_35_keys)
- {
- insert_and_get_to_and_from_hash_index(35);
- }
- TEST_CASE(hash_index_40_keys)
- {
- insert_and_get_to_and_from_hash_index(40);
- }
- TEST_CASE(hash_index_45_keys)
- {
- insert_and_get_to_and_from_hash_index(45);
- }
- TEST_CASE(hash_index_50_keys)
- {
- insert_and_get_to_and_from_hash_index(50);
- }
- void insert_into_and_scan_hash_index(int num_keys)
- {
- ScopeGuard guard([]() { unlink("/tmp/test.db"); });
- {
- auto heap = SQL::Heap::construct("/tmp/test.db");
- EXPECT(!heap->open().is_error());
- SQL::Serializer serializer(heap);
- auto hash_index = setup_hash_index(serializer);
- for (auto ix = 0; ix < num_keys; ix++) {
- SQL::Key k(hash_index->descriptor());
- k[0] = keys[ix];
- k[1] = String::formatted("The key value is {} and the pointer is {}", keys[ix], pointers[ix]);
- k.set_pointer(pointers[ix]);
- hash_index->insert(k);
- }
- #ifdef LIST_HASH_INDEX
- hash_index->list_hash();
- #endif
- }
- {
- auto heap = SQL::Heap::construct("/tmp/test.db");
- EXPECT(!heap->open().is_error());
- SQL::Serializer serializer(heap);
- auto hash_index = setup_hash_index(serializer);
- Vector<bool> found;
- for (auto ix = 0; ix < num_keys; ix++) {
- found.append(false);
- }
- int count = 0;
- for (auto iter = hash_index->begin(); !iter.is_end(); iter++, count++) {
- auto key = (*iter);
- auto key_value = (int)key[0];
- for (auto ix = 0; ix < num_keys; ix++) {
- if (keys[ix] == key_value) {
- EXPECT_EQ(key.pointer(), pointers[ix]);
- if (found[ix])
- FAIL(String::formatted("Key {}, index {} already found previously", key_value, ix));
- found[ix] = true;
- break;
- }
- }
- }
- #ifdef LIST_HASH_INDEX
- hash_index->list_hash();
- #endif
- EXPECT_EQ(count, num_keys);
- for (auto ix = 0; ix < num_keys; ix++) {
- if (!found[ix])
- FAIL(String::formatted("Key {}, index {} not found", keys[ix], ix));
- }
- }
- }
- TEST_CASE(hash_index_scan_one_key)
- {
- insert_into_and_scan_hash_index(1);
- }
- TEST_CASE(hash_index_scan_four_keys)
- {
- insert_into_and_scan_hash_index(4);
- }
- TEST_CASE(hash_index_scan_five_keys)
- {
- insert_into_and_scan_hash_index(5);
- }
- TEST_CASE(hash_index_scan_10_keys)
- {
- insert_into_and_scan_hash_index(10);
- }
- TEST_CASE(hash_index_scan_15_keys)
- {
- insert_into_and_scan_hash_index(15);
- }
- TEST_CASE(hash_index_scan_20_keys)
- {
- insert_into_and_scan_hash_index(20);
- }
- TEST_CASE(hash_index_scan_30_keys)
- {
- insert_into_and_scan_hash_index(30);
- }
- TEST_CASE(hash_index_scan_40_keys)
- {
- insert_into_and_scan_hash_index(40);
- }
- TEST_CASE(hash_index_scan_50_keys)
- {
- insert_into_and_scan_hash_index(50);
- }
|