Open miaomiao1992 opened 1 year ago
Yeah, this is an unfortunate limitation that needs to be fixed.
Part of the question is, how to resolve which databases to codegen for if you have multiple features enabled.
Some options might be:
any
database.#[ormlite(database = "postgres")]
for any #[derive(Model)]
struct.Thoughts?
Considering that I don't know how's statistically relevant in terms of use case, I'd opt for the option 3. It's a bit more verbose, but it's also clear and explicit, so that developers don't get confused about which model belongs to which db, and codegen doesn't need to produce unneeded pieces (like the option 2).
Wouldn't option 3 make it less flexible? My use-case for having support or multiple databases is so the administrator could choose. It wouldn't be able to do this flexibly at runtime anymore if we use annotations, since we then need to have duplicate models for every database supported.
My use-case for having support or multiple databases is so the administrator could choose. It wouldn't be able to do this flexibly at runtime anymore if we use annotations
Maybe I misunderstood your words, or I've read them too literally, but "switching db at runtime from an admin action" is something out of scope for an ORM library.
If, instead, you were referring to the ability to switch the database through some kind of configuration (and then restarting the app) maybe option 2 is more appropriate for the goal. But this solution might be a problem if/when your use-case is to have different models on different dbs (which I know it might be a very narrow/rare use case).
I really don't have idea about how much it is possible/reasonable, but perhaps a combination of 1, 2 and 3 would work well: you either choose a specific db
or any
annotation on model, then codegen accordingly.
Just my 2 cents
If, instead, you were referring to the ability to switch the database through some kind of configuration (and then restarting the app) maybe option 2 is more appropriate for the goal. But this solution might be a problem if/when your use-case is to have different models on different dbs (which I know it might be a very narrow/rare use case).
This was more what I was thinking yes. Meant runtime as in it checks and chooses backend when i starts up as part of initialization.
A combination as you described might be good.
It's not done, but the commit above starts to build support for this.
Since the database gets parameterized in a generic, there will be support for backing the same model with multiple databases.
That would enable the use case of switching backends at runtime, but I agree that making that seamless is beyond the scope of an ORM.
Finishing this is mostly about fixing compile issues at this point, so I'd welcome PRs if anyone wants to get it over the finish line.
The syntax that I think makes the most sense is something like the following:
# cargo build --features sqlite,postgres
#[ormlite(database="sqlite")
pub struct BuiltForSqlite {}
// without the annotation, this will fail to compile.
pub struct NoAnnotation {}
// two annotations also works
#[ormlite(database="sqlite")
#[ormlite(database="postgres")
pub struct TwoAnnotations {}
Additionally, there would be features, default-<db>
to avoid defaults for most structs
# cargo build --features sqlite,default-postgres
// the annotation overrides the default, so this is built only for sqlite
#[ormlite(database="sqlite")
pub struct BuiltForSqlite {}
// because of default-postgres feature, this now compiles with postgres.
pub struct NoAnnotation {}
// two annotations works as before
#[ormlite(database="sqlite")
#[ormlite(database="postgres")
pub struct TwoAnnotations {}
Let me know any feedback!
[cfg(feature = "mysql")]
compile_error!("mysql is currently not supported");
[cfg(feature = "postgres")]
pub type DB = postgres::PostgresBackend;
[cfg(feature = "sqlite")]
pub type DB = sqlite::SqliteBackend;