use std::collections::HashSet; use std::convert::TryFrom; use rusqlite::params; use crate::database::Db; use crate::id::Id; use crate::result::RudeResult; use crate::try_log; use crate::world::Zone; impl Db { /// Get root zone pub fn root_zone(&self, zone: &Zone) -> RudeResult { // get rid of the & let mut zone = Zone { id: zone.id, parent: zone.parent, name: zone.name.clone(), users_visible: zone.users_visible, areas: zone.areas.clone(), }; // loop until find the root loop { zone = match self.load_zone(zone.id) { Ok(Some(z)) => z, Ok(None) => { log::error!( "{}({}) :: Can't find parent zone :: None value", file!(), line!() ); return Err(Box::from("None value")); } Err(e) => return Err(e), }; if zone.id == zone.parent { return Ok(zone); } } } /// Save a zone to the database. pub fn save_zone(&self, zone: &Zone) -> RudeResult<()> { let mut statement = try_log!( self.0.prepare( "insert into zones (id, parent, name, users_visible) values (?, ?, ?, ?) on conflict(id) do update set id=?, parent=?, name=?, users_visible=?;" ), "Unable to prepare sql statement" ); let _ = try_log!( statement.execute(params![ zone.id, zone.parent, zone.name, zone.users_visible, zone.id, zone.parent, zone.name, zone.users_visible, ]), "Unable to perform query" ); Ok(()) } /// Load a zone from the database. pub fn load_zone(&self, id: Id) -> RudeResult> { let mut statement = try_log!( self.0 .prepare("select id, parent, name, users_visible from zones where id = ?"), "Unable to prepare sql statement" ); let mut rows = try_log!(statement.query(params![id]), "Unable to perform query"); let mut zone = if let Some(row) = try_log!(rows.next(), "Unable to retrieve row") { try_log!(Zone::try_from(row), "Unable to get Zone from Row") } else { return Ok(None); }; zone.areas = { let mut a = HashSet::new(); let mut statement = try_log!( self.0.prepare("select id from zones where parent = ?;"), "Unable to prepare sql statement" ); let mut rows = try_log!(statement.query(params![id]), "Unable to perform query"); while let Some(row) = try_log!(rows.next(), "Unable to retrieve row") { let new_id = try_log!(row.get(0), "Unable to retrieve field"); if new_id != id { a.insert(new_id); } } let mut statement = try_log!( self.0.prepare("select id from rooms where zone = ?;"), "Unable to prepare sql statement" ); let mut rows = try_log!(statement.query(params![id]), "Unable to perform query"); while let Some(row) = try_log!(rows.next(), "Unable to retrieve row") { a.insert(try_log!(row.get(0), "Unable to retrieve field")); } a }; Ok(Some(zone)) } }