dinoco 0.0.7

A modern Rust ORM for schema-driven queries, migrations, and database operations.
Documentation
use std::marker::PhantomData;

use dinoco_engine::{DinocoAdapter, DinocoResult};

use crate::{
    InsertConnection, InsertModel, Projection, execute_connection_updates, execute_insert,
    execute_insert_relation_links, execute_insert_returning, execution::execute_reload_many_by_identity,
};

use super::{
    InsertManyWithConnection, InsertManyWithConnectionReturning, InsertManyWithConnections,
    InsertManyWithConnectionsReturning, validate_pair_len,
};

impl<M, R> InsertManyWithConnections<M, R>
where
    M: InsertModel + InsertConnection<R> + Projection<M>,
{
    pub fn returning<S>(self) -> InsertManyWithConnectionsReturning<M, R, S>
    where
        S: Projection<M>,
    {
        InsertManyWithConnectionsReturning {
            items: self.items,
            connected_groups: self.connected_groups,
            marker: PhantomData,
        }
    }

    pub fn execute<'a, A>(
        self,
        client: &'a crate::DinocoClient<A>,
    ) -> impl std::future::Future<Output = DinocoResult<()>> + Send + 'a
    where
        M: Send + Sync + 'a,
        R: Send + Sync + 'a,
        A: DinocoAdapter,
    {
        async move {
            let items = self.items;
            let connected_groups = self.connected_groups;
            let mut connection_updates = Vec::new();
            let mut relation_links = Vec::new();

            validate_pair_len(items.len(), connected_groups.len(), "connection group")?;

            if M::auto_increment_primary_key_column().is_some() {
                let inserted_items = execute_insert_returning::<M, M, A>(items, client).await?;

                for (item, group) in inserted_items.iter().zip(connected_groups.into_iter()) {
                    for connected in group {
                        connection_updates.extend(item.connection_updates(&connected));
                        relation_links.extend(item.connection_links(&connected));
                    }
                }
            } else {
                for (item, group) in items.iter().zip(connected_groups.iter()) {
                    for connected in group {
                        connection_updates.extend(item.connection_updates(connected));
                        relation_links.extend(item.connection_links(connected));
                    }
                }

                execute_insert::<M, A>(items, client).await?;
            }

            execute_connection_updates(connection_updates, client).await?;
            execute_insert_relation_links(relation_links, client).await
        }
    }
}

impl<M, R> InsertManyWithConnection<M, R>
where
    M: InsertModel + InsertConnection<R> + Projection<M>,
{
    pub fn returning<S>(self) -> InsertManyWithConnectionReturning<M, R, S>
    where
        S: Projection<M>,
    {
        InsertManyWithConnectionReturning {
            items: self.items,
            connected_items: self.connected_items,
            marker: PhantomData,
        }
    }

    pub fn execute<'a, A>(
        self,
        client: &'a crate::DinocoClient<A>,
    ) -> impl std::future::Future<Output = DinocoResult<()>> + Send + 'a
    where
        M: Send + Sync + 'a,
        R: Send + Sync + 'a,
        A: DinocoAdapter,
    {
        async move {
            let items = self.items;
            let connected_items = self.connected_items;
            let mut connection_updates = Vec::new();
            let mut relation_links = Vec::new();

            validate_pair_len(items.len(), connected_items.len(), "connection size")?;

            if M::auto_increment_primary_key_column().is_some() {
                let inserted_items = execute_insert_returning::<M, M, A>(items, client).await?;

                for (item, connected) in inserted_items.iter().zip(connected_items.iter()) {
                    connection_updates.extend(item.connection_updates(connected));
                    relation_links.extend(item.connection_links(connected));
                }
            } else {
                for (item, connected) in items.iter().zip(connected_items.iter()) {
                    connection_updates.extend(item.connection_updates(connected));
                    relation_links.extend(item.connection_links(connected));
                }

                execute_insert::<M, A>(items, client).await?;
            }

            execute_connection_updates(connection_updates, client).await?;
            execute_insert_relation_links(relation_links, client).await
        }
    }
}

impl<M, R, S> InsertManyWithConnectionsReturning<M, R, S>
where
    M: InsertModel + InsertConnection<R> + Projection<M> + Clone,
    S: Projection<M>,
{
    pub fn execute<'a, A>(
        self,
        client: &'a crate::DinocoClient<A>,
    ) -> impl std::future::Future<Output = DinocoResult<Vec<S>>> + Send + 'a
    where
        M: Send + Sync + 'a,
        R: Send + Sync + 'a,
        S: Send + Sync + 'a,
        A: DinocoAdapter,
    {
        async move {
            let items = self.items;
            let connected_groups = self.connected_groups;
            let mut connection_updates = Vec::new();
            let mut relation_links = Vec::new();

            validate_pair_len(items.len(), connected_groups.len(), "connection group")?;

            let parent_items = if M::auto_increment_primary_key_column().is_some() {
                let inserted = execute_insert_returning::<M, M, A>(items, client).await?;

                for (item, group) in inserted.iter().zip(connected_groups.into_iter()) {
                    for connected in group {
                        connection_updates.extend(item.connection_updates(&connected));
                        relation_links.extend(item.connection_links(&connected));
                    }
                }

                inserted
            } else {
                for (item, group) in items.iter().zip(connected_groups.iter()) {
                    for connected in group {
                        connection_updates.extend(item.connection_updates(connected));
                        relation_links.extend(item.connection_links(connected));
                    }
                }

                execute_insert::<M, A>(items.clone(), client).await?;
                items
            };

            execute_connection_updates(connection_updates, client).await?;
            execute_insert_relation_links(relation_links, client).await?;

            execute_reload_many_by_identity::<M, S, A>(&parent_items, client).await
        }
    }
}

impl<M, R, S> InsertManyWithConnectionReturning<M, R, S>
where
    M: InsertModel + InsertConnection<R> + Projection<M> + Clone,
    S: Projection<M>,
{
    pub fn execute<'a, A>(
        self,
        client: &'a crate::DinocoClient<A>,
    ) -> impl std::future::Future<Output = DinocoResult<Vec<S>>> + Send + 'a
    where
        M: Send + Sync + 'a,
        R: Send + Sync + 'a,
        S: Send + Sync + 'a,
        A: DinocoAdapter,
    {
        async move {
            let items = self.items;
            let connected_items = self.connected_items;
            let mut connection_updates = Vec::new();
            let mut relation_links = Vec::new();

            validate_pair_len(items.len(), connected_items.len(), "connection size")?;

            let parent_items = if M::auto_increment_primary_key_column().is_some() {
                let inserted = execute_insert_returning::<M, M, A>(items, client).await?;

                for (item, connected) in inserted.iter().zip(connected_items.iter()) {
                    connection_updates.extend(item.connection_updates(connected));
                    relation_links.extend(item.connection_links(connected));
                }

                inserted
            } else {
                for (item, connected) in items.iter().zip(connected_items.iter()) {
                    connection_updates.extend(item.connection_updates(connected));
                    relation_links.extend(item.connection_links(connected));
                }

                execute_insert::<M, A>(items.clone(), client).await?;
                items
            };

            execute_connection_updates(connection_updates, client).await?;
            execute_insert_relation_links(relation_links, client).await?;

            execute_reload_many_by_identity::<M, S, A>(&parent_items, client).await
        }
    }
}