feat: support default value when inserting data (#854)

This commit is contained in:
Zheming Li
2023-01-13 14:49:05 +08:00
committed by GitHub
parent e428a84446
commit 0959c1d16b
8 changed files with 224 additions and 52 deletions

View File

@@ -131,6 +131,9 @@ pub enum Error {
#[snafu(backtrace)]
source: api::error::Error,
},
#[snafu(display("Invalid sql value: {}", value))]
InvalidSqlValue { value: String, backtrace: Backtrace },
}
impl ErrorExt for Error {
@@ -156,6 +159,7 @@ impl ErrorExt for Error {
UnsupportedAlterTableStatement { .. } => StatusCode::InvalidSyntax,
SerializeColumnDefaultConstraint { source, .. } => source.status_code(),
ConvertToGrpcDataType { source, .. } => source.status_code(),
InvalidSqlValue { .. } => StatusCode::InvalidArguments,
}
}

View File

@@ -39,8 +39,9 @@ use crate::ast::{
Value as SqlValue,
};
use crate::error::{
self, ColumnTypeMismatchSnafu, ConvertToGrpcDataTypeSnafu, ParseSqlValueSnafu, Result,
SerializeColumnDefaultConstraintSnafu, UnsupportedDefaultValueSnafu,
self, ColumnTypeMismatchSnafu, ConvertToGrpcDataTypeSnafu, InvalidSqlValueSnafu,
ParseSqlValueSnafu, Result, SerializeColumnDefaultConstraintSnafu,
UnsupportedDefaultValueSnafu,
};
// TODO(LFC): Get rid of this function, use session context aware version of "table_idents_to_full_name" instead.
@@ -222,6 +223,7 @@ pub fn sql_value_to_value(
parse_string_to_value(column_name, s.to_owned(), data_type)?
}
SqlValue::HexStringLiteral(s) => parse_hex_string(s)?,
SqlValue::Placeholder(s) => return InvalidSqlValueSnafu { value: s }.fail(),
_ => todo!("Other sql value"),
})
}
@@ -720,4 +722,14 @@ mod tests {
assert!(!column_schema.is_nullable());
assert!(!column_schema.is_time_index());
}
#[test]
pub fn test_parse_placeholder_value() {
assert!(sql_value_to_value(
"test",
&ConcreteDataType::string_datatype(),
&SqlValue::Placeholder("default".into())
)
.is_err());
}
}

View File

@@ -66,7 +66,13 @@ fn sql_exprs_to_values(exprs: &Vec<Vec<Expr>>) -> Result<Vec<Vec<Value>>> {
for expr in es.iter() {
vs.push(match expr {
Expr::Value(v) => v.clone(),
Expr::Identifier(ident) => Value::SingleQuotedString(ident.value.clone()),
Expr::Identifier(ident) => {
if ident.quote_style.is_none() {
Value::Placeholder(ident.value.clone())
} else {
Value::SingleQuotedString(ident.value.clone())
}
}
Expr::UnaryOp { op, expr }
if matches!(op, UnaryOperator::Minus | UnaryOperator::Plus) =>
{
@@ -146,4 +152,61 @@ mod tests {
_ => unreachable!(),
}
}
#[test]
fn test_insert_value_with_default() {
use crate::statements::statement::Statement;
// insert "default"
let sql = "INSERT INTO my_table VALUES(default)";
let stmt = ParserContext::create_with_dialect(sql, &GenericDialect {})
.unwrap()
.remove(0);
match stmt {
Statement::Insert(insert) => {
let values = insert.values().unwrap();
assert_eq!(values, vec![vec![Value::Placeholder("default".to_owned())]]);
}
_ => unreachable!(),
}
}
#[test]
fn test_insert_value_with_default_uppercase() {
use crate::statements::statement::Statement;
// insert "DEFAULT"
let sql = "INSERT INTO my_table VALUES(DEFAULT)";
let stmt = ParserContext::create_with_dialect(sql, &GenericDialect {})
.unwrap()
.remove(0);
match stmt {
Statement::Insert(insert) => {
let values = insert.values().unwrap();
assert_eq!(values, vec![vec![Value::Placeholder("DEFAULT".to_owned())]]);
}
_ => unreachable!(),
}
}
#[test]
fn test_insert_value_with_quoted_string() {
use crate::statements::statement::Statement;
// insert "'default'"
let sql = "INSERT INTO my_table VALUES('default')";
let stmt = ParserContext::create_with_dialect(sql, &GenericDialect {})
.unwrap()
.remove(0);
match stmt {
Statement::Insert(insert) => {
let values = insert.values().unwrap();
assert_eq!(
values,
vec![vec![Value::SingleQuotedString("default".to_owned())]]
);
}
_ => unreachable!(),
}
}
}