Skip to content

Commit 142b7f3

Browse files
committed
insert_many method
1 parent fa772ae commit 142b7f3

File tree

14 files changed

+223
-73
lines changed

14 files changed

+223
-73
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ ormlite-macro = { path = "macro", version = "0.22" }
1919
ormlite = { path = "ormlite", version = "0.22" }
2020
convert_case = "0.7.1"
2121
quote = "1.0"
22+
itertools = "0.14.0"

core/src/model.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ where
7575
A: 'a + Send + sqlx::Acquire<'a, Database = DB>,
7676
Self: Send;
7777

78-
// fn insert_many<'e, E>(db: E, values: Vec<Self>) -> BoxFuture<'e, Result<Vec<Self>>>
79-
// where
80-
// E: 'e + sqlx::Executor<'e, Database = DB>;
78+
fn insert_many<'e, E>(values: Vec<Self>, db: E) -> BoxFuture<'e, Result<Vec<Self>>>
79+
where
80+
E: 'e + sqlx::Executor<'e, Database = DB>;
8181

8282
/// `Model` objects can't track what fields are updated, so this method will update all fields.
8383
/// If you want to update only some fields, use `update_partial` instead.

macro/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ default-postgres = ["postgres"]
2121
default-mysql = ["mysql"]
2222

2323
[dependencies]
24-
syn = { version = "2", features = ["derive", "parsing"] }
25-
quote = "1"
26-
proc-macro2 = "1"
24+
syn.workspace = true
25+
quote.workspace = true
26+
proc-macro2.workspace = true
2727
ormlite-core.workspace = true
2828
ormlite-attr.workspace = true
2929
sqlx.workspace = true
30-
itertools = "0.13.0"
30+
itertools.workspace = true
3131
convert_case.workspace = true

macro/src/codegen/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ pub fn insertion_binding(c: &ColumnMeta) -> TokenStream {
140140
}
141141

142142
pub trait OrmliteCodegen {
143+
fn dialect_ts(&self) -> TokenStream;
143144
fn database_ts(&self) -> TokenStream;
144145
fn placeholder_ts(&self) -> TokenStream;
145146
// A placeholder that works at the phase when its invoked (e.g. during comp time, it can be used.

macro/src/codegen/from_row.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub fn impl_FromRow(db: &dyn OrmliteCodegen, attr: &TableMeta, cache: &MetadataC
7272
)*
7373
{
7474
fn from_row(row: &'a #row) -> ::std::result::Result<Self, ::ormlite::SqlxError> {
75+
#[allow(unused_mut)]
7576
let mut model = Self::from_row_using_aliases(row, &[
7677
#(
7778
#field_names,

macro/src/codegen/insert.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use itertools::Itertools;
12
use crate::codegen::common::{generate_conditional_bind, insertion_binding, OrmliteCodegen};
23
use crate::MetadataCache;
34
use ormlite_attr::ColumnMeta;
@@ -38,6 +39,7 @@ pub fn impl_Model__insert(db: &dyn OrmliteCodegen, attr: &ModelMeta, metadata_ca
3839
});
3940

4041
quote! {
42+
#[allow(unused_mut)]
4143
fn insert<'a, A>(mut self, conn: A) -> ::ormlite::__private::Insertion<'a, A, Self, #db>
4244
where
4345
A: 'a + Send + ::ormlite::Acquire<'a, Database=#db>
@@ -132,11 +134,12 @@ pub fn impl_Insert(db: &dyn OrmliteCodegen, meta: &TableMeta, model: &Ident, ret
132134
let query_bindings = meta.database_columns().filter(|&c| !c.has_database_default).map(|c| {
133135
if let Some(rust_default) = &c.rust_default {
134136
let default: syn::Expr = syn::parse_str(&rust_default).expect("Failed to parse default_value");
135-
return quote! {
137+
quote! {
136138
q = q.bind(#default);
137-
};
139+
}
140+
} else {
141+
insertion_binding(c)
138142
}
139-
insertion_binding(c)
140143
});
141144

142145
let insert_join = meta.many_to_one_joins().map(|c| insert_join(c));
@@ -152,6 +155,7 @@ pub fn impl_Insert(db: &dyn OrmliteCodegen, meta: &TableMeta, model: &Ident, ret
152155
impl ::ormlite::model::Insert<#db> for #model {
153156
type Model = #returns;
154157

158+
#[allow(unused_mut)]
155159
fn insert<'a, A>(self, db: A) -> #box_future<'a, ::ormlite::Result<Self::Model>>
156160
where
157161
A: 'a + Send + ::ormlite::Acquire<'a, Database = #db>,
@@ -214,3 +218,54 @@ pub fn insert_join(c: &ColumnMeta) -> TokenStream {
214218
};
215219
}
216220
}
221+
222+
pub fn impl_Model__insert_many(db: &dyn OrmliteCodegen, meta: &ModelMeta, _mc: &MetadataCache) -> TokenStream {
223+
let box_future = crate::util::box_fut_ts();
224+
let placeholder = db.placeholder_ts();
225+
let dialect = db.dialect_ts();
226+
let db = db.database_ts();
227+
228+
let query_bindings = meta.database_columns().map(|c| {
229+
if let Some(rust_default) = &c.rust_default {
230+
let default: syn::Expr = syn::parse_str(&rust_default).expect("Failed to parse default_value");
231+
quote! {
232+
q = q.bind(#default);
233+
}
234+
} else if c.is_join() {
235+
let name = &c.ident;
236+
quote! {
237+
q = q.bind(model.#name._id());
238+
}
239+
} else {
240+
insertion_binding(c)
241+
}
242+
}).collect_vec();
243+
244+
quote! {
245+
fn insert_many<'e, E>(values: Vec<Self>, db: E) -> #box_future<'e, ::ormlite::Result<Vec<Self>>>
246+
where
247+
E: 'e + ::ormlite::Executor<'e, Database = #db>,
248+
{
249+
Box::pin(async move {
250+
let table = <Self as ::ormlite::TableMeta>::table_name();
251+
let columns = <Self as ::ormlite::TableMeta>::table_columns();
252+
let mut sql_values = ::ormlite::__private::Values::Values(Vec::new());
253+
for _ in 0..values.len() {
254+
let mut value = ::ormlite::__private::Value::new();
255+
value = value.placeholders(columns.len(), #dialect);
256+
sql_values = sql_values.value(value);
257+
}
258+
let sql = ::ormlite::__private::Insert::new(table)
259+
.columns(columns)
260+
.values(sql_values)
261+
.returning(columns);
262+
let sql = ::ormlite::__private::ToSql::to_sql(&sql, #dialect);
263+
let mut q = ::ormlite::query_as::<#db, Self>(&sql);
264+
for model in values {
265+
#(#query_bindings)*
266+
}
267+
q.fetch_all(db).await.map_err(Into::into)
268+
})
269+
}
270+
}
271+
}

macro/src/codegen/model.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::codegen::common::OrmliteCodegen;
2-
use crate::codegen::insert::impl_Model__insert;
2+
use crate::codegen::insert::{impl_Model__insert, impl_Model__insert_many};
33
use crate::codegen::select::impl_Model__select;
44
use crate::codegen::update::impl_Model__update_all_fields;
55
use crate::MetadataCache;
@@ -12,6 +12,7 @@ pub fn impl_Model(db: &dyn OrmliteCodegen, attr: &ModelMeta, metadata_cache: &Me
1212
let partial_model = attr.builder_struct();
1313

1414
let impl_Model__insert = impl_Model__insert(db, &attr, metadata_cache);
15+
let impl_Model__insert_many = impl_Model__insert_many(db, &attr, metadata_cache);
1516
let impl_Model__update_all_fields = impl_Model__update_all_fields(db, attr);
1617
let impl_Model__delete = impl_Model__delete(db, attr);
1718
let impl_Model__fetch_one = impl_Model__fetch_one(db, attr);
@@ -24,6 +25,7 @@ pub fn impl_Model(db: &dyn OrmliteCodegen, attr: &ModelMeta, metadata_cache: &Me
2425
type ModelBuilder<'a> = #partial_model<'a> where Self: 'a;
2526

2627
#impl_Model__insert
28+
#impl_Model__insert_many
2729
#impl_Model__update_all_fields
2830
#impl_Model__delete
2931
#impl_Model__fetch_one

macro/src/codegen/mysql.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use quote::quote;
77
pub struct MysqlBackend {}
88

99
impl OrmliteCodegen for MysqlBackend {
10+
fn dialect_ts(&self) -> TokenStream {
11+
quote! { ::ormlite::__private::Dialect::Mysql }
12+
}
1013
fn database_ts(&self) -> TokenStream {
1114
quote! { ::ormlite::mysql::Mysql }
1215
}

macro/src/codegen/postgres.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use quote::quote;
77
pub struct PostgresBackend;
88

99
impl OrmliteCodegen for PostgresBackend {
10+
fn dialect_ts(&self) -> TokenStream {
11+
quote! { ::ormlite::__private::Dialect::Postgres }
12+
}
1013
fn database_ts(&self) -> TokenStream {
1114
quote! { ::ormlite::postgres::Postgres }
1215
}

macro/src/codegen/sqlite.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use quote::quote;
77
pub struct SqliteBackend {}
88

99
impl OrmliteCodegen for SqliteBackend {
10+
fn dialect_ts(&self) -> TokenStream {
11+
quote! { ::ormlite::__private::Dialect::Sqlite }
12+
}
1013
fn database_ts(&self) -> TokenStream {
1114
quote! { ::ormlite::sqlite::Sqlite }
1215
}

0 commit comments

Comments
 (0)