Xander
Xander

Reputation: 69

SQL insert slice of interface

I'm writing a function that add one row to an SQLite database.

func ManageDB(db *sqlx.DB, query string, args ...interface{}) (int64, error) {

stmt, err := db.Prepare(query)
    if err != nil {
        return -1, err
    }
    defer stmt.Close()

    tx, err := db.Begin()
    if err != nil {
        return -1, err
    }
    _, err = tx.Stmt(stmt).Exec(args...)
    if err != nil {
        log.Errorf("error inserting row '%s' %v", query, err)
        log.Debugln("Doing rollback on Insert")
        tx.Rollback()
    } else {
        tx.Commit()
    }

  return res.LastInsertId()
}

and I call it with with that


b := "INSERT INTO MYTABLE (name1, name2, name3, name4) VALUES($1, $2, $3, $4)"

c := []interface{}{
      "string1",
      "string2",
      0,          // int64
      "string4", //string4 
    }

idt, err := models.ManageDB(
      db,  //db initialized 
      b,
      c,
    ) 

.......

When I test that function it works like it should, and add items without problem.

When I run it on the main code, it reports this error:

sql: converting argument $1 type: unsupported type []interface {}, a slice of interface

I don't understand what is wrong.

Upvotes: 1

Views: 1377

Answers (1)

nkcmr
nkcmr

Reputation: 11010

In the second snippet, you are not spreading c over the arguments, you are simply passing c. Therefore in ManageDB, args is equal to:

[]interface{}{
    []interface{}{
        "string1",
        "string2",
        0,
        "string4",
    }
}

And so sqlx thinks you want $1 to be that whole array.

Fix would be to call ManageDB like so:

models.ManageDB(db, b, c...) 

Upvotes: 2

Related Questions