risingwave_expr_impl/scalar/
concat_ws.rs1use std::fmt::Write;
16
17use risingwave_common::row::Row;
18use risingwave_common::types::ToText;
19use risingwave_expr::function;
20
21#[function("concat_ws(varchar, variadic anyarray) -> varchar")]
38fn concat_ws(sep: &str, vals: impl Row, writer: &mut impl Write) {
39 let mut string_iter = vals.iter().flatten();
40 if let Some(string) = string_iter.next() {
41 string.write(writer).unwrap();
42 }
43 for string in string_iter {
44 write!(writer, "{}", sep).unwrap();
45 string.write(writer).unwrap();
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use risingwave_common::array::DataChunk;
52 use risingwave_common::row::Row;
53 use risingwave_common::test_prelude::DataChunkTestExt;
54 use risingwave_common::types::ToOwnedDatum;
55 use risingwave_common::util::iter_util::ZipEqDebug;
56 use risingwave_expr::expr::build_from_pretty;
57
58 #[tokio::test]
59 async fn test_concat_ws() {
60 let concat_ws =
61 build_from_pretty("(concat_ws:varchar $0:varchar $1:varchar $2:varchar $3:varchar)");
62 let (input, expected) = DataChunk::from_pretty(
63 "T T T T T
64 , a b c a,b,c
65 , . b c b,c
66 . a b c .
67 , . . . (empty)
68 . . . . .",
69 )
70 .split_column_at(4);
71
72 let output = concat_ws.eval(&input).await.unwrap();
74 assert_eq!(&output, expected.column_at(0));
75
76 for (row, expected) in input.rows().zip_eq_debug(expected.rows()) {
78 let result = concat_ws.eval_row(&row.to_owned_row()).await.unwrap();
79 assert_eq!(result, expected.datum_at(0).to_owned_datum());
80 }
81 }
82}