提交 1a246f71 编写于 作者: V Viacheslav Petrenko 提交者: Aaron Patterson

Patched Arel v2.0.6 to support MSSQL SQL queries. Based on work of James Abley...

Patched Arel v2.0.6 to support MSSQL SQL queries. Based on work of James Abley (https://github.com/jabley/arel).
上级 ee3c55c8
......@@ -24,6 +24,8 @@
require 'arel/nodes/count'
require 'arel/nodes/values'
require 'arel/nodes/offset'
require 'arel/nodes/limit'
require 'arel/nodes/top'
require 'arel/nodes/sum'
require 'arel/nodes/exists'
require 'arel/nodes/max'
......
module Arel
module Nodes
class Limit < Arel::Nodes::Unary
end
end
end
module Arel
module Nodes
class SelectCore < Arel::Nodes::Node
attr_accessor :froms, :projections, :wheres, :groups
attr_accessor :top, :froms, :projections, :wheres, :groups
attr_accessor :having
def initialize
@top = nil
@froms = nil
@projections = []
@wheres = []
......
module Arel
module Nodes
class Top < Arel::Nodes::Unary
end
end
end
......@@ -10,7 +10,7 @@ def initialize engine, table = nil
end
def taken
@ast.limit
@ast.limit && @ast.limit.expr
end
def constraints
......@@ -131,7 +131,8 @@ def where_sql
end
def take limit
@ast.limit = limit
@ast.limit = Nodes::Limit.new(limit)
@ctx.top = Nodes::Top.new(limit)
self
end
......
......@@ -4,6 +4,7 @@
require 'arel/visitors/sqlite'
require 'arel/visitors/postgresql'
require 'arel/visitors/mysql'
require 'arel/visitors/mssql'
require 'arel/visitors/oracle'
require 'arel/visitors/join_sql'
require 'arel/visitors/where_sql'
......@@ -16,6 +17,8 @@ module 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,
......
module Arel
module Visitors
class MSSQL < Arel::Visitors::ToSql
private
def visit_Arel_Nodes_Limit o
""
end
def visit_Arel_Nodes_Top o
"TOP #{visit o.expr}"
end
end
end
end
......@@ -10,7 +10,7 @@ def visit_Arel_Nodes_Lock o
# :'(
# http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
def visit_Arel_Nodes_SelectStatement o
o.limit = 18446744073709551615 if o.offset && !o.limit
o.limit = Arel::Nodes::Limit.new(18446744073709551615) if o.offset && !o.limit
super
end
......
......@@ -3,7 +3,7 @@ module Visitors
class SQLite < Arel::Visitors::ToSql
private
def visit_Arel_Nodes_SelectStatement o
o.limit = -1 if o.offset && !o.limit
o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit
super
end
end
......
......@@ -76,7 +76,7 @@ def visit_Arel_Nodes_SelectStatement o
[
o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
("LIMIT #{visit o.limit}" if o.limit),
(visit(o.limit) if o.limit),
(visit(o.offset) if o.offset),
(visit(o.lock) if o.lock),
].compact.join ' '
......@@ -84,7 +84,9 @@ def visit_Arel_Nodes_SelectStatement o
def visit_Arel_Nodes_SelectCore o
[
"SELECT #{o.projections.map { |x| visit x }.join ', '}",
"SELECT",
(visit(o.top) if o.top),
"#{o.projections.map { |x| visit x }.join ', '}",
("FROM #{visit o.froms}" if o.froms),
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
......@@ -100,6 +102,15 @@ def visit_Arel_Nodes_Offset o
"OFFSET #{visit o.expr}"
end
def visit_Arel_Nodes_Limit o
"LIMIT #{visit o.expr}"
end
# FIXME: this does nothing on most databases, but does on MSSQL
def visit_Arel_Nodes_Top o
""
end
# FIXME: this does nothing on SQLLite3, but should do things on other
# databases.
def visit_Arel_Nodes_Lock o
......
require 'helper'
module Arel
module Visitors
describe 'the mssql visitor' do
before do
@visitor = MSSQL.new Table.engine
end
it 'uses TOP to limit results' do
stmt = Nodes::SelectStatement.new
stmt.cores.last.top = Nodes::Top.new(1)
sql = @visitor.accept(stmt)
sql.must_be_like "SELECT TOP 1"
end
end
end
end
......@@ -32,7 +32,7 @@ module Visitors
it "should escape LIMIT" do
sc = Arel::Nodes::SelectStatement.new
sc.limit = "omg"
sc.limit = Arel::Nodes::Limit.new("omg")
assert_match(/LIMIT 'omg'/, @visitor.accept(sc))
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册