blob: 3ed6f44c9031912f1ff2129563a5257985507a31 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
// This file is copied from
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/FunctionsCodingIP.cpp
// and modified by Doris
#pragma once
#include <glog/logging.h>
#include "vec/columns/column.h"
#include "vec/columns/column_string.h"
#include "vec/columns/column_vector.h"
#include "vec/common/format_ip.h"
#include "vec/core/column_with_type_and_name.h"
#include "vec/data_types/data_type_string.h"
#include "vec/functions/function.h"
#include "vec/functions/simple_function_factory.h"
namespace doris::vectorized {
/** If mask_tail_octets > 0, the last specified number of octets will be filled with "xxx".
*/
template <size_t mask_tail_octets, typename Name>
class FunctionIPv4NumToString : public IFunction {
private:
template <typename ArgType>
Status execute_type(Block& block, const ColumnWithTypeAndName& argument, size_t result) const {
using ColumnType = ColumnVector<ArgType>;
const ColumnPtr& column = argument.column;
if (const ColumnType* col = typeid_cast<const ColumnType*>(column.get())) {
const typename ColumnType::Container& vec_in = col->get_data();
auto col_res = ColumnString::create();
ColumnString::Chars& vec_res = col_res->get_chars();
ColumnString::Offsets& offsets_res = col_res->get_offsets();
vec_res.resize(vec_in.size() *
(IPV4_MAX_TEXT_LENGTH + 1)); /// the longest value is: 255.255.255.255\0
offsets_res.resize(vec_in.size());
char* begin = reinterpret_cast<char*>(vec_res.data());
char* pos = begin;
auto null_map = ColumnUInt8::create(vec_in.size(), 0);
size_t src_size = std::min(sizeof(ArgType), (unsigned long)4);
for (size_t i = 0; i < vec_in.size(); ++i) {
auto value = vec_in[i];
if (value < IPV4_MIN_NUM_VALUE || value > IPV4_MAX_NUM_VALUE) {
offsets_res[i] = pos - begin;
null_map->get_data()[i] = 1;
} else {
formatIPv4(reinterpret_cast<const unsigned char*>(&vec_in[i]), src_size, pos,
mask_tail_octets, "xxx");
offsets_res[i] = pos - begin;
}
}
vec_res.resize(pos - begin);
block.replace_by_position(
result, ColumnNullable::create(std::move(col_res), std::move(null_map)));
return Status::OK();
} else
return Status::RuntimeError("Illegal column {} of argument of function {}",
argument.column->get_name(), get_name());
}
public:
static constexpr auto name = "ipv4_num_to_string";
static FunctionPtr create() {
return std::make_shared<FunctionIPv4NumToString<mask_tail_octets, Name>>();
}
String get_name() const override { return name; }
size_t get_number_of_arguments() const override { return 1; }
DataTypePtr get_return_type_impl(const DataTypes& arguments) const override {
return make_nullable(std::make_shared<DataTypeString>());
}
bool use_default_implementation_for_nulls() const override { return true; }
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
size_t result, size_t input_rows_count) override {
ColumnWithTypeAndName& argument = block.get_by_position(arguments[0]);
switch (argument.type->get_type_id()) {
case TypeIndex::Int8:
return execute_type<Int8>(block, argument, result);
case TypeIndex::Int16:
return execute_type<Int16>(block, argument, result);
case TypeIndex::Int32:
return execute_type<Int32>(block, argument, result);
case TypeIndex::Int64:
return execute_type<Int64>(block, argument, result);
default:
break;
}
return Status::RuntimeError(
"Illegal column {} of argument of function {}, expected Int8 or Int16 or Int32 or "
"Int64",
argument.name, get_name());
}
};
} // namespace doris::vectorized