mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-13 18:02:24 +00:00
175 lines
5.4 KiB
C++
175 lines
5.4 KiB
C++
#include <Core/Block.h>
|
|
#include <Core/SortDescription.h>
|
|
#include <IO/Operators.h>
|
|
#include <Common/JSONBuilder.h>
|
|
#include <Common/SipHash.h>
|
|
|
|
#if USE_EMBEDDED_COMPILER
|
|
#include <DataTypes/Native.h>
|
|
#include <Interpreters/JIT/compileFunction.h>
|
|
#include <Interpreters/JIT/CompiledExpressionCache.h>
|
|
#endif
|
|
|
|
namespace DB
|
|
{
|
|
|
|
void dumpSortDescription(const SortDescription & description, WriteBuffer & out)
|
|
{
|
|
bool first = true;
|
|
|
|
for (const auto & desc : description)
|
|
{
|
|
if (!first)
|
|
out << ", ";
|
|
first = false;
|
|
|
|
out << desc.column_name;
|
|
|
|
if (desc.direction > 0)
|
|
out << " ASC";
|
|
else
|
|
out << " DESC";
|
|
|
|
if (desc.with_fill)
|
|
out << " WITH FILL";
|
|
}
|
|
}
|
|
|
|
void SortColumnDescription::explain(JSONBuilder::JSONMap & map) const
|
|
{
|
|
map.add("Column", column_name);
|
|
map.add("Ascending", direction > 0);
|
|
map.add("With Fill", with_fill);
|
|
}
|
|
|
|
#if USE_EMBEDDED_COMPILER
|
|
|
|
static CHJIT & getJITInstance()
|
|
{
|
|
static CHJIT jit;
|
|
return jit;
|
|
}
|
|
|
|
class CompiledSortDescriptionFunctionHolder final : public CompiledExpressionCacheEntry
|
|
{
|
|
public:
|
|
explicit CompiledSortDescriptionFunctionHolder(CompiledSortDescriptionFunction compiled_function_)
|
|
: CompiledExpressionCacheEntry(compiled_function_.compiled_module.size)
|
|
, compiled_sort_description_function(compiled_function_)
|
|
{}
|
|
|
|
~CompiledSortDescriptionFunctionHolder() override
|
|
{
|
|
getJITInstance().deleteCompiledModule(compiled_sort_description_function.compiled_module);
|
|
}
|
|
|
|
CompiledSortDescriptionFunction compiled_sort_description_function;
|
|
};
|
|
|
|
static std::string getSortDescriptionDump(const SortDescription & description, const DataTypes & header_types)
|
|
{
|
|
WriteBufferFromOwnString buffer;
|
|
|
|
for (size_t i = 0; i < description.size(); ++i)
|
|
buffer << header_types[i]->getName() << ' ' << description[i].direction << ' ' << description[i].nulls_direction;
|
|
|
|
return buffer.str();
|
|
}
|
|
|
|
static Poco::Logger * getLogger()
|
|
{
|
|
static Poco::Logger & logger = Poco::Logger::get("SortDescription");
|
|
return &logger;
|
|
}
|
|
|
|
void compileSortDescriptionIfNeeded(SortDescription & description, const DataTypes & sort_description_types, bool increase_compile_attempts)
|
|
{
|
|
static std::unordered_map<UInt128, UInt64, UInt128Hash> counter;
|
|
static std::mutex mutex;
|
|
|
|
if (!description.compile_sort_description || sort_description_types.empty())
|
|
return;
|
|
|
|
for (const auto & type : sort_description_types)
|
|
{
|
|
if (!type->createColumn()->isComparatorCompilable() || !canBeNativeType(*type))
|
|
return;
|
|
}
|
|
|
|
auto description_dump = getSortDescriptionDump(description, sort_description_types);
|
|
|
|
SipHash sort_description_dump_hash;
|
|
sort_description_dump_hash.update(description_dump);
|
|
|
|
UInt128 sort_description_hash_key;
|
|
sort_description_dump_hash.get128(sort_description_hash_key);
|
|
|
|
{
|
|
std::lock_guard lock(mutex);
|
|
UInt64 & current_counter = counter[sort_description_hash_key];
|
|
if (current_counter < description.min_count_to_compile_sort_description)
|
|
{
|
|
current_counter += static_cast<UInt64>(increase_compile_attempts);
|
|
return;
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<CompiledSortDescriptionFunctionHolder> compiled_sort_description_holder;
|
|
|
|
if (auto * compilation_cache = CompiledExpressionCacheFactory::instance().tryGetCache())
|
|
{
|
|
auto [compiled_function_cache_entry, _] = compilation_cache->getOrSet(sort_description_hash_key, [&] ()
|
|
{
|
|
LOG_TRACE(getLogger(), "Compile sort description {}", description_dump);
|
|
|
|
auto compiled_sort_description = compileSortDescription(getJITInstance(), description, sort_description_types, description_dump);
|
|
return std::make_shared<CompiledSortDescriptionFunctionHolder>(std::move(compiled_sort_description));
|
|
});
|
|
|
|
compiled_sort_description_holder = std::static_pointer_cast<CompiledSortDescriptionFunctionHolder>(compiled_function_cache_entry);
|
|
}
|
|
else
|
|
{
|
|
LOG_TRACE(getLogger(), "Compile sort description {}", description_dump);
|
|
auto compiled_sort_description = compileSortDescription(getJITInstance(), description, sort_description_types, description_dump);
|
|
compiled_sort_description_holder = std::make_shared<CompiledSortDescriptionFunctionHolder>(std::move(compiled_sort_description));
|
|
}
|
|
|
|
auto comparator_function = compiled_sort_description_holder->compiled_sort_description_function.comparator_function;
|
|
description.compiled_sort_description = reinterpret_cast<void *>(comparator_function);
|
|
description.compiled_sort_description_holder = std::move(compiled_sort_description_holder);
|
|
}
|
|
|
|
#else
|
|
|
|
void compileSortDescriptionIfNeeded(SortDescription & description, const DataTypes & sort_description_types, bool increase_compile_attempts)
|
|
{
|
|
(void)(description);
|
|
(void)(sort_description_types);
|
|
(void)(increase_compile_attempts);
|
|
}
|
|
|
|
#endif
|
|
|
|
std::string dumpSortDescription(const SortDescription & description)
|
|
{
|
|
WriteBufferFromOwnString wb;
|
|
dumpSortDescription(description, wb);
|
|
return wb.str();
|
|
}
|
|
|
|
JSONBuilder::ItemPtr explainSortDescription(const SortDescription & description)
|
|
{
|
|
auto json_array = std::make_unique<JSONBuilder::JSONArray>();
|
|
for (const auto & descr : description)
|
|
{
|
|
auto json_map = std::make_unique<JSONBuilder::JSONMap>();
|
|
descr.explain(*json_map);
|
|
json_array->add(std::move(json_map));
|
|
}
|
|
|
|
return json_array;
|
|
}
|
|
|
|
}
|