Skip to content

Commit 2a026c0

Browse files
authored
Merge pull request #146 from WattSense/sync_wrapper_cleanup
Add SyncConnectionWrapper type
2 parents d02798c + d5a1d4f commit 2a026c0

File tree

18 files changed

+709
-47
lines changed

18 files changed

+709
-47
lines changed

.github/workflows/ci.yml

+101-21
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,16 @@ jobs:
2121
fail-fast: false
2222
matrix:
2323
rust: ["stable", "beta", "nightly"]
24-
backend: ["postgres", "mysql"]
25-
os: [ubuntu-latest, macos-latest, windows-latest]
24+
backend: ["postgres", "mysql", "sqlite"]
25+
os: [ubuntu-latest, macos-latest, macos-14, windows-2019]
2626
runs-on: ${{ matrix.os }}
2727
steps:
2828
- name: Checkout sources
29-
uses: actions/checkout@v2
29+
uses: actions/checkout@v4
3030

3131
- name: Cache cargo registry
32-
uses: actions/cache@v2
32+
uses: Swatinem/rust-cache@v2
3333
with:
34-
path: |
35-
~/.cargo/registry
36-
~/.cargo/git
3734
key: ${{ runner.os }}-${{ matrix.backend }}-cargo-${{ hashFiles('**/Cargo.toml') }}
3835

3936
- name: Set environment variables
@@ -66,24 +63,86 @@ jobs:
6663
mysql -e "create database diesel_test; create database diesel_unit_test; grant all on \`diesel_%\`.* to 'root'@'localhost';" -uroot -proot
6764
echo "DATABASE_URL=mysql://root:root@localhost/diesel_test" >> $GITHUB_ENV
6865
66+
- name: Install sqlite (Linux)
67+
if: runner.os == 'Linux' && matrix.backend == 'sqlite'
68+
run: |
69+
curl -fsS --retry 3 -o sqlite-autoconf-3400100.tar.gz https://www.sqlite.org/2022/sqlite-autoconf-3400100.tar.gz
70+
tar zxf sqlite-autoconf-3400100.tar.gz
71+
cd sqlite-autoconf-3400100
72+
CFLAGS="$CFLAGS -O2 -fno-strict-aliasing \
73+
-DSQLITE_DEFAULT_FOREIGN_KEYS=1 \
74+
-DSQLITE_SECURE_DELETE \
75+
-DSQLITE_ENABLE_COLUMN_METADATA \
76+
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
77+
-DSQLITE_ENABLE_RTREE=1 \
78+
-DSQLITE_SOUNDEX=1 \
79+
-DSQLITE_ENABLE_UNLOCK_NOTIFY \
80+
-DSQLITE_OMIT_LOOKASIDE=1 \
81+
-DSQLITE_ENABLE_DBSTAT_VTAB \
82+
-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 \
83+
-DSQLITE_ENABLE_LOAD_EXTENSION \
84+
-DSQLITE_ENABLE_JSON1 \
85+
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS \
86+
-DSQLITE_THREADSAFE=1 \
87+
-DSQLITE_ENABLE_FTS3_TOKENIZER=1 \
88+
-DSQLITE_MAX_SCHEMA_RETRY=25 \
89+
-DSQLITE_ENABLE_PREUPDATE_HOOK \
90+
-DSQLITE_ENABLE_SESSION \
91+
-DSQLITE_ENABLE_STMTVTAB \
92+
-DSQLITE_MAX_VARIABLE_NUMBER=250000" \
93+
./configure --prefix=/usr \
94+
--enable-threadsafe \
95+
--enable-dynamic-extensions \
96+
--libdir=/usr/lib/x86_64-linux-gnu \
97+
--libexecdir=/usr/lib/x86_64-linux-gnu/sqlite3
98+
sudo make
99+
sudo make install
100+
echo "DATABASE_URL=/tmp/test.db" >> $GITHUB_ENV
101+
69102
- name: Install postgres (MacOS)
70-
if: runner.os == 'macOS' && matrix.backend == 'postgres'
103+
if: matrix.os == 'macos-latest' && matrix.backend == 'postgres'
71104
run: |
72105
initdb -D /usr/local/var/postgres
73106
pg_ctl -D /usr/local/var/postgres start
74107
sleep 3
75108
createuser -s postgres
76109
echo "DATABASE_URL=postgres://postgres@localhost/" >> $GITHUB_ENV
77110
111+
- name: Install postgres (MacOS M1)
112+
if: matrix.os == 'macos-14' && matrix.backend == 'postgres'
113+
run: |
114+
brew install postgresql
115+
brew services start postgresql@14
116+
sleep 3
117+
createuser -s postgres
118+
echo "DATABASE_URL=postgres://postgres@localhost/" >> $GITHUB_ENV
119+
- name: Install sqlite (MacOS)
120+
if: runner.os == 'macOS' && matrix.backend == 'sqlite'
121+
run: |
122+
brew install sqlite
123+
echo "DATABASE_URL=/tmp/test.db" >> $GITHUB_ENV
124+
78125
- name: Install mysql (MacOS)
79-
if: runner.os == 'macOS' && matrix.backend == 'mysql'
126+
if: matrix.os == 'macos-latest' && matrix.backend == 'mysql'
127+
run: |
128+
brew install [email protected]
129+
/usr/local/opt/[email protected]/bin/mysql_install_db
130+
/usr/local/opt/[email protected]/bin/mysql.server start
131+
sleep 3
132+
/usr/local/opt/[email protected]/bin/mysqladmin -u runner password diesel
133+
/usr/local/opt/[email protected]/bin/mysql -e "create database diesel_test; create database diesel_unit_test; grant all on \`diesel_%\`.* to 'runner'@'localhost';" -urunner
134+
echo "DATABASE_URL=mysql://runner:diesel@localhost/diesel_test" >> $GITHUB_ENV
135+
136+
- name: Install mysql (MacOS M1)
137+
if: matrix.os == 'macos-14' && matrix.backend == 'mysql'
80138
run: |
81-
brew install --overwrite [email protected]
82-
/usr/local/opt/[email protected]/bin/mysql_install_db
83-
/usr/local/opt/[email protected]/bin/mysql.server start
139+
brew install [email protected]
140+
ls /opt/homebrew/opt/[email protected]
141+
/opt/homebrew/opt/[email protected]/bin/mysql_install_db
142+
/opt/homebrew/opt/[email protected]/bin/mysql.server start
84143
sleep 3
85-
/usr/local/opt/mariadb@10.8/bin/mysql -e "ALTER USER 'runner'@'localhost' IDENTIFIED BY 'diesel';" -urunner
86-
/usr/local/opt/mariadb@10.8/bin/mysql -e "create database diesel_test; create database diesel_unit_test; grant all on \`diesel_%\`.* to 'runner'@'localhost';" -urunner -pdiesel
144+
/opt/homebrew/opt/mariadb@11.3/bin/mysqladmin -u runner password diesel
145+
/opt/homebrew/opt/mariadb@11.3/bin/mysql -e "create database diesel_test; create database diesel_unit_test; grant all on \`diesel_%\`.* to 'runner'@'localhost';" -urunner
87146
echo "DATABASE_URL=mysql://runner:diesel@localhost/diesel_test" >> $GITHUB_ENV
88147
89148
- name: Install postgres (Windows)
@@ -106,6 +165,22 @@ jobs:
106165
run: |
107166
echo "DATABASE_URL=mysql://root@localhost/diesel_test" >> $GITHUB_ENV
108167
168+
- name: Install sqlite (Windows)
169+
if: runner.os == 'Windows' && matrix.backend == 'sqlite'
170+
shell: cmd
171+
run: |
172+
choco install sqlite
173+
cd /D C:\ProgramData\chocolatey\lib\SQLite\tools
174+
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
175+
lib /machine:x64 /def:sqlite3.def /out:sqlite3.lib
176+
- name: Set variables for sqlite (Windows)
177+
if: runner.os == 'Windows' && matrix.backend == 'sqlite'
178+
shell: bash
179+
run: |
180+
echo "C:\ProgramData\chocolatey\lib\SQLite\tools" >> $GITHUB_PATH
181+
echo "SQLITE3_LIB_DIR=C:\ProgramData\chocolatey\lib\SQLite\tools" >> $GITHUB_ENV
182+
echo "DATABASE_URL=C:\test.db" >> $GITHUB_ENV
183+
109184
- name: Install rust toolchain
110185
uses: dtolnay/rust-toolchain@master
111186
with:
@@ -115,26 +190,29 @@ jobs:
115190

116191
- name: Test diesel_async
117192
run: cargo +${{ matrix.rust }} test --manifest-path Cargo.toml --no-default-features --features "${{ matrix.backend }} deadpool bb8 mobc"
118-
- name: Run examples
193+
194+
- name: Run examples (Postgres)
119195
if: matrix.backend == 'postgres'
120196
run: |
121197
cargo +${{ matrix.rust }} check --manifest-path examples/postgres/pooled-with-rustls/Cargo.toml
122198
cargo +${{ matrix.rust }} check --manifest-path examples/postgres/run-pending-migrations-with-rustls/Cargo.toml
123199
200+
- name: Run examples (Sqlite)
201+
if: matrix.backend == 'sqlite'
202+
run: |
203+
cargo +${{ matrix.rust }} check --manifest-path examples/sync-wrapper/Cargo.toml
204+
124205
rustfmt_and_clippy:
125206
name: Check rustfmt style && run clippy
126207
runs-on: ubuntu-latest
127208
steps:
128-
- uses: actions/checkout@v2
209+
- uses: actions/checkout@v4
129210
- uses: dtolnay/rust-toolchain@stable
130211
with:
131212
components: clippy, rustfmt
132213
- name: Cache cargo registry
133-
uses: actions/cache@v2
214+
uses: Swatinem/rust-cache@v2
134215
with:
135-
path: |
136-
~/.cargo/registry
137-
~/.cargo/git
138216
key: clippy-cargo-${{ hashFiles('**/Cargo.toml') }}
139217

140218
- name: Remove potential newer clippy.toml from dependencies
@@ -152,12 +230,14 @@ jobs:
152230
name: Check Minimal supported rust version (1.65.0)
153231
runs-on: ubuntu-latest
154232
steps:
155-
- uses: actions/checkout@v3
233+
- uses: actions/checkout@v4
156234
- uses: dtolnay/[email protected]
157235
- uses: dtolnay/rust-toolchain@nightly
158236
- uses: taiki-e/install-action@cargo-hack
159237
- uses: taiki-e/install-action@cargo-minimal-versions
160238
- name: Check diesel-async
161239
# cannot test mysql yet as that crate
162240
# has broken min-version dependencies
241+
# cannot test sqlite yet as that crate
242+
# as broken min-version dependencies as well
163243
run: cargo +stable minimal-versions check -p diesel-async --features "postgres bb8 deadpool mobc"

Cargo.toml

+8-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ diesel_migrations = "2.1.0"
3838
default = []
3939
mysql = ["diesel/mysql_backend", "mysql_async", "mysql_common", "futures-channel", "tokio"]
4040
postgres = ["diesel/postgres_backend", "tokio-postgres", "tokio", "tokio/rt"]
41-
async-connection-wrapper = []
41+
sqlite = ["diesel/sqlite", "sync-connection-wrapper"]
42+
sync-connection-wrapper = ["tokio/rt"]
43+
async-connection-wrapper = ["tokio/net"]
4244
r2d2 = ["diesel/r2d2"]
4345

4446
[[test]]
@@ -47,7 +49,7 @@ path = "tests/lib.rs"
4749
harness = true
4850

4951
[package.metadata.docs.rs]
50-
features = ["postgres", "mysql", "deadpool", "bb8", "mobc", "async-connection-wrapper", "r2d2"]
52+
features = ["postgres", "mysql", "sqlite", "deadpool", "bb8", "mobc", "async-connection-wrapper", "sync-connection-wrapper", "r2d2"]
5153
no-default-features = true
5254
rustc-args = ["--cfg", "doc_cfg"]
5355
rustdoc-args = ["--cfg", "doc_cfg"]
@@ -57,4 +59,8 @@ members = [
5759
".",
5860
"examples/postgres/pooled-with-rustls",
5961
"examples/postgres/run-pending-migrations-with-rustls",
62+
"examples/sync-wrapper",
6063
]
64+
65+
[patch.crates-io]
66+
diesel = { git = "http://github.com/diesel-rs/diesel", rev = "793de72" }

examples/sync-wrapper/Cargo.toml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "sync-wrapper"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
diesel = { version = "2.1.0", default-features = false }
10+
diesel-async = { version = "0.4.0", path = "../../", features = ["sync-connection-wrapper", "async-connection-wrapper"] }
11+
diesel_migrations = "2.1.0"
12+
futures-util = "0.3.21"
13+
tokio = { version = "1.2.0", default-features = false, features = ["macros", "rt-multi-thread"] }
14+
15+
[features]
16+
default = ["sqlite"]
17+
sqlite = ["diesel-async/sqlite"]

examples/sync-wrapper/diesel.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# For documentation on how to configure this file,
2+
# see https://diesel.rs/guides/configuring-diesel-cli
3+
4+
[print_schema]
5+
file = "src/schema.rs"
6+
custom_type_derives = ["diesel::query_builder::QueryId"]
7+
8+
[migrations_directory]
9+
dir = "migrations"

examples/sync-wrapper/migrations/.keep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE IF EXISTS users;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
2+
3+
INSERT INTO users(id, name) VALUES(123, 'hello world');

examples/sync-wrapper/src/main.rs

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use diesel::prelude::*;
2+
use diesel::sqlite::{Sqlite, SqliteConnection};
3+
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
4+
use diesel_async::sync_connection_wrapper::SyncConnectionWrapper;
5+
use diesel_async::{AsyncConnection, RunQueryDsl, SimpleAsyncConnection};
6+
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
7+
8+
// ordinary diesel model setup
9+
10+
table! {
11+
users {
12+
id -> Integer,
13+
name -> Text,
14+
}
15+
}
16+
17+
#[derive(Debug, Queryable, Selectable)]
18+
#[diesel(table_name = users)]
19+
struct User {
20+
id: i32,
21+
name: String,
22+
}
23+
24+
const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
25+
26+
type InnerConnection = SqliteConnection;
27+
28+
type InnerDB = Sqlite;
29+
30+
async fn establish(db_url: &str) -> ConnectionResult<SyncConnectionWrapper<InnerConnection>> {
31+
// It is necessary to specify the specific inner connection type because of inference issues
32+
SyncConnectionWrapper::<SqliteConnection>::establish(db_url).await
33+
}
34+
35+
async fn run_migrations<A>(async_connection: A) -> Result<(), Box<dyn std::error::Error>>
36+
where
37+
A: AsyncConnection<Backend = InnerDB> + 'static,
38+
{
39+
let mut async_wrapper: AsyncConnectionWrapper<A> =
40+
AsyncConnectionWrapper::from(async_connection);
41+
42+
tokio::task::spawn_blocking(move || {
43+
async_wrapper.run_pending_migrations(MIGRATIONS).unwrap();
44+
})
45+
.await
46+
.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)
47+
}
48+
49+
#[tokio::main]
50+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
51+
let db_url = std::env::var("DATABASE_URL").expect("Env var `DATABASE_URL` not set");
52+
53+
// create an async connection for the migrations
54+
let sync_wrapper: SyncConnectionWrapper<InnerConnection> = establish(&db_url).await?;
55+
run_migrations(sync_wrapper).await?;
56+
57+
let mut sync_wrapper: SyncConnectionWrapper<InnerConnection> = establish(&db_url).await?;
58+
59+
sync_wrapper.batch_execute("DELETE FROM users").await?;
60+
61+
sync_wrapper
62+
.batch_execute("INSERT INTO users(id, name) VALUES (3, 'toto')")
63+
.await?;
64+
65+
let data: Vec<User> = users::table
66+
.select(User::as_select())
67+
.load(&mut sync_wrapper)
68+
.await?;
69+
println!("{data:?}");
70+
71+
diesel::delete(users::table)
72+
.execute(&mut sync_wrapper)
73+
.await?;
74+
75+
diesel::insert_into(users::table)
76+
.values((users::id.eq(1), users::name.eq("iLuke")))
77+
.execute(&mut sync_wrapper)
78+
.await?;
79+
80+
let data: Vec<User> = users::table
81+
.filter(users::id.gt(0))
82+
.or_filter(users::name.like("%Luke"))
83+
.select(User::as_select())
84+
.load(&mut sync_wrapper)
85+
.await?;
86+
println!("{data:?}");
87+
88+
Ok(())
89+
}

src/async_connection_wrapper.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,14 @@ pub type AsyncConnectionWrapper<C, B = self::implementation::Tokio> =
100100
pub use self::implementation::AsyncConnectionWrapper;
101101

102102
mod implementation {
103-
use diesel::connection::SimpleConnection;
103+
use diesel::connection::{Instrumentation, SimpleConnection};
104104

105105
use super::*;
106106

107107
pub struct AsyncConnectionWrapper<C, B> {
108108
inner: C,
109109
runtime: B,
110+
instrumentation: Option<Box<dyn Instrumentation>>,
110111
}
111112

112113
impl<C, B> From<C> for AsyncConnectionWrapper<C, B>
@@ -118,6 +119,7 @@ mod implementation {
118119
Self {
119120
inner,
120121
runtime: B::get_runtime(),
122+
instrumentation: None,
121123
}
122124
}
123125
}
@@ -148,7 +150,11 @@ mod implementation {
148150
let runtime = B::get_runtime();
149151
let f = C::establish(database_url);
150152
let inner = runtime.block_on(f)?;
151-
Ok(Self { inner, runtime })
153+
Ok(Self {
154+
inner,
155+
runtime,
156+
instrumentation: None,
157+
})
152158
}
153159

154160
fn execute_returning_count<T>(&mut self, source: &T) -> diesel::QueryResult<usize>
@@ -164,6 +170,14 @@ mod implementation {
164170
) -> &mut <Self::TransactionManager as diesel::connection::TransactionManager<Self>>::TransactionStateData{
165171
self.inner.transaction_state()
166172
}
173+
174+
fn instrumentation(&mut self) -> &mut dyn Instrumentation {
175+
&mut self.instrumentation
176+
}
177+
178+
fn set_instrumentation(&mut self, instrumentation: impl Instrumentation) {
179+
self.instrumentation = Some(Box::new(instrumentation));
180+
}
167181
}
168182

169183
impl<C, B> diesel::connection::LoadConnection for AsyncConnectionWrapper<C, B>

0 commit comments

Comments
 (0)