Skip to content

Commit cc3e348

Browse files
fvaleyeion-elgreco
authored andcommitted
feat: add validator crate and use to have update table metadata validation in Rust
Signed-off-by: Florian VALEYE <florian.valeye@gmail.com>
1 parent bfb8c7c commit cc3e348

7 files changed

Lines changed: 168 additions & 121 deletions

File tree

crates/core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ rand = "0.8"
9494
maplit = "1"
9595
sqlparser = { version = "0.56.0" }
9696
humantime = { version = "2.1.0" }
97+
validator = { version = "0.19", features = ["derive"] }
9798

9899
[dev-dependencies]
99100
criterion = "0.5"

crates/core/src/operations/update_table_metadata.rs

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::sync::Arc;
44

55
use futures::future::BoxFuture;
6+
use validator::Validate;
67

78
use super::{CustomExecuteHandler, Operation};
89
use crate::kernel::transaction::{CommitBuilder, CommitProperties};
@@ -13,40 +14,33 @@ use crate::table::state::DeltaTableState;
1314
use crate::DeltaTable;
1415
use crate::{DeltaResult, DeltaTableError};
1516

16-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
17-
pub enum TableMetadataUpdate {
18-
/// Update the table name
19-
TableName(String),
20-
/// Update the table description
21-
TableDescription(String),
17+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Validate)]
18+
#[validate(schema(
19+
function = "validate_at_least_one_field",
20+
message = "No metadata update specified"
21+
))]
22+
pub struct TableMetadataUpdate {
23+
#[validate(length(
24+
min = 1,
25+
max = 255,
26+
message = "Table name cannot be empty and cannot exceed 255 characters"
27+
))]
28+
pub name: Option<String>,
29+
30+
#[validate(length(
31+
max = 4000,
32+
message = "Table description cannot exceed 4000 characters"
33+
))]
34+
pub description: Option<String>,
2235
}
2336

24-
impl TableMetadataUpdate {
25-
/// Create a validated table name update
26-
pub fn table_name(name: impl Into<String>) -> DeltaResult<Self> {
27-
let name = name.into();
28-
if name.len() > 255 {
29-
return Err(DeltaTableError::MetadataError(format!(
30-
"Table name cannot exceed 255 characters. Provided name has {} characters.",
31-
name.len()
32-
)));
33-
}
34-
Ok(TableMetadataUpdate::TableName(name))
35-
}
36-
37-
/// Create a validated table description update
38-
pub fn table_description(description: impl Into<String>) -> DeltaResult<Self> {
39-
let description = description.into();
40-
let max_description_length = 4000;
41-
if description.len() > max_description_length {
42-
return Err(DeltaTableError::MetadataError(format!(
43-
"Table description cannot exceed {} characters. Provided description has {} characters.",
44-
max_description_length,
45-
description.len()
46-
)));
47-
}
48-
Ok(TableMetadataUpdate::TableDescription(description))
37+
fn validate_at_least_one_field(
38+
update: &TableMetadataUpdate,
39+
) -> Result<(), validator::ValidationError> {
40+
if update.name.is_none() && update.description.is_none() {
41+
return Err(validator::ValidationError::new("no_fields_specified"));
4942
}
43+
Ok(())
5044
}
5145

5246
/// Update table metadata operation
@@ -83,16 +77,19 @@ impl UpdateTableMetadataBuilder {
8377
}
8478
}
8579

80+
/// Specify the complete metadata update
8681
pub fn with_update(mut self, update: TableMetadataUpdate) -> Self {
8782
self.update = Some(update);
8883
self
8984
}
9085

86+
/// Additional metadata to be added to commit info
9187
pub fn with_commit_properties(mut self, commit_properties: CommitProperties) -> Self {
9288
self.commit_properties = commit_properties;
9389
self
9490
}
9591

92+
/// Set a custom execute handler, for pre and post execution
9693
pub fn with_custom_execute_handler(mut self, handler: Arc<dyn CustomExecuteHandler>) -> Self {
9794
self.custom_execute_handler = Some(handler);
9895
self
@@ -114,28 +111,17 @@ impl std::future::IntoFuture for UpdateTableMetadataBuilder {
114111
let update = this.update.ok_or_else(|| {
115112
DeltaTableError::MetadataError("No metadata update specified".to_string())
116113
})?;
114+
update
115+
.validate()
116+
.map_err(|e| DeltaTableError::MetadataError(format!("{}", e)))?;
117117

118118
let mut metadata = this.snapshot.metadata().clone();
119119

120-
match update.clone() {
121-
TableMetadataUpdate::TableName(name) => {
122-
if name.len() > 255 {
123-
return Err(DeltaTableError::MetadataError(format!(
124-
"Table name cannot exceed 255 characters. Provided name has {} characters.",
125-
name.len()
126-
)));
127-
}
128-
metadata.name = Some(name.clone());
129-
}
130-
TableMetadataUpdate::TableDescription(description) => {
131-
if description.len() > 4000 {
132-
return Err(DeltaTableError::MetadataError(format!(
133-
"Table description cannot exceed 4,000 characters. Provided description has {} characters.",
134-
description.len()
135-
)));
136-
}
137-
metadata.description = Some(description.clone());
138-
}
120+
if let Some(name) = &update.name {
121+
metadata.name = Some(name.clone());
122+
}
123+
if let Some(description) = &update.description {
124+
metadata.description = Some(description.clone());
139125
}
140126

141127
let operation = DeltaOperation::UpdateTableMetadata {

0 commit comments

Comments
 (0)