Skip to content
This repository was archived by the owner on Apr 25, 2023. It is now read-only.

Commit 0b8b102

Browse files
author
Julius de Bruijn
committed
Last insert id for my/sqlite
1 parent 608e75c commit 0b8b102

File tree

11 files changed

+90
-26
lines changed

11 files changed

+90
-26
lines changed

Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ documentation = "https://docs.rs/quaint/"
2222
features = [ "full", "serde-support", "json-1", "uuid-0_8", "chrono-0_4", "array" ]
2323

2424
[features]
25-
default = []
25+
default = ["runtime-tokio"]
2626

27-
full = ["pooled", "json-1", "postgresql", "uuid-0_8", "chrono-0_4", "mysql", "mssql"]
27+
full = ["pooled", "json-1", "postgresql", "uuid-0_8", "chrono-0_4", "mysql", "mssql", "sqlite"]
2828
full-postgresql = ["pooled", "postgresql", "json-1", "uuid-0_8", "chrono-0_4", "array"]
2929
full-mysql = ["pooled", "mysql", "json-1", "uuid-0_8", "chrono-0_4"]
3030
full-sqlite = ["pooled", "sqlite", "json-1", "uuid-0_8", "chrono-0_4"]
3131
full-mssql = ["pooled", "mssql"]
3232

33-
single = [ "json-1", "postgresql", "uuid-0_8", "chrono-0_4", "mysql", "mssql"]
33+
single = [ "json-1", "postgresql", "uuid-0_8", "chrono-0_4", "mysql", "mssql", "sqlite"]
3434
single-postgresql = ["postgresql", "json-1", "uuid-0_8", "chrono-0_4", "array"]
3535
single-mysql = ["mysql", "json-1", "uuid-0_8", "chrono-0_4"]
3636
single-sqlite = ["sqlite", "json-1", "uuid-0_8", "chrono-0_4"]

src/connector/mssql.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod conversion;
33
mod error;
44

55
use crate::{
6-
ast::{Query, Value},
6+
ast::{Insert, Query, Value},
77
connector::{metrics, queryable::*, timeout::timeout, ResultSet, Transaction},
88
visitor::{self, Visitor},
99
};
@@ -126,6 +126,10 @@ impl Queryable for Mssql {
126126
.await
127127
}
128128

129+
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
130+
self.query(q.into()).await
131+
}
132+
129133
async fn raw_cmd(&self, cmd: &str) -> crate::Result<()> {
130134
metrics::query_new("mssql.raw_cmd", cmd, vec![], move |_| async move {
131135
let mut client = self.client.lock().await;

src/connector/mysql.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ pub use config::*;
88

99
use async_trait::async_trait;
1010
use futures::{lock::Mutex, TryStreamExt};
11-
use sqlx::{Column, Connect, MySqlConnection, Row};
11+
use sqlx::{Column, Connection, Done, MySqlConnection, Row};
1212
use std::time::Duration;
1313

1414
use crate::{
15-
ast::{Query, Value},
15+
ast::{Insert, Query, Value},
1616
connector::{bind::Bind, metrics, queryable::*, timeout::timeout, ResultSet},
1717
error::Error,
1818
visitor::{self, Visitor},
@@ -97,9 +97,30 @@ impl Queryable for Mysql {
9797
}
9898

9999
let mut conn = self.connection.lock().await;
100-
let changes = timeout(self.socket_timeout, query.execute(&mut *conn)).await?;
100+
let done = timeout(self.socket_timeout, query.execute(&mut *conn)).await?;
101101

102-
Ok(changes)
102+
Ok(done.rows_affected())
103+
})
104+
.await
105+
}
106+
107+
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
108+
let (sql, params) = visitor::Mysql::build(q)?;
109+
110+
metrics::query_new("mysql.execute_raw", &sql, params, |params| async {
111+
let mut query = sqlx::query(&sql);
112+
113+
for param in params.into_iter() {
114+
query = query.bind_value(param, None)?;
115+
}
116+
117+
let mut conn = self.connection.lock().await;
118+
let done = timeout(self.socket_timeout, query.execute(&mut *conn)).await?;
119+
120+
let mut result_set = ResultSet::default();
121+
result_set.set_last_insert_id(done.last_insert_id());
122+
123+
Ok(result_set)
103124
})
104125
.await
105126
}

src/connector/postgres.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ mod conversion;
33
mod error;
44

55
use crate::{
6-
ast::{Query, Value},
6+
ast::{Insert, Query, Value},
77
connector::{bind::Bind, metrics, queryable::*, timeout::timeout, ResultSet, Transaction},
88
visitor::{self, Visitor},
99
};
1010
use async_trait::async_trait;
1111
pub use config::*;
1212
use either::Either;
1313
use futures::lock::Mutex;
14-
use sqlx::{Column as _, Connect, Executor, PgConnection};
14+
use sqlx::{Column as _, Connection, Done, Executor, PgConnection};
1515
use std::time::Duration;
1616

1717
/// A connector interface for the PostgreSQL database.
@@ -66,6 +66,10 @@ impl Queryable for PostgreSql {
6666
self.execute_raw(sql.as_str(), params).await
6767
}
6868

69+
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
70+
self.query(q.into()).await
71+
}
72+
6973
async fn query_raw(&self, sql: &str, params: Vec<Value<'_>>) -> crate::Result<ResultSet> {
7074
metrics::query_new("postgres.query_raw", sql, params, |params| async move {
7175
let mut conn = self.connection.lock().await;
@@ -110,9 +114,9 @@ impl Queryable for PostgreSql {
110114
}
111115

112116
let mut conn = self.connection.lock().await;
113-
let changes = query.execute(&mut *conn).await?;
117+
let done = query.execute(&mut *conn).await?;
114118

115-
Ok(changes)
119+
Ok(done.rows_affected())
116120
})
117121
.await
118122
}

src/connector/queryable.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ pub trait Queryable: Send + Sync {
4646
}
4747

4848
/// Execute an `INSERT` query.
49-
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
50-
self.query(q.into()).await
51-
}
49+
///
50+
/// A special case where `INSERT` could return data in PostgreSQL or SQL
51+
/// Server should be handled with the `insert` method. For other databases
52+
/// the `ResultSet` is empty but might contain the last insert id.
53+
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet>;
5254

5355
/// Execute an `UPDATE` query, returning the number of affected rows.
5456
async fn update(&self, q: Update<'_>) -> crate::Result<u64> {

src/connector/sqlite.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod conversion;
33
mod error;
44

55
use crate::{
6-
ast::{Query, Value},
6+
ast::{Insert, Query, Value},
77
connector::{bind::Bind, metrics, queryable::*, timeout::timeout, ResultSet},
88
error::Error,
99
visitor::{self, Visitor},
@@ -13,7 +13,7 @@ pub use config::*;
1313
use futures::{lock::Mutex, TryStreamExt};
1414
use sqlx::{
1515
sqlite::{SqliteConnectOptions, SqliteRow},
16-
Column as _, Connect, Row as _, SqliteConnection,
16+
Column as _, Connection, Done, Row as _, SqliteConnection,
1717
};
1818
use std::{collections::HashSet, convert::TryFrom, time::Duration};
1919

@@ -84,6 +84,27 @@ impl Queryable for Sqlite {
8484
self.execute_raw(&sql, params).await
8585
}
8686

87+
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
88+
let (sql, params) = visitor::Mysql::build(q)?;
89+
90+
metrics::query_new("sqlite.execute_raw", &sql, params, |params| async {
91+
let mut query = sqlx::query(&sql);
92+
93+
for param in params.into_iter() {
94+
query = query.bind_value(param, None)?;
95+
}
96+
97+
let mut conn = self.connection.lock().await;
98+
let done = timeout(self.socket_timeout, query.execute(&mut *conn)).await?;
99+
100+
let mut result_set = ResultSet::default();
101+
result_set.set_last_insert_id(done.last_insert_rowid() as u64);
102+
103+
Ok(result_set)
104+
})
105+
.await
106+
}
107+
87108
async fn query_raw(&self, sql: &str, params: Vec<Value<'_>>) -> crate::Result<ResultSet> {
88109
metrics::query_new("sqlite.query_raw", sql, params, move |params| async move {
89110
let mut query = sqlx::query(sql);
@@ -125,9 +146,9 @@ impl Queryable for Sqlite {
125146
}
126147

127148
let mut conn = self.connection.lock().await;
128-
let changes = timeout(self.socket_timeout, query.execute(&mut *conn)).await?;
149+
let done = timeout(self.socket_timeout, query.execute(&mut *conn)).await?;
129150

130-
Ok(changes)
151+
Ok(done.rows_affected())
131152
})
132153
.await
133154
}
@@ -473,9 +494,9 @@ mod tests {
473494
}
474495
}
475496

476-
#[tokio::test]
497+
#[tokio::test(threaded_scheduler)]
477498
async fn upper_fun() {
478-
let conn = Sqlite::try_from("file:db/test.db").unwrap();
499+
let conn = Sqlite::new("file:db/test.db").await.unwrap();
479500
let select = Select::default().value(upper("foo").alias("val"));
480501

481502
let res = conn.query(select.into()).await.unwrap();
@@ -485,9 +506,9 @@ mod tests {
485506
assert_eq!(Some("FOO"), val);
486507
}
487508

488-
#[tokio::test]
509+
#[tokio::test(threaded_scheduler)]
489510
async fn lower_fun() {
490-
let conn = Sqlite::try_from("file:db/test.db").unwrap();
511+
let conn = Sqlite::new("file:db/test.db").await.unwrap();
491512
let select = Select::default().value(lower("BAR").alias("val"));
492513

493514
let res = conn.query(select.into()).await.unwrap();

src/connector/transaction.rs

+4
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ impl<'a> Queryable for Transaction<'a> {
6161
async fn version(&self) -> crate::Result<Option<String>> {
6262
self.inner.version().await
6363
}
64+
65+
async fn insert(&self, q: Insert<'_>) -> crate::Result<ResultSet> {
66+
self.inner.insert(q).await
67+
}
6468
}

src/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl From<sqlx::Error> for Error {
291291
}
292292

293293
sqlx::Error::Io(io_error) => Error::builder(ErrorKind::ConnectionError(io_error.into())).build(),
294-
sqlx::Error::ParseConnectOptions(_) => Error::builder(ErrorKind::InvalidConnectionArguments).build(),
294+
sqlx::Error::Configuration(_) => Error::builder(ErrorKind::InvalidConnectionArguments).build(),
295295
sqlx::Error::Tls(e) => Error::builder(ErrorKind::TlsError { message: e.to_string() }).build(),
296296

297297
sqlx::Error::Protocol(s) => {

src/pooled/manager.rs

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ impl Queryable for PooledConnection {
3131
self.inner.execute(q).await
3232
}
3333

34+
async fn insert(&self, q: ast::Insert<'_>) -> crate::Result<connector::ResultSet> {
35+
self.inner.insert(q).await
36+
}
37+
3438
async fn query_raw(&self, sql: &str, params: Vec<ast::Value<'_>>) -> crate::Result<connector::ResultSet> {
3539
self.inner.query_raw(sql, params).await
3640
}

src/single.rs

+4
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ impl Queryable for Quaint {
165165
self.inner.execute(q).await
166166
}
167167

168+
async fn insert(&self, q: ast::Insert<'_>) -> crate::Result<connector::ResultSet> {
169+
self.inner.insert(q).await
170+
}
171+
168172
async fn query_raw(&self, sql: &str, params: Vec<ast::Value<'_>>) -> crate::Result<connector::ResultSet> {
169173
self.inner.query_raw(sql, params).await
170174
}

src/visitor/postgres.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ mod tests {
373373
#[test]
374374
fn equality_with_a_json_value() {
375375
let expected = expected_values(
376-
r#"SELECT "users".* FROM "users" WHERE "jsonField"::jsonb = $1::jsonb"#,
376+
r#"SELECT "users".* FROM "users" WHERE "jsonField"::jsonb = $1"#,
377377
vec![serde_json::json!({"a": "b"})],
378378
);
379379

@@ -388,7 +388,7 @@ mod tests {
388388
#[test]
389389
fn difference_with_a_json_value() {
390390
let expected = expected_values(
391-
r#"SELECT "users".* FROM "users" WHERE "jsonField"::jsonb <> $1::jsonb"#,
391+
r#"SELECT "users".* FROM "users" WHERE "jsonField"::jsonb <> $1"#,
392392
vec![serde_json::json!({"a": "b"})],
393393
);
394394

0 commit comments

Comments
 (0)