-
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
0.6.0: RETURNING causes value to have an extra Option
wrapped
#1923
Comments
I am pretty sure you should use fetch_one instead of fetch_optional in this use case |
I don't think so, What I'm trying to point out is the API has had a breaking change between 0.5.x -> 0.6 that I think was unintentional. edit: I should mention, I'm happy to PR to fix this if someone can point me in the right direction I believe. I have identified a test that I could add an extra Line 179 in 061fdca
|
Ok so a simple question, what should fetch_optional in your opinion return when no row was created? You want to return an i64 when no row was created? From where should fetch_optional get then the i64 from? |
I believe the return type of
It always returned Option The field on |
Ah ok, right |
And just to explain this further, even if I use sqlx/examples/postgres/todos/src/main.rs Line 45 in 061fdca
Again, I would like to PR this, just point me in the right direction. |
I can confirm having this issue with an insert statement. |
I think the problem is that sqlx now cannot infer nullability correctly. To be fair, the sqlite byte code is not considered as part of the API, and not meant to be depended on by external applications.
I also don't know if this is related to the CTE feature #1816, which made extensive change to the module parsing the sqlite byte code. For this specific issue I think you might be able to force the column to be not null. https://docs.rs/sqlx/latest/sqlx/macro.query.html#type-overrides-output-columns sqlx::query!(
r#"
UPDATE foo
....
RETURNING ip as "ip!"
"#,
)
.fetch_optional(conn)
.await?
.map(|cur| IpAddr::V4(Ipv4Addr::from(cur.ip as u32)))) |
Unfortunately I can't dig into the root cause right now. But if you want to dig deeper, this is the workflow I had settled into for most of my prior changes:
I typically end up adding temporary debug statements into where it looks like the issue is (unless it's obvious), before actually fixing anything. The actual code to fix will be somewhere within: sqlx-core/src/sqlite/connection/explain.rs Hopefully this actually helps you... |
Thanks @tyrelr . Ive got some time tomorrow, will see if I can make progress on this. edit: I haven't been having much luck getting the |
Did |
Yep, I just double checked that after todays rebase to get a fix for an unrelated CI failure. Thanks for the good reproduction steps. Those make life so much easier. |
I can confirm this has been fixed in 0.7-dev |
It appears to still be broken in some cases on 0.7.0 @serzhshakur I have a reproduce case, I think it has something to do with the
produces:
If I change |
@tyrelr pinging you in case you haven't seen this. I have the reproduce case above, I've been trying to create a test that fails but I can't seem to satisfy the DATABASE_URL for the sqlite tests edit: I think I got the tests to run properly and a test case that fails when it should pass. Ran tests with:
test case:
here column 0 is |
That test looks good, but it might be quite a while before I get spare time to poke at it. If you want a quick fix, you probably will want to use the type alias override functionality to work around the bug. Any behavioural change in the analyzer is considered a breaking change, so wouldn't be included in a bugfix release. If you want to try poking the bug itself, run the test with environment variable RUST_LOG=trace to get a listing of all the execution paths from. Warning/Apology in advance... the logs are not easy to read. But the idea is basically to search through to find find an execution path which resulted in null, then reason through where sqlx logic handled something wrong. It's often due to some command or control flow having implicit/explicit null handling which isn't recognized/implemented by the logic in sqlx-sqlite/src/connection/explain.rs. |
Thanks, I appreciate the tips, I will post here if I have any luck next week. |
Any updates on this? #[derive(Deserialize, Serialize, FromRow)]
pub struct Todo {
pub id: i64,
pub title: String,
pub description: String,
}
pub async fn create_todo(pool: &SqlitePool, todo: CreateTodo) -> Result<Todo, InternalError> {
let todo = sqlx::query_as!(
Todo,
"INSERT INTO todos (title, description) VALUES (?, ?) RETURNING *",
todo.title,
todo.description
)
.fetch_one(pool)
.await?;
Ok(todo)
} This works too: pub async fn update_todo(
pool: &SqlitePool,
id: i64,
todo: CreateTodo,
) -> Result<(), InternalError> {
sqlx::query_as!(
Todo,
"UPDATE todos SET title = ?, description = ? WHERE id = ?",
todo.title,
todo.description,
id,
)
.fetch_one(pool)
.await?;
Ok(())
} But this fails: pub async fn update_todo(
pool: &SqlitePool,
id: i64,
todo: CreateTodo,
) -> Result<Todo, InternalError> {
let todo = sqlx::query_as!(
Todo,
// notice the difference is the RETURNING clause
"UPDATE todos SET title = ?, description = ? WHERE id = ? RETURNING *",
todo.title,
todo.description,
id,
)
.fetch_one(pool)
.await?;
Ok(todo)
} with:
using TOML:
and lock:
|
I have the same issue as @joao-conde |
I have defined a
NOT NULL
column:After the update to 0.6.0, wherever regular SELECT queries happen the type is correctly not optional:
However, if I use
RETURNING
the type has an extraOption
wrap and fails to compile now:edit: using sqlite backend
The text was updated successfully, but these errors were encountered: