Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go MySQL queries with SET variables

Tags:

mysql

go

I'm trying to clean up how Go is calling MySQL queries by setting some variables before running the query with a decent amount of case statements around a single value. The query I'm attempting to run works fine on the console but is failing on me with a syntax issue at the SELECT when running it through Go. Is something like this possible?

func (d *DB) SelectByUserId(uid string, srt string, pg, lim int) ([]Inventory, error) {
    query := `
    SET @user_id := ?,
        @orderBy := ?;
    SELECT
        *
    FROM
        inventory
    WHERE
        user_id = @user_id
    ORDER BY
        (CASE WHEN @orderBy = 'type,asc' THEN type END),
        (CASE WHEN @orderBy = 'type,desc' THEN type END) DESC,
        (CASE WHEN @orderBy = 'visible,asc' THEN visible END),
        (CASE WHEN @orderBy = 'visible,desc' THEN visible END) DESC,
        (CASE WHEN @orderBy = 'create_date,asc' THEN create_date END),
        (CASE WHEN @orderBy = 'create_date,desc' THEN create_date END) DESC,
        (CASE WHEN @orderBy = 'update_date,asc' THEN update_date END),
        (CASE WHEN @orderBy = 'update_date,desc' THEN update_date END) DESC
    LIMIT ?,?;
    `
    
    rows, err := d.Query(
        query,
        uid,
        srt,
        pg*lim,
        lim,
    )

    if err != nil {
        return nil, err
    }
    defer rows.Close()

    result := make([]Inventory, 0)
    for rows.Next() {
        var inv Inventory
        if err := rows.Scan(
            &inv.Id,
            &inv.UserId,
            &inv.Type,
            &inv.Name,
            &inv.Description,
            &inv.Visible,
            &inv.CreateDate,
            &inv.UpdateDate); err != nil {
            return result, err
        }
        result = append(result, inv)
    }
    if err = rows.Err(); err != nil {
        return result, err
    }

    return result, nil
}

Now, if I take out the SET pieces and replace all the @ variables with the ? and then pass the srt variable in multiple times like below this all works. But would really like to not have to have a query call such as:

rows, err := d.Query(
        query,
        uid,
        srt,
        srt,
        srt,
        srt,
        srt,
        srt,
        srt,
        srt,
        pg*lim,
        lim)

The error being reported isn't very helpful:

Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT\n    *\nFROM\n    inventory\nWHERE\n    user_id = @user_id\nORDER BY\n ' at line 3

Thanks for your help.

like image 779
djneely Avatar asked Oct 13 '25 07:10

djneely


1 Answers

For those interested I've solved my issue with a few updates.

  1. There are settings on the DSN when connecting ?...&multiStatements=true&interpolateParams=true

  2. After adding the above I started getting a new error regarding the collation (Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_general_ci,IMPLICIT) for operation '='. I went through and converted the DB and the tables to utf8mb4_general_ci and everything is working as expected.

Thank you to those that provided their solutions but this is the route we wound up taking.

like image 58
djneely Avatar answered Oct 14 '25 20:10

djneely