Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix order by #19821

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ require (
gopkg.in/yaml.v2 v2.4.0
mvdan.cc/xurls/v2 v2.4.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
xorm.io/builder v0.3.10
xorm.io/builder v0.3.11-0.20220528023925-443794ecabe6
xorm.io/xorm v1.2.5
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2319,7 +2319,7 @@ sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
xorm.io/builder v0.3.9/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.10 h1:Rvkncad3Lo9YIVqCbgIf6QnpR/HcW3IEr0AANNpuyMQ=
xorm.io/builder v0.3.10/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.11-0.20220528023925-443794ecabe6 h1:q87Pe12cfWbN7gCS2dydxNQwr4V29EQjyP+LhsBQ0QQ=
xorm.io/builder v0.3.11-0.20220528023925-443794ecabe6/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.2.5 h1:tqN7OhN8P9xi52qBb76I8m5maAJMz/SSbgK2RGPCPbo=
xorm.io/xorm v1.2.5/go.mod h1:fTG8tSjk6O1BYxwuohZUK+S1glnRycsCF05L1qQyEU0=
5 changes: 5 additions & 0 deletions integrations/api_repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ func TestAPISearchRepo(t *testing.T) {
user2: {count: 7, repoName: "big_test_"},
},
},
{
name: "RepositoriesByName", requestURL: fmt.Sprintf("/api/v1/repos/search?q=%s&private=false", "user2/big_test_"), expectedResults: expectedResults{
user2: {count: 7, repoName: "big_test_"},
},
},
{
name: "RepositoriesAccessibleAndRelatedToUser", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user.ID), expectedResults: expectedResults{
nil: {count: 5},
Expand Down
62 changes: 40 additions & 22 deletions models/repo_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"

Expand Down Expand Up @@ -520,7 +521,8 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
// SearchRepositoryByCondition search repositories by condition
func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
ctx := db.DefaultContext
sess, count, err := searchRepositoryByCondition(ctx, opts, cond)

b, count, err := searchRepositoryByCondition(ctx, opts, "*", cond)
if err != nil {
return nil, 0, err
}
Expand All @@ -530,7 +532,7 @@ func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loa
defaultSize = opts.PageSize
}
repos := make(RepositoryList, 0, defaultSize)
if err := sess.Find(&repos); err != nil {
if err := db.GetEngine(ctx).SQL(b).Find(&repos); err != nil {
return nil, 0, fmt.Errorf("Repo: %v", err)
}

Expand All @@ -547,41 +549,57 @@ func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loa
return repos, count, nil
}

func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond) (db.Engine, int64, error) {
func withDB() *builder.Builder {
switch {
case setting.Database.UseSQLite3:
return builder.Dialect(builder.SQLITE)
case setting.Database.UseMySQL:
return builder.Dialect(builder.MYSQL)
case setting.Database.UsePostgreSQL:
return builder.Dialect(builder.POSTGRES)
case setting.Database.UseMSSQL:
return builder.Dialect(builder.MSSQL)
}
return &builder.Builder{}
}

func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, selCols string, cond builder.Cond) (*builder.Builder, int64, error) {
if opts.Page <= 0 {
opts.Page = 1
}

var count int64
if opts.PageSize > 0 {
var err error
count, err = db.GetEngine(ctx).
Where(cond).
Count(new(repo_model.Repository))
if err != nil {
return nil, 0, fmt.Errorf("Count: %v", err)
}
}

if len(opts.OrderBy) == 0 {
opts.OrderBy = db.SearchOrderByAlphabetically
}

var orderBy interface{}
if opts.PriorityOwnerID > 0 {
opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = %d THEN 0 ELSE owner_id END, %s", opts.PriorityOwnerID, opts.OrderBy))
orderBy = fmt.Sprintf("CASE WHEN owner_id = %d THEN 0 ELSE owner_id END, %s", opts.PriorityOwnerID, opts.OrderBy)
} else if strings.Count(opts.Keyword, "/") == 1 {
// With "owner/repo" search times, prioritise results which match the owner field
orgName := strings.Split(opts.Keyword, "/")[0]
opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE '%s' THEN 0 ELSE 1 END, %s", orgName, opts.OrderBy))
orderBy = builder.Expr(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", opts.OrderBy), orgName)
} else {
orderBy = opts.OrderBy.String()
}

sess := db.GetEngine(ctx)

var count int64
b := withDB().Select(selCols).From("repository").Where(cond).OrderBy(orderBy)
if opts.PageSize > 0 {
var err error
count, err = sess.
Where(cond).
Count(new(repo_model.Repository))
if err != nil {
return nil, 0, fmt.Errorf("Count: %v", err)
}
b.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}

sess = sess.Where(cond).OrderBy(opts.OrderBy.String())
if opts.PageSize > 0 {
sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
return sess, count, nil
return b, count, nil
}

// accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
Expand Down Expand Up @@ -634,7 +652,7 @@ func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) {

cond := SearchRepositoryCondition(opts)

sess, count, err := searchRepositoryByCondition(db.DefaultContext, opts, cond)
b, count, err := searchRepositoryByCondition(db.DefaultContext, opts, "id", cond)
if err != nil {
return nil, 0, err
}
Expand All @@ -645,7 +663,7 @@ func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) {
}

ids := make([]int64, 0, defaultSize)
err = sess.Select("id").Table("repository").Find(&ids)
err = db.GetEngine(db.DefaultContext).SQL(b).Find(&ids)
if opts.PageSize <= 0 {
count = int64(len(ids))
}
Expand Down