risingwave_expr_impl/scalar/
array_to_string.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
15use risingwave_common::array::*;
16use risingwave_common::types::ToText;
17use risingwave_expr::expr::Context;
18use risingwave_expr::function;
19
20/// Converts each array element to its text representation, and concatenates those
21/// separated by the delimiter string. If `null_string` is given and is not NULL,
22/// then NULL array entries are represented by that string; otherwise, they are omitted.
23///
24/// ```sql
25/// array_to_string ( array anyarray, delimiter text [, null_string text ] ) → text
26/// ```
27///
28/// Examples:
29///
30/// ```slt
31/// query T
32/// select array_to_string(array[1, 2, 3, NULL, 5], ',')
33/// ----
34/// 1,2,3,5
35///
36/// query T
37/// select array_to_string(array[1, 2, 3, NULL, 5], ',', '*')
38/// ----
39/// 1,2,3,*,5
40///
41/// query T
42/// select array_to_string(array[null,'foo',null], ',', '*');
43/// ----
44/// *,foo,*
45///
46/// query T
47/// select array_to_string(array['2023-02-20 17:35:25'::timestamp, null,'2023-02-19 13:01:30'::timestamp], ',', '*');
48/// ----
49/// 2023-02-20 17:35:25,*,2023-02-19 13:01:30
50///
51/// query T
52/// with t as (
53///   select array[1,null,2,3] as arr, ',' as d union all
54///   select array[4,5,6,null,7] as arr, '|')
55/// select array_to_string(arr, d) from t;
56/// ----
57/// 1,2,3
58/// 4|5|6|7
59///
60/// # `array` or `delimiter` are required. Otherwise, returns null.
61/// query T
62/// select array_to_string(array[1,2], NULL);
63/// ----
64/// NULL
65///
66/// query error polymorphic type
67/// select array_to_string(null, ',');
68///
69/// # multidimensional array
70/// query T
71/// select array_to_string(array[array['one', null], array['three', 'four']]::text[][], ',');
72/// ----
73/// one,three,four
74///
75/// query T
76/// select array_to_string(array[array['one', null], array['three', 'four']]::text[][], ',', '*');
77/// ----
78/// one,*,three,four
79/// ```
80#[function("array_to_string(anyarray, varchar) -> varchar")]
81fn array_to_string(
82    array: ListRef<'_>,
83    delimiter: &str,
84    ctx: &Context,
85    writer: &mut impl std::fmt::Write,
86) {
87    let element_data_type = ctx.arg_types[0].unnest_list();
88    let mut first = true;
89    for element in array.flatten().iter() {
90        let Some(element) = element else { continue };
91        if !first {
92            write!(writer, "{}", delimiter).unwrap();
93        } else {
94            first = false;
95        }
96        element.write_with_type(element_data_type, writer).unwrap();
97    }
98}
99
100#[function("array_to_string(anyarray, varchar, varchar) -> varchar")]
101fn array_to_string_with_null(
102    array: ListRef<'_>,
103    delimiter: &str,
104    null_string: &str,
105    ctx: &Context,
106    writer: &mut impl std::fmt::Write,
107) {
108    let element_data_type = ctx.arg_types[0].unnest_list();
109    let mut first = true;
110    for element in array.flatten().iter() {
111        if !first {
112            write!(writer, "{}", delimiter).unwrap();
113        } else {
114            first = false;
115        }
116        match element {
117            Some(s) => s.write_with_type(element_data_type, writer).unwrap(),
118            None => write!(writer, "{}", null_string).unwrap(),
119        }
120    }
121}