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(expr): support pow function #7789

Merged
merged 5 commits into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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.

51 changes: 51 additions & 0 deletions e2e_test/batch/functions/pow.slt.part
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
query R
select pow(2.0, 3.0)
----
8

query R
select pow(2.0::decimal, 3.0::decimal)
----
8

query R
select pow(2.0::double, 3.0::double)
----
8

query R
select pow(2.0::smallint, 3.0::smallint)
----
8

query R
select pow(2.0::bigint, 3.0::bigint)
----
8

query R
select pow(2.0, -2);
----
0.25

query R
select pow(2.23, -2.33);
----
0.15432975583772085

query R
select pow(100000, 0);
----
1

query R
select pow(100000, -200000000000000);
----
0

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


statement error QueryError: Expr error: Numeric out of range
select pow(-100000, 200000000000001);
1 change: 1 addition & 0 deletions proto/expr.proto
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ message ExprNode {
BIT_LENGTH = 230;
OVERLAY = 231;
REGEXP_MATCH = 232;
POW = 233;

// Boolean comparison
IS_TRUE = 301;
Expand Down
13 changes: 12 additions & 1 deletion src/common/src/types/ordered_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ use core::str::FromStr;
pub use num_traits::Float;
use num_traits::{
AsPrimitive, Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub,
FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero,
FromPrimitive, Num, NumCast, One, Pow, Signed, ToPrimitive, Zero,
};

// masks for the parts of the IEEE 754 float
Expand Down Expand Up @@ -389,6 +389,17 @@ impl_ordered_float_binop! {Mul, mul, MulAssign, mul_assign}
impl_ordered_float_binop! {Div, div, DivAssign, div_assign}
impl_ordered_float_binop! {Rem, rem, RemAssign, rem_assign}

impl<T> Pow<OrderedFloat<T>> for OrderedFloat<T>
where
T: Float,
{
type Output = OrderedFloat<T>;

fn pow(self, rhs: Self) -> Self::Output {
OrderedFloat(self.0.powf(rhs.0))
}
}

impl<T> CheckedAdd for OrderedFloat<T>
where
T: Float,
Expand Down
57 changes: 57 additions & 0 deletions src/expr/src/expr/expr_binary_nonnull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,56 @@ 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 @@ -662,6 +712,13 @@ pub fn new_binary_expr(
},
}
}
Type::Pow => {
gen_binary_expr_pow! {
gen_atm_impl,
l, r, ret,
general_pow,
}
}
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
2 changes: 1 addition & 1 deletion src/expr/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub fn build_from_prost(prost: &ExprNode) -> Result<BoxedExpression> {
| IsNotNull | Neg | Ascii | Abs | Ceil | Floor | Round | BitwiseNot | CharLength
| BoolOut | OctetLength | BitLength | ToTimestamp => build_unary_expr_prost(prost),
Equal | NotEqual | LessThan | LessThanOrEqual | GreaterThan | GreaterThanOrEqual | Add
| Subtract | Multiply | Divide | Modulus | Extract | RoundDigit | TumbleStart
| Subtract | Multiply | Divide | Modulus | Extract | RoundDigit | Pow | TumbleStart
| Position | BitwiseShiftLeft | BitwiseShiftRight | BitwiseAnd | BitwiseOr | BitwiseXor
| ConcatOp | AtTimeZone | CastWithTimeZone => build_binary_expr_prost(prost),
And | Or | IsDistinctFrom | IsNotDistinctFrom | ArrayAccess => {
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 @@ -172,6 +172,7 @@ fn build_type_derive_map() -> FuncSigMap {
&[T::Int16, T::Int32, T::Int64, T::Decimal],
);
map.insert(E::RoundDigit, vec![T::Decimal, T::Int32], T::Decimal);
map.insert(E::Pow, vec![T::Float64, T::Float64], T::Float64);

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

use chrono::{Duration, NaiveDateTime};
use num_traits::{CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, Signed, Zero};
use num_traits::{CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedSub, Pow, Signed, Zero};
use risingwave_common::types::{
CheckedAdd, Decimal, IntervalUnit, NaiveDateTimeWrapper, NaiveDateWrapper, NaiveTimeWrapper,
OrderedF64,
Expand Down Expand Up @@ -108,6 +108,21 @@ 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>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we cast them in frontend, I guess we can only support a concrete implementation (f64,f64)->f64 instead of a general one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least the Decimal version needs to be implemented besides the f64 version.

image

where
T1: Into<T3> + Debug,
T2: Into<T3> + Debug,
T3: Pow<T3> + num_traits::Float,
{
let res = l.into().powf(r.into());
if res.is_infinite() {
Err(ExprError::NumericOutOfRange)
} else {
Ok(res)
}
}

#[inline(always)]
pub fn general_atm<T1, T2, T3, F>(l: T1, r: T2, atm: F) -> Result<T3>
where
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/binder/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ impl Binder {
(1, raw_call(ExprType::Round)),
]),
),
("pow", raw_call(ExprType::Pow)),
("ceil", raw_call(ExprType::Ceil)),
("floor", raw_call(ExprType::Floor)),
("abs", raw_call(ExprType::Abs)),
Expand Down
1 change: 1 addition & 0 deletions src/tests/sqlsmith/src/sql_gen/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ fn make_general_expr(func: ExprType, exprs: Vec<Expr>) -> Option<Expr> {
E::IsNotFalse => Some(Expr::IsNotFalse(Box::new(exprs[0].clone()))),
E::Position => Some(Expr::Function(make_simple_func("position", &exprs))),
E::RoundDigit => Some(Expr::Function(make_simple_func("round", &exprs))),
E::Pow => Some(Expr::Function(make_simple_func("pow", &exprs))),
E::Repeat => Some(Expr::Function(make_simple_func("repeat", &exprs))),
E::CharLength => Some(Expr::Function(make_simple_func("char_length", &exprs))),
E::Substr => Some(Expr::Function(make_simple_func("substr", &exprs))),
Expand Down