use assembly_data::fdb::{ common::{Value, ValueType}, mem::{Database, Tables}, }; use mapr::Mmap; use std::{fs::File, path::PathBuf, time::Instant}; use structopt::StructOpt; #[derive(Debug, StructOpt)] /// Prints statistics on an FDB file struct Options { /// The FDB file file: PathBuf, } fn main() -> color_eyre::Result<()> { let opt = Options::from_args(); let start = Instant::now(); let file = File::open(&opt.file)?; let mmap = unsafe { Mmap::map(&file)? }; let buffer: &[u8] = &mmap; println!("Scanning database, this may take a while..."); let db = Database::new(buffer); let tables: Tables<'_> = db.tables()?; let table_count = tables.len(); let mut column_count = 0; let mut field_count = 0; let mut row_count = 0; let mut bucket_count = 0; let mut null_field_count = 0; let mut int_field_count = 0; let mut float_field_count = 0; let mut text_field_count = 0; let mut bool_field_count = 0; let mut bigint_field_count = 0; let mut xml_field_count = 0; let mut null_column_count = 0; let mut int_column_count = 0; let mut float_column_count = 0; let mut text_column_count = 0; let mut bool_column_count = 0; let mut bigint_column_count = 0; let mut xml_column_count = 0; for table in tables.iter() { let table = table?; for column in table.column_iter() { column_count += 1; match column.value_type() { ValueType::Nothing => null_column_count += 1, ValueType::Integer => int_column_count += 1, ValueType::Float => float_column_count += 1, ValueType::Text => text_column_count += 1, ValueType::Boolean => bool_column_count += 1, ValueType::BigInt => bigint_column_count += 1, ValueType::VarChar => xml_column_count += 1, } } for bucket in table.bucket_iter() { bucket_count += 1; for row in bucket.row_iter() { row_count += 1; for field in row.field_iter() { field_count += 1; match field { Value::Nothing => null_field_count += 1, Value::Integer(_) => int_field_count += 1, Value::Float(_) => float_field_count += 1, Value::Text(_) => text_field_count += 1, Value::Boolean(_) => bool_field_count += 1, Value::BigInt(_) => bigint_field_count += 1, Value::VarChar(_) => xml_field_count += 1, } } } } } let string_count = text_field_count + column_count + table_count; println!(); println!("# General"); println!("Tables: {}", table_count); println!("Columns: {}", column_count); println!("Fields: {}", field_count); println!("Rows: {}", row_count); println!("Buckets: {}", bucket_count); println!("Strings: {}", string_count); println!(); println!("# Column Types"); println!("null: {}", null_column_count); println!("int: {}", int_column_count); println!("float: {}", float_column_count); println!("text: {}", text_column_count); println!("bool: {}", bool_column_count); println!("bigint: {}", bigint_column_count); println!("xml: {}", xml_column_count); println!(); println!("# Field Types"); println!("null: {}", null_field_count); println!("int: {}", int_field_count); println!("float: {}", float_field_count); println!("text: {}", text_field_count); println!("bool: {}", bool_field_count); println!("bigint: {}", bigint_field_count); println!("xml: {}", xml_field_count); println!(); let duration = start.elapsed(); println!( "Finished in {}.{}s", duration.as_secs(), duration.subsec_millis() ); Ok(()) }