Skip to content

Commit

Permalink
fixed replacing bug on WHERE IN statement (fixes #778)
Browse files Browse the repository at this point in the history
  • Loading branch information
sio4 committed Sep 24, 2022
1 parent 3f5bb8a commit 30ded0f
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 30 deletions.
2 changes: 1 addition & 1 deletion query.go
Expand Up @@ -145,7 +145,7 @@ func (q *Query) Where(stmt string, args ...interface{}) *Query {
inq = append(inq, "?")
}
qs := fmt.Sprintf("(%s)", strings.Join(inq, ","))
stmt = strings.Replace(stmt, "(?)", qs, 1)
stmt = inRegex.ReplaceAllString(stmt, " IN "+qs)
}
q.whereClauses = append(q.whereClauses, clause{stmt, args})
return q
Expand Down
123 changes: 94 additions & 29 deletions query_test.go
Expand Up @@ -17,20 +17,28 @@ func Test_Where(t *testing.T) {
m := NewModel(new(Enemy), context.Background())

q := PDB.Where("id = ?", 1)
sql, _ := q.ToSQL(m)
sql, args := q.ToSQL(m)
a.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE id = ?"), sql)
a.Equal([]interface{}{1}, args)

q.Where("first_name = ? and last_name = ?", "Mark", "Bates")
sql, _ = q.ToSQL(m)
sql, args = q.ToSQL(m)
a.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE id = ? AND first_name = ? and last_name = ?"), sql)
a.Equal([]interface{}{1, "Mark", "Bates"}, args)

q = PDB.Where("name = ?", "Mark 'Awesome' Bates")
sql, _ = q.ToSQL(m)
sql, args = q.ToSQL(m)
a.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE name = ?"), sql)
a.Equal([]interface{}{"Mark 'Awesome' Bates"}, args)

q = PDB.Where("name = ?", "'; truncate users; --")
sql, _ = q.ToSQL(m)
a.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE name = ?"), sql)

q = PDB.Where("id is not null") // no args
sql, args = q.ToSQL(m)
a.Equal(ts("SELECT enemies.A FROM enemies AS enemies WHERE id is not null"), sql)
a.Equal([]interface{}{}, args)
}

func Test_Where_In(t *testing.T) {
Expand All @@ -42,15 +50,12 @@ func Test_Where_In(t *testing.T) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "B"}
u3 := &Song{Title: "C"}
err := tx.Create(u1)
r.NoError(err)
err = tx.Create(u2)
r.NoError(err)
err = tx.Create(u3)
r.NoError(err)
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

var songs []Song
err = tx.Where("id in (?)", u1.ID, u3.ID).All(&songs)
err := tx.Where("id in (?)", u1.ID, u3.ID).All(&songs)
r.NoError(err)
r.Len(songs, 2)
})
Expand All @@ -65,20 +70,40 @@ func Test_Where_In_Slice(t *testing.T) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "A"}
u3 := &Song{Title: "A"}
err := tx.Create(u1)
r.NoError(err)
err = tx.Create(u2)
r.NoError(err)
err = tx.Create(u3)
r.NoError(err)
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

var songs []Song
err = tx.Where("id in (?)", []uuid.UUID{u1.ID, u3.ID}).Where("title = ?", "A").All(&songs)
err := tx.Where("id in (?)", []uuid.UUID{u1.ID, u3.ID}).Where("title = ?", "A").All(&songs)
r.NoError(err)
r.Len(songs, 2)
})
}

func Test_Where_In_One(t *testing.T) {
if PDB == nil {
t.Skip("skipping integration tests")
}
r := require.New(t)
transaction(func(tx *Connection) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "B"}
u3 := &Song{Title: "C"}
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

Debug = true
defer func() { Debug = false }()

var songs []Song
err := tx.Where("id in (?)", u1.ID).All(&songs)
r.NoError(err)
r.Len(songs, 1)
})
}

func Test_Where_In_Complex(t *testing.T) {
if PDB == nil {
t.Skip("skipping integration tests")
Expand All @@ -88,15 +113,58 @@ func Test_Where_In_Complex(t *testing.T) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "A"}
u3 := &Song{Title: "A"}
err := tx.Create(u1)
r.NoError(err)
err = tx.Create(u2)
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

var songs []Song
err := tx.Where("id in (?)", u1.ID, u3.ID).Where("title = ?", "A").All(&songs)
r.NoError(err)
err = tx.Create(u3)
r.Len(songs, 2)
})
}

func Test_Where_In_Complex_One(t *testing.T) {
if PDB == nil {
t.Skip("skipping integration tests")
}
r := require.New(t)
transaction(func(tx *Connection) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "A"}
u3 := &Song{Title: "A"}
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

Debug = true
defer func() { Debug = false }()

var songs []Song
err := tx.Where("id in (?)", u3.ID).Where("title = ?", "A").All(&songs)
r.NoError(err)
r.Len(songs, 1)
})
}

func Test_Where_In_Space(t *testing.T) {
if PDB == nil {
t.Skip("skipping integration tests")
}
r := require.New(t)
transaction(func(tx *Connection) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "B"}
u3 := &Song{Title: "C"}
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

Debug = true
defer func() { Debug = false }()

var songs []Song
err = tx.Where("id in (?)", u1.ID, u3.ID).Where("title = ?", "A").All(&songs)
err := tx.Where("id in ( ? )", u1.ID, u3.ID).All(&songs)
r.NoError(err)
r.Len(songs, 2)
})
Expand Down Expand Up @@ -127,15 +195,12 @@ func Test_Order_With_Args(t *testing.T) {
u1 := &Song{Title: "A"}
u2 := &Song{Title: "B"}
u3 := &Song{Title: "C"}
err := tx.Create(u1)
r.NoError(err)
err = tx.Create(u2)
r.NoError(err)
err = tx.Create(u3)
r.NoError(err)
r.NoError(tx.Create(u1))
r.NoError(tx.Create(u2))
r.NoError(tx.Create(u3))

var songs []Song
err = tx.Where("id in (?)", []uuid.UUID{u1.ID, u2.ID, u3.ID}).
err := tx.Where("id in (?)", []uuid.UUID{u1.ID, u2.ID, u3.ID}).
Order("title > ? DESC", "A").Order("title").
All(&songs)
r.NoError(err)
Expand Down

0 comments on commit 30ded0f

Please sign in to comment.