@@ -469,18 +469,28 @@ def quote_string(string)
469469 string . gsub ( /\' / , "''" )
470470 end
471471
472+ # If name is on the form "foo.bar.baz"
472473 def quote_table_name ( name )
473- if name . split ( "." ) . length == 3
474- b = name . split ( "." )
474+ if name . to_s . split ( "." ) . length == 3
475+ b = name . to_s . split ( "." )
475476 "[#{ b [ 0 ] } ].[#{ b [ 1 ] } ].[#{ b [ 2 ] } ]"
476477 else
477478 super ( name )
478479 end
479480
480481 end
481482
482- def quote_column_name ( name )
483- "[#{ name } ]"
483+ # Quotes the given column identifier.
484+ #
485+ # Examples
486+ #
487+ # quote_column_name('foo') # => '[foo]'
488+ # quote_column_name(:foo) # => '[foo]'
489+ # quote_column_name('foo.bar') # => '[foo].[bar]'
490+ def quote_column_name ( identifier )
491+ identifier . to_s . split ( '.' ) . collect do |name |
492+ "[#{ name } ]"
493+ end . join ( "." )
484494 end
485495
486496 def add_limit_offset! ( sql , options )
@@ -509,26 +519,32 @@ def add_limit_offset!(sql, options)
509519 if ( options [ :limit ] + options [ :offset ] ) >= total_rows
510520 options [ :limit ] = ( total_rows - options [ :offset ] >= 0 ) ? ( total_rows - options [ :offset ] ) : 0
511521 end
522+
523+ # Wrap the SQL query in a bunch of outer SQL queries that emulate proper LIMIT,OFFSET support.
512524 sql . sub! ( /^\s *SELECT(\s +DISTINCT)?/i , "SELECT * FROM (SELECT TOP #{ options [ :limit ] } * FROM (SELECT#{ $1} TOP #{ options [ :limit ] + options [ :offset ] } " )
513525 sql << ") AS tmp1"
526+
514527 if options [ :order ]
515- # don't strip the table name, it is needed later on
516- #options[:order] = options[:order].split(',').map do |field|
517528 order = options [ :order ] . split ( ',' ) . map do |field |
518- parts = field . split ( " " )
519- # tc = column_name etc (not direction of sort)
520- tc = parts [ 0 ]
521- #if sql =~ /\.\[/ and tc =~ /\./ # if column quoting used in query
522- # tc.gsub!(/\./, '\\.\\[')
523- # tc << '\\]'
524- #end
525- if sql =~ /#{ Regexp . escape ( tc ) } AS (t\d _r\d \d ?)/
526- parts [ 0 ] = $1
527- elsif parts [ 0 ] =~ /\w +\. \[ ?(\w +)\] ?/
528- parts [ 0 ] = $1
529+ order_by_column , order_direction = field . split ( " " )
530+ order_by_column = quote_column_name ( order_by_column )
531+
532+ # Investigate the SQL query to figure out if the order_by_column has been renamed.
533+ if sql =~ /#{ Regexp . escape ( order_by_column ) } AS (t\d _r\d \d ?)/
534+ # Fx "[foo].[bar] AS t4_r2" was found in the SQL. Use the column alias (ie 't4_r2') for the subsequent orderings
535+ order_by_column = $1
536+ elsif order_by_column =~ /\w +\. \[ ?(\w +)\] ?/
537+ order_by_column = $1
538+ else
539+ # It doesn't appear that the column name has been renamed as part of the query. Use just the column
540+ # name rather than the full identifier for the outer queries.
541+ order_by_column = order_by_column . split ( '.' ) . last
529542 end
530- parts . join ( ' ' )
543+
544+ # Put the column name and eventual direction back together
545+ [ order_by_column , order_direction ] . join ( ' ' ) . strip
531546 end . join ( ', ' )
547+
532548 sql << " ORDER BY #{ change_order_direction ( order ) } ) AS tmp2 ORDER BY #{ order } "
533549 else
534550 sql << ") AS tmp2"
0 commit comments