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

Commit 23aaa05

Browse files
author
Julius de Bruijn
committed
Use SQLx in Postgres, MySQL and SQLite connectors
MySQL in SQLx SQLite in SQLx PostgreSQL in SQLx Refactor to latest SQLx Type-aware value binding Split mssql config to its own file, unified timeut Force JSON arguments to be of type JSONB Fix visitor tests to cope with jsonb casts switch to git sqlx Fix the caching issues finally in pg Send a clear error if having incompatible arrays Allow choosing between tokio and async-std Support decoding of TIMESTAMP Allow switching of runtime in mobc Skip a few loops by using describe's column info Last insert id for my/sqlite Remove tokio from default features Create sqlite database if it doesn't exist. Honing the types Fixing pg enums and raw_cmd. Testing last_insert_id. More green tests Back to git sqlx More green tests Test setup WIP Fixing the test
1 parent 61a8fdc commit 23aaa05

33 files changed

+2879
-2660
lines changed

Cargo.toml

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,77 +24,72 @@ features = [ "full", "serde-support", "json-1", "uuid-0_8", "chrono-0_4", "array
2424
[features]
2525
default = []
2626

27-
full = ["pooled", "sqlite", "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 = ["sqlite", "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"]
3737
single-mssql = ["mssql"]
3838

3939
postgresql = [
40-
"rust_decimal/tokio-pg",
41-
"native-tls",
42-
"tokio-postgres",
43-
"postgres-types",
44-
"postgres-native-tls",
40+
"sqlx/postgres",
4541
"array",
4642
"bytes",
47-
"tokio",
4843
"bit-vec",
49-
"lru-cache"
44+
"ipnetwork"
5045
]
5146

5247
pooled = ["mobc"]
53-
sqlite = ["rusqlite", "libsqlite3-sys", "tokio/sync"]
48+
sqlite = ["sqlx/sqlite"]
5449
json-1 = ["serde_json", "base64"]
55-
uuid-0_8 = ["uuid"]
50+
uuid-0_8 = ["uuid", "sqlx/uuid"]
5651
chrono-0_4 = ["chrono"]
57-
mysql = ["mysql_async", "tokio"]
58-
mssql = ["tiberius", "uuid-0_8", "chrono-0_4", "tokio-util"]
52+
mysql = ["sqlx/mysql"]
53+
mssql = ["tiberius", "uuid-0_8", "chrono-0_4"]
5954
tracing-log = ["tracing", "tracing-core"]
6055
array = []
6156
serde-support = ["serde", "chrono/serde"]
6257

58+
runtime-tokio = ["tokio", "tokio-util", "sqlx/runtime-tokio", "tiberius/sql-browser-tokio", "mobc/tokio"]
59+
runtime-async-std = ["async-std", "sqlx/runtime-async-std", "tiberius/sql-browser-async-std", "mobc/async-std"]
60+
6361
[dependencies]
6462
url = "2.1"
6563
metrics = "0.12"
6664
percent-encoding = "2"
6765
once_cell = "1.3"
6866
num_cpus = "1.12"
69-
rust_decimal = { git = "https://github.com/pimeys/rust-decimal", branch = "pgbouncer-mode" }
67+
rust_decimal = "1.7"
7068
futures = "0.3"
7169
thiserror = "1.0"
7270
async-trait = "0.1"
7371
hex = "0.4"
72+
bigdecimal = "0.1"
7473

7574
uuid = { version = "0.8", optional = true }
7675
chrono = { version = "0.4", optional = true }
7776
serde_json = { version = "1.0.48", optional = true }
7877
base64 = { version = "0.11.0", optional = true }
7978
lru-cache = { version = "0.1", optional = true }
8079

81-
rusqlite = { version = "0.21", features = ["chrono", "bundled"], optional = true }
82-
libsqlite3-sys = { version = "0.17", default-features = false, features = ["bundled"], optional = true }
83-
84-
native-tls = { version = "0.2", optional = true }
85-
86-
mysql_async = { version = "0.23", optional = true }
87-
8880
log = { version = "0.4", features = ["release_max_level_trace"] }
8981
tracing = { version = "0.1", optional = true }
9082
tracing-core = { version = "0.1", optional = true }
9183

92-
mobc = { version = "0.5.7", optional = true }
84+
mobc = { version = "0.5.7", optional = true, default-features = false, features = ["unstable"] }
9385
bytes = { version = "0.5", optional = true }
9486
tokio = { version = "0.2", features = ["rt-threaded", "macros", "sync"], optional = true}
9587
tokio-util = { version = "0.3", features = ["compat"], optional = true }
88+
async-std = { version = "1.6.2", optional = true }
9689
serde = { version = "1.0", optional = true }
9790
bit-vec = { version = "0.6.1", optional = true }
91+
ipnetwork = { version = "0.16.0", optional = true }
92+
either = "1.5.3"
9893

9994
[dev-dependencies]
10095
tokio = { version = "0.2", features = ["rt-threaded", "macros"]}
@@ -106,24 +101,17 @@ test-setup = { path = "test-setup" }
106101
paste = "1.0"
107102

108103
[dependencies.tiberius]
109-
git = "https://github.com/prisma/tiberius"
104+
version = "0.4"
110105
optional = true
111-
features = ["rust_decimal", "sql-browser-tokio", "chrono"]
112-
branch = "pgbouncer-mode-hack"
106+
features = ["rust_decimal", "chrono"]
113107

114-
[dependencies.tokio-postgres]
115-
git = "https://github.com/pimeys/rust-postgres"
116-
features = ["with-uuid-0_8", "with-chrono-0_4", "with-serde_json-1", "with-bit-vec-0_6"]
117-
branch = "pgbouncer-mode"
108+
[dependencies.sqlx]
109+
path = "../sqlx"
110+
default_features = false
111+
features = ["decimal", "json", "chrono", "ipnetwork", "bit-vec"]
118112
optional = true
119113

120-
[dependencies.postgres-types]
121-
git = "https://github.com/pimeys/rust-postgres"
122-
features = ["with-uuid-0_8", "with-chrono-0_4", "with-serde_json-1", "with-bit-vec-0_6"]
123-
branch = "pgbouncer-mode"
124-
optional = true
125-
126-
[dependencies.postgres-native-tls]
127-
git = "https://github.com/pimeys/rust-postgres"
128-
optional = true
129-
branch = "pgbouncer-mode"
114+
[[test]]
115+
name = "mysql-types"
116+
path = "tests/mysql/types.rs"
117+
required-features = [ "mysql" ]

src/ast/values.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ impl<'a> Value<'a> {
332332

333333
/// Transforms the `Value` to a `String` if it's text,
334334
/// otherwise `None`.
335+
335336
pub fn into_string(self) -> Option<String> {
336337
match self {
337338
Value::Text(Some(cow)) => Some(cow.into_owned()),
@@ -366,6 +367,15 @@ impl<'a> Value<'a> {
366367
}
367368
}
368369

370+
/// Returns a `Vec<u8>` if the value is text or a byte slice, otherwise `None`.
371+
pub fn into_bytes(self) -> Option<Vec<u8>> {
372+
match self {
373+
Value::Text(Some(cow)) => Some(cow.into_owned().into_bytes()),
374+
Value::Bytes(Some(cow)) => Some(cow.into_owned()),
375+
_ => None,
376+
}
377+
}
378+
369379
/// `true` if the `Value` is an integer.
370380
pub fn is_integer(&self) -> bool {
371381
match self {
@@ -485,6 +495,7 @@ impl<'a> Value<'a> {
485495
pub fn as_date(&self) -> Option<NaiveDate> {
486496
match self {
487497
Value::Date(dt) => dt.clone(),
498+
Value::DateTime(dt) => dt.map(|dt| dt.date().naive_utc()),
488499
_ => None,
489500
}
490501
}
@@ -503,6 +514,7 @@ impl<'a> Value<'a> {
503514
pub fn as_time(&self) -> Option<NaiveTime> {
504515
match self {
505516
Value::Time(time) => time.clone(),
517+
Value::DateTime(dt) => dt.map(|dt| dt.time()),
506518
_ => None,
507519
}
508520
}

src/connector.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
//! implement the [Queryable](trait.Queryable.html) trait for generalized
1010
//! querying interface.
1111
12+
mod bind;
1213
mod connection_info;
1314
pub(crate) mod metrics;
1415
mod queryable;
1516
mod result_set;
17+
mod timeout;
1618
mod transaction;
1719
mod type_identifier;
1820

@@ -25,16 +27,15 @@ pub(crate) mod postgres;
2527
#[cfg(feature = "sqlite")]
2628
pub(crate) mod sqlite;
2729

28-
#[cfg(feature = "mysql")]
29-
pub use self::mysql::*;
3030
#[cfg(feature = "postgresql")]
3131
pub use self::postgres::*;
3232
pub use self::result_set::*;
3333
pub use connection_info::*;
3434
#[cfg(feature = "mssql")]
3535
pub use mssql::*;
36+
#[cfg(feature = "mysql")]
37+
pub use mysql::*;
3638
pub use queryable::*;
3739
#[cfg(feature = "sqlite")]
3840
pub use sqlite::*;
3941
pub use transaction::*;
40-
pub(crate) use type_identifier::*;

src/connector/bind.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use crate::ast::Value;
2+
use sqlx::Database;
3+
4+
pub trait Bind<'a, DB>
5+
where
6+
DB: Database,
7+
{
8+
fn bind_value(self, value: Value<'a>, type_info: Option<&DB::TypeInfo>) -> crate::Result<Self>
9+
where
10+
Self: Sized;
11+
}

src/connector/metrics.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,45 @@ where
4040

4141
res
4242
}
43+
44+
pub(crate) async fn query_new<'a, F, T, U>(
45+
tag: &'static str,
46+
query: &'a str,
47+
params: Vec<Value<'a>>,
48+
f: F,
49+
) -> crate::Result<T>
50+
where
51+
F: FnOnce(Vec<Value<'a>>) -> U + 'a,
52+
U: Future<Output = crate::Result<T>> + 'a,
53+
{
54+
if *crate::LOG_QUERIES {
55+
let start = Instant::now();
56+
let res = f(params.clone()).await;
57+
let end = Instant::now();
58+
59+
#[cfg(not(feature = "tracing-log"))]
60+
{
61+
info!(
62+
"query: \"{}\", params: {} (in {}ms)",
63+
query,
64+
Params(&params),
65+
start.elapsed().as_millis(),
66+
);
67+
}
68+
#[cfg(feature = "tracing-log")]
69+
{
70+
tracing::info!(
71+
query,
72+
item_type = "query",
73+
params = %Params(&params),
74+
duration_ms = start.elapsed().as_millis() as u64,
75+
)
76+
}
77+
78+
timing!(format!("{}.query.time", tag), start, end);
79+
80+
res
81+
} else {
82+
f(params).await
83+
}
84+
}

0 commit comments

Comments
 (0)