Repository: risingwavelabs/risingwave
File: src/expr/macro/src/lib.rs (Rust)

Code before:
/// ```ignore
/// #[function("trim(varchar) -> varchar")]
/// fn trim(s: &str, writer: &mut impl std::fmt::Write) -> Result<()> {
///     writer.write_str(s.trim()).unwrap();
///     Ok(())
/// }
/// ```
///
/// If the function may return NULL, use `Option<()>`:
///
/// ```ignore
/// #[function("trim(varchar) -> varchar")]
/// fn trim(s: &str, writer: &mut impl std::fmt::Write) -> Option<()> {
///     if s.is_empty() {
///         None
///     } else {
///         writer.write_str(s.trim()).unwrap();
///         Some(())
///     }
/// }
/// ```
///
/// Writer types:
/// - For `varchar`: `impl std::fmt::Write`
/// - For `bytea`: `impl std::io::Write`
/// - For `jsonb`: `jsonbb::Builder`
///
/// Note: Use fully-qualified trait paths (for example, `impl std::io::Write` or `impl std::fmt::Write`).
/// Partial or relative paths (such as `impl Write` or `impl ::std::fmt::Write`) are not recognized.
///
/// ## Preprocessing Constant Arguments
///
/// When some input arguments of the function are constants, they can be preprocessed to avoid
/// calculations every time the function is called.
///
/// A classic use case is regular expression matching:
///
/// ```ignore
/// #[function(
///     "regexp_match(varchar, varchar, varchar) -> varchar[]",
///     prebuild = "RegexpContext::from_pattern_flags($1, $2)?"
/// )]
/// fn regexp_match(text: &str, regex: &RegexpContext) -> ListValue {
///     regex.captures(text).collect()
/// }
/// ```
///
/// The `prebuild` argument can be specified, and its value is a Rust expression `Type::method(...)`
/// used to construct a new variable of `Type` from the input arguments of the function.
/// Here `$1`, `$2` represent the second and third arguments of the function (indexed from 0),
/// and their types are `&str`. In the Rust function signature, these positions of parameters will

Review comment (suggestion):
The documentation states the writer type for `jsonb` is `jsonbb::Builder`, but based on the parse logic and actual function implementations, it should be `&mut jsonbb::Builder`. The documentation should be updated to match the actual required signature: `&mut jsonbb::Builder`.
```suggestion
/// - For `jsonb`: `&mut jsonbb::Builder`
```

Code after:
/// ```ignore
/// #[function("trim(varchar) -> varchar")]
/// fn trim(s: &str, writer: &mut impl std::fmt::Write) -> Result<()> {
///     writer.write_str(s.trim()).unwrap();
///     Ok(())
/// }
/// ```
///
/// If the function may return NULL, use `Option<()>`:
///
/// ```ignore
/// #[function("trim(varchar) -> varchar")]
/// fn trim(s: &str, writer: &mut impl std::fmt::Write) -> Option<()> {
///     if s.is_empty() {
///         None
///     } else {
///         writer.write_str(s.trim()).unwrap();
///         Some(())
///     }
/// }
/// ```
///
/// Writer types:
/// - For `varchar`: `&mut impl std::fmt::Write`
/// - For `bytea`: `&mut impl std::io::Write`
/// - For `jsonb`: `&mut jsonbb::Builder`
///
/// Note: Use fully-qualified trait paths (for example, `impl std::io::Write` or `impl std::fmt::Write`).
/// Partial or relative paths (such as `impl Write` or `impl ::std::fmt::Write`) are not recognized.
///
/// ## Preprocessing Constant Arguments
///
/// When some input arguments of the function are constants, they can be preprocessed to avoid
/// calculations every time the function is called.
///
/// A classic use case is regular expression matching:
///
/// ```ignore
/// #[function(
///     "regexp_match(varchar, varchar, varchar) -> varchar[]",
///     prebuild = "RegexpContext::from_pattern_flags($1, $2)?"
/// )]
/// fn regexp_match(text: &str, regex: &RegexpContext) -> ListValue {
///     regex.captures(text).collect()
/// }
/// ```
///
/// The `prebuild` argument can be specified, and its value is a Rust expression `Type::method(...)`
/// used to construct a new variable of `Type` from the input arguments of the function.
/// Here `$1`, `$2` represent the second and third arguments of the function (indexed from 0),
/// and their types are `&str`. In the Rust function signature, these positions of parameters will