mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-24 00:40:40 +00:00
refactor: use derive_builder for boilerplate builders (#116)
* refactor: remove boilerplate builder code with derive_builder macro * refactor: better build creation using Default::default() * refactor: resolve api change issues in benchmark code * refactor: address some review issues * refactor: address clippy issues * chore: doc and todo update * refactor: add builder for RegionDescriptor
This commit is contained in:
@@ -16,6 +16,7 @@ futures = "0.3"
|
||||
object-store = { path = "../object-store" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
snafu = { version = "0.7", features = ["backtraces"] }
|
||||
derive_builder = "0.11"
|
||||
|
||||
[dev-dependencies]
|
||||
async-stream = "0.3"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//! Storage related APIs
|
||||
|
||||
pub mod logstore;
|
||||
pub mod manifest;
|
||||
pub mod storage;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use datatypes::value::Value;
|
||||
use derive_builder::Builder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::manifest::MetadataId;
|
||||
@@ -20,19 +21,35 @@ pub fn gen_region_name(id: RegionId) -> String {
|
||||
|
||||
// TODO(yingwen): Validate default value has same type with column, and name is a valid column name.
|
||||
/// A [ColumnDescriptor] contains information to create a column.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Builder)]
|
||||
#[builder(pattern = "owned")]
|
||||
pub struct ColumnDescriptor {
|
||||
pub id: ColumnId,
|
||||
#[builder(setter(into))]
|
||||
pub name: String,
|
||||
pub data_type: ConcreteDataType,
|
||||
/// Is column nullable, default is true.
|
||||
#[builder(default = "true")]
|
||||
pub is_nullable: bool,
|
||||
/// Default value of column, default is None, which means no default value
|
||||
/// for this column, and user must provide value for a not-null column.
|
||||
#[builder(default)]
|
||||
pub default_value: Option<Value>,
|
||||
#[builder(default, setter(into))]
|
||||
pub comment: String,
|
||||
}
|
||||
|
||||
impl ColumnDescriptorBuilder {
|
||||
pub fn new<S: Into<String>>(id: ColumnId, name: S, data_type: ConcreteDataType) -> Self {
|
||||
Self {
|
||||
id: Some(id),
|
||||
name: Some(name.into()),
|
||||
data_type: Some(data_type),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ColumnDescriptor> for ColumnSchema {
|
||||
fn from(desc: &ColumnDescriptor) -> ColumnSchema {
|
||||
ColumnSchema::new(&desc.name, desc.data_type.clone(), desc.is_nullable)
|
||||
@@ -40,32 +57,39 @@ impl From<&ColumnDescriptor> for ColumnSchema {
|
||||
}
|
||||
|
||||
/// A [RowKeyDescriptor] contains information about row key.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Builder)]
|
||||
#[builder(pattern = "owned")]
|
||||
pub struct RowKeyDescriptor {
|
||||
#[builder(default)]
|
||||
pub columns: Vec<ColumnDescriptor>,
|
||||
/// Timestamp key column.
|
||||
pub timestamp: ColumnDescriptor,
|
||||
/// Enable version column in row key if this field is true.
|
||||
///
|
||||
/// The default value is true.
|
||||
// FIXME(yingwen): Change default value to true (Disable version column by default).
|
||||
/// The default value is false.
|
||||
#[builder(default = "false")]
|
||||
pub enable_version_column: bool,
|
||||
}
|
||||
|
||||
/// A [ColumnFamilyDescriptor] contains information to create a column family.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Builder)]
|
||||
pub struct ColumnFamilyDescriptor {
|
||||
#[builder(default = "consts::DEFAULT_CF_ID")]
|
||||
pub cf_id: ColumnFamilyId,
|
||||
#[builder(default = "consts::DEFAULT_CF_NAME.to_string()", setter(into))]
|
||||
pub name: String,
|
||||
/// Descriptors of columns in this column family.
|
||||
#[builder(default)]
|
||||
pub columns: Vec<ColumnDescriptor>,
|
||||
}
|
||||
|
||||
/// A [RegionDescriptor] contains information to create a region.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq, Builder)]
|
||||
#[builder(pattern = "owned")]
|
||||
pub struct RegionDescriptor {
|
||||
pub id: RegionId,
|
||||
/// Region name.
|
||||
#[builder(setter(into))]
|
||||
pub name: String,
|
||||
/// Row key descriptor of this region.
|
||||
pub row_key: RowKeyDescriptor,
|
||||
@@ -75,154 +99,51 @@ pub struct RegionDescriptor {
|
||||
pub extra_cfs: Vec<ColumnFamilyDescriptor>,
|
||||
}
|
||||
|
||||
pub struct ColumnDescriptorBuilder {
|
||||
id: ColumnId,
|
||||
name: String,
|
||||
data_type: ConcreteDataType,
|
||||
is_nullable: bool,
|
||||
default_value: Option<Value>,
|
||||
comment: String,
|
||||
}
|
||||
|
||||
impl ColumnDescriptorBuilder {
|
||||
pub fn new<T: Into<String>>(id: ColumnId, name: T, data_type: ConcreteDataType) -> Self {
|
||||
Self {
|
||||
id,
|
||||
name: name.into(),
|
||||
data_type,
|
||||
is_nullable: true,
|
||||
default_value: None,
|
||||
comment: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_nullable(mut self, is_nullable: bool) -> Self {
|
||||
self.is_nullable = is_nullable;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn default_value(mut self, value: Option<Value>) -> Self {
|
||||
self.default_value = value;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn comment<T: Into<String>>(mut self, comment: T) -> Self {
|
||||
self.comment = comment.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> ColumnDescriptor {
|
||||
ColumnDescriptor {
|
||||
id: self.id,
|
||||
name: self.name,
|
||||
data_type: self.data_type,
|
||||
is_nullable: self.is_nullable,
|
||||
default_value: self.default_value,
|
||||
comment: self.comment,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RowKeyDescriptorBuilder {
|
||||
columns: Vec<ColumnDescriptor>,
|
||||
timestamp: ColumnDescriptor,
|
||||
enable_version_column: bool,
|
||||
}
|
||||
|
||||
impl RowKeyDescriptorBuilder {
|
||||
pub fn new(timestamp: ColumnDescriptor) -> Self {
|
||||
Self {
|
||||
columns: Vec::new(),
|
||||
timestamp,
|
||||
enable_version_column: false,
|
||||
timestamp: Some(timestamp),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn columns_capacity(mut self, capacity: usize) -> Self {
|
||||
self.columns.reserve(capacity);
|
||||
self.columns = Some(Vec::with_capacity(capacity));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn push_column(mut self, column: ColumnDescriptor) -> Self {
|
||||
self.columns.push(column);
|
||||
let columns = self.columns.get_or_insert_with(Vec::new);
|
||||
columns.push(column);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn enable_version_column(mut self, enable: bool) -> Self {
|
||||
self.enable_version_column = enable;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> RowKeyDescriptor {
|
||||
RowKeyDescriptor {
|
||||
columns: self.columns,
|
||||
timestamp: self.timestamp,
|
||||
enable_version_column: self.enable_version_column,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ColumnFamilyDescriptorBuilder {
|
||||
cf_id: ColumnFamilyId,
|
||||
name: String,
|
||||
columns: Vec<ColumnDescriptor>,
|
||||
}
|
||||
|
||||
impl ColumnFamilyDescriptorBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cf_id: consts::DEFAULT_CF_ID,
|
||||
name: consts::DEFAULT_CF_NAME.to_string(),
|
||||
columns: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cf_id(mut self, cf_id: ColumnFamilyId) -> Self {
|
||||
self.cf_id = cf_id;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name<T: Into<String>>(mut self, name: T) -> Self {
|
||||
self.name = name.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn columns_capacity(mut self, capacity: usize) -> Self {
|
||||
self.columns.reserve(capacity);
|
||||
self.columns = Some(Vec::with_capacity(capacity));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn push_column(mut self, column: ColumnDescriptor) -> Self {
|
||||
self.columns.push(column);
|
||||
let columns = self.columns.get_or_insert_with(Vec::new);
|
||||
columns.push(column);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> ColumnFamilyDescriptor {
|
||||
ColumnFamilyDescriptor {
|
||||
cf_id: self.cf_id,
|
||||
name: self.name,
|
||||
columns: self.columns,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ColumnFamilyDescriptorBuilder {
|
||||
fn default() -> ColumnFamilyDescriptorBuilder {
|
||||
ColumnFamilyDescriptorBuilder::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[inline]
|
||||
fn new_column_desc_builder() -> ColumnDescriptorBuilder {
|
||||
ColumnDescriptorBuilder::new(3, "test", ConcreteDataType::int32_datatype())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_column_descriptor_builder() {
|
||||
let desc = new_column_desc_builder().build();
|
||||
let desc = new_column_desc_builder().build().unwrap();
|
||||
assert_eq!(3, desc.id);
|
||||
assert_eq!("test", desc.name);
|
||||
assert_eq!(ConcreteDataType::int32_datatype(), desc.data_type);
|
||||
@@ -230,73 +151,98 @@ mod tests {
|
||||
assert!(desc.default_value.is_none());
|
||||
assert!(desc.comment.is_empty());
|
||||
|
||||
let desc = new_column_desc_builder().is_nullable(false).build();
|
||||
let desc = new_column_desc_builder()
|
||||
.is_nullable(false)
|
||||
.build()
|
||||
.unwrap();
|
||||
assert!(!desc.is_nullable);
|
||||
|
||||
let desc = new_column_desc_builder()
|
||||
.default_value(Some(Value::Null))
|
||||
.build();
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(Value::Null, desc.default_value.unwrap());
|
||||
|
||||
let desc = new_column_desc_builder()
|
||||
.default_value(Some(Value::Int32(123)))
|
||||
.build();
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(Value::Int32(123), desc.default_value.unwrap());
|
||||
|
||||
let desc = new_column_desc_builder().comment("A test column").build();
|
||||
let desc = new_column_desc_builder()
|
||||
.comment("A test column")
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!("A test column", desc.comment);
|
||||
}
|
||||
|
||||
fn new_timestamp_desc() -> ColumnDescriptor {
|
||||
ColumnDescriptorBuilder::new(5, "timestamp", ConcreteDataType::int64_datatype()).build()
|
||||
ColumnDescriptorBuilder::new(5, "timestamp", ConcreteDataType::int64_datatype())
|
||||
.build()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_row_key_descriptor_builder() {
|
||||
let timestamp = new_timestamp_desc();
|
||||
|
||||
let desc = RowKeyDescriptorBuilder::new(timestamp.clone()).build();
|
||||
let desc = RowKeyDescriptorBuilder::new(timestamp.clone())
|
||||
.build()
|
||||
.unwrap();
|
||||
assert!(desc.columns.is_empty());
|
||||
assert!(!desc.enable_version_column);
|
||||
|
||||
let desc = RowKeyDescriptorBuilder::new(timestamp.clone())
|
||||
.columns_capacity(1)
|
||||
.push_column(
|
||||
ColumnDescriptorBuilder::new(6, "c1", ConcreteDataType::int32_datatype()).build(),
|
||||
ColumnDescriptorBuilder::new(6, "c1", ConcreteDataType::int32_datatype())
|
||||
.build()
|
||||
.unwrap(),
|
||||
)
|
||||
.push_column(
|
||||
ColumnDescriptorBuilder::new(7, "c2", ConcreteDataType::int32_datatype()).build(),
|
||||
ColumnDescriptorBuilder::new(7, "c2", ConcreteDataType::int32_datatype())
|
||||
.build()
|
||||
.unwrap(),
|
||||
)
|
||||
.build();
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(2, desc.columns.len());
|
||||
assert!(!desc.enable_version_column);
|
||||
|
||||
let desc = RowKeyDescriptorBuilder::new(timestamp)
|
||||
.enable_version_column(false)
|
||||
.build();
|
||||
.build()
|
||||
.unwrap();
|
||||
assert!(desc.columns.is_empty());
|
||||
assert!(!desc.enable_version_column);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cf_descriptor_builder() {
|
||||
let desc = ColumnFamilyDescriptorBuilder::default().build();
|
||||
let desc = ColumnFamilyDescriptorBuilder::default().build().unwrap();
|
||||
assert_eq!(consts::DEFAULT_CF_ID, desc.cf_id);
|
||||
assert_eq!(consts::DEFAULT_CF_NAME, desc.name);
|
||||
assert!(desc.columns.is_empty());
|
||||
|
||||
let desc = ColumnFamilyDescriptorBuilder::new()
|
||||
let desc = ColumnFamilyDescriptorBuilder::default()
|
||||
.cf_id(32)
|
||||
.name("cf1")
|
||||
.build();
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(32, desc.cf_id);
|
||||
assert_eq!("cf1", desc.name);
|
||||
|
||||
let desc = ColumnFamilyDescriptorBuilder::new()
|
||||
let desc = ColumnFamilyDescriptorBuilder::default()
|
||||
.push_column(
|
||||
ColumnDescriptorBuilder::new(6, "c1", ConcreteDataType::int32_datatype()).build(),
|
||||
ColumnDescriptorBuilder::default()
|
||||
.id(6)
|
||||
.name("c1")
|
||||
.data_type(ConcreteDataType::int32_datatype())
|
||||
.build()
|
||||
.unwrap(),
|
||||
)
|
||||
.build();
|
||||
.build()
|
||||
.unwrap();
|
||||
assert_eq!(1, desc.columns.len());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user