Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support exp and refactor pow #7971

Merged
merged 6 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions dashboard/proto/gen/expr.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions e2e_test/batch/functions/pow.slt.part
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ select pow(2.0, 3.0)
----
8

query R
select power(2.0, 3.0)
----
8

query R
select pow(2.0::decimal, 3.0::decimal)
----
Expand Down Expand Up @@ -49,3 +54,38 @@ select pow(100000, 200000000000000);

statement error QueryError: Expr error: Numeric out of range
select pow(-100000, 200000000000001);

query R
select exp(0::smallint);
----
1

query R
select exp(0.0);
----
1

query R
select exp(0.0::decimal);
----
1

query R
select exp(2.0);
----
7.38905609893065

query R
select exp(2::smallint)
----
7.38905609893065

statement error QueryError: Expr error: Numeric out of range
select exp(10000000);

# We remark that this test case underflows in PG. TODO: We can make it fully compatible if necessary
# https://github.com/postgres/postgres/blob/REL_15_2/src/backend/utils/adt/float.c#L1649
query T
select exp(-10000000);
----
0
1 change: 1 addition & 0 deletions proto/expr.proto
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ message ExprNode {
OVERLAY = 231;
REGEXP_MATCH = 232;
POW = 233;
EXP = 234;

// Boolean comparison
IS_TRUE = 301;
Expand Down
2 changes: 1 addition & 1 deletion src/expr/src/expr/build_expr_from_prost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn build_from_prost(prost: &ExprNode) -> Result<BoxedExpression> {
match prost.get_expr_type().unwrap() {
// Fixed number of arguments and based on `Unary/Binary/Ternary/...Expression`
Cast | Upper | Lower | Md5 | Not | IsTrue | IsNotTrue | IsFalse | IsNotFalse | IsNull
| IsNotNull | Neg | Ascii | Abs | Ceil | Floor | Round | BitwiseNot | CharLength
| IsNotNull | Neg | Ascii | Abs | Ceil | Floor | Round | Exp | BitwiseNot | CharLength
| BoolOut | OctetLength | BitLength | ToTimestamp => build_unary_expr_prost(prost),
Equal | NotEqual | LessThan | LessThanOrEqual | GreaterThan | GreaterThanOrEqual | Add
| Subtract | Multiply | Divide | Modulus | Extract | RoundDigit | Pow | TumbleStart
Expand Down
64 changes: 5 additions & 59 deletions src/expr/src/expr/expr_binary_nonnull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
// limitations under the License.

use risingwave_common::array::{
Array, BoolArray, DecimalArray, I32Array, I64Array, IntervalArray, ListArray, NaiveDateArray,
NaiveDateTimeArray, StructArray, Utf8Array,
Array, BoolArray, DecimalArray, F64Array, I32Array, I64Array, IntervalArray, ListArray,
NaiveDateArray, NaiveDateTimeArray, StructArray, Utf8Array,
};
use risingwave_common::types::*;
use risingwave_pb::expr::expr_node::Type;
Expand Down Expand Up @@ -288,56 +288,6 @@ macro_rules! gen_binary_expr_atm {
};
}

/// `gen_binary_expr_atm` is similar to `gen_binary_expr_cmp`.
/// `atm` means arithmetic here.
/// They are differentiate cuz one type may not support atm and cmp at the same time. For example,
/// Varchar can support compare but not arithmetic.
/// * `$general_f`: generic atm function (require a common ``TryInto`` type for two input)
/// * `$i1`, `$i2`, `$rt`, `$func`: extra list passed to `$macro` directly
macro_rules! gen_binary_expr_pow {
($macro:ident, $l:expr, $r:expr, $ret:expr, $general_f:ident,) => {
$macro! {
[$l, $r, $ret],
{ int16, int16, float64, $general_f },
{ int16, int32, float64, $general_f },
{ int16, int64, float64, $general_f },
{ int16, float32, float64, $general_f },
{ int16, float64, float64, $general_f },
{ int32, int16, float64, $general_f },
{ int32, int32, float64, $general_f },
{ int32, int64, float64, $general_f },
{ int32, float32, float64, $general_f },
{ int32, float64, float64, $general_f },
{ int64, int16, float64, $general_f },
{ int64, int32, float64, $general_f },
{ int64, int64, float64, $general_f },
{ int64, float32, float64 , $general_f},
{ int64, float64, float64, $general_f },
{ float32, int16, float64, $general_f },
{ float32, int32, float64, $general_f },
{ float32, int64, float64 , $general_f},
{ float32, float32, float64, $general_f },
{ float32, float64, float64, $general_f },
{ float64, int16, float64, $general_f },
{ float64, int32, float64, $general_f },
{ float64, int64, float64, $general_f },
{ float64, float32, float64, $general_f },
{ float64, float64, float64, $general_f },
{ decimal, int16, float64, $general_f },
{ decimal, int32, float64, $general_f },
{ decimal, int64, float64, $general_f },
{ decimal, float32, float64, $general_f },
{ decimal, float64, float64, $general_f },
{ int16, decimal, float64, $general_f },
{ int32, decimal, float64, $general_f },
{ int64, decimal, float64, $general_f },
{ decimal, decimal, float64, $general_f },
{ float32, decimal, float64, $general_f },
{ float64, decimal, float64, $general_f },
}
};
}

/// `gen_binary_expr_bitwise` is similar to `gen_binary_expr_atm`.
/// They are differentiate because bitwise operation only supports integral datatype.
/// * `$general_f`: generic atm function (require a common ``TryInto`` type for two input)
Expand Down Expand Up @@ -713,13 +663,9 @@ pub fn new_binary_expr(
},
}
}
Type::Pow => {
gen_binary_expr_pow! {
gen_atm_impl,
l, r, ret,
general_pow,
}
}
Type::Pow => Box::new(BinaryExpression::<F64Array, F64Array, F64Array, _>::new(
l, r, ret, pow_f64,
)),
Type::Extract => build_extract_expr(ret, l, r)?,
Type::AtTimeZone => build_at_time_zone_expr(ret, l, r)?,
Type::CastWithTimeZone => build_cast_with_time_zone_expr(ret, l, r)?,
Expand Down
8 changes: 7 additions & 1 deletion src/expr/src/expr/expr_unary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::vector_op::bitwise_op::general_bitnot;
use crate::vector_op::cast::*;
use crate::vector_op::cmp::{is_false, is_not_false, is_not_true, is_true};
use crate::vector_op::conjunction;
use crate::vector_op::exp::exp_f64;
use crate::vector_op::length::{bit_length, length_default, octet_length};
use crate::vector_op::lower::lower;
use crate::vector_op::ltrim::ltrim;
Expand Down Expand Up @@ -288,12 +289,17 @@ pub fn new_unary_expr(
(ProstType::Ceil, _, _) => {
gen_round_expr! {"Ceil", child_expr, return_type, ceil_f64, ceil_decimal}
}
(ProstType::Floor, _, _) => {
(ProstType::Floor, DataType::Float64, DataType::Float64) => {
gen_round_expr! {"Floor", child_expr, return_type, floor_f64, floor_decimal}
}
(ProstType::Round, _, _) => {
gen_round_expr! {"Ceil", child_expr, return_type, round_f64, round_decimal}
}
(ProstType::Exp, _, _) => Box::new(UnaryExpression::<F64Array, F64Array, _>::new(
child_expr,
return_type,
exp_f64,
)),
(ProstType::ToTimestamp, DataType::Timestamptz, DataType::Float64) => {
Box::new(UnaryExpression::<F64Array, I64Array, _>::new(
child_expr,
Expand Down
1 change: 1 addition & 0 deletions src/expr/src/sig/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ fn build_type_derive_map() -> FuncSigMap {
);
map.insert(E::RoundDigit, vec![T::Decimal, T::Int32], T::Decimal);
map.insert(E::Pow, vec![T::Float64, T::Float64], T::Float64);
map.insert(E::Exp, vec![T::Float64], T::Float64);

// build bitwise operator
// bitwise operator
Expand Down
13 changes: 4 additions & 9 deletions src/expr/src/vector_op/arithmetic_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use std::convert::TryInto;
use std::fmt::Debug;

use chrono::{Duration, NaiveDateTime};
use num_traits::{CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, Pow, Signed, Zero};
use num_traits::real::Real;
use num_traits::{CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, Signed, Zero};
use risingwave_common::types::{
CheckedAdd, Decimal, IntervalUnit, NaiveDateTimeWrapper, NaiveDateWrapper, NaiveTimeWrapper,
OrderedF64,
Expand Down Expand Up @@ -108,14 +109,8 @@ pub fn decimal_abs(decimal: Decimal) -> Result<Decimal> {
Ok(Decimal::abs(&decimal))
}

#[inline(always)]
pub fn general_pow<T1, T2, T3>(l: T1, r: T2) -> Result<T3>
where
T1: Into<T3> + Debug,
T2: Into<T3> + Debug,
T3: Pow<T3> + num_traits::Float,
{
let res = l.into().powf(r.into());
pub fn pow_f64(l: OrderedF64, r: OrderedF64) -> Result<OrderedF64> {
let res = l.powf(r);
if res.is_infinite() {
Err(ExprError::NumericOutOfRange)
} else {
Expand Down
27 changes: 27 additions & 0 deletions src/expr/src/vector_op/exp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2023 RisingWave Labs
//
// 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.

use num_traits::Float;
lmatz marked this conversation as resolved.
Show resolved Hide resolved
use risingwave_common::types::OrderedF64;

use crate::{ExprError, Result};

pub fn exp_f64(input: OrderedF64) -> Result<OrderedF64> {
let res = input.exp();
if res.is_infinite() {
Err(ExprError::NumericOutOfRange)
lmatz marked this conversation as resolved.
Show resolved Hide resolved
} else {
Ok(res)
}
}
1 change: 1 addition & 0 deletions src/expr/src/vector_op/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod cmp;
pub mod concat_op;
pub mod conjunction;
pub mod date_trunc;
pub mod exp;
pub mod extract;
pub mod format_type;
pub mod length;
Expand Down
3 changes: 3 additions & 0 deletions src/frontend/src/binder/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,12 @@ impl Binder {
]),
),
("pow", raw_call(ExprType::Pow)),
// "power" is the function name used in PG.
("power", raw_call(ExprType::Pow)),
("ceil", raw_call(ExprType::Ceil)),
("floor", raw_call(ExprType::Floor)),
("abs", raw_call(ExprType::Abs)),
("exp", raw_call(ExprType::Exp)),
lmatz marked this conversation as resolved.
Show resolved Hide resolved
("mod", raw_call(ExprType::Modulus)),
(
"to_timestamp",
Expand Down
10 changes: 9 additions & 1 deletion src/tests/regress/data/expected/float8.out
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,15 @@ ERROR: cannot take logarithm of zero
SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
ERROR: cannot take logarithm of a negative number
SELECT exp(f.f1) from FLOAT8_TBL f;
ERROR: value out of range: underflow
exp
-----------------------
1
0
0
7.399123060905129e-16
lmatz marked this conversation as resolved.
Show resolved Hide resolved
1
(5 rows)

SELECT f.f1 / '0.0' from FLOAT8_TBL f;
ERROR: division by zero
SELECT * FROM FLOAT8_TBL;
Expand Down
2 changes: 1 addition & 1 deletion src/tests/regress/data/sql/float8.sql
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;

SELECT ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;

SELECT exp(f.f1) from FLOAT8_TBL f;
--@ SELECT exp(f.f1) from FLOAT8_TBL f;

--@ SELECT f.f1 / '0.0' from FLOAT8_TBL f;

Expand Down