risingwave_expr_impl/scalar/
array_transform.rs1use std::sync::Arc;
16
17use risingwave_common::array::{ArrayRef, DataChunk};
18use risingwave_common::row::OwnedRow;
19use risingwave_common::types::{DataType, Datum, ListValue, ScalarImpl};
20use risingwave_expr::expr::{
21 AsyncExpression, AsyncExpressionBoxExt, BoxedExpression, ExpressionInfo, SyncExpression,
22 SyncExpressionBoxExt,
23};
24use risingwave_expr::{Result, build_function};
25
26#[derive(Debug)]
27struct ArrayTransformExpression<E> {
28 array: E,
29 lambda: E,
30}
31
32impl<E: ExpressionInfo> ExpressionInfo for ArrayTransformExpression<E> {
33 fn return_type(&self) -> DataType {
34 DataType::list(self.lambda.return_type())
35 }
36}
37
38impl<E: SyncExpression> SyncExpression for ArrayTransformExpression<E> {
39 fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
40 let lambda_input = self.array.eval(input)?;
41 let lambda_input = Arc::unwrap_or_clone(lambda_input).into_list();
42 let new_list = lambda_input.map_inner_sync(|flatten_input| {
43 let flatten_len = flatten_input.len();
44 let chunk = DataChunk::new(vec![Arc::new(flatten_input)], flatten_len);
45 self.lambda.eval(&chunk).map(Arc::unwrap_or_clone)
46 })?;
47 Ok(Arc::new(new_list.into()))
48 }
49
50 fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
51 let lambda_input = self.array.eval_row(input)?;
52 let lambda_input = lambda_input.map(ScalarImpl::into_list);
53 if let Some(lambda_input) = lambda_input {
54 let len = lambda_input.len();
55 let chunk = DataChunk::new(vec![Arc::new(lambda_input.into_array())], len);
56 let new_vals = self.lambda.eval(&chunk)?;
57 let new_list = ListValue::new(Arc::unwrap_or_clone(new_vals));
58 Ok(Some(new_list.into()))
59 } else {
60 Ok(None)
61 }
62 }
63}
64
65impl<E: AsyncExpression> AsyncExpression for ArrayTransformExpression<E> {
66 async fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
67 let lambda_input = self.array.eval(input).await?;
68 let lambda_input = Arc::unwrap_or_clone(lambda_input).into_list();
69 let new_list = lambda_input
70 .map_inner(|flatten_input| async move {
71 let flatten_len = flatten_input.len();
72 let chunk = DataChunk::new(vec![Arc::new(flatten_input)], flatten_len);
73 self.lambda.eval(&chunk).await.map(Arc::unwrap_or_clone)
74 })
75 .await?;
76 Ok(Arc::new(new_list.into()))
77 }
78
79 async fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
80 let lambda_input = self.array.eval_row(input).await?;
81 let lambda_input = lambda_input.map(ScalarImpl::into_list);
82 if let Some(lambda_input) = lambda_input {
83 let len = lambda_input.len();
84 let chunk = DataChunk::new(vec![Arc::new(lambda_input.into_array())], len);
85 let new_vals = self.lambda.eval(&chunk).await?;
86 let new_list = ListValue::new(Arc::unwrap_or_clone(new_vals));
87 Ok(Some(new_list.into()))
88 } else {
89 Ok(None)
90 }
91 }
92}
93
94#[build_function("array_transform(anyarray, any) -> anyarray")]
95fn build(_: DataType, children: Vec<BoxedExpression>) -> Result<BoxedExpression> {
96 let [array, lambda] = <[BoxedExpression; 2]>::try_from(children).unwrap();
97 Ok(match (array, lambda) {
98 (BoxedExpression::Sync(array), BoxedExpression::Sync(lambda)) => {
99 ArrayTransformExpression { array, lambda }.boxed()
100 }
101 (array, lambda) => ArrayTransformExpression { array, lambda }.boxed(),
102 })
103}
104
105#[cfg(test)]
106mod tests {
107 use risingwave_common::array::{DataChunk, DataChunkTestExt};
108 use risingwave_common::row::Row;
109 use risingwave_common::types::ToOwnedDatum;
110 use risingwave_common::util::iter_util::ZipEqDebug;
111 use risingwave_expr::expr::build_from_pretty;
112
113 #[tokio::test]
114 async fn test_array_transform() {
115 let expr =
116 build_from_pretty("(array_transform:int4[] $0:int4[] (multiply:int4 $0:int4 2:int4))");
117 let (input, expected) = DataChunk::from_pretty(
118 "i[] i[]
119 {1,2,3} {2,4,6}",
120 )
121 .split_column_at(1);
122
123 let output = expr.eval(&input).await.unwrap();
125 assert_eq!(&output, expected.column_at(0));
126
127 for (row, expected) in input.rows().zip_eq_debug(expected.rows()) {
129 let result = expr.eval_row(&row.to_owned_row()).await.unwrap();
130 assert_eq!(result, expected.datum_at(0).to_owned_datum());
131 }
132 }
133}