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}