diff --git a/src/common/src/types/datetime.rs b/src/common/src/types/datetime.rs index a3984aaae367b..8d559525bc61a 100644 --- a/src/common/src/types/datetime.rs +++ b/src/common/src/types/datetime.rs @@ -74,7 +74,10 @@ impl_chrono_wrapper!(Time, NaiveTime); /// /// # Example /// ``` -/// # use risingwave_common::types::Date; +/// use std::str::FromStr; +/// +/// use risingwave_common::types::Date; +/// /// Date::from_str("1999-01-08").unwrap(); /// ``` impl FromStr for Date { @@ -92,7 +95,10 @@ impl FromStr for Date { /// /// # Example /// ``` -/// # use risingwave_common::types::Time; +/// use std::str::FromStr; +/// +/// use risingwave_common::types::Time; +/// /// Time::from_str("04:05").unwrap(); /// Time::from_str("04:05:06").unwrap(); /// ``` @@ -115,7 +121,10 @@ impl FromStr for Time { /// /// # Example /// ``` -/// # use risingwave_common::types::Timestamp; +/// use std::str::FromStr; +/// +/// use risingwave_common::types::Timestamp; +/// /// Timestamp::from_str("1999-01-08 04:02").unwrap(); /// Timestamp::from_str("1999-01-08 04:05:06").unwrap(); /// Timestamp::from_str("1999-01-08T04:05:06").unwrap(); diff --git a/src/expr/core/src/expr/expr_case.rs b/src/expr/core/src/expr/expr_case.rs index 5e2afb7e09208..83f1881a249eb 100644 --- a/src/expr/core/src/expr/expr_case.rs +++ b/src/expr/core/src/expr/expr_case.rs @@ -171,7 +171,7 @@ mod tests { let els = build_from_pretty("2:int4"); let case = CaseExpression::new(DataType::Int32, when_clauses, Some(els)); let (input, expected) = DataChunk::from_pretty( - "B f + "B i f 1 t 2 f 1 @@ -200,7 +200,7 @@ mod tests { }]; let case = CaseExpression::new(DataType::Int32, when_clauses, None); let (input, expected) = DataChunk::from_pretty( - "B f + "B i t 1 f . t 1 diff --git a/src/expr/core/src/sig/func.rs b/src/expr/core/src/sig/func.rs index e8e0d19ec11d7..f6557686c8ca9 100644 --- a/src/expr/core/src/sig/func.rs +++ b/src/expr/core/src/sig/func.rs @@ -115,102 +115,3 @@ pub unsafe fn _register(desc: FuncSign) { /// vector. The calls are guaranteed to be sequential. The vector will be drained and moved into /// `FUNC_SIG_MAP` on the first access of `FUNC_SIG_MAP`. static mut FUNC_SIG_MAP_INIT: Vec = Vec::new(); - -#[cfg(test)] -mod tests { - use std::collections::BTreeMap; - - use itertools::Itertools; - - use super::*; - - #[test] - fn test_func_sig_map() { - // convert FUNC_SIG_MAP to a more convenient map for testing - let mut new_map: BTreeMap, Vec>> = - BTreeMap::new(); - for (func, sigs) in &FUNC_SIG_MAP.0 { - for sig in sigs { - // validate the FUNC_SIG_MAP is consistent - assert_eq!(func, &sig.func); - // exclude deprecated functions - if sig.deprecated { - continue; - } - - new_map - .entry(*func) - .or_default() - .entry(sig.inputs_type.to_vec()) - .or_default() - .push(sig.clone()); - } - } - - let duplicated: BTreeMap<_, Vec<_>> = new_map - .into_iter() - .filter_map(|(k, funcs_with_same_name)| { - let funcs_with_same_name_type: Vec<_> = funcs_with_same_name - .into_values() - .filter_map(|v| { - if v.len() > 1 { - Some( - format!( - "{:}({:?}) -> {:?}", - v[0].func.as_str_name(), - v[0].inputs_type.iter().format(", "), - v.iter().map(|sig| sig.ret_type).format("/") - ) - .to_ascii_lowercase(), - ) - } else { - None - } - }) - .collect(); - if !funcs_with_same_name_type.is_empty() { - Some((k, funcs_with_same_name_type)) - } else { - None - } - }) - .collect(); - - // This snapshot shows the function signatures without a unique match. Frontend has to - // handle them specially without relying on FuncSigMap. - let expected = expect_test::expect![[r#" - { - Cast: [ - "cast(boolean) -> int32/varchar", - "cast(int16) -> int256/decimal/float64/float32/int64/int32/varchar", - "cast(int32) -> int256/int16/decimal/float64/float32/int64/boolean/varchar", - "cast(int64) -> int256/int32/int16/decimal/float64/float32/varchar", - "cast(float32) -> decimal/int64/int32/int16/float64/varchar", - "cast(float64) -> decimal/float32/int64/int32/int16/varchar", - "cast(decimal) -> float64/float32/int64/int32/int16/varchar", - "cast(date) -> timestamp/varchar", - "cast(varchar) -> date/time/timestamp/jsonb/interval/int256/float32/float64/decimal/int16/int32/int64/varchar/boolean/bytea/list", - "cast(time) -> interval/varchar", - "cast(timestamp) -> date/time/varchar", - "cast(interval) -> time/varchar", - "cast(list) -> varchar/list", - "cast(jsonb) -> boolean/float64/float32/decimal/int64/int32/int16/varchar", - "cast(int256) -> float64/varchar", - ], - ArrayAccess: [ - "array_access(list, int32) -> boolean/int16/int32/int64/int256/float32/float64/decimal/serial/date/time/timestamp/timestamptz/interval/varchar/bytea/jsonb/list/struct", - ], - ArrayMin: [ - "array_min(list) -> bytea/varchar/timestamptz/timestamp/time/date/int256/serial/decimal/float32/float64/int16/int32/int64", - ], - ArrayMax: [ - "array_max(list) -> bytea/varchar/timestamptz/timestamp/time/date/int256/serial/decimal/float32/float64/int16/int32/int64", - ], - ArraySum: [ - "array_sum(list) -> interval/decimal/float64/float32/int64", - ], - } - "#]]; - expected.assert_debug_eq(&duplicated); - } -} diff --git a/src/expr/impl/src/table_function/mod.rs b/src/expr/impl/src/table_function/mod.rs index 6c38623db2567..ea46bebb5471e 100644 --- a/src/expr/impl/src/table_function/mod.rs +++ b/src/expr/impl/src/table_function/mod.rs @@ -15,5 +15,6 @@ mod generate_series; mod generate_subscripts; mod jsonb; +mod pg_expandarray; mod regexp_matches; mod unnest; diff --git a/src/expr/impl/src/table_function/pg_expandarray.rs b/src/expr/impl/src/table_function/pg_expandarray.rs index a302e0dea9c3e..4ed8516921654 100644 --- a/src/expr/impl/src/table_function/pg_expandarray.rs +++ b/src/expr/impl/src/table_function/pg_expandarray.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use risingwave_common::types::{ListRef, ScalarRefImpl, StructType}; -use risingwave_expr::function; +use risingwave_common::types::{DataType, ListRef, ScalarRefImpl, StructType}; +use risingwave_expr::{function, Result}; /// Returns the input array as a set of rows with an index. /// @@ -33,7 +33,7 @@ use risingwave_expr::function; /// three 3 /// ``` #[function( - "_pg_expandarray(list) -> setof struct", + "_pg_expandarray(list) -> setof struct", type_infer = "infer_type" )] fn _pg_expandarray(array: ListRef<'_>) -> impl Iterator>, i32)> { diff --git a/src/expr/impl/tests/sig.rs b/src/expr/impl/tests/sig.rs new file mode 100644 index 0000000000000..34a4bf16beba2 --- /dev/null +++ b/src/expr/impl/tests/sig.rs @@ -0,0 +1,107 @@ +// 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 std::collections::BTreeMap; + +risingwave_expr_impl::enable!(); + +use itertools::Itertools; +use risingwave_common::types::DataTypeName; +use risingwave_expr::sig::func::{func_sigs, FuncSign}; +use risingwave_pb::expr::expr_node::PbType; + +#[test] +fn test_func_sig_map() { + // convert FUNC_SIG_MAP to a more convenient map for testing + let mut new_map: BTreeMap, Vec>> = BTreeMap::new(); + for sig in func_sigs() { + // exclude deprecated functions + if sig.deprecated { + continue; + } + + new_map + .entry(sig.func) + .or_default() + .entry(sig.inputs_type.to_vec()) + .or_default() + .push(sig.clone()); + } + + let duplicated: BTreeMap<_, Vec<_>> = new_map + .into_iter() + .filter_map(|(k, funcs_with_same_name)| { + let funcs_with_same_name_type: Vec<_> = funcs_with_same_name + .into_values() + .filter_map(|v| { + if v.len() > 1 { + Some( + format!( + "{:}({:?}) -> {:?}", + v[0].func.as_str_name(), + v[0].inputs_type.iter().format(", "), + v.iter().map(|sig| sig.ret_type).format("/") + ) + .to_ascii_lowercase(), + ) + } else { + None + } + }) + .collect(); + if !funcs_with_same_name_type.is_empty() { + Some((k, funcs_with_same_name_type)) + } else { + None + } + }) + .collect(); + + // This snapshot shows the function signatures without a unique match. Frontend has to + // handle them specially without relying on FuncSigMap. + let expected = expect_test::expect![[r#" + { + Cast: [ + "cast(boolean) -> int32/varchar", + "cast(int16) -> int256/decimal/float64/float32/int64/int32/varchar", + "cast(int32) -> int256/int16/decimal/float64/float32/int64/boolean/varchar", + "cast(int64) -> int256/int32/int16/decimal/float64/float32/varchar", + "cast(float32) -> decimal/int64/int32/int16/float64/varchar", + "cast(float64) -> decimal/float32/int64/int32/int16/varchar", + "cast(decimal) -> float64/float32/int64/int32/int16/varchar", + "cast(date) -> timestamp/varchar", + "cast(varchar) -> jsonb/interval/timestamp/time/date/int256/float32/float64/decimal/int16/int32/int64/varchar/boolean/bytea/list", + "cast(time) -> interval/varchar", + "cast(timestamp) -> time/date/varchar", + "cast(interval) -> time/varchar", + "cast(list) -> varchar/list", + "cast(jsonb) -> boolean/float64/float32/decimal/int64/int32/int16/varchar", + "cast(int256) -> float64/varchar", + ], + ArrayAccess: [ + "array_access(list, int32) -> boolean/int16/int32/int64/int256/float32/float64/decimal/serial/date/time/timestamp/timestamptz/interval/varchar/bytea/jsonb/list/struct", + ], + ArrayMin: [ + "array_min(list) -> bytea/varchar/timestamptz/timestamp/time/date/int256/serial/decimal/float32/float64/int16/int32/int64", + ], + ArrayMax: [ + "array_max(list) -> bytea/varchar/timestamptz/timestamp/time/date/int256/serial/decimal/float32/float64/int16/int32/int64", + ], + ArraySum: [ + "array_sum(list) -> interval/decimal/float64/float32/int64", + ], + } + "#]]; + expected.assert_debug_eq(&duplicated); +}