1#include "duckdb/main/config.hpp"
2#include "duckdb/function/compression_function.hpp"
3#include "duckdb/function/compression/compression.hpp"
4#include "duckdb/common/pair.hpp"
5
6namespace duckdb {
7
8typedef CompressionFunction (*get_compression_function_t)(PhysicalType type);
9typedef bool (*compression_supports_type_t)(PhysicalType type);
10
11struct DefaultCompressionMethod {
12 CompressionType type;
13 get_compression_function_t get_function;
14 compression_supports_type_t supports_type;
15};
16
17static DefaultCompressionMethod internal_compression_methods[] = {
18 {.type: CompressionType::COMPRESSION_CONSTANT, .get_function: ConstantFun::GetFunction, .supports_type: ConstantFun::TypeIsSupported},
19 {.type: CompressionType::COMPRESSION_UNCOMPRESSED, .get_function: UncompressedFun::GetFunction, .supports_type: UncompressedFun::TypeIsSupported},
20 {.type: CompressionType::COMPRESSION_RLE, .get_function: RLEFun::GetFunction, .supports_type: RLEFun::TypeIsSupported},
21 {.type: CompressionType::COMPRESSION_BITPACKING, .get_function: BitpackingFun::GetFunction, .supports_type: BitpackingFun::TypeIsSupported},
22 {.type: CompressionType::COMPRESSION_DICTIONARY, .get_function: DictionaryCompressionFun::GetFunction,
23 .supports_type: DictionaryCompressionFun::TypeIsSupported},
24 {.type: CompressionType::COMPRESSION_CHIMP, .get_function: ChimpCompressionFun::GetFunction, .supports_type: ChimpCompressionFun::TypeIsSupported},
25 {.type: CompressionType::COMPRESSION_PATAS, .get_function: PatasCompressionFun::GetFunction, .supports_type: PatasCompressionFun::TypeIsSupported},
26 {.type: CompressionType::COMPRESSION_FSST, .get_function: FSSTFun::GetFunction, .supports_type: FSSTFun::TypeIsSupported},
27 {.type: CompressionType::COMPRESSION_AUTO, .get_function: nullptr, .supports_type: nullptr}};
28
29static optional_ptr<CompressionFunction> FindCompressionFunction(CompressionFunctionSet &set, CompressionType type,
30 PhysicalType data_type) {
31 auto &functions = set.functions;
32 auto comp_entry = functions.find(x: type);
33 if (comp_entry != functions.end()) {
34 auto &type_functions = comp_entry->second;
35 auto type_entry = type_functions.find(x: data_type);
36 if (type_entry != type_functions.end()) {
37 return &type_entry->second;
38 }
39 }
40 return nullptr;
41}
42
43static optional_ptr<CompressionFunction> LoadCompressionFunction(CompressionFunctionSet &set, CompressionType type,
44 PhysicalType data_type) {
45 for (idx_t index = 0; internal_compression_methods[index].get_function; index++) {
46 const auto &method = internal_compression_methods[index];
47 if (method.type == type) {
48 // found the correct compression type
49 if (!method.supports_type(data_type)) {
50 // but it does not support this data type: bail out
51 return nullptr;
52 }
53 // the type is supported: create the function and insert it into the set
54 auto function = method.get_function(data_type);
55 set.functions[type].insert(x: make_pair(x&: data_type, y&: function));
56 return FindCompressionFunction(set, type, data_type);
57 }
58 }
59 throw InternalException("Unsupported compression function type");
60}
61
62static void TryLoadCompression(DBConfig &config, vector<reference<CompressionFunction>> &result, CompressionType type,
63 PhysicalType data_type) {
64 auto function = config.GetCompressionFunction(type, data_type);
65 if (!function) {
66 return;
67 }
68 result.push_back(x: *function);
69}
70
71vector<reference<CompressionFunction>> DBConfig::GetCompressionFunctions(PhysicalType data_type) {
72 vector<reference<CompressionFunction>> result;
73 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_UNCOMPRESSED, data_type);
74 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_RLE, data_type);
75 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_BITPACKING, data_type);
76 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_DICTIONARY, data_type);
77 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_CHIMP, data_type);
78 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_PATAS, data_type);
79 TryLoadCompression(config&: *this, result, type: CompressionType::COMPRESSION_FSST, data_type);
80 return result;
81}
82
83optional_ptr<CompressionFunction> DBConfig::GetCompressionFunction(CompressionType type, PhysicalType data_type) {
84 lock_guard<mutex> l(compression_functions->lock);
85 // check if the function is already loaded
86 auto function = FindCompressionFunction(set&: *compression_functions, type, data_type);
87 if (function) {
88 return function;
89 }
90 // else load the function
91 return LoadCompressionFunction(set&: *compression_functions, type, data_type);
92}
93
94} // namespace duckdb
95