diff options
author | Bryan Helmkamp <bryan@brynary.com> | 2009-09-20 12:00:39 -0400 |
---|---|---|
committer | Bryan Helmkamp <bryan@brynary.com> | 2009-09-20 12:00:39 -0400 |
commit | 58920bc508a533d02140f4df3db25c3b9e1c7597 (patch) | |
tree | a27fcdd77290be44d495c4ff145df94fd130c9fa /lib/arel/engines | |
parent | 724b48620c5cf21920717d66eea6e7cd4148b535 (diff) | |
parent | 8852db7087a8f4f98e5fd26fa33bac14a5400979 (diff) | |
download | rails-58920bc508a533d02140f4df3db25c3b9e1c7597.tar.gz rails-58920bc508a533d02140f4df3db25c3b9e1c7597.tar.bz2 rails-58920bc508a533d02140f4df3db25c3b9e1c7597.zip |
Merge remote branch 'miloops/master' into miloops
Conflicts:
spec/connections/mysql_connection.rb
spec/connections/postgresql_connection.rb
spec/connections/sqlite3_connection.rb
Diffstat (limited to 'lib/arel/engines')
-rw-r--r-- | lib/arel/engines/sql/formatters.rb | 9 | ||||
-rw-r--r-- | lib/arel/engines/sql/primitives.rb | 2 | ||||
-rw-r--r-- | lib/arel/engines/sql/relations/operations/join.rb | 4 | ||||
-rw-r--r-- | lib/arel/engines/sql/relations/relation.rb | 24 | ||||
-rw-r--r-- | lib/arel/engines/sql/relations/writes.rb | 46 |
5 files changed, 72 insertions, 13 deletions
diff --git a/lib/arel/engines/sql/formatters.rb b/lib/arel/engines/sql/formatters.rb index ae80feb18e..626803a887 100644 --- a/lib/arel/engines/sql/formatters.rb +++ b/lib/arel/engines/sql/formatters.rb @@ -13,7 +13,6 @@ module Arel class SelectClause < Formatter def attribute(attribute) - # FIXME this should check that the column exists "#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}" + (attribute.alias ? " AS #{quote(attribute.alias.to_s)}" : "") end @@ -92,8 +91,12 @@ module Arel end def table(table) - quote_table_name(table.name) + - (table.name != name_for(table) ? " AS " + quote_table_name(name_for(table)) : '') + if table.name =~ /\s/ + table.name + else + quote_table_name(table.name) + + (table.name != name_for(table) ? " AS " + quote_table_name(name_for(table)) : '') + end end end diff --git a/lib/arel/engines/sql/primitives.rb b/lib/arel/engines/sql/primitives.rb index 16e1abdf59..6cce46a441 100644 --- a/lib/arel/engines/sql/primitives.rb +++ b/lib/arel/engines/sql/primitives.rb @@ -7,6 +7,8 @@ module Arel def to_sql(formatter = nil) self end + + include Attribute::Expressions end class Attribute diff --git a/lib/arel/engines/sql/relations/operations/join.rb b/lib/arel/engines/sql/relations/operations/join.rb index 7c5e13510a..a3aaaa163b 100644 --- a/lib/arel/engines/sql/relations/operations/join.rb +++ b/lib/arel/engines/sql/relations/operations/join.rb @@ -26,8 +26,8 @@ module Arel end class StringJoin < Join - def joins(_, __ = nil) - relation2 + def joins(environment, formatter = Sql::TableReference.new(environment)) + [relation1.joins(environment), relation2].compact.join(" ") end end end diff --git a/lib/arel/engines/sql/relations/relation.rb b/lib/arel/engines/sql/relations/relation.rb index 4cfb83a601..ed7f19ddbd 100644 --- a/lib/arel/engines/sql/relations/relation.rb +++ b/lib/arel/engines/sql/relations/relation.rb @@ -5,6 +5,26 @@ module Arel end def select_sql + if engine.adapter_name == "PostgreSQL" && !orders.blank? && using_distinct_on? + # PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this + # by wrapping the +sql+ string as a sub-select and ordering in that query. + order = order_clauses.join(', ').split(',').map { |s| s.strip }.reject(&:blank?) + order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{'DESC' if s =~ /\bdesc$/i}" }.join(', ') + + query = build_query \ + "SELECT #{select_clauses.to_s}", + "FROM #{table_sql(Sql::TableReference.new(self))}", + (joins(self) unless joins(self).blank? ), + ("WHERE #{where_clauses.join("\n\tAND ")}" unless wheres.blank? ), + ("GROUP BY #{group_clauses.join(', ')}" unless groupings.blank? ) + + build_query \ + "SELECT * FROM (#{query}) AS id_list", + "ORDER BY #{order}", + ("LIMIT #{taken}" unless taken.blank? ), + ("OFFSET #{skipped}" unless skipped.blank? ) + + else build_query \ "SELECT #{select_clauses.join(', ')}", "FROM #{table_sql(Sql::TableReference.new(self))}", @@ -14,6 +34,7 @@ module Arel ("ORDER BY #{order_clauses.join(', ')}" unless orders.blank? ), ("LIMIT #{taken}" unless taken.blank? ), ("OFFSET #{skipped}" unless skipped.blank? ) + end end def inclusion_predicate_sql @@ -46,5 +67,8 @@ module Arel orders.collect { |o| o.to_sql(Sql::OrderClause.new(self)) } end + def using_distinct_on? + select_clauses.any? { |x| x =~ /DISTINCT ON/ } + end end end diff --git a/lib/arel/engines/sql/relations/writes.rb b/lib/arel/engines/sql/relations/writes.rb index f1a9bfd2ac..d648a54d91 100644 --- a/lib/arel/engines/sql/relations/writes.rb +++ b/lib/arel/engines/sql/relations/writes.rb @@ -11,11 +11,17 @@ module Arel class Insert < Compound def to_sql(formatter = nil) + insertion_attributes_values_sql = if record.is_a?(Value) + record.value + else + build_query "(#{record.keys.collect { |key| engine.quote_column_name(key.name) }.join(', ')})", + "VALUES (#{record.collect { |key, value| key.format(value) }.join(', ')})" + end + build_query \ "INSERT", "INTO #{table_sql}", - "(#{record.keys.collect { |key| engine.quote_column_name(key.name) }.join(', ')})", - "VALUES (#{record.collect { |key, value| key.format(value) }.join(', ')})" + insertion_attributes_values_sql end end @@ -24,16 +30,40 @@ module Arel build_query \ "UPDATE #{table_sql} SET", assignment_sql, - ("WHERE #{wheres.collect(&:to_sql).join('\n\tAND ')}" unless wheres.blank? ), - ("LIMIT #{taken}" unless taken.blank? ) + build_update_conditions_sql end protected - def assignment_sql - assignments.collect do |attribute, value| - "#{engine.quote_column_name(attribute.name)} = #{attribute.format(value)}" - end.join(",\n") + if assignments.respond_to?(:collect) + assignments.collect do |attribute, value| + "#{engine.quote_column_name(attribute.name)} = #{attribute.format(value)}" + end.join(",\n") + else + assignments.value + end + end + + def build_update_conditions_sql + conditions = "" + conditions << " WHERE #{wheres.collect(&:to_sql).join('\n\tAND ')}" unless wheres.blank? + conditions << " ORDER BY #{order_clauses.join(', ')}" unless orders.blank? + + unless taken.blank? + conditions << " LIMIT #{taken}" + + if engine.adapter_name != "MySQL" + begin + quote_primary_key = engine.quote_column_name(table.name.classify.constantize.primary_key) + rescue NameError + quote_primary_key = engine.quote_column_name("id") + end + + conditions = "WHERE #{quote_primary_key} IN (SELECT #{quote_primary_key} FROM #{engine.connection.quote_table_name table.name} #{conditions})" + end + end + + conditions end end end |