Skip to content

Commit d35fb95

Browse files
authored
[feature](Nereids): Convert log(x) to ln(x) (#52862)
### What problem does this PR solve? Problem Summary: * In MySQL, LOG(col, e) is equivalent to LN(col), where e is Euler’s number (~2.71828). * Currently, MySQL also supports LOG(col) as a shorthand for LOG(col, e) (i.e., natural logarithm). * This conversion replaces LOG(col) with LN(col) when only a single argument is provided. doc: apache/doris-website#2605
1 parent 156b151 commit d35fb95

File tree

6 files changed

+98
-3
lines changed

6 files changed

+98
-3
lines changed

fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionOptimization.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.doris.nereids.rules.expression.rules.DistinctPredicatesRule;
2626
import org.apache.doris.nereids.rules.expression.rules.ExtractCommonFactorRule;
2727
import org.apache.doris.nereids.rules.expression.rules.LikeToEqualRewrite;
28+
import org.apache.doris.nereids.rules.expression.rules.LogToLn;
2829
import org.apache.doris.nereids.rules.expression.rules.NullSafeEqualToEqual;
2930
import org.apache.doris.nereids.rules.expression.rules.SimplifyComparisonPredicate;
3031
import org.apache.doris.nereids.rules.expression.rules.SimplifyConflictCompound;
@@ -61,7 +62,8 @@ public class ExpressionOptimization extends ExpressionRewrite {
6162
TopnToMax.INSTANCE,
6263
NullSafeEqualToEqual.INSTANCE,
6364
LikeToEqualRewrite.INSTANCE,
64-
BetweenToEqual.INSTANCE
65+
BetweenToEqual.INSTANCE,
66+
LogToLn.INSTANCE
6567
)
6668
);
6769

fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public enum ExpressionRuleType {
3434
EXTRACT_COMMON_FACTOR,
3535
FOLD_CONSTANT_ON_BE,
3636
FOLD_CONSTANT_ON_FE,
37+
LOG_TO_LN,
3738
IN_PREDICATE_DEDUP,
3839
IN_PREDICATE_EXTRACT_NON_CONSTANT,
3940
IN_PREDICATE_TO_EQUAL_TO,
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.apache.doris.nereids.rules.expression.rules;
19+
20+
import org.apache.doris.nereids.rules.expression.ExpressionPatternMatcher;
21+
import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory;
22+
import org.apache.doris.nereids.rules.expression.ExpressionRuleType;
23+
import org.apache.doris.nereids.trees.expressions.Expression;
24+
import org.apache.doris.nereids.trees.expressions.functions.scalar.Ln;
25+
import org.apache.doris.nereids.trees.expressions.functions.scalar.Log;
26+
27+
import com.google.common.collect.ImmutableList;
28+
29+
import java.util.List;
30+
31+
/**
32+
* In MySQL, LOG(col, e) is equivalent to LN(col), where e is Euler’s number (~2.71828).
33+
* Currently, MySQL also supports LOG(col) as a shorthand for LOG(col, e) (i.e., natural logarithm).
34+
* This conversion replaces LOG(col) with LN(col) when only a single argument is provided.
35+
*/
36+
public class LogToLn implements ExpressionPatternRuleFactory {
37+
38+
public static final LogToLn INSTANCE = new LogToLn();
39+
40+
@Override
41+
public List<ExpressionPatternMatcher<? extends Expression>> buildRules() {
42+
return ImmutableList.of(
43+
matchesType(Log.class).then(LogToLn::rewrite)
44+
.toRule(ExpressionRuleType.LOG_TO_LN)
45+
);
46+
}
47+
48+
/** rewrite */
49+
public static Expression rewrite(Log log) {
50+
if (log.arity() == 1) {
51+
return new Ln(log.child(0));
52+
} else {
53+
return log;
54+
}
55+
}
56+
}

fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/Log.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,17 @@ public class Log extends ScalarFunction
3737
implements BinaryExpression, ExplicitlyCastableSignature, AlwaysNullable {
3838

3939
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
40+
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE),
4041
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, DoubleType.INSTANCE)
4142
);
4243

44+
/**
45+
* constructor with 1 arguments.
46+
*/
47+
public Log(Expression arg0) {
48+
super("log", arg0);
49+
}
50+
4351
/**
4452
* constructor with 2 arguments.
4553
*/
@@ -52,8 +60,13 @@ public Log(Expression arg0, Expression arg1) {
5260
*/
5361
@Override
5462
public Log withChildren(List<Expression> children) {
55-
Preconditions.checkArgument(children.size() == 2);
56-
return new Log(children.get(0), children.get(1));
63+
Preconditions.checkArgument(children.size() == 1 || children.size() == 2,
64+
"Log function should have 1 or 2 children, but got: %s", children.size());
65+
if (children.size() == 1) {
66+
return new Log(children.get(0));
67+
} else {
68+
return new Log(children.get(0), children.get(1));
69+
}
5770
}
5871

5972
@Override

regression-test/data/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,17 @@
149149
7 \N true
150150
8 \N true
151151

152+
-- !dlog_tbl_1 --
153+
1 0.09531017980432493 0.09531017980432493 1.0986122886681098 1.0986122886681098
154+
2 \N \N 1.0986122886681098 1.0986122886681098
155+
3 \N \N 1.0986122886681098 1.0986122886681098
156+
4 \N \N 1.0986122886681098 1.0986122886681098
157+
5 \N \N 1.0986122886681098 1.0986122886681098
158+
6 \N \N 1.0986122886681098 1.0986122886681098
159+
7 \N \N 1.0986122886681098 1.0986122886681098
160+
8 \N \N 1.0986122886681098 1.0986122886681098
161+
9 0.1823215567939546 0.1823215567939546 1.0986122886681098 1.0986122886681098
162+
10 0.7884573603642703 0.7884573603642703 1.0986122886681098 1.0986122886681098
163+
11 1.2237754316221157 1.2237754316221157 1.0986122886681098 1.0986122886681098
164+
12 1.7227665977411035 1.7227665977411035 1.0986122886681098 1.0986122886681098
165+

regression-test/suites/query_p0/sql_functions/math_functions/test_math_unary_always_nullable.groovy

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,13 @@ suite("test_math_unary_alway_nullable") {
110110
select rowid, dsqrt(val), dsqrt(val) is null from test_math_unary_alway_nullable order by rowid;
111111
"""
112112

113+
sql """
114+
insert into test_math_unary_alway_nullable values
115+
(9, 1.2), (10, 2.2), (11, 3.4), (12, 5.6)
116+
"""
117+
118+
qt_dlog_tbl_1 """
119+
select rowid, log(val), ln(val), log(3), ln(3) from test_math_unary_alway_nullable order by rowid;
120+
"""
121+
113122
}

0 commit comments

Comments
 (0)