1use std::sync::Arc;
16
17use risingwave_common::array::{Array, ArrayRef, BoolArray, DataChunk};
18use risingwave_common::row::OwnedRow;
19use risingwave_common::types::{DataType, Datum, Scalar, ScalarRefImpl};
20use risingwave_common::util::iter_util::ZipEqFast;
21use risingwave_common::{bail, ensure};
22use risingwave_pb::expr::expr_node::{RexNode, Type};
23use risingwave_pb::expr::{ExprNode, FunctionCall};
24
25use super::build::get_children_and_return_type;
26use super::{
27 AsyncExpression, AsyncExpressionBoxExt, BoxedExpression, BuildBoxed, ExpressionInfo,
28 SyncExpression, SyncExpressionBoxExt,
29};
30use crate::Result;
31
32#[derive(Debug)]
33pub struct SomeAllExpression<E> {
34 left_expr: E,
35 right_expr: E,
36 expr_type: Type,
37 func: E,
38}
39
40impl<E> SomeAllExpression<E> {
41 pub fn new(left_expr: E, right_expr: E, expr_type: Type, func: E) -> Self {
42 SomeAllExpression {
43 left_expr,
44 right_expr,
45 expr_type,
46 func,
47 }
48 }
49
50 fn resolve_bools(&self, bools: impl Iterator<Item = Option<bool>>) -> Option<bool> {
53 match self.expr_type {
54 Type::Some => {
55 let mut any_none = false;
56 for b in bools {
57 match b {
58 Some(true) => return Some(true),
59 Some(false) => continue,
60 None => any_none = true,
61 }
62 }
63 if any_none { None } else { Some(false) }
64 }
65 Type::All => {
66 let mut all_true = true;
67 for b in bools {
68 if b == Some(false) {
69 return Some(false);
70 }
71 if b != Some(true) {
72 all_true = false;
73 }
74 }
75 if all_true { Some(true) } else { None }
76 }
77 _ => unreachable!(),
78 }
79 }
80}
81
82impl<E: ExpressionInfo> ExpressionInfo for SomeAllExpression<E> {
83 fn return_type(&self) -> DataType {
84 DataType::Boolean
85 }
86}
87
88macro_rules! eval_some_all {
89 ($mode:ident, $this:expr, $data_chunk:expr) => {{
90 let arr_left = forward!($mode, $this.left_expr, eval($data_chunk))?;
91 let arr_right = forward!($mode, $this.right_expr, eval($data_chunk))?;
92 let mut num_array = Vec::with_capacity($data_chunk.capacity());
93
94 let arr_right_inner = arr_right.as_list();
95 let elem_type = arr_right_inner.data_type().into_list_elem();
96 let capacity = arr_right_inner.flatten().len();
97
98 let mut unfolded_arr_left_builder = arr_left.create_builder(capacity);
99 let mut unfolded_arr_right_builder = elem_type.create_array_builder(capacity);
100
101 let mut unfolded_left_right =
102 |left: Option<ScalarRefImpl<'_>>,
103 right: Option<ScalarRefImpl<'_>>,
104 num_array: &mut Vec<Option<usize>>| {
105 if right.is_none() {
106 num_array.push(None);
107 return;
108 }
109
110 let array = right.unwrap().into_list();
111 let flattened = array.flatten();
112 let len = flattened.len();
113 num_array.push(Some(len));
114 unfolded_arr_left_builder.append_n(len, left);
115 for item in flattened.iter() {
116 unfolded_arr_right_builder.append(item);
117 }
118 };
119
120 if $data_chunk.is_vis_compacted() {
121 for (left, right) in arr_left.iter().zip_eq_fast(arr_right.iter()) {
122 unfolded_left_right(left, right, &mut num_array);
123 }
124 } else {
125 for ((left, right), visible) in arr_left
126 .iter()
127 .zip_eq_fast(arr_right.iter())
128 .zip_eq_fast($data_chunk.visibility().iter())
129 {
130 if !visible {
131 num_array.push(None);
132 continue;
133 }
134 unfolded_left_right(left, right, &mut num_array);
135 }
136 }
137
138 assert_eq!(num_array.len(), $data_chunk.capacity());
139
140 let unfolded_arr_left = unfolded_arr_left_builder.finish();
141 let unfolded_arr_right = unfolded_arr_right_builder.finish();
142
143 assert_eq!(unfolded_arr_left.len(), unfolded_arr_right.len());
146 let unfolded_compact_len = unfolded_arr_left.len();
147
148 let data_chunk = DataChunk::new(
149 vec![unfolded_arr_left.into(), unfolded_arr_right.into()],
150 unfolded_compact_len,
151 );
152
153 let func_results = forward!($mode, $this.func, eval(&data_chunk))?;
154 let bools = func_results.as_bool();
155 let mut offset = 0;
156 Ok(Arc::new(
157 num_array
158 .into_iter()
159 .map(|num| match num {
160 Some(num) => {
161 let range = offset..offset + num;
162 offset += num;
163 $this.resolve_bools(range.map(|i| bools.value_at(i)))
164 }
165 None => None,
166 })
167 .collect::<BoolArray>()
168 .into(),
169 ))
170 }};
171}
172
173macro_rules! eval_row_some_all {
174 ($mode:ident, $this:expr, $row:expr) => {{
175 let datum_left = forward!($mode, $this.left_expr, eval_row($row))?;
176 let datum_right = forward!($mode, $this.right_expr, eval_row($row))?;
177 let Some(array_right) = datum_right else {
178 return Ok(None);
179 };
180 let array_right = array_right.into_list().into_array();
181 let len = array_right.len();
182
183 let array_left = {
185 let mut builder = $this.left_expr.return_type().create_array_builder(len);
186 builder.append_n(len, datum_left);
187 builder.finish().into_ref()
188 };
189
190 let chunk = DataChunk::new(vec![array_left, Arc::new(array_right)], len);
191 let bools = forward!($mode, $this.func, eval(&chunk))?;
192
193 Ok($this
194 .resolve_bools(bools.as_bool().iter())
195 .map(|b| b.to_scalar_value()))
196 }};
197}
198
199impl<E: SyncExpression> SyncExpression for SomeAllExpression<E> {
200 fn eval(&self, data_chunk: &DataChunk) -> Result<ArrayRef> {
201 eval_some_all!(sync, self, data_chunk)
202 }
203
204 fn eval_row(&self, row: &OwnedRow) -> Result<Datum> {
205 eval_row_some_all!(sync, self, row)
206 }
207}
208
209impl<E: AsyncExpression> AsyncExpression for SomeAllExpression<E> {
210 async fn eval(&self, data_chunk: &DataChunk) -> Result<ArrayRef> {
211 eval_some_all!(async, self, data_chunk)
212 }
213
214 async fn eval_row(&self, row: &OwnedRow) -> Result<Datum> {
215 eval_row_some_all!(async, self, row)
216 }
217}
218
219impl SomeAllExpression<BoxedExpression> {
220 fn build(
221 prost: &ExprNode,
222 build_child: impl Fn(&ExprNode) -> Result<BoxedExpression>,
223 ) -> Result<Self> {
224 let outer_expr_type = prost.get_function_type().unwrap();
225 let (outer_children, outer_return_type) = get_children_and_return_type(prost)?;
226 ensure!(matches!(outer_return_type, DataType::Boolean));
227
228 let mut inner_expr_type = outer_children[0].get_function_type().unwrap();
229 let (mut inner_children, mut inner_return_type) =
230 get_children_and_return_type(&outer_children[0])?;
231 let mut stack = vec![];
232 while inner_children.len() != 2 {
233 stack.push((inner_expr_type, inner_return_type));
234 inner_expr_type = inner_children[0].get_function_type().unwrap();
235 (inner_children, inner_return_type) = get_children_and_return_type(&inner_children[0])?;
236 }
237
238 let left_expr = build_child(&inner_children[0])?;
239 let right_expr = build_child(&inner_children[1])?;
240
241 let DataType::List(right_list_type) = right_expr.return_type() else {
242 bail!("Expect Array Type");
243 };
244 let right_expr_return_type = right_list_type.into_elem();
245
246 let eval_func = {
247 let left_expr_input_ref = ExprNode {
248 function_type: Type::Unspecified as i32,
249 return_type: Some(left_expr.return_type().to_protobuf()),
250 rex_node: Some(RexNode::InputRef(0)),
251 };
252 let right_expr_input_ref = ExprNode {
253 function_type: Type::Unspecified as i32,
254 return_type: Some(right_expr_return_type.to_protobuf()),
255 rex_node: Some(RexNode::InputRef(1)),
256 };
257 let mut root_expr_node = ExprNode {
258 function_type: inner_expr_type as i32,
259 return_type: Some(inner_return_type.to_protobuf()),
260 rex_node: Some(RexNode::FuncCall(FunctionCall {
261 children: vec![left_expr_input_ref, right_expr_input_ref],
262 })),
263 };
264 while let Some((expr_type, return_type)) = stack.pop() {
265 root_expr_node = ExprNode {
266 function_type: expr_type as i32,
267 return_type: Some(return_type.to_protobuf()),
268 rex_node: Some(RexNode::FuncCall(FunctionCall {
269 children: vec![root_expr_node],
270 })),
271 }
272 }
273 build_child(&root_expr_node)?
274 };
275
276 Ok(SomeAllExpression::new(
277 left_expr,
278 right_expr,
279 outer_expr_type,
280 eval_func,
281 ))
282 }
283}
284
285impl BuildBoxed for SomeAllExpression<BoxedExpression> {
286 fn build_boxed(
287 prost: &ExprNode,
288 build_child: impl Fn(&ExprNode) -> Result<BoxedExpression>,
289 ) -> Result<BoxedExpression> {
290 let expr = Self::build(prost, build_child)?;
291 Ok(match (expr.left_expr, expr.right_expr, expr.func) {
292 (
293 BoxedExpression::Sync(left_expr),
294 BoxedExpression::Sync(right_expr),
295 BoxedExpression::Sync(func),
296 ) => SomeAllExpression::new(left_expr, right_expr, expr.expr_type, func).boxed(),
297 (left_expr, right_expr, func) => {
298 SomeAllExpression::new(left_expr, right_expr, expr.expr_type, func).boxed()
299 }
300 })
301 }
302}
303
304#[cfg(test)]
305mod tests {
306 use risingwave_common::row::Row;
307 use risingwave_common::test_prelude::DataChunkTestExt;
308 use risingwave_common::types::ToOwnedDatum;
309 use risingwave_common::util::iter_util::ZipEqDebug;
310 use risingwave_expr::expr::build_from_pretty;
311
312 use super::*;
313
314 #[tokio::test]
315 async fn test_some() {
316 let expr = SomeAllExpression::new(
317 build_from_pretty("0:int4"),
318 build_from_pretty("$0:boolean"),
319 Type::Some,
320 build_from_pretty("$1:boolean"),
321 );
322 let (input, expected) = DataChunk::from_pretty(
323 "B[] B
324 . .
325 {} f
326 {NULL} .
327 {NULL,f} .
328 {NULL,t} t
329 {t,f} t
330 {f,t} t", )
332 .split_column_at(1);
333
334 let output = expr.eval(&input).await.unwrap();
336 assert_eq!(&output, expected.column_at(0));
337
338 for (row, expected) in input.rows().zip_eq_debug(expected.rows()) {
340 let result = expr.eval_row(&row.to_owned_row()).await.unwrap();
341 assert_eq!(result, expected.datum_at(0).to_owned_datum());
342 }
343 }
344
345 #[tokio::test]
346 async fn test_all() {
347 let expr = SomeAllExpression::new(
348 build_from_pretty("0:int4"),
349 build_from_pretty("$0:boolean"),
350 Type::All,
351 build_from_pretty("$1:boolean"),
352 );
353 let (input, expected) = DataChunk::from_pretty(
354 "B[] B
355 . .
356 {} t
357 {NULL} .
358 {NULL,t} .
359 {NULL,f} f
360 {f,f} f
361 {t} t", )
363 .split_column_at(1);
364
365 let output = expr.eval(&input).await.unwrap();
367 assert_eq!(&output, expected.column_at(0));
368
369 for (row, expected) in input.rows().zip_eq_debug(expected.rows()) {
371 let result = expr.eval_row(&row.to_owned_row()).await.unwrap();
372 assert_eq!(result, expected.datum_at(0).to_owned_datum());
373 }
374 }
375}