1use common_time::timezone::Timezone;
16use datatypes::prelude::ConcreteDataType;
17use datatypes::schema::constraint::{CURRENT_TIMESTAMP, CURRENT_TIMESTAMP_FN};
18use datatypes::schema::ColumnDefaultConstraint;
19use sqlparser::ast::ValueWithSpan;
20pub use sqlparser::ast::{
21 visit_expressions_mut, visit_statements_mut, BinaryOperator, ColumnDef, ColumnOption,
22 ColumnOptionDef, DataType, Expr, Function, FunctionArg, FunctionArgExpr, FunctionArguments,
23 Ident, ObjectName, SqlOption, TableConstraint, TimezoneInfo, UnaryOperator, Value as SqlValue,
24 Visit, VisitMut, Visitor, VisitorMut,
25};
26
27use crate::convert::{sql_number_to_value, sql_value_to_value};
28use crate::error::{Result, UnsupportedDefaultValueSnafu};
29
30pub fn parse_column_default_constraint(
31 column_name: &str,
32 data_type: &ConcreteDataType,
33 opts: &[ColumnOptionDef],
34 timezone: Option<&Timezone>,
35) -> Result<Option<ColumnDefaultConstraint>> {
36 if let Some(opt) = opts
37 .iter()
38 .find(|o| matches!(o.option, ColumnOption::Default(_)))
39 {
40 let default_constraint = match &opt.option {
41 ColumnOption::Default(Expr::Value(v)) => ColumnDefaultConstraint::Value(
42 sql_value_to_value(column_name, data_type, &v.value, timezone, None, false)?,
43 ),
44 ColumnOption::Default(Expr::Function(func)) => {
45 let mut func = format!("{func}").to_lowercase();
46 if func == CURRENT_TIMESTAMP {
48 func = CURRENT_TIMESTAMP_FN.to_string();
49 }
50 ColumnDefaultConstraint::Function(func.to_lowercase())
52 }
53
54 ColumnOption::Default(Expr::UnaryOp { op, expr }) => {
55 if let (
59 UnaryOperator::Minus,
60 Expr::Value(ValueWithSpan {
61 value: SqlValue::Number(n, _),
62 span: _,
63 }),
64 ) = (op, expr.as_ref())
65 {
66 return Ok(Some(ColumnDefaultConstraint::Value(sql_number_to_value(
67 data_type,
68 &format!("-{n}"),
69 )?)));
70 }
71
72 if let Expr::Value(v) = &**expr {
73 let value = sql_value_to_value(
74 column_name,
75 data_type,
76 &v.value,
77 timezone,
78 Some(*op),
79 false,
80 )?;
81 ColumnDefaultConstraint::Value(value)
82 } else {
83 return UnsupportedDefaultValueSnafu {
84 column_name,
85 expr: *expr.clone(),
86 }
87 .fail();
88 }
89 }
90 ColumnOption::Default(others) => {
91 return UnsupportedDefaultValueSnafu {
92 column_name,
93 expr: others.clone(),
94 }
95 .fail();
96 }
97 _ => {
98 return UnsupportedDefaultValueSnafu {
99 column_name,
100 expr: Expr::Value(SqlValue::Null.into()),
101 }
102 .fail();
103 }
104 };
105
106 Ok(Some(default_constraint))
107 } else {
108 Ok(None)
109 }
110}
111
112#[cfg(test)]
113mod test {
114 use std::assert_matches::assert_matches;
115
116 use datatypes::prelude::{ConcreteDataType, Value};
117 use datatypes::types::BooleanType;
118
119 use super::*;
120
121 #[test]
122 pub fn test_parse_column_default_constraint() {
123 let bool_value = sqlparser::ast::Value::Boolean(true);
124
125 let opts = vec![
126 ColumnOptionDef {
127 name: None,
128 option: ColumnOption::Default(Expr::Value(bool_value.into())),
129 },
130 ColumnOptionDef {
131 name: None,
132 option: ColumnOption::NotNull,
133 },
134 ];
135
136 let constraint = parse_column_default_constraint(
137 "coll",
138 &ConcreteDataType::Boolean(BooleanType),
139 &opts,
140 None,
141 )
142 .unwrap();
143
144 assert_matches!(
145 constraint,
146 Some(ColumnDefaultConstraint::Value(Value::Boolean(true)))
147 );
148
149 let opts = vec![ColumnOptionDef {
151 name: None,
152 option: ColumnOption::Default(Expr::UnaryOp {
153 op: UnaryOperator::Minus,
154 expr: Box::new(Expr::Value(
155 SqlValue::Number("32768".to_string(), false).into(),
156 )),
157 }),
158 }];
159
160 let constraint = parse_column_default_constraint(
161 "coll",
162 &ConcreteDataType::int16_datatype(),
163 &opts,
164 None,
165 )
166 .unwrap();
167
168 assert_matches!(
169 constraint,
170 Some(ColumnDefaultConstraint::Value(Value::Int16(-32768)))
171 );
172 }
173
174 #[test]
175 fn test_incorrect_default_value_issue_3479() {
176 let opts = vec![ColumnOptionDef {
177 name: None,
178 option: ColumnOption::Default(Expr::Value(
179 SqlValue::Number("0.047318541668048164".into(), false).into(),
180 )),
181 }];
182 let constraint = parse_column_default_constraint(
183 "coll",
184 &ConcreteDataType::float64_datatype(),
185 &opts,
186 None,
187 )
188 .unwrap()
189 .unwrap();
190 assert_eq!("0.047318541668048164", constraint.to_string());
191 let encoded: Vec<u8> = constraint.clone().try_into().unwrap();
192 let decoded = ColumnDefaultConstraint::try_from(encoded.as_ref()).unwrap();
193 assert_eq!(decoded, constraint);
194 }
195}