forked from mirror/gorm
parent
4b22a55a75
commit
e8f48b5c15
|
@ -244,7 +244,7 @@ func (db *DB) Order(value interface{}) (tx *DB) {
|
||||||
// Limit specify the number of records to be retrieved
|
// Limit specify the number of records to be retrieved
|
||||||
func (db *DB) Limit(limit int) (tx *DB) {
|
func (db *DB) Limit(limit int) (tx *DB) {
|
||||||
tx = db.getInstance()
|
tx = db.getInstance()
|
||||||
tx.Statement.AddClause(clause.Limit{Limit: limit})
|
tx.Statement.AddClause(clause.Limit{Limit: &limit})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ func BenchmarkSelect(b *testing.B) {
|
||||||
func BenchmarkComplexSelect(b *testing.B) {
|
func BenchmarkComplexSelect(b *testing.B) {
|
||||||
user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
|
user, _ := schema.Parse(&tests.User{}, &sync.Map{}, db.NamingStrategy)
|
||||||
|
|
||||||
|
limit10 := 10
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
stmt := gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
|
stmt := gorm.Statement{DB: db, Table: user.Table, Schema: user, Clauses: map[string]clause.Clause{}}
|
||||||
clauses := []clause.Interface{
|
clauses := []clause.Interface{
|
||||||
|
@ -43,7 +44,7 @@ func BenchmarkComplexSelect(b *testing.B) {
|
||||||
clause.Or(clause.Gt{Column: "score", Value: 100}, clause.Like{Column: "name", Value: "%linus%"}),
|
clause.Or(clause.Gt{Column: "score", Value: 100}, clause.Like{Column: "name", Value: "%linus%"}),
|
||||||
}},
|
}},
|
||||||
clause.GroupBy{Columns: []clause.Column{{Name: "role"}}, Having: []clause.Expression{clause.Eq{"role", "admin"}}},
|
clause.GroupBy{Columns: []clause.Column{{Name: "role"}}, Having: []clause.Expression{clause.Eq{"role", "admin"}}},
|
||||||
clause.Limit{Limit: 10, Offset: 20},
|
clause.Limit{Limit: &limit10, Offset: 20},
|
||||||
clause.OrderBy{Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}},
|
clause.OrderBy{Columns: []clause.OrderByColumn{{Column: clause.PrimaryColumn, Desc: true}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import "strconv"
|
||||||
|
|
||||||
// Limit limit clause
|
// Limit limit clause
|
||||||
type Limit struct {
|
type Limit struct {
|
||||||
Limit int
|
Limit *int
|
||||||
Offset int
|
Offset int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,12 @@ func (limit Limit) Name() string {
|
||||||
|
|
||||||
// Build build where clause
|
// Build build where clause
|
||||||
func (limit Limit) Build(builder Builder) {
|
func (limit Limit) Build(builder Builder) {
|
||||||
if limit.Limit > 0 {
|
if limit.Limit != nil && *limit.Limit >= 0 {
|
||||||
builder.WriteString("LIMIT ")
|
builder.WriteString("LIMIT ")
|
||||||
builder.WriteString(strconv.Itoa(limit.Limit))
|
builder.WriteString(strconv.Itoa(*limit.Limit))
|
||||||
}
|
}
|
||||||
if limit.Offset > 0 {
|
if limit.Offset > 0 {
|
||||||
if limit.Limit > 0 {
|
if limit.Limit != nil && *limit.Limit >= 0 {
|
||||||
builder.WriteByte(' ')
|
builder.WriteByte(' ')
|
||||||
}
|
}
|
||||||
builder.WriteString("OFFSET ")
|
builder.WriteString("OFFSET ")
|
||||||
|
@ -33,7 +33,7 @@ func (limit Limit) MergeClause(clause *Clause) {
|
||||||
clause.Name = ""
|
clause.Name = ""
|
||||||
|
|
||||||
if v, ok := clause.Expression.(Limit); ok {
|
if v, ok := clause.Expression.(Limit); ok {
|
||||||
if limit.Limit == 0 && v.Limit != 0 {
|
if (limit.Limit == nil || *limit.Limit == 0) && (v.Limit != nil && *v.Limit != 0) {
|
||||||
limit.Limit = v.Limit
|
limit.Limit = v.Limit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLimit(t *testing.T) {
|
func TestLimit(t *testing.T) {
|
||||||
|
limit0 := 0
|
||||||
|
limit10 := 10
|
||||||
|
limit50 := 50
|
||||||
|
limitNeg10 := -10
|
||||||
results := []struct {
|
results := []struct {
|
||||||
Clauses []clause.Interface
|
Clauses []clause.Interface
|
||||||
Result string
|
Result string
|
||||||
|
@ -15,11 +19,15 @@ func TestLimit(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{
|
||||||
Limit: 10,
|
Limit: &limit10,
|
||||||
Offset: 20,
|
Offset: 20,
|
||||||
}},
|
}},
|
||||||
"SELECT * FROM `users` LIMIT 10 OFFSET 20", nil,
|
"SELECT * FROM `users` LIMIT 10 OFFSET 20", nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: &limit0}},
|
||||||
|
"SELECT * FROM `users` LIMIT 0", nil,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Offset: 20}},
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Offset: 20}},
|
||||||
"SELECT * FROM `users` OFFSET 20", nil,
|
"SELECT * FROM `users` OFFSET 20", nil,
|
||||||
|
@ -29,23 +37,23 @@ func TestLimit(t *testing.T) {
|
||||||
"SELECT * FROM `users` OFFSET 30", nil,
|
"SELECT * FROM `users` OFFSET 30", nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Offset: 20}, clause.Limit{Limit: 10}},
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Offset: 20}, clause.Limit{Limit: &limit10}},
|
||||||
"SELECT * FROM `users` LIMIT 10 OFFSET 20", nil,
|
"SELECT * FROM `users` LIMIT 10 OFFSET 20", nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: 10, Offset: 20}, clause.Limit{Offset: 30}},
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: &limit10, Offset: 20}, clause.Limit{Offset: 30}},
|
||||||
"SELECT * FROM `users` LIMIT 10 OFFSET 30", nil,
|
"SELECT * FROM `users` LIMIT 10 OFFSET 30", nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: 10, Offset: 20}, clause.Limit{Offset: 30}, clause.Limit{Offset: -10}},
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: &limit10, Offset: 20}, clause.Limit{Offset: 30}, clause.Limit{Offset: -10}},
|
||||||
"SELECT * FROM `users` LIMIT 10", nil,
|
"SELECT * FROM `users` LIMIT 10", nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: 10, Offset: 20}, clause.Limit{Offset: 30}, clause.Limit{Limit: -10}},
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: &limit10, Offset: 20}, clause.Limit{Offset: 30}, clause.Limit{Limit: &limitNeg10}},
|
||||||
"SELECT * FROM `users` OFFSET 30", nil,
|
"SELECT * FROM `users` OFFSET 30", nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: 10, Offset: 20}, clause.Limit{Offset: 30}, clause.Limit{Limit: 50}},
|
[]clause.Interface{clause.Select{}, clause.From{}, clause.Limit{Limit: &limit10, Offset: 20}, clause.Limit{Offset: 30}, clause.Limit{Limit: &limit50}},
|
||||||
"SELECT * FROM `users` LIMIT 50 OFFSET 30", nil,
|
"SELECT * FROM `users` LIMIT 50 OFFSET 30", nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,9 @@ func (db *DB) FindInBatches(dest interface{}, batchSize int, fc func(tx *DB, bat
|
||||||
var totalSize int
|
var totalSize int
|
||||||
if c, ok := tx.Statement.Clauses["LIMIT"]; ok {
|
if c, ok := tx.Statement.Clauses["LIMIT"]; ok {
|
||||||
if limit, ok := c.Expression.(clause.Limit); ok {
|
if limit, ok := c.Expression.(clause.Limit); ok {
|
||||||
totalSize = limit.Limit
|
if limit.Limit != nil {
|
||||||
|
totalSize = *limit.Limit
|
||||||
|
}
|
||||||
|
|
||||||
if totalSize > 0 && batchSize > totalSize {
|
if totalSize > 0 && batchSize > totalSize {
|
||||||
batchSize = totalSize
|
batchSize = totalSize
|
||||||
|
|
Loading…
Reference in New Issue