Skip to content

Commit

Permalink
Integrate migrationsm, though migration::tests::migrate still fails...
Browse files Browse the repository at this point in the history
  • Loading branch information
Einliterflasche committed Oct 10, 2023
1 parent d1ccad0 commit 7cbd0c5
Show file tree
Hide file tree
Showing 4 changed files with 354 additions and 65 deletions.
52 changes: 52 additions & 0 deletions pg-worm-derive/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,46 @@ impl ModelInput {
let model = self.impl_model();

quote!(
#[automatically_derived]
impl #ident {
#column_consts
#insert
#columns
}

#[automatically_derived]
#try_from_row
#[automatically_derived]
#model
)
}

fn impl_table(&self) -> TokenStream {
let table_name = self.table_name();
let primary_keys = self
.all_fields()
.filter_map(|i| {
if !i.primary_key {
None
} else {
Some(i.column_name())
}
})
.collect::<Vec<String>>();
let columns = self.all_fields().map(|i| i.create_column());

quote!(
fn table() -> ::pg_worm::migration::Table {
use ::pg_worm::migration::{Table, Column};

Table::new(#table_name).primary_key(vec![#(#primary_keys.to_string()), *])
#(
.column(#columns)
)*
}
)
}

/// Generate the code for implementing the
/// `Model` trait.
fn impl_model(&self) -> TokenStream {
Expand All @@ -113,6 +142,7 @@ impl ModelInput {
let delete = self.impl_delete();
let update = self.impl_update();
let query = self.impl_query();
let table = self.impl_table();

quote!(
#[pg_worm::async_trait]
Expand All @@ -121,6 +151,7 @@ impl ModelInput {
#update
#delete
#query
#table

fn table_name() -> &'static str {
#table_name
Expand Down Expand Up @@ -384,6 +415,27 @@ impl ModelField {
self.ident().to_string().to_lowercase()
}

fn create_column(&self) -> TokenStream {
let name = self.column_name();
let mut dtype = self.try_pg_datatype().unwrap().to_string();
if self.array {
dtype.push_str("[]");
}

let mut res =
quote!(::pg_worm::migration::Column::new(#name.to_string(), #dtype.to_string()));

if self.unique {
res.extend(quote!(.unique()));
}

if !self.nullable {
res.extend(quote!(.not_null()));
}

res
}

/// Get the corresponding postgres type
fn try_pg_datatype(&self) -> Result<Type, Error> {
let ty = self.ty.clone();
Expand Down
25 changes: 25 additions & 0 deletions pg-worm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ pub enum Error {
/// Emitted when no connection could be fetched from the pool.
#[error("couldn't fetch connection from pool")]
NoConnectionInPool,
/// Emitted when pg-worm couldn't parse the query result into
/// the corresponding model.
#[error("couldn't parse row into {0}: couldn't read field {1}")]
ParseError(&'static str, &'static str),
/// Errors emitted by the Postgres server.
///
/// Most likely an invalid query.
Expand Down Expand Up @@ -401,6 +405,10 @@ pub trait Model<T>: FromRow {
#[must_use]
fn _table_creation_sql() -> &'static str;

/// Returns a table object used to created migrations.
#[doc(hidden)]
fn table() -> migration::Table;

/// Returns a slice of all columns this model's table has.
fn columns() -> &'static [&'static dyn Deref<Target = Column>];

Expand Down Expand Up @@ -431,6 +439,23 @@ pub trait Model<T>: FromRow {
fn query(_: impl Into<String>, _: Vec<&(dyn ToSql + Sync)>) -> Query<'_, Vec<T>>;
}

/// A cleaner api for [`migration::migrate_tables`].
///
/// Call like this:
/// ```ignore
/// #[derive(Model)]
/// struct Book {
/// id: 64
/// }
///
/// migrate_tables(Book).await?;
#[macro_export]
macro_rules! migrate_tables {
($($x:ty), +) => {
$crate::migration::migrate_tables(vec![$(<$x as $crate::Model<$x>>::table()),*])
};
}

/// Create a table for your model.
///
/// Use the [`try_create_table!`] macro for a more convenient api.
Expand Down
Loading

0 comments on commit 7cbd0c5

Please sign in to comment.