mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-28 10:50:39 +00:00
feat: Support altering table TTL (#4848)
* feat/alter-ttl: Update greptime-proto source and add ChangeTableOptions handling - Change greptime-proto source repository and revision in Cargo.lock and Cargo.toml - Implement handling for ChangeTableOptions in grpc-expr and meta modules - Add support for parsing and applying region option changes in mito2 - Introduce new error type for invalid change table option requests - Add humantime dependency to store-api - Fix SQL syntax in tests for changing column types * chore: remove write buffer size option handling since we don't support specifying write_buffer_size for single table or region * persist ttl to manifest * chore: add sqlness * fix: sqlness * fix: typo and toml format * fix: tests * update: change alter syntax * feat/alter-ttl: Add Clone trait to RegionFlushRequest and remove redundant Default derive in region_request.rs. * feat/alter-ttl: Refactor code to replace 'ChangeTableOption' with 'ChangeRegionOption' and handle TTL as a region option • Rename ChangeTableOption to ChangeRegionOption across various files. • Update AlterKind::ChangeTableOptions to AlterKind::ChangeRegionOptions. • Modify TTL handling to treat '0d' as None for TTL in table options. • Adjust related function names and comments to reflect the change from table to region options. • Include test case updates to verify the new TTL handling behavior. * chore: update format * refactor: update region options in DatanodeTableValue * feat/alter-ttl: Remove TTL handling from RegionManifest and related structures - Eliminate TTL fields from `RegionManifest`, `RegionChange`, and associated handling logic. - Update tests and checksums to reflect removal of TTL. - Refactor `RegionOpener` and `handle_alter` to adjust to TTL removal. - Simplify `RegionChangeResult` by replacing `change` with `new_meta`. * chore: fmt * remove useless delete op * feat/alter-ttl: Updated Cargo.lock and gRPC expression Cargo.toml to include store-api dependency. Refactored alter.rs to use ChangeOption from store-api instead of ChangeTableOptionRequest. Adjusted error handling in error.rs to use MetadataError. Modified handle_alter.rs to handle TTL changes with ChangeOption. Simplified region_request.rs by replacing ChangeRegionOption with ChangeOption and removing redundant code. Removed UnsupportedTableOptionChange error in table/src/error.rs. Updated metadata.rs to use ChangeOption for table options. Removed ChangeTableOptionRequest enum and related conversion code from requests.rs. * feat/alter-ttl: Update greptime-proto dependency to revision 53ab9a9553 * chore: format code * chore: update greptime-proto
This commit is contained in:
@@ -15,12 +15,12 @@
|
||||
use common_query::AddColumnLocation;
|
||||
use snafu::ResultExt;
|
||||
use sqlparser::keywords::Keyword;
|
||||
use sqlparser::parser::ParserError;
|
||||
use sqlparser::parser::{Parser, ParserError};
|
||||
use sqlparser::tokenizer::Token;
|
||||
|
||||
use crate::error::{self, Result};
|
||||
use crate::parser::ParserContext;
|
||||
use crate::statements::alter::{AlterTable, AlterTableOperation};
|
||||
use crate::statements::alter::{AlterTable, AlterTableOperation, ChangeTableOption};
|
||||
use crate::statements::statement::Statement;
|
||||
|
||||
impl ParserContext<'_> {
|
||||
@@ -94,6 +94,14 @@ impl ParserContext<'_> {
|
||||
}
|
||||
};
|
||||
AlterTableOperation::RenameTable { new_table_name }
|
||||
} else if self.parser.parse_keyword(Keyword::SET) {
|
||||
let options = self
|
||||
.parser
|
||||
.parse_comma_separated(parse_string_options)?
|
||||
.into_iter()
|
||||
.map(|(key, value)| ChangeTableOption { key, value })
|
||||
.collect();
|
||||
AlterTableOperation::ChangeTableOptions { options }
|
||||
} else {
|
||||
return Err(ParserError::ParserError(format!(
|
||||
"expect keyword ADD or DROP or MODIFY or RENAME after ALTER TABLE, found {}",
|
||||
@@ -104,6 +112,22 @@ impl ParserContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_string_options(parser: &mut Parser) -> std::result::Result<(String, String), ParserError> {
|
||||
let name = parser.parse_literal_string()?;
|
||||
parser.expect_token(&Token::Eq)?;
|
||||
let value = if parser.parse_keyword(Keyword::NULL) {
|
||||
"".to_string()
|
||||
} else if let Ok(v) = parser.parse_literal_string() {
|
||||
v
|
||||
} else {
|
||||
return Err(ParserError::ParserError(format!(
|
||||
"Unexpected option value for alter table statements, expect string literal or NULL, got: `{}`",
|
||||
parser.next_token()
|
||||
)));
|
||||
};
|
||||
Ok((name, value))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::assert_matches::assert_matches;
|
||||
@@ -272,7 +296,7 @@ mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let sql_2 = "ALTER TABLE my_metric_1 MODIFY a STRING";
|
||||
let sql_2 = "ALTER TABLE my_metric_1 MODIFY COLUMN a STRING";
|
||||
let mut result_2 = ParserContext::create_with_dialect(
|
||||
sql_2,
|
||||
&GreptimeDbDialect {},
|
||||
@@ -406,4 +430,44 @@ mod tests {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_parse_alter_table(sql: &str, expected: &[(&str, &str)]) {
|
||||
let result =
|
||||
ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
|
||||
.unwrap();
|
||||
assert_eq!(1, result.len());
|
||||
let Statement::Alter(alter) = &result[0] else {
|
||||
unreachable!()
|
||||
};
|
||||
assert_eq!("test_table", alter.table_name.0[0].value);
|
||||
let AlterTableOperation::ChangeTableOptions { options } = &alter.alter_operation else {
|
||||
unreachable!()
|
||||
};
|
||||
let res = options
|
||||
.iter()
|
||||
.map(|o| (o.key.as_str(), o.value.as_str()))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(expected, &res);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_alter_column() {
|
||||
check_parse_alter_table("ALTER TABLE test_table SET 'a'='A';", &[("a", "A")]);
|
||||
check_parse_alter_table(
|
||||
"ALTER TABLE test_table SET 'a'='A','b'='B'",
|
||||
&[("a", "A"), ("b", "B")],
|
||||
);
|
||||
check_parse_alter_table(
|
||||
"ALTER TABLE test_table SET 'a'='A','b'='B','c'='C';",
|
||||
&[("a", "A"), ("b", "B"), ("c", "C")],
|
||||
);
|
||||
check_parse_alter_table("ALTER TABLE test_table SET 'a'=NULL;", &[("a", "")]);
|
||||
|
||||
ParserContext::create_with_dialect(
|
||||
"ALTER TABLE test_table SET a INTEGER",
|
||||
&GreptimeDbDialect {},
|
||||
ParseOptions::default(),
|
||||
)
|
||||
.unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,15 @@
|
||||
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
use api::v1;
|
||||
use common_query::AddColumnLocation;
|
||||
use sqlparser::ast::{ColumnDef, DataType, Ident, ObjectName, TableConstraint};
|
||||
use sqlparser_derive::{Visit, VisitMut};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
pub struct AlterTable {
|
||||
table_name: ObjectName,
|
||||
alter_operation: AlterTableOperation,
|
||||
pub table_name: ObjectName,
|
||||
pub alter_operation: AlterTableOperation,
|
||||
}
|
||||
|
||||
impl AlterTable {
|
||||
@@ -67,6 +68,8 @@ pub enum AlterTableOperation {
|
||||
column_name: Ident,
|
||||
target_type: DataType,
|
||||
},
|
||||
/// `MODIFY <table attrs key> = <table attr value>`
|
||||
ChangeTableOptions { options: Vec<ChangeTableOption> },
|
||||
/// `DROP COLUMN <name>`
|
||||
DropColumn { name: Ident },
|
||||
/// `RENAME <new_table_name>`
|
||||
@@ -97,6 +100,27 @@ impl Display for AlterTableOperation {
|
||||
} => {
|
||||
write!(f, r#"MODIFY COLUMN {column_name} {target_type}"#)
|
||||
}
|
||||
AlterTableOperation::ChangeTableOptions { options } => {
|
||||
for ChangeTableOption { key, value } in options {
|
||||
write!(f, r#"MODIFY '{key}'='{value}', "#)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut)]
|
||||
pub struct ChangeTableOption {
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl From<ChangeTableOption> for v1::ChangeTableOption {
|
||||
fn from(c: ChangeTableOption) -> Self {
|
||||
v1::ChangeTableOption {
|
||||
key: c.key,
|
||||
value: c.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user