From 438791b3e4f5165f2ae6464da885e7afc56387b6 Mon Sep 17 00:00:00 2001 From: Lin Yihai Date: Tue, 17 Jun 2025 17:33:56 +0800 Subject: [PATCH] feat: Add `DROP DEFAULT` (#6290) * feat: Add `DROP DEFAULT` Signed-off-by: Yihai Lin * chore: use `next_token` Signed-off-by: Yihai Lin --------- Signed-off-by: Yihai Lin --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/common/grpc-expr/src/alter.rs | 16 +++ .../src/ddl/alter_table/region_request.rs | 1 + .../src/ddl/alter_table/update_metadata.rs | 3 +- src/operator/src/expr_helper.rs | 21 +++- src/sql/src/parsers/alter_parser.rs | 89 +++++++++++++- src/sql/src/statements/alter.rs | 35 ++++++ src/store-api/src/metadata.rs | 99 ++++++++++++++- src/store-api/src/region_request.rs | 16 +++ src/table/src/metadata.rs | 55 ++++++++- src/table/src/requests.rs | 3 + ...ter_table_alter_column_drop_default.result | 113 ++++++++++++++++++ .../alter_table_alter_column_drop_default.sql | 30 +++++ 14 files changed, 474 insertions(+), 11 deletions(-) create mode 100644 tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.result create mode 100644 tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.sql diff --git a/Cargo.lock b/Cargo.lock index 54327fbbb3..5f703e2c94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5143,7 +5143,7 @@ dependencies = [ [[package]] name = "greptime-proto" version = "0.1.0" -source = "git+https://github.com/GreptimeTeam/greptime-proto.git?rev=fdcbe5f1c7c467634c90a1fd1a00a784b92a4e80#fdcbe5f1c7c467634c90a1fd1a00a784b92a4e80" +source = "git+https://github.com/firefantasy/greptime-proto.git?rev=abaee5144a833a025f5bc0e41642ef733d9c5c98#abaee5144a833a025f5bc0e41642ef733d9c5c98" dependencies = [ "prost 0.13.5", "serde", diff --git a/Cargo.toml b/Cargo.toml index 636162fd2d..95c2f97af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -134,7 +134,7 @@ etcd-client = "0.14" fst = "0.4.7" futures = "0.3" futures-util = "0.3" -greptime-proto = { git = "https://github.com/GreptimeTeam/greptime-proto.git", rev = "fdcbe5f1c7c467634c90a1fd1a00a784b92a4e80" } +greptime-proto = { git = "https://github.com/firefantasy/greptime-proto.git", rev = "abaee5144a833a025f5bc0e41642ef733d9c5c98" } hex = "0.4" http = "1" humantime = "2.1" diff --git a/src/common/grpc-expr/src/alter.rs b/src/common/grpc-expr/src/alter.rs index 5afa8e3487..5688f3c989 100644 --- a/src/common/grpc-expr/src/alter.rs +++ b/src/common/grpc-expr/src/alter.rs @@ -180,6 +180,22 @@ pub fn alter_expr_to_request(table_id: TableId, expr: AlterTableExpr) -> Result< }, None => return MissingAlterIndexOptionSnafu.fail(), }, + Kind::DropDefaults(o) => { + let names = o + .drop_defaults + .into_iter() + .map(|col| { + ensure!( + !col.column_name.is_empty(), + MissingFieldSnafu { + field: "column_name" + } + ); + Ok(col.column_name) + }) + .collect::>>()?; + AlterKind::DropDefaults { names } + } }; let request = AlterTableRequest { diff --git a/src/common/meta/src/ddl/alter_table/region_request.rs b/src/common/meta/src/ddl/alter_table/region_request.rs index ef3038cfba..cf8e0d57aa 100644 --- a/src/common/meta/src/ddl/alter_table/region_request.rs +++ b/src/common/meta/src/ddl/alter_table/region_request.rs @@ -135,6 +135,7 @@ fn create_proto_alter_kind( Kind::UnsetTableOptions(v) => Ok(Some(alter_request::Kind::UnsetTableOptions(v.clone()))), Kind::SetIndex(v) => Ok(Some(alter_request::Kind::SetIndex(v.clone()))), Kind::UnsetIndex(v) => Ok(Some(alter_request::Kind::UnsetIndex(v.clone()))), + Kind::DropDefaults(v) => Ok(Some(alter_request::Kind::DropDefaults(v.clone()))), } } diff --git a/src/common/meta/src/ddl/alter_table/update_metadata.rs b/src/common/meta/src/ddl/alter_table/update_metadata.rs index f7cf073b48..08ea63689e 100644 --- a/src/common/meta/src/ddl/alter_table/update_metadata.rs +++ b/src/common/meta/src/ddl/alter_table/update_metadata.rs @@ -61,7 +61,8 @@ impl AlterTableProcedure { | AlterKind::SetTableOptions { .. } | AlterKind::UnsetTableOptions { .. } | AlterKind::SetIndex { .. } - | AlterKind::UnsetIndex { .. } => {} + | AlterKind::UnsetIndex { .. } + | AlterKind::DropDefaults { .. } => {} } Ok(new_info) diff --git a/src/operator/src/expr_helper.rs b/src/operator/src/expr_helper.rs index eff0ec5555..6b07e0e40f 100644 --- a/src/operator/src/expr_helper.rs +++ b/src/operator/src/expr_helper.rs @@ -24,11 +24,11 @@ use api::v1::column_def::options_from_column_schema; use api::v1::{ set_index, unset_index, AddColumn, AddColumns, AlterDatabaseExpr, AlterTableExpr, Analyzer, ColumnDataType, ColumnDataTypeExtension, CreateFlowExpr, CreateTableExpr, CreateViewExpr, - DropColumn, DropColumns, ExpireAfter, FulltextBackend as PbFulltextBackend, ModifyColumnType, - ModifyColumnTypes, RenameTable, SemanticType, SetDatabaseOptions, SetFulltext, SetIndex, - SetInverted, SetSkipping, SetTableOptions, SkippingIndexType as PbSkippingIndexType, TableName, - UnsetDatabaseOptions, UnsetFulltext, UnsetIndex, UnsetInverted, UnsetSkipping, - UnsetTableOptions, + DropColumn, DropColumns, DropDefaults, ExpireAfter, FulltextBackend as PbFulltextBackend, + ModifyColumnType, ModifyColumnTypes, RenameTable, SemanticType, SetDatabaseOptions, + SetFulltext, SetIndex, SetInverted, SetSkipping, SetTableOptions, + SkippingIndexType as PbSkippingIndexType, TableName, UnsetDatabaseOptions, UnsetFulltext, + UnsetIndex, UnsetInverted, UnsetSkipping, UnsetTableOptions, }; use common_error::ext::BoxedError; use common_grpc_expr::util::ColumnExpr; @@ -631,6 +631,17 @@ pub(crate) fn to_alter_table_expr( })), }, }), + AlterTableOperation::DropDefaults { columns } => { + AlterTableKind::DropDefaults(DropDefaults { + drop_defaults: columns + .into_iter() + .map(|col| { + let column_name = col.0.to_string(); + Ok(api::v1::DropDefault { column_name }) + }) + .collect::>>()?, + }) + } }; Ok(AlterTableExpr { diff --git a/src/sql/src/parsers/alter_parser.rs b/src/sql/src/parsers/alter_parser.rs index 0cfd4b0964..1d922f2f32 100644 --- a/src/sql/src/parsers/alter_parser.rs +++ b/src/sql/src/parsers/alter_parser.rs @@ -30,7 +30,7 @@ use crate::parsers::utils::{ }; use crate::statements::alter::{ AddColumn, AlterDatabase, AlterDatabaseOperation, AlterTable, AlterTableOperation, - KeyValueOption, SetIndexOperation, UnsetIndexOperation, + DropDefaultsOperation, KeyValueOption, SetIndexOperation, UnsetIndexOperation, }; use crate::statements::statement::Statement; use crate::util::parse_option_string; @@ -156,6 +156,7 @@ impl ParserContext<'_> { .collect(); AlterTableOperation::SetTableOptions { options } } + Keyword::ALTER => self.parse_alter_columns()?, _ => self.expected( "ADD or DROP or MODIFY or RENAME or SET after ALTER TABLE", self.parser.peek_token(), @@ -168,6 +169,29 @@ impl ParserContext<'_> { Ok(AlterTable::new(table_name, alter_operation)) } + // Parse the following: ALTER TABLE table_name ALTER ... + fn parse_alter_columns(&mut self) -> Result { + let _ = self.parser.next_token(); + let _ = self.parser.next_token(); + let ts = self.parser.next_token(); + match ts.token { + // Parse `DROP DEFAULT`: ALTER TABLE `table_name` ALTER `a` DROP DEFAULT, ALTER `b` DROP DEFAULT, ... + Token::Word(w) if w.keyword == Keyword::DROP => { + let ts = self.parser.peek_token(); + match ts.token { + Token::Word(w) if w.keyword == Keyword::DEFAULT => { + self.parser.prev_token(); + self.parser.prev_token(); + self.parser.prev_token(); + self.parse_alter_table_drop_default() + } + _ => self.expected("DEFAULT is expecting after DROP", ts), + } + } + _ => self.expected("DROP after ALTER COLUMN", ts), + } + } + fn parse_alter_table_unset(&mut self) -> Result { let _ = self.parser.next_token(); let keys = self @@ -198,6 +222,14 @@ impl ParserContext<'_> { } } + fn parse_alter_table_drop_default(&mut self) -> Result { + let columns = self + .parser + .parse_comma_separated(parse_alter_column_drop_default) + .context(error::SyntaxSnafu)?; + Ok(AlterTableOperation::DropDefaults { columns }) + } + fn parse_alter_table_modify(&mut self) -> Result { let _ = self.parser.next_token(); self.parser @@ -385,6 +417,23 @@ impl ParserContext<'_> { } } +fn parse_alter_column_drop_default( + parser: &mut Parser, +) -> std::result::Result { + parser.next_token(); + let column_name = ParserContext::canonicalize_identifier(parser.parse_identifier()?); + if parser.parse_keywords(&[Keyword::DROP, Keyword::DEFAULT]) { + Ok(DropDefaultsOperation(column_name)) + } else { + let not_drop = parser.peek_token(); + parser.next_token(); + let not_default = parser.peek_token(); + Err(ParserError::ParserError(format!( + "Unexpected keyword, expect DROP DEFAULT, got: `{not_drop} {not_default}`" + ))) + } +} + /// Parses a string literal and an optional string literal value. fn parse_string_options(parser: &mut Parser) -> std::result::Result<(String, String), ParserError> { let name = parser.parse_literal_string()?; @@ -1125,4 +1174,42 @@ mod tests { } } } + + #[test] + fn test_parse_alter_drop_default() { + let columns = vec![vec!["a"], vec!["a", "b", "c"]]; + for col in columns { + let sql = col + .iter() + .map(|x| format!("ALTER {x} DROP DEFAULT")) + .collect::>() + .join(","); + let sql = format!("ALTER TABLE test_table {sql}"); + let mut result = ParserContext::create_with_dialect( + &sql, + &GreptimeDbDialect {}, + ParseOptions::default(), + ) + .unwrap(); + assert_eq!(1, result.len()); + let statement = result.remove(0); + assert_matches!(statement, Statement::AlterTable { .. }); + match statement { + Statement::AlterTable(alter_table) => { + assert_eq!("test_table", alter_table.table_name().0[0].value); + let alter_operation = alter_table.alter_operation(); + match alter_operation { + AlterTableOperation::DropDefaults { columns } => { + assert_eq!(col.len(), columns.len()); + for i in 0..columns.len() { + assert_eq!(col[i], columns[i].0.value); + } + } + _ => unreachable!(), + } + } + _ => unreachable!(), + } + } + } } diff --git a/src/sql/src/statements/alter.rs b/src/sql/src/statements/alter.rs index 5aec1cfb47..ae865c5b7b 100644 --- a/src/sql/src/statements/alter.rs +++ b/src/sql/src/statements/alter.rs @@ -92,8 +92,15 @@ pub enum AlterTableOperation { UnsetIndex { options: UnsetIndexOperation, }, + DropDefaults { + columns: Vec, + }, } +#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)] +/// `ALTER DROP DEFAULT` +pub struct DropDefaultsOperation(pub Ident); + #[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)] pub enum SetIndexOperation { /// `MODIFY COLUMN SET FULLTEXT INDEX [WITH ]` @@ -204,6 +211,13 @@ impl Display for AlterTableOperation { write!(f, "MODIFY COLUMN {column_name} UNSET SKIPPING INDEX") } }, + AlterTableOperation::DropDefaults { columns } => { + let columns = columns + .iter() + .map(|column| format!("ALTER {} DROP DEFAULT", column.0)) + .join(", "); + write!(f, "{columns}") + } } } } @@ -487,5 +501,26 @@ ALTER TABLE monitor MODIFY COLUMN a SET INVERTED INDEX"#, unreachable!(); } } + + let sql = "ALTER TABLE monitor ALTER a DROP DEFAULT"; + let stmts = + ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default()) + .unwrap(); + assert_eq!(1, stmts.len()); + assert_matches!(&stmts[0], Statement::AlterTable { .. }); + + match &stmts[0] { + Statement::AlterTable(set) => { + let new_sql = format!("\n{}", set); + assert_eq!( + r#" +ALTER TABLE monitor ALTER a DROP DEFAULT"#, + &new_sql + ); + } + _ => { + unreachable!(); + } + } } } diff --git a/src/store-api/src/metadata.rs b/src/store-api/src/metadata.rs index 453e0a1383..62cb1b7e60 100644 --- a/src/store-api/src/metadata.rs +++ b/src/store-api/src/metadata.rs @@ -612,6 +612,9 @@ impl RegionMetadataBuilder { AlterKind::UnsetRegionOptions { keys: _ } => { // nothing to be done with RegionMetadata } + AlterKind::DropDefaults { names } => { + self.drop_defaults(names)?; + } } Ok(self) } @@ -826,6 +829,40 @@ impl RegionMetadataBuilder { } Ok(()) } + + fn drop_defaults(&mut self, column_names: Vec) -> Result<()> { + for name in column_names.iter() { + let meta = self + .column_metadatas + .iter_mut() + .find(|col| col.column_schema.name == *name); + if let Some(meta) = meta { + if !meta.column_schema.is_nullable() { + return InvalidRegionRequestSnafu { + region_id: self.region_id, + err: format!( + "column {name} is not nullable and `default` cannot be dropped", + ), + } + .fail(); + } + meta.column_schema = meta + .column_schema + .clone() + .with_default_constraint(None) + .with_context(|_| CastDefaultValueSnafu { + reason: format!("Failed to drop default : {name:?}"), + })?; + } else { + return InvalidRegionRequestSnafu { + region_id: self.region_id, + err: format!("column {name} not found",), + } + .fail(); + } + } + Ok(()) + } } /// Fields skipped in serialization. @@ -1100,7 +1137,10 @@ fn unset_column_fulltext_options( #[cfg(test)] mod test { use datatypes::prelude::ConcreteDataType; - use datatypes::schema::{ColumnSchema, FulltextAnalyzer, FulltextBackend}; + use datatypes::schema::{ + ColumnDefaultConstraint, ColumnSchema, FulltextAnalyzer, FulltextBackend, + }; + use datatypes::value::Value; use super::*; @@ -1423,6 +1463,19 @@ mod test { assert_eq!(names, actual); } + fn get_columns_default_constraint( + metadata: &RegionMetadata, + name: String, + ) -> Option> { + metadata.column_metadatas.iter().find_map(|col| { + if col.column_schema.name == name { + Some(col.column_schema.default_constraint()) + } else { + None + } + }) + } + #[test] fn test_alter() { // a (tag), b (field), c (ts) @@ -1500,6 +1553,50 @@ mod test { let err = builder.build().unwrap_err(); assert_eq!(StatusCode::InvalidArguments, err.status_code()); + let mut builder: RegionMetadataBuilder = RegionMetadataBuilder::from_existing(metadata); + let mut column_metadata = new_column_metadata("g", false, 8); + let default_constraint = Some(ColumnDefaultConstraint::Value(Value::from("g"))); + column_metadata.column_schema = column_metadata + .column_schema + .with_default_constraint(default_constraint.clone()) + .unwrap(); + builder + .alter(AlterKind::AddColumns { + columns: vec![AddColumn { + column_metadata, + location: None, + }], + }) + .unwrap(); + let metadata = builder.build().unwrap(); + assert_eq!( + get_columns_default_constraint(&metadata, "g".to_string()).unwrap(), + default_constraint.as_ref() + ); + check_columns(&metadata, &["a", "b", "f", "c", "d", "g"]); + + let mut builder: RegionMetadataBuilder = RegionMetadataBuilder::from_existing(metadata); + builder + .alter(AlterKind::DropDefaults { + names: vec!["g".to_string()], + }) + .unwrap(); + let metadata = builder.build().unwrap(); + assert_eq!( + get_columns_default_constraint(&metadata, "g".to_string()).unwrap(), + None + ); + check_columns(&metadata, &["a", "b", "f", "c", "d", "g"]); + + let mut builder: RegionMetadataBuilder = RegionMetadataBuilder::from_existing(metadata); + builder + .alter(AlterKind::DropColumns { + names: vec!["g".to_string()], + }) + .unwrap(); + let metadata = builder.build().unwrap(); + check_columns(&metadata, &["a", "b", "f", "c", "d"]); + let mut builder = RegionMetadataBuilder::from_existing(metadata); builder .alter(AlterKind::ModifyColumnTypes { diff --git a/src/store-api/src/region_request.rs b/src/store-api/src/region_request.rs index 57c5aee71e..f9b71c4bc6 100644 --- a/src/store-api/src/region_request.rs +++ b/src/store-api/src/region_request.rs @@ -530,6 +530,11 @@ pub enum AlterKind { SetIndex { options: ApiSetIndexOptions }, /// Unset index options. UnsetIndex { options: ApiUnsetIndexOptions }, + /// Drop column default value. + DropDefaults { + /// Name of columns to drop. + names: Vec, + }, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -627,6 +632,11 @@ impl AlterKind { options.is_fulltext(), )?; } + AlterKind::DropDefaults { names } => { + names + .iter() + .try_for_each(|name| Self::validate_column_to_drop(name, metadata))?; + } } Ok(()) } @@ -656,6 +666,9 @@ impl AlterKind { AlterKind::UnsetIndex { options } => { metadata.column_by_name(options.column_name()).is_some() } + AlterKind::DropDefaults { names } => names + .iter() + .any(|name| metadata.column_by_name(name).is_some()), } } @@ -794,6 +807,9 @@ impl TryFrom for AlterKind { }, }, }, + alter_request::Kind::DropDefaults(x) => AlterKind::DropDefaults { + names: x.drop_defaults.into_iter().map(|x| x.column_name).collect(), + }, }; Ok(alter_kind) diff --git a/src/table/src/metadata.rs b/src/table/src/metadata.rs index 14f734afd4..5f644cbc10 100644 --- a/src/table/src/metadata.rs +++ b/src/table/src/metadata.rs @@ -264,6 +264,7 @@ impl TableMeta { self.change_column_skipping_index_options(table_name, column_name, None) } }, + AlterKind::DropDefaults { names } => self.drop_defaults(table_name, names), } } @@ -926,8 +927,60 @@ impl TableMeta { column_names, }) } -} + fn drop_defaults(&self, table_name: &str, column_names: &[String]) -> Result { + let table_schema = &self.schema; + let mut meta_builder = self.new_meta_builder(); + let mut columns = Vec::with_capacity(table_schema.num_columns()); + for column_schema in table_schema.column_schemas() { + if let Some(name) = column_names.iter().find(|s| **s == column_schema.name) { + // Drop default constraint. + ensure!( + column_schema.default_constraint().is_some(), + error::InvalidAlterRequestSnafu { + table: table_name, + err: format!("column {name} does not have a default value"), + } + ); + if !column_schema.is_nullable() { + return error::InvalidAlterRequestSnafu { + table: table_name, + err: format!( + "column {name} is not nullable and `default` cannot be dropped", + ), + } + .fail(); + } + let new_column_schema = column_schema.clone(); + let new_column_schema = new_column_schema + .with_default_constraint(None) + .with_context(|_| error::SchemaBuildSnafu { + msg: format!("Table {table_name} cannot drop default values"), + })?; + columns.push(new_column_schema); + } else { + columns.push(column_schema.clone()); + } + } + + let mut builder = SchemaBuilder::try_from_columns(columns) + .with_context(|_| error::SchemaBuildSnafu { + msg: format!("Failed to convert column schemas into schema for table {table_name}"), + })? + // Also bump the schema version. + .version(table_schema.version() + 1); + for (k, v) in table_schema.metadata().iter() { + builder = builder.add_metadata(k, v); + } + let new_schema = builder.build().with_context(|_| error::SchemaBuildSnafu { + msg: format!("Table {table_name} cannot drop default values"), + })?; + + let _ = meta_builder.schema(Arc::new(new_schema)); + + Ok(meta_builder) + } +} #[derive(Clone, Debug, PartialEq, Eq, Builder)] #[builder(pattern = "owned")] pub struct TableInfo { diff --git a/src/table/src/requests.rs b/src/table/src/requests.rs index 206bafe29c..7cbf5b3e1f 100644 --- a/src/table/src/requests.rs +++ b/src/table/src/requests.rs @@ -257,6 +257,9 @@ pub enum AlterKind { UnsetIndex { options: UnsetIndexOptions, }, + DropDefaults { + names: Vec, + }, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.result b/tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.result new file mode 100644 index 0000000000..a4ea729899 --- /dev/null +++ b/tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.result @@ -0,0 +1,113 @@ +--- alter table to add new column with default timestamp values aware of session timezone test --- +CREATE TABLE test1 (i INTEGER, j TIMESTAMP time index, PRIMARY KEY(i)); + +Affected Rows: 0 + +ALTER TABLE test1 ADD COLUMN k INTEGER DEFAULT 100; + +Affected Rows: 0 + +ALTER TABLE test1 ADD COLUMN l INTEGER DEFAULT 200; + +Affected Rows: 0 + +ALTER TABLE test1 ADD COLUMN m TIMESTAMP DEFAULT '2024-01-30 00:00:00'; + +Affected Rows: 0 + +ALTER TABLE test1 ADD COLUMN n INTEGER DEFAULT 300; + +Affected Rows: 0 + +SHOW CREATE TABLE test1; + ++-------+-------------------------------------------------------------+ +| Table | Create Table | ++-------+-------------------------------------------------------------+ +| test1 | CREATE TABLE IF NOT EXISTS "test1" ( | +| | "i" INT NULL, | +| | "j" TIMESTAMP(3) NOT NULL, | +| | "k" INT NULL DEFAULT 100, | +| | "l" INT NULL DEFAULT 200, | +| | "m" TIMESTAMP(3) NULL DEFAULT '2024-01-30 00:00:00+0000', | +| | "n" INT NULL DEFAULT 300, | +| | TIME INDEX ("j"), | +| | PRIMARY KEY ("i") | +| | ) | +| | | +| | ENGINE=mito | +| | | ++-------+-------------------------------------------------------------+ + +INSERT INTO test1 VALUES (1, '2024-01-30 12:00:00', DEFAULT, DEFAULT, DEFAULT, DEFAULT); + +Affected Rows: 1 + +SELECT * FROM test1; + ++---+---------------------+-----+-----+---------------------+-----+ +| i | j | k | l | m | n | ++---+---------------------+-----+-----+---------------------+-----+ +| 1 | 2024-01-30T12:00:00 | 100 | 200 | 2024-01-30T00:00:00 | 300 | ++---+---------------------+-----+-----+---------------------+-----+ + +ALTER TABLE test1 ALTER k DROP DEFAULT; + +Affected Rows: 0 + +ALTER TABLE test1 ALTER l DROP DEFAULT, ALTER m DROP DEFAULT, ALTER n DROP DEFAULT; + +Affected Rows: 0 + +SHOW CREATE TABLE test1; + ++-------+--------------------------------------+ +| Table | Create Table | ++-------+--------------------------------------+ +| test1 | CREATE TABLE IF NOT EXISTS "test1" ( | +| | "i" INT NULL, | +| | "j" TIMESTAMP(3) NOT NULL, | +| | "k" INT NULL, | +| | "l" INT NULL, | +| | "m" TIMESTAMP(3) NULL, | +| | "n" INT NULL, | +| | TIME INDEX ("j"), | +| | PRIMARY KEY ("i") | +| | ) | +| | | +| | ENGINE=mito | +| | | ++-------+--------------------------------------+ + +INSERT INTO test1 VALUES (1, '2024-01-30 12:00:00', DEFAULT, DEFAULT, DEFAULT, DEFAULT); + +Affected Rows: 1 + +SELECT * FROM test1; + ++---+---------------------+---+---+---+---+ +| i | j | k | l | m | n | ++---+---------------------+---+---+---+---+ +| 1 | 2024-01-30T12:00:00 | | | | | ++---+---------------------+---+---+---+---+ + +ALTER TABLE test1 ADD COLUMN o INTEGER NOT NULL DEFAULT 400; + +Affected Rows: 0 + +SELECT * FROM test1; + ++---+---------------------+---+---+---+---+-----+ +| i | j | k | l | m | n | o | ++---+---------------------+---+---+---+---+-----+ +| 1 | 2024-01-30T12:00:00 | | | | | 400 | ++---+---------------------+---+---+---+---+-----+ + +ALTER TABLE test1 ALTER o DROP DEFAULT; + +Error: 1004(InvalidArguments), Invalid alter table(test1) request: column o is not nullable and `default` cannot be dropped + +DROP TABLE test1; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.sql b/tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.sql new file mode 100644 index 0000000000..4e0eeebc39 --- /dev/null +++ b/tests/cases/standalone/common/alter/alter_table_alter_column_drop_default.sql @@ -0,0 +1,30 @@ +--- alter table to add new column with default timestamp values aware of session timezone test --- + +CREATE TABLE test1 (i INTEGER, j TIMESTAMP time index, PRIMARY KEY(i)); + +ALTER TABLE test1 ADD COLUMN k INTEGER DEFAULT 100; +ALTER TABLE test1 ADD COLUMN l INTEGER DEFAULT 200; +ALTER TABLE test1 ADD COLUMN m TIMESTAMP DEFAULT '2024-01-30 00:00:00'; +ALTER TABLE test1 ADD COLUMN n INTEGER DEFAULT 300; + +SHOW CREATE TABLE test1; + +INSERT INTO test1 VALUES (1, '2024-01-30 12:00:00', DEFAULT, DEFAULT, DEFAULT, DEFAULT); + +SELECT * FROM test1; + +ALTER TABLE test1 ALTER k DROP DEFAULT; +ALTER TABLE test1 ALTER l DROP DEFAULT, ALTER m DROP DEFAULT, ALTER n DROP DEFAULT; + +SHOW CREATE TABLE test1; + +INSERT INTO test1 VALUES (1, '2024-01-30 12:00:00', DEFAULT, DEFAULT, DEFAULT, DEFAULT); + +SELECT * FROM test1; + +ALTER TABLE test1 ADD COLUMN o INTEGER NOT NULL DEFAULT 400; +SELECT * FROM test1; + +ALTER TABLE test1 ALTER o DROP DEFAULT; + +DROP TABLE test1;