@@ -287,41 +287,37 @@ def rollback_db_transaction
287287 end
288288
289289 def add_limit_offset! ( sql , options )
290+ # Validate and/or convert integers for :limit and :offets options.
290291 if options [ :offset ]
291292 raise ArgumentError , "offset should have a limit" unless options [ :limit ]
292- unless options [ :offset ] . kind_of? Integer
293+ unless options [ :offset ] . kind_of? ( Integer )
293294 if options [ :offset ] =~ /^\d +$/
294295 options [ :offset ] = options [ :offset ] . to_i
295296 else
296297 raise ArgumentError , "offset should be an integer"
297298 end
298299 end
299300 end
300-
301- if options [ :limit ] && !( options [ :limit ] . kind_of? Integer )
302- # is it just a string which should be an integer?
301+ if options [ :limit ] && !( options [ :limit ] . kind_of? ( Integer ) )
303302 if options [ :limit ] =~ /^\d +$/
304303 options [ :limit ] = options [ :limit ] . to_i
305304 else
306305 raise ArgumentError , "limit should be an integer"
307306 end
308307 end
309-
308+ # The buisiness of adding limit/offset
310309 if options [ :limit ] and options [ :offset ]
311- total_rows = raw_connection . select_all ( "SELECT count(*) as TotalRows from (#{ sql . gsub ( /\b SELECT(\s +DISTINCT)?\b /i , "SELECT#{ $1} TOP 1000000000" ) } ) tally" ) [ 0 ] [ :TotalRows ] . to_i
310+ total_rows = select_value ( "SELECT count(*) as TotalRows from (#{ sql . gsub ( /\b SELECT(\s +DISTINCT)?\b /i , "SELECT#{ $1} TOP 1000000000" ) } ) tally" ) . to_i
312311 if ( options [ :limit ] + options [ :offset ] ) >= total_rows
313312 options [ :limit ] = ( total_rows - options [ :offset ] >= 0 ) ? ( total_rows - options [ :offset ] ) : 0
314313 end
315-
316314 # Wrap the SQL query in a bunch of outer SQL queries that emulate proper LIMIT,OFFSET support.
317315 sql . sub! ( /^\s *SELECT(\s +DISTINCT)?/i , "SELECT * FROM (SELECT TOP #{ options [ :limit ] } * FROM (SELECT#{ $1} TOP #{ options [ :limit ] + options [ :offset ] } " )
318316 sql << ") AS tmp1"
319-
320317 if options [ :order ]
321318 order = options [ :order ] . split ( ',' ) . map do |field |
322319 order_by_column , order_direction = field . split ( " " )
323320 order_by_column = quote_column_name ( order_by_column )
324-
325321 # Investigate the SQL query to figure out if the order_by_column has been renamed.
326322 if sql =~ /#{ Regexp . escape ( order_by_column ) } AS (t\d _r\d \d ?)/
327323 # Fx "[foo].[bar] AS t4_r2" was found in the SQL. Use the column alias (ie 't4_r2') for the subsequent orderings
@@ -333,19 +329,22 @@ def add_limit_offset!(sql, options)
333329 # name rather than the full identifier for the outer queries.
334330 order_by_column = order_by_column . split ( '.' ) . last
335331 end
336-
337332 # Put the column name and eventual direction back together
338333 [ order_by_column , order_direction ] . join ( ' ' ) . strip
339334 end . join ( ', ' )
340-
341335 sql << " ORDER BY #{ change_order_direction ( order ) } ) AS tmp2 ORDER BY #{ order } "
342336 else
343337 sql << ") AS tmp2"
344338 end
345339 elsif sql !~ /^\s *SELECT (@@|COUNT\( )/i
346- sql . sub! ( /^\s *SELECT(\s +DISTINCT)?/i ) do
347- "SELECT#{ $1} TOP #{ options [ :limit ] } "
348- end unless options [ :limit ] . nil? || options [ :limit ] < 1
340+ unless options [ :limit ] . nil? || options [ :limit ] < 1
341+ if md = sql . match ( /^(\s *SELECT)(\s +DISTINCT)?(.*)/im )
342+ sql . replace "#{ md [ 1 ] } #{ md [ 2 ] } TOP #{ options [ :limit ] } #{ md [ 3 ] } "
343+ else
344+ # Account for building SQL fragments without SELECT yet. See #update_all and #limited_update_conditions.
345+ sql . replace "TOP #{ options [ :limit ] } #{ sql } "
346+ end
347+ end
349348 end
350349 end
351350
@@ -365,6 +364,13 @@ def case_sensitive_equality_operator
365364 "COLLATE Latin1_General_CS_AS ="
366365 end
367366
367+ def limited_update_conditions ( where_sql , quoted_table_name , quoted_primary_key )
368+ match_data = where_sql . match ( /(.*)WHERE/ )
369+ limit = match_data [ 1 ]
370+ where_sql . sub! ( limit , '' )
371+ "WHERE #{ quoted_primary_key } IN (SELECT #{ limit } #{ quoted_primary_key } FROM #{ quoted_table_name } #{ where_sql } )"
372+ end
373+
368374 # SCHEMA STATEMENTS ========================================#
369375
370376 def native_database_types
0 commit comments