너를 속였다
너를 속였다

Reputation: 1079

extract macro argument inside string

I have following macro :-

macro_rules! update_user {
    ($tx:ident, $id:expr, $key:expr, $val:expr) => {
        sqlx::query!(
            "UPDATE users SET
            $key = ?
            WHERE id = $id
            "
            , $val
        ).execute(&mut $tx).await?;

    };
}

How can I make this macro use value of $id and $key inside string ? I can't use format! as query! expects only string literal

EDIT; concat! macro is not working


macro_rules! update  {
    ($tx:ident, $col:tt, $val:expr, $id:expr) => {
        if let Some(some) = $val {
            sqlx::query!(
                concat!(
                "UPDATE users SET",
                $col ," = ?  ",
                "where id = ? "
                ),
                some, $id
            ).execute(&mut $tx).await?;
        }
    };
}

pub(crate) async fn update_user<'a> (
    db : &MySqlPool,
    user : User<'a>,
) -> RouteResult<()> {

    let mut tx = db.begin().await?;

    update!(tx, "uname", user.uname, user.id);

    if let Some(uname) = user.uname {
        sqlx::query!(
            "UPDATE users SET
            uname = ? 
            where id = ? 
            ",
            uname, user.id
        ).execute(&mut tx).await?;
    }

    tx.commit().await?;

    Ok(())
}

This gives expected string literal error.

Upvotes: 2

Views: 525

Answers (2)

너를 속였다
너를 속였다

Reputation: 1079

Got answer on sqlx's discord forum. I had to use + instead of concat!. I'm accepting Mihir's answer as it answers the title but I had to use following

macro_rules! update {
    ($tx:ident, $table:tt, $col:tt, $val:expr, $id:expr) => {
        if let Some(some) = $val {
            sqlx::query!(
                "UPDATE "
                    + $table
                    + " SET "
                    + $col
                    + " = ?  
                where id = ? ",
                some,
                $id
            )
            .execute(&mut $tx)
            .await?;
        }
    };
}
...
//use it like this
update!(tx, "users", "uname", user.uname, user.id);

Upvotes: 1

Mihir Luthra
Mihir Luthra

Reputation: 6779

You probably need concat!() for this. It would concatenate literals to yield a &'static str:

macro_rules! update_user {
    ($tx:ident, $id:expr, $key:expr, $val:expr) => {
        sqlx::query!(
            concat!("UPDATE users SET $key = ", $key, " WHERE id = ", $id),
            $val
        ).execute(&mut $tx).await?;

    };
}

A similar example: Playground

Upvotes: 1

Related Questions