launchbadge / sqlx

🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.
Apache License 2.0
12.36k stars 1.18k forks source link

[MariaDB] Can't parse MySqlRow to struct with `RETURNING *` feature #3318

Closed joao-conde closed 2 days ago

joao-conde commented 4 days ago

Bug Description

The following code works for an Sqlite connection:

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 same code should work for a MariaDB database:

pub async fn create_todo(pool: &MySqlPool, todo: CreateTodo) -> Result<Todo, InternalError> {
    ...
}

However, it doesn't and fails with the error: ColumnNotFound("id")

The same happens if one manually specifies the column names like so:

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 id, title, description",
        todo.title,
        todo.description
    )
    .fetch_one(pool)
    .await?;
    Ok(todo)
}

A quick debug print reveals something interesting:

[src\db\user.rs:49:5] &row = MySqlRow {
    row: Row {
        storage: b"\0\x01\0\0\0\0\0\0\0\x08username\x0femail@email.com",
        values: [
            Some(
                1..9,
            ),
            Some(
                10..18,
            ),
            Some(
                19..34,
            ),
        ],
    },
    format: Binary,
    columns: [
        MySqlColumn {
            ordinal: 0,
            name: id,
            type_info: MySqlTypeInfo {
                type: LongLong,
                flags: ColumnFlags(
                    NOT_NULL | PRIMARY_KEY | UNIQUE_KEY | UNSIGNED | AUTO_INCREMENT,
                ),
                char_set: 63,
                max_size: Some(
                    20,
                ),
            },
            flags: Some(
                ColumnFlags(
                    NOT_NULL | PRIMARY_KEY | UNIQUE_KEY | UNSIGNED | AUTO_INCREMENT,
                ),
            ),
        },
        MySqlColumn {
            ordinal: 1,
            name: title,
            type_info: MySqlTypeInfo {
                type: VarString,
                flags: ColumnFlags(
                    NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE,
                ),
                char_set: 224,
                max_size: Some(
                    256,
                ),
            },
            flags: Some(
                ColumnFlags(
                    NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE,
                ),
            ),
        },
        MySqlColumn {
            ordinal: 2,
            name: description,
            type_info: MySqlTypeInfo {
                type: VarString,
                flags: ColumnFlags(
                    UNIQUE_KEY,
                ),
                char_set: 224,
                max_size: Some(
                test db::user::tests::get_user ...     ok1280
,
                ),
            },
            flags: Some(
                ColumnFlags(
                    UNIQUE_KEY,
                ),
            ),
        },
    ],
    column_names: {},
}

There seems to be all the column data there, but the field column_names is empty. That would raise the error we are observing here: https://github.com/launchbadge/sqlx/blob/main/sqlx-mysql/src/row.rs#L46

So I suspect its simply not parsing the column names field properly when using RETURNING with mariadb.

Minimal Reproduction

See snippets above.

Info

joao-conde commented 4 days ago

@abonander hope it has enough info, hopefully something to solve trivial when getting the column names data from the query result.

abonander commented 4 days ago

I actually just remembered that this is likely due to a bug in MariaDB: https://github.com/launchbadge/sqlx/issues/1530

joao-conde commented 4 days ago

Thanks for linking. Seems original issue is big dated, but the JIRA ticket for MariaDB had no updates yet. So I think I'll just have to live with it.