Skip to content

Commit

Permalink
This is an automated cherry-pick of pingcap#8114
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
  • Loading branch information
windtalker authored and ti-chi-bot committed Sep 20, 2023
1 parent d8cb780 commit 0891087
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 3 deletions.
35 changes: 32 additions & 3 deletions dbms/src/Functions/FunctionsMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,9 +581,33 @@ struct PiImpl
};


bool logNullable(double b, double & result)
{
if (b <= 0)
return true;
result = log(b);
return false;
}

bool log2Nullable(double b, double & result)
{
if (b <= 0)
return true;
result = log2(b);
return false;
}

bool log10Nullable(double b, double & result)
{
if (b <= 0)
return true;
result = log10(b);
return false;
}

bool log2args(double b, double e, double & result)
{
if (b == 1 || b < 0 || e < 0)
if (b == 1 || b <= 0 || e <= 0)
{
return true;
}
Expand Down Expand Up @@ -696,13 +720,18 @@ using FunctionSign = FunctionMathUnaryFloat64<UnaryFunctionPlain<SignName, DB::s
using FunctionE = FunctionMathNullaryConstFloat64<EImpl>;
using FunctionPi = FunctionMathNullaryConstFloat64<PiImpl>;
using FunctionExp = FunctionMathUnaryFloat64<UnaryFunctionVectorized<ExpName, exp>>;
using FunctionLog = FunctionMathUnaryFloat64<UnaryFunctionVectorized<LogName, log>>;
using FunctionLog = FunctionMathUnaryFloat64Nullable<UnaryFunctionNullableVectorized<LogName, DB::logNullable>>;
using FunctionLog2Args = FunctionMathBinaryFloat64Nullable<BinaryFunctionNullablePlain<Log2ArgsName, DB::log2args>>;
using FunctionExp2 = FunctionMathUnaryFloat64<UnaryFunctionVectorized<Exp2Name, exp2>>;
using FunctionLog2 = FunctionMathUnaryFloat64<UnaryFunctionVectorized<Log2Name, log2>>;
using FunctionLog2 = FunctionMathUnaryFloat64Nullable<UnaryFunctionNullableVectorized<Log2Name, DB::log2Nullable>>;
using FunctionExp10 = FunctionMathUnaryFloat64<UnaryFunctionVectorized<Exp10Name, preciseExp10>>;
<<<<<<< HEAD
using FunctionLog10 = FunctionMathUnaryFloat64<UnaryFunctionVectorized<Log10Name, log10>>;
using FunctionSqrt = FunctionMathUnaryFloat64<UnaryFunctionVectorized<SqrtName, sqrt>>;
=======
using FunctionLog10 = FunctionMathUnaryFloat64Nullable<UnaryFunctionNullableVectorized<Log10Name, DB::log10Nullable>>;
using FunctionSqrt = FunctionMathUnaryFloat64Nullable<UnaryFunctionNullableVectorized<SqrtName, DB::sqrtNullable>>;
>>>>>>> d8fa1d1c3d (Fix func log error (#8114))

using FunctionCbrt = FunctionMathUnaryFloat64<UnaryFunctionVectorized<CbrtName,
#if USE_VECTORCLASS
Expand Down
208 changes: 208 additions & 0 deletions dbms/src/Functions/tests/gtest_functions_log.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// Copyright 2023 PingCAP, Inc.
//
// Licensed 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.

#include <Common/FieldVisitors.h>
#include <DataTypes/DataTypeDecimal.h>
#include <DataTypes/DataTypeNullable.h>
#include <DataTypes/DataTypesNumber.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/registerFunctions.h>
#include <TestUtils/FunctionTestUtils.h>
#include <TestUtils/TiFlashTestBasic.h>

namespace DB
{
namespace tests
{
class TestFunctionLog : public DB::tests::FunctionTest
{
};

TEST_F(TestFunctionLog, Log)
try
{
String func_name = "log";
/// not null column
auto input = createColumn<Float64>({-1, 0, 0.5, 1, 2});
auto ref = std::log(0.5);
auto output = createColumn<Nullable<Float64>>({{}, {}, ref, 0, -ref});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable column
input = createColumn<Nullable<Float64>>({{}, -1, 0, 0.5, 1, 2});
output = createColumn<Nullable<Float64>>({{}, {}, {}, ref, 0, -ref});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// not null constant
input = createConstColumn<Float64>(5, 0);
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
input = createConstColumn<Float64>(5, 1);
output = createConstColumn<Nullable<Float64>>(5, 0);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable constant with not null value
input = createConstColumn<Nullable<Float64>>(5, 0);
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
input = createConstColumn<Nullable<Float64>>(5, 1);
output = createConstColumn<Nullable<Float64>>(5, 0);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable constant with null value
input = createConstColumn<Nullable<Float64>>(5, {});
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// typeNothing
input = createOnlyNullColumnConst(5);
output = createOnlyNullColumnConst(5);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// don't need to test other data tpe like int/decimal since TiDB will ensure the input must be float64
}
CATCH

TEST_F(TestFunctionLog, Log2Args)
try
{
String func_name = "log2args";
/// func(column,column)
auto input1 = createColumn<Float64>({1, 0, -1, 2, 2, 2});
auto input2 = createColumn<Float64>({2, 2, 2, 0, -1, 2});
auto output = createColumn<Nullable<Float64>>({{}, {}, {}, {}, {}, 1});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
input1 = createColumn<Nullable<Float64>>({1, 0, -1, 2, 2, 2, {}});
input2 = createColumn<Float64>({2, 2, 2, 0, -1, 2, 2});
output = createColumn<Nullable<Float64>>({{}, {}, {}, {}, {}, 1, {}});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
input1 = createColumn<Float64>({1, 0, -1, 2, 2, 2, 2});
input2 = createColumn<Nullable<Float64>>({2, 2, 2, 0, -1, 2, {}});
output = createColumn<Nullable<Float64>>({{}, {}, {}, {}, {}, 1, {}});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
input1 = createColumn<Nullable<Float64>>({1, 0, -1, 2, 2, 2, 2});
input2 = createColumn<Nullable<Float64>>({2, 2, 2, 0, -1, 2, {}});
output = createColumn<Nullable<Float64>>({{}, {}, {}, {}, {}, 1, {}});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
/// func(const,column)
input1 = createConstColumn<Float64>(7, 2);
input2 = createColumn<Float64>({2, 2, 2, 0, -1, 2, 2});
output = createColumn<Nullable<Float64>>({1, 1, 1, {}, {}, 1, 1});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
/// func(column,const)
input1 = createColumn<Nullable<Float64>>({1, 0, -1, 2, 2, 2, {}});
input2 = createConstColumn<Float64>(7, 2);
output = createColumn<Nullable<Float64>>({{}, {}, {}, 1, 1, 1, {}});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
/// func(const,const)
input1 = createConstColumn<Float64>(7, 2);
input2 = createConstColumn<Float64>(7, 2);
output = createConstColumn<Nullable<Float64>>(7, 1);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
input1 = createConstColumn<Float64>(7, 1);
input2 = createConstColumn<Float64>(7, 2);
output = createConstColumn<Nullable<Float64>>(7, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
/// typeNothing
input1 = createOnlyNullColumnConst(5);
input2 = createConstColumn<Float64>(5, 2);
output = createOnlyNullColumnConst(5);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
input1 = createConstColumn<Float64>(5, 2);
input2 = createOnlyNullColumnConst(5);
output = createOnlyNullColumnConst(5);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
input1 = createOnlyNullColumnConst(5);
input2 = createOnlyNullColumnConst(5);
output = createOnlyNullColumnConst(5);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input1, input2));
}
CATCH

TEST_F(TestFunctionLog, Log2)
try
{
String func_name = "log2";
/// not null column
auto input = createColumn<Float64>({-1, 0, 0.5, 1, 2});
auto ref = std::log2(0.5);
auto output = createColumn<Nullable<Float64>>({{}, {}, ref, 0, -ref});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable column
input = createColumn<Nullable<Float64>>({{}, -1, 0, 0.5, 1, 2});
output = createColumn<Nullable<Float64>>({{}, {}, {}, ref, 0, -ref});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// not null constant
input = createConstColumn<Float64>(5, 0);
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
input = createConstColumn<Float64>(5, 1);
output = createConstColumn<Nullable<Float64>>(5, 0);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable constant with not null value
input = createConstColumn<Nullable<Float64>>(5, 0);
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
input = createConstColumn<Nullable<Float64>>(5, 1);
output = createConstColumn<Nullable<Float64>>(5, 0);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable constant with null value
input = createConstColumn<Nullable<Float64>>(5, {});
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// typeNothing
input = createOnlyNullColumnConst(5);
output = createOnlyNullColumnConst(5);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// don't need to test other data tpe like int/decimal since TiDB will ensure the input must be float64
}
CATCH

TEST_F(TestFunctionLog, Log10)
try
{
String func_name = "log10";
/// not null column
auto input = createColumn<Float64>({-1, 0, 0.5, 1, 2});
auto ref = std::log10(0.5);
auto output = createColumn<Nullable<Float64>>({{}, {}, ref, 0, -ref});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable column
input = createColumn<Nullable<Float64>>({{}, -1, 0, 0.5, 1, 2});
output = createColumn<Nullable<Float64>>({{}, {}, {}, ref, 0, -ref});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// not null constant
input = createConstColumn<Float64>(5, 0);
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
input = createConstColumn<Float64>(5, 1);
output = createConstColumn<Nullable<Float64>>(5, 0);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable constant with not null value
input = createConstColumn<Nullable<Float64>>(5, 0);
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
input = createConstColumn<Nullable<Float64>>(5, 1);
output = createConstColumn<Nullable<Float64>>(5, 0);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// nullable constant with null value
input = createConstColumn<Nullable<Float64>>(5, {});
output = createConstColumn<Nullable<Float64>>(5, {});
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// typeNothing
input = createOnlyNullColumnConst(5);
output = createOnlyNullColumnConst(5);
ASSERT_COLUMN_EQ(output, executeFunction(func_name, input));
/// don't need to test other data tpe like int/decimal since TiDB will ensure the input must be float64
}
CATCH

} // namespace tests

} // namespace DB
File renamed without changes.
22 changes: 22 additions & 0 deletions tests/fullstack-test/expr/issue_8113.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2023 PingCAP, Inc.
#
# Licensed 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.

mysql> drop table if exists test.t0
mysql> create table test.t0(c0 BOOL);
mysql> INSERT INTO test.t0 VALUES (false)
mysql> alter table test.t0 set tiflash replica 1

func> wait_table test t0

mysql> use test; set tidb_enforce_mpp=1; SELECT /*+ READ_FROM_STORAGE(TIFLASH[t0])*/t0.c0 FROM t0 WHERE LOG(t0.c0)

0 comments on commit 0891087

Please sign in to comment.