Skip to content

Commit b1e714b

Browse files
author
Alexei Pastuchov
committed
Merge branch 'weiznich-issue-3' into issue-3
2 parents 4ed4ca7 + 494511e commit b1e714b

File tree

11 files changed

+330
-1049
lines changed

11 files changed

+330
-1049
lines changed

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

+3
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>]>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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::deserialize::FromSql;
13+
use diesel::dsl::SqlTypeOf;
14+
use diesel::expression::{Expression, NonAggregate, SelectableExpression};
15+
use diesel::insertable::CanInsertInSingleQuery;
16+
use diesel::mysql::Mysql;
17+
use diesel::query_builder::{BoxedSelectStatement, QueryFragment};
18+
use diesel::query_dsl::methods::{BoxedDsl, FilterDsl};
19+
use diesel::sql_types::{Bigint, HasSqlType, Integer};
20+
use diesel::{no_arg_sql_function, EqAll, Identifiable};
21+
use diesel::{AppearsOnTable, Connection, Insertable, RunQueryDsl, Table};
22+
use juniper::{ExecutionResult, Executor, Selection, Value};
23+
use std::convert::TryFrom;
24+
25+
// https://dev.mysql.com/doc/refman/8.0/en/getting-unique-id.html
26+
diesel::no_arg_sql_function!(LAST_INSERT_ID, Bigint);
27+
28+
impl<I, Ctx, L, T> HandleInsert<L, I, Mysql, Ctx> for T
29+
where
30+
T: Table + HasTable<Table = T> + 'static,
31+
T::FromClause: QueryFragment<Mysql>,
32+
L: LoadingHandler<Mysql, Ctx, Table = T> + 'static,
33+
L::Columns: BuildOrder<T, Mysql>
34+
+ BuildSelect<T, Mysql, SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
35+
Ctx: WundergraphContext + QueryModifier<L, Mysql>,
36+
Ctx::Connection: Connection<Backend = Mysql>,
37+
L::FieldList: WundergraphFieldList<Mysql, L::PrimaryKeyIndex, T, Ctx>,
38+
I: Insertable<T>,
39+
I::Values: QueryFragment<Mysql> + CanInsertInSingleQuery<Mysql>,
40+
T::PrimaryKey: QueryFragment<Mysql> + Default,
41+
T: BoxedDsl<
42+
'static,
43+
Mysql,
44+
Output = BoxedSelectStatement<'static, SqlTypeOf<<T as Table>::AllColumns>, T, Mysql>,
45+
>,
46+
<Ctx::Connection as Connection>::Backend: HasSqlType<SqlTypeOf<T::PrimaryKey>>
47+
+ HasSqlType<SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
48+
<L::Filter as BuildFilter<Mysql>>::Ret: AppearsOnTable<T>,
49+
T::PrimaryKey: EqAll<i32>,
50+
T::PrimaryKey: Expression<SqlType = diesel::sql_types::Integer>,
51+
&'static L: Identifiable,
52+
<&'static L as Identifiable>::Id: UnRef<'static, UnRefed = i32>,
53+
<T::PrimaryKey as EqAll<i32>>::Output:
54+
SelectableExpression<T> + NonAggregate + QueryFragment<Mysql> + 'static,
55+
{
56+
fn handle_insert(
57+
selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
58+
executor: &Executor<'_, Ctx, WundergraphScalarValue>,
59+
insertable: I,
60+
) -> ExecutionResult<WundergraphScalarValue> {
61+
handle_single_insert(selection, executor, insertable)
62+
}
63+
}
64+
65+
impl<I, Ctx, L, T> HandleBatchInsert<L, I, Mysql, Ctx> for T
66+
where
67+
T: Table + HasTable<Table = T> + 'static,
68+
T::FromClause: QueryFragment<Mysql>,
69+
L: LoadingHandler<Mysql, Ctx, Table = T> + 'static,
70+
L::Columns: BuildOrder<T, Mysql>
71+
+ BuildSelect<T, Mysql, SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
72+
Ctx: WundergraphContext + QueryModifier<L, Mysql>,
73+
Ctx::Connection: Connection<Backend = Mysql>,
74+
L::FieldList: WundergraphFieldList<Mysql, L::PrimaryKeyIndex, T, Ctx>,
75+
I: Insertable<T>,
76+
I::Values: QueryFragment<Mysql> + CanInsertInSingleQuery<Mysql>,
77+
T::PrimaryKey: QueryFragment<Mysql> + Default,
78+
T: BoxedDsl<
79+
'static,
80+
Mysql,
81+
Output = BoxedSelectStatement<'static, SqlTypeOf<<T as Table>::AllColumns>, T, Mysql>,
82+
>,
83+
<Ctx::Connection as Connection>::Backend: HasSqlType<SqlTypeOf<T::PrimaryKey>>
84+
+ HasSqlType<SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
85+
<L::Filter as BuildFilter<Mysql>>::Ret: AppearsOnTable<T>,
86+
T::PrimaryKey: EqAll<i32>,
87+
T::PrimaryKey: Expression<SqlType = diesel::sql_types::Integer>,
88+
&'static L: Identifiable,
89+
<&'static L as Identifiable>::Id: UnRef<'static, UnRefed = i32>,
90+
<T::PrimaryKey as EqAll<i32>>::Output:
91+
SelectableExpression<T> + NonAggregate + QueryFragment<Mysql> + 'static,
92+
{
93+
fn handle_batch_insert(
94+
selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
95+
executor: &Executor<'_, Ctx, WundergraphScalarValue>,
96+
batch: Vec<I>,
97+
) -> ExecutionResult<WundergraphScalarValue> {
98+
let r = batch
99+
.into_iter()
100+
.map(|i| handle_single_insert(selection, executor, i))
101+
.collect::<Result<Vec<_>, _>>()?;
102+
Ok(Value::List(r))
103+
}
104+
}
105+
106+
fn handle_single_insert<L, I, T, Ctx>(
107+
selection: Option<&'_ [Selection<'_, WundergraphScalarValue>]>,
108+
executor: &Executor<'_, Ctx, WundergraphScalarValue>,
109+
insertable: I,
110+
) -> ExecutionResult<WundergraphScalarValue>
111+
where
112+
L: LoadingHandler<Mysql, Ctx, Table = T> + 'static,
113+
L::FieldList: WundergraphFieldList<Mysql, L::PrimaryKeyIndex, T, Ctx>,
114+
<L::Filter as BuildFilter<Mysql>>::Ret: AppearsOnTable<T>,
115+
L::Columns: BuildOrder<T, Mysql>
116+
+ BuildSelect<T, Mysql, SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
117+
&'static L: Identifiable,
118+
I: Insertable<T>,
119+
I::Values: QueryFragment<Mysql> + CanInsertInSingleQuery<Mysql>,
120+
Ctx: WundergraphContext + QueryModifier<L, Mysql>,
121+
Ctx::Connection: Connection<Backend = Mysql>,
122+
<Ctx::Connection as Connection>::Backend: HasSqlType<SqlTypeOf<T::PrimaryKey>>
123+
+ HasSqlType<SqlTypeOfPlaceholder<L::FieldList, Mysql, L::PrimaryKeyIndex, T, Ctx>>,
124+
T: Table + HasTable<Table = T> + 'static,
125+
T::FromClause: QueryFragment<Mysql>,
126+
T: BoxedDsl<
127+
'static,
128+
Mysql,
129+
Output = BoxedSelectStatement<'static, SqlTypeOf<<T as Table>::AllColumns>, T, Mysql>,
130+
>,
131+
T::PrimaryKey: EqAll<i32>,
132+
T::PrimaryKey: Expression<SqlType = Integer>,
133+
T::PrimaryKey: QueryFragment<Mysql> + Default,
134+
<T::PrimaryKey as EqAll<i32>>::Output:
135+
SelectableExpression<T> + NonAggregate + QueryFragment<Mysql> + 'static,
136+
i32: FromSql<Integer, Mysql>,
137+
{
138+
let ctx = executor.context();
139+
let conn = ctx.get_connection();
140+
let look_ahead = executor.look_ahead();
141+
insertable.insert_into(T::table()).execute(conn).unwrap();
142+
let last_insert_id: i64 = diesel::select(LAST_INSERT_ID).first(conn)?;
143+
let last_insert_id = i32::try_from(last_insert_id)?;
144+
let q = L::build_query(&[], &look_ahead)?;
145+
let q = FilterDsl::filter(q, T::PrimaryKey::default().eq_all(last_insert_id));
146+
let items = L::load(&look_ahead, selection, executor, q)?;
147+
Ok(items.into_iter().next().unwrap_or(Value::Null))
148+
}

wundergraph/src/query_builder/selection/offset.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use diesel::backend::Backend;
1010
use diesel::query_dsl::methods::LimitDsl;
1111
#[cfg(any(feature = "postgres", feature = "sqlite", feature = "mysql"))]
1212
use diesel::query_dsl::methods::OffsetDsl;
13+
1314
use juniper::LookAheadSelection;
1415

1516
/// A trait abstracting over the different behaviour of limit/offset

wundergraph_cli/src/print_schema/mod.rs

-39
Original file line numberDiff line numberDiff line change
@@ -39,45 +39,6 @@ pub fn print<W: Write>(
3939
)?;
4040
writeln!(out, "use wundergraph::scalar::WundergraphScalarValue;")?;
4141
writeln!(out, "use wundergraph::WundergraphEntity;")?;
42-
if cfg!(feature = "mysql") {
43-
writeln!(out, "use diesel::dsl::SqlTypeOf;")?;
44-
writeln!(out, "use diesel::mysql::Mysql;")?;
45-
writeln!(out, "use diesel::query_dsl::methods::FilterDsl;")?;
46-
writeln!(out, "use diesel::sql_types::{{Bigint, HasSqlType}};")?;
47-
writeln!(out, "use diesel::{{")?;
48-
writeln!(out, " no_arg_sql_function, AppearsOnTable, Connection, EqAll, Identifiable, Insertable, RunQueryDsl,")?;
49-
writeln!(out, "}};")?;
50-
writeln!(
51-
out,
52-
"use juniper::{{ExecutionResult, Executor, Selection, Value}};"
53-
)?;
54-
writeln!(out, "use std::convert::TryFrom;")?;
55-
writeln!(
56-
out,
57-
"use wundergraph::query_builder::mutations::{{HandleBatchInsert, HandleInsert}};"
58-
)?;
59-
writeln!(
60-
out,
61-
"use wundergraph::query_builder::selection::fields::WundergraphFieldList;"
62-
)?;
63-
writeln!(
64-
out,
65-
"use wundergraph::query_builder::selection::filter::BuildFilter;"
66-
)?;
67-
writeln!(
68-
out,
69-
"use wundergraph::query_builder::selection::order::BuildOrder;"
70-
)?;
71-
writeln!(
72-
out,
73-
"use wundergraph::query_builder::selection::select::BuildSelect;"
74-
)?;
75-
writeln!(out, "use wundergraph::query_builder::selection::{{LoadingHandler, QueryModifier, SqlTypeOfPlaceholder}};")?;
76-
writeln!(out, "use wundergraph::WundergraphContext;")?;
77-
writeln!(out)?;
78-
writeln!(out, "diesel::no_arg_sql_function!(LAST_INSERT_ID, Bigint);")?;
79-
}
80-
8142
writeln!(out)?;
8243
writeln!(out, "{}", definitions)?;
8344
writeln!(out)?;

0 commit comments

Comments
 (0)