Commit 379580a0 authored by Amos Wenger's avatar Amos Wenger

SearchParams => Search, pass by value instead of by ref

parent 918412f4
Pipeline #11186 passed with stage
in 28 seconds
......@@ -19,7 +19,7 @@ func (c *Context) Exec(conn *sqlite.Conn, b *builder.Builder, resultFn ResultFn)
return c.ExecRaw(conn, query, resultFn, args...)
}
func (c *Context) ExecWithSearch(conn *sqlite.Conn, b *builder.Builder, search *SearchParams, resultFn ResultFn) error {
func (c *Context) ExecWithSearch(conn *sqlite.Conn, b *builder.Builder, search Search, resultFn ResultFn) error {
query, args, err := b.ToSQL()
if err != nil {
return errors.WithStack(err)
......
......@@ -79,12 +79,12 @@ func Test_HasMany(t *testing.T) {
assert.EqualValues(t, 3, len(p1bis.Qualities), "preload replaces, doesn't append")
wtest.Must(t, c.Preload(conn, p1bis,
hades.AssocWithSearch("Qualities", hades.Search().OrderBy("id ASC"))),
hades.AssocWithSearch("Qualities", hades.Search{}.OrderBy("id ASC"))),
)
assert.EqualValues(t, "Inspiration", p1bis.Qualities[0].Label, "orders by (asc)")
wtest.Must(t, c.Preload(conn, p1bis,
hades.AssocWithSearch("Qualities", hades.Search().OrderBy("id DESC"))),
hades.AssocWithSearch("Qualities", hades.Search{}.OrderBy("id DESC"))),
)
assert.EqualValues(t, "Inspiration again", p1bis.Qualities[0].Label, "orders by (desc)")
......
......@@ -177,7 +177,7 @@ func Test_ManyToManyRevenge(t *testing.T) {
builder.Select("games.title").
From("games").
LeftJoin("profile_games", builder.Expr("profile_games.game_id = games.id")),
hades.Search().OrderBy("profile_games.\"order\" ASC"),
hades.Search{}.OrderBy("profile_games.\"order\" ASC"),
c.IntoRowsScanner(&names),
))
assert.EqualValues(t, []struct {
......
......@@ -153,9 +153,7 @@ func (scope *Scope) GetModelStruct() *ModelStruct {
} else if _, ok := field.TagSettings[TagSettingSquash]; ok {
field.IsSquashed = true
nestedModelStruct := scope.ctx.NewScope(reflect.Zero(field.Struct.Type).Interface()).GetModelStruct()
for _, sf := range nestedModelStruct.StructFields {
field.SquashedFields = append(field.SquashedFields, sf)
}
field.SquashedFields = append(field.SquashedFields, nestedModelStruct.StructFields...)
} else {
if _, ok := field.TagSettings[TagSettingPrimaryKey]; ok {
field.IsPrimaryKey = true
......
......@@ -15,7 +15,7 @@ type QueryFn func(query string) string
// retrieve cached items in a []*SomeModel
// for some reason, reflect.New returns a &[]*SomeModel instead,
// I'm guessing slices can't be interfaces, but pointers to slices can?
func (c *Context) fetchPagedByPK(conn *sqlite.Conn, PKDBName string, keys []interface{}, sliceType reflect.Type, search *SearchParams) (reflect.Value, error) {
func (c *Context) fetchPagedByPK(conn *sqlite.Conn, PKDBName string, keys []interface{}, sliceType reflect.Type, search Search) (reflect.Value, error) {
// actually defaults to 999, but let's get some breathing room
result := reflect.New(sliceType)
resultVal := result.Elem()
......
......@@ -9,7 +9,7 @@ const (
type assocField struct {
name string
search *SearchParams
search Search
mode AssocMode
children []AssocField
}
......@@ -36,7 +36,7 @@ type AssocField interface {
PreloadParam
Name() string
Mode() AssocMode
Search() *SearchParams
Search() Search
Children() []AssocField
}
......@@ -75,7 +75,7 @@ func AssocReplace(fieldName string, children ...AssocField) AssocField {
}
}
func AssocWithSearch(fieldName string, search *SearchParams, children ...AssocField) AssocField {
func AssocWithSearch(fieldName string, search Search, children ...AssocField) AssocField {
return &assocField{
name: fieldName,
mode: AssocModeAppend,
......@@ -104,6 +104,6 @@ func (f *assocField) Children() []AssocField {
return f.children
}
func (f *assocField) Search() *SearchParams {
func (f *assocField) Search() Search {
return f.search
}
......@@ -18,7 +18,7 @@ func (c *Context) saveJoins(conn *sqlite.Conn, mode AssocMode, mtm *ManyToMany)
for sourceKey, joinRecs := range mtm.Values {
cacheAddr := reflect.New(reflect.SliceOf(joinType))
err := c.Select(conn, cacheAddr.Interface(), builder.Eq{mtm.SourceDBName: sourceKey}, nil)
err := c.Select(conn, cacheAddr.Interface(), builder.Eq{mtm.SourceDBName: sourceKey}, Search{})
if err != nil {
return errors.WithMessage(err, "fetching cached records to compare later")
}
......
......@@ -133,7 +133,7 @@ func (c *Context) saveRows(conn *sqlite.Conn, mode AssocMode, inputIface interfa
keys = append(keys, getKey(record))
}
cacheAddr, err := c.fetchPagedByPK(conn, primaryField.DBName, keys, fresh.Type(), nil)
cacheAddr, err := c.fetchPagedByPK(conn, primaryField.DBName, keys, fresh.Type(), Search{})
if err != nil {
return errors.WithMessage(err, "getting existing rows")
}
......
......@@ -55,7 +55,7 @@ func Test_Scan(t *testing.T) {
builder.Select("games.*", "game_embed_data.*").
From("games").
LeftJoin("game_embed_data", builder.Expr("game_embed_data.game_id = games.id")),
hades.Search().OrderBy("games.id ASC"),
hades.Search{}.OrderBy("games.id ASC"),
c.IntoRowsScanner(&rows),
))
......
......@@ -5,56 +5,50 @@ import (
"strings"
)
type SearchParams struct {
type Search struct {
orders []string
offset *int64
limit *int64
}
func Search() *SearchParams {
return &SearchParams{}
}
func (s *SearchParams) OrderBy(order string) *SearchParams {
func (s Search) OrderBy(order string) Search {
s.orders = append(s.orders, order)
return s
}
func (s *SearchParams) Limit(limit int64) *SearchParams {
func (s Search) Limit(limit int64) Search {
s.limit = &limit
return s
}
func (s *SearchParams) Offset(offset int64) *SearchParams {
func (s Search) Offset(offset int64) Search {
s.offset = &offset
return s
}
func (s *SearchParams) Apply(sql string) string {
if s != nil {
if len(s.orders) > 0 {
sql = fmt.Sprintf("%s ORDER BY %s", sql, strings.Join(s.orders, ", "))
}
func (s Search) Apply(sql string) string {
if len(s.orders) > 0 {
sql = fmt.Sprintf("%s ORDER BY %s", sql, strings.Join(s.orders, ", "))
}
if s.limit != nil || s.offset != nil {
var limit int64 = -1
if s.limit != nil {
limit = *s.limit
}
if s.limit != nil || s.offset != nil {
var limit int64 = -1
if s.limit != nil {
limit = *s.limit
}
// offset must appear without limit,
// and a negative limit means no limit.
// see https://www.sqlite.org/lang_select.html#limitoffset
sql = fmt.Sprintf("%s LIMIT %d", sql, limit)
// offset must appear without limit,
// and a negative limit means no limit.
// see https://www.sqlite.org/lang_select.html#limitoffset
sql = fmt.Sprintf("%s LIMIT %d", sql, limit)
if s.offset != nil {
sql = fmt.Sprintf("%s OFFSET %d", sql, *s.offset)
}
if s.offset != nil {
sql = fmt.Sprintf("%s OFFSET %d", sql, *s.offset)
}
}
return sql
}
func (s *SearchParams) String() string {
func (s Search) String() string {
return s.Apply("")
}
......@@ -7,11 +7,11 @@ import (
)
func Test_Search(t *testing.T) {
assert.EqualValues(t, "x", Search().Apply("x"))
assert.EqualValues(t, "x LIMIT 1", Search().Limit(1).Apply("x"))
assert.EqualValues(t, "x LIMIT -1 OFFSET 1", Search().Offset(1).Apply("x"))
assert.EqualValues(t, "x LIMIT 10 OFFSET 5", Search().Offset(5).Limit(10).Apply("x"))
assert.EqualValues(t, "x ORDER BY id desc", Search().OrderBy("id desc").Apply("x"))
assert.EqualValues(t, "x ORDER BY id asc", Search().OrderBy("id asc").Apply("x"))
assert.EqualValues(t, "x ORDER BY id asc, created_at desc", Search().OrderBy("id asc").OrderBy("created_at desc").Apply("x"))
assert.EqualValues(t, "x", Search{}.Apply("x"))
assert.EqualValues(t, "x LIMIT 1", Search{}.Limit(1).Apply("x"))
assert.EqualValues(t, "x LIMIT -1 OFFSET 1", Search{}.Offset(1).Apply("x"))
assert.EqualValues(t, "x LIMIT 10 OFFSET 5", Search{}.Offset(5).Limit(10).Apply("x"))
assert.EqualValues(t, "x ORDER BY id desc", Search{}.OrderBy("id desc").Apply("x"))
assert.EqualValues(t, "x ORDER BY id asc", Search{}.OrderBy("id asc").Apply("x"))
assert.EqualValues(t, "x ORDER BY id asc, created_at desc", Search{}.OrderBy("id asc").OrderBy("created_at desc").Apply("x"))
}
......@@ -9,7 +9,7 @@ import (
"github.com/pkg/errors"
)
func (c *Context) Select(conn *sqlite.Conn, result interface{}, cond builder.Cond, search *SearchParams) error {
func (c *Context) Select(conn *sqlite.Conn, result interface{}, cond builder.Cond, search Search) error {
resultVal := reflect.ValueOf(result)
originalType := resultVal.Type()
......@@ -73,7 +73,7 @@ func (c *Context) SelectOne(conn *sqlite.Conn, result interface{}, cond builder.
if err != nil {
return found, err
}
query = Search().Limit(1).Apply(query)
query = Search{}.Limit(1).Apply(query)
err = c.ExecRaw(conn, query, func(stmt *sqlite.Stmt) error {
err := c.Scan(stmt, fields, resultVal)
......
......@@ -65,17 +65,17 @@ func Test_Select(t *testing.T) {
assert.True(t, found)
var honors []*Honor
wtest.Must(t, c.Select(conn, &honors, builder.Gte{"id": 2}, nil))
wtest.Must(t, c.Select(conn, &honors, builder.Gte{"id": 2}, hades.Search{}))
assert.EqualValues(t, 2, len(honors))
wtest.Must(t, c.ExecRaw(conn, "DROP TABLE honors", nil))
// ---------
err = c.Select(conn, []Honor{}, builder.Eq{"id": 3}, nil)
err = c.Select(conn, []Honor{}, builder.Eq{"id": 3}, hades.Search{})
assert.Error(t, err, "Select must reject non-pointer slice")
err = c.Select(conn, &Honor{}, builder.Eq{"id": 3}, nil)
err = c.Select(conn, &Honor{}, builder.Eq{"id": 3}, hades.Search{})
assert.Error(t, err, "Select must reject pointer to non-slice")
type NotAModel struct {
......@@ -83,7 +83,7 @@ func Test_Select(t *testing.T) {
}
var namSlice []*NotAModel
err = c.Select(conn, &namSlice, builder.Eq{"id": 3}, nil)
err = c.Select(conn, &namSlice, builder.Eq{"id": 3}, hades.Search{})
assert.Error(t, err, "Select must reject pointer to slice of non-models")
// ---------
......
......@@ -174,7 +174,7 @@ func Test_SquashedFull(t *testing.T) {
assert.EqualValues(t, 15, u.ID)
wtest.Must(t, c.Preload(conn, u,
hades.AssocWithSearch("Games", hades.Search().OrderBy("id ASC").Offset(1)),
hades.AssocWithSearch("Games", hades.Search{}.OrderBy("id ASC").Offset(1)),
))
assert.EqualValues(t, 2, len(u.Games))
assert.EqualValues(t, FakeGameTraits{Ubiquitous: true}, u.Games[0].Traits)
......@@ -185,7 +185,7 @@ func Test_SquashedFull(t *testing.T) {
wtest.Must(t, c.Save(conn, fu, hades.Assoc("Games")))
wtest.Must(t, c.Preload(conn, u,
hades.AssocWithSearch("Games", hades.Search().OrderBy("id ASC").Offset(2).Limit(1)),
hades.AssocWithSearch("Games", hades.Search{}.OrderBy("id ASC").Offset(2).Limit(1)),
))
assert.EqualValues(t, 1, len(u.Games))
assert.EqualValues(t, 6, u.Games[0].ID)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment