squirrel icon indicating copy to clipboard operation
squirrel copied to clipboard

Reusable conditional where query

Open unbearables opened this issue 1 year ago • 2 comments

Hello,

I want to create reusable conditional query for pagination (count query + offset query).

I haven't found any official reusable solution. So far I have following solution:

import (
  "strings"

  sqrl "github.com/Masterminds/squirrel"
)
...
var whereConds []string
var whereArgs []interface{}

if condition {
  sqlQuery, args, _ := sqrl.Eq{"user_id": userId}.ToSql()
  whereConds = append(whereConds, sqlQuery)
  whereArgs = append(whereArgs, args...)
}
// more conditional queries

var count uint
err := sqrl.Select("COUNT(*)").From("users").
  Where(strings.Join(whereConds, " AND "), whereArgs...).
  RunWith(db).Scan(&count)
if err != nil {
  panic(err)
}

users := []UserEntity{}
if count > 0 {
  offset := (pageNumber - 1) * (pageSize + 1)

  sql, args, _ := sqrl.Select("*").From("users").
    Where(strings.Join(whereConds, " AND "), whereArgs...).
    Limit(uint64(pageSize)).Offset(uint64(offset)).
    ToSql()
  err := db.Select(&users, sql, args...)
  if err != nil {
    panic(err)
  }
}

Is there any better solution for reusing a where condition?

unbearables avatar Jan 17 '23 22:01 unbearables

I was just messing around with this for a very similar problem, and I think you can just use squirrel.And (which is the default).

This is a snippet of what I came up with:

filterPredicate := squirrel.And{}

if len(query.Status) > 0 {
	filterPredicate = append(filterPredicate, squirrel.Eq{"status": query.Status})
}

if !query.CreatedBefore.IsZero() {
	filterPredicate = append(filterPredicate, squirrel.LtOrEq{"created": query.CreatedBefore})
}

if !query.CreatedAfter.IsZero() {
	filterPredicate = append(filterPredicate, squirrel.GtOrEq{"created": query.CreatedAfter})
}

resultsSql = resultsSql.Where(filterPredicate)
totalSql = totalSql.Where(filterPredicate)

This seems to work ok. The part where I got stumped was when I needed to have custom dialect queries like: .Where("? = ANY(name)", query.Name), so if anyone knows how to do that using squirrel I'd love to know.

ericedem avatar Mar 17 '23 16:03 ericedem

it don not support this :

filterPredicate = append(filterPredicate, squirrel.Eq{"title LIKE ?": fmt.Sprint("%", data.Title, "%")})

jsonMark avatar Apr 12 '23 08:04 jsonMark