rails/arel — pull request #319 by yahonda (2014-09-25 20:20:01+00:00)
Title: Support Oracle 12c top-N query 

This pull request has two separate commits to support Oracle 12c better Top N query support using `FETCH FIRST n ROWS ONLY` and `OFFSET n ROWS`.

c6a31ee3587d6298cb1a4939fb79292e3fa231c0 Extract visit_Arel_Nodes_SelectOptions

It extracts `visit_Arel_Nodes_SelectOptions` from `visit_Arel_Nodes_SelectStatement` method to prepare Oracle 12c support since it will be able to reuse most of super's `visit_Arel_Nodes_SelectStatement` method because Oracle requires to add collector in the following order.
```
offset
limit
lock
```
Unlike other database require in this order.
```
limit
offset
lock
```

This method is not called using visitor pattern, I'd like to hear `visit_Arel_Nodes_SelectOptions` is an appropreate method name.

a19190ab06db4d68765fb08ec1a4dc6c8ebb2eb5	Create Arel::Visitors::Oracle12 to provide better top-N query

Oracle Database 12c introduces better top-N query support using `FETCH FIRST n ROWS ONLY` and `OFFSET n ROWS`. Also to support older version of Oracle 11gR2 or lower version, this commit creates
another visitor named `Arel::Visitors::Oracle12`, 12 comes from the database version.

By changing oracle enhanced adapter as follows to execute each Arel visitor based on
if this top-n query feature supported. https://github.com/yahonda/oracle-enhanced/commit/fcb22dbae0cd6f5baf8c68c57cff8d2c9f5b7c18

```ruby
if supports_fetch_first_n_rows_and_offset?
@visitor = Arel::Visitors::Oracle12.new self
else
@visitor = Arel::Visitors::Oracle.new self
end
```

It looks `Arel::Visitors` just allows 1 database adapter to have 1 visitor, but my implementation works to switch two visitors just changing `Arel::Visitors::Oracle12` or `Arel::Visitors::Oracle` based on its database version. It looks 1 database adapter can have 2 or more visitor(s). Are these lines can be removed?
https://github.com/yahonda/arel/blob/a19190ab06db4d68765fb08ec1a4dc6c8ebb2eb5/lib/arel/visitors.rb#L15-L41

```ruby

module Arel
module Visitors
VISITORS = {
'postgresql' => Arel::Visitors::PostgreSQL,
'mysql' => Arel::Visitors::MySQL,
'mysql2' => Arel::Visitors::MySQL,
'mssql' => Arel::Visitors::MSSQL,
'sqlserver' => Arel::Visitors::MSSQL,
'oracle_enhanced' => Arel::Visitors::Oracle,
'sqlite' => Arel::Visitors::SQLite,
'sqlite3' => Arel::Visitors::SQLite,
'ibm_db' => Arel::Visitors::IBM_DB,
'informix' => Arel::Visitors::Informix,
}

ENGINE_VISITORS = Hash.new do |hash, engine|
pool = engine.connection_pool
adapter = pool.spec.config[:adapter]
hash[engine] = (VISITORS[adapter] || Visitors::ToSql).new(engine)
end

def self.visitor_for engine
ENGINE_VISITORS[engine]
end
class << self; alias :for :visitor_for; end
end
end
```