1 | #include <Functions/FunctionFactory.h> |
2 | #include <Functions/GeoUtils.h> |
3 | #include <Functions/FunctionHelpers.h> |
4 | |
5 | #include <Columns/ColumnString.h> |
6 | #include <Columns/ColumnFixedString.h> |
7 | #include <Columns/ColumnsNumber.h> |
8 | #include <Columns/ColumnTuple.h> |
9 | #include <DataTypes/DataTypeString.h> |
10 | #include <DataTypes/DataTypeTuple.h> |
11 | #include <DataTypes/DataTypesNumber.h> |
12 | |
13 | #include <string> |
14 | |
15 | |
16 | namespace DB |
17 | { |
18 | |
19 | namespace ErrorCodes |
20 | { |
21 | extern const int ILLEGAL_COLUMN; |
22 | } |
23 | |
24 | |
25 | // geohashDecode(string) => (lon float64, lat float64) |
26 | class FunctionGeohashDecode : public IFunction |
27 | { |
28 | public: |
29 | static constexpr auto name = "geohashDecode" ; |
30 | static FunctionPtr create(const Context &) { return std::make_shared<FunctionGeohashDecode>(); } |
31 | |
32 | String getName() const override |
33 | { |
34 | return name; |
35 | } |
36 | |
37 | size_t getNumberOfArguments() const override { return 1; } |
38 | bool useDefaultImplementationForConstants() const override { return true; } |
39 | |
40 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
41 | { |
42 | validateArgumentType(*this, arguments, 0, isStringOrFixedString, "string or fixed string" ); |
43 | |
44 | return std::make_shared<DataTypeTuple>( |
45 | DataTypes{std::make_shared<DataTypeFloat64>(), std::make_shared<DataTypeFloat64>()}, |
46 | Strings{"longitude" , "latitude" }); |
47 | } |
48 | |
49 | template <typename ColumnTypeEncoded> |
50 | bool tryExecute(const IColumn * encoded_column, ColumnPtr & result_column) |
51 | { |
52 | const auto * encoded = checkAndGetColumn<ColumnTypeEncoded>(encoded_column); |
53 | if (!encoded) |
54 | return false; |
55 | |
56 | const size_t count = encoded->size(); |
57 | |
58 | auto latitude = ColumnFloat64::create(count); |
59 | auto longitude = ColumnFloat64::create(count); |
60 | |
61 | ColumnFloat64::Container & lon_data = longitude->getData(); |
62 | ColumnFloat64::Container & lat_data = latitude->getData(); |
63 | |
64 | for (size_t i = 0; i < count; ++i) |
65 | { |
66 | StringRef encoded_string = encoded->getDataAt(i); |
67 | GeoUtils::geohashDecode(encoded_string.data, encoded_string.size, &lon_data[i], &lat_data[i]); |
68 | } |
69 | |
70 | MutableColumns result; |
71 | result.emplace_back(std::move(longitude)); |
72 | result.emplace_back(std::move(latitude)); |
73 | result_column = ColumnTuple::create(std::move(result)); |
74 | |
75 | return true; |
76 | } |
77 | |
78 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override |
79 | { |
80 | const IColumn * encoded = block.getByPosition(arguments[0]).column.get(); |
81 | ColumnPtr & res_column = block.getByPosition(result).column; |
82 | |
83 | if (tryExecute<ColumnString>(encoded, res_column) || |
84 | tryExecute<ColumnFixedString>(encoded, res_column)) |
85 | return; |
86 | |
87 | throw Exception("Unsupported argument type:" + block.getByPosition(arguments[0]).column->getName() |
88 | + " of argument of function " + getName(), |
89 | ErrorCodes::ILLEGAL_COLUMN); |
90 | } |
91 | }; |
92 | |
93 | |
94 | void registerFunctionGeohashDecode(FunctionFactory & factory) |
95 | { |
96 | factory.registerFunction<FunctionGeohashDecode>(); |
97 | } |
98 | |
99 | } |
100 | |