fix: interval rewrite rule that messes up show create flow function (#5642)

* fix/interval-cast-rewrite:
 ### Enhance Interval Parsing and Casting

 - **`create_parser.rs`**: Added a test case `test_parse_interval_cast` to verify the parsing of interval casts.
 - **`expand_interval.rs`**: Refactored interval casting logic to handle `CastKind` and `format` attributes. Removed the `create_interval` function and integrated its logic directly into the casting process.
 - **`interval.result`**: Updated test results to reflect changes in interval representation, switching from `IntervalMonthDayNano` to `Utf8` format for interval operations.

* reformat code
This commit is contained in:
Lei, HUANG
2025-03-04 19:55:25 +08:00
committed by GitHub
parent 0e2fd8e2bd
commit abf1680d14
3 changed files with 121 additions and 108 deletions

View File

@@ -2475,4 +2475,13 @@ CREATE TABLE log (
assert!(extensions.fulltext_index_options.is_some());
}
}
#[test]
fn test_parse_interval_cast() {
let s = "select '10s'::INTERVAL";
let stmts =
ParserContext::create_with_dialect(s, &GreptimeDbDialect {}, ParseOptions::default())
.unwrap();
assert_eq!("SELECT '10 seconds'::INTERVAL", &stmts[0].to_string());
}
}

View File

@@ -99,15 +99,21 @@ impl TransformRule for ExpandIntervalTransformRule {
Expr::Cast {
expr: cast_exp,
data_type,
..
kind,
format,
} => {
if DataType::Interval == *data_type {
match &**cast_exp {
Expr::Value(Value::SingleQuotedString(value))
| Expr::Value(Value::DoubleQuotedString(value)) => {
let interval_name =
let interval_value =
normalize_interval_name(value).unwrap_or_else(|| value.to_string());
*expr = create_interval(single_quoted_string_expr(interval_name));
*expr = Expr::Cast {
kind: kind.clone(),
expr: single_quoted_string_expr(interval_value),
data_type: DataType::Interval,
format: std::mem::take(format),
}
}
_ => {}
}
@@ -123,16 +129,6 @@ fn single_quoted_string_expr(string: String) -> Box<Expr> {
Box::new(Expr::Value(Value::SingleQuotedString(string)))
}
fn create_interval(value: Box<Expr>) -> Expr {
Expr::Interval(Interval {
value,
leading_field: None,
leading_precision: None,
last_field: None,
fractional_seconds_precision: None,
})
}
fn update_existing_interval_with_value(interval: &Interval, value: Box<Expr>) -> Expr {
Expr::Interval(Interval {
value,
@@ -199,14 +195,23 @@ fn expand_interval_abbreviation(interval_str: &str) -> Option<String> {
mod tests {
use std::ops::ControlFlow;
use sqlparser::ast::{BinaryOperator, DataType, Expr, Interval, Value};
use sqlparser::ast::{BinaryOperator, CastKind, DataType, Expr, Interval, Value};
use crate::statements::transform::expand_interval::{
create_interval, normalize_interval_name, single_quoted_string_expr,
ExpandIntervalTransformRule,
normalize_interval_name, single_quoted_string_expr, ExpandIntervalTransformRule,
};
use crate::statements::transform::TransformRule;
fn create_interval(value: Box<Expr>) -> Expr {
Expr::Interval(Interval {
value,
leading_field: None,
leading_precision: None,
last_field: None,
fractional_seconds_precision: None,
})
}
#[test]
fn test_transform_interval_basic_conversions() {
let test_cases = vec![
@@ -379,15 +384,14 @@ mod tests {
assert_eq!(control_flow, ControlFlow::Continue(()));
assert_eq!(
cast_to_interval_expr,
Expr::Interval(Interval {
value: Box::new(Expr::Value(Value::SingleQuotedString(
Expr::Cast {
kind: CastKind::Cast,
expr: Box::new(Expr::Value(Value::SingleQuotedString(
"3 years 2 months".to_string()
))),
leading_field: None,
leading_precision: None,
last_field: None,
fractional_seconds_precision: None,
})
data_type: DataType::Interval,
format: None,
}
);
let mut cast_to_i64_expr = Expr::Cast {

View File

@@ -25,11 +25,11 @@ SELECT INTERVAL '-2 months';
SELECT '3 hours'::INTERVAL;
+--------------------------------------------------------------------------------------------------+
| IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 0, nanoseconds: 10800000000000 }") |
+--------------------------------------------------------------------------------------------------+
| 3 hours |
+--------------------------------------------------------------------------------------------------+
+-----------------+
| Utf8("3 hours") |
+-----------------+
| 3 hours |
+-----------------+
SELECT INTERVAL '1 year 2 months 3 days 4 hours' + INTERVAL '1 year';
@@ -128,11 +128,11 @@ SELECT INTERVAL '1y2w3d4h';
SELECT '3y2mon'::INTERVAL;
+--------------------------------------------------------------------------------------+
| IntervalMonthDayNano("IntervalMonthDayNano { months: 38, days: 0, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------+
| 38 mons |
+--------------------------------------------------------------------------------------+
+--------------------------+
| Utf8("3 years 2 months") |
+--------------------------+
| 38 mons |
+--------------------------+
SELECT INTERVAL '7 days' - INTERVAL '1d';
@@ -169,11 +169,11 @@ SELECT INTERVAL '-P3Y3M700DT133H17M36.789S';
SELECT 'P3Y3M700DT133H17M36.789S'::INTERVAL;
+------------------------------------------------------------------------------------------------------+
| IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 0, nanoseconds: 163343856789000000 }") |
+------------------------------------------------------------------------------------------------------+
| 45373 hours 17 mins 36.789000000 secs |
+------------------------------------------------------------------------------------------------------+
+---------------------------------------+
| Utf8("163343856789 milliseconds") |
+---------------------------------------+
| 45373 hours 17 mins 36.789000000 secs |
+---------------------------------------+
SELECT INTERVAL '2h' + INTERVAL 'P3Y3M700DT133H17M36.789S';
@@ -185,115 +185,115 @@ SELECT INTERVAL '2h' + INTERVAL 'P3Y3M700DT133H17M36.789S';
select '2022-01-01T00:00:01'::timestamp + '1 days'::interval;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 1, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2022-01-02T00:00:01 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + Utf8("1 days") |
+-----------------------------------------------------------------------------------------------+
| 2022-01-02T00:00:01 |
+-----------------------------------------------------------------------------------------------+
select '2022-01-01T00:00:01'::timestamp + '2 days'::interval;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 2, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2022-01-03T00:00:01 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + Utf8("2 days") |
+-----------------------------------------------------------------------------------------------+
| 2022-01-03T00:00:01 |
+-----------------------------------------------------------------------------------------------+
select '2022-01-01T00:00:01'::timestamp - '1 days'::interval;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) - IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 1, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2021-12-31T00:00:01 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) - Utf8("1 days") |
+-----------------------------------------------------------------------------------------------+
| 2021-12-31T00:00:01 |
+-----------------------------------------------------------------------------------------------+
select '2022-01-01T00:00:01'::timestamp - '2 days'::interval;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) - IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 2, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2021-12-30T00:00:01 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) - Utf8("2 days") |
+-----------------------------------------------------------------------------------------------+
| 2021-12-30T00:00:01 |
+-----------------------------------------------------------------------------------------------+
select '2022-01-01T00:00:01'::timestamp + '1 month'::interval;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + IntervalMonthDayNano("IntervalMonthDayNano { months: 1, days: 0, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2022-02-01T00:00:01 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + Utf8("1 month") |
+------------------------------------------------------------------------------------------------+
| 2022-02-01T00:00:01 |
+------------------------------------------------------------------------------------------------+
select '2022-01-01T00:00:01'::timestamp + '2 months'::interval;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + IntervalMonthDayNano("IntervalMonthDayNano { months: 2, days: 0, nanoseconds: 0 }") |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2022-03-01T00:00:01 |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + Utf8("2 months") |
+-------------------------------------------------------------------------------------------------+
| 2022-03-01T00:00:01 |
+-------------------------------------------------------------------------------------------------+
select '2022-01-01T00:00:01'::timestamp + '1 year'::interval;
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + IntervalMonthDayNano("IntervalMonthDayNano { months: 12, days: 0, nanoseconds: 0 }") |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2023-01-01T00:00:01 |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-----------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2022-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + Utf8("1 year") |
+-----------------------------------------------------------------------------------------------+
| 2023-01-01T00:00:01 |
+-----------------------------------------------------------------------------------------------+
select '2023-01-01T00:00:01'::timestamp + '2 years'::interval;
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2023-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + IntervalMonthDayNano("IntervalMonthDayNano { months: 24, days: 0, nanoseconds: 0 }") |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2025-01-01T00:00:01 |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+------------------------------------------------------------------------------------------------+
| arrow_cast(Utf8("2023-01-01T00:00:01"),Utf8("Timestamp(Millisecond, None)")) + Utf8("2 years") |
+------------------------------------------------------------------------------------------------+
| 2025-01-01T00:00:01 |
+------------------------------------------------------------------------------------------------+
-- DATE + INTERVAL
SELECT DATE '2000-10-30' + '1 days'::interval;
+----------------------------------------------------------------------------------------------------------+
| Utf8("2000-10-30") + IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 1, nanoseconds: 0 }") |
+----------------------------------------------------------------------------------------------------------+
| 2000-10-31 |
+----------------------------------------------------------------------------------------------------------+
+-------------------------------------+
| Utf8("2000-10-30") + Utf8("1 days") |
+-------------------------------------+
| 2000-10-31 |
+-------------------------------------+
SELECT DATE '2000-10-30' + '2 months'::interval;
+----------------------------------------------------------------------------------------------------------+
| Utf8("2000-10-30") + IntervalMonthDayNano("IntervalMonthDayNano { months: 2, days: 0, nanoseconds: 0 }") |
+----------------------------------------------------------------------------------------------------------+
| 2000-12-30 |
+----------------------------------------------------------------------------------------------------------+
+---------------------------------------+
| Utf8("2000-10-30") + Utf8("2 months") |
+---------------------------------------+
| 2000-12-30 |
+---------------------------------------+
SELECT DATE '2000-10-30' + '2 years'::interval;
+-----------------------------------------------------------------------------------------------------------+
| Utf8("2000-10-30") + IntervalMonthDayNano("IntervalMonthDayNano { months: 24, days: 0, nanoseconds: 0 }") |
+-----------------------------------------------------------------------------------------------------------+
| 2002-10-30 |
+-----------------------------------------------------------------------------------------------------------+
+--------------------------------------+
| Utf8("2000-10-30") + Utf8("2 years") |
+--------------------------------------+
| 2002-10-30 |
+--------------------------------------+
-- DATE - INTERVAL
SELECT DATE '2000-10-30' - '1 days'::interval;
+----------------------------------------------------------------------------------------------------------+
| Utf8("2000-10-30") - IntervalMonthDayNano("IntervalMonthDayNano { months: 0, days: 1, nanoseconds: 0 }") |
+----------------------------------------------------------------------------------------------------------+
| 2000-10-29 |
+----------------------------------------------------------------------------------------------------------+
+-------------------------------------+
| Utf8("2000-10-30") - Utf8("1 days") |
+-------------------------------------+
| 2000-10-29 |
+-------------------------------------+
SELECT DATE '2000-10-30' - '2 months'::interval;
+----------------------------------------------------------------------------------------------------------+
| Utf8("2000-10-30") - IntervalMonthDayNano("IntervalMonthDayNano { months: 2, days: 0, nanoseconds: 0 }") |
+----------------------------------------------------------------------------------------------------------+
| 2000-08-30 |
+----------------------------------------------------------------------------------------------------------+
+---------------------------------------+
| Utf8("2000-10-30") - Utf8("2 months") |
+---------------------------------------+
| 2000-08-30 |
+---------------------------------------+
SELECT DATE '2000-10-30' - '2 years'::interval;
+-----------------------------------------------------------------------------------------------------------+
| Utf8("2000-10-30") - IntervalMonthDayNano("IntervalMonthDayNano { months: 24, days: 0, nanoseconds: 0 }") |
+-----------------------------------------------------------------------------------------------------------+
| 1998-10-30 |
+-----------------------------------------------------------------------------------------------------------+
+--------------------------------------+
| Utf8("2000-10-30") - Utf8("2 years") |
+--------------------------------------+
| 1998-10-30 |
+--------------------------------------+