sqlx can't build in workspace?
Firstly, a fresh git clone of sqlx will not compile if you try to build examples/sqlite/todos because of a missing tls feature flag? This shouldn't be needed for sqlite I would've thought, but the main issue:
After following the instructions for exporting the DATABASE_URL and running requisite sqlx commands the example will still not build with the following error:
error: error returned from database: unable to open database file
--> examples/sqlite/todos/src/main.rs:80:16
|
80 | let recs = sqlx::query!(
| ________________^
81 | | r#"
82 | | SELECT id, description, done
83 | | FROM todos
84 | | ORDER BY id
85 | | "#
86 | | )
Note that cargo build will fail both from the workspace root and from the sub-crate dir. I assume this worked at some point because otherwise the example would have never compiled?
moving todos.db and migrations to the workspace root and the example will build again.
I then attempted to use offline mode by adding the "offline" feature flag and running cargo sqlx prepare, the generated json file also needs to be moved into the root or else unable to open database file will be returned also, so compiling the sub-crate in offline mode does not work either afaict.
I have a small workspace project that can show this issue as a repro if you want, but it should be easily reproducible from the main sqlx repo
migrate! & migrations does not appear to work anywhere outside the workspace root either (when compiling the workspace) from docs:
The directory must be relative to the **project root** (the directory containing Cargo.toml), unlike include_str!() which uses compiler internals to get the path of the file where it was invoked.
I was trying to have the migrations placed in a sub-crate of a workspace. I get the following error:
error: paths relative to the current file's directory are not currently supported
--> bin/sqlx_test/src/main.rs:21:20
|
21 | sqlx::migrate!("migrations").run(&pool).await?;
However, if I move migrations to the workspace root and change the path to migrate!("../../migrations"), it will compile. This is the opposite of the behaviour the error message says, I think, as the working path is relative to where migrate! is called from. It also stands in contrast with where the path starts for DATABASE_URL which seems to begin at the workspace root.
hi, in order to just execute /examples/sqlite/todos do:
export DATABASE_URL="sqlite:/YOUR ABSOLUTE PATH/sqlx/examples/sqlite/todos/todos.db" sqlx db create sqlx migrate run
previously to cargo run
hope this help, regards.
Okay, perhaps the README needs to be updated? I will close this ticket.
@leshow: I think, this issue shouldn't have been closed. Relative paths are clearly broken at the moment. If relative paths are not supported, then that needs be mentioned in the documentation (and closing the issues makes it less likely that this will happen).
The problem doesn't only happen with macros.
Edit: Actually, I made a mistake. I couldn't find a description of the database URL-format within the documentation of sqlx, so I did some research on Google. Several search results said that relative paths start with three slashes at the beginning (e.g. this snippet).
Today I stumbled upon this page, which made me realize, that this is incorrect, and how to properly define a relative path.
The remainder of this comment after this section is therefore irrelevant/wrong.
Because I requested to re-open this issue, I checked if I could run the SQLite example successfully. However, I get the same error as described above. So there still seems to be a problem with relative paths and the macros.
I'm using the following code to connect to an SQLite database:
dotenv().expect("Failed to init dotenv");
let db_path = std::env::var("DATABASE_URL").expect("No DATABASE_URL env var");
dbg!(&db_path);
let db = SqlitePoolOptions::new()
.max_connections(5)
.connect(&db_path)
.await
.expect("Failed to connect to database")
Which fails, although no macros are involved.
The error message that is returned, is Database(SqliteError { code: 14, message: "unable to open database file" }), which is a bit frustrating to debug, to be honest.
Everything works as expected, when I switch from:
DATABASE_URL=sqlite:///data/db.sqlit
to:
DATABASE_URL=sqlite:///${CARGO_MANIFEST_DIR}/data/db.sqlite.
Alright, if I'm not the only one running into this then I'll re-open.
Thanks, @leshow.
There is also https://github.com/launchbadge/sqlx/issues/1260.
It turned out that my own problem described above was the result of an error on my side (see my edit above). The problem with relative paths therefore seems to really be only related to the macros.
@d4h0 I'm not sure I follow, I think there is still an issue though, have a look at this project structure:
.
├── bin
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── Cargo.lock
├── Cargo.toml
├── .env
├── projectname
│ ├── Cargo.toml
│ └── src
│ ├── libs.rs
├── libs
│ └── storage
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ ├── lib.rs
│ └── sqlite.rs
├── migrations
│ └── 20210824204854_initial.sql
The .env file is in workspace root and contains:
DATABASE_URL="sqlite:em.db"
main.rs uses dotenv:
fn main() -> Result<()> {
dotenv::dotenv()?
...
With this setup, cargo build works just fine, but cargo test will fail because sqlx::query! is used in libs/storage/src/sqlite.rs:
error: error returned from database: unable to open database file
--> /home/leshow/dev/projectname/libs/storage/src/sqlite.rs:277:19
|
277 | let cur = sqlx::query!(
| ___________________^
It seems the macro cannot find the location of the database. Now, if I change DATABASE_URL to sqlite:../../em.db, cargo test will pass, but now cargo build will fail with the same error. The macros definitely don't work inside a workspace, AFAICT. Did you find a solution to this?
edit: FYI, using DATABASE_URL="sqlite:///${CARGO_MANIFEST_DIR}/em.db" build and test both fail, I have tried with / /// or //, it seems to make no difference
@leshow: Sure, there is still the problem you reported above. The meaning of my last comment was, that the problem that I've described (which doesn't involve macros), was the result of me using an incorrect database URL (see my edit here).
When I actually started to use sqlx via the macros (and a correct database URL), I experienced the problem you reported as well (of course).
Today I finished implementing a fix for the issue, however.
I'll probably submit a PR in the next few days (I'd like to use my fork for a few days, first).
It seems the macro cannot find the location of the database.
The problem is, that the macro code doesn't run in the same working directory as your regular code (in a workspace, the workspace root directory is the working directory of the macros. Therefore, relative paths don't work).
DATABASE_URL="sqlite:///${CARGO_MANIFEST_DIR}/em.db"
According to this page, three slashes would be correct (but I believe any amount above two slashes should work).
So that would be:
DATABASE_URL="sqlite://${CARGO_MANIFEST_DIR}/em.db"
(CARGO_MANIFEST_DIR starts with a slash)
This works if you use cargo run (or whatever) from the 'projectname' directory and 'em.db' is in 'projectname/em.db'.
CARGO_MANIFEST_DIR refers to an crate directory (e.g. 'projectname' or 'bin'), not the workspace directory.
For posterity, CARGO_MANIFEST_DIR seems to not refer to the workspace root when doing either build or test in my workspace (maybe just one of those, I can't remember), for me it was printing out one of the sub-crate directories when that particular crate was compiled. I was able to get around this by using the current working directory (as in sqlite://${PWD}/em.db), so the variable is populated independent of cargo. This feels a little brittle though as if you go into one of the sub-crate dirs, the path will be wrong. Maybe there is a better way to refer to the workspace root?
In any case, with the absolute path, all the targets are able to complete. Thanks for taking the time to write back!
Superceded by #3099