Skip to content

Commit 1df6409

Browse files
committed
Use generic connection trait
This should allow SeaORM to perform schema discovery with a DatabaseConnection Also queries will not be run in parallel
1 parent 3b64e35 commit 1df6409

27 files changed

Lines changed: 434 additions & 289 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ name = "sea_schema"
3434
path = "src/lib.rs"
3535

3636
[dependencies]
37-
futures = { version = "0.3", default-features = false, optional = true, features = ["alloc"] }
37+
async-trait = { version = "0.1", default-features = false }
3838
sea-schema-derive = { version = "0.3.0", path = "sea-schema-derive", default-features = false }
3939
sea-query = { version = "1.0.0-rc.14", default-features = false, features = ["derive"] }
4040
sea-query-sqlx = { version = "0.8.0-rc.1", default-features = false, optional = true }
@@ -50,7 +50,7 @@ postgres = ["sea-query/backend-postgres"]
5050
postgres-vector = ["sea-query/postgres-vector", "sea-query-sqlx/postgres-vector"]
5151
sqlite = ["sea-query/backend-sqlite"]
5252
def = []
53-
discovery = ["futures", "parser"]
53+
discovery = ["parser"]
5454
parser = ["query"]
5555
query = ["def"]
5656
writer = ["def"]
@@ -60,21 +60,18 @@ sqlx-dep = ["sqlx"]
6060
sqlx-all = ["sqlx-mysql", "sqlx-postgres", "sqlx-sqlite"]
6161
sqlx-mysql = [
6262
"mysql",
63-
"futures",
6463
"sqlx-dep",
6564
"sea-query-sqlx/sqlx-mysql",
6665
"sqlx/mysql",
6766
]
6867
sqlx-postgres = [
6968
"postgres",
70-
"futures",
7169
"sqlx-dep",
7270
"sea-query-sqlx/sqlx-postgres",
7371
"sqlx/postgres",
7472
]
7573
sqlx-sqlite = [
7674
"sqlite",
77-
"futures",
7875
"sqlx-dep",
7976
"sea-query-sqlx/sqlx-sqlite",
8077
"sqlx/sqlite",

src/connection.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use crate::sqlx_types::{SqlxError, SqlxRow};
2+
use sea_query::SelectStatement;
3+
4+
#[async_trait::async_trait]
5+
pub trait Connection: Sized + Sync {
6+
async fn query_all(&self, select: SelectStatement) -> Result<Vec<SqlxRow>, SqlxError>;
7+
8+
async fn query_all_raw(&self, sql: String) -> Result<Vec<SqlxRow>, SqlxError>;
9+
}

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@ pub(crate) mod util;
2121
pub mod name;
2222
pub use name::*;
2323

24+
mod connection;
25+
pub use connection::*;
26+
2427
#[cfg(feature = "probe")]
2528
pub mod probe;
Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
1-
use crate::sqlx_types::{MySqlPool, mysql::MySqlRow};
1+
use crate::{
2+
Connection,
3+
sqlx_types::{MySqlPool, SqlxRow},
4+
};
25
use sea_query::{MysqlQueryBuilder, SelectStatement};
36

47
use crate::{debug_print, sqlx_types::SqlxError};
58

69
#[allow(dead_code)]
7-
pub struct Executor {
8-
pool: MySqlPool,
9-
}
10+
pub struct Executor {}
1011

1112
pub trait IntoExecutor {
1213
fn into_executor(self) -> Executor;
1314
}
1415

1516
impl IntoExecutor for MySqlPool {
1617
fn into_executor(self) -> Executor {
17-
Executor { pool: self }
18+
Executor {}
1819
}
1920
}
2021

21-
impl Executor {
22-
pub async fn fetch_all(&self, select: SelectStatement) -> Result<Vec<MySqlRow>, SqlxError> {
22+
#[async_trait::async_trait]
23+
impl Connection for Executor {
24+
async fn query_all(&self, select: SelectStatement) -> Result<Vec<SqlxRow>, SqlxError> {
2325
let (_sql, _values) = select.build(MysqlQueryBuilder);
2426
debug_print!("{}, {:?}", _sql, _values);
2527

2628
panic!("This is a mock Executor");
2729
}
30+
31+
async fn query_all_raw(&self, _sql: String) -> Result<Vec<SqlxRow>, SqlxError> {
32+
debug_print!("{}", _sql);
33+
34+
panic!("This is a mock Executor");
35+
}
2836
}

src/mysql/discovery/executor/real.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use sea_query::{MysqlQueryBuilder, SelectStatement};
22
use sea_query_sqlx::SqlxBinder;
3-
use sqlx::{MySqlPool, Row, mysql::MySqlRow};
3+
use sqlx::MySqlPool;
44

5-
use crate::{debug_print, sqlx_types::SqlxError};
5+
use crate::{
6+
Connection, debug_print,
7+
sqlx_types::{Row, SqlxError, SqlxRow, mysql::MySqlRow},
8+
};
69

710
pub struct Executor {
811
pool: MySqlPool,
@@ -18,17 +21,6 @@ impl IntoExecutor for MySqlPool {
1821
}
1922
}
2023

21-
impl Executor {
22-
pub async fn fetch_all(&self, select: SelectStatement) -> Result<Vec<MySqlRow>, SqlxError> {
23-
let (sql, values) = select.build_sqlx(MysqlQueryBuilder);
24-
debug_print!("{}, {:?}", sql, values);
25-
26-
sqlx::query_with(&sql, values)
27-
.fetch_all(&mut *self.pool.acquire().await?)
28-
.await
29-
}
30-
}
31-
3224
pub trait GetMySqlValue {
3325
fn get_string(&self, idx: usize) -> String;
3426

@@ -45,3 +37,29 @@ impl GetMySqlValue for MySqlRow {
4537
.map(|v| String::from_utf8(v).unwrap())
4638
}
4739
}
40+
41+
#[async_trait::async_trait]
42+
impl Connection for Executor {
43+
async fn query_all(&self, select: SelectStatement) -> Result<Vec<SqlxRow>, SqlxError> {
44+
let (sql, values) = select.build_sqlx(MysqlQueryBuilder);
45+
debug_print!("{}, {:?}", sql, values);
46+
47+
Ok(sqlx::query_with(&sql, values)
48+
.fetch_all(&mut *self.pool.acquire().await?)
49+
.await?
50+
.into_iter()
51+
.map(SqlxRow::MySql)
52+
.collect())
53+
}
54+
55+
async fn query_all_raw(&self, sql: String) -> Result<Vec<SqlxRow>, SqlxError> {
56+
debug_print!("{}", sql);
57+
58+
Ok(sqlx::query(&sql)
59+
.fetch_all(&mut *self.pool.acquire().await?)
60+
.await?
61+
.into_iter()
62+
.map(SqlxRow::MySql)
63+
.collect())
64+
}
65+
}

src/mysql/discovery/mod.rs

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,45 @@ use crate::mysql::query::{
77
ColumnQueryResult, ForeignKeyQueryResult, IndexQueryResult, SchemaQueryBuilder,
88
TableQueryResult, VersionQueryResult,
99
};
10-
use crate::sqlx_types::SqlxError;
11-
use futures::future;
10+
use crate::{
11+
Connection,
12+
sqlx_types::{MySqlPool, SqlxError},
13+
};
1214
use sea_query::{Alias, DynIden, IntoIden, SeaRc};
1315

1416
mod executor;
1517
pub use executor::*;
1618

17-
pub struct SchemaDiscovery {
19+
pub struct SchemaDiscovery<C: Connection> {
1820
pub query: SchemaQueryBuilder,
19-
pub executor: Executor,
2021
pub schema: DynIden,
22+
conn: C,
23+
}
24+
25+
impl SchemaDiscovery<Executor> {
26+
/// Discover schema from a SQLx pool
27+
pub fn new(pool: MySqlPool, schema: &str) -> Self {
28+
Self::conn(pool.into_executor(), schema)
29+
}
2130
}
2231

23-
impl SchemaDiscovery {
24-
pub fn new<E>(executor: E, schema: &str) -> Self
25-
where
26-
E: IntoExecutor,
27-
{
28-
Self {
32+
impl<C: Connection> SchemaDiscovery<C> {
33+
/// Discover schema from a generic SQLx connection
34+
pub fn conn(conn: C, schema: &str) -> Self {
35+
SchemaDiscovery {
2936
query: SchemaQueryBuilder::default(),
30-
executor: executor.into_executor(),
3137
schema: Alias::new(schema).into_iden(),
38+
conn,
3239
}
3340
}
3441

3542
pub async fn discover(mut self) -> Result<Schema, SqlxError> {
3643
self.query = SchemaQueryBuilder::new(self.discover_system().await?);
37-
let tables = self.discover_tables().await?;
38-
let tables = future::try_join_all(
39-
tables
40-
.into_iter()
41-
.map(|t| (&self, t))
42-
.map(Self::discover_table_static),
43-
)
44-
.await?;
44+
let mut tables = Vec::new();
45+
46+
for table in self.discover_tables().await? {
47+
tables.push(self.discover_table(table).await?);
48+
}
4549

4650
Ok(Schema {
4751
schema: self.schema.to_string(),
@@ -51,10 +55,10 @@ impl SchemaDiscovery {
5155
}
5256

5357
pub async fn discover_system(&mut self) -> Result<SystemInfo, SqlxError> {
54-
let rows = self.executor.fetch_all(self.query.query_version()).await?;
58+
let rows = self.conn.query_all(self.query.query_version()).await?;
5559

5660
#[allow(clippy::never_loop)]
57-
for row in rows.iter() {
61+
for row in rows {
5862
let result: VersionQueryResult = row.into();
5963
debug_print!("{:?}", result);
6064
let version = result.parse();
@@ -66,12 +70,12 @@ impl SchemaDiscovery {
6670

6771
pub async fn discover_tables(&mut self) -> Result<Vec<TableInfo>, SqlxError> {
6872
let rows = self
69-
.executor
70-
.fetch_all(self.query.query_tables(self.schema.clone()))
73+
.conn
74+
.query_all(self.query.query_tables(self.schema.clone()))
7175
.await?;
7276

7377
let tables: Vec<TableInfo> = rows
74-
.iter()
78+
.into_iter()
7579
.map(|row| {
7680
let result: TableQueryResult = row.into();
7781
debug_print!("{:?}", result);
@@ -84,12 +88,6 @@ impl SchemaDiscovery {
8488
Ok(tables)
8589
}
8690

87-
async fn discover_table_static(params: (&Self, TableInfo)) -> Result<TableDef, SqlxError> {
88-
let this = params.0;
89-
let info = params.1;
90-
Self::discover_table(this, info).await
91-
}
92-
9391
pub async fn discover_table(&self, info: TableInfo) -> Result<TableDef, SqlxError> {
9492
let table = SeaRc::new(Alias::new(info.name.as_str()));
9593
let columns = self
@@ -117,12 +115,12 @@ impl SchemaDiscovery {
117115
system: &SystemInfo,
118116
) -> Result<Vec<ColumnInfo>, SqlxError> {
119117
let rows = self
120-
.executor
121-
.fetch_all(self.query.query_columns(schema.clone(), table.clone()))
118+
.conn
119+
.query_all(self.query.query_columns(schema.clone(), table.clone()))
122120
.await?;
123121

124122
let columns = rows
125-
.iter()
123+
.into_iter()
126124
.map(|row| {
127125
let result: ColumnQueryResult = row.into();
128126
debug_print!("{:?}", result);
@@ -141,12 +139,12 @@ impl SchemaDiscovery {
141139
table: DynIden,
142140
) -> Result<Vec<IndexInfo>, SqlxError> {
143141
let rows = self
144-
.executor
145-
.fetch_all(self.query.query_indexes(schema.clone(), table.clone()))
142+
.conn
143+
.query_all(self.query.query_indexes(schema.clone(), table.clone()))
146144
.await?;
147145

148146
let results = rows.into_iter().map(|row| {
149-
let result: IndexQueryResult = (&row).into();
147+
let result: IndexQueryResult = row.into();
150148
debug_print!("{:?}", result);
151149
result
152150
});
@@ -164,12 +162,12 @@ impl SchemaDiscovery {
164162
table: DynIden,
165163
) -> Result<Vec<ForeignKeyInfo>, SqlxError> {
166164
let rows = self
167-
.executor
168-
.fetch_all(self.query.query_foreign_key(schema.clone(), table.clone()))
165+
.conn
166+
.query_all(self.query.query_foreign_key(schema.clone(), table.clone()))
169167
.await?;
170168

171169
let results = rows.into_iter().map(|row| {
172-
let result: ForeignKeyQueryResult = (&row).into();
170+
let result: ForeignKeyQueryResult = row.into();
173171
debug_print!("{:?}", result);
174172
result
175173
});

src/mysql/query/column.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{InformationSchema, SchemaQueryBuilder};
2-
use crate::sqlx_types::mysql::MySqlRow;
2+
use crate::sqlx_types::SqlxRow;
33
use sea_query::{DynIden, Expr, ExprTrait, Order, Query, SelectStatement, Value};
44

55
#[derive(Debug, sea_query::Iden)]
@@ -71,9 +71,10 @@ impl SchemaQueryBuilder {
7171
}
7272

7373
#[cfg(feature = "sqlx-mysql")]
74-
impl From<&MySqlRow> for ColumnQueryResult {
75-
fn from(row: &MySqlRow) -> Self {
74+
impl From<SqlxRow> for ColumnQueryResult {
75+
fn from(row: SqlxRow) -> Self {
7676
use crate::mysql::discovery::GetMySqlValue;
77+
let row = row.mysql();
7778
Self {
7879
column_name: row.get_string(0),
7980
column_type: row.get_string(1),
@@ -88,8 +89,8 @@ impl From<&MySqlRow> for ColumnQueryResult {
8889
}
8990

9091
#[cfg(not(feature = "sqlx-mysql"))]
91-
impl From<&MySqlRow> for ColumnQueryResult {
92-
fn from(_: &MySqlRow) -> Self {
92+
impl From<SqlxRow> for ColumnQueryResult {
93+
fn from(_: SqlxRow) -> Self {
9394
Self::default()
9495
}
9596
}

src/mysql/query/foreign_key.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{InformationSchema, SchemaQueryBuilder};
2-
use crate::sqlx_types::mysql::MySqlRow;
2+
use crate::sqlx_types::SqlxRow;
33
use sea_query::{DynIden, Expr, ExprTrait, Order, Query, SelectStatement};
44

55
#[derive(Debug, sea_query::Iden)]
@@ -79,8 +79,9 @@ impl SchemaQueryBuilder {
7979
}
8080

8181
#[cfg(feature = "sqlx-mysql")]
82-
impl From<&MySqlRow> for ForeignKeyQueryResult {
83-
fn from(row: &MySqlRow) -> Self {
82+
impl From<SqlxRow> for ForeignKeyQueryResult {
83+
fn from(row: SqlxRow) -> Self {
84+
let row = row.mysql();
8485
use crate::mysql::discovery::GetMySqlValue;
8586
Self {
8687
constraint_name: row.get_string(0),
@@ -94,8 +95,8 @@ impl From<&MySqlRow> for ForeignKeyQueryResult {
9495
}
9596

9697
#[cfg(not(feature = "sqlx-mysql"))]
97-
impl From<&MySqlRow> for ForeignKeyQueryResult {
98-
fn from(_: &MySqlRow) -> Self {
98+
impl From<SqlxRow> for ForeignKeyQueryResult {
99+
fn from(_: SqlxRow) -> Self {
99100
Self::default()
100101
}
101102
}

0 commit comments

Comments
 (0)