Skip to main content

risingwave_expr_macro/
gen.rs

1// Copyright 2023 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Generate code for the functions.
16
17use itertools::Itertools;
18use proc_macro2::{Ident, Span};
19use quote::{format_ident, quote};
20
21use super::*;
22
23impl FunctionAttr {
24    /// Expands the wildcard in function arguments or return type.
25    pub fn expand(&self) -> Vec<Self> {
26        // handle variadic argument
27        if self
28            .args
29            .last()
30            .is_some_and(|arg| arg.starts_with("variadic"))
31        {
32            // expand:  foo(a, b, variadic anyarray)
33            // to:      foo(a, b, ...)
34            //        + foo_variadic(a, b, anyarray)
35            let mut attrs = Vec::new();
36            attrs.extend(
37                FunctionAttr {
38                    args: {
39                        let mut args = self.args.clone();
40                        *args.last_mut().unwrap() = "...".to_owned();
41                        args
42                    },
43                    ..self.clone()
44                }
45                .expand(),
46            );
47            attrs.extend(
48                FunctionAttr {
49                    name: format!("{}_variadic", self.name),
50                    args: {
51                        let mut args = self.args.clone();
52                        let last = args.last_mut().unwrap();
53                        *last = last.strip_prefix("variadic ").unwrap().into();
54                        args
55                    },
56                    ..self.clone()
57                }
58                .expand(),
59            );
60            return attrs;
61        }
62        let args = self.args.iter().map(|ty| types::expand_type_wildcard(ty));
63        let ret = types::expand_type_wildcard(&self.ret);
64        let mut attrs = Vec::new();
65        for (args, mut ret) in args.multi_cartesian_product().cartesian_product(ret) {
66            if ret == "auto" {
67                ret = types::min_compatible_type(&args);
68            }
69            let attr = FunctionAttr {
70                args: args.iter().map(|s| s.to_string()).collect(),
71                ret: ret.to_owned(),
72                ..self.clone()
73            };
74            attrs.push(attr);
75        }
76        attrs
77    }
78
79    /// Generate the type infer function: `fn(&[DataType]) -> Result<DataType>`
80    fn generate_type_infer_fn(&self) -> Result<TokenStream2> {
81        if let Some(func) = &self.type_infer {
82            if func == "unreachable" {
83                return Ok(
84                    quote! { |_| unreachable!("type inference for this function should be specially handled in frontend, and should not call sig.type_infer") },
85                );
86            }
87            // use the user defined type inference function
88            return Ok(func.parse().unwrap());
89        } else if self.ret == "any" {
90            // TODO: if there are multiple "any", they should be the same type
91            if let Some(i) = self.args.iter().position(|t| t == "any") {
92                // infer as the type of "any" argument
93                return Ok(quote! { |args| Ok(args[#i].clone()) });
94            }
95            if let Some(i) = self.args.iter().position(|t| t == "anyarray") {
96                // infer as the element type of "anyarray" argument
97                return Ok(quote! { |args| Ok(args[#i].as_list_elem().clone()) });
98            }
99        } else if self.ret == "anyarray" {
100            if let Some(i) = self.args.iter().position(|t| t == "anyarray") {
101                // infer as the type of "anyarray" argument
102                return Ok(quote! { |args| Ok(args[#i].clone()) });
103            }
104            if let Some(i) = self.args.iter().position(|t| t == "any") {
105                // infer as the array type of "any" argument
106                return Ok(quote! { |args| Ok(DataType::list(args[#i].clone())) });
107            }
108        } else if self.ret == "struct" {
109            if let Some(i) = self.args.iter().position(|t| t == "struct") {
110                // infer as the type of "struct" argument
111                return Ok(quote! { |args| Ok(args[#i].clone()) });
112            }
113        } else if self.ret == "anymap" {
114            if let Some(i) = self.args.iter().position(|t| t == "anymap") {
115                // infer as the type of "anymap" argument
116                return Ok(quote! { |args| Ok(args[#i].clone()) });
117            }
118        } else {
119            // the return type is fixed
120            let ty = data_type(&self.ret);
121            return Ok(quote! { |_| Ok(#ty) });
122        }
123        Err(Error::new(
124            Span::call_site(),
125            "type inference function cannot be automatically derived. You should provide: `type_infer = \"|args| Ok(...)\"`",
126        ))
127    }
128
129    /// Generate a descriptor (`FuncSign`) of the scalar or table function.
130    ///
131    /// The types of arguments and return value should not contain wildcard.
132    ///
133    /// # Arguments
134    /// `build_fn`: whether the user provided a function is a build function.
135    /// (from the `#[build_function]` macro)
136    pub fn generate_function_descriptor(
137        &self,
138        user_fn: &UserFunctionAttr,
139        build_fn: bool,
140    ) -> Result<TokenStream2> {
141        if self.is_table_function {
142            return self.generate_table_function_descriptor(user_fn, build_fn);
143        }
144        let name = self.name.clone();
145        let variadic = matches!(self.args.last(), Some(t) if t == "...");
146        let args = match variadic {
147            true => &self.args[..self.args.len() - 1],
148            false => &self.args[..],
149        }
150        .iter()
151        .map(|ty| sig_data_type(ty))
152        .collect_vec();
153        let ret = sig_data_type(&self.ret);
154
155        let pb_type = format_ident!("{}", utils::to_camel_case(&name));
156        let ctor_name = format_ident!("{}", self.ident_name());
157        let build_fn = if build_fn {
158            let name = format_ident!("{}", user_fn.name);
159            quote! { #name }
160        } else if self.rewritten {
161            quote! { |_, _| Err(ExprError::UnsupportedFunction(#name.into())) }
162        } else {
163            // This is the core logic for `#[function]`
164            self.generate_build_scalar_function(user_fn, true)?
165        };
166        let type_infer_fn = self.generate_type_infer_fn()?;
167        let deprecated = self.deprecated;
168        let maybe_allow_deprecated = if deprecated {
169            quote! { #[allow(deprecated)] }
170        } else {
171            quote! {}
172        };
173
174        Ok(quote! {
175            #[risingwave_expr::codegen::linkme::distributed_slice(risingwave_expr::sig::FUNCTIONS)]
176            fn #ctor_name() -> risingwave_expr::sig::FuncSign {
177                use risingwave_common::types::{DataType, DataTypeName};
178                use risingwave_expr::sig::{FuncSign, SigDataType, FuncBuilder};
179
180                #maybe_allow_deprecated
181                FuncSign {
182                    name: risingwave_pb::expr::expr_node::Type::#pb_type.into(),
183                    inputs_type: vec![#(#args),*],
184                    variadic: #variadic,
185                    ret_type: #ret,
186                    build: FuncBuilder::Scalar(#build_fn),
187                    type_infer: #type_infer_fn,
188                    deprecated: #deprecated,
189                }
190            }
191        })
192    }
193
194    /// Generate a build function for the scalar function.
195    ///
196    /// If `optimize_const` is true, the function will be optimized for constant arguments,
197    /// and fallback to the general version if any argument is not constant.
198    fn generate_build_scalar_function(
199        &self,
200        user_fn: &UserFunctionAttr,
201        optimize_const: bool,
202    ) -> Result<TokenStream2> {
203        let variadic = matches!(self.args.last(), Some(t) if t == "...");
204        let num_args = self.args.len() - if variadic { 1 } else { 0 };
205        let fn_name = format_ident!("{}", user_fn.name);
206        let struct_name = match optimize_const {
207            true => format_ident!("{}OptimizeConst", utils::to_camel_case(&self.ident_name())),
208            false => format_ident!("{}", utils::to_camel_case(&self.ident_name())),
209        };
210        let async_struct_name = format_ident!("Async{}", struct_name);
211
212        // we divide all arguments into two groups: prebuilt and non-prebuilt.
213        // prebuilt arguments are collected from the "prebuild" field.
214        // let's say we have a function with 3 arguments: [0, 1, 2]
215        // and the prebuild field contains "$1".
216        // then we have:
217        //     prebuilt_indices = [1]
218        //     non_prebuilt_indices = [0, 2]
219        //
220        // if the const argument optimization is enabled, prebuilt arguments are
221        // evaluated at build time, thus the children only contain non-prebuilt arguments:
222        //     children_indices = [0, 2]
223        // otherwise, the children contain all arguments:
224        //     children_indices = [0, 1, 2]
225
226        let prebuilt_indices = match &self.prebuild {
227            Some(s) => (0..num_args)
228                .filter(|i| s.contains(&format!("${i}")))
229                .collect_vec(),
230            None => vec![],
231        };
232        let non_prebuilt_indices = match &self.prebuild {
233            Some(s) => (0..num_args)
234                .filter(|i| !s.contains(&format!("${i}")))
235                .collect_vec(),
236            _ => (0..num_args).collect_vec(),
237        };
238        let children_indices = match optimize_const {
239            #[allow(clippy::redundant_clone)] // false-positive
240            true => non_prebuilt_indices.clone(),
241            false => (0..num_args).collect_vec(),
242        };
243
244        /// Return a list of identifiers with the given prefix and indices.
245        fn idents(prefix: &str, indices: &[usize]) -> Vec<Ident> {
246            indices
247                .iter()
248                .map(|i| format_ident!("{prefix}{i}"))
249                .collect()
250        }
251        let inputs = idents("i", &children_indices);
252        let prebuilt_inputs = idents("i", &prebuilt_indices);
253        let non_prebuilt_inputs = idents("i", &non_prebuilt_indices);
254        let array_refs = idents("array", &children_indices);
255        let arrays = idents("a", &children_indices);
256        let datums = idents("v", &children_indices);
257        let arg_arrays = children_indices
258            .iter()
259            .map(|i| format_ident!("{}", types::array_type(&self.args[*i])));
260        let arg_arrays = arg_arrays.collect_vec();
261        let arg_types = children_indices.iter().map(|i| {
262            types::ref_type(&self.args[*i])
263                .parse::<TokenStream2>()
264                .unwrap()
265        });
266        let arg_types = arg_types.collect_vec();
267        let annotation: TokenStream2 = match user_fn.core_return_type.as_str() {
268            // add type annotation for functions that return generic types
269            "T" | "T1" | "T2" | "T3" => format!(": Option<{}>", types::owned_type(&self.ret))
270                .parse()
271                .unwrap(),
272            _ => quote! {},
273        };
274        let ret_array_type = format_ident!("{}", types::array_type(&self.ret));
275        let builder_type = format_ident!("{}Builder", types::array_type(&self.ret));
276        let prebuilt_arg_type = match &self.prebuild {
277            Some(s) if optimize_const => s.split("::").next().unwrap().parse().unwrap(),
278            _ => quote! { () },
279        };
280        let prebuilt_arg_value = match &self.prebuild {
281            // example:
282            // prebuild = "RegexContext::new($1)"
283            // return = "RegexContext::new(i1)"
284            Some(s) => s
285                .replace('$', "i")
286                .parse()
287                .expect("invalid prebuild syntax"),
288            None => quote! { () },
289        };
290        let prebuild_const = if self.prebuild.is_some() && optimize_const {
291            let build_general = self.generate_build_scalar_function(user_fn, false)?;
292            quote! {{
293                let build_general = #build_general;
294                #(
295                    // try to evaluate constant for prebuilt arguments
296                    let #prebuilt_inputs = match children[#prebuilt_indices].eval_const() {
297                        Ok(s) => s,
298                        // prebuilt argument is not constant, fallback to general
299                        Err(_) => return build_general(return_type, children),
300                    };
301                    // get reference to the constant value
302                    let #prebuilt_inputs = match &#prebuilt_inputs {
303                        Some(s) => s.as_scalar_ref_impl().try_into()?,
304                        // the function should always return null if any const argument is null
305                        None => return Ok(risingwave_expr::expr::LiteralExpression::new(
306                            return_type,
307                            None,
308                        ).boxed()),
309                    };
310                )*
311                #prebuilt_arg_value
312            }}
313        } else {
314            quote! { () }
315        };
316
317        // ensure the number of children matches the number of arguments
318        let check_children = match variadic {
319            true => quote! { risingwave_expr::ensure!(children.len() >= #num_args); },
320            false => quote! { risingwave_expr::ensure!(children.len() == #num_args); },
321        };
322
323        // evaluate variadic arguments in sync `eval`
324        let eval_variadic_sync = variadic.then(|| {
325            quote! {
326                let mut columns = Vec::with_capacity(self.children.len() - #num_args);
327                for child in &self.children[#num_args..] {
328                    columns.push(child.eval(input)?);
329                }
330                let variadic_input = DataChunk::new(columns, input.visibility().clone());
331            }
332        });
333        // evaluate variadic arguments in async `eval`
334        let eval_variadic_async = variadic.then(|| {
335            quote! {
336                let mut columns = Vec::with_capacity(self.children.len() - #num_args);
337                for child in &self.children[#num_args..] {
338                    columns.push(child.eval(input).await?);
339                }
340                let variadic_input = DataChunk::new(columns, input.visibility().clone());
341            }
342        });
343        // evaluate variadic arguments in sync `eval_row`
344        let eval_row_variadic_sync = variadic.then(|| {
345            quote! {
346                let mut row = Vec::with_capacity(self.children.len() - #num_args);
347                for child in &self.children[#num_args..] {
348                    row.push(child.eval_row(input)?);
349                }
350                let variadic_row = OwnedRow::new(row);
351            }
352        });
353        // evaluate variadic arguments in async `eval_row`
354        let eval_row_variadic_async = variadic.then(|| {
355            quote! {
356                let mut row = Vec::with_capacity(self.children.len() - #num_args);
357                for child in &self.children[#num_args..] {
358                    row.push(child.eval_row(input).await?);
359                }
360                let variadic_row = OwnedRow::new(row);
361            }
362        });
363
364        let generic = (self.ret == "boolean" && user_fn.generic == 3).then(|| {
365            // XXX: for generic compare functions, we need to specify the compatible type
366            let compatible_type = types::ref_type(types::min_compatible_type(&self.args))
367                .parse::<TokenStream2>()
368                .unwrap();
369            quote! { ::<_, _, #compatible_type> }
370        });
371        let prebuilt_arg = match (&self.prebuild, optimize_const) {
372            // use the prebuilt argument
373            (Some(_), true) => quote! { &self.prebuilt_arg, },
374            // build the argument on site
375            (Some(_), false) => quote! { &#prebuilt_arg_value, },
376            // no prebuilt argument
377            (None, _) => quote! {},
378        };
379        let variadic_args = variadic.then(|| quote! { &variadic_row, });
380        let context = user_fn.context.then(|| quote! { &self.context, });
381        let writer = user_fn
382            .writer_type_kind
383            .is_some()
384            .then(|| quote! { &mut writer, });
385        let await_ = user_fn.async_.then(|| quote! { .await });
386
387        let record_error = {
388            // Uniform arguments into `DatumRef`.
389            #[allow(clippy::disallowed_methods)] // allow zip
390            let inputs_args = inputs
391                .iter()
392                .zip(user_fn.args_option.iter())
393                .map(|(input, opt)| {
394                    if *opt {
395                        quote! { #input.map(|s| ScalarRefImpl::from(s)) }
396                    } else {
397                        quote! { Some(ScalarRefImpl::from(#input)) }
398                    }
399                });
400            let inputs_args = quote! {
401                let args: &[DatumRef<'_>] = &[#(#inputs_args),*];
402                let args = args.iter().copied();
403            };
404            let var_args = variadic.then(|| {
405                quote! {
406                    let args = args.chain(variadic_row.iter());
407                }
408            });
409
410            quote! {
411                #inputs_args
412                #var_args
413                errors.push(ExprError::function(
414                    stringify!(#fn_name),
415                    args,
416                    e,
417                ));
418            }
419        };
420
421        // call the user defined function
422        // inputs: [ Option<impl ScalarRef> ]
423        let mut output = quote! { #fn_name #generic(
424            #(#non_prebuilt_inputs,)*
425            #variadic_args
426            #prebuilt_arg
427            #context
428            #writer
429        ) #await_ };
430        // handle error if the function returns `Result`
431        // wrap a `Some` if the function doesn't return `Option`
432        output = match user_fn.return_type_kind {
433            // XXX: we don't support void type yet. return null::int for now.
434            _ if self.ret == "void" => quote! { { #output; Option::<i32>::None } },
435            ReturnTypeKind::T => quote! { Some(#output) },
436            ReturnTypeKind::Option => output,
437            ReturnTypeKind::Result => quote! {
438                match #output {
439                    Ok(x) => Some(x),
440                    Err(e) => {
441                        #record_error
442                        None
443                    }
444                }
445            },
446            ReturnTypeKind::ResultOption => quote! {
447                match #output {
448                    Ok(x) => x,
449                    Err(e) => {
450                        #record_error
451                        None
452                    }
453                }
454            },
455        };
456        // if user function accepts non-option arguments, we assume the function
457        // returns null on null input, so we need to unwrap the inputs before calling.
458        if self.prebuild.is_some() {
459            output = quote! {
460                match (#(#inputs,)*) {
461                    (#(Some(#inputs),)*) => #output,
462                    _ => None,
463                }
464            };
465        } else {
466            #[allow(clippy::disallowed_methods)] // allow zip
467            let some_inputs = inputs
468                .iter()
469                .zip(user_fn.args_option.iter())
470                .map(|(input, opt)| {
471                    if *opt {
472                        quote! { #input }
473                    } else {
474                        quote! { Some(#input) }
475                    }
476                });
477            output = quote! {
478                match (#(#inputs,)*) {
479                    (#(#some_inputs,)*) => #output,
480                    _ => None,
481                }
482            };
483        };
484        // now the `output` is: Option<impl ScalarRef or Scalar>
485        let append_output = match user_fn.writer_type_kind {
486            Some(WriterTypeKind::FmtWrite)
487            | Some(WriterTypeKind::IoWrite)
488            | Some(WriterTypeKind::ListWrite) => quote! {{
489                let mut writer = builder.writer();
490                if #output.is_some() {
491                    writer.finish();
492                } else {
493                    writer.rollback();
494                    builder.append_null();
495                }
496            }},
497            Some(WriterTypeKind::JsonbbBuilder) => quote! {{
498                let mut writer_wrapper = builder.writer();
499                let mut writer = writer_wrapper.inner();
500                if #output.is_some() {
501                    writer_wrapper.finish();
502                } else {
503                    writer_wrapper.rollback();
504                    builder.append_null();
505                }
506            }},
507            None if user_fn.core_return_type == "impl AsRef < [u8] >" => quote! {
508                builder.append(#output.as_ref().map(|s| s.as_ref()));
509            },
510            None => quote! {
511                let output #annotation = #output;
512                builder.append(output.as_ref().map(|s| s.as_scalar_ref()));
513            },
514        };
515        // the output expression in `eval_row`
516        let row_output = match user_fn.writer_type_kind {
517            Some(WriterTypeKind::FmtWrite) => quote! {{
518                let mut writer = String::new();
519                #output.map(|_| writer.into())
520            }},
521            Some(WriterTypeKind::IoWrite) => quote! {{
522                let mut writer = Vec::new();
523                #output.map(|_| writer.into())
524            }},
525            Some(WriterTypeKind::JsonbbBuilder) => quote! {{
526                let mut writer = jsonbb::Builder::<Vec<u8>>::new();
527                #output.map(|_| JsonbVal::from(writer.finish()).into())
528            }},
529            Some(WriterTypeKind::ListWrite) => quote! {{
530                let mut writer = {
531                    let DataType::List(list_ty) = &self.context.return_type else {
532                        panic!("data type must be DataType::List");
533                    };
534                    list_ty.elem().create_array_builder(1)
535                };
536                #output.map(|_| ListValue::new(writer.finish()).into())
537            }},
538            None if user_fn.core_return_type == "impl AsRef < [u8] >" => quote! {
539                #output.map(|s| s.as_ref().into())
540            },
541            None => quote! {{
542                let output #annotation = #output;
543                output.map(|s| s.into())
544            }},
545        };
546        // the main body in `eval`
547        let eval = if let Some(batch_fn) = &self.batch_fn {
548            assert!(
549                !variadic,
550                "customized batch function is not supported for variadic functions"
551            );
552            // user defined batch function
553            let fn_name = format_ident!("{}", batch_fn);
554            quote! {
555                let c = #fn_name(#(#arrays),*);
556                Arc::new(c.into())
557            }
558        } else if (types::is_primitive(&self.ret) || self.ret == "boolean")
559            && user_fn.is_pure()
560            && !variadic
561            && self.prebuild.is_none()
562        {
563            // SIMD optimization for primitive types
564            match self.args.len() {
565                0 => quote! {
566                    let c = #ret_array_type::from_iter_bitmap(
567                        std::iter::repeat_with(|| #fn_name()).take(input.capacity()),
568                        Bitmap::ones(input.capacity()),
569                    );
570                    Arc::new(c.into())
571                },
572                1 => quote! {
573                    let c = #ret_array_type::from_iter_bitmap(
574                        a0.raw_iter().map(|a| #fn_name(a)),
575                        a0.null_bitmap().clone()
576                    );
577                    Arc::new(c.into())
578                },
579                2 => quote! {
580                    // allow using `zip` for performance
581                    #[allow(clippy::disallowed_methods)]
582                    let c = #ret_array_type::from_iter_bitmap(
583                        a0.raw_iter()
584                            .zip(a1.raw_iter())
585                            .map(|(a, b)| #fn_name #generic(a, b)),
586                        a0.null_bitmap() & a1.null_bitmap(),
587                    );
588                    Arc::new(c.into())
589                },
590                n => todo!("SIMD optimization for {n} arguments"),
591            }
592        } else {
593            // no optimization
594            let let_variadic = variadic.then(|| {
595                quote! {
596                    let variadic_row = variadic_input.row_at_unchecked_vis(i);
597                }
598            });
599            quote! {
600                let mut builder = #builder_type::with_type(input.capacity(), self.context.return_type.clone());
601
602                if input.is_vis_compacted() {
603                    for i in 0..input.capacity() {
604                        #(let #inputs = unsafe { #arrays.value_at_unchecked(i) };)*
605                        #let_variadic
606                        #append_output
607                    }
608                } else {
609                    for i in 0..input.capacity() {
610                        if unsafe { !input.visibility().is_set_unchecked(i) } {
611                            builder.append_null();
612                            continue;
613                        }
614                        #(let #inputs = unsafe { #arrays.value_at_unchecked(i) };)*
615                        #let_variadic
616                        #append_output
617                    }
618                }
619                Arc::new(builder.finish().into())
620            }
621        };
622
623        let sync_impl = if user_fn.async_ {
624            quote! {}
625        } else {
626            quote! {
627                #[derive(Debug)]
628                struct #struct_name {
629                    context: Context,
630                    children: Vec<Arc<dyn risingwave_expr::expr::SyncExpression>>,
631                    prebuilt_arg: #prebuilt_arg_type,
632                }
633                impl risingwave_expr::expr::ExpressionInfo for #struct_name {
634                    fn return_type(&self) -> DataType {
635                        self.context.return_type.clone()
636                    }
637                }
638                impl risingwave_expr::expr::SyncExpression for #struct_name {
639                    fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
640                        #(
641                            let #array_refs = self.children[#children_indices].eval(input)?;
642                            let #arrays: &#arg_arrays = #array_refs.as_ref().into();
643                        )*
644                        #eval_variadic_sync
645                        let mut errors = vec![];
646                        let array = { #eval };
647                        if errors.is_empty() {
648                            Ok(array)
649                        } else {
650                            Err(ExprError::Multiple(array, errors.into()))
651                        }
652                    }
653                    fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
654                        #(
655                            let #datums = self.children[#children_indices].eval_row(input)?;
656                            let #inputs: Option<#arg_types> = #datums.as_ref().map(|s| s.as_scalar_ref_impl().try_into().unwrap());
657                        )*
658                        #eval_row_variadic_sync
659                        let mut errors: Vec<ExprError> = vec![];
660                        let output = #row_output;
661                        if let Some(err) = errors.into_iter().next() {
662                            Err(err.into())
663                        } else {
664                            Ok(output)
665                        }
666                    }
667                }
668            }
669        };
670        let build_sync = if user_fn.async_ {
671            quote! {}
672        } else {
673            quote! {
674                use risingwave_expr::expr::try_into_sync_exprs;
675
676                let children = match try_into_sync_exprs(children) {
677                    Ok(children) => {
678                        return Ok(#struct_name {
679                            context,
680                            children,
681                            prebuilt_arg,
682                        }.boxed());
683                    }
684                    Err(children) => children,
685                };
686            }
687        };
688
689        Ok(quote! {
690            |return_type: DataType, children: Vec<risingwave_expr::expr::BoxedExpression>|
691                -> risingwave_expr::Result<risingwave_expr::expr::BoxedExpression>
692            {
693                use std::sync::Arc;
694                use risingwave_common::array::*;
695                use risingwave_common::types::*;
696                use risingwave_common::bitmap::Bitmap;
697                use risingwave_common::row::OwnedRow;
698                use risingwave_common::util::iter_util::ZipEqFast;
699
700                use risingwave_expr::expr::{Context, BoxedExpression, SyncExpressionBoxExt, AsyncExpressionBoxExt};
701                use risingwave_expr::{ExprError, Result};
702                use risingwave_expr::codegen::*;
703
704                #check_children
705                let prebuilt_arg = #prebuild_const;
706                let context = Context {
707                    return_type,
708                    arg_types: children.iter().map(|c| c.return_type()).collect(),
709                    variadic: #variadic,
710                };
711
712                #sync_impl
713
714                #[derive(Debug)]
715                struct #async_struct_name {
716                    context: Context,
717                    children: Vec<BoxedExpression>,
718                    prebuilt_arg: #prebuilt_arg_type,
719                }
720                impl risingwave_expr::expr::ExpressionInfo for #async_struct_name {
721                    fn return_type(&self) -> DataType {
722                        self.context.return_type.clone()
723                    }
724                }
725                impl risingwave_expr::expr::AsyncExpression for #async_struct_name {
726                    async fn eval(&self, input: &DataChunk) -> Result<ArrayRef> {
727                        #(
728                            let #array_refs = self.children[#children_indices].eval(input).await?;
729                            let #arrays: &#arg_arrays = #array_refs.as_ref().into();
730                        )*
731                        #eval_variadic_async
732                        let mut errors = vec![];
733                        let array = { #eval };
734                        if errors.is_empty() {
735                            Ok(array)
736                        } else {
737                            Err(ExprError::Multiple(array, errors.into()))
738                        }
739                    }
740                    async fn eval_row(&self, input: &OwnedRow) -> Result<Datum> {
741                        #(
742                            let #datums = self.children[#children_indices].eval_row(input).await?;
743                            let #inputs: Option<#arg_types> = #datums.as_ref().map(|s| s.as_scalar_ref_impl().try_into().unwrap());
744                        )*
745                        #eval_row_variadic_async
746                        let mut errors: Vec<ExprError> = vec![];
747                        let output = #row_output;
748                        if let Some(err) = errors.into_iter().next() {
749                            Err(err.into())
750                        } else {
751                            Ok(output)
752                        }
753                    }
754                }
755
756                #build_sync
757
758                Ok(#async_struct_name {
759                    context,
760                    children,
761                    prebuilt_arg,
762                }.boxed())
763            }
764        })
765    }
766
767    /// Generate a descriptor of the aggregate function.
768    ///
769    /// The types of arguments and return value should not contain wildcard.
770    /// `user_fn` could be either `fn` or `impl`.
771    /// If `build_fn` is true, `user_fn` must be a `fn` that builds the aggregate function.
772    pub fn generate_aggregate_descriptor(
773        &self,
774        user_fn: &AggregateFnOrImpl,
775        build_fn: bool,
776    ) -> Result<TokenStream2> {
777        let name = self.name.clone();
778
779        let mut args = Vec::with_capacity(self.args.len());
780        for ty in &self.args {
781            args.push(sig_data_type(ty));
782        }
783        let ret = sig_data_type(&self.ret);
784        let state_type = match &self.state {
785            Some(ty) if ty != "ref" => {
786                let ty = data_type(ty);
787                quote! { Some(#ty) }
788            }
789            _ => quote! { None },
790        };
791        let append_only = match build_fn {
792            false => !user_fn.has_retract(),
793            true => self.append_only,
794        };
795
796        let pb_kind = format_ident!("{}", utils::to_camel_case(&name));
797        let ctor_name = match append_only {
798            false => format_ident!("{}", self.ident_name()),
799            true => format_ident!("{}_append_only", self.ident_name()),
800        };
801        let build_fn = if build_fn {
802            let name = format_ident!("{}", user_fn.as_fn().name);
803            quote! { #name }
804        } else if self.rewritten {
805            quote! { |_| Err(ExprError::UnsupportedFunction(#name.into())) }
806        } else {
807            self.generate_agg_build_fn(user_fn)?
808        };
809        let build_retractable = match append_only {
810            true => quote! { None },
811            false => quote! { Some(#build_fn) },
812        };
813        let build_append_only = match append_only {
814            false => quote! { None },
815            true => quote! { Some(#build_fn) },
816        };
817        let retractable_state_type = match append_only {
818            true => quote! { None },
819            false => state_type.clone(),
820        };
821        let append_only_state_type = match append_only {
822            false => quote! { None },
823            true => state_type,
824        };
825        let type_infer_fn = self.generate_type_infer_fn()?;
826        let deprecated = self.deprecated;
827        let maybe_allow_deprecated = if deprecated {
828            quote! { #[allow(deprecated)] }
829        } else {
830            quote! {}
831        };
832
833        Ok(quote! {
834            #[risingwave_expr::codegen::linkme::distributed_slice(risingwave_expr::sig::FUNCTIONS)]
835            fn #ctor_name() -> risingwave_expr::sig::FuncSign {
836                use risingwave_common::types::{DataType, DataTypeName};
837                use risingwave_expr::sig::{FuncSign, SigDataType, FuncBuilder};
838
839                #maybe_allow_deprecated
840                FuncSign {
841                    name: risingwave_pb::expr::agg_call::PbKind::#pb_kind.into(),
842                    inputs_type: vec![#(#args),*],
843                    variadic: false,
844                    ret_type: #ret,
845                    build: FuncBuilder::Aggregate {
846                        retractable: #build_retractable,
847                        append_only: #build_append_only,
848                        retractable_state_type: #retractable_state_type,
849                        append_only_state_type: #append_only_state_type,
850                    },
851                    type_infer: #type_infer_fn,
852                    deprecated: #deprecated,
853                }
854            }
855        })
856    }
857
858    /// Generate build function for aggregate function.
859    fn generate_agg_build_fn(&self, user_fn: &AggregateFnOrImpl) -> Result<TokenStream2> {
860        // If the first argument of the aggregate function is of type `&mut T`,
861        // we assume it is a user defined state type.
862        let custom_state = user_fn.accumulate().first_mut_ref_arg.as_ref();
863        let state_type: TokenStream2 = match (custom_state, &self.state) {
864            (Some(s), _) => s.parse().unwrap(),
865            (_, Some(state)) if state == "ref" => types::ref_type(&self.ret).parse().unwrap(),
866            (_, Some(state)) if state != "ref" => types::owned_type(state).parse().unwrap(),
867            _ => types::owned_type(&self.ret).parse().unwrap(),
868        };
869        let let_arrays = self
870            .args
871            .iter()
872            .enumerate()
873            .map(|(i, arg)| {
874                let array = format_ident!("a{i}");
875                let array_type: TokenStream2 = types::array_type(arg).parse().unwrap();
876                quote! {
877                    let #array: &#array_type = input.column_at(#i).as_ref().into();
878                }
879            })
880            .collect_vec();
881        let let_values = (0..self.args.len())
882            .map(|i| {
883                let v = format_ident!("v{i}");
884                let a = format_ident!("a{i}");
885                quote! { let #v = unsafe { #a.value_at_unchecked(row_id) }; }
886            })
887            .collect_vec();
888        let downcast_state = if custom_state.is_some() {
889            quote! { let mut state: &mut #state_type = state0.downcast_mut(); }
890        } else if let Some(s) = &self.state
891            && s == "ref"
892        {
893            quote! { let mut state: Option<#state_type> = state0.as_datum_mut().as_ref().map(|x| x.as_scalar_ref_impl().try_into().unwrap()); }
894        } else {
895            quote! { let mut state: Option<#state_type> = state0.as_datum_mut().take().map(|s| s.try_into().unwrap()); }
896        };
897        let restore_state = if custom_state.is_some() {
898            quote! {}
899        } else if let Some(s) = &self.state
900            && s == "ref"
901        {
902            quote! { *state0.as_datum_mut() = state.map(|x| x.to_owned_scalar().into()); }
903        } else {
904            quote! { *state0.as_datum_mut() = state.map(|s| s.into()); }
905        };
906        let create_state = if custom_state.is_some() {
907            quote! {
908                fn create_state(&self) -> Result<AggregateState> {
909                    Ok(AggregateState::Any(Box::<#state_type>::default()))
910                }
911            }
912        } else if let Some(state) = &self.init_state {
913            let state: TokenStream2 = state.parse().unwrap();
914            quote! {
915                fn create_state(&self) -> Result<AggregateState> {
916                    Ok(AggregateState::Datum(Some(#state.into())))
917                }
918            }
919        } else {
920            // by default: `AggregateState::Datum(None)`
921            quote! {}
922        };
923        let args = (0..self.args.len()).map(|i| format_ident!("v{i}"));
924        let args = quote! { #(#args,)* };
925        let panic_on_retract = {
926            let msg = format!(
927                "attempt to retract on aggregate function {}, but it is append-only",
928                self.name
929            );
930            quote! { assert_eq!(op, Op::Insert, #msg); }
931        };
932        let mut next_state = match user_fn {
933            AggregateFnOrImpl::Fn(f) => {
934                let context = f.context.then(|| quote! { &self.context, });
935                let fn_name = format_ident!("{}", f.name);
936                match f.retract {
937                    true => {
938                        quote! { #fn_name(state, #args matches!(op, Op::Delete | Op::UpdateDelete) #context) }
939                    }
940                    false => quote! {{
941                        #panic_on_retract
942                        #fn_name(state, #args #context)
943                    }},
944                }
945            }
946            AggregateFnOrImpl::Impl(i) => {
947                let retract = match i.retract {
948                    Some(_) => quote! { self.function.retract(state, #args) },
949                    None => panic_on_retract,
950                };
951                quote! {
952                    if matches!(op, Op::Delete | Op::UpdateDelete) {
953                        #retract
954                    } else {
955                        self.function.accumulate(state, #args)
956                    }
957                }
958            }
959        };
960        next_state = match user_fn.accumulate().return_type_kind {
961            ReturnTypeKind::T => quote! { Some(#next_state) },
962            ReturnTypeKind::Option => next_state,
963            ReturnTypeKind::Result => quote! { Some(#next_state?) },
964            ReturnTypeKind::ResultOption => quote! { #next_state? },
965        };
966        if user_fn.accumulate().args_option.iter().all(|b| !b) {
967            match self.args.len() {
968                0 => {
969                    next_state = quote! {
970                        match state {
971                            Some(state) => #next_state,
972                            None => state,
973                        }
974                    };
975                }
976                1 => {
977                    let first_state = if self.init_state.is_some() {
978                        // for count, the state will never be None
979                        quote! { unreachable!() }
980                    } else if let Some(s) = &self.state
981                        && s == "ref"
982                    {
983                        // for min/max/first/last, the state is the first value
984                        quote! { Some(v0) }
985                    } else if let AggregateFnOrImpl::Impl(impl_) = user_fn
986                        && impl_.create_state.is_some()
987                    {
988                        // use user-defined create_state function
989                        quote! {{
990                            let state = self.function.create_state();
991                            #next_state
992                        }}
993                    } else {
994                        quote! {{
995                            let state = #state_type::default();
996                            #next_state
997                        }}
998                    };
999                    next_state = quote! {
1000                        match (state, v0) {
1001                            (Some(state), Some(v0)) => #next_state,
1002                            (None, Some(v0)) => #first_state,
1003                            (state, None) => state,
1004                        }
1005                    };
1006                }
1007                _ => todo!("multiple arguments are not supported for non-option function"),
1008            }
1009        }
1010        let update_state = if custom_state.is_some() {
1011            quote! { _ = #next_state; }
1012        } else {
1013            quote! { state = #next_state; }
1014        };
1015        let get_result = if custom_state.is_some() {
1016            quote! { Ok(state.downcast_ref::<#state_type>().into()) }
1017        } else if let AggregateFnOrImpl::Impl(impl_) = user_fn
1018            && impl_.finalize.is_some()
1019        {
1020            quote! {
1021                let state = match state.as_datum() {
1022                    Some(s) => s.as_scalar_ref_impl().try_into().unwrap(),
1023                    None => return Ok(None),
1024                };
1025                Ok(Some(self.function.finalize(state).into()))
1026            }
1027        } else {
1028            quote! { Ok(state.as_datum().clone()) }
1029        };
1030        let function_field = match user_fn {
1031            AggregateFnOrImpl::Fn(_) => quote! {},
1032            AggregateFnOrImpl::Impl(i) => {
1033                let struct_name = format_ident!("{}", i.struct_name);
1034                let generic = self.generic.as_ref().map(|g| {
1035                    let g = format_ident!("{g}");
1036                    quote! { <#g> }
1037                });
1038                quote! { function: #struct_name #generic, }
1039            }
1040        };
1041        let function_new = match user_fn {
1042            AggregateFnOrImpl::Fn(_) => quote! {},
1043            AggregateFnOrImpl::Impl(i) => {
1044                let struct_name = format_ident!("{}", i.struct_name);
1045                let generic = self.generic.as_ref().map(|g| {
1046                    let g = format_ident!("{g}");
1047                    quote! { ::<#g> }
1048                });
1049                quote! { function: #struct_name #generic :: default(), }
1050            }
1051        };
1052
1053        Ok(quote! {
1054            |agg| {
1055                use std::collections::HashSet;
1056                use std::ops::Range;
1057                use risingwave_common::array::*;
1058                use risingwave_common::types::*;
1059                use risingwave_common::bail;
1060                use risingwave_common::bitmap::Bitmap;
1061                use risingwave_common_estimate_size::EstimateSize;
1062
1063                use risingwave_expr::expr::Context;
1064                use risingwave_expr::Result;
1065                use risingwave_expr::aggregate::AggregateState;
1066                use risingwave_expr::codegen::async_trait;
1067
1068                let context = Context {
1069                    return_type: agg.return_type.clone(),
1070                    arg_types: agg.args.arg_types().to_owned(),
1071                    variadic: false,
1072                };
1073
1074                struct Agg {
1075                    context: Context,
1076                    #function_field
1077                }
1078
1079                #[async_trait]
1080                impl risingwave_expr::aggregate::AggregateFunction for Agg {
1081                    fn return_type(&self) -> DataType {
1082                        self.context.return_type.clone()
1083                    }
1084
1085                    #create_state
1086
1087                    async fn update(&self, state0: &mut AggregateState, input: &StreamChunk) -> Result<()> {
1088                        #(#let_arrays)*
1089                        #downcast_state
1090                        for row_id in input.visibility().iter_ones() {
1091                            let op = unsafe { *input.ops().get_unchecked(row_id) };
1092                            #(#let_values)*
1093                            #update_state
1094                        }
1095                        #restore_state
1096                        Ok(())
1097                    }
1098
1099                    async fn update_range(&self, state0: &mut AggregateState, input: &StreamChunk, range: Range<usize>) -> Result<()> {
1100                        assert!(range.end <= input.capacity());
1101                        #(#let_arrays)*
1102                        #downcast_state
1103                        if input.is_vis_compacted() {
1104                            for row_id in range {
1105                                let op = unsafe { *input.ops().get_unchecked(row_id) };
1106                                #(#let_values)*
1107                                #update_state
1108                            }
1109                        } else {
1110                            for row_id in input.visibility().iter_ones() {
1111                                if row_id < range.start {
1112                                    continue;
1113                                } else if row_id >= range.end {
1114                                    break;
1115                                }
1116                                let op = unsafe { *input.ops().get_unchecked(row_id) };
1117                                #(#let_values)*
1118                                #update_state
1119                            }
1120                        }
1121                        #restore_state
1122                        Ok(())
1123                    }
1124
1125                    async fn get_result(&self, state: &AggregateState) -> Result<Datum> {
1126                        #get_result
1127                    }
1128                }
1129
1130                Ok(Box::new(Agg {
1131                    context,
1132                    #function_new
1133                }))
1134            }
1135        })
1136    }
1137
1138    /// Generate a descriptor of the table function.
1139    ///
1140    /// The types of arguments and return value should not contain wildcard.
1141    fn generate_table_function_descriptor(
1142        &self,
1143        user_fn: &UserFunctionAttr,
1144        build_fn: bool,
1145    ) -> Result<TokenStream2> {
1146        let name = self.name.clone();
1147        let mut args = Vec::with_capacity(self.args.len());
1148        for ty in &self.args {
1149            args.push(sig_data_type(ty));
1150        }
1151        let ret = sig_data_type(&self.ret);
1152
1153        let pb_type = format_ident!("{}", utils::to_camel_case(&name));
1154        let ctor_name = format_ident!("{}", self.ident_name());
1155        let build_fn = if build_fn {
1156            let name = format_ident!("{}", user_fn.name);
1157            quote! { #name }
1158        } else if self.rewritten {
1159            quote! { |_, _| Err(ExprError::UnsupportedFunction(#name.into())) }
1160        } else {
1161            self.generate_build_table_function(user_fn)?
1162        };
1163        let type_infer_fn = self.generate_type_infer_fn()?;
1164        let deprecated = self.deprecated;
1165        let maybe_allow_deprecated = if deprecated {
1166            quote! { #[allow(deprecated)] }
1167        } else {
1168            quote! {}
1169        };
1170
1171        Ok(quote! {
1172            #[risingwave_expr::codegen::linkme::distributed_slice(risingwave_expr::sig::FUNCTIONS)]
1173            fn #ctor_name() -> risingwave_expr::sig::FuncSign {
1174                use risingwave_common::types::{DataType, DataTypeName};
1175                use risingwave_expr::sig::{FuncSign, SigDataType, FuncBuilder};
1176
1177                #maybe_allow_deprecated
1178                FuncSign {
1179                    name: risingwave_pb::expr::table_function::Type::#pb_type.into(),
1180                    inputs_type: vec![#(#args),*],
1181                    variadic: false,
1182                    ret_type: #ret,
1183                    build: FuncBuilder::Table(#build_fn),
1184                    type_infer: #type_infer_fn,
1185                    deprecated: #deprecated,
1186                }
1187            }
1188        })
1189    }
1190
1191    fn generate_build_table_function(&self, user_fn: &UserFunctionAttr) -> Result<TokenStream2> {
1192        let num_args = self.args.len();
1193        let return_types = output_types(&self.ret);
1194        let fn_name = format_ident!("{}", user_fn.name);
1195        let struct_name = format_ident!("{}", utils::to_camel_case(&self.ident_name()));
1196        let arg_ids = (0..num_args)
1197            .filter(|i| match &self.prebuild {
1198                Some(s) => !s.contains(&format!("${i}")),
1199                None => true,
1200            })
1201            .collect_vec();
1202        let const_ids = (0..num_args).filter(|i| match &self.prebuild {
1203            Some(s) => s.contains(&format!("${i}")),
1204            None => false,
1205        });
1206        let inputs: Vec<_> = arg_ids.iter().map(|i| format_ident!("i{i}")).collect();
1207        let all_child: Vec<_> = (0..num_args).map(|i| format_ident!("child{i}")).collect();
1208        let const_child: Vec<_> = const_ids.map(|i| format_ident!("child{i}")).collect();
1209        let child: Vec<_> = arg_ids.iter().map(|i| format_ident!("child{i}")).collect();
1210        let array_refs: Vec<_> = arg_ids.iter().map(|i| format_ident!("array{i}")).collect();
1211        let arrays: Vec<_> = arg_ids.iter().map(|i| format_ident!("a{i}")).collect();
1212        let arg_arrays = arg_ids
1213            .iter()
1214            .map(|i| format_ident!("{}", types::array_type(&self.args[*i])));
1215        let outputs = (0..return_types.len())
1216            .map(|i| format_ident!("o{i}"))
1217            .collect_vec();
1218        let builders = (0..return_types.len())
1219            .map(|i| format_ident!("builder{i}"))
1220            .collect_vec();
1221        let builder_types = return_types
1222            .iter()
1223            .map(|ty| format_ident!("{}Builder", types::array_type(ty)))
1224            .collect_vec();
1225        let return_types = if return_types.len() == 1 {
1226            vec![quote! { self.context.return_type.clone() }]
1227        } else {
1228            (0..return_types.len())
1229                .map(|i| quote! { self.context.return_type.as_struct().types().nth(#i).unwrap().clone() })
1230                .collect()
1231        };
1232        #[allow(clippy::disallowed_methods)]
1233        let optioned_outputs = user_fn
1234            .core_return_type
1235            .split(',')
1236            .map(|t| t.contains("Option"))
1237            // example: "(Option<&str>, i32)" => [true, false]
1238            .zip(&outputs)
1239            .map(|(optional, o)| match optional {
1240                false => quote! { Some(#o.as_scalar_ref()) },
1241                true => quote! { #o.map(|o| o.as_scalar_ref()) },
1242            })
1243            .collect_vec();
1244        let build_value_array = if return_types.len() == 1 {
1245            quote! { let [value_array] = value_arrays; }
1246        } else {
1247            quote! {
1248                let value_array = StructArray::new(
1249                    self.context.return_type.as_struct().clone(),
1250                    value_arrays.to_vec(),
1251                    Bitmap::ones(len),
1252                ).into_ref();
1253            }
1254        };
1255        let context = user_fn.context.then(|| quote! { &self.context, });
1256        let prebuilt_arg = match &self.prebuild {
1257            Some(_) => quote! { &self.prebuilt_arg, },
1258            None => quote! {},
1259        };
1260        let prebuilt_arg_type = match &self.prebuild {
1261            Some(s) => s.split("::").next().unwrap().parse().unwrap(),
1262            None => quote! { () },
1263        };
1264        let prebuilt_arg_value = match &self.prebuild {
1265            Some(s) => s
1266                .replace('$', "child")
1267                .parse()
1268                .expect("invalid prebuild syntax"),
1269            None => quote! { () },
1270        };
1271        let iter = quote! { #fn_name(#(#inputs,)* #prebuilt_arg #context) };
1272        let mut iter = match user_fn.return_type_kind {
1273            ReturnTypeKind::T => quote! { #iter },
1274            ReturnTypeKind::Option => quote! { match #iter {
1275                Some(it) => it,
1276                None => continue,
1277            } },
1278            ReturnTypeKind::Result => quote! { match #iter {
1279                Ok(it) => it,
1280                Err(e) => {
1281                    index_builder.append(Some(i as i32));
1282                    #(#builders.append_null();)*
1283                    error_builder.append_display(Some(e.as_report()));
1284                    continue;
1285                }
1286            } },
1287            ReturnTypeKind::ResultOption => quote! { match #iter {
1288                Ok(Some(it)) => it,
1289                Ok(None) => continue,
1290                Err(e) => {
1291                    index_builder.append(Some(i as i32));
1292                    #(#builders.append_null();)*
1293                    error_builder.append_display(Some(e.as_report()));
1294                    continue;
1295                }
1296            } },
1297        };
1298        // if user function accepts non-option arguments, we assume the function
1299        // returns empty on null input, so we need to unwrap the inputs before calling.
1300        #[allow(clippy::disallowed_methods)] // allow zip
1301        let some_inputs = inputs
1302            .iter()
1303            .zip(user_fn.args_option.iter())
1304            .map(|(input, opt)| {
1305                if *opt {
1306                    quote! { #input }
1307                } else {
1308                    quote! { Some(#input) }
1309                }
1310            });
1311        iter = quote! {
1312            match (#(#inputs,)*) {
1313                (#(#some_inputs,)*) => #iter,
1314                _ => continue,
1315            }
1316        };
1317        let iterator_item_type = user_fn.iterator_item_kind.clone().ok_or_else(|| {
1318            Error::new(
1319                user_fn.return_type_span,
1320                "expect `impl Iterator` in return type",
1321            )
1322        })?;
1323        let append_output = match iterator_item_type {
1324            ReturnTypeKind::T => quote! {
1325                let (#(#outputs),*) = output;
1326                #(#builders.append(#optioned_outputs);)* error_builder.append_null();
1327            },
1328            ReturnTypeKind::Option => quote! { match output {
1329                Some((#(#outputs),*)) => { #(#builders.append(#optioned_outputs);)* error_builder.append_null(); }
1330                None => { #(#builders.append_null();)* error_builder.append_null(); }
1331            } },
1332            ReturnTypeKind::Result => quote! { match output {
1333                Ok((#(#outputs),*)) => { #(#builders.append(#optioned_outputs);)* error_builder.append_null(); }
1334                Err(e) => { #(#builders.append_null();)* error_builder.append_display(Some(e.as_report())); }
1335            } },
1336            ReturnTypeKind::ResultOption => quote! { match output {
1337                Ok(Some((#(#outputs),*))) => { #(#builders.append(#optioned_outputs);)* error_builder.append_null(); }
1338                Ok(None) => { #(#builders.append_null();)* error_builder.append_null(); }
1339                Err(e) => { #(#builders.append_null();)* error_builder.append_display(Some(e.as_report())); }
1340            } },
1341        };
1342
1343        Ok(quote! {
1344            |return_type, chunk_size, children| {
1345                use risingwave_common::array::*;
1346                use risingwave_common::types::*;
1347                use risingwave_common::bitmap::Bitmap;
1348                use risingwave_common::util::iter_util::ZipEqFast;
1349                use risingwave_expr::expr::{BoxedExpression, Context};
1350                use risingwave_expr::{Result, ExprError};
1351                use risingwave_expr::codegen::*;
1352
1353                risingwave_expr::ensure!(children.len() == #num_args);
1354
1355                let context = Context {
1356                    return_type: return_type.clone(),
1357                    arg_types: children.iter().map(|c| c.return_type()).collect(),
1358                    variadic: false,
1359                };
1360
1361                let mut iter = children.into_iter();
1362                #(let #all_child = iter.next().unwrap();)*
1363                #(
1364                    let #const_child = #const_child.eval_const()?;
1365                    let #const_child = match &#const_child {
1366                        Some(s) => s.as_scalar_ref_impl().try_into()?,
1367                        // the function should always return empty if any const argument is null
1368                        None => return Ok(risingwave_expr::table_function::empty(return_type)),
1369                    };
1370                )*
1371
1372                #[derive(Debug)]
1373                struct #struct_name {
1374                    context: Context,
1375                    chunk_size: usize,
1376                    #(#child: BoxedExpression,)*
1377                    prebuilt_arg: #prebuilt_arg_type,
1378                }
1379                #[async_trait]
1380                impl risingwave_expr::table_function::TableFunction for #struct_name {
1381                    fn return_type(&self) -> DataType {
1382                        self.context.return_type.clone()
1383                    }
1384                    async fn eval<'a>(&'a self, input: &'a DataChunk) -> BoxStream<'a, Result<DataChunk>> {
1385                        self.eval_inner(input)
1386                    }
1387                }
1388                impl #struct_name {
1389                    #[try_stream(boxed, ok = DataChunk, error = ExprError)]
1390                    async fn eval_inner<'a>(&'a self, input: &'a DataChunk) {
1391                        #(
1392                        let #array_refs = self.#child.eval(input).await?;
1393                        let #arrays: &#arg_arrays = #array_refs.as_ref().into();
1394                        )*
1395
1396                        let mut index_builder = I32ArrayBuilder::new(self.chunk_size);
1397                        #(let mut #builders = #builder_types::with_type(self.chunk_size, #return_types);)*
1398                        let mut error_builder = Utf8ArrayBuilder::new(self.chunk_size);
1399
1400                        for i in 0..input.capacity() {
1401                            if unsafe { !input.visibility().is_set_unchecked(i) } {
1402                                continue;
1403                            }
1404                            #(let #inputs = unsafe { #arrays.value_at_unchecked(i) };)*
1405                            for output in #iter {
1406                                index_builder.append(Some(i as i32));
1407                                #append_output
1408
1409                                if index_builder.len() == self.chunk_size {
1410                                    let len = index_builder.len();
1411                                    let index_array = std::mem::replace(&mut index_builder, I32ArrayBuilder::new(self.chunk_size)).finish().into_ref();
1412                                    let value_arrays = [#(std::mem::replace(&mut #builders, #builder_types::with_type(self.chunk_size, #return_types)).finish().into_ref()),*];
1413                                    #build_value_array
1414                                    let error_array = std::mem::replace(&mut error_builder, Utf8ArrayBuilder::new(self.chunk_size)).finish().into_ref();
1415                                    if error_array.null_bitmap().any() {
1416                                        yield DataChunk::new(vec![index_array, value_array, error_array], self.chunk_size);
1417                                    } else {
1418                                        yield DataChunk::new(vec![index_array, value_array], self.chunk_size);
1419                                    }
1420                                }
1421                            }
1422                        }
1423
1424                        if index_builder.len() > 0 {
1425                            let len = index_builder.len();
1426                            let index_array = index_builder.finish().into_ref();
1427                            let value_arrays = [#(#builders.finish().into_ref()),*];
1428                            #build_value_array
1429                            let error_array = error_builder.finish().into_ref();
1430                            if error_array.null_bitmap().any() {
1431                                yield DataChunk::new(vec![index_array, value_array, error_array], len);
1432                            } else {
1433                                yield DataChunk::new(vec![index_array, value_array], len);
1434                            }
1435                        }
1436                    }
1437                }
1438
1439                Ok(Box::new(#struct_name {
1440                    context,
1441                    chunk_size,
1442                    #(#child,)*
1443                    prebuilt_arg: #prebuilt_arg_value,
1444                }))
1445            }
1446        })
1447    }
1448}
1449
1450fn sig_data_type(ty: &str) -> TokenStream2 {
1451    match ty {
1452        "any" => quote! { SigDataType::Any },
1453        "anyarray" => quote! { SigDataType::AnyArray },
1454        "anymap" => quote! { SigDataType::AnyMap },
1455        "vector" => quote! { SigDataType::Vector },
1456        "struct" => quote! { SigDataType::AnyStruct },
1457        _ if ty.starts_with("struct") && ty.contains("any") => quote! { SigDataType::AnyStruct },
1458        _ => {
1459            let datatype = data_type(ty);
1460            quote! { SigDataType::Exact(#datatype) }
1461        }
1462    }
1463}
1464
1465fn data_type(ty: &str) -> TokenStream2 {
1466    if let Some(ty) = ty.strip_suffix("[]") {
1467        let inner_type = data_type(ty);
1468        return quote! { DataType::list(#inner_type) };
1469    }
1470    if ty.starts_with("struct<") {
1471        return quote! { DataType::Struct(#ty.parse().expect("invalid struct type")) };
1472    }
1473    let variant = format_ident!("{}", types::data_type(ty));
1474    // TODO: enable the check
1475    // assert!(
1476    //     !matches!(ty, "any" | "anyarray" | "anymap" | "struct"),
1477    //     "{ty}, {variant}"
1478    // );
1479
1480    quote! { DataType::#variant }
1481}
1482
1483/// Extract multiple output types.
1484///
1485/// ```ignore
1486/// output_types("int4") -> ["int4"]
1487/// output_types("struct<key varchar, value jsonb>") -> ["varchar", "jsonb"]
1488/// ```
1489fn output_types(ty: &str) -> Vec<&str> {
1490    if let Some(s) = ty.strip_prefix("struct<")
1491        && let Some(args) = s.strip_suffix('>')
1492    {
1493        args.split(',')
1494            .map(|s| s.split_whitespace().nth(1).unwrap())
1495            .collect()
1496    } else {
1497        vec![ty]
1498    }
1499}