-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support multiple databases in the same crate (compile-time macros) #916
Comments
From a UX perspective, 3 is the friendliest to IDEs because it can be done with |
Option 4sqlx::database!(name = "foo", url = "env:FOO_DATABASE_URL");
// [...]
let rows = foo::query!("SELECT * FROM bar WHERE x = ?val", val = 10)
.fetch_all(&mut conn)?; To keep it 1-line (if that's important), we could inline the module creation within "Option 3". |
I would think What about sqlx::database!(mod foo, name = "bar_test_db") which declares a module |
I like the idea of I don't like I'd probably prefer the 3-line # .env
DATABASE_URL="postgres://postgres@localhost/foo"
OTHER_DATABASE_URL="postgres://postgres@other/foo" mod bar { sqlx::database!(name = "bar"); } // url is "postgres://postgres@localhost/bar"
mod other_foo { sqlx::database!(url = "env:OTHER_DATABASE_URL"); } // url is "postgres://postgres@other/foo" |
What about sqlx::database!(mod = "foo", db = "bar") |
What else is it going to produce besides a sqlx::database!(foo, url = "env:FOO_DATABASE_URL"); Although if the user wants to put additional items in that module or adjust the visibility, the above macro could delegate to another one with both exposed: mod foo { sqlx::database_impl!(url = "env:FOO_DATABASE_URL"); } |
That's a really good reason for me to not generate the rust module at all. I hadn't considered visibility. |
Yeah, that could get messy. |
@mehcode I just realized we were already talking about doing this a long time ago, potentially with allowing other configuration to the macros such as specifying type overrides #121 We also have talked about a |
In talking about it, @mehcode and I settled on |
Unfortunately, the whole idea with using Even in the 2018 edition you still can't invoke a macro in the same crate via its fully-qualified path; you have to use There's still some utility with We could make it work like this, though: sqlx::macros!(
db_url[foo] = "env::DATABASE_FOO",
db_url[bar] = "env::DATABASE_BAR",
types[bar] = {
"BAZ": crate::model::Baz,
},
// top-level option which applies to both `foo` and `bar`:
types = {
"CITEXT": String,
}
);
// this matches how arguments are passed to the macros internally but can be changed
query!(db = foo, "select * from ...") I'm thinking any configuration options we plan to add, we can have them optionally accept a database name as subscript, and then they only apply to that database. Otherwise, they apply to all databases. It could also look like this, maybe (again, with top-level options applying to all databases): sqlx::macros! (
db.foo = {
url: "env::DATABASE_FOO",
},
db.bar = {
url: "env::DATABASE_BAR",
types: {
"BAZ": crate::model::Baz,
}
},
types = {
"CITEXT": String,
}
); Or combine both and make the subscript |
However, I'm also recalling some issues with macros-defining-macros where you want to use parameters from the outer macro invocation in the inner macro... things get weird. Maybe it's time to dust off the |
Actually there is some movement towards integrating Wanted to link to that earlier but apparently it's virtually impossible to find with regular search engines, I only found it again now because I got a notification about a new comment. |
It's been put to an RFC now so it's still going to take a while to get merged and then stabilized, but it's nice to see that it's possible. It sounds like they want to make it part of the 2021 Edition though. As for this:
Apparently it just works now so I'm not sure what funkiness I was remembering: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4de9983692e5894f174caf52b6c49191 |
I think to reduce the syntax surface area I would be much more in favor of: // all do the same, just bikeshedding
sqlx::macros!(foo, url = "env:DATABASE_URL");
sqlx::macros!(name: foo, url = "env:DATABASE_URL");
sqlx::macros!(prefix: foo, url = "env:DATABASE_URL");
sqlx::macros!(prefix = foo, url = "env:DATABASE_URL"); and used as: foo_query!("SELECT ...");
foo_query_as!(Bar, "SELECT ..."); Yes this requires the macros to be in |
Hello I'm facing the issue where I've multiple DB connections in the same crate. I would like to work on a solution, can we fixe one of the propose option as a base to iterate? |
Sadly the |
While this may not be a proper solution, it's a workaround that works in my case (as I have no duplicate table names, and my database schemas are not updated often), so maybe it will be of use to someone else. Essentially I created a new database (C) that contains the schema of tables in databases A and B. The connection string to database C is then set in the It's then up to me to make sure that the correct database worker pool (i.e. database A or B) is used when calling |
I'm having this issue as well. wondering if there's any progress |
I'm working with multiple databases at the same time in a codebase, and this is a real issue- it's so unfortunate to have to give up 90% of what makes SQLx great to use (compile time queries) due to this. Is this something you're looking for community help on? |
|
The current plan is to use the There will be a new proc-macro to define a new set of sqlx::macros_with_config!("sqlx.foo.toml"); This will look for Under the hood, this will just pass the file path to Additionally, it can support some control arguments: sqlx::macros_with_config!(
"sqlx.foo.toml",
// Add a prefix to the macro names
prefix = "foo_" // (`foo_query!()`, `foo_migrate!()`, etc.)
// Add attributes to the generated macros
attr(macro_export), // (`#[macro_export]`)
attr(cfg(feature = "foo")) // (`#[cfg(feature = "foo")]`),'
// Any others we might want?
); |
@abonander very excited about seeing some activity here. We were about to fork and see if we could get this working, obviously hoping to contribute back once we did -- great timing. I was headed down the sqlx.toml path as well as I was documenting our plan -- that seemed to be the most straight forward and rust-analyzer friendly path. Any help / insight myself or our team can provide to get this across the line, let us know! |
Option 1
Inspired from the
log
crate andlog!(target: _)
.Option 2
Option 3
That's all I can think of at the moment. I prefer Option 2.
This is a solution to #121 and #224.
Thoughts?
The text was updated successfully, but these errors were encountered: