### データ挿入時のエラー処理
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)]