mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-17 13:30:38 +00:00
feat: distributed alter table in region server (#2311)
* feat: distributed alter table in region server * rebase
This commit is contained in:
@@ -82,5 +82,6 @@ client = { workspace = true }
|
||||
common-query = { workspace = true }
|
||||
common-test-util = { workspace = true }
|
||||
datafusion-common.workspace = true
|
||||
meta-srv = { workspace = true, features = ["mock"] }
|
||||
mito = { workspace = true, features = ["test"] }
|
||||
session = { workspace = true }
|
||||
|
||||
@@ -323,13 +323,13 @@ async fn new_dummy_catalog_list(
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use api::v1::add_column::location::LocationType;
|
||||
use api::v1::add_column::Location;
|
||||
use api::v1::add_column_location::LocationType;
|
||||
use api::v1::column::Values;
|
||||
use api::v1::{
|
||||
alter_expr, AddColumn, AddColumns, AlterExpr, Column, ColumnDataType, ColumnDef,
|
||||
CreateDatabaseExpr, CreateTableExpr, DeleteRequest, DropTableExpr, InsertRequest,
|
||||
InsertRequests, QueryRequest, RenameTable, SemanticType, TableId, TruncateTableExpr,
|
||||
alter_expr, AddColumn, AddColumnLocation as Location, AddColumns, AlterExpr, Column,
|
||||
ColumnDataType, ColumnDef, CreateDatabaseExpr, CreateTableExpr, DeleteRequest,
|
||||
DropTableExpr, InsertRequest, InsertRequests, QueryRequest, RenameTable, SemanticType,
|
||||
TableId, TruncateTableExpr,
|
||||
};
|
||||
use common_catalog::consts::MITO_ENGINE;
|
||||
use common_error::ext::ErrorExt;
|
||||
@@ -378,15 +378,17 @@ mod test {
|
||||
column_defs: vec![
|
||||
ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "ts".to_string(),
|
||||
datatype: ColumnDataType::TimestampMillisecond as i32,
|
||||
data_type: ColumnDataType::TimestampMillisecond as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Timestamp as i32,
|
||||
},
|
||||
],
|
||||
time_index: "ts".to_string(),
|
||||
@@ -432,15 +434,17 @@ mod test {
|
||||
column_defs: vec![
|
||||
ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "ts".to_string(),
|
||||
datatype: ColumnDataType::TimestampMillisecond as i32,
|
||||
data_type: ColumnDataType::TimestampMillisecond as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Timestamp as i32,
|
||||
},
|
||||
],
|
||||
time_index: "ts".to_string(),
|
||||
@@ -500,15 +504,17 @@ mod test {
|
||||
column_defs: vec![
|
||||
ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Field as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "ts".to_string(),
|
||||
datatype: ColumnDataType::TimestampMillisecond as i32,
|
||||
data_type: ColumnDataType::TimestampMillisecond as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Timestamp as i32,
|
||||
},
|
||||
],
|
||||
time_index: "ts".to_string(),
|
||||
@@ -531,22 +537,16 @@ mod test {
|
||||
add_columns: vec![AddColumn {
|
||||
column_def: Some(ColumnDef {
|
||||
name: "b".to_string(),
|
||||
datatype: ColumnDataType::Int32 as i32,
|
||||
data_type: ColumnDataType::Int32 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
}),
|
||||
is_key: true,
|
||||
location: None,
|
||||
}],
|
||||
})),
|
||||
..Default::default()
|
||||
})),
|
||||
});
|
||||
let output = instance
|
||||
.do_query(query.clone(), QueryContext::arc())
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(matches!(output, Output::AffectedRows(0)));
|
||||
|
||||
let output = instance.do_query(query, QueryContext::arc()).await.unwrap();
|
||||
assert!(matches!(output, Output::AffectedRows(0)));
|
||||
@@ -561,16 +561,14 @@ mod test {
|
||||
add_columns: vec![AddColumn {
|
||||
column_def: Some(ColumnDef {
|
||||
name: "b".to_string(),
|
||||
datatype: ColumnDataType::Int32 as i32,
|
||||
data_type: ColumnDataType::Int32 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
}),
|
||||
is_key: true,
|
||||
location: None,
|
||||
}],
|
||||
})),
|
||||
table_version: 1,
|
||||
..Default::default()
|
||||
})),
|
||||
});
|
||||
let err = instance
|
||||
@@ -582,7 +580,6 @@ mod test {
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_rename_table_twice() {
|
||||
common_telemetry::init_default_ut_logging();
|
||||
let instance = MockInstance::new("test_alter_table_twice").await;
|
||||
let instance = instance.inner();
|
||||
|
||||
@@ -605,15 +602,17 @@ mod test {
|
||||
column_defs: vec![
|
||||
ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Field as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "ts".to_string(),
|
||||
datatype: ColumnDataType::TimestampMillisecond as i32,
|
||||
data_type: ColumnDataType::TimestampMillisecond as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Timestamp as i32,
|
||||
},
|
||||
],
|
||||
time_index: "ts".to_string(),
|
||||
@@ -636,8 +635,6 @@ mod test {
|
||||
kind: Some(alter_expr::Kind::RenameTable(RenameTable {
|
||||
new_table_name: "new_my_table".to_string(),
|
||||
})),
|
||||
table_id: Some(TableId { id: 1025 }),
|
||||
..Default::default()
|
||||
})),
|
||||
});
|
||||
let output = instance
|
||||
@@ -647,11 +644,8 @@ mod test {
|
||||
assert!(matches!(output, Output::AffectedRows(0)));
|
||||
|
||||
// renames it again.
|
||||
let output = instance
|
||||
.do_query(query.clone(), QueryContext::arc())
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(matches!(output, Output::AffectedRows(0)));
|
||||
let result = instance.do_query(query, QueryContext::arc()).await;
|
||||
assert!(matches!(result, Err(error::Error::TableNotFound { .. })));
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
@@ -678,15 +672,17 @@ mod test {
|
||||
column_defs: vec![
|
||||
ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "ts".to_string(),
|
||||
datatype: ColumnDataType::TimestampMillisecond as i32,
|
||||
data_type: ColumnDataType::TimestampMillisecond as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Timestamp as i32,
|
||||
},
|
||||
],
|
||||
time_index: "ts".to_string(),
|
||||
@@ -707,21 +703,21 @@ mod test {
|
||||
AddColumn {
|
||||
column_def: Some(ColumnDef {
|
||||
name: "b".to_string(),
|
||||
datatype: ColumnDataType::Int32 as i32,
|
||||
data_type: ColumnDataType::Int32 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
}),
|
||||
is_key: true,
|
||||
location: None,
|
||||
},
|
||||
AddColumn {
|
||||
column_def: Some(ColumnDef {
|
||||
name: "c".to_string(),
|
||||
datatype: ColumnDataType::Int32 as i32,
|
||||
data_type: ColumnDataType::Int32 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
}),
|
||||
is_key: true,
|
||||
location: Some(Location {
|
||||
location_type: LocationType::First.into(),
|
||||
after_column_name: "".to_string(),
|
||||
@@ -730,11 +726,11 @@ mod test {
|
||||
AddColumn {
|
||||
column_def: Some(ColumnDef {
|
||||
name: "d".to_string(),
|
||||
datatype: ColumnDataType::Int32 as i32,
|
||||
data_type: ColumnDataType::Int32 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
}),
|
||||
is_key: true,
|
||||
location: Some(Location {
|
||||
location_type: LocationType::After.into(),
|
||||
after_column_name: "a".to_string(),
|
||||
@@ -742,7 +738,6 @@ mod test {
|
||||
},
|
||||
],
|
||||
})),
|
||||
..Default::default()
|
||||
})),
|
||||
});
|
||||
let output = instance.do_query(query, QueryContext::arc()).await.unwrap();
|
||||
|
||||
@@ -78,25 +78,20 @@ impl Instance {
|
||||
expr: AlterExpr,
|
||||
ctx: QueryContextRef,
|
||||
) -> Result<Output> {
|
||||
let table_id = match expr.table_id.as_ref() {
|
||||
None => {
|
||||
self.catalog_manager
|
||||
.table(&expr.catalog_name, &expr.schema_name, &expr.table_name)
|
||||
.await
|
||||
.context(CatalogSnafu)?
|
||||
.with_context(|| TableNotFoundSnafu {
|
||||
table_name: format_full_table_name(
|
||||
&expr.catalog_name,
|
||||
&expr.schema_name,
|
||||
&expr.table_name,
|
||||
),
|
||||
})?
|
||||
.table_info()
|
||||
.ident
|
||||
.table_id
|
||||
}
|
||||
Some(table_id) => table_id.id, // For requests from Metasrv.
|
||||
};
|
||||
let table_id = self
|
||||
.catalog_manager
|
||||
.table(&expr.catalog_name, &expr.schema_name, &expr.table_name)
|
||||
.await
|
||||
.context(CatalogSnafu)?
|
||||
.with_context(|| TableNotFoundSnafu {
|
||||
table_name: format_full_table_name(
|
||||
&expr.catalog_name,
|
||||
&expr.schema_name,
|
||||
&expr.table_name,
|
||||
),
|
||||
})?
|
||||
.table_info()
|
||||
.table_id();
|
||||
|
||||
let request = alter_expr_to_request(table_id, expr).context(AlterExprToRequestSnafu)?;
|
||||
self.sql_handler()
|
||||
@@ -165,7 +160,7 @@ impl Instance {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use api::v1::{column_def, ColumnDataType, ColumnDef, TableId};
|
||||
use api::v1::{column_def, ColumnDataType, ColumnDef, SemanticType, TableId};
|
||||
use common_catalog::consts::{MIN_USER_TABLE_ID, MITO_ENGINE};
|
||||
use common_grpc_expr::create_table_schema;
|
||||
use datatypes::prelude::ConcreteDataType;
|
||||
@@ -218,9 +213,10 @@ mod tests {
|
||||
fn test_create_column_schema() {
|
||||
let column_def = ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: 1024,
|
||||
data_type: 1024,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
};
|
||||
let result = column_def::try_as_column_schema(&column_def);
|
||||
assert!(matches!(
|
||||
@@ -230,9 +226,10 @@ mod tests {
|
||||
|
||||
let column_def = ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
};
|
||||
let column_schema = column_def::try_as_column_schema(&column_def).unwrap();
|
||||
assert_eq!(column_schema.name, "a");
|
||||
@@ -242,9 +239,10 @@ mod tests {
|
||||
let default_constraint = ColumnDefaultConstraint::Value(Value::from("default value"));
|
||||
let column_def = ColumnDef {
|
||||
name: "a".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: default_constraint.clone().try_into().unwrap(),
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
};
|
||||
let column_schema = column_def::try_as_column_schema(&column_def).unwrap();
|
||||
assert_eq!(column_schema.name, "a");
|
||||
@@ -260,27 +258,31 @@ mod tests {
|
||||
let column_defs = vec![
|
||||
ColumnDef {
|
||||
name: "host".to_string(),
|
||||
datatype: ColumnDataType::String as i32,
|
||||
data_type: ColumnDataType::String as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Tag as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "ts".to_string(),
|
||||
datatype: ColumnDataType::TimestampMillisecond as i32,
|
||||
data_type: ColumnDataType::TimestampMillisecond as i32,
|
||||
is_nullable: false,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Timestamp as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "cpu".to_string(),
|
||||
datatype: ColumnDataType::Float32 as i32,
|
||||
data_type: ColumnDataType::Float32 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Field as i32,
|
||||
},
|
||||
ColumnDef {
|
||||
name: "memory".to_string(),
|
||||
datatype: ColumnDataType::Float64 as i32,
|
||||
data_type: ColumnDataType::Float64 as i32,
|
||||
is_nullable: true,
|
||||
default_constraint: vec![],
|
||||
semantic_type: SemanticType::Field as i32,
|
||||
},
|
||||
];
|
||||
CreateTableExpr {
|
||||
|
||||
Reference in New Issue
Block a user