aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBryan Helmkamp <bryan@brynary.com>2009-05-17 15:42:42 -0400
committerBryan Helmkamp <bryan@brynary.com>2009-05-17 15:42:42 -0400
commit8339f024c7663133a78c4d0a8824b5b6fafaf239 (patch)
treea43ebc9c956d8484647d81e5ea14534e7b0570a0
parent4c71e3b2ea4b8da574954cbd8a26d12f2cc640d0 (diff)
downloadrails-8339f024c7663133a78c4d0a8824b5b6fafaf239.tar.gz
rails-8339f024c7663133a78c4d0a8824b5b6fafaf239.tar.bz2
rails-8339f024c7663133a78c4d0a8824b5b6fafaf239.zip
recursive memory operations now possible
Conflicts: lib/arel/algebra/relations/relation.rb
-rw-r--r--doc/TODO7
-rw-r--r--lib/arel/algebra/extensions/hash.rb7
-rw-r--r--lib/arel/algebra/relations.rb1
-rw-r--r--lib/arel/algebra/relations/relation.rb4
-rw-r--r--lib/arel/algebra/relations/row.rb21
-rw-r--r--lib/arel/engines/memory/predicates.rb6
-rw-r--r--lib/arel/engines/memory/relations.rb1
-rw-r--r--lib/arel/engines/memory/relations/array.rb2
-rw-r--r--lib/arel/engines/memory/relations/compound.rb4
-rw-r--r--lib/arel/engines/memory/relations/operations.rb10
-rw-r--r--lib/arel/engines/memory/relations/relation.rb7
-rw-r--r--spec/arel/engines/memory/unit/relations/array_spec.rb83
12 files changed, 107 insertions, 46 deletions
diff --git a/doc/TODO b/doc/TODO
index f97e74ef17..7af8db6bdf 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,11 +1,11 @@
todo:
-- reorganize sql tests
+- recursive memory operations
- reorganize memory tests
-- blocks for joins
+- deal with table tests in algebra
- implement joins in memory
-- recursive memory operations
- result sets should be array relations
- cross-engine joins
+- blocks for joins
- fix grouping
- implement mnesia adapter
- fix AR
@@ -92,6 +92,7 @@ done:
- expressions should be class-based, and joins too, anything _sql should be renamed
- implement in memory adapter
- clean up block_given stuff
+- reorganize sql tests
icebox:
- #bind in Attribute and Expression should be doing a descend?
diff --git a/lib/arel/algebra/extensions/hash.rb b/lib/arel/algebra/extensions/hash.rb
index bc97785e62..7472b5aa73 100644
--- a/lib/arel/algebra/extensions/hash.rb
+++ b/lib/arel/algebra/extensions/hash.rb
@@ -4,11 +4,4 @@ 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/relations.rb b/lib/arel/algebra/relations.rb
index b75a31e5e3..94df5938fe 100644
--- a/lib/arel/algebra/relations.rb
+++ b/lib/arel/algebra/relations.rb
@@ -2,6 +2,7 @@ require 'arel/algebra/relations/relation'
require 'arel/algebra/relations/utilities/compound'
require 'arel/algebra/relations/utilities/nil'
require 'arel/algebra/relations/utilities/externalization'
+require 'arel/algebra/relations/row'
require 'arel/algebra/relations/writes'
require 'arel/algebra/relations/operations/alias'
require 'arel/algebra/relations/operations/group'
diff --git a/lib/arel/algebra/relations/relation.rb b/lib/arel/algebra/relations/relation.rb
index 6d76e66638..fe8cab4b02 100644
--- a/lib/arel/algebra/relations/relation.rb
+++ b/lib/arel/algebra/relations/relation.rb
@@ -14,10 +14,6 @@ module Arel
self
end
- def root
- self
- end
-
module Enumerable
include ::Enumerable
diff --git a/lib/arel/algebra/relations/row.rb b/lib/arel/algebra/relations/row.rb
new file mode 100644
index 0000000000..2d63498452
--- /dev/null
+++ b/lib/arel/algebra/relations/row.rb
@@ -0,0 +1,21 @@
+module Arel
+ class Row
+ attributes :relation, :tuple
+ deriving :==, :initialize
+
+ def [](attribute)
+ tuple[relation.position_of(attribute)]
+ end
+
+ def slice(*attributes)
+ Row.new(relation, attributes.inject([]) do |cheese, attribute|
+ cheese << self[attribute]
+ cheese
+ end)
+ end
+
+ def bind(relation)
+ Row.new(relation, tuple)
+ end
+ end
+end \ No newline at end of file
diff --git a/lib/arel/engines/memory/predicates.rb b/lib/arel/engines/memory/predicates.rb
index bbf39ba794..e233f3ba39 100644
--- a/lib/arel/engines/memory/predicates.rb
+++ b/lib/arel/engines/memory/predicates.rb
@@ -21,15 +21,19 @@ module Arel
end
class Equality < Binary
+ def operator; :== end
end
class GreaterThanOrEqualTo < Binary
+ def operator; :>= end
end
class GreaterThan < Binary
+ def operator; :> end
end
class LessThanOrEqualTo < Binary
+ def operator; :<= end
end
class LessThan < Binary
@@ -37,8 +41,10 @@ module Arel
end
class Match < Binary
+ def operator; :=~ end
end
class In < Binary
+ def operator; :include? end
end
end
diff --git a/lib/arel/engines/memory/relations.rb b/lib/arel/engines/memory/relations.rb
index 1b009537b9..820b0af4b2 100644
--- a/lib/arel/engines/memory/relations.rb
+++ b/lib/arel/engines/memory/relations.rb
@@ -1,3 +1,4 @@
+require 'arel/engines/memory/relations/relation'
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/array.rb b/lib/arel/engines/memory/relations/array.rb
index c02c62891b..ea0b5af5ba 100644
--- a/lib/arel/engines/memory/relations/array.rb
+++ b/lib/arel/engines/memory/relations/array.rb
@@ -15,7 +15,7 @@ module Arel
end
def eval
- @array.collect { |row| attributes.zip(row).to_hash }
+ @array.collect { |r| Row.new(self, r) }
end
end
end \ No newline at end of file
diff --git a/lib/arel/engines/memory/relations/compound.rb b/lib/arel/engines/memory/relations/compound.rb
index b029082d57..3791fa4622 100644
--- a/lib/arel/engines/memory/relations/compound.rb
+++ b/lib/arel/engines/memory/relations/compound.rb
@@ -1,5 +1,9 @@
module Arel
class Compound < Relation
delegate :array, :to => :relation
+
+ def unoperated_rows
+ relation.eval.collect { |row| row.bind(self) }
+ end
end
end
diff --git a/lib/arel/engines/memory/relations/operations.rb b/lib/arel/engines/memory/relations/operations.rb
index 115df054df..8e03aca7b1 100644
--- a/lib/arel/engines/memory/relations/operations.rb
+++ b/lib/arel/engines/memory/relations/operations.rb
@@ -1,13 +1,13 @@
module Arel
class Where < Compound
def eval
- relation.eval.select { |row| predicate.eval(row) }
+ unoperated_rows.select { |row| predicate.eval(row) }
end
end
class Order < Compound
def eval
- relation.eval.sort do |row1, row2|
+ unoperated_rows.sort do |row1, row2|
ordering = orderings.detect { |o| o.eval(row1, row2) != 0 } || orderings.last
ordering.eval(row1, row2)
end
@@ -16,19 +16,19 @@ module Arel
class Project < Compound
def eval
- relation.eval.collect { |r| r.slice(*projections) }
+ unoperated_rows.collect { |r| r.slice(*projections) }
end
end
class Take < Compound
def eval
- relation.eval[0, taken]
+ unoperated_rows[0, taken]
end
end
class Skip < Compound
def eval
- relation.eval[skipped..-1]
+ unoperated_rows[skipped..-1]
end
end
diff --git a/lib/arel/engines/memory/relations/relation.rb b/lib/arel/engines/memory/relations/relation.rb
new file mode 100644
index 0000000000..abfb8bb37f
--- /dev/null
+++ b/lib/arel/engines/memory/relations/relation.rb
@@ -0,0 +1,7 @@
+module Arel
+ class Relation
+ def position_of(attribute)
+ attributes.index(self[attribute])
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/arel/engines/memory/unit/relations/array_spec.rb b/spec/arel/engines/memory/unit/relations/array_spec.rb
index 8d40858c5f..22cddf7156 100644
--- a/spec/arel/engines/memory/unit/relations/array_spec.rb
+++ b/spec/arel/engines/memory/unit/relations/array_spec.rb
@@ -22,61 +22,92 @@ module Arel
describe '#call' do
it "manufactures an array of hashes of attributes to values" do
@relation.call.should == [
- { @relation[:id] => 1, @relation[:name] => 'duck' },
- { @relation[:id] => 2, @relation[:name] => 'duck' },
- { @relation[:id] => 3, @relation[:name] => 'goose' }
+ Row.new(@relation, [1, 'duck']),
+ Row.new(@relation, [2, 'duck']),
+ Row.new(@relation, [3, 'goose'])
]
end
describe 'where' do
+ xit 'filters the relation with the provided predicate' do
+ @relation \
+ .where(@relation[:id].lt(3)) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1, 'duck']),
+ Row.new(relation, [2, 'duck']),
+ ]
+ end
+ end
+
it 'filters the relation with the provided predicate' do
- @relation.where(@relation[:id].lt(3)).call.should == [
- { @relation[:id] => 1, @relation[:name] => 'duck' },
- { @relation[:id] => 2, @relation[:name] => 'duck' }
- ]
+ @relation \
+ .where(@relation[:id].gt(1)) \
+ .where(@relation[:id].lt(3)) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [2, 'duck'])
+ ]
+ end
end
end
describe 'group' do
- it 'sorts the relation with the provided ordering' do
+ xit 'sorts the relation with the provided ordering' do
end
end
describe 'order' do
it 'sorts the relation with the provided ordering' do
- @relation.order(@relation[:id].desc).call.should == [
- { @relation[:id] => 3, @relation[:name] => 'goose' },
- { @relation[:id] => 2, @relation[:name] => 'duck' },
- { @relation[:id] => 1, @relation[:name] => 'duck' }
- ]
+ @relation \
+ .order(@relation[:id].desc) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [3, 'goose']),
+ Row.new(relation, [2, 'duck']),
+ Row.new(relation, [1, 'duck'])
+ ]
+ end
end
end
describe 'project' do
it 'projects' do
- @relation.project(@relation[:id]).call.should == [
- { @relation[:id] => 1 },
- { @relation[:id] => 2 },
- { @relation[:id] => 3 }
- ]
+ @relation \
+ .project(@relation[:id]) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1]),
+ Row.new(relation, [2]),
+ Row.new(relation, [3])
+ ]
+ end
end
end
describe 'skip' do
it 'slices' do
- @relation.skip(1).call.should == [
- { @relation[:id] => 2, @relation[:name] => 'duck' },
- { @relation[:id] => 3, @relation[:name] => 'goose' }
- ]
+ @relation \
+ .skip(1) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [2, 'duck']),
+ Row.new(relation, [3, 'goose']),
+ ]
+ end
end
end
describe 'take' do
it 'dices' do
- @relation.take(2).call.should == [
- { @relation[:id] => 1, @relation[:name] => 'duck' },
- { @relation[:id] => 2, @relation[:name] => 'duck' }
- ]
+ @relation \
+ .take(2) \
+ .let do |relation|
+ relation.call.should == [
+ Row.new(relation, [1, 'duck']),
+ Row.new(relation, [2, 'duck']),
+ ]
+ end
end
end