From 84b89289a3bc95f1d27860b222ae2abc73cd5fa5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 6 May 2014 11:11:44 +0800 Subject: [PATCH] start & limit implementation for mssql --- statement.go | 53 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/statement.go b/statement.go index 02078cb9..5185c91e 100644 --- a/statement.go +++ b/statement.go @@ -974,20 +974,52 @@ func (statement *Statement) genSelectSql(columnStr string) (a string) { distinct = "DISTINCT " } - // !nashtsai! REVIEW Sprintf is considered slowest mean of string concatnation, better to work with builder pattern - a = fmt.Sprintf("SELECT %v%v FROM %v", distinct, columnStr, - statement.Engine.Quote(statement.TableName())) - if statement.JoinStr != "" { - a = fmt.Sprintf("%v %v", a, statement.JoinStr) + var top string + var mssqlCondi string + var orderBy string + if statement.OrderStr != "" { + orderBy = fmt.Sprintf(" ORDER BY %v", statement.OrderStr) } statement.processIdParam() + var whereStr string if statement.WhereStr != "" { - a = fmt.Sprintf("%v WHERE %v", a, statement.WhereStr) + whereStr = fmt.Sprintf(" WHERE %v", statement.WhereStr) if statement.ConditionStr != "" { - a = fmt.Sprintf("%v AND %v", a, statement.ConditionStr) + whereStr = fmt.Sprintf("%v AND %v", whereStr, statement.ConditionStr) } } else if statement.ConditionStr != "" { - a = fmt.Sprintf("%v WHERE %v", a, statement.ConditionStr) + whereStr = fmt.Sprintf(" WHERE %v", statement.ConditionStr) + } + var fromStr string = " FROM " + statement.Engine.Quote(statement.TableName()) + if statement.JoinStr != "" { + fromStr = fmt.Sprintf("%v %v", fromStr, statement.JoinStr) + } + + if statement.Engine.dialect.DBType() == core.MSSQL { + top = fmt.Sprintf(" TOP %d", statement.LimitN) + if statement.Start > 0 { + var column string = "(id)" + if len(statement.RefTable.PKColumns()) == 0 { + for _, index := range statement.RefTable.Indexes { + if len(index.Cols) == 1 { + column = index.Cols[0] + break + } + } + if len(column) == 0 { + column = statement.RefTable.ColumnsSeq()[0] + } + } + mssqlCondi = fmt.Sprintf("(%s NOT IN (SELECT TOP %d %s%s%s%s))", + column, statement.Start, column, fromStr, whereStr, orderBy) + } + } + + // !nashtsai! REVIEW Sprintf is considered slowest mean of string concatnation, better to work with builder pattern + a = fmt.Sprintf("SELECT %v%v%v%v%v", top, distinct, columnStr, + fromStr, whereStr) + if mssqlCondi != "" { + a += " AND " + mssqlCondi } if statement.GroupByStr != "" { @@ -1005,11 +1037,6 @@ func (statement *Statement) genSelectSql(columnStr string) (a string) { } else if statement.LimitN > 0 { a = fmt.Sprintf("%v LIMIT %v", a, statement.LimitN) } - } else { - //TODO: for mssql, should handler limit. - /*SELECT * FROM ( - SELECT *, ROW_NUMBER() OVER (ORDER BY id desc) as row FROM "userinfo" - ) a WHERE row > [start] and row <= [start+limit] order by id desc*/ } return