@@ -18,7 +18,8 @@ import (
18
18
)
19
19
20
20
var (
21
- selectSqlTmp = `SELECT * FROM (SELECT TOP %d * FROM (SELECT TOP %d %s) as TMP1_ ) as TMP2_ `
21
+ orderBySqlTmp = `SELECT %s %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY`
22
+ withoutOrderBySqlTmp = `SELECT %s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY`
22
23
selectWithOrderSqlTmp = `
23
24
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_
24
25
WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d
@@ -78,89 +79,55 @@ func (d *Driver) parseSql(toBeCommittedSql string) (string, error) {
78
79
79
80
func (d * Driver ) handleSelectSqlReplacement (toBeCommittedSql string ) (newSql string , err error ) {
80
81
// SELECT * FROM USER WHERE ID=1 LIMIT 1
81
- match , err := gregex .MatchString (`^SELECT(.+)LIMIT 1$` , toBeCommittedSql )
82
+ match , err := gregex .MatchString (`^SELECT(.+? )LIMIT\s+ 1$` , toBeCommittedSql )
82
83
if err != nil {
83
84
return "" , err
84
85
}
85
86
if len (match ) > 1 {
86
- return fmt .Sprintf (`SELECT TOP 1 %s` , match [1 ]), nil
87
+ return fmt .Sprintf (`SELECT TOP 1 %s` , strings . TrimSpace ( match [1 ]) ), nil
87
88
}
88
89
89
90
// SELECT * FROM USER WHERE AGE>18 ORDER BY ID DESC LIMIT 100, 200
90
- patten := `^\s* (?i)( SELECT)|( LIMIT\s*(\d+)\s*,\s*(\d+))`
91
- if gregex .IsMatchString (patten , toBeCommittedSql ) == false {
91
+ pattern := `(?i)SELECT(.+?)(ORDER BY.+?)?\s* LIMIT\s*(\d+)(?: \s*,\s*(\d+))? `
92
+ if ! gregex .IsMatchString (pattern , toBeCommittedSql ) {
92
93
return toBeCommittedSql , nil
93
94
}
94
- allMatch , err := gregex .MatchAllString (patten , toBeCommittedSql )
95
+
96
+ allMatch , err := gregex .MatchString (pattern , toBeCommittedSql )
95
97
if err != nil {
96
98
return "" , err
97
99
}
98
- var index = 1
99
- // LIMIT statement checks.
100
- if len (allMatch ) < 2 ||
101
- (strings .HasPrefix (allMatch [index ][0 ], "LIMIT" ) == false &&
102
- strings .HasPrefix (allMatch [index ][0 ], "limit" ) == false ) {
103
- return toBeCommittedSql , nil
104
- }
105
- if gregex .IsMatchString ("((?i)SELECT)(.+)((?i)LIMIT)" , toBeCommittedSql ) == false {
106
- return toBeCommittedSql , nil
100
+
101
+ // SELECT and ORDER BY
102
+ selectStr := strings .TrimSpace (allMatch [1 ])
103
+ orderStr := ""
104
+ if len (allMatch [2 ]) > 0 {
105
+ orderStr = strings .TrimSpace (allMatch [2 ])
107
106
}
108
- // ORDER BY statement checks.
109
- var (
110
- selectStr = ""
111
- orderStr = ""
112
- haveOrder = gregex .IsMatchString ("((?i)SELECT)(.+)((?i)ORDER BY)" , toBeCommittedSql )
113
- )
114
- if haveOrder {
115
- queryExpr , _ := gregex .MatchString ("((?i)SELECT)(.+)((?i)ORDER BY)" , toBeCommittedSql )
116
- if len (queryExpr ) != 4 ||
117
- strings .EqualFold (queryExpr [1 ], "SELECT" ) == false ||
118
- strings .EqualFold (queryExpr [3 ], "ORDER BY" ) == false {
119
- return toBeCommittedSql , nil
120
- }
121
- selectStr = queryExpr [2 ]
122
- orderExpr , _ := gregex .MatchString ("((?i)ORDER BY)(.+)((?i)LIMIT)" , toBeCommittedSql )
123
- if len (orderExpr ) != 4 ||
124
- strings .EqualFold (orderExpr [1 ], "ORDER BY" ) == false ||
125
- strings .EqualFold (orderExpr [3 ], "LIMIT" ) == false {
126
- return toBeCommittedSql , nil
127
- }
128
- orderStr = orderExpr [2 ]
107
+
108
+ // LIMIT and OFFSET value
109
+ first , _ := strconv .Atoi (allMatch [3 ]) // LIMIT first parameter
110
+ limit := 0
111
+ if len (allMatch ) > 4 && allMatch [4 ] != "" {
112
+ limit , _ = strconv .Atoi (allMatch [4 ]) // LIMIT second parameter
129
113
} else {
130
- queryExpr , _ := gregex .MatchString ("((?i)SELECT)(.+)((?i)LIMIT)" , toBeCommittedSql )
131
- if len (queryExpr ) != 4 ||
132
- strings .EqualFold (queryExpr [1 ], "SELECT" ) == false ||
133
- strings .EqualFold (queryExpr [3 ], "LIMIT" ) == false {
134
- return toBeCommittedSql , nil
135
- }
136
- selectStr = queryExpr [2 ]
114
+ limit = first
115
+ first = 0
137
116
}
138
- first , limit := 0 , 0
139
- for i := 1 ; i < len (allMatch [index ]); i ++ {
140
- if len (strings .TrimSpace (allMatch [index ][i ])) == 0 {
141
- continue
142
- }
143
- if strings .HasPrefix (allMatch [index ][i ], "LIMIT" ) ||
144
- strings .HasPrefix (allMatch [index ][i ], "limit" ) {
145
- first , _ = strconv .Atoi (allMatch [index ][i + 1 ])
146
- limit , _ = strconv .Atoi (allMatch [index ][i + 2 ])
147
- break
148
- }
149
- }
150
- if haveOrder {
151
- toBeCommittedSql = fmt .Sprintf (
152
- selectWithOrderSqlTmp ,
153
- orderStr , selectStr , first , first + limit ,
117
+
118
+ if orderStr != "" {
119
+ // have ORDER BY clause
120
+ newSql = fmt .Sprintf (
121
+ orderBySqlTmp ,
122
+ selectStr , orderStr , first , limit ,
123
+ )
124
+ } else {
125
+ // without ORDER BY clause
126
+ newSql = fmt .Sprintf (
127
+ withoutOrderBySqlTmp ,
128
+ selectStr , first , limit ,
154
129
)
155
- return toBeCommittedSql , nil
156
130
}
157
131
158
- if first == 0 {
159
- first = limit
160
- }
161
- toBeCommittedSql = fmt .Sprintf (
162
- selectSqlTmp ,
163
- limit , first + limit , selectStr ,
164
- )
165
- return toBeCommittedSql , nil
132
+ return newSql , nil
166
133
}
0 commit comments