Skip to content

Commit 52759f9

Browse files
author
Alexei Pastuchov
committed
[UNFINISHED DRAFT] Implement HandleInsert and HandleBatchInsert for diesel::mysql::Mysql
1 parent 0ebcb0d commit 52759f9

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

wundergraph/src/query_builder/mutations/insert/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ mod pg;
1515
#[cfg(feature = "sqlite")]
1616
mod sqlite;
1717

18+
#[cfg(feature = "mysql")]
19+
mod mysql;
20+
1821
#[doc(hidden)]
1922
pub fn handle_insert<DB, I, R, Ctx>(
2023
selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use super::{HandleBatchInsert, HandleInsert};
2+
use crate::context::WundergraphContext;
3+
use crate::helper::UnRef;
4+
use crate::query_builder::selection::fields::WundergraphFieldList;
5+
use crate::query_builder::selection::filter::build_filter::BuildFilter;
6+
use crate::query_builder::selection::order::BuildOrder;
7+
use crate::query_builder::selection::query_modifier::QueryModifier;
8+
use crate::query_builder::selection::select::BuildSelect;
9+
use crate::query_builder::selection::{LoadingHandler, SqlTypeOfPlaceholder};
10+
use crate::scalar::WundergraphScalarValue;
11+
use diesel::associations::HasTable;
12+
use diesel::dsl::SqlTypeOf;
13+
use diesel::expression::{Expression, NonAggregate, SelectableExpression};
14+
use diesel::insertable::CanInsertInSingleQuery;
15+
use diesel::mysql::Mysql;
16+
use diesel::query_builder::{BoxedSelectStatement, QueryFragment};
17+
use diesel::query_dsl::methods::{BoxedDsl, FilterDsl, LimitDsl};
18+
use diesel::sql_types::{Bigint, HasSqlType};
19+
use diesel::{AppearsOnTable, Connection, Insertable, RunQueryDsl, Table};
20+
use diesel::{no_arg_sql_function, EqAll, Identifiable, Queryable};
21+
use juniper::{ExecutionResult, Executor, Selection, Value};
22+
23+
// https://dev.mysql.com/doc/refman/8.0/en/getting-unique-id.html
24+
diesel::no_arg_sql_function!(LAST_INSERT_ID, Bigint);
25+
26+
impl<I, Ctx, L, T> HandleInsert<L, I, Mysql, Ctx> for T
27+
where
28+
T: Table + HasTable<Table = T> + 'static,
29+
T::FromClause: QueryFragment<Mysql>,
30+
L: LoadingHandler<Mysql, Ctx, Table = T> + 'static,
31+
L::Columns: BuildOrder<T, Mysql>
32+
+ BuildSelect<T, Mysql, SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
33+
Ctx: WundergraphContext + QueryModifier<L, Mysql>,
34+
Ctx::Connection: Connection<Backend = Mysql>,
35+
L::FieldList: WundergraphFieldList<Mysql, L::PrimaryKeyIndex, T, Ctx>,
36+
I: Insertable<T>,
37+
I::Values: QueryFragment<Mysql> + CanInsertInSingleQuery<Mysql>,
38+
T::PrimaryKey: QueryFragment<Mysql> + Default,
39+
T: BoxedDsl<
40+
'static,
41+
Mysql,
42+
Output = BoxedSelectStatement<'static, SqlTypeOf<<T as Table>::AllColumns>, T, Mysql>,
43+
>,
44+
<Ctx::Connection as Connection>::Backend: HasSqlType<SqlTypeOf<T::PrimaryKey>>
45+
+ HasSqlType<SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
46+
<L::Filter as BuildFilter<Mysql>>::Ret: AppearsOnTable<T>,
47+
T::PrimaryKey: EqAll<i32>,
48+
T::PrimaryKey: Expression<SqlType = diesel::sql_types::Integer>,
49+
&'static L: Identifiable,
50+
<&'static L as Identifiable>::Id: UnRef<'static, UnRefed = i32>,
51+
<T::PrimaryKey as EqAll<i32>>::Output:
52+
SelectableExpression<T> + NonAggregate + QueryFragment<Mysql> + 'static,
53+
{
54+
fn handle_insert(
55+
selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
56+
executor: &Executor<'_, Ctx, WundergraphScalarValue>,
57+
insertable: I,
58+
) -> ExecutionResult<WundergraphScalarValue> {
59+
let ctx = executor.context();
60+
let conn = ctx.get_connection();
61+
conn.transaction(|| -> ExecutionResult<WundergraphScalarValue> {
62+
let look_ahead = executor.look_ahead();
63+
insertable.insert_into(T::table()).execute(conn)?;
64+
65+
let last_insert_id: i64 = diesel::select(LAST_INSERT_ID).first(conn)?;
66+
67+
let q = L::build_query(&[], &look_ahead)?;
68+
let q = FilterDsl::filter(q, T::PrimaryKey::default().eq_all(last_insert_id as i32));
69+
let q = LimitDsl::limit(q, 1);
70+
#[cfg(feature = "debug")]
71+
{
72+
log::debug!("{}", ::diesel::debug_query(&q));
73+
}
74+
let items = L::load(&look_ahead, selection, executor, q)?;
75+
76+
Ok(items.into_iter().next().unwrap_or(Value::Null))
77+
})
78+
}
79+
}
80+
81+
impl<I, Ctx, L, T, Id> HandleBatchInsert<L, I, Mysql, Ctx> for T
82+
where
83+
T: Table + HasTable<Table = T> + 'static,
84+
T::FromClause: QueryFragment<Mysql>,
85+
L: LoadingHandler<Mysql, Ctx, Table = T> + 'static,
86+
L::Columns: BuildOrder<T, Mysql>
87+
+ BuildSelect<T, Mysql, SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
88+
Ctx: WundergraphContext + QueryModifier<L, Mysql>,
89+
Ctx::Connection: Connection<Backend = Mysql>,
90+
L::FieldList: WundergraphFieldList<Mysql, L::PrimaryKeyIndex, T, Ctx>,
91+
Vec<I>: Insertable<T>,
92+
<Vec<I> as Insertable<T>>::Values: QueryFragment<Mysql> + CanInsertInSingleQuery<Mysql>,
93+
T::PrimaryKey: QueryFragment<Mysql> + Default,
94+
T: BoxedDsl<
95+
'static,
96+
Mysql,
97+
Output = BoxedSelectStatement<'static, SqlTypeOf<<T as Table>::AllColumns>, T, Mysql>,
98+
>,
99+
<Ctx::Connection as Connection>::Backend: HasSqlType<SqlTypeOf<T::PrimaryKey>>
100+
+ HasSqlType<SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
101+
<L::Filter as BuildFilter<Mysql>>::Ret: AppearsOnTable<T>,
102+
T::PrimaryKey: EqAll<Id>,
103+
&'static L: Identifiable,
104+
<&'static L as Identifiable>::Id: UnRef<'static, UnRefed = Id>,
105+
Id: Queryable<<T::PrimaryKey as Expression>::SqlType, Mysql>,
106+
<T::PrimaryKey as EqAll<Id>>::Output:
107+
SelectableExpression<T> + NonAggregate + QueryFragment<Mysql> + 'static,
108+
{
109+
fn handle_batch_insert(
110+
_selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
111+
executor: &Executor<'_, Ctx, WundergraphScalarValue>,
112+
_batch: Vec<I>,
113+
) -> ExecutionResult<WundergraphScalarValue> {
114+
let ctx = executor.context();
115+
let conn = ctx.get_connection();
116+
conn.transaction(|| -> ExecutionResult<WundergraphScalarValue> {
117+
unimplemented!()
118+
})
119+
}
120+
}

0 commit comments

Comments
 (0)