Skip to content

with sqlite query_as considers TEXT NOT NULL as nullable when there is an ORDER BY clause #4147

@Don42

Description

@Don42

I have found these related issues/pull requests

Description

I tried migrating a small CLI application from rusqlite to sqlx to take advantage of the migration feature.
After that worked I tried to switch to the query macros for build time checks, but I ran into an issue that I reproduced with the following minimal example. The error disappears when I comment out the ORDER BY line in the statement. I know the workaround is to override nullability, but it does seem like a bug.

cargo build reports:

error[E0277]: the trait bound `std::string::String: From<Option<std::string::String>>` is not satisfied
  --> src/main.rs:17:17
   |
17 |       let items = sqlx::query_as!(
   |  _________________^
18 | |         Bar,
19 | |         "SELECT
20 | |                 foo
...  |
24 | |                       LIMIT 10000;",
25 | |     )
   | |_____^ the trait `From<Option<std::string::String>>` is not implemented for `std::string::String`
   |
   = help: the following other types implement trait `From<T>`:
             `std::string::String` implements `From<&mut str>`
             `std::string::String` implements `From<&std::string::String>`
             `std::string::String` implements `From<&str>`
             `std::string::String` implements `From<Box<str>>`
             `std::string::String` implements `From<Cow<'_, str>>`
             `std::string::String` implements `From<char>`
             `std::string::String` implements `From<url::Url>`
   = note: required for `Option<std::string::String>` to implement `Into<std::string::String>`
   = note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)
  • sqlx = { version = "0.8.6", features = ["sqlite", "runtime-async-std", "macros"] }
    • The issue also occurs with the runtime-tokio feature
    • The issue also occurs with the sqlite-unbundled instead of sqlite
  • sqlx-cli v0.8.6
CREATE TABLE bar (
	id integer PRIMARY KEY,
	time INTEGER NOT NULL DEFAULT (unixepoch()),
	foo TEXT NOT NULL
);
use sqlx::ConnectOptions;
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode};
use std::str::FromStr;

async fn query() {
    #[derive(Debug)]
    struct Bar {
        foo: String,
    }

    let opts = SqliteConnectOptions::from_str("sqlite://history.db")
        .unwrap()
        .journal_mode(SqliteJournalMode::Wal)
        .create_if_missing(true);
    let mut con = opts.connect().await.unwrap();
    let items = sqlx::query_as!(
        Bar,
        "SELECT 
                foo
          FROM bar
          GROUP BY foo
          ORDER BY max(time) desc
          ;",
    )
    .fetch_all(&mut con)
    .await
    .unwrap();
    println!("{:?}", items)
}

fn main() {
    smol::block_on(query())
}
``

### Reproduction steps

1. Create sqlite database with the table described above
2. Set `DATABASE_URL` accordingly
3. Run `cargo build`

### SQLx version

0.8.6

### Enabled SQLx features

sqlite, runtime-async-std, macros

### Database server and version

Sqlite

### Operating system

Linux/Debian

### Rust version

rustc 1.91.1 (ed61e7d7e 2025-11-07)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions