Skip to content

Commit 189d4db

Browse files
committed
refactor: Update feature combination macros for database trait generation
This commit refactors the feature combination macros used for generating the `AnyEncode`, `AnyDecode`, and `AnyColumnIndex` traits in the sqlx-core library. The new structure improves clarity and maintainability by consolidating the macro definitions and enhancing the way database combinations are processed, while ensuring continued support for all specified databases.
1 parent 890417e commit 189d4db

File tree

5 files changed

+69
-150
lines changed

5 files changed

+69
-150
lines changed

sqlx-core/src/any/column.rs

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -88,55 +88,6 @@ impl Column for AnyColumn {
8888
}
8989
}
9090

91-
// Macro to generate all feature combinations for column index
92-
macro_rules! for_all_feature_combinations {
93-
// Entry point
94-
( $callback:ident ) => {
95-
for_all_feature_combinations!(@parse_databases [
96-
("postgres", PgRow, PgStatement),
97-
("mysql", MySqlRow, MySqlStatement),
98-
("mssql", MssqlRow, MssqlStatement),
99-
("sqlite", SqliteRow, SqliteStatement),
100-
("odbc", OdbcRow, OdbcStatement)
101-
] $callback);
102-
};
103-
104-
// Convert the database list format to tokens suitable for recursion
105-
(@parse_databases [ $(($feat:literal, $row:ident, $stmt:ident)),* ] $callback:ident) => {
106-
for_all_feature_combinations!(@recurse [] [] [$( ($feat, $row, $stmt) )*] $callback);
107-
};
108-
109-
// Recursive case: process each database
110-
(@recurse [$($yes:tt)*] [$($no:tt)*] [($feat:literal, $row:ident, $stmt:ident) $($rest:tt)*] $callback:ident) => {
111-
// Include this database
112-
for_all_feature_combinations!(@recurse
113-
[$($yes)* ($feat, $row, $stmt)]
114-
[$($no)*]
115-
[$($rest)*]
116-
$callback
117-
);
118-
119-
// Exclude this database
120-
for_all_feature_combinations!(@recurse
121-
[$($yes)*]
122-
[$($no)* $feat]
123-
[$($rest)*]
124-
$callback
125-
);
126-
};
127-
128-
// Base case: no more databases, generate the implementation if we have at least one
129-
(@recurse [$(($feat:literal, $row:ident, $stmt:ident))+] [$($no:literal)*] [] $callback:ident) => {
130-
#[cfg(all($(feature = $feat),+ $(, not(feature = $no))*))]
131-
$callback! { $(($row, $stmt)),+ }
132-
};
133-
134-
// Base case: no databases selected, skip
135-
(@recurse [] [$($no:literal)*] [] $callback:ident) => {
136-
// Don't generate anything for zero databases
137-
};
138-
}
139-
14091
// Callback macro that generates the actual trait and impl
14192
macro_rules! impl_any_column_index_for_databases {
14293
($(($row:ident, $stmt:ident)),+) => {
@@ -150,4 +101,13 @@ macro_rules! impl_any_column_index_for_databases {
150101
}
151102

152103
// Generate all combinations
153-
for_all_feature_combinations!(impl_any_column_index_for_databases);
104+
for_all_feature_combinations! {
105+
entries: [
106+
("postgres", (PgRow, PgStatement)),
107+
("mysql", (MySqlRow, MySqlStatement)),
108+
("mssql", (MssqlRow, MssqlStatement)),
109+
("sqlite", (SqliteRow, SqliteStatement)),
110+
("odbc", (OdbcRow, OdbcStatement)),
111+
],
112+
callback: impl_any_column_index_for_databases
113+
}

sqlx-core/src/any/decode.rs

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -58,55 +58,6 @@ macro_rules! impl_any_decode {
5858
};
5959
}
6060

61-
// Macro to generate all feature combinations
62-
macro_rules! for_all_feature_combinations {
63-
// Entry point
64-
( $callback:ident ) => {
65-
for_all_feature_combinations!(@parse_databases [
66-
("postgres", Postgres),
67-
("mysql", MySql),
68-
("mssql", Mssql),
69-
("sqlite", Sqlite),
70-
("odbc", Odbc)
71-
] $callback);
72-
};
73-
74-
// Convert the database list format to tokens suitable for recursion
75-
(@parse_databases [ $(($feat:literal, $ty:ident)),* ] $callback:ident) => {
76-
for_all_feature_combinations!(@recurse [] [] [$( ($feat, $ty) )*] $callback);
77-
};
78-
79-
// Recursive case: process each database
80-
(@recurse [$($yes:tt)*] [$($no:tt)*] [($feat:literal, $ty:ident) $($rest:tt)*] $callback:ident) => {
81-
// Include this database
82-
for_all_feature_combinations!(@recurse
83-
[$($yes)* ($feat, $ty)]
84-
[$($no)*]
85-
[$($rest)*]
86-
$callback
87-
);
88-
89-
// Exclude this database
90-
for_all_feature_combinations!(@recurse
91-
[$($yes)*]
92-
[$($no)* $feat]
93-
[$($rest)*]
94-
$callback
95-
);
96-
};
97-
98-
// Base case: no more databases, generate the implementation if we have at least one
99-
(@recurse [$(($feat:literal, $ty:ident))+] [$($no:literal)*] [] $callback:ident) => {
100-
#[cfg(all($(feature = $feat),+ $(, not(feature = $no))*))]
101-
$callback! { $($ty),+ }
102-
};
103-
104-
// Base case: no databases selected, skip
105-
(@recurse [] [$($no:literal)*] [] $callback:ident) => {
106-
// Don't generate anything for zero databases
107-
};
108-
}
109-
11061
// Callback macro that generates the actual trait and impl
11162
macro_rules! impl_any_decode_for_databases {
11263
($($db:ident),+) => {
@@ -120,4 +71,13 @@ macro_rules! impl_any_decode_for_databases {
12071
}
12172

12273
// Generate all combinations
123-
for_all_feature_combinations!(impl_any_decode_for_databases);
74+
for_all_feature_combinations! {
75+
entries: [
76+
("postgres", Postgres),
77+
("mysql", MySql),
78+
("mssql", Mssql),
79+
("sqlite", Sqlite),
80+
("odbc", Odbc),
81+
],
82+
callback: impl_any_decode_for_databases
83+
}

sqlx-core/src/any/encode.rs

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -60,55 +60,6 @@ macro_rules! impl_any_encode {
6060
};
6161
}
6262

63-
// Macro to generate all feature combinations
64-
macro_rules! for_all_feature_combinations {
65-
// Entry point
66-
( $callback:ident ) => {
67-
for_all_feature_combinations!(@parse_databases [
68-
("postgres", Postgres),
69-
("mysql", MySql),
70-
("mssql", Mssql),
71-
("sqlite", Sqlite),
72-
("odbc", Odbc)
73-
] $callback);
74-
};
75-
76-
// Convert the database list format to tokens suitable for recursion
77-
(@parse_databases [ $(($feat:literal, $ty:ident)),* ] $callback:ident) => {
78-
for_all_feature_combinations!(@recurse [] [] [$( ($feat, $ty) )*] $callback);
79-
};
80-
81-
// Recursive case: process each database
82-
(@recurse [$($yes:tt)*] [$($no:tt)*] [($feat:literal, $ty:ident) $($rest:tt)*] $callback:ident) => {
83-
// Include this database
84-
for_all_feature_combinations!(@recurse
85-
[$($yes)* ($feat, $ty)]
86-
[$($no)*]
87-
[$($rest)*]
88-
$callback
89-
);
90-
91-
// Exclude this database
92-
for_all_feature_combinations!(@recurse
93-
[$($yes)*]
94-
[$($no)* $feat]
95-
[$($rest)*]
96-
$callback
97-
);
98-
};
99-
100-
// Base case: no more databases, generate the implementation if we have at least one
101-
(@recurse [$(($feat:literal, $ty:ident))+] [$($no:literal)*] [] $callback:ident) => {
102-
#[cfg(all($(feature = $feat),+ $(, not(feature = $no))*))]
103-
$callback! { $($ty),+ }
104-
};
105-
106-
// Base case: no databases selected, skip
107-
(@recurse [] [$($no:literal)*] [] $callback:ident) => {
108-
// Don't generate anything for zero databases
109-
};
110-
}
111-
11263
// Callback macro that generates the actual trait and impl
11364
macro_rules! impl_any_encode_for_databases {
11465
($($db:ident),+) => {
@@ -122,4 +73,13 @@ macro_rules! impl_any_encode_for_databases {
12273
}
12374

12475
// Generate all combinations
125-
for_all_feature_combinations!(impl_any_encode_for_databases);
76+
for_all_feature_combinations! {
77+
entries: [
78+
("postgres", Postgres),
79+
("mysql", MySql),
80+
("mssql", Mssql),
81+
("sqlite", Sqlite),
82+
("odbc", Odbc),
83+
],
84+
callback: impl_any_encode_for_databases
85+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Shared recursive macro to generate all non-empty combinations of feature flags.
2+
// Pass a list of entries with a feature name and an arbitrary payload which is
3+
// forwarded to the callback when that feature is selected.
4+
//
5+
// Usage:
6+
// for_all_feature_combinations!{
7+
// entries: [("postgres", Postgres), ("mysql", MySql)],
8+
// callback: my_callback
9+
// }
10+
// will expand to (for the active feature configuration):
11+
// #[cfg(all(feature="postgres"), not(feature="mysql"))] my_callback!(Postgres);
12+
// #[cfg(all(feature="mysql"), not(feature="postgres"))] my_callback!(MySql);
13+
// #[cfg(all(feature="postgres", feature="mysql"))] my_callback!(Postgres, MySql);
14+
// and so on for all non-empty subsets.
15+
#[macro_export]
16+
macro_rules! for_all_feature_combinations {
17+
( entries: [ $( ( $feat:literal, $payload:tt ) ),* $(,)? ], callback: $callback:ident ) => {
18+
$crate::for_all_feature_combinations!(@recurse [] [] [ $( ( $feat, $payload ) )* ] $callback);
19+
};
20+
21+
(@recurse [$($yes:tt)*] [$($no:tt)*] [ ( $feat:literal, $payload:tt ) $($rest:tt)* ] $callback:ident ) => {
22+
$crate::for_all_feature_combinations!(@recurse [ $($yes)* ( $feat, $payload ) ] [ $($no)* ] [ $($rest)* ] $callback);
23+
$crate::for_all_feature_combinations!(@recurse [ $($yes)* ] [ $($no)* $feat ] [ $($rest)* ] $callback);
24+
};
25+
26+
// Base case: at least one selected
27+
(@recurse [ $( ( $yfeat:literal, $ypayload:tt ) )+ ] [ $( $nfeat:literal )* ] [] $callback:ident ) => {
28+
#[cfg(all( $( feature = $yfeat ),+ $(, not(feature = $nfeat ))* ))]
29+
$callback!( $( $ypayload ),+ );
30+
};
31+
32+
// Base case: none selected (skip)
33+
(@recurse [] [ $( $nfeat:literal )* ] [] $callback:ident ) => {};
34+
}
35+
36+

sqlx-core/src/any/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
33
use crate::executor::Executor;
44

5+
#[macro_use]
6+
mod feature_combinations;
7+
58
#[macro_use]
69
mod decode;
710

0 commit comments

Comments
 (0)