risingwave_frontend/binder/expr/
value.rs

1// Copyright 2025 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 itertools::Itertools;
16use risingwave_common::bail_not_implemented;
17use risingwave_common::types::{
18    DataType, DateTimeField, Decimal, Interval, MapType, ScalarImpl, StructType,
19};
20use risingwave_sqlparser::ast::{DateTimeField as AstDateTimeField, Expr, Value};
21use thiserror_ext::AsReport;
22
23use crate::binder::Binder;
24use crate::error::{ErrorCode, Result};
25use crate::expr::{Expr as _, ExprImpl, ExprType, FunctionCall, Literal, align_types};
26
27impl Binder {
28    pub fn bind_value(&mut self, value: &Value) -> Result<Literal> {
29        match value {
30            Value::Number(s) => self.bind_number(s.clone()),
31            Value::SingleQuotedString(s) => self.bind_string(s),
32            Value::CstyleEscapedString(s) => self.bind_string(&s.value),
33            Value::Boolean(b) => self.bind_bool(*b),
34            // Both null and string literal will be treated as `unknown` during type inference.
35            // See [`ExprImpl::is_unknown`].
36            Value::Null => Ok(Literal::new_untyped(None)),
37            Value::Interval {
38                value,
39                leading_field,
40                // TODO: support more interval types.
41                leading_precision: None,
42                last_field: None,
43                fractional_seconds_precision: None,
44            } => self.bind_interval(value, *leading_field),
45            _ => bail_not_implemented!("value: {:?}", value),
46        }
47    }
48
49    pub(super) fn bind_string(&mut self, s: &str) -> Result<Literal> {
50        Ok(Literal::new_untyped(Some(s.to_owned())))
51    }
52
53    fn bind_bool(&mut self, b: bool) -> Result<Literal> {
54        Ok(Literal::new(Some(ScalarImpl::Bool(b)), DataType::Boolean))
55    }
56
57    fn bind_number(&mut self, mut s: String) -> Result<Literal> {
58        let prefix_start = match s.starts_with('-') {
59            true => 1,
60            false => 0,
61        };
62        let base = match prefix_start + 2 <= s.len() {
63            true => match &s[prefix_start..prefix_start + 2] {
64                // tokenizer already converts them to lowercase
65                "0x" => 16,
66                "0o" => 8,
67                "0b" => 2,
68                _ => 10,
69            },
70            false => 10,
71        };
72        if base != 10 {
73            s.replace_range(prefix_start..prefix_start + 2, "");
74        }
75
76        let (data, data_type) = if let Ok(int_32) = i32::from_str_radix(&s, base) {
77            (Some(ScalarImpl::Int32(int_32)), DataType::Int32)
78        } else if let Ok(int_64) = i64::from_str_radix(&s, base) {
79            (Some(ScalarImpl::Int64(int_64)), DataType::Int64)
80        } else if let Ok(decimal) = Decimal::from_str_radix(&s, base) {
81            // Notice: when the length of decimal exceeds 29(>= 30), it will be rounded up.
82            (Some(ScalarImpl::Decimal(decimal)), DataType::Decimal)
83        } else if let Some(scientific) = Decimal::from_scientific(&s) {
84            (Some(ScalarImpl::Decimal(scientific)), DataType::Decimal)
85        } else {
86            return Err(ErrorCode::BindError(format!("Number {s} overflows")).into());
87        };
88        Ok(Literal::new(data, data_type))
89    }
90
91    fn bind_interval(
92        &mut self,
93        s: &str,
94        leading_field: Option<AstDateTimeField>,
95    ) -> Result<Literal> {
96        let interval =
97            Interval::parse_with_fields(s, leading_field.map(Self::bind_date_time_field))
98                .map_err(|e| ErrorCode::BindError(e.to_report_string()))?;
99        let datum = Some(ScalarImpl::Interval(interval));
100        let literal = Literal::new(datum, DataType::Interval);
101
102        Ok(literal)
103    }
104
105    pub(crate) fn bind_date_time_field(field: AstDateTimeField) -> DateTimeField {
106        // This is a binder function rather than `impl From<AstDateTimeField> for DateTimeField`,
107        // so that the `sqlparser` crate and the `common` crate are kept independent.
108        match field {
109            AstDateTimeField::Year => DateTimeField::Year,
110            AstDateTimeField::Month => DateTimeField::Month,
111            AstDateTimeField::Day => DateTimeField::Day,
112            AstDateTimeField::Hour => DateTimeField::Hour,
113            AstDateTimeField::Minute => DateTimeField::Minute,
114            AstDateTimeField::Second => DateTimeField::Second,
115        }
116    }
117
118    /// `ARRAY[...]` is represented as an function call at the binder stage.
119    pub(super) fn bind_array(&mut self, exprs: &[Expr]) -> Result<ExprImpl> {
120        if exprs.is_empty() {
121            return Err(ErrorCode::BindError("cannot determine type of empty array\nHINT:  Explicitly cast to the desired type, for example ARRAY[]::integer[].".into()).into());
122        }
123        let mut exprs = exprs
124            .iter()
125            .map(|e| self.bind_expr_inner(e))
126            .collect::<Result<Vec<ExprImpl>>>()?;
127        let element_type = align_types(exprs.iter_mut())?;
128        let expr: ExprImpl = FunctionCall::new_unchecked(
129            ExprType::Array,
130            exprs,
131            DataType::List(Box::new(element_type)),
132        )
133        .into();
134        Ok(expr)
135    }
136
137    pub(super) fn bind_map(&mut self, entries: &[(Expr, Expr)]) -> Result<ExprImpl> {
138        if entries.is_empty() {
139            return Err(ErrorCode::BindError("cannot determine type of empty map\nHINT:  Explicitly cast to the desired type, for example MAP{}::map(int,int).".into()).into());
140        }
141        let mut keys = Vec::with_capacity(entries.len());
142        let mut values = Vec::with_capacity(entries.len());
143        for (k, v) in entries {
144            keys.push(self.bind_expr_inner(k)?);
145            values.push(self.bind_expr_inner(v)?);
146        }
147        let key_type = align_types(keys.iter_mut())?;
148        let value_type = align_types(values.iter_mut())?;
149
150        let keys: ExprImpl = FunctionCall::new_unchecked(
151            ExprType::Array,
152            keys,
153            DataType::List(Box::new(key_type.clone())),
154        )
155        .into();
156        let values: ExprImpl = FunctionCall::new_unchecked(
157            ExprType::Array,
158            values,
159            DataType::List(Box::new(value_type.clone())),
160        )
161        .into();
162
163        let expr: ExprImpl = FunctionCall::new_unchecked(
164            ExprType::MapFromKeyValues,
165            vec![keys, values],
166            DataType::Map(MapType::from_kv(key_type, value_type)),
167        )
168        .into();
169        Ok(expr)
170    }
171
172    pub(super) fn bind_array_cast(
173        &mut self,
174        exprs: &[Expr],
175        element_type: &DataType,
176    ) -> Result<ExprImpl> {
177        let exprs = exprs
178            .iter()
179            .map(|e| self.bind_cast_inner(e, element_type))
180            .collect::<Result<Vec<ExprImpl>>>()?;
181
182        let expr: ExprImpl = FunctionCall::new_unchecked(
183            ExprType::Array,
184            exprs,
185            DataType::List(Box::new(element_type.clone())),
186        )
187        .into();
188        Ok(expr)
189    }
190
191    pub(super) fn bind_map_cast(
192        &mut self,
193        entries: &[(Expr, Expr)],
194        map_type: &MapType,
195    ) -> Result<ExprImpl> {
196        let mut keys = Vec::with_capacity(entries.len());
197        let mut values = Vec::with_capacity(entries.len());
198        for (k, v) in entries {
199            keys.push(self.bind_cast_inner(k, map_type.key())?);
200            values.push(self.bind_cast_inner(v, map_type.value())?);
201        }
202
203        let keys: ExprImpl = FunctionCall::new_unchecked(
204            ExprType::Array,
205            keys,
206            DataType::List(Box::new(map_type.key().clone())),
207        )
208        .into();
209        let values: ExprImpl = FunctionCall::new_unchecked(
210            ExprType::Array,
211            values,
212            DataType::List(Box::new(map_type.value().clone())),
213        )
214        .into();
215
216        let expr: ExprImpl = FunctionCall::new_unchecked(
217            ExprType::MapFromKeyValues,
218            vec![keys, values],
219            DataType::Map(map_type.clone()),
220        )
221        .into();
222        Ok(expr)
223    }
224
225    pub(super) fn bind_index(&mut self, obj: &Expr, index: &Expr) -> Result<ExprImpl> {
226        let obj = self.bind_expr_inner(obj)?;
227        match obj.return_type() {
228            DataType::List(return_type) => Ok(FunctionCall::new_unchecked(
229                ExprType::ArrayAccess,
230                vec![obj, self.bind_expr_inner(index)?],
231                *return_type,
232            )
233            .into()),
234            DataType::Map(m) => Ok(FunctionCall::new_unchecked(
235                ExprType::MapAccess,
236                vec![obj, self.bind_expr_inner(index)?],
237                m.value().clone(),
238            )
239            .into()),
240            data_type => Err(ErrorCode::BindError(format!(
241                "index operator applied to type {}, which is not a list or map",
242                data_type
243            ))
244            .into()),
245        }
246    }
247
248    pub(super) fn bind_array_range_index(
249        &mut self,
250        obj: &Expr,
251        start: Option<&Expr>,
252        end: Option<&Expr>,
253    ) -> Result<ExprImpl> {
254        let obj = self.bind_expr_inner(obj)?;
255        let start = match start {
256            None => ExprImpl::literal_int(1),
257            Some(expr) => self
258                .bind_expr_inner(expr)?
259                .cast_implicit(&DataType::Int32)?,
260        };
261        // Don't worry, the backend implementation will stop iterating once it encounters the end
262        // of the array.
263        let end = match end {
264            None => ExprImpl::literal_int(i32::MAX),
265            Some(expr) => self
266                .bind_expr_inner(expr)?
267                .cast_implicit(&DataType::Int32)?,
268        };
269        match obj.return_type() {
270            DataType::List(return_type) => Ok(FunctionCall::new_unchecked(
271                ExprType::ArrayRangeAccess,
272                vec![obj, start, end],
273                DataType::List(return_type),
274            )
275            .into()),
276            data_type => Err(ErrorCode::BindError(format!(
277                "array range index applied to type {}, which is not a list",
278                data_type
279            ))
280            .into()),
281        }
282    }
283
284    /// `Row(...)` is represented as an function call at the binder stage.
285    pub(super) fn bind_row(&mut self, exprs: &[Expr]) -> Result<ExprImpl> {
286        let exprs = exprs
287            .iter()
288            .map(|e| self.bind_expr_inner(e))
289            .collect::<Result<Vec<ExprImpl>>>()?;
290        let data_type =
291            StructType::unnamed(exprs.iter().map(|e| e.return_type()).collect_vec()).into();
292        let expr: ExprImpl = FunctionCall::new_unchecked(ExprType::Row, exprs, data_type).into();
293        Ok(expr)
294    }
295}
296
297#[cfg(test)]
298mod tests {
299    use risingwave_common::types::test_utils::IntervalTestExt;
300    use risingwave_expr::expr::build_from_prost;
301    use risingwave_sqlparser::ast::Value::Number;
302
303    use super::*;
304    use crate::binder::test_utils::mock_binder;
305    use crate::expr::Expr;
306
307    #[tokio::test]
308    async fn test_bind_value() {
309        use std::str::FromStr;
310
311        let mut binder = mock_binder();
312        let values = [
313            "1",
314            "111111111111111",
315            "111111111.111111",
316            "111111111111111111111111",
317            "0.111111",
318            "-0.01",
319        ];
320        let data = [
321            Some(ScalarImpl::Int32(1)),
322            Some(ScalarImpl::Int64(111111111111111)),
323            Some(ScalarImpl::Decimal(
324                Decimal::from_str("111111111.111111").unwrap(),
325            )),
326            Some(ScalarImpl::Decimal(
327                Decimal::from_str("111111111111111111111111").unwrap(),
328            )),
329            Some(ScalarImpl::Decimal(Decimal::from_str("0.111111").unwrap())),
330            Some(ScalarImpl::Decimal(Decimal::from_str("-0.01").unwrap())),
331        ];
332        let data_type = [
333            DataType::Int32,
334            DataType::Int64,
335            DataType::Decimal,
336            DataType::Decimal,
337            DataType::Decimal,
338            DataType::Decimal,
339        ];
340
341        for i in 0..values.len() {
342            let value = Value::Number(String::from(values[i]));
343            let res = binder.bind_value(&value).unwrap();
344            let ans = Literal::new(data[i].clone(), data_type[i].clone());
345            assert_eq!(res, ans);
346        }
347    }
348
349    #[tokio::test]
350    async fn test_bind_radix() {
351        let mut binder = mock_binder();
352
353        for (input, expected) in [
354            ("0x42e3", ScalarImpl::Int32(0x42e3)),
355            ("-0x40", ScalarImpl::Int32(-0x40)),
356            ("0b1101", ScalarImpl::Int32(0b1101)),
357            ("-0b101", ScalarImpl::Int32(-0b101)),
358            ("0o664", ScalarImpl::Int32(0o664)),
359            ("-0o755", ScalarImpl::Int32(-0o755)),
360            ("2147483647", ScalarImpl::Int32(2147483647)),
361            ("2147483648", ScalarImpl::Int64(2147483648)),
362            ("-2147483648", ScalarImpl::Int32(-2147483648)),
363            ("0x7fffffff", ScalarImpl::Int32(0x7fffffff)),
364            ("0x80000000", ScalarImpl::Int64(0x80000000)),
365            ("-0x80000000", ScalarImpl::Int32(-0x80000000)),
366        ] {
367            let lit = binder.bind_number(input.into()).unwrap();
368            assert_eq!(lit.get_data().as_ref().unwrap(), &expected);
369        }
370    }
371
372    #[tokio::test]
373    async fn test_bind_scientific_number() {
374        use std::str::FromStr;
375
376        let mut binder = mock_binder();
377        let values = [
378            ("1e6"),
379            ("1.25e6"),
380            ("1.25e1"),
381            ("1e-2"),
382            ("1.25e-2"),
383            ("1e15"),
384        ];
385        let data = [
386            Some(ScalarImpl::Decimal(Decimal::from_str("1000000").unwrap())),
387            Some(ScalarImpl::Decimal(Decimal::from_str("1250000").unwrap())),
388            Some(ScalarImpl::Decimal(Decimal::from_str("12.5").unwrap())),
389            Some(ScalarImpl::Decimal(Decimal::from_str("0.01").unwrap())),
390            Some(ScalarImpl::Decimal(Decimal::from_str("0.0125").unwrap())),
391            Some(ScalarImpl::Decimal(
392                Decimal::from_str("1000000000000000").unwrap(),
393            )),
394        ];
395        let data_type = [
396            DataType::Decimal,
397            DataType::Decimal,
398            DataType::Decimal,
399            DataType::Decimal,
400            DataType::Decimal,
401            DataType::Decimal,
402        ];
403
404        for i in 0..values.len() {
405            let res = binder.bind_value(&Number(values[i].to_owned())).unwrap();
406            let ans = Literal::new(data[i].clone(), data_type[i].clone());
407            assert_eq!(res, ans);
408        }
409    }
410
411    #[test]
412    fn test_array_expr() {
413        let expr: ExprImpl = FunctionCall::new_unchecked(
414            ExprType::Array,
415            vec![ExprImpl::literal_int(11)],
416            DataType::List(Box::new(DataType::Int32)),
417        )
418        .into();
419        let expr_pb = expr.to_expr_proto();
420        let expr = build_from_prost(&expr_pb).unwrap();
421        match expr.return_type() {
422            DataType::List(datatype) => {
423                assert_eq!(datatype, Box::new(DataType::Int32));
424            }
425            _ => panic!("unexpected type"),
426        };
427    }
428
429    #[test]
430    fn test_array_index_expr() {
431        let array_expr = FunctionCall::new_unchecked(
432            ExprType::Array,
433            vec![ExprImpl::literal_int(11), ExprImpl::literal_int(22)],
434            DataType::List(Box::new(DataType::Int32)),
435        )
436        .into();
437
438        let expr: ExprImpl = FunctionCall::new_unchecked(
439            ExprType::ArrayAccess,
440            vec![array_expr, ExprImpl::literal_int(1)],
441            DataType::Int32,
442        )
443        .into();
444
445        let expr_pb = expr.to_expr_proto();
446        let expr = build_from_prost(&expr_pb).unwrap();
447        assert_eq!(expr.return_type(), DataType::Int32);
448    }
449
450    #[tokio::test]
451    async fn test_bind_interval() {
452        let mut binder = mock_binder();
453        let values = [
454            "1 hour",
455            "1 h",
456            "1 year",
457            "6 second",
458            "2 minutes",
459            "1 month",
460        ];
461        let data = vec![
462            Literal::new(
463                Some(ScalarImpl::Interval(Interval::from_minutes(60))),
464                DataType::Interval,
465            ),
466            Literal::new(
467                Some(ScalarImpl::Interval(Interval::from_minutes(60))),
468                DataType::Interval,
469            ),
470            Literal::new(
471                Some(ScalarImpl::Interval(Interval::from_ymd(1, 0, 0))),
472                DataType::Interval,
473            ),
474            Literal::new(
475                Some(ScalarImpl::Interval(Interval::from_millis(6 * 1000))),
476                DataType::Interval,
477            ),
478            Literal::new(
479                Some(ScalarImpl::Interval(Interval::from_minutes(2))),
480                DataType::Interval,
481            ),
482            Literal::new(
483                Some(ScalarImpl::Interval(Interval::from_month(1))),
484                DataType::Interval,
485            ),
486        ];
487
488        for i in 0..values.len() {
489            let value = Value::Interval {
490                value: values[i].to_owned(),
491                leading_field: None,
492                leading_precision: None,
493                last_field: None,
494                fractional_seconds_precision: None,
495            };
496            assert_eq!(binder.bind_value(&value).unwrap(), data[i]);
497        }
498    }
499}