diff --git a/Cargo.lock b/Cargo.lock index 1228bbc5cd..14cbe863a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5324,7 +5324,7 @@ dependencies = [ [[package]] name = "greptime-proto" version = "0.1.0" -source = "git+https://github.com/GreptimeTeam/greptime-proto.git?rev=69680846a078aae670d93fb30511a72738345199#69680846a078aae670d93fb30511a72738345199" +source = "git+https://github.com/GreptimeTeam/greptime-proto.git?rev=9edc8c4d2a7e3c7d8e4982a6af94426da4057687#9edc8c4d2a7e3c7d8e4982a6af94426da4057687" dependencies = [ "prost 0.13.5", "serde", diff --git a/Cargo.toml b/Cargo.toml index 491be89a82..071659173d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -140,7 +140,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 = "69680846a078aae670d93fb30511a72738345199" } +greptime-proto = { git = "https://github.com/GreptimeTeam/greptime-proto.git", rev = "9edc8c4d2a7e3c7d8e4982a6af94426da4057687" } hex = "0.4" http = "1" humantime = "2.1" diff --git a/src/cli/src/metadata/repair/create_table.rs b/src/cli/src/metadata/repair/create_table.rs index a2cda030d0..e37c823c7e 100644 --- a/src/cli/src/metadata/repair/create_table.rs +++ b/src/cli/src/metadata/repair/create_table.rs @@ -74,11 +74,19 @@ pub fn make_create_region_request_for_peer( let catalog = &create_table_expr.catalog_name; let schema = &create_table_expr.schema_name; let storage_path = region_storage_path(catalog, schema); + let partition_exprs = region_routes + .iter() + .map(|r| (r.region.id.region_number(), r.region.partition_expr())) + .collect::>(); for region_number in ®ions_on_this_peer { let region_id = RegionId::new(logical_table_id, *region_number); - let region_request = - request_builder.build_one(region_id, storage_path.clone(), &HashMap::new()); + let region_request = request_builder.build_one( + region_id, + storage_path.clone(), + &HashMap::new(), + &partition_exprs, + ); requests.push(region_request); } diff --git a/src/common/meta/src/ddl/create_logical_tables/region_request.rs b/src/common/meta/src/ddl/create_logical_tables/region_request.rs index de00230d68..233a971e4a 100644 --- a/src/common/meta/src/ddl/create_logical_tables/region_request.rs +++ b/src/common/meta/src/ddl/create_logical_tables/region_request.rs @@ -40,6 +40,10 @@ impl CreateLogicalTablesProcedure { let table_ids_already_exists = &self.data.table_ids_already_exists; let regions_on_this_peer = find_leader_regions(region_routes, peer); let mut requests = Vec::with_capacity(tasks.len() * regions_on_this_peer.len()); + let partition_exprs = region_routes + .iter() + .map(|r| (r.region.id.region_number(), r.region.partition_expr())) + .collect(); for (task, table_id_already_exists) in tasks.iter().zip(table_ids_already_exists) { if table_id_already_exists.is_some() { continue; @@ -57,8 +61,12 @@ impl CreateLogicalTablesProcedure { for region_number in ®ions_on_this_peer { let region_id = RegionId::new(logical_table_id, *region_number); - let one_region_request = - request_builder.build_one(region_id, storage_path.clone(), &HashMap::new()); + let one_region_request = request_builder.build_one( + region_id, + storage_path.clone(), + &HashMap::new(), + &partition_exprs, + ); requests.push(one_region_request); } } diff --git a/src/common/meta/src/ddl/create_table.rs b/src/common/meta/src/ddl/create_table.rs index 45b7336229..5efe518e26 100644 --- a/src/common/meta/src/ddl/create_table.rs +++ b/src/common/meta/src/ddl/create_table.rs @@ -214,6 +214,11 @@ impl CreateTableProcedure { let leaders = find_leaders(region_routes); let mut create_region_tasks = Vec::with_capacity(leaders.len()); + let partition_exprs = region_routes + .iter() + .map(|r| (r.region.id.region_number(), r.region.partition_expr())) + .collect(); + for datanode in leaders { let requester = self.context.node_manager.datanode(&datanode).await; @@ -221,8 +226,12 @@ impl CreateTableProcedure { let mut requests = Vec::with_capacity(regions.len()); for region_number in regions { let region_id = RegionId::new(self.table_id(), region_number); - let create_region_request = - request_builder.build_one(region_id, storage_path.clone(), region_wal_options); + let create_region_request = request_builder.build_one( + region_id, + storage_path.clone(), + region_wal_options, + &partition_exprs, + ); requests.push(PbRegionRequest::Create(create_region_request)); } diff --git a/src/common/meta/src/ddl/create_table_template.rs b/src/common/meta/src/ddl/create_table_template.rs index 55adc2cded..df745e2f48 100644 --- a/src/common/meta/src/ddl/create_table_template.rs +++ b/src/common/meta/src/ddl/create_table_template.rs @@ -15,8 +15,10 @@ use std::collections::HashMap; use api::v1::column_def::try_as_column_def; +use api::v1::meta::Partition; use api::v1::region::{CreateRequest, RegionColumnDef}; use api::v1::{ColumnDef, CreateTableExpr, SemanticType}; +use common_telemetry::warn; use snafu::{OptionExt, ResultExt}; use store_api::metric_engine_consts::{LOGICAL_TABLE_METADATA_KEY, METRIC_ENGINE_NAME}; use store_api::storage::{RegionId, RegionNumber}; @@ -60,6 +62,7 @@ pub(crate) fn build_template_from_raw_table_info( primary_key: primary_key_indices.iter().map(|i| *i as u32).collect(), path: String::new(), options, + partition: None, }; Ok(template) @@ -121,6 +124,7 @@ pub(crate) fn build_template(create_table_expr: &CreateTableExpr) -> Result, + partition_exprs: &HashMap, ) -> CreateRequest { let mut request = self.template.clone(); @@ -157,6 +162,7 @@ impl CreateRequestBuilder { request.path = storage_path; // Stores the encoded wal options into the request options. prepare_wal_options(&mut request.options, region_id, region_wal_options); + request.partition = Some(prepare_partition_expr(region_id, partition_exprs)); if let Some(physical_table_id) = self.physical_table_id { // Logical table has the same region numbers with physical table, and they have a one-to-one mapping. @@ -173,3 +179,55 @@ impl CreateRequestBuilder { request } } + +fn prepare_partition_expr( + region_id: RegionId, + partition_exprs: &HashMap, +) -> Partition { + let expr = partition_exprs.get(®ion_id.region_number()).cloned(); + if expr.is_none() { + warn!("region {} has no partition expr", region_id); + } + + Partition { + expression: expr.unwrap_or_default(), + ..Default::default() + } +} + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + + use store_api::storage::{RegionId, RegionNumber}; + + use super::*; + + #[test] + fn test_build_one_sets_partition_expr_per_region() { + // minimal template + let template = CreateRequest { + region_id: 0, + engine: "mito".to_string(), + column_defs: vec![], + primary_key: vec![], + path: String::new(), + options: Default::default(), + partition: None, + }; + let builder = CreateRequestBuilder::new(template, None); + + let mut partition_exprs: HashMap = HashMap::new(); + let expr_a = + r#"{"Expr":{"lhs":{"Column":"a"},"op":"Eq","rhs":{"Value":{"UInt32":1}}}}"#.to_string(); + partition_exprs.insert(0, expr_a.clone()); + + let r0 = builder.build_one( + RegionId::new(42, 0), + "/p".to_string(), + &Default::default(), + &partition_exprs, + ); + assert_eq!(r0.partition.as_ref().unwrap().expression, expr_a); + } +} diff --git a/src/common/meta/src/reconciliation/reconcile_logical_tables/reconcile_regions.rs b/src/common/meta/src/reconciliation/reconcile_logical_tables/reconcile_regions.rs index 98e8290425..078af1af65 100644 --- a/src/common/meta/src/reconciliation/reconcile_logical_tables/reconcile_regions.rs +++ b/src/common/meta/src/reconciliation/reconcile_logical_tables/reconcile_regions.rs @@ -21,7 +21,7 @@ use common_telemetry::info; use common_telemetry::tracing_context::TracingContext; use futures::future; use serde::{Deserialize, Serialize}; -use store_api::storage::{RegionId, TableId}; +use store_api::storage::{RegionId, RegionNumber, TableId}; use table::metadata::RawTableInfo; use crate::ddl::utils::{add_peer_context_if_needed, region_storage_path}; @@ -112,16 +112,23 @@ impl ReconcileRegions { let create_tables = &ctx.persistent_ctx.create_tables; let mut requests = Vec::with_capacity(region_numbers.len() * create_tables.len()); + for (table_id, table_info) in create_tables { let request_builder = create_region_request_from_raw_table_info(table_info, physical_table_id)?; let storage_path = region_storage_path(&table_name.catalog_name, &table_name.schema_name); + let partition_exprs = prepare_partition_exprs(ctx, *table_id); for region_number in region_numbers { let region_id = RegionId::new(*table_id, *region_number); - let one_region_request = - request_builder.build_one(region_id, storage_path.clone(), &HashMap::new()); + + let one_region_request = request_builder.build_one( + region_id, + storage_path.clone(), + &HashMap::new(), + &partition_exprs, + ); requests.push(one_region_request); } } @@ -144,3 +151,20 @@ fn create_region_request_from_raw_table_info( let template = build_template_from_raw_table_info(raw_table_info)?; Ok(CreateRequestBuilder::new(template, Some(physical_table_id))) } + +fn prepare_partition_exprs( + ctx: &ReconcileLogicalTablesContext, + table_id: TableId, +) -> HashMap { + ctx.persistent_ctx + .physical_table_route + .as_ref() + .map(|r| { + r.region_routes + .iter() + .filter(|r| r.region.id.table_id() == table_id) + .map(|r| (r.region.id.region_number(), r.region.partition_expr())) + .collect::>() + }) + .unwrap_or_default() +} diff --git a/src/file-engine/src/region.rs b/src/file-engine/src/region.rs index 82469a5aff..6c495ee031 100644 --- a/src/file-engine/src/region.rs +++ b/src/file-engine/src/region.rs @@ -124,6 +124,7 @@ mod tests { options: new_test_options(), table_dir: "create_region_dir/".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }; let region_id = RegionId::new(1, 0); @@ -163,6 +164,7 @@ mod tests { options: new_test_options(), table_dir: region_dir.clone(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }; let region_id = RegionId::new(1, 0); @@ -203,6 +205,7 @@ mod tests { options: new_test_options(), table_dir: region_dir.clone(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }; let region_id = RegionId::new(1, 0); diff --git a/src/meta-srv/src/procedure/tests.rs b/src/meta-srv/src/procedure/tests.rs index 2d3dc8c483..5fc861f6d7 100644 --- a/src/meta-srv/src/procedure/tests.rs +++ b/src/meta-srv/src/procedure/tests.rs @@ -158,6 +158,7 @@ fn test_region_request_builder() { primary_key: vec![2, 1], path: String::new(), options: HashMap::new(), + partition: None, }; assert_eq!(template.template(), &expected); } diff --git a/src/metric-engine/src/engine/create.rs b/src/metric-engine/src/engine/create.rs index 763dd3443e..26f80129d2 100644 --- a/src/metric-engine/src/engine/create.rs +++ b/src/metric-engine/src/engine/create.rs @@ -486,6 +486,7 @@ impl MetricEngineInner { options, table_dir: request.table_dir.clone(), path_type: PathType::Metadata, + partition_expr_json: Some("".to_string()), } } @@ -653,6 +654,7 @@ mod test { engine: METRIC_ENGINE_NAME.to_string(), primary_key: vec![], options: HashMap::new(), + partition_expr_json: Some("".to_string()), }; let result = MetricEngineInner::verify_region_create_request(&request); assert!(result.is_err()); @@ -699,6 +701,7 @@ mod test { options: [(PHYSICAL_TABLE_METADATA_KEY.to_string(), String::new())] .into_iter() .collect(), + partition_expr_json: Some("".to_string()), }; MetricEngineInner::verify_region_create_request(&request).unwrap(); } @@ -731,6 +734,7 @@ mod test { engine: METRIC_ENGINE_NAME.to_string(), primary_key: vec![], options: HashMap::new(), + partition_expr_json: Some("".to_string()), }; MetricEngineInner::verify_region_create_request(&request).unwrap_err(); @@ -783,6 +787,7 @@ mod test { options, table_dir: "/test_dir".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }; // set up diff --git a/src/metric-engine/src/engine/create/extract_new_columns.rs b/src/metric-engine/src/engine/create/extract_new_columns.rs index 531464833d..84cdf5dc19 100644 --- a/src/metric-engine/src/engine/create/extract_new_columns.rs +++ b/src/metric-engine/src/engine/create/extract_new_columns.rs @@ -96,6 +96,7 @@ mod tests { options: HashMap::new(), table_dir: "test".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }, ), ( @@ -116,6 +117,7 @@ mod tests { options: HashMap::new(), table_dir: "test".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }, ), ]; @@ -157,6 +159,7 @@ mod tests { options: HashMap::new(), table_dir: "test".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }, )]; diff --git a/src/metric-engine/src/test_util.rs b/src/metric-engine/src/test_util.rs index db7112a355..be039e26ea 100644 --- a/src/metric-engine/src/test_util.rs +++ b/src/metric-engine/src/test_util.rs @@ -152,6 +152,7 @@ impl TestEnv { .collect(), table_dir: table_dir.to_string(), path_type: PathType::Bare, // Use Bare path type for engine regions + partition_expr_json: Some("".to_string()), }; // create physical region @@ -336,6 +337,7 @@ pub fn create_logical_region_request( .collect(), table_dir: table_dir.to_string(), path_type: PathType::Bare, // Use Bare path type for engine regions + partition_expr_json: Some("".to_string()), } } diff --git a/src/mito2/src/engine/basic_test.rs b/src/mito2/src/engine/basic_test.rs index 1196b7b1a2..20f2e1eb3c 100644 --- a/src/mito2/src/engine/basic_test.rs +++ b/src/mito2/src/engine/basic_test.rs @@ -657,6 +657,7 @@ async fn test_cache_null_primary_key() { options: HashMap::new(), table_dir: "test".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }; let column_schemas = rows_schema(&request); diff --git a/src/mito2/src/engine/create_test.rs b/src/mito2/src/engine/create_test.rs index 84b539809c..c194fc1cb5 100644 --- a/src/mito2/src/engine/create_test.rs +++ b/src/mito2/src/engine/create_test.rs @@ -22,7 +22,9 @@ use store_api::storage::{RegionId, ScanRequest}; use crate::config::MitoConfig; use crate::region::options::MemtableOptions; -use crate::test_util::{build_rows, put_rows, rows_schema, CreateRequestBuilder, TestEnv}; +use crate::test_util::{ + build_rows, put_rows, reopen_region, rows_schema, CreateRequestBuilder, TestEnv, +}; #[tokio::test] async fn test_engine_create_new_region() { @@ -243,3 +245,31 @@ async fn test_engine_create_with_memtable_opts() { +-------+---------+---------------------+"; assert_eq!(expected, batches.pretty_print().unwrap()); } + +#[tokio::test] +async fn create_with_partition_expr_persists_manifest() { + let mut env = TestEnv::new().await; + let engine = env.create_engine(MitoConfig::default()).await; + + let region_id = RegionId::new(1, 1); + let expr_json = r#"{"Expr":{"lhs":{"Column":"a"},"op":"GtEq","rhs":{"Value":{"UInt32":10}}}}"#; + let request = CreateRequestBuilder::new() + .partition_expr_json(Some(expr_json.to_string())) + .build(); + let table_dir = request.table_dir.clone(); + + engine + .handle_request(region_id, RegionRequest::Create(request)) + .await + .unwrap(); + + let region = engine.get_region(region_id).unwrap(); + let manifest = region.manifest_ctx.manifest().await; + assert_eq!(manifest.metadata.partition_expr.as_deref(), Some(expr_json)); + + // Reopen the region with options containing partition.expr_json + reopen_region(&engine, region_id, table_dir, false, Default::default()).await; + let region = engine.get_region(region_id).unwrap(); + let manifest = region.manifest_ctx.manifest().await; + assert_eq!(manifest.metadata.partition_expr.as_deref(), Some(expr_json)); +} diff --git a/src/mito2/src/manifest/manager.rs b/src/mito2/src/manifest/manager.rs index d32f28baab..7d4e8e34da 100644 --- a/src/mito2/src/manifest/manager.rs +++ b/src/mito2/src/manifest/manager.rs @@ -641,6 +641,36 @@ mod test { manager.validate_manifest(&metadata, 0); } + #[tokio::test] + async fn manifest_with_partition_expr_roundtrip() { + let env = TestEnv::new().await; + let expr_json = + r#"{"Expr":{"lhs":{"Column":"a"},"op":"GtEq","rhs":{"Value":{"UInt32":10}}}}"#; + let mut metadata = basic_region_metadata(); + metadata.partition_expr = Some(expr_json.to_string()); + let metadata = Arc::new(metadata); + let mut manager = env + .create_manifest_manager(CompressionType::Uncompressed, 10, Some(metadata.clone())) + .await + .unwrap() + .unwrap(); + + // persisted manifest should contain the same partition_expr JSON + let manifest = manager.manifest(); + assert_eq!(manifest.metadata.partition_expr.as_deref(), Some(expr_json)); + + manager.stop().await; + + // Reopen and check again + let manager = env + .create_manifest_manager(CompressionType::Uncompressed, 10, None) + .await + .unwrap() + .unwrap(); + let manifest = manager.manifest(); + assert_eq!(manifest.metadata.partition_expr.as_deref(), Some(expr_json)); + } + #[tokio::test] async fn region_change_add_column() { let metadata = Arc::new(basic_region_metadata()); @@ -783,6 +813,6 @@ mod test { // get manifest size again let manifest_size = manager.manifest_usage(); - assert_eq!(manifest_size, 1204); + assert_eq!(manifest_size, 1226); } } diff --git a/src/mito2/src/manifest/tests/checkpoint.rs b/src/mito2/src/manifest/tests/checkpoint.rs index 001ae1b01c..77ef19591e 100644 --- a/src/mito2/src/manifest/tests/checkpoint.rs +++ b/src/mito2/src/manifest/tests/checkpoint.rs @@ -179,7 +179,7 @@ async fn manager_with_checkpoint_distance_1() { .unwrap(); let raw_json = std::str::from_utf8(&raw_bytes).unwrap(); let expected_json = - "{\"size\":879,\"version\":10,\"checksum\":2245967096,\"extend_metadata\":{}}"; + "{\"size\":901,\"version\":10,\"checksum\":2571452538,\"extend_metadata\":{}}"; assert_eq!(expected_json, raw_json); // reopen the manager diff --git a/src/mito2/src/test_util.rs b/src/mito2/src/test_util.rs index 670187c063..65340eb76a 100644 --- a/src/mito2/src/test_util.rs +++ b/src/mito2/src/test_util.rs @@ -646,6 +646,7 @@ pub struct CreateRequestBuilder { ts_type: ConcreteDataType, /// kafka topic name kafka_topic: Option, + partition_expr_json: Option, } impl Default for CreateRequestBuilder { @@ -660,6 +661,7 @@ impl Default for CreateRequestBuilder { engine: MITO_ENGINE_NAME.to_string(), ts_type: ConcreteDataType::timestamp_millisecond_datatype(), kafka_topic: None, + partition_expr_json: None, } } } @@ -718,6 +720,12 @@ impl CreateRequestBuilder { self } + #[must_use] + pub fn partition_expr_json(mut self, partition_expr_json: Option) -> Self { + self.partition_expr_json = partition_expr_json; + self + } + pub fn build(&self) -> RegionCreateRequest { let mut column_id = 0; let mut column_metadatas = Vec::with_capacity(self.tag_num + self.field_num + 1); @@ -775,6 +783,7 @@ impl CreateRequestBuilder { options, table_dir: self.table_dir.clone(), path_type: PathType::Bare, + partition_expr_json: self.partition_expr_json.clone(), } } } diff --git a/src/mito2/src/worker/handle_create.rs b/src/mito2/src/worker/handle_create.rs index ca0a80dbcc..b7c945bed3 100644 --- a/src/mito2/src/worker/handle_create.rs +++ b/src/mito2/src/worker/handle_create.rs @@ -51,6 +51,9 @@ impl RegionWorkerLoop { builder.push_column_metadata(column); } builder.primary_key(request.primary_key); + if let Some(expr_json) = request.partition_expr_json.as_ref() { + builder.partition_expr_json(Some(expr_json.clone())); + } // Create a MitoRegion from the RegionMetadata. let region = RegionOpener::new( diff --git a/src/store-api/src/metadata.rs b/src/store-api/src/metadata.rs index 0e24706f38..bb842f0735 100644 --- a/src/store-api/src/metadata.rs +++ b/src/store-api/src/metadata.rs @@ -153,6 +153,12 @@ pub struct RegionMetadata { /// Primary key encoding mode. pub primary_key_encoding: PrimaryKeyEncoding, + + /// Partition expression serialized as a JSON string. + /// Compatibility behavior: + /// - None: no partition expr was ever set in the manifest (legacy regions). + /// - Some(""): an explicit “single-region/no-partition” designation. This is distinct from None and should be preserved as-is. + pub partition_expr: Option, } impl fmt::Debug for RegionMetadata { @@ -163,6 +169,7 @@ impl fmt::Debug for RegionMetadata { .field("primary_key", &self.primary_key) .field("region_id", &self.region_id) .field("schema_version", &self.schema_version) + .field("partition_expr", &self.partition_expr) .finish() } } @@ -183,6 +190,8 @@ impl<'de> Deserialize<'de> for RegionMetadata { schema_version: u64, #[serde(default)] primary_key_encoding: PrimaryKeyEncoding, + #[serde(default)] + partition_expr: Option, } let without_schema = RegionMetadataWithoutSchema::deserialize(deserializer)?; @@ -198,6 +207,7 @@ impl<'de> Deserialize<'de> for RegionMetadata { region_id: without_schema.region_id, schema_version: without_schema.schema_version, primary_key_encoding: without_schema.primary_key_encoding, + partition_expr: without_schema.partition_expr, }) } } @@ -350,6 +360,7 @@ impl RegionMetadata { region_id: self.region_id, schema_version: self.schema_version, primary_key_encoding: self.primary_key_encoding, + partition_expr: self.partition_expr.clone(), }) } @@ -524,6 +535,7 @@ pub struct RegionMetadataBuilder { primary_key: Vec, schema_version: u64, primary_key_encoding: PrimaryKeyEncoding, + partition_expr: Option, } impl RegionMetadataBuilder { @@ -535,6 +547,7 @@ impl RegionMetadataBuilder { primary_key: vec![], schema_version: 0, primary_key_encoding: PrimaryKeyEncoding::Dense, + partition_expr: None, } } @@ -546,6 +559,7 @@ impl RegionMetadataBuilder { region_id: existing.region_id, schema_version: existing.schema_version, primary_key_encoding: existing.primary_key_encoding, + partition_expr: existing.partition_expr, } } @@ -555,6 +569,12 @@ impl RegionMetadataBuilder { self } + /// Sets the partition expression in JSON string form. + pub fn partition_expr_json(&mut self, expr_json: Option) -> &mut Self { + self.partition_expr = expr_json; + self + } + /// Pushes a new column metadata to this region's metadata. pub fn push_column_metadata(&mut self, column_metadata: ColumnMetadata) -> &mut Self { self.column_metadatas.push(column_metadata); @@ -623,6 +643,7 @@ impl RegionMetadataBuilder { region_id: self.region_id, schema_version: self.schema_version, primary_key_encoding: self.primary_key_encoding, + partition_expr: self.partition_expr, }; meta.validate()?; @@ -1258,7 +1279,8 @@ mod test { semantic_type: SemanticType::Timestamp, column_id: 3, }) - .primary_key(vec![1]); + .primary_key(vec![1]) + .partition_expr_json(Some("".to_string())); builder.build().unwrap() } @@ -1901,7 +1923,7 @@ mod test { fn test_debug_for_column_metadata() { let region_metadata = build_test_region_metadata(); let formatted = format!("{:?}", region_metadata); - assert_eq!(formatted, "RegionMetadata { column_metadatas: [[a Int64 not null Tag 1], [b Float64 not null Field 2], [c TimestampMillisecond not null Timestamp 3]], time_index: 3, primary_key: [1], region_id: 5299989648942(1234, 5678), schema_version: 0 }"); + assert_eq!(formatted, "RegionMetadata { column_metadatas: [[a Int64 not null Tag 1], [b Float64 not null Field 2], [c TimestampMillisecond not null Timestamp 3]], time_index: 3, primary_key: [1], region_id: 5299989648942(1234, 5678), schema_version: 0, partition_expr: Some(\"\") }"); } #[test] diff --git a/src/store-api/src/region_request.rs b/src/store-api/src/region_request.rs index 92c3c34ec1..fad0680048 100644 --- a/src/store-api/src/region_request.rs +++ b/src/store-api/src/region_request.rs @@ -229,6 +229,7 @@ fn parse_region_create(create: CreateRequest) -> Result<(RegionId, RegionCreateR .collect::>>()?; let region_id = RegionId::from(create.region_id); let table_dir = table_dir(&create.path, region_id.table_id()); + let partition_expr_json = create.partition.as_ref().map(|p| p.expression.clone()); Ok(( region_id, RegionCreateRequest { @@ -238,6 +239,7 @@ fn parse_region_create(create: CreateRequest) -> Result<(RegionId, RegionCreateR options: create.options, table_dir, path_type: PathType::Bare, + partition_expr_json, }, )) } @@ -426,6 +428,9 @@ pub struct RegionCreateRequest { pub table_dir: String, /// Path type for generating paths pub path_type: PathType, + /// Partition expression JSON from table metadata. Set to empty string for a region without partition. + /// `Option` to keep compatibility with old clients. + pub partition_expr_json: Option, } impl RegionCreateRequest { @@ -1853,6 +1858,7 @@ mod tests { options: HashMap::new(), table_dir: "path".to_string(), path_type: PathType::Bare, + partition_expr_json: Some("".to_string()), }; assert!(create.validate().is_err()); diff --git a/tests/cases/standalone/common/information_schema/region_statistics.result b/tests/cases/standalone/common/information_schema/region_statistics.result index aa8e649ec2..507151820e 100644 --- a/tests/cases/standalone/common/information_schema/region_statistics.result +++ b/tests/cases/standalone/common/information_schema/region_statistics.result @@ -29,7 +29,7 @@ SELECT SUM(region_rows), SUM(disk_size), SUM(sst_size), SUM(index_size) +-------------------------------------------------------+-----------------------------------------------------+----------------------------------------------------+------------------------------------------------------+ | sum(information_schema.region_statistics.region_rows) | sum(information_schema.region_statistics.disk_size) | sum(information_schema.region_statistics.sst_size) | sum(information_schema.region_statistics.index_size) | +-------------------------------------------------------+-----------------------------------------------------+----------------------------------------------------+------------------------------------------------------+ -| 3 | 2238 | 0 | 0 | +| 3 | 2699 | 0 | 0 | +-------------------------------------------------------+-----------------------------------------------------+----------------------------------------------------+------------------------------------------------------+ SELECT data_length, index_length, avg_row_length, table_rows FROM INFORMATION_SCHEMA.TABLES WHERE table_name = 'test';