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