aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBryan Helmkamp <bryan@brynary.com>2009-09-20 12:00:39 -0400
committerBryan Helmkamp <bryan@brynary.com>2009-09-20 12:00:39 -0400
commit58920bc508a533d02140f4df3db25c3b9e1c7597 (patch)
treea27fcdd77290be44d495c4ff145df94fd130c9fa /lib
parent724b48620c5cf21920717d66eea6e7cd4148b535 (diff)
parent8852db7087a8f4f98e5fd26fa33bac14a5400979 (diff)
downloadrails-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')
-rw-r--r--lib/arel.rb9
-rw-r--r--lib/arel/.DS_Storebin6148 -> 0 bytes
-rw-r--r--lib/arel/algebra/relations/relation.rb2
-rw-r--r--lib/arel/engines/sql/formatters.rb9
-rw-r--r--lib/arel/engines/sql/primitives.rb2
-rw-r--r--lib/arel/engines/sql/relations/operations/join.rb4
-rw-r--r--lib/arel/engines/sql/relations/relation.rb24
-rw-r--r--lib/arel/engines/sql/relations/writes.rb46
-rw-r--r--lib/arel/session.rb3
9 files changed, 78 insertions, 21 deletions
diff --git a/lib/arel.rb b/lib/arel.rb
index fcca60758e..c4069aa78e 100644
--- a/lib/arel.rb
+++ b/lib/arel.rb
@@ -1,10 +1,11 @@
-$LOAD_PATH.unshift(File.dirname(__FILE__))
+require 'active_support/inflector'
+require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/class/attribute_accessors'
-require 'rubygems'
-require 'activesupport'
-require 'activerecord'
+require 'active_record'
require 'active_record/connection_adapters/abstract/quoting'
+$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'arel/algebra'
require 'arel/engines'
require 'arel/session'
diff --git a/lib/arel/.DS_Store b/lib/arel/.DS_Store
deleted file mode 100644
index 9918127870..0000000000
--- a/lib/arel/.DS_Store
+++ /dev/null
Binary files differ
diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
index 9fdac26528..5403e40fae 100644
--- a/lib/arel/algebra/relations/relation.rb
+++ b/lib/arel/algebra/relations/relation.rb
@@ -110,7 +110,7 @@ module Arel
private
def matching_attributes(attribute)
(@matching_attributes ||= attributes.inject({}) do |hash, a|
- (hash[a.root] ||= []) << a
+ (hash[a.is_a?(Value) ? a.value : a.root] ||= []) << a
hash
end)[attribute.root] || []
end
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
diff --git a/lib/arel/session.rb b/lib/arel/session.rb
index 921ad0a7ac..cf04e8a93a 100644
--- a/lib/arel/session.rb
+++ b/lib/arel/session.rb
@@ -24,7 +24,6 @@ module Arel
module CRUD
def create(insert)
insert.call
- insert
end
def read(select)
@@ -35,12 +34,10 @@ module Arel
def update(update)
update.call
- update
end
def delete(delete)
delete.call
- delete
end
end
include CRUD