Skip to content

Commit

Permalink
improve
Browse files Browse the repository at this point in the history
  • Loading branch information
amorynan committed Jan 17, 2025
1 parent 05bc29d commit a0fe1ca
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 5 deletions.
3 changes: 3 additions & 0 deletions be/src/vec/functions/function_ip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,8 @@ void register_function_ip(SimpleFunctionFactory& factory) {

/// Cut IPv6 part
factory.register_function<FunctionCutIPv6>();

// Covert to IPv6 from uint128-string
factory.register_function<FunctionIPv6FromUInt128StringOrNull>();
}
} // namespace doris::vectorized
44 changes: 44 additions & 0 deletions be/src/vec/functions/function_ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,50 @@ class FunctionCutIPv6 : public IFunction {
}
};

class FunctionIPv6FromUInt128StringOrNull : public IFunction {
public:
static constexpr auto name = "ipv6_from_uint128_string_or_null";
static FunctionPtr create() { return std::make_shared<FunctionIPv6FromUInt128StringOrNull>(); }

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 std::make_shared<DataTypeNullable>(std::make_shared<DataTypeIPv6>());
}

Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
uint32_t result, size_t input_rows_count) const override {
const auto& ipv6_column_with_type_and_name = block.get_by_position(arguments[0]);
const auto& [ipv6_column, ipv6_const] =
unpack_if_const(ipv6_column_with_type_and_name.column);
const auto* ipv6_addr_column = assert_cast<const ColumnString*>(ipv6_column.get());
// result is nullable column
auto col_res = ColumnNullable::create(ColumnIPv6::create(input_rows_count, 0),
ColumnUInt8::create(input_rows_count, 1));
auto& col_res_data = assert_cast<ColumnIPv6*>(&col_res->get_nested_column())->get_data();
auto& res_null_map_data = col_res->get_null_map_data();

for (size_t i = 0; i < input_rows_count; ++i) {
IPv6 ipv6 = 0;
auto ipv6_idx = index_check_const(i, ipv6_const);
StringRef uint128_string = ipv6_addr_column->get_data_at(ipv6_idx);
if (!IPv6Value::from_uint128_string(ipv6, uint128_string.data, uint128_string.size)) {
LOG(WARNING) << "Invalid uin128 IPv6 value '" << uint128_string.to_string_view()
<< "'";
// we should set null to the result not throw exception for load senior
} else {
col_res_data[i] = ipv6;
res_null_map_data[i] = 0;
}
}

block.replace_by_position(result, std::move(col_res));
return Status::OK();
}
};

} // namespace doris::vectorized

#include "common/compile_check_end.h"
4 changes: 0 additions & 4 deletions be/src/vec/io/io_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,6 @@ template <typename T>
bool read_ipv6_text_impl(T& x, ReadBuffer& buf) {
static_assert(std::is_same_v<IPv6, T>);
bool res = IPv6Value::from_string(x, buf.position(), buf.count());
if (!res) {
// try to parse as uint128
res = IPv6Value::from_uint128_string(x, buf.position(), buf.count());
}
buf.position() = buf.end();
return res;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNumOrNull;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4ToIpv6;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6CIDRToRange;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6FromUInt128StringOrNull;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6NumToString;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNum;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNumOrDefault;
Expand Down Expand Up @@ -703,6 +704,7 @@ public class BuiltinScalarFunctions implements FunctionHelper {
scalar(IsIpAddressInRange.class, "is_ip_address_in_range"),
scalar(Ipv4CIDRToRange.class, "ipv4_cidr_to_range"),
scalar(Ipv6CIDRToRange.class, "ipv6_cidr_to_range"),
scalar(Ipv6FromUInt128StringOrNull.class, "ipv6_from_uint128_string_or_null"),
scalar(JsonArray.class, "json_array"),
scalar(JsonObject.class, "json_object"),
scalar(JsonQuote.class, "json_quote"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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.

package org.apache.doris.nereids.trees.expressions.functions.scalar;

import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.IPv6Type;
import org.apache.doris.nereids.types.StringType;
import org.apache.doris.nereids.types.VarcharType;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;

import java.util.List;

/**
* scalar function ipv6_from_uint128_string_or_null
* args just accept varchar as uint128 string
* return ipv6 or null
* sql : select ipv6_from_uint128_string_or_null('340282366920938463463374607431768211455');
*/
public class Ipv6FromUInt128StringOrNull extends ScalarFunction
implements UnaryExpression, ExplicitlyCastableSignature, AlwaysNullable {

public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(IPv6Type.INSTANCE).args(VarcharType.SYSTEM_DEFAULT),
FunctionSignature.ret(IPv6Type.INSTANCE).args(StringType.INSTANCE));

public Ipv6FromUInt128StringOrNull(Expression arg0) {
super("ipv6_from_uint128_string_or_null", arg0);
}

@Override
public Ipv6FromUInt128StringOrNull withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 1,
"ipv6_from_uint128_string_or_null accept 1 args, but got %s (%s)",
children.size(),
children);
return new Ipv6FromUInt128StringOrNull(children.get(0));
}

@Override
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}

@Override
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitIpv6FromUInt128StringOrNull(this, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4StringToNumOrNull;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv4ToIpv6;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6CIDRToRange;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6FromUInt128StringOrNull;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6NumToString;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNum;
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ipv6StringToNumOrDefault;
Expand Down Expand Up @@ -1353,6 +1354,10 @@ default R visitIpv6StringToNumOrNull(Ipv6StringToNumOrNull ipv6StringToNumOrNull
return visitScalarFunction(ipv6StringToNumOrNull, context);
}

default R visitIpv6FromUInt128StringOrNull(Ipv6FromUInt128StringOrNull ipv6FromUInt128StringOrNull, C context) {
return visitScalarFunction(ipv6FromUInt128StringOrNull, context);
}

default R visitIsIpv4Compat(IsIpv4Compat isIpv4Compat, C context) {
return visitScalarFunction(isIpv4Compat, context);
}
Expand Down
2 changes: 2 additions & 0 deletions gensrc/script/doris_builtins_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2153,6 +2153,8 @@
[['to_ipv6_or_null'], 'IPV6', ['STRING'], 'ALWAYS_NULLABLE'],
[['ipv4_to_ipv6'], 'IPV6', ['IPV4'], 'DEPEND_ON_ARGUMENT'],
[['cut_ipv6'], 'STRING', ['IPV6', 'TINYINT', 'TINYINT'], 'DEPEND_ON_ARGUMENT'],
[['ipv6_from_uint128_string_or_null'], 'IPV6', ['VARCHAR'], 'ALWAYS_NULLABLE'],
[['ipv6_from_uint128_string_or_null'], 'IPV6', ['STRING'], 'ALWAYS_NULLABLE']
],

"NonNullalbe": [
Expand Down
3 changes: 2 additions & 1 deletion regression-test/suites/datatype_p0/ip/test_ip_basic.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ suite("test_ip_basic") {
db 'regression_test_datatype_p0_ip'
table 'table_ipv6_uint128'
set 'column_separator', ','
set 'columns', 'col0, tmp, ipv6, ipv6_uint128=ipv6_from_uint128_string_or_null(tmp)'
file 'test_data/ipv6_uint128.csv'
time 10000 // limit inflight 10s
// stream load action will check result, include Success status, and NumberTotalRows == NumberLoadedRows
Expand Down Expand Up @@ -234,5 +235,5 @@ suite("test_ip_basic") {
}

// then cast ipv6_uint128 to ipv6
qt_sql_ipv6_string """ select cast(ipv6_uint128 as ipv6), ipv6 from table_ipv6_uint128_string order by col0 """
qt_sql_ipv6_string """ select ipv6_from_uint128_string_or_null(ipv6_uint128) as ipv6_uint128, ipv6 from table_ipv6_uint128_string order by col0 """
}

0 comments on commit a0fe1ca

Please sign in to comment.