ClickHouse
105 строк · 3.1 Кб
1#include <DataTypes/DataTypeString.h>
2#include <DataTypes/DataTypesNumber.h>
3#include <Columns/ColumnString.h>
4#include <Columns/ColumnsNumber.h>
5#include <Functions/FunctionFactory.h>
6#include <Parsers/queryNormalization.h>
7
8
9/** The function returns 64bit hash value that is identical for similar queries.
10* See also 'normalizeQuery'. This function is only slightly more efficient.
11*/
12
13namespace DB
14{
15namespace ErrorCodes
16{
17extern const int ILLEGAL_COLUMN;
18extern const int ILLEGAL_TYPE_OF_ARGUMENT;
19}
20
21namespace
22{
23
24template <bool keep_names>
25struct Impl
26{
27static void vector(
28const ColumnString::Chars & data,
29const ColumnString::Offsets & offsets,
30PaddedPODArray<UInt64> & res_data)
31{
32size_t size = offsets.size();
33res_data.resize(size);
34
35ColumnString::Offset prev_src_offset = 0;
36for (size_t i = 0; i < size; ++i)
37{
38ColumnString::Offset curr_src_offset = offsets[i];
39res_data[i] = normalizedQueryHash(
40reinterpret_cast<const char *>(&data[prev_src_offset]),
41reinterpret_cast<const char *>(&data[curr_src_offset - 1]),
42keep_names);
43prev_src_offset = offsets[i];
44}
45}
46};
47
48template <bool keep_names>
49class FunctionNormalizedQueryHash : public IFunction
50{
51public:
52static constexpr auto name = keep_names ? "normalizedQueryHashKeepNames" : "normalizedQueryHash";
53static FunctionPtr create(ContextPtr)
54{
55return std::make_shared<FunctionNormalizedQueryHash>();
56}
57
58String getName() const override
59{
60return name;
61}
62
63size_t getNumberOfArguments() const override
64{
65return 1;
66}
67
68DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
69{
70if (!isString(arguments[0]))
71throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type {} of argument of function {}", arguments[0]->getName(), getName());
72
73return std::make_shared<DataTypeUInt64>();
74}
75
76bool useDefaultImplementationForConstants() const override { return true; }
77
78bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
79
80ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t /*input_rows_count*/) const override
81{
82const ColumnPtr column = arguments[0].column;
83if (const ColumnString * col = checkAndGetColumn<ColumnString>(column.get()))
84{
85auto col_res = ColumnUInt64::create();
86typename ColumnUInt64::Container & vec_res = col_res->getData();
87vec_res.resize(col->size());
88Impl<keep_names>::vector(col->getChars(), col->getOffsets(), vec_res);
89return col_res;
90}
91else
92throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of argument of function {}",
93arguments[0].column->getName(), getName());
94}
95};
96
97}
98
99REGISTER_FUNCTION(NormalizedQueryHash)
100{
101factory.registerFunction<FunctionNormalizedQueryHash<true>>();
102factory.registerFunction<FunctionNormalizedQueryHash<false>>();
103}
104
105}
106