diff options
author | Bryan Helmkamp <bryan@brynary.com> | 2009-05-17 14:58:46 -0400 |
---|---|---|
committer | Bryan Helmkamp <bryan@brynary.com> | 2009-05-17 14:58:46 -0400 |
commit | 4e3c9a01307339916f6b947d24f19b0f442afd78 (patch) | |
tree | 21d75fb31b0c920deaeb8eb0d8c71e84525dca50 /lib | |
parent | 437429764510338bdc5f4915286425f07565a573 (diff) | |
download | rails-4e3c9a01307339916f6b947d24f19b0f442afd78.tar.gz rails-4e3c9a01307339916f6b947d24f19b0f442afd78.tar.bz2 rails-4e3c9a01307339916f6b947d24f19b0f442afd78.zip |
most in memory operations save join and group
Conflicts:
lib/arel/algebra/extensions/object.rb
lib/arel/algebra/primitives/value.rb
lib/arel/engines/memory/relations.rb
lib/arel/engines/sql/formatters.rb
lib/arel/engines/sql/primitives.rb
spec/arel/unit/relations/alias_spec.rb
spec/arel/unit/relations/array_spec.rb
spec/arel/unit/relations/order_spec.rb
Diffstat (limited to 'lib')
-rw-r--r-- | lib/arel/algebra/extensions/array.rb | 7 | ||||
-rw-r--r-- | lib/arel/algebra/extensions/hash.rb | 7 | ||||
-rw-r--r-- | lib/arel/algebra/extensions/object.rb | 5 | ||||
-rw-r--r-- | lib/arel/algebra/primitives.rb | 1 | ||||
-rw-r--r-- | lib/arel/algebra/primitives/attribute.rb | 17 | ||||
-rw-r--r-- | lib/arel/algebra/primitives/ordering.rb | 18 | ||||
-rw-r--r-- | lib/arel/algebra/primitives/value.rb | 8 | ||||
-rw-r--r-- | lib/arel/algebra/relations/operations/order.rb | 3 | ||||
-rw-r--r-- | lib/arel/engines/memory/primitives.rb | 14 | ||||
-rw-r--r-- | lib/arel/engines/memory/relations.rb | 1 | ||||
-rw-r--r-- | lib/arel/engines/memory/relations/compound.rb | 5 | ||||
-rw-r--r-- | lib/arel/engines/memory/relations/operations.rb | 33 | ||||
-rw-r--r-- | lib/arel/engines/sql/formatters.rb | 6 | ||||
-rw-r--r-- | lib/arel/engines/sql/primitives.rb | 14 | ||||
-rw-r--r-- | lib/arel/engines/sql/relations/utilities/compound.rb | 2 |
15 files changed, 130 insertions, 11 deletions
diff --git a/lib/arel/algebra/extensions/array.rb b/lib/arel/algebra/extensions/array.rb index 5b6d6d6abd..935569a07b 100644 --- a/lib/arel/algebra/extensions/array.rb +++ b/lib/arel/algebra/extensions/array.rb @@ -2,4 +2,11 @@ class Array def to_hash Hash[*flatten] end + + def group_by + inject({}) do |groups, element| + (groups[yield(element)] ||= []) << element + groups + end + end end
\ No newline at end of file diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb index 7472b5aa73..bc97785e62 100644 --- a/lib/arel/algebra/extensions/hash.rb +++ b/lib/arel/algebra/extensions/hash.rb @@ -4,4 +4,11 @@ class Hash bound.merge(key.bind(relation) => value.bind(relation)) end end + + def slice(*attributes) + inject({}) do |cheese, (key, value)| + cheese[key] = value if attributes.include?(key) + cheese + end + end end
\ No newline at end of file diff --git a/lib/arel/algebra/extensions/object.rb b/lib/arel/algebra/extensions/object.rb index d626407dcb..efdbbf525f 100644 --- a/lib/arel/algebra/extensions/object.rb +++ b/lib/arel/algebra/extensions/object.rb @@ -12,4 +12,9 @@ class Object self end end + + def let + yield(self) + end end + diff --git a/lib/arel/algebra/primitives.rb b/lib/arel/algebra/primitives.rb index a4c3169e0b..df8d16a5d5 100644 --- a/lib/arel/algebra/primitives.rb +++ b/lib/arel/algebra/primitives.rb @@ -1,4 +1,5 @@ require 'arel/algebra/primitives/attribute' +require 'arel/algebra/primitives/ordering' require 'arel/algebra/primitives/value' require 'arel/algebra/primitives/expression' diff --git a/lib/arel/algebra/primitives/attribute.rb b/lib/arel/algebra/primitives/attribute.rb index 943c5b030e..7a4411e248 100644 --- a/lib/arel/algebra/primitives/attribute.rb +++ b/lib/arel/algebra/primitives/attribute.rb @@ -17,6 +17,10 @@ module Arel def aggregation? false end + + def inspect + "<Attribute #{name}>" + end module Transformations def self.included(klass) @@ -129,5 +133,18 @@ module Arel end end include Expressions + + module Orderings + def asc + Ascending.new(self) + end + + def desc + Descending.new(self) + end + + alias_method :to_ordering, :asc + end + include Orderings end end diff --git a/lib/arel/algebra/primitives/ordering.rb b/lib/arel/algebra/primitives/ordering.rb new file mode 100644 index 0000000000..e8d8f97188 --- /dev/null +++ b/lib/arel/algebra/primitives/ordering.rb @@ -0,0 +1,18 @@ +module Arel + class Ordering + attributes :attribute + deriving :initialize, :== + delegate :relation, :to => :attribute + + def bind(relation) + self.class.new(attribute.bind(relation)) + end + + def to_ordering + self + end + end + + class Ascending < Ordering; end + class Descending < Ordering; end +end
\ No newline at end of file diff --git a/lib/arel/algebra/primitives/value.rb b/lib/arel/algebra/primitives/value.rb index 76c82890d0..e363805140 100644 --- a/lib/arel/algebra/primitives/value.rb +++ b/lib/arel/algebra/primitives/value.rb @@ -7,12 +7,8 @@ module Arel Value.new(value, relation) end - def aggregation? - false - end - - def to_attribute - value + def to_ordering + self end end end diff --git a/lib/arel/algebra/relations/operations/order.rb b/lib/arel/algebra/relations/operations/order.rb index 05af3fde4d..eccd8bcda0 100644 --- a/lib/arel/algebra/relations/operations/order.rb +++ b/lib/arel/algebra/relations/operations/order.rb @@ -10,7 +10,8 @@ module Arel # TESTME def orders - (orderings + relation.orders).collect { |o| o.bind(self) } + # QUESTION - do we still need relation.orders ? + (orderings + relation.orders).collect { |o| o.bind(self) }.collect { |o| o.to_ordering } end end end
\ No newline at end of file diff --git a/lib/arel/engines/memory/primitives.rb b/lib/arel/engines/memory/primitives.rb index 77d4c1a52c..f8bbcedb55 100644 --- a/lib/arel/engines/memory/primitives.rb +++ b/lib/arel/engines/memory/primitives.rb @@ -10,4 +10,18 @@ module Arel value end end + + class Ordering + def eval(row1, row2) + (attribute.eval(row1) <=> attribute.eval(row2)) * direction + end + end + + class Descending < Ordering + def direction; -1 end + end + + class Ascending < Ordering + def direction; 1 end + end end
\ No newline at end of file diff --git a/lib/arel/engines/memory/relations.rb b/lib/arel/engines/memory/relations.rb index 9f8264c439..1b009537b9 100644 --- a/lib/arel/engines/memory/relations.rb +++ b/lib/arel/engines/memory/relations.rb @@ -1,3 +1,4 @@ require 'arel/engines/memory/relations/array' require 'arel/engines/memory/relations/operations' +require 'arel/engines/memory/relations/compound' diff --git a/lib/arel/engines/memory/relations/compound.rb b/lib/arel/engines/memory/relations/compound.rb new file mode 100644 index 0000000000..b029082d57 --- /dev/null +++ b/lib/arel/engines/memory/relations/compound.rb @@ -0,0 +1,5 @@ +module Arel + class Compound < Relation + delegate :array, :to => :relation + end +end diff --git a/lib/arel/engines/memory/relations/operations.rb b/lib/arel/engines/memory/relations/operations.rb index eb11fb55fd..115df054df 100644 --- a/lib/arel/engines/memory/relations/operations.rb +++ b/lib/arel/engines/memory/relations/operations.rb @@ -4,4 +4,37 @@ module Arel relation.eval.select { |row| predicate.eval(row) } end end + + class Order < Compound + def eval + relation.eval.sort do |row1, row2| + ordering = orderings.detect { |o| o.eval(row1, row2) != 0 } || orderings.last + ordering.eval(row1, row2) + end + end + end + + class Project < Compound + def eval + relation.eval.collect { |r| r.slice(*projections) } + end + end + + class Take < Compound + def eval + relation.eval[0, taken] + end + end + + class Skip < Compound + def eval + relation.eval[skipped..-1] + end + end + + class Group < Compound + def eval + raise NotImplementedError + end + end end
\ No newline at end of file diff --git a/lib/arel/engines/sql/formatters.rb b/lib/arel/engines/sql/formatters.rb index f82ddf631f..bc5f0f7c64 100644 --- a/lib/arel/engines/sql/formatters.rb +++ b/lib/arel/engines/sql/formatters.rb @@ -47,9 +47,9 @@ module Arel class WhereClause < PassThrough end - class OrderClause < PassThrough - def attribute(attribute) - "#{quote_table_name(name_for(attribute.original_relation))}.#{quote_column_name(attribute.name)}" + class OrderClause < PassThrough + def ordering(ordering) + "#{quote_table_name(name_for(ordering.attribute.original_relation))}.#{quote_column_name(ordering.attribute.name)} #{ordering.direction_sql}" end end diff --git a/lib/arel/engines/sql/primitives.rb b/lib/arel/engines/sql/primitives.rb index 6f89723afe..9e9143ac0f 100644 --- a/lib/arel/engines/sql/primitives.rb +++ b/lib/arel/engines/sql/primitives.rb @@ -24,6 +24,20 @@ module Arel object.to_sql(Sql::Value.new(relation)) end end + + class Ordering + def to_sql(formatter = Sql::OrderClause.new(relation)) + formatter.ordering self + end + end + + class Ascending < Ordering + def direction_sql; 'ASC' end + end + + class Descending < Ordering + def direction_sql; 'DESC' end + end class Expression < Attribute def to_sql(formatter = Sql::SelectClause.new(relation)) diff --git a/lib/arel/engines/sql/relations/utilities/compound.rb b/lib/arel/engines/sql/relations/utilities/compound.rb index 502bf8b01e..61df196d6e 100644 --- a/lib/arel/engines/sql/relations/utilities/compound.rb +++ b/lib/arel/engines/sql/relations/utilities/compound.rb @@ -1,6 +1,6 @@ module Arel class Compound < Relation - delegate :table, :table_sql, :array, :to => :relation + delegate :table, :table_sql, :to => :relation end end
\ No newline at end of file |