risingwave_expr_impl/scalar/
coalesce.rs1use std::ops::BitAnd;
16use std::sync::Arc;
17
18use risingwave_common::array::{ArrayRef, DataChunk};
19use risingwave_common::row::OwnedRow;
20use risingwave_common::types::{DataType, Datum};
21use risingwave_expr::expr::{
22 AsyncExpression, AsyncExpressionBoxExt, BoxedExpression, ExpressionInfo, SyncExpression,
23 SyncExpressionBoxExt, try_into_sync_exprs,
24};
25use risingwave_expr::{Result, build_function};
26
27#[derive(Debug)]
28pub struct CoalesceExpression<E> {
29 return_type: DataType,
30 children: Vec<E>,
31}
32
33impl<E: ExpressionInfo> ExpressionInfo for CoalesceExpression<E> {
34 fn return_type(&self) -> DataType {
35 self.return_type.clone()
36 }
37}
38
39macro_rules! eval_coalesce {
40 ($mode:ident, $this:expr, $input:expr) => {{
41 let init_vis = $input.visibility();
42 let mut input = $input.clone();
43 let len = input.capacity();
44 let mut selection: Vec<Option<usize>> = vec![None; len];
45 let mut children_array = Vec::with_capacity($this.children.len());
46 for (child_idx, child) in $this.children.iter().enumerate() {
47 let res = risingwave_expr::forward!($mode, child, eval(&input))?;
48 let res_bitmap = res.null_bitmap();
49 let orig_vis = input.visibility();
50 for pos in orig_vis.bitand(res_bitmap).iter_ones() {
51 selection[pos] = Some(child_idx);
52 }
53 let new_vis = orig_vis & !res_bitmap;
54 input.set_visibility(new_vis);
55 children_array.push(res);
56 }
57 let mut builder = $this.return_type.create_array_builder(len);
58 for (i, sel) in selection.iter().enumerate() {
59 if init_vis.is_set(i)
60 && let Some(child_idx) = sel
61 {
62 builder.append(children_array[*child_idx].value_at(i));
63 } else {
64 builder.append_null()
65 }
66 }
67 Ok(Arc::new(builder.finish()))
68 }};
69}
70
71macro_rules! eval_row_coalesce {
72 ($mode:ident, $this:expr, $input:expr) => {{
73 for child in &$this.children {
74 let datum = risingwave_expr::forward!($mode, child, eval_row($input))?;
75 if datum.is_some() {
76 return Ok(datum);
77 }
78 }
79 Ok(None)
80 }};
81}
82
83impl<E: SyncExpression> SyncExpression for CoalesceExpression<E> {
84 fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
85 eval_coalesce!(sync, self, input)
86 }
87
88 fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
89 eval_row_coalesce!(sync, self, input)
90 }
91}
92
93impl<E: AsyncExpression> AsyncExpression for CoalesceExpression<E> {
94 async fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
95 eval_coalesce!(async, self, input)
96 }
97
98 async fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
99 eval_row_coalesce!(async, self, input)
100 }
101}
102
103#[build_function("coalesce(...) -> any", type_infer = "unreachable")]
104fn build(return_type: DataType, children: Vec<BoxedExpression>) -> Result<BoxedExpression> {
105 match try_into_sync_exprs(children) {
106 Ok(children) => Ok(CoalesceExpression {
107 return_type,
108 children,
109 }
110 .boxed()),
111 Err(children) => Ok(CoalesceExpression {
112 return_type,
113 children,
114 }
115 .boxed()),
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use risingwave_common::array::DataChunk;
122 use risingwave_common::row::Row;
123 use risingwave_common::test_prelude::DataChunkTestExt;
124 use risingwave_common::types::ToOwnedDatum;
125 use risingwave_common::util::iter_util::ZipEqDebug;
126 use risingwave_expr::expr::build_from_pretty;
127
128 #[tokio::test]
129 async fn test_coalesce_expr() {
130 let expr = build_from_pretty("(coalesce:int4 $0:int4 $1:int4 $2:int4)");
131 let (input, expected) = DataChunk::from_pretty(
132 "i i i i
133 1 . . 1
134 . 2 . 2
135 . . 3 3
136 . . . .",
137 )
138 .split_column_at(3);
139
140 let output = expr.eval(&input).await.unwrap();
142 assert_eq!(&output, expected.column_at(0));
143
144 for (row, expected) in input.rows().zip_eq_debug(expected.rows()) {
146 let result = expr.eval_row(&row.to_owned_row()).await.unwrap();
147 assert_eq!(result, expected.datum_at(0).to_owned_datum());
148 }
149 }
150}