risingwave_expr_impl/scalar/
array_contain.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//! Range expression functions.
16
17use std::collections::HashSet;
18
19use risingwave_common::types::ListRef;
20use risingwave_expr::function;
21
22/// Returns whether left range contains right range.
23///
24/// Examples:
25///
26/// ```slt
27/// query I
28/// select array[1,2,3] @> array[2,3];
29/// ----
30/// t
31///
32/// query I
33/// select array[1,2,3] @> array[3,4];
34/// ----
35/// f
36///
37/// query I
38/// SELECT array[1,2,3] @> array[3,1];
39/// ----
40/// t
41///
42/// query I
43/// SELECT array[1,2] @> array[1,1];
44/// ----
45/// t
46///
47/// query I
48/// SELECT array[1,2,3] @> array[]::int[];
49/// ----
50/// t
51///
52/// query I
53/// SELECT ARRAY[]::int[] @> ARRAY[]::int[];
54/// ----
55/// t
56///
57/// query I
58/// select array[[[1,2],[3,4]],[[5,6],[7,8]]] @> array[2,3];
59/// ----
60/// t
61///
62/// query I
63/// select array[1,2,3] @> null;
64/// ----
65/// NULL
66///
67/// query I
68/// select null @> array[3,4];
69/// ----
70/// NULL
71///
72/// query I
73/// select array[1,null,2] @> array[1,null,2];
74/// ----
75/// f
76///
77/// query I
78/// select array[1,null,2] @> array[1,2];
79/// ----
80/// t
81///
82/// query I
83/// SELECT array[1,NULL,2] @> array[NULL]::int[];
84/// ----
85/// f
86///
87/// query I
88/// SELECT NULL::int[] @> ARRAY[1];
89/// ----
90/// NULL
91/// ```
92#[function("array_contains(anyarray, anyarray) -> boolean")]
93fn array_contains(left: ListRef<'_>, right: ListRef<'_>) -> bool {
94    let flatten = left.flatten();
95    let set: HashSet<_> = flatten.iter().collect();
96    right
97        .flatten()
98        .iter()
99        .all(|item| item.is_some_and(|v| set.contains(&Some(v))))
100}
101
102#[function("array_contained(anyarray, anyarray) -> boolean")]
103fn array_contained(left: ListRef<'_>, right: ListRef<'_>) -> bool {
104    array_contains(right, left)
105}
106
107#[cfg(test)]
108mod tests {
109    use risingwave_common::types::{ListValue, Scalar};
110
111    use super::*;
112
113    #[test]
114    fn test_contains() {
115        assert!(array_contains(
116            ListValue::from_iter([2, 3]).as_scalar_ref(),
117            ListValue::from_iter([2]).as_scalar_ref(),
118        ));
119        assert!(!array_contains(
120            ListValue::from_iter([2, 3]).as_scalar_ref(),
121            ListValue::from_iter([5]).as_scalar_ref(),
122        ));
123    }
124}