mattn/go-sqlite3

Binding Values to Prepared Statement Returns "row value misused"

source-transformer opened this issue · 4 comments

If I bind more than one value to a prepared statement - I get "row value misused".

This works:

"SELECT * FROM `table1` WHERE `table1`.`column1` = ?"

The following doesn't work:

"SELECT * FROM `table1` WHERE `table1`.`column1` = ? AND `table1`.`column2` = ?"

It doesn't work in the sense that I get the following error returned:
"row value misused"

same result if you remove the backticks.

I cloned this repository and found this bit of code (but that's as far as I've looked into this):

SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
  if( ExprUseXSelect(pExpr) ){
    sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
  }else
#endif
  {
    sqlite3ErrorMsg(pParse, "row value misused");

If I just manually inject the values into the SQL statement it works without issue.

I'm using go-sqlite3 thru GORM - my code looks like this:

func runQuery(ctx context.Context, query *models.FooRecord, values ...interface{}) (string, error) {

	db := s.GetDB(ctx)
	var fooRecords []*models.FooRecord
	stmt := db.Session(&gorm.Session{DryRun: true}).Model(&models.FooRecord{}).Where(query).Find(&fooRecords).Statement
	stmtStr := stmt.SQL.String()

	var results map[string]interface{}
	rawRes := db.Raw(stmtStr, values)
	if rawRes.Error != nil {
		return "", errors.New("runQuery: explain query failed: " + rawRes.Error.Error())
	}
	res := rawRes.Scan(&results)
	if res.Error != nil {
		return "", errors.New("runQuery: explain query failed: " + res.Error.Error())
	}
	// SNIPPED rest of code - but at this point you can just return nil, nil
	return nil, nil
}

Not sure if it is useful - but here is how this is being called:

	fooQuery := &models.FooRecord{
	}

	oneID := "asdf"
	twoID := "qwer"
	result, err = runQuery(ctx, fooQuery, oneID, twoID)

@source-transformer What version of this library are you using? What are the database schema and contents? Please provide a reproducer that only uses this library (via database/sql), not gorm.

Right - sorry forgot those details.

I was originally on version
v1.14.12

then I tried upgrading to latest
v1.14.16

with same result.

The db schema is just

table1

with column1 + column2 both being primary keys (together forming composite key).

I'm walking thru the build/install instructions (https://github.com/mattn/go-sqlite3#mac-osx) now to see if I can create a unit test. Any tips/pointers on where/how to create a unit test that creates a table along with my other specifics?

Thanks!

I think I can just clone this function and alter it to my needs:

func testManyQueryRow(t *testing.T) {
	if testing.Short() {
		t.Log("skipping in short mode")
		return
	}
	db.tearDown()
	db.mustExec("create table foo (id integer primary key, name varchar(50))")
	db.mustExec(db.q("insert into foo (id, name) values(?,?)"), 1, "bob")
	var name string
	for i := 0; i < 10000; i++ {
		err := db.QueryRow(db.q("select name from foo where id = ?"), 1).Scan(&name)
		if err != nil || name != "bob" {
			t.Fatalf("on query %d: err=%v, name=%q", i, err, name)
		}
	}
}

I added a couple of tests that have reassured me that sqlite3 is not the culprit - I can create a PR with those two new tests if you'd like them.

I found the bug in gorm - somehow it is appending a second question mark to my prepared statement:

"SELECT * FROM table1 WHERE table1.column1 = (?,?) AND table1.column2 = ?"

I'm going to see if I can create a git issue for gorm.