Skip to main content

risingwave_expr_macro/
types.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//! This module provides utility functions for SQL data type conversion and manipulation.
16
17//  name        data type   array type          owned type      ref type            primitive
18const TYPE_MATRIX: &str = "
19    boolean     Boolean     BoolArray           bool            bool                _
20    int2        Int16       I16Array            i16             i16                 y
21    int4        Int32       I32Array            i32             i32                 y
22    int8        Int64       I64Array            i64             i64                 y
23    int256      Int256      Int256Array         Int256          Int256Ref<'_>       _
24    float4      Float32     F32Array            F32             F32                 y
25    float8      Float64     F64Array            F64             F64                 y
26    decimal     Decimal     DecimalArray        Decimal         Decimal             y
27    serial      Serial      SerialArray         Serial          Serial              y
28    date        Date        DateArray           Date            Date                y
29    time        Time        TimeArray           Time            Time                y
30    timestamp   Timestamp   TimestampArray      Timestamp       Timestamp           y
31    timestamptz Timestamptz TimestamptzArray    Timestamptz     Timestamptz         y
32    interval    Interval    IntervalArray       Interval        Interval            y
33    varchar     Varchar     Utf8Array           Box<str>        &str                _
34    bytea       Bytea       BytesArray          Box<[u8]>       &[u8]               _
35    jsonb       Jsonb       JsonbArray          JsonbVal        JsonbRef<'_>        _
36    variant     Variant     VariantArray        VariantVal      VariantRef<'_>      _
37    vector      Vector      VectorArray         VectorVal       VectorRef<'_>       _
38    anyarray    List        ListArray           ListValue       ListRef<'_>         _
39    struct      Struct      StructArray         StructValue     StructRef<'_>       _
40    anymap      Map         MapArray            MapValue        MapRef<'_>          _
41    any         ???         ArrayImpl           ScalarImpl      ScalarRefImpl<'_>   _
42";
43
44/// Maps a data type to its corresponding data type name.
45pub fn data_type(ty: &str) -> &str {
46    lookup_matrix(ty, 1)
47}
48
49/// Maps a data type to its corresponding array type name.
50pub fn array_type(ty: &str) -> &str {
51    lookup_matrix(ty, 2)
52}
53
54/// Maps a data type to its corresponding `Scalar` type name.
55pub fn owned_type(ty: &str) -> &str {
56    lookup_matrix(ty, 3)
57}
58
59/// Maps a data type to its corresponding `ScalarRef` type name.
60pub fn ref_type(ty: &str) -> &str {
61    lookup_matrix(ty, 4)
62}
63
64/// Checks if a data type is primitive.
65pub fn is_primitive(ty: &str) -> bool {
66    lookup_matrix(ty, 5) == "y"
67}
68
69fn lookup_matrix(mut ty: &str, idx: usize) -> &str {
70    if ty.ends_with("[]") {
71        ty = "anyarray";
72    } else if ty.starts_with("struct") {
73        ty = "struct";
74    } else if ty == "void" {
75        // XXX: we don't support void type yet.
76        //      replace it with int for now.
77        ty = "int4";
78    }
79    let s = TYPE_MATRIX.trim().lines().find_map(|line| {
80        let mut parts = line.split_whitespace();
81        if parts.next() == Some(ty) {
82            Some(parts.nth(idx - 1).unwrap())
83        } else {
84            None
85        }
86    });
87    s.unwrap_or_else(|| panic!("failed to lookup type matrix: unknown type: {}", ty))
88}
89
90/// Expands a type wildcard string into a list of concrete types.
91pub fn expand_type_wildcard(ty: &str) -> Vec<&str> {
92    match ty {
93        "*" => TYPE_MATRIX
94            .trim()
95            .lines()
96            .map(|l| l.split_whitespace().next().unwrap())
97            .filter(|l| *l != "any")
98            .collect(),
99        "*int" => vec!["int2", "int4", "int8"],
100        "*float" => vec!["float4", "float8"],
101        _ => vec![ty],
102    }
103}
104
105/// Computes the minimal compatible type between a pair of data types.
106///
107/// This function is used to determine the `auto` type.
108pub fn min_compatible_type(types: &[impl AsRef<str>]) -> &str {
109    if types.len() == 1 {
110        return types[0].as_ref();
111    }
112    assert_eq!(types.len(), 2);
113    match (types[0].as_ref(), types[1].as_ref()) {
114        (a, b) if a == b => a,
115
116        ("int2", "int2") => "int2",
117        ("int2", "int4") => "int4",
118        ("int2", "int8") => "int8",
119
120        ("int4", "int2") => "int4",
121        ("int4", "int4") => "int4",
122        ("int4", "int8") => "int8",
123
124        ("int8", "int2") => "int8",
125        ("int8", "int4") => "int8",
126        ("int8", "int8") => "int8",
127
128        ("int2", "int256") => "int256",
129        ("int4", "int256") => "int256",
130        ("int8", "int256") => "int256",
131        ("int256", "int2") => "int256",
132        ("int256", "int4") => "int256",
133        ("int256", "int8") => "int256",
134        ("int256", "float8") => "float8",
135        ("float8", "int256") => "float8",
136
137        ("float4", "float4") => "float4",
138        ("float4", "float8") => "float8",
139
140        ("float8", "float4") => "float8",
141        ("float8", "float8") => "float8",
142
143        ("decimal", "decimal") => "decimal",
144
145        ("date", "timestamp") => "timestamp",
146        ("timestamp", "date") => "timestamp",
147        ("time", "interval") => "interval",
148        ("interval", "time") => "interval",
149
150        (a, b) => panic!("unknown minimal compatible type for {a:?} and {b:?}"),
151    }
152}