]> source.dussan.org Git - gitea.git/commitdiff
Fix db.Find bug (#23115) (#23119)
authorYarden Shoham <hrsi88@gmail.com>
Fri, 24 Feb 2023 14:05:36 +0000 (16:05 +0200)
committerGitHub <noreply@github.com>
Fri, 24 Feb 2023 14:05:36 +0000 (14:05 +0000)
Backport #23115

Caused by #20821

Fix #23110

models/db/list.go [new file with mode: 0644]
models/db/list_options.go [deleted file]
models/db/list_test.go [new file with mode: 0644]

diff --git a/models/db/list.go b/models/db/list.go
new file mode 100644 (file)
index 0000000..9fb4d07
--- /dev/null
@@ -0,0 +1,152 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package db
+
+import (
+       "context"
+
+       "code.gitea.io/gitea/modules/setting"
+
+       "xorm.io/builder"
+       "xorm.io/xorm"
+)
+
+const (
+       // DefaultMaxInSize represents default variables number on IN () in SQL
+       DefaultMaxInSize = 50
+)
+
+// Paginator is the base for different ListOptions types
+type Paginator interface {
+       GetSkipTake() (skip, take int)
+       GetStartEnd() (start, end int)
+       IsListAll() bool
+}
+
+// GetPaginatedSession creates a paginated database session
+func GetPaginatedSession(p Paginator) *xorm.Session {
+       skip, take := p.GetSkipTake()
+
+       return x.Limit(take, skip)
+}
+
+// SetSessionPagination sets pagination for a database session
+func SetSessionPagination(sess Engine, p Paginator) *xorm.Session {
+       skip, take := p.GetSkipTake()
+
+       return sess.Limit(take, skip)
+}
+
+// SetEnginePagination sets pagination for a database engine
+func SetEnginePagination(e Engine, p Paginator) Engine {
+       skip, take := p.GetSkipTake()
+
+       return e.Limit(take, skip)
+}
+
+// ListOptions options to paginate results
+type ListOptions struct {
+       PageSize int
+       Page     int  // start from 1
+       ListAll  bool // if true, then PageSize and Page will not be taken
+}
+
+var _ Paginator = &ListOptions{}
+
+// GetSkipTake returns the skip and take values
+func (opts *ListOptions) GetSkipTake() (skip, take int) {
+       opts.SetDefaultValues()
+       return (opts.Page - 1) * opts.PageSize, opts.PageSize
+}
+
+// GetStartEnd returns the start and end of the ListOptions
+func (opts *ListOptions) GetStartEnd() (start, end int) {
+       start, take := opts.GetSkipTake()
+       end = start + take
+       return start, end
+}
+
+// IsListAll indicates PageSize and Page will be ignored
+func (opts *ListOptions) IsListAll() bool {
+       return opts.ListAll
+}
+
+// SetDefaultValues sets default values
+func (opts *ListOptions) SetDefaultValues() {
+       if opts.PageSize <= 0 {
+               opts.PageSize = setting.API.DefaultPagingNum
+       }
+       if opts.PageSize > setting.API.MaxResponseItems {
+               opts.PageSize = setting.API.MaxResponseItems
+       }
+       if opts.Page <= 0 {
+               opts.Page = 1
+       }
+}
+
+// AbsoluteListOptions absolute options to paginate results
+type AbsoluteListOptions struct {
+       skip int
+       take int
+}
+
+var _ Paginator = &AbsoluteListOptions{}
+
+// NewAbsoluteListOptions creates a list option with applied limits
+func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
+       if skip < 0 {
+               skip = 0
+       }
+       if take <= 0 {
+               take = setting.API.DefaultPagingNum
+       }
+       if take > setting.API.MaxResponseItems {
+               take = setting.API.MaxResponseItems
+       }
+       return &AbsoluteListOptions{skip, take}
+}
+
+// IsListAll will always return false
+func (opts *AbsoluteListOptions) IsListAll() bool {
+       return false
+}
+
+// GetSkipTake returns the skip and take values
+func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
+       return opts.skip, opts.take
+}
+
+// GetStartEnd returns the start and end values
+func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) {
+       return opts.skip, opts.skip + opts.take
+}
+
+// FindOptions represents a find options
+type FindOptions interface {
+       Paginator
+       ToConds() builder.Cond
+}
+
+// Find represents a common find function which accept an options interface
+func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error {
+       sess := GetEngine(ctx).Where(opts.ToConds())
+       if !opts.IsListAll() {
+               sess.Limit(opts.GetSkipTake())
+       }
+       return sess.Find(objects)
+}
+
+// Count represents a common count function which accept an options interface
+func Count[T any](ctx context.Context, opts FindOptions, object T) (int64, error) {
+       return GetEngine(ctx).Where(opts.ToConds()).Count(object)
+}
+
+// FindAndCount represents a common findandcount function which accept an options interface
+func FindAndCount[T any](ctx context.Context, opts FindOptions, objects *[]T) (int64, error) {
+       sess := GetEngine(ctx).Where(opts.ToConds())
+       if !opts.IsListAll() {
+               sess.Limit(opts.GetSkipTake())
+       }
+       return sess.FindAndCount(objects)
+}
diff --git a/models/db/list_options.go b/models/db/list_options.go
deleted file mode 100644 (file)
index 2456f90..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2020 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package db
-
-import (
-       "context"
-
-       "code.gitea.io/gitea/modules/setting"
-
-       "xorm.io/builder"
-       "xorm.io/xorm"
-)
-
-const (
-       // DefaultMaxInSize represents default variables number on IN () in SQL
-       DefaultMaxInSize = 50
-)
-
-// Paginator is the base for different ListOptions types
-type Paginator interface {
-       GetSkipTake() (skip, take int)
-       GetStartEnd() (start, end int)
-       IsListAll() bool
-}
-
-// GetPaginatedSession creates a paginated database session
-func GetPaginatedSession(p Paginator) *xorm.Session {
-       skip, take := p.GetSkipTake()
-
-       return x.Limit(take, skip)
-}
-
-// SetSessionPagination sets pagination for a database session
-func SetSessionPagination(sess Engine, p Paginator) *xorm.Session {
-       skip, take := p.GetSkipTake()
-
-       return sess.Limit(take, skip)
-}
-
-// SetEnginePagination sets pagination for a database engine
-func SetEnginePagination(e Engine, p Paginator) Engine {
-       skip, take := p.GetSkipTake()
-
-       return e.Limit(take, skip)
-}
-
-// ListOptions options to paginate results
-type ListOptions struct {
-       PageSize int
-       Page     int  // start from 1
-       ListAll  bool // if true, then PageSize and Page will not be taken
-}
-
-var _ Paginator = &ListOptions{}
-
-// GetSkipTake returns the skip and take values
-func (opts *ListOptions) GetSkipTake() (skip, take int) {
-       opts.SetDefaultValues()
-       return (opts.Page - 1) * opts.PageSize, opts.PageSize
-}
-
-// GetStartEnd returns the start and end of the ListOptions
-func (opts *ListOptions) GetStartEnd() (start, end int) {
-       start, take := opts.GetSkipTake()
-       end = start + take
-       return start, end
-}
-
-// IsListAll indicates PageSize and Page will be ignored
-func (opts *ListOptions) IsListAll() bool {
-       return opts.ListAll
-}
-
-// SetDefaultValues sets default values
-func (opts *ListOptions) SetDefaultValues() {
-       if opts.PageSize <= 0 {
-               opts.PageSize = setting.API.DefaultPagingNum
-       }
-       if opts.PageSize > setting.API.MaxResponseItems {
-               opts.PageSize = setting.API.MaxResponseItems
-       }
-       if opts.Page <= 0 {
-               opts.Page = 1
-       }
-}
-
-// AbsoluteListOptions absolute options to paginate results
-type AbsoluteListOptions struct {
-       skip int
-       take int
-}
-
-var _ Paginator = &AbsoluteListOptions{}
-
-// NewAbsoluteListOptions creates a list option with applied limits
-func NewAbsoluteListOptions(skip, take int) *AbsoluteListOptions {
-       if skip < 0 {
-               skip = 0
-       }
-       if take <= 0 {
-               take = setting.API.DefaultPagingNum
-       }
-       if take > setting.API.MaxResponseItems {
-               take = setting.API.MaxResponseItems
-       }
-       return &AbsoluteListOptions{skip, take}
-}
-
-// IsListAll will always return false
-func (opts *AbsoluteListOptions) IsListAll() bool {
-       return false
-}
-
-// GetSkipTake returns the skip and take values
-func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) {
-       return opts.skip, opts.take
-}
-
-// GetStartEnd returns the start and end values
-func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) {
-       return opts.skip, opts.skip + opts.take
-}
-
-// FindOptions represents a find options
-type FindOptions interface {
-       Paginator
-       ToConds() builder.Cond
-}
-
-// Find represents a common find function which accept an options interface
-func Find[T any](ctx context.Context, opts FindOptions, objects *[]T) error {
-       sess := GetEngine(ctx).Where(opts.ToConds())
-       if !opts.IsListAll() {
-               sess.Limit(opts.GetSkipTake())
-       }
-       return sess.Find(&objects)
-}
-
-// Count represents a common count function which accept an options interface
-func Count[T any](ctx context.Context, opts FindOptions, object T) (int64, error) {
-       return GetEngine(ctx).Where(opts.ToConds()).Count(object)
-}
-
-// FindAndCount represents a common findandcount function which accept an options interface
-func FindAndCount[T any](ctx context.Context, opts FindOptions, objects *[]T) (int64, error) {
-       sess := GetEngine(ctx).Where(opts.ToConds())
-       if !opts.IsListAll() {
-               sess.Limit(opts.GetSkipTake())
-       }
-       return sess.FindAndCount(&objects)
-}
diff --git a/models/db/list_test.go b/models/db/list_test.go
new file mode 100644 (file)
index 0000000..ffef1e4
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package db_test
+
+import (
+       "testing"
+
+       "code.gitea.io/gitea/models/db"
+       repo_model "code.gitea.io/gitea/models/repo"
+       "code.gitea.io/gitea/models/unittest"
+
+       "github.com/stretchr/testify/assert"
+       "xorm.io/builder"
+)
+
+type mockListOptions struct {
+       db.ListOptions
+}
+
+func (opts *mockListOptions) IsListAll() bool {
+       return true
+}
+
+func (opts *mockListOptions) ToConds() builder.Cond {
+       return builder.NewCond()
+}
+
+func TestFind(t *testing.T) {
+       assert.NoError(t, unittest.PrepareTestDatabase())
+       xe := unittest.GetXORMEngine()
+       assert.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
+
+       opts := mockListOptions{}
+       var repoUnits []repo_model.RepoUnit
+       err := db.Find(db.DefaultContext, &opts, &repoUnits)
+       assert.NoError(t, err)
+       assert.EqualValues(t, 83, len(repoUnits))
+
+       cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
+       assert.NoError(t, err)
+       assert.EqualValues(t, 83, cnt)
+
+       repoUnits = make([]repo_model.RepoUnit, 0, 10)
+       newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
+       assert.NoError(t, err)
+       assert.EqualValues(t, cnt, newCnt)
+}