### データ挿入時のエラー処理
impl Tableでinsert_rowとして、カラムにマッチするデータのみ挿入可能とする。
impl Table { fn insert_row(&mut self, row: Vec<Value>) -> Result<(), String> { if row.len() != self.columns.columns.len() { return Err(format!( "Row length({}) does not match column count({}", row.len(), self.columns.columns.len() )); } for (i, (value, column)) in row.iter().zip(&self.columns.columns).enumerate() { let expected = column.constraint.to_lowercase(); let actual = match value { Value::Integer(_) => "integer", Value::Float(_) => "float", Value::Text(_) => "text", Value::Boolean(_) => "boolean", Value::Date(_) => "date", Value::DateTime(_) => "datetime", Value::Time(_) => "time", Value::Null => "null", Value::Binary(_) => "binary", Value::UUID(_) => "uuid", Value::Json(_) => "json", Value::Decimal(_) => "decimal", }; if expected != actual { return Err(format!( "Type mismatch at column {} ({}): expected {}, got {}", i, column.name, expected, actual )); } } self.rows.push(row); Ok(()) } } fn main() { let columns = Columns { columns: vec![ Column { name: "id".to_string(), constraint: "integer".to_string(), }, Column { name: "name".to_string(), constraint: "text".to_string(), }, Column { name: "age".to_string(), constraint: "integer".to_string(), }, ] }; let mut table = Table { name: "users".to_string(), columns: columns, rows: vec![], }; let result = table.insert_row(vec![ Value::Integer(1), Value::Text("Alice".to_string()), Value::Integer(30), ]); println!("{:?}", table); }
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.50s
Running `target/debug/rds`
Table { name: “users”, columns: Columns { columns: [Column { name: “id”, constraint: “integer” }, Column { name: “name”, constraint: “text” }, Column { name: “age”, constraint: “integer” }] }, rows: [[Integer(1), Text(“Alice”), Integer(30)]] }
### テーブル作成時のカラムの指定
カラムタイプもenumで指定し、その中のtypeしか設定できないようにする。
#[derive(Debug, Clone, PartialEq)] enum ColumnType { Integer, Float, Text, Boolean, Date, DateTime, Time, Null, Binary, UUID, Json, Decimal, }
すると、impl Tableのinsert_rowも以下のようになる。
for (i, (value, column)) in row.iter().zip(self.columns.columns.iter()).enumerate() { if !type_matches(value, &column.constraint) { return Err(format!( "Type mismatch at column {} ({}): expected {:?}, got {:?}", i, column.name, column.constraint, value )); } } // fn type_matches(value: &Value, column_type: &ColumnType) -> bool { match(value, column_type) { (Value::Integer(_), ColumnType::Integer) => true, (Value::Float(_), ColumnType::Float) => true, (Value::Text(_), ColumnType::Text) => true, (Value::Boolean(_), ColumnType::Boolean) => true, (Value::Date(_), ColumnType::Date) => true, (Value::DateTime(_), ColumnType::DateTime) => true, (Value::Time(_), ColumnType::Time) => true, (Value::Null, ColumnType::Null) => true, (Value::Binary(_), ColumnType::Binary) => true, (Value::UUID(_), ColumnType::UUID) => true, (Value::Json(_), ColumnType::Json) => true, (Value::Decimal(_), ColumnType::Decimal) => true, _ => false, } }
実際の使用例
fn main() { let columns = Columns { columns: vec![ Column { name: "id".to_string(), constraint: ColumnType::Integer, }, Column { name: "name".to_string(), constraint: ColumnType::Text, }, Column { name: "age".to_string(), constraint: ColumnType::Integer, }, ] }; let mut table = Table { name: "users".to_string(), columns: columns, rows: vec![], }; let result = table.insert_row(vec![ Value::Integer(1), Value::Text("Alice".to_string()), Value::Integer(30), ]); let result = table.insert_row(vec![ Value::Integer(2), Value::Text("Bob".to_string()), Value::Integer(25), ]); println!("{:?}", table); }
Table { name: “users”, columns: Columns { columns: [Column { name: “id”, constraint: Integer }, Column { name: “name”, constraint: Text }, Column { name: “age”, constraint: Integer }] }, rows: [[Integer(1), Text(“Alice”), Integer(30)], [Integer(2), Text(“Bob”), Integer(25)]] }
### 検索機能
colum名と値を指定して、そのレコードを抽出したい
fn find_rows_by_column_value(&self, column_name: &str, target: &Value) -> Vec<&Vec<Value>> { let index = self.columns.columns.iter().position(|col| col.name == column_name); if let Some(idx) = index { self.rows .iter() .filter(|row| row.get(idx) == Some(target)) .collect() } else { vec![] } } // let matching_rows = table.find_rows_by_column_value("id", &Value::Integer(2)); for row in matching_rows { println!("Matched row: {:?}", row); }
Matched row: [Integer(2), Text(“Bob”), Integer(25)]