diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/arel/nodes.rb | 1 | ||||
-rw-r--r-- | lib/arel/nodes/lock.rb | 6 | ||||
-rw-r--r-- | lib/arel/nodes/named_function.rb | 2 | ||||
-rw-r--r-- | lib/arel/nodes/node.rb | 2 | ||||
-rw-r--r-- | lib/arel/nodes/unary.rb | 1 | ||||
-rw-r--r-- | lib/arel/predications.rb | 2 | ||||
-rw-r--r-- | lib/arel/select_manager.rb | 37 | ||||
-rw-r--r-- | lib/arel/visitors/mssql.rb | 7 | ||||
-rw-r--r-- | lib/arel/visitors/mysql.rb | 2 | ||||
-rw-r--r-- | lib/arel/visitors/postgresql.rb | 2 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 52 |
11 files changed, 60 insertions, 54 deletions
diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index 129c43b713..4b97e28668 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -1,6 +1,5 @@ # node require 'arel/nodes/node' -require 'arel/nodes/lock' require 'arel/nodes/select_statement' require 'arel/nodes/select_core' require 'arel/nodes/insert_statement' diff --git a/lib/arel/nodes/lock.rb b/lib/arel/nodes/lock.rb deleted file mode 100644 index e5fb258e26..0000000000 --- a/lib/arel/nodes/lock.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Arel - module Nodes - class Lock < Arel::Nodes::Node - end - end -end diff --git a/lib/arel/nodes/named_function.rb b/lib/arel/nodes/named_function.rb index 56669bf858..5fca33e323 100644 --- a/lib/arel/nodes/named_function.rb +++ b/lib/arel/nodes/named_function.rb @@ -3,6 +3,8 @@ module Arel class NamedFunction < Arel::Nodes::Function attr_accessor :name + include Arel::Predications + def initialize name, expr, aliaz = nil super(expr, aliaz) @name = name diff --git a/lib/arel/nodes/node.rb b/lib/arel/nodes/node.rb index 711fa34b6d..1a5bc27856 100644 --- a/lib/arel/nodes/node.rb +++ b/lib/arel/nodes/node.rb @@ -10,7 +10,7 @@ module Arel # Factory method to create a Nodes::Not node that has the recipient of # the caller as a child. def not - Nodes::Not.new Nodes::Grouping.new self + Nodes::Not.new self end ### diff --git a/lib/arel/nodes/unary.rb b/lib/arel/nodes/unary.rb index e1576b9c99..1b1dcb1053 100644 --- a/lib/arel/nodes/unary.rb +++ b/lib/arel/nodes/unary.rb @@ -18,6 +18,7 @@ module Arel Offset On Top + Lock }.each do |name| const_set(name, Class.new(Unary)) end diff --git a/lib/arel/predications.rb b/lib/arel/predications.rb index 58f02a2b53..920a9ee374 100644 --- a/lib/arel/predications.rb +++ b/lib/arel/predications.rb @@ -163,6 +163,7 @@ module Arel private def grouping_any method_id, others + others = others.dup first = send method_id, others.shift Nodes::Grouping.new others.inject(first) { |memo,expr| @@ -171,6 +172,7 @@ module Arel end def grouping_all method_id, others + others = others.dup first = send method_id, others.shift Nodes::Grouping.new others.inject(first) { |memo,expr| diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb index 0fa344945e..7f533fa91b 100644 --- a/lib/arel/select_manager.rb +++ b/lib/arel/select_manager.rb @@ -18,10 +18,19 @@ module Arel @ctx.wheres end + def offset + @ast.offset && @ast.offset.expr + end + def skip amount - @ast.offset = Nodes::Offset.new(amount) + if amount + @ast.offset = Nodes::Offset.new(amount) + else + @ast.offset = nil + end self end + alias :offset= :skip ### # Produces an Arel::Nodes::Exists node @@ -37,10 +46,16 @@ module Arel @ctx.wheres.map { |c| to_sql.accept c } end - def lock locking = true - # FIXME: do we even need to store this? If locking is +false+ shouldn't - # we just remove the node from the AST? - @ast.lock = Nodes::Lock.new + def lock locking = Arel.sql('FOR UPDATE') + case locking + when true + locking = Arel.sql('FOR UPDATE') + when Arel::Nodes::SqlLiteral + when String + locking = Arel.sql locking + end + + @ast.lock = Nodes::Lock.new(locking) self end @@ -161,13 +176,21 @@ module Arel node_class = Nodes::With end @ast.with = node_class.new(subqueries.flatten) + + self end def take limit - @ast.limit = Nodes::Limit.new(limit) - @ctx.top = Nodes::Top.new(limit) + if limit + @ast.limit = Nodes::Limit.new(limit) + @ctx.top = Nodes::Top.new(limit) + else + @ast.limit = nil + @ctx.top = nil + end self end + alias limit= take def join_sql return nil if @ctx.source.right.empty? diff --git a/lib/arel/visitors/mssql.rb b/lib/arel/visitors/mssql.rb index 9b0e77c19b..ea7ab6394c 100644 --- a/lib/arel/visitors/mssql.rb +++ b/lib/arel/visitors/mssql.rb @@ -3,6 +3,13 @@ module Arel class MSSQL < Arel::Visitors::ToSql private + def build_subselect key, o + stmt = super + core = stmt.cores.first + core.top = Nodes::Top.new(o.limit.expr) if o.limit + stmt + end + def visit_Arel_Nodes_Limit o "" end diff --git a/lib/arel/visitors/mysql.rb b/lib/arel/visitors/mysql.rb index e90161eee4..4f029245ac 100644 --- a/lib/arel/visitors/mysql.rb +++ b/lib/arel/visitors/mysql.rb @@ -3,7 +3,7 @@ module Arel class MySQL < Arel::Visitors::ToSql private def visit_Arel_Nodes_Lock o - "FOR UPDATE" + visit o.expr end ### diff --git a/lib/arel/visitors/postgresql.rb b/lib/arel/visitors/postgresql.rb index 0e82a703ca..c423dc6fc6 100644 --- a/lib/arel/visitors/postgresql.rb +++ b/lib/arel/visitors/postgresql.rb @@ -3,7 +3,7 @@ module Arel class PostgreSQL < Arel::Visitors::ToSql private def visit_Arel_Nodes_Lock o - "FOR UPDATE" + visit o.expr end def visit_Arel_Nodes_SelectStatement o diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 376d1460db..7eaaff8e13 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -11,14 +11,6 @@ module Arel @last_column = nil @quoted_tables = {} @quoted_columns = {} - @column_cache = Hash.new { |h,pool| - h[pool] = Hash.new { |conn_h,column| - conn_h[column] = {} - } - } - @table_exists = Hash.new { |h,pool| - h[pool] = {} - } end def accept object @@ -38,6 +30,17 @@ module Arel ].compact.join ' ' end + # FIXME: we should probably have a 2-pass visitor for this + def build_subselect key, o + stmt = Nodes::SelectStatement.new + core = stmt.cores.first + core.froms = o.relation + core.projections = [key] + stmt.limit = o.limit + stmt.orders = o.orders + stmt + end + def visit_Arel_Nodes_UpdateStatement o if o.orders.empty? && o.limit.nil? wheres = o.wheres @@ -52,15 +55,7 @@ key on UpdateManager using UpdateManager#key= key = o.relation.primary_key end - wheres = o.wheres - stmt = Nodes::SelectStatement.new - core = stmt.cores.first - core.froms = o.relation - core.projections = [key] - stmt.limit = o.limit - stmt.orders = o.orders - - wheres = [Nodes::In.new(key, [stmt])] + wheres = [Nodes::In.new(key, [build_subselect(key, o)])] end [ @@ -88,37 +83,20 @@ key on UpdateManager using UpdateManager#key= end def table_exists? name - return true if table_exists.key? name - - @connection.tables.each do |table| - table_exists[table] = true - end - - table_exists.key? name - end - - def table_exists - @table_exists[@pool] + @pool.table_exists? name end def column_for attr - name = attr.name.to_sym + name = attr.name.to_s table = attr.relation.name return nil unless table_exists? table - # If we don't have this column cached, get a list of columns and - # cache them for this table - unless column_cache.key? table - columns = @connection.columns(table, "#{table}(#{name}) Columns") - column_cache[table] = Hash[columns.map { |c| [c.name.to_sym, c] }] - end - column_cache[table][name] end def column_cache - @column_cache[@pool] + @pool.columns_hash end def visit_Arel_Nodes_Values o |