123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- use serde::de::Visitor;
- use std::cell::Cell;
- use std::rc::Rc;
- #[derive(Debug)]
- pub struct CreateDeserializer<'de> {
- struct_visited: bool,
- column_types: Vec<&'static str>,
- expected_length: Rc<Cell<usize>>,
- _de: std::marker::PhantomData<&'de u8>,
- }
- impl<'de> CreateDeserializer<'de> {
- fn integral_type(&mut self) {
- self.column_types.push("integer");
- }
- }
- impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut CreateDeserializer<'de> {
- type Error = super::ModelError;
- // we (ab)use the forward_to_deserialize_any! macro to stub out the types we don't care about
- serde::forward_to_deserialize_any! {
- bool i128 u64 u128 f32 f64 char str
- option unit unit_struct tuple
- tuple_struct map enum identifier ignored_any
- }
- fn deserialize_any<V: Visitor<'de>>(self, _v: V) -> Result<V::Value, Self::Error> {
- todo!()
- }
- fn deserialize_u8<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_u8(0)
- }
- fn deserialize_u16<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_u16(0)
- }
- fn deserialize_u32<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_u32(0)
- }
- fn deserialize_i8<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_i8(0)
- }
- fn deserialize_i16<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_i16(0)
- }
- fn deserialize_i32<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_i32(0)
- }
- fn deserialize_i64<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.integral_type();
- v.visit_i64(0)
- }
- fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.column_types.push("text");
- v.visit_string("".to_owned())
- }
- fn deserialize_bytes<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.column_types.push("blob");
- v.visit_bytes(&[])
- }
- fn deserialize_byte_buf<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- self.column_types.push("blob");
- v.visit_bytes(&[])
- }
- fn deserialize_seq<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
- v.visit_seq(self)
- }
- fn deserialize_struct<V: Visitor<'de>>(
- self,
- _name: &'static str,
- fields: &'static [&'static str],
- v: V,
- ) -> Result<V::Value, Self::Error> {
- if self.struct_visited {
- panic!("Nested structs not allowed!");
- } else {
- self.expected_length.set(fields.len());
- v.visit_seq(self)
- }
- }
- fn deserialize_newtype_struct<V: Visitor<'de>>(
- self,
- _name: &'static str,
- v: V,
- ) -> Result<V::Value, Self::Error> {
- let elength = self.expected_length.clone();
- let old_elength = elength.get();
- elength.set(1);
- let ret = v.visit_seq(self);
- elength.set(old_elength);
- ret
- }
- }
- impl<'de> serde::de::SeqAccess<'de> for CreateDeserializer<'de> {
- type Error = super::ModelError;
- fn next_element_seed<T: serde::de::DeserializeSeed<'de>>(
- &mut self,
- seed: T,
- ) -> Result<Option<T::Value>, Self::Error> {
- if self.expected_length.get() == 0 {
- return Err(Self::Error::CreateError);
- }
- self.expected_length.set(self.expected_length.get() - 1);
- seed.deserialize(self).map(Some)
- }
- }
- pub fn sql_for<T: crate::model::Entity>() -> (String, String) {
- let elength = Rc::new(Cell::new(0));
- let mut cd = CreateDeserializer {
- struct_visited: false,
- column_types: Vec::new(),
- expected_length: elength,
- _de: std::marker::PhantomData {},
- };
- T::deserialize(&mut cd).expect("SQL creation failed!");
- // +1 to account for id column that is included in column_count
- assert_eq!(T::column_count(), cd.column_types.len() + 1);
- let mut columns = Vec::new();
- columns.push("id integer primary key".to_owned());
- for i in 1..T::column_count() {
- let col = <T::Column as std::convert::TryFrom<usize>>::try_from(i).unwrap();
- let fk = T::foreign_keys()
- .iter()
- .filter(|x| x.local_column() == &col)
- .take(1);
- let fk = fk.map(|x| {
- format!(
- " references \"{}\"(\"{}\")",
- x.foreign_table_name(),
- x.foreign_column_name()
- )
- });
- columns.push(format!(
- "\"{}\" {}{}",
- T::name(col),
- cd.column_types[i - 1],
- fk.last().unwrap_or("".to_string())
- ));
- }
- (
- format!(
- "DROP TABLE IF EXISTS \"{}\"",
- <T as crate::model::Entity>::table_name()
- ),
- format!(
- "CREATE TABLE IF NOT EXISTS \"{}\" ({})",
- <T as crate::model::Entity>::table_name(),
- columns.join(",")
- ),
- )
- }
- #[cfg(test)]
- mod test {
- #[derive(serde::Serialize, serde::Deserialize, crate::Entity)]
- #[microrm_internal]
- pub struct Empty {}
- #[derive(serde::Serialize, serde::Deserialize, crate::Entity)]
- #[microrm_internal]
- pub struct Single {
- e: i32,
- }
- #[derive(serde::Serialize, serde::Deserialize, crate::Entity)]
- #[microrm_internal]
- pub struct Reference {
- e: SingleID,
- }
- #[test]
- fn example_sql_for() {
- assert_eq!(
- super::sql_for::<Empty>(),
- (
- r#"DROP TABLE IF EXISTS "empty""#.to_owned(),
- r#"CREATE TABLE IF NOT EXISTS "empty" (id integer primary key)"#.to_owned()
- )
- );
- assert_eq!(
- super::sql_for::<Single>(),
- (
- r#"DROP TABLE IF EXISTS "single""#.to_owned(),
- r#"CREATE TABLE IF NOT EXISTS "single" (id integer primary key,"e" integer)"#.to_owned()
- )
- );
- assert_eq!(
- super::sql_for::<Reference>(),
- (
- r#"DROP TABLE IF EXISTS "reference""#.to_owned(),
- r#"CREATE TABLE IF NOT EXISTS "reference" (id integer primary key,"e" integer)"#.to_owned()
- )
- );
- }
- #[derive(serde::Serialize, serde::Deserialize, crate::Modelable)]
- #[microrm_internal]
- pub struct Unit(u8);
- #[derive(serde::Serialize, serde::Deserialize, crate::Entity)]
- #[microrm_internal]
- pub struct UnitNewtype {
- newtype: Unit,
- }
- #[test]
- fn unit_newtype_struct() {
- assert_eq!(
- super::sql_for::<UnitNewtype>(),
- (
- r#"DROP TABLE IF EXISTS "unit_newtype""#.to_owned(),
- r#"CREATE TABLE IF NOT EXISTS "unit_newtype" (id integer primary key,"newtype" integer)"#
- .to_owned()
- )
- );
- }
- #[derive(serde::Serialize, serde::Deserialize, crate::Modelable)]
- #[microrm_internal]
- pub struct NonUnit(u8, u8);
- #[derive(serde::Serialize, serde::Deserialize, crate::Entity)]
- #[microrm_internal]
- pub struct NonUnitNewtype {
- newtype: NonUnit,
- }
- #[test]
- #[should_panic]
- fn nonunit_newtype_struct() {
- super::sql_for::<NonUnitNewtype>();
- }
- #[derive(serde::Serialize, serde::Deserialize, crate::Entity)]
- #[microrm_internal]
- pub struct Child {
- #[microrm_foreign]
- parent_id: SingleID,
- }
- #[test]
- fn test_foreign_key() {
- assert_eq!(
- super::sql_for::<Child>(),
- (
- r#"DROP TABLE IF EXISTS "child""#.to_owned(),
- r#"CREATE TABLE IF NOT EXISTS "child" (id integer primary key,"parent_id" integer references "single"("id"))"#.to_owned()
- )
- );
- }
- }
|