|
@@ -6,9 +6,7 @@ use std::rc::Rc;
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
pub struct CreateDeserializer<'de> {
|
|
pub struct CreateDeserializer<'de> {
|
|
struct_visited: bool,
|
|
struct_visited: bool,
|
|
- column_names: Vec<&'static str>,
|
|
|
|
column_types: Vec<&'static str>,
|
|
column_types: Vec<&'static str>,
|
|
- column_name_stack: Vec<&'static str>,
|
|
|
|
expected_length: Rc<Cell<usize>>,
|
|
expected_length: Rc<Cell<usize>>,
|
|
_de: std::marker::PhantomData<&'de u8>,
|
|
_de: std::marker::PhantomData<&'de u8>,
|
|
}
|
|
}
|
|
@@ -16,8 +14,6 @@ pub struct CreateDeserializer<'de> {
|
|
impl<'de> CreateDeserializer<'de> {
|
|
impl<'de> CreateDeserializer<'de> {
|
|
fn integral_type(&mut self) {
|
|
fn integral_type(&mut self) {
|
|
self.column_types.push("integer");
|
|
self.column_types.push("integer");
|
|
- self.column_names
|
|
|
|
- .push(self.column_name_stack.pop().unwrap());
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -72,22 +68,16 @@ impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut CreateDeserializer<'de> {
|
|
|
|
|
|
fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
|
|
fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
|
|
self.column_types.push("text");
|
|
self.column_types.push("text");
|
|
- self.column_names
|
|
|
|
- .push(self.column_name_stack.pop().unwrap());
|
|
|
|
v.visit_string("".to_owned())
|
|
v.visit_string("".to_owned())
|
|
}
|
|
}
|
|
|
|
|
|
fn deserialize_bytes<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
|
|
fn deserialize_bytes<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
|
|
self.column_types.push("blob");
|
|
self.column_types.push("blob");
|
|
- self.column_names
|
|
|
|
- .push(self.column_name_stack.pop().unwrap());
|
|
|
|
v.visit_bytes(&[])
|
|
v.visit_bytes(&[])
|
|
}
|
|
}
|
|
|
|
|
|
fn deserialize_byte_buf<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
|
|
fn deserialize_byte_buf<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
|
|
self.column_types.push("blob");
|
|
self.column_types.push("blob");
|
|
- self.column_names
|
|
|
|
- .push(self.column_name_stack.pop().unwrap());
|
|
|
|
v.visit_bytes(&[])
|
|
v.visit_bytes(&[])
|
|
}
|
|
}
|
|
|
|
|
|
@@ -104,7 +94,6 @@ impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut CreateDeserializer<'de> {
|
|
if self.struct_visited {
|
|
if self.struct_visited {
|
|
panic!("Nested structs not allowed!");
|
|
panic!("Nested structs not allowed!");
|
|
} else {
|
|
} else {
|
|
- self.column_name_stack.extend(fields.iter().rev());
|
|
|
|
self.expected_length.set(fields.len());
|
|
self.expected_length.set(fields.len());
|
|
v.visit_seq(self)
|
|
v.visit_seq(self)
|
|
}
|
|
}
|
|
@@ -148,29 +137,54 @@ pub fn sql_for<T: crate::model::Entity>() -> (String, String) {
|
|
|
|
|
|
let mut cd = CreateDeserializer {
|
|
let mut cd = CreateDeserializer {
|
|
struct_visited: false,
|
|
struct_visited: false,
|
|
- column_names: Vec::new(),
|
|
|
|
column_types: Vec::new(),
|
|
column_types: Vec::new(),
|
|
- column_name_stack: Vec::new(),
|
|
|
|
expected_length: elength,
|
|
expected_length: elength,
|
|
_de: std::marker::PhantomData {},
|
|
_de: std::marker::PhantomData {},
|
|
};
|
|
};
|
|
|
|
|
|
T::deserialize(&mut cd).expect("SQL creation failed!");
|
|
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 num_enum::TryFromPrimitive>::try_from_primitive(i).unwrap();
|
|
|
|
+ println!("{}", T::name(col));
|
|
|
|
+
|
|
|
|
+ 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!(
|
|
format!(
|
|
"DROP TABLE IF EXISTS \"{}\"",
|
|
"DROP TABLE IF EXISTS \"{}\"",
|
|
<T as crate::model::Entity>::table_name()
|
|
<T as crate::model::Entity>::table_name()
|
|
),
|
|
),
|
|
format!(
|
|
format!(
|
|
- "CREATE TABLE \"{}\" (id integer primary key{})",
|
|
|
|
|
|
+ "CREATE TABLE \"{}\" ({})",
|
|
<T as crate::model::Entity>::table_name(),
|
|
<T as crate::model::Entity>::table_name(),
|
|
- cd.column_names
|
|
|
|
- .iter()
|
|
|
|
- .zip(cd.column_types.iter())
|
|
|
|
- .map(|(n, t)| format!(", \"{}\" {}", n, t))
|
|
|
|
- .collect::<Vec<_>>()
|
|
|
|
- .join("")
|
|
|
|
|
|
+ columns.join(",")
|
|
),
|
|
),
|
|
)
|
|
)
|
|
}
|
|
}
|
|
@@ -208,7 +222,7 @@ mod test {
|
|
super::sql_for::<Single>(),
|
|
super::sql_for::<Single>(),
|
|
(
|
|
(
|
|
r#"DROP TABLE IF EXISTS "single""#.to_owned(),
|
|
r#"DROP TABLE IF EXISTS "single""#.to_owned(),
|
|
- r#"CREATE TABLE "single" (id integer primary key, "e" integer)"#.to_owned()
|
|
|
|
|
|
+ r#"CREATE TABLE "single" (id integer primary key,"e" integer)"#.to_owned()
|
|
)
|
|
)
|
|
);
|
|
);
|
|
|
|
|
|
@@ -216,7 +230,7 @@ mod test {
|
|
super::sql_for::<Reference>(),
|
|
super::sql_for::<Reference>(),
|
|
(
|
|
(
|
|
r#"DROP TABLE IF EXISTS "reference""#.to_owned(),
|
|
r#"DROP TABLE IF EXISTS "reference""#.to_owned(),
|
|
- r#"CREATE TABLE "reference" (id integer primary key, "e" integer)"#.to_owned()
|
|
|
|
|
|
+ r#"CREATE TABLE "reference" (id integer primary key,"e" integer)"#.to_owned()
|
|
)
|
|
)
|
|
);
|
|
);
|
|
}
|
|
}
|
|
@@ -236,7 +250,7 @@ mod test {
|
|
super::sql_for::<UnitNewtype>(),
|
|
super::sql_for::<UnitNewtype>(),
|
|
(
|
|
(
|
|
r#"DROP TABLE IF EXISTS "unit_newtype""#.to_owned(),
|
|
r#"DROP TABLE IF EXISTS "unit_newtype""#.to_owned(),
|
|
- r#"CREATE TABLE "unit_newtype" (id integer primary key, "newtype" integer)"#
|
|
|
|
|
|
+ r#"CREATE TABLE "unit_newtype" (id integer primary key,"newtype" integer)"#
|
|
.to_owned()
|
|
.to_owned()
|
|
)
|
|
)
|
|
);
|
|
);
|
|
@@ -256,4 +270,22 @@ mod test {
|
|
fn nonunit_newtype_struct() {
|
|
fn nonunit_newtype_struct() {
|
|
super::sql_for::<NonUnitNewtype>();
|
|
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 "child" (id integer primary key,"parent_id" integer references "single"("id"))"#.to_owned()
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+ }
|
|
}
|
|
}
|