Files
email-tracker/external/duckdb/test/sql/index/test_art_keys.cpp
2025-10-24 19:21:19 -05:00

273 lines
11 KiB
C++

#include "catch.hpp"
#include "duckdb/common/radix.hpp"
#include "duckdb/common/types/string_type.hpp"
#include "duckdb/execution/index/art/art_key.hpp"
#include <cstring>
#include <iostream>
using namespace duckdb;
using namespace std;
static void TestKeyEqual(ARTKey &left, ARTKey &right) {
REQUIRE(left == right);
REQUIRE(left >= right);
REQUIRE(!(left > right));
REQUIRE(right == left);
REQUIRE(right >= left);
REQUIRE(!(right > left));
}
static void TestKeyBigger(ARTKey &big_key, ARTKey &small_key) {
REQUIRE(!(big_key == small_key));
if (!(big_key >= small_key)) {
REQUIRE(0);
}
REQUIRE(big_key > small_key);
REQUIRE(!(small_key == big_key));
REQUIRE(!(small_key >= big_key));
REQUIRE(!(small_key > big_key));
}
static void TestKeys(duckdb::vector<ARTKey> &keys) {
for (idx_t outer = 0; outer < keys.size(); outer++) {
for (idx_t inner = 0; inner < keys.size(); inner++) {
if (inner == outer) {
TestKeyEqual(keys[inner], keys[outer]);
} else if (inner > outer) {
TestKeyBigger(keys[inner], keys[outer]);
} else {
TestKeyBigger(keys[outer], keys[inner]);
}
}
}
}
static ARTKey CreateCompoundKey(ArenaAllocator &arena_allocator, const string &str_val, int32_t int_val) {
auto key_left = ARTKey::CreateARTKey<string_t>(arena_allocator, string_t(str_val.c_str(), str_val.size()));
auto key_right = ARTKey::CreateARTKey<int32_t>(arena_allocator, int_val);
auto data = arena_allocator.Allocate(key_left.len + key_right.len);
memcpy(data, key_left.data, key_left.len);
memcpy(data + key_left.len, key_right.data, key_right.len);
return ARTKey(data, key_left.len + key_right.len);
}
TEST_CASE("Test correct functioning of art keys", "[art]") {
ArenaAllocator arena_allocator(Allocator::DefaultAllocator());
// Test tiny int
duckdb::vector<ARTKey> keys;
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, -127));
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, -55));
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, -1));
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, 55));
keys.push_back(ARTKey::CreateARTKey<int8_t>(arena_allocator, 127));
TestKeys(keys);
keys.clear();
// Test small int
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, -32767));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, -127));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, -55));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, -1));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, 55));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, 127));
keys.push_back(ARTKey::CreateARTKey<int16_t>(arena_allocator, 32767));
TestKeys(keys);
keys.clear();
// Test int
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, -2147483647));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, -8388608));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, -32767));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, -1));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, 32767));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, 8388608));
keys.push_back(ARTKey::CreateARTKey<int32_t>(arena_allocator, 2147483647));
TestKeys(keys);
keys.clear();
// Test big int
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -9223372036854775807));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -72057594037927936));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -281474976710656));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -1099511627776));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -2147483647));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -8388608));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -32767));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, -1));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 32767));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 8388608));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 2147483647));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 1099511627776));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 281474976710656));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 72057594037927936));
keys.push_back(ARTKey::CreateARTKey<int64_t>(arena_allocator, 9223372036854775807));
TestKeys(keys);
keys.clear();
// Test utiny int
keys.push_back(ARTKey::CreateARTKey<uint8_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<uint8_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<uint8_t>(arena_allocator, 55));
keys.push_back(ARTKey::CreateARTKey<uint8_t>(arena_allocator, 127));
keys.push_back(ARTKey::CreateARTKey<uint8_t>(arena_allocator, 200));
keys.push_back(ARTKey::CreateARTKey<uint8_t>(arena_allocator, 250));
TestKeys(keys);
keys.clear();
// Test usmall int
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 55));
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 127));
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 32767));
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 40000));
keys.push_back(ARTKey::CreateARTKey<uint16_t>(arena_allocator, 60000));
TestKeys(keys);
keys.clear();
// Test uint
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 32767));
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 8388608));
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 2147483647));
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 3047483647));
keys.push_back(ARTKey::CreateARTKey<uint32_t>(arena_allocator, 4047483647));
TestKeys(keys);
keys.clear();
// Test ubig int
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 1));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 32767));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 8388608));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 2147483647));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 1099511627776));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 281474976710656));
keys.push_back(ARTKey::CreateARTKey<uint64_t>(arena_allocator, 72057594037927936));
TestKeys(keys);
keys.clear();
// Test strings
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "abc"));
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "babababa"));
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "hello"));
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "hellow"));
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "torororororo"));
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "torororororp"));
keys.push_back(ARTKey::CreateARTKey<const char *>(arena_allocator, "z"));
TestKeys(keys);
keys.clear();
// test compound keys
keys.push_back(CreateCompoundKey(arena_allocator, "abc", -100));
keys.push_back(CreateCompoundKey(arena_allocator, "abc", 1000));
keys.push_back(CreateCompoundKey(arena_allocator, "abcd", -100000));
keys.push_back(CreateCompoundKey(arena_allocator, "hello", -100000));
keys.push_back(CreateCompoundKey(arena_allocator, "hello", -1));
keys.push_back(CreateCompoundKey(arena_allocator, "hello", 0));
keys.push_back(CreateCompoundKey(arena_allocator, "hello", 1));
keys.push_back(CreateCompoundKey(arena_allocator, "hellow", -10000));
keys.push_back(CreateCompoundKey(arena_allocator, "z", 30));
TestKeys(keys);
keys.clear();
keys.push_back(ARTKey::CreateARTKey<double>(arena_allocator, 0));
keys.push_back(ARTKey::CreateARTKey<double>(arena_allocator, 0.1));
keys.push_back(ARTKey::CreateARTKey<double>(arena_allocator, 488566));
keys.push_back(ARTKey::CreateARTKey<double>(arena_allocator, 1163404482));
TestKeys(keys);
keys.clear();
}
TEST_CASE("Test correct functioning of art EncodeFloat/EncodeDouble", "[art-enc]") {
{
// EncodeFloat
// positive values
duckdb::vector<float> values;
float current_value = 0.00001f;
while (isfinite(current_value)) {
values.push_back(current_value);
current_value *= 2;
}
// negative values
current_value = -0.00001f;
while (isfinite(current_value)) {
values.push_back(current_value);
current_value *= 2;
}
std::sort(values.begin(), values.end());
uint32_t current_encoded = Radix::EncodeFloat(values[0]);
for (idx_t i = 1; i < values.size(); i++) {
uint32_t next_encoded = Radix::EncodeFloat(values[i]);
if (next_encoded <= current_encoded) {
printf("Failure in Key::EncodeFloat!\n");
printf(
"Generated value for key %f (=> %u) is bigger or equal to the generated value for key %f (=> %u)\n",
values[i - 1], current_encoded, values[i], next_encoded);
}
REQUIRE(next_encoded > current_encoded);
current_encoded = next_encoded;
}
}
{
// EncodeDouble
// positive values
duckdb::vector<double> values;
double current_value = 0.0000001;
while (isfinite(current_value)) {
values.push_back(current_value);
current_value *= 2;
}
// negative values
current_value = -0.0000001;
while (isfinite(current_value)) {
values.push_back(current_value);
current_value *= 2;
}
std::sort(values.begin(), values.end());
uint64_t current_encoded = Radix::EncodeDouble(values[0]);
for (idx_t i = 1; i < values.size(); i++) {
uint64_t next_encoded = Radix::EncodeDouble(values[i]);
if (next_encoded <= current_encoded) {
cout << "Failure in Key::EncodeDouble!" << std::endl;
cout << "Generated value for key " << values[i - 1] << " (=> %" << current_encoded
<< ") is bigger or equal to the generated value for key " << values[i] << "(=> %" << next_encoded
<< ")" << std::endl;
}
REQUIRE(next_encoded > current_encoded);
current_encoded = next_encoded;
}
}
}