- Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Bug Description
I have this function in my code:
pub async fn fetch_post(&self, id: Option<usize>) -> Option<Post> { let query = match id { Some(id) => sqlx::query("SELECT id, title, date, text FROM posts WHERE id = ?") .bind(id as u64), None => sqlx::query("SELECT id, title, date, text FROM posts ORDER BY id DESC"), }; query.fetch_one(&self.pool) // self.pool: sqlx::Pool<sqlx::MySql> .await .map(|row| match Post::from_row(&row) { Ok(post) => post, Err(err) => panic!("Failed to parse post: {:?} ({:?})", err, row), }) .ok() }Where Post is:
#[derive(sqlx::FromRow)] pub struct Post { id: u32, title: String, date: PrimitiveDateTime, text: String, }And the schema of the posts table in my database is (there are several records in this table):
+-------+--------------+------+-----+-------------------+-------------------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+-------------------+-------------------+ | id | int unsigned | NO | PRI | NULL | | | title | varchar(128) | YES | | NULL | | | date | datetime | YES | | CURRENT_TIMESTAMP | DEFAULT_GENERATED | | text | text | YES | | NULL | | +-------+--------------+------+-----+-------------------+-------------------+ This is the bug: In my scenario, only the second query (None => sqlx::query("...) usually gets called. At some point, calling that query will start returning an sqlx::Error::ColumnNotFound error is returned instead (notice column_names is empty):
thread 'actix-server worker 0' panicked at 'Failed to parse post: ColumnNotFound("id") (MySqlRow { ..., columns: [MySqlColumn { ordinal: 0, name: id, type_info: ..., flags: ... }, MySqlColumn { ordinal: 1, name: title, type_info: ..., flags: ... }, MySqlColumn { ordinal: 2, name: date, type_info: ..., flags: ... }, MySqlColumn { ordinal: 3, name: text, type_info: ..., flags: ... }],, column_names: {} })' Because column_names is empty, and indexing into a row relies on the existence of columns in column_names...
// sqlx-core/src/mysql/row.rs impl ColumnIndex<MySqlRow> for &'_ str { fn index(&self, row: &MySqlRow) -> Result<usize, Error> { row.column_names // <-- always empty .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) .map(|v| *v) } }...Error::ColumnNotFound will keep on being returned. I'd imagine SQLx determines the columns involved in a SELECT query from the output of the database, so it seems like column_names being empty is a bug.
Minimal Reproduction
I know it's incredibly frustrating that I don't have any clear way to reproduce this, since it's such a niche issue...
Info
- SQLx version: 0.6.2
- SQLx features enabled:
["runtime-tokio-rustls", "mysql", "uuid", "time"] - Database server and version: MySQL 8.0.26
- Operating system: Linux
rustc --version:rustc 1.65.0 (897e37553 2022-11-02)