forked from mirror/gorm
Use validated interface{} for limit/offset values to ensure values greater than
max 32-bit integer are addressable, and in a backwards-compatible way.
This commit is contained in:
parent
caa792644c
commit
1485f4bce9
|
@ -35,7 +35,7 @@ type Dialect interface {
|
|||
HasColumn(tableName string, columnName string) bool
|
||||
|
||||
// LimitAndOffsetSQL return generated SQL with Limit and Offset, as mssql has special case
|
||||
LimitAndOffsetSQL(limit, offset int) string
|
||||
LimitAndOffsetSQL(limit, offset interface{}) string
|
||||
// SelectFromDummyTable return select values, for most dbs, `SELECT values` just works, mysql needs `SELECT value FROM DUAL`
|
||||
SelectFromDummyTable() string
|
||||
// LastInsertIdReturningSuffix most dbs support LastInsertId, but postgres needs to use `RETURNING`
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -122,13 +123,15 @@ func (s commonDialect) currentDatabase() (name string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (commonDialect) LimitAndOffsetSQL(limit, offset int) (sql string) {
|
||||
if limit > 0 || offset > 0 {
|
||||
if limit >= 0 {
|
||||
sql += fmt.Sprintf(" LIMIT %d", limit)
|
||||
func (commonDialect) LimitAndOffsetSQL(limit, offset interface{}) (sql string) {
|
||||
if limit != nil {
|
||||
if parsedLimit, err := strconv.ParseInt(fmt.Sprint(limit), 0, 0); err == nil && parsedLimit > 0 {
|
||||
sql += fmt.Sprintf(" LIMIT %d", parsedLimit)
|
||||
}
|
||||
if offset >= 0 {
|
||||
sql += fmt.Sprintf(" OFFSET %d", offset)
|
||||
}
|
||||
if offset != nil {
|
||||
if parsedOffset, err := strconv.ParseInt(fmt.Sprint(offset), 0, 0); err == nil && parsedOffset > 0 {
|
||||
sql += fmt.Sprintf(" OFFSET %d", parsedOffset)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -127,16 +128,15 @@ func (s mssql) currentDatabase() (name string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (mssql) LimitAndOffsetSQL(limit, offset int) (sql string) {
|
||||
if limit > 0 || offset > 0 {
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
func (mssql) LimitAndOffsetSQL(limit, offset interface{}) (sql string) {
|
||||
if limit != nil {
|
||||
if parsedLimit, err := strconv.ParseInt(fmt.Sprint(limit), 0, 0); err == nil && parsedLimit > 0 {
|
||||
sql += fmt.Sprintf(" FETCH NEXT %d ROWS ONLY", parsedLimit)
|
||||
}
|
||||
|
||||
sql += fmt.Sprintf(" OFFSET %d ROWS", offset)
|
||||
|
||||
if limit >= 0 {
|
||||
sql += fmt.Sprintf(" FETCH NEXT %d ROWS ONLY", limit)
|
||||
}
|
||||
if offset != nil {
|
||||
if parsedOffset, err := strconv.ParseInt(fmt.Sprint(offset), 0, 0); err == nil && parsedOffset > 0 {
|
||||
sql += fmt.Sprintf(" OFFSET %d ROWS", parsedOffset)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
4
main.go
4
main.go
|
@ -156,12 +156,12 @@ func (s *DB) Not(query interface{}, args ...interface{}) *DB {
|
|||
}
|
||||
|
||||
// Limit specify the number of records to be retrieved
|
||||
func (s *DB) Limit(limit int) *DB {
|
||||
func (s *DB) Limit(limit interface{}) *DB {
|
||||
return s.clone().search.Limit(limit).db
|
||||
}
|
||||
|
||||
// Offset specify the number of records to skip before starting to return the records
|
||||
func (s *DB) Offset(offset int) *DB {
|
||||
func (s *DB) Offset(offset interface{}) *DB {
|
||||
return s.clone().search.Offset(offset).db
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ type search struct {
|
|||
omits []string
|
||||
orders []string
|
||||
preload []searchPreload
|
||||
offset int
|
||||
limit int
|
||||
offset interface{}
|
||||
limit interface{}
|
||||
group string
|
||||
tableName string
|
||||
raw bool
|
||||
|
@ -82,12 +82,12 @@ func (s *search) Omit(columns ...string) *search {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *search) Limit(limit int) *search {
|
||||
func (s *search) Limit(limit interface{}) *search {
|
||||
s.limit = limit
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *search) Offset(offset int) *search {
|
||||
func (s *search) Offset(offset interface{}) *search {
|
||||
s.offset = offset
|
||||
return s
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue