diff --git a/modules/fdb/src/sqlite.rs b/modules/fdb/src/sqlite.rs index 7dbcae56..684c6108 100644 --- a/modules/fdb/src/sqlite.rs +++ b/modules/fdb/src/sqlite.rs @@ -26,6 +26,63 @@ impl<'a> ToSql for Field<'a> { } } +impl ValueType { + /// Get the canonical SQLite name of this data type + pub fn to_sqlite_type(self) -> &'static str { + match self { + ValueType::Nothing => "BLOB_NONE", + ValueType::Integer => "INT32", + ValueType::Float => "REAL", + ValueType::Text => "TEXT4", + ValueType::Boolean => "INT_BOOL", + ValueType::BigInt => "INT64", + ValueType::VarChar => "TEXT_XML", + } + } + + /// Take an SQLite column declaration type and guess the ValueType + /// + /// This function does a proper round-trip with `to_sqlite_type` + /// + /// ``` + /// use assembly_fdb::common::ValueType; + /// + /// fn round_trip(v: ValueType) -> Option { + /// ValueType::from_sqlite_type(v.to_sqlite_type()) + /// } + /// + /// // Check whether the round-trip works + /// assert_eq!(round_trip(ValueType::Nothing), Some(ValueType::Nothing)); + /// assert_eq!(round_trip(ValueType::Integer), Some(ValueType::Integer)); + /// assert_eq!(round_trip(ValueType::Float), Some(ValueType::Float)); + /// assert_eq!(round_trip(ValueType::Text), Some(ValueType::Text)); + /// assert_eq!(round_trip(ValueType::Boolean), Some(ValueType::Boolean)); + /// assert_eq!(round_trip(ValueType::BigInt), Some(ValueType::BigInt)); + /// assert_eq!(round_trip(ValueType::VarChar), Some(ValueType::VarChar)); + /// + /// // Check whether lcdr's names work + /// assert_eq!(ValueType::from_sqlite_type("none"), Some(ValueType::Nothing)); + /// assert_eq!(ValueType::from_sqlite_type("int32"), Some(ValueType::Integer)); + /// assert_eq!(ValueType::from_sqlite_type("real"), Some(ValueType::Float)); + /// assert_eq!(ValueType::from_sqlite_type("text_4"), Some(ValueType::Text)); + /// assert_eq!(ValueType::from_sqlite_type("int_bool"), Some(ValueType::Boolean)); + /// assert_eq!(ValueType::from_sqlite_type("int64"), Some(ValueType::BigInt)); + /// assert_eq!(ValueType::from_sqlite_type("text_8"), Some(ValueType::VarChar)); + /// ``` + pub fn from_sqlite_type(decl_type: &str) -> Option { + match decl_type { + "BLOB_NONE" | "blob_none" | "none" | "NULL" => Some(ValueType::Nothing), + "INT32" | "int32" | "TINYINT" | "SMALLINT" => Some(ValueType::Integer), + "real" | "REAL" | "FLOAT" => Some(ValueType::Float), + "TEXT4" | "text_4" | "TEXT" => Some(ValueType::Text), + "BIT" | "INT_BOOL" | "int_bool" => Some(ValueType::Boolean), + "INT64" | "int64" | "BIGINT" | "INTEGER" => Some(ValueType::BigInt), + "XML" | "TEXT_XML" | "xml" | "text_8" | "text_xml" | "VARCHAR" => Some(ValueType::VarChar), + _ => None, + } + } +} + /// Try to export a database to a SQL connection /// /// This function does the following: @@ -52,15 +109,7 @@ pub fn try_export_db(conn: &mut Connection, db: Database) -> rusqlite::Result<() writeln!(create_query, ",").unwrap(); write!(insert_query, ", ").unwrap(); } - let typ = match col.value_type() { - ValueType::Nothing => "NULL", - ValueType::Integer => "INTEGER", - ValueType::Float => "REAL", - ValueType::Text => "TEXT", - ValueType::Boolean => "INTEGER", - ValueType::BigInt => "INTEGER", - ValueType::VarChar => "BLOB", - }; + let typ = col.value_type().to_sqlite_type(); write!(create_query, " [{}] {}", col.name(), typ).unwrap(); write!(insert_query, "[{}]", col.name()).unwrap(); }