fix: unused table options (#2267)

* fix: unused table options keys

* refactor: simplify validate table options

* chore: Add newlines

---------

Co-authored-by: Yingwen <realevenyag@gmail.com>
This commit is contained in:
Niwaka
2023-09-03 15:56:05 +09:00
committed by Ruihang Xia
parent fad58835bf
commit 3504d8254e
15 changed files with 305 additions and 14 deletions

View File

@@ -19,6 +19,7 @@ once_cell.workspace = true
regex.workspace = true
snafu = { version = "0.7", features = ["backtraces"] }
sqlparser.workspace = true
table = { workspace = true }
[dev-dependencies]
common-datasource = { workspace = true }

View File

@@ -103,6 +103,9 @@ pub enum Error {
source: datatypes::error::Error,
},
#[snafu(display("Invalid table option key: {}", key))]
InvalidTableOption { key: String, location: Location },
#[snafu(display("Failed to serialize column default constraint, source: {}", source))]
SerializeColumnDefaultConstraint {
location: Location,
@@ -168,7 +171,8 @@ impl ErrorExt for Error {
| ColumnTypeMismatch { .. }
| InvalidTableName { .. }
| InvalidSqlValue { .. }
| TimestampOverflow { .. } => StatusCode::InvalidArguments,
| TimestampOverflow { .. }
| InvalidTableOption { .. } => StatusCode::InvalidArguments,
SerializeColumnDefaultConstraint { source, .. } => source.status_code(),
ConvertToGrpcDataType { source, .. } => source.status_code(),

View File

@@ -13,6 +13,7 @@
// limitations under the License.
use std::cmp::Ordering;
use std::collections::HashMap;
use common_catalog::consts::default_engine;
use itertools::Itertools;
@@ -24,11 +25,12 @@ use sqlparser::keywords::ALL_KEYWORDS;
use sqlparser::parser::IsOptional::Mandatory;
use sqlparser::parser::{Parser, ParserError};
use sqlparser::tokenizer::{Token, TokenWithLocation, Word};
use table::requests::valid_table_option;
use crate::ast::{ColumnDef, Ident, TableConstraint, Value as SqlValue};
use crate::error::{
self, InvalidColumnOptionSnafu, InvalidTimeIndexSnafu, MissingTimeIndexSnafu, Result,
SyntaxSnafu,
self, InvalidColumnOptionSnafu, InvalidTableOptionSnafu, InvalidTimeIndexSnafu,
MissingTimeIndexSnafu, Result, SyntaxSnafu,
};
use crate::parser::ParserContext;
use crate::statements::create::{
@@ -91,8 +93,15 @@ impl<'a> ParserContext<'a> {
None
}
})
.collect();
.collect::<HashMap<String, String>>();
for key in options.keys() {
ensure!(
valid_table_option(key),
InvalidTableOptionSnafu {
key: key.to_string()
}
);
}
Ok(Statement::CreateExternalTable(CreateExternalTable {
name: table_name,
columns,
@@ -149,7 +158,14 @@ impl<'a> ParserContext<'a> {
.parser
.parse_options(Keyword::WITH)
.context(error::SyntaxSnafu { sql: self.sql })?;
for option in options.iter() {
ensure!(
valid_table_option(&option.name.value),
InvalidTableOptionSnafu {
key: option.name.value.to_string()
}
);
}
let create_table = CreateTable {
if_not_exists,
name: table_name,
@@ -807,6 +823,24 @@ mod tests {
use super::*;
use crate::dialect::GreptimeDbDialect;
#[test]
fn test_validate_external_table_options() {
let sql = "CREATE EXTERNAL TABLE city (
host string,
ts int64,
cpu float64 default 0,
memory float64,
TIME INDEX (ts),
PRIMARY KEY(ts, host)
) with(location='/var/data/city.csv',format='csv',foo='bar');";
let result = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {});
assert!(matches!(
result,
Err(error::Error::InvalidTableOption { .. })
));
}
#[test]
fn test_parse_create_external_table() {
struct Test<'a> {

View File

@@ -222,6 +222,7 @@ pub struct CreateExternalTable {
#[cfg(test)]
mod tests {
use crate::dialect::GreptimeDbDialect;
use crate::error::Error::InvalidTableOption;
use crate::parser::ParserContext;
use crate::statements::statement::Statement;
@@ -319,4 +320,26 @@ ENGINE=mito
_ => unreachable!(),
}
}
#[test]
fn test_validate_table_options() {
let sql = r"create table if not exists demo(
host string,
ts bigint,
cpu double default 0,
memory double,
TIME INDEX (ts),
PRIMARY KEY(ts, host)
)
PARTITION BY RANGE COLUMNS (ts) (
PARTITION r0 VALUES LESS THAN (5),
PARTITION r1 VALUES LESS THAN (9),
PARTITION r2 VALUES LESS THAN (MAXVALUE),
)
engine=mito
with(regions=1, ttl='7d', hello='world');
";
let result = ParserContext::create_with_dialect(sql, &GreptimeDbDialect {});
assert!(matches!(result, Err(InvalidTableOption { .. })))
}
}