Skip to content

Commit

Permalink
Use validated interface{} for limit/offset values to ensure values gr…
Browse files Browse the repository at this point in the history
…eater than

max 32-bit integer are addressable, and in a backwards-compatible way.
  • Loading branch information
jaytaylor committed Jun 23, 2016
1 parent caa7926 commit 1485f4b
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 22 deletions.
2 changes: 1 addition & 1 deletion dialect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
15 changes: 9 additions & 6 deletions dialect_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
Expand Down Expand Up @@ -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
Expand Down
18 changes: 9 additions & 9 deletions dialects/mssql/mssql.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"database/sql"
"fmt"
"reflect"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
8 changes: 4 additions & 4 deletions search.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit 1485f4b

Please sign in to comment.