Skip to main content

diesel/sqlite/query_builder/
batch_update.rs

1use crate::query_builder::update_statement::batch_update::{
2    BATCH_UPDATE_ALIAS, BatchAssignHelper, BatchKeyHelper, BatchUpdate, BatchValueHelper,
3};
4use crate::query_builder::update_statement::changeset::{Assign, ColumnWrapperForUpdate};
5use crate::query_builder::{AstPass, QueryFragment};
6use crate::result::EmptyChangeset;
7use crate::result::Error::QueryBuilderError;
8use crate::{QueryResult, Table};
9
10impl<C, T> BatchAssignHelper<crate::sqlite::Sqlite> for Assign<ColumnWrapperForUpdate<C>, T>
11where
12    ColumnWrapperForUpdate<C>: QueryFragment<crate::sqlite::Sqlite>,
13{
14    fn batch_assign_identifier<'b>(
15        &'b self,
16        mut out: AstPass<'_, 'b, crate::sqlite::Sqlite>,
17    ) -> QueryResult<()> {
18        self.target.walk_ast(out.reborrow())
19    }
20}
21
22impl<I, C, Tab> QueryFragment<crate::sqlite::Sqlite, crate::sqlite::backend::SqliteBatchUpdate>
23    for BatchUpdate<I, C, Tab::PrimaryKey, Tab>
24where
25    I: BatchKeyHelper<Tab::PrimaryKey, crate::sqlite::Sqlite>,
26    C: BatchValueHelper<crate::sqlite::Sqlite>,
27    Tab: Table,
28{
29    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, crate::sqlite::Sqlite>) -> QueryResult<()> {
30        // Always unsafe to cache since this does not have a static query id.
31        out.unsafe_to_cache_prepared();
32
33        out.push_sql(" SET ");
34        // for sqlite:
35        // update test set name = source.name from (with cte(id, name) as (values (1, 'boom'), (2, 'baz')) select * from cte)
36        // as source where source.id = test.id;
37
38        let first = self
39            .values
40            .first()
41            .ok_or_else(|| QueryBuilderError(alloc::boxed::Box::new(EmptyChangeset)))?;
42
43        BatchValueHelper::assign(&first.1, out.reborrow())?;
44
45        out.push_sql(" FROM( WITH ");
46        out.push_identifier("CTE")?;
47        out.push_sql("(");
48        BatchKeyHelper::column_name(&first.0, out.reborrow())?;
49        out.push_sql(", ");
50        BatchValueHelper::column_name(&first.1, out.reborrow())?;
51        out.push_sql(") AS ( VALUES");
52        let mut values = self.values.iter();
53        if let Some((key, value)) = values.next() {
54            out.push_sql("(");
55            BatchKeyHelper::bind_value(key, out.reborrow())?;
56            out.push_sql(", ");
57            BatchValueHelper::bind_value(value, out.reborrow())?;
58            out.push_sql(")");
59        }
60        for (key, value) in values {
61            out.push_sql(", (");
62            BatchKeyHelper::bind_value(key, out.reborrow())?;
63            out.push_sql(", ");
64            BatchValueHelper::bind_value(value, out.reborrow())?;
65            out.push_sql(")");
66        }
67        out.push_sql(" ) SELECT * FROM ");
68        out.push_identifier("CTE")?;
69        out.push_sql(")");
70
71        out.push_sql(" AS ");
72        out.push_identifier(BATCH_UPDATE_ALIAS)?;
73        out.push_sql(" WHERE ");
74        <I as BatchKeyHelper<Tab::PrimaryKey, crate::sqlite::Sqlite>>::assign(
75            &self.primary_key,
76            out,
77        )?;
78
79        Ok(())
80    }
81}