alf-sequel 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +3 -3
- data/lib/alf/sequel/cog.rb +29 -24
- data/lib/alf/sequel/compiler.rb +65 -24
- data/lib/alf/sequel/connection/schema_methods.rb +3 -3
- data/lib/alf/sequel/unit_of_work/update.rb +2 -2
- data/lib/alf/sequel/version.rb +1 -1
- data/spec/compiler/test_frame.rb +89 -0
- data/spec/compiler/test_join.rb +9 -1
- data/spec/compiler/test_matching.rb +1 -1
- data/spec/compiler/test_not_matching.rb +1 -1
- data/spec/compiler/test_page.rb +86 -0
- metadata +7 -5
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
alf-core (0.
|
4
|
+
alf-core (0.14.0)
|
5
5
|
domain (~> 1.0)
|
6
6
|
myrrha (~> 3.0)
|
7
7
|
path (~> 1.3)
|
@@ -11,7 +11,7 @@ GEM
|
|
11
11
|
jdbc-sqlite3 (3.7.2.1)
|
12
12
|
myrrha (3.0.0)
|
13
13
|
domain (~> 1.0)
|
14
|
-
path (1.3.
|
14
|
+
path (1.3.3)
|
15
15
|
rake (10.1.0)
|
16
16
|
rspec (2.14.1)
|
17
17
|
rspec-core (~> 2.14.0)
|
@@ -30,7 +30,7 @@ PLATFORMS
|
|
30
30
|
ruby
|
31
31
|
|
32
32
|
DEPENDENCIES
|
33
|
-
alf-core (~> 0.
|
33
|
+
alf-core (~> 0.14.0)
|
34
34
|
jdbc-sqlite3 (~> 3.7)
|
35
35
|
rake (~> 10.1)
|
36
36
|
rspec (~> 2.14)
|
data/lib/alf/sequel/cog.rb
CHANGED
@@ -3,7 +3,8 @@ module Alf
|
|
3
3
|
class Cog
|
4
4
|
include Engine::Cog
|
5
5
|
|
6
|
-
def initialize(connection, opts)
|
6
|
+
def initialize(expr, connection, opts)
|
7
|
+
super(expr)
|
7
8
|
@connection = connection
|
8
9
|
@opts = opts
|
9
10
|
end
|
@@ -24,41 +25,45 @@ module Alf
|
|
24
25
|
|
25
26
|
### Delegation to Dataset, that is, facade over ::Sequel itself
|
26
27
|
|
27
|
-
def select(attrs)
|
28
|
-
branch dataset: dataset.select(*qualify(attrs))
|
28
|
+
def select(expr, attrs)
|
29
|
+
branch expr, dataset: dataset.select(*qualify(attrs))
|
29
30
|
end
|
30
31
|
|
31
|
-
def rename(attrs, opts)
|
32
|
-
branch dataset: dataset.select(*qualify(attrs)).from_self(opts),
|
33
|
-
|
32
|
+
def rename(expr, attrs, opts)
|
33
|
+
branch expr, dataset: dataset.select(*qualify(attrs)).from_self(opts),
|
34
|
+
as: opts[:alias]
|
34
35
|
end
|
35
36
|
|
36
|
-
def distinct(*args, &bl)
|
37
|
-
branch dataset: dataset.distinct(*args, &bl)
|
37
|
+
def distinct(expr, *args, &bl)
|
38
|
+
branch expr, dataset: dataset.distinct(*args, &bl)
|
38
39
|
end
|
39
40
|
|
40
|
-
def order(*args, &bl)
|
41
|
-
branch dataset: dataset.order(*args, &bl)
|
41
|
+
def order(expr, *args, &bl)
|
42
|
+
branch expr, dataset: dataset.order(*args, &bl)
|
42
43
|
end
|
43
44
|
|
44
|
-
def filter(*args, &bl)
|
45
|
-
branch dataset: dataset.filter(*args, &bl)
|
45
|
+
def filter(expr, *args, &bl)
|
46
|
+
branch expr, dataset: dataset.filter(*args, &bl)
|
46
47
|
end
|
47
48
|
|
48
|
-
def intersect(other, opts={})
|
49
|
-
branch dataset: dataset.intersect(other.dataset, opts),
|
50
|
-
|
49
|
+
def intersect(expr, other, opts={})
|
50
|
+
branch expr, dataset: dataset.intersect(other.dataset, opts),
|
51
|
+
as: opts[:alias]
|
51
52
|
end
|
52
53
|
|
53
|
-
def join(other, cols, opts={})
|
54
|
-
join = dataset.inner_join(other.dataset, cols, :table_alias => opts[:alias])
|
55
|
-
branch dataset: join.from_self(opts),
|
56
|
-
|
54
|
+
def join(expr, other, cols, opts={})
|
55
|
+
join = dataset.from_self.inner_join(other.dataset, cols, :table_alias => opts[:alias])
|
56
|
+
branch expr, dataset: join.from_self(opts),
|
57
|
+
as: opts[:alias]
|
57
58
|
end
|
58
59
|
|
59
|
-
def union(other, opts={})
|
60
|
-
branch dataset: dataset.union(other.dataset, opts),
|
61
|
-
|
60
|
+
def union(expr, other, opts={})
|
61
|
+
branch expr, dataset: dataset.union(other.dataset, opts),
|
62
|
+
as: opts[:alias]
|
63
|
+
end
|
64
|
+
|
65
|
+
def limit(expr, *args, &bl)
|
66
|
+
branch expr, dataset: dataset.limit(*args, &bl)
|
62
67
|
end
|
63
68
|
|
64
69
|
### compilation tools
|
@@ -79,8 +84,8 @@ module Alf
|
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
82
|
-
def branch(opts = {})
|
83
|
-
Cog.new connection, self.opts.merge(opts)
|
87
|
+
def branch(expr, opts = {})
|
88
|
+
Cog.new expr, connection, self.opts.merge(opts)
|
84
89
|
end
|
85
90
|
|
86
91
|
def to_s
|
data/lib/alf/sequel/compiler.rb
CHANGED
@@ -14,7 +14,7 @@ module Alf
|
|
14
14
|
|
15
15
|
def on_leaf_operand(expr)
|
16
16
|
if Algebra::Operand::Named===expr
|
17
|
-
expr.connection.cog(expr.name, :alias => next_alias)
|
17
|
+
expr.connection.cog(expr.name, expr, :alias => next_alias)
|
18
18
|
else
|
19
19
|
expr.to_cog
|
20
20
|
end
|
@@ -29,53 +29,61 @@ module Alf
|
|
29
29
|
|
30
30
|
def on_clip(expr)
|
31
31
|
rewrite(expr){|rw|
|
32
|
-
rw.operand.select(expr.stay_attributes)
|
32
|
+
rw.operand.select(expr, expr.stay_attributes)
|
33
33
|
}
|
34
34
|
end
|
35
35
|
|
36
36
|
def on_compact(expr)
|
37
37
|
rewrite(expr){|rw|
|
38
|
-
rw.operand.distinct
|
38
|
+
rw.operand.distinct(expr)
|
39
39
|
}
|
40
40
|
end
|
41
41
|
|
42
42
|
def on_sort(expr)
|
43
43
|
rewrite(expr){|rw|
|
44
|
-
operand
|
45
|
-
ordering = expr.ordering
|
46
|
-
|
47
|
-
}
|
48
|
-
operand.order(*ordering)
|
44
|
+
operand = rw.operand
|
45
|
+
ordering = to_sequel_ordering(operand, expr.ordering)
|
46
|
+
operand.order(expr, *ordering)
|
49
47
|
}
|
50
48
|
end
|
51
49
|
|
52
50
|
### relational
|
53
51
|
|
54
52
|
alias :on_extend :pass
|
53
|
+
|
54
|
+
def on_frame(expr)
|
55
|
+
rewrite(expr){|rw|
|
56
|
+
offset, limit, ordering = expr.offset, expr.limit, expr.total_ordering
|
57
|
+
operand = rw.operand
|
58
|
+
ordering = to_sequel_ordering(operand, ordering)
|
59
|
+
operand.order(expr, *ordering).limit(expr, limit, offset)
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
55
63
|
alias :on_group :pass
|
56
64
|
alias :on_infer_heading :pass
|
57
65
|
|
58
66
|
def on_intersect(expr)
|
59
67
|
rewrite(expr){|rw|
|
60
|
-
rw.left.intersect(rw.right, :alias => next_alias)
|
68
|
+
rw.left.intersect(expr, rw.right, {:alias => next_alias})
|
61
69
|
}
|
62
70
|
end
|
63
71
|
|
64
72
|
def on_join(expr)
|
65
73
|
rewrite(expr){|rw|
|
66
|
-
rw.left.join(rw.right, expr.common_attributes.to_a, :alias => next_alias)
|
74
|
+
rw.left.join(expr, rw.right, expr.common_attributes.to_a, {:alias => next_alias})
|
67
75
|
}
|
68
76
|
end
|
69
77
|
|
70
78
|
def on_matching(expr)
|
71
79
|
rewrite(expr) do |rw|
|
72
|
-
rw.left.filter(matching2filter(expr, rw))
|
80
|
+
rw.left.filter(expr, matching2filter(expr, rw))
|
73
81
|
end
|
74
82
|
end
|
75
83
|
|
76
84
|
def on_not_matching(expr)
|
77
85
|
rewrite(expr) do |rw|
|
78
|
-
rw.left.filter(~matching2filter(expr, rw))
|
86
|
+
rw.left.filter(expr, ~matching2filter(expr, rw))
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
@@ -83,7 +91,7 @@ module Alf
|
|
83
91
|
commons = expr.common_attributes.to_a
|
84
92
|
if commons.size==1
|
85
93
|
# (NOT) IN (SELECT ...)
|
86
|
-
pred = ::Alf::Predicate.in(commons.first, rw.right.select(commons).dataset)
|
94
|
+
pred = ::Alf::Predicate.in(commons.first, rw.right.select(expr, commons).dataset)
|
87
95
|
Predicate.new(:qualifier => rw.left.as).call(pred)
|
88
96
|
elsif commons.size==0
|
89
97
|
# (NOT) EXISTS (SELECT ... no join condition ...)
|
@@ -92,17 +100,26 @@ module Alf
|
|
92
100
|
# (NOT) EXISTS (SELECT ...)
|
93
101
|
filter = Hash[rw.left.qualify(commons).zip(rw.right.qualify(commons))]
|
94
102
|
filter = ::Sequel.expr filter
|
95
|
-
filter = rw.right.filter(filter)
|
103
|
+
filter = rw.right.filter(expr, filter)
|
96
104
|
filter.dataset.exists
|
97
105
|
end
|
98
106
|
end
|
99
107
|
|
100
108
|
alias :on_minus :pass
|
101
109
|
|
110
|
+
def on_page(expr)
|
111
|
+
rewrite(expr){|rw|
|
112
|
+
index, size, ordering = expr.page_index, expr.page_size, expr.total_ordering
|
113
|
+
operand, offset, limit = rw.operand, (index.abs - 1) * size, size
|
114
|
+
ordering = to_sequel_ordering(operand, index >= 0 ? ordering : ordering.reverse)
|
115
|
+
operand.order(expr, *ordering).limit(expr, offset , limit)
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
102
119
|
def on_project(expr)
|
103
120
|
rewrite(expr){|rw|
|
104
|
-
compiled = rw.operand.select(expr.stay_attributes)
|
105
|
-
compiled = compiled.distinct unless key_preserving?(expr){ false }
|
121
|
+
compiled = rw.operand.select(expr, expr.stay_attributes)
|
122
|
+
compiled = compiled.distinct(expr) unless key_preserving?(expr){ false }
|
106
123
|
compiled
|
107
124
|
}
|
108
125
|
end
|
@@ -112,14 +129,14 @@ module Alf
|
|
112
129
|
|
113
130
|
def on_rename(expr)
|
114
131
|
rewrite(expr){|rw|
|
115
|
-
rw.operand.rename(expr.complete_renaming.to_hash, :alias => next_alias)
|
132
|
+
rw.operand.rename(expr, expr.complete_renaming.to_hash, :alias => next_alias)
|
116
133
|
}
|
117
134
|
end
|
118
135
|
|
119
136
|
def on_restrict(expr)
|
120
137
|
rewrite(expr){|rw|
|
121
138
|
filter = Predicate.new(:qualifier => rw.operand.as).call(rw.predicate)
|
122
|
-
rw.operand.filter(filter)
|
139
|
+
rw.operand.filter(expr, filter)
|
123
140
|
}
|
124
141
|
end
|
125
142
|
|
@@ -128,7 +145,7 @@ module Alf
|
|
128
145
|
|
129
146
|
def on_union(expr)
|
130
147
|
rewrite(expr){|rw|
|
131
|
-
rw.left.union(rw.right, :alias => next_alias)
|
148
|
+
rw.left.union(expr, rw.right, :alias => next_alias)
|
132
149
|
}
|
133
150
|
end
|
134
151
|
|
@@ -137,6 +154,13 @@ module Alf
|
|
137
154
|
|
138
155
|
private
|
139
156
|
|
157
|
+
def to_sequel_ordering(operand, ordering)
|
158
|
+
ordering.to_a.map{|(sel,dir)|
|
159
|
+
raise NotSupportedError if sel.composite?
|
160
|
+
::Sequel.send(dir, operand.qualify(sel.outcoerce))
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
140
164
|
def key_preserving?(expr)
|
141
165
|
expr.key_preserving?
|
142
166
|
rescue NotSupportedError
|
@@ -146,12 +170,29 @@ module Alf
|
|
146
170
|
private
|
147
171
|
|
148
172
|
def rewrite(expr)
|
149
|
-
|
150
|
-
|
151
|
-
|
173
|
+
# copy and apply on expr. the result is the same expression, but
|
174
|
+
# with cogs instead of operands
|
175
|
+
rewritten = copy_and_apply(expr)
|
176
|
+
|
177
|
+
# Continue compilation process provided all operands are recognized.
|
178
|
+
if block_given? and rewritten.operands.all?{|op| recognized?(op) }
|
179
|
+
# Compilation of predicates may throw a pass
|
180
|
+
catch(:pass){
|
181
|
+
rewritten = yield(rewritten)
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
# If the result is itself recognized, proceed
|
186
|
+
# Otherwise, give a change to the upper-stage compiler with a proxy
|
187
|
+
if recognized?(rewritten)
|
188
|
+
rewritten
|
189
|
+
else
|
190
|
+
operands = rewritten.operands.map{|op|
|
191
|
+
Algebra::Operand::Proxy.new(op)
|
192
|
+
}
|
193
|
+
rewritten = rewritten.with_operands(*operands)
|
194
|
+
engine.call(rewritten)
|
152
195
|
end
|
153
|
-
rewrited = engine.call(rewrited) unless recognized?(rewrited)
|
154
|
-
rewrited
|
155
196
|
end
|
156
197
|
|
157
198
|
def recognized?(op)
|
@@ -11,11 +11,11 @@ module Alf
|
|
11
11
|
sequel_db[name]
|
12
12
|
end
|
13
13
|
|
14
|
-
def cog(name, opts={})
|
14
|
+
def cog(name, expr = nil, opts = {})
|
15
15
|
if as = opts[:alias]
|
16
|
-
Cog.new(self, dataset: dataset(:"#{name}___#{as}"), as: as)
|
16
|
+
Cog.new(expr, self, dataset: dataset(:"#{name}___#{as}"), as: as)
|
17
17
|
else
|
18
|
-
Cog.new(self, dataset: dataset(name))
|
18
|
+
Cog.new(expr, self, dataset: dataset(name))
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
data/lib/alf/sequel/version.rb
CHANGED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'compiler_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Compiler, "frame" do
|
5
|
+
|
6
|
+
subject{ compile(expr) }
|
7
|
+
|
8
|
+
let(:expr){
|
9
|
+
frame(operand, ordering, offset, limit)
|
10
|
+
}
|
11
|
+
|
12
|
+
context 'when fully compilable' do
|
13
|
+
let(:operand){ suppliers }
|
14
|
+
|
15
|
+
[
|
16
|
+
[ [[:name, :asc]], 0, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC LIMIT 8 OFFSET 0" ],
|
17
|
+
[ [[:name, :asc]], 2, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC LIMIT 8 OFFSET 2" ],
|
18
|
+
[ [[:city, :asc]], 0, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` ASC, `t1`.`sid` ASC LIMIT 8 OFFSET 0" ],
|
19
|
+
[ [[:city, :desc]], 2, 8, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` DESC, `t1`.`sid` ASC LIMIT 8 OFFSET 2" ],
|
20
|
+
].each do |(ordering,offset,limit,expected)|
|
21
|
+
|
22
|
+
context "frame(#{ordering}, #{offset}, #{limit})" do
|
23
|
+
let(:ordering){ ordering }
|
24
|
+
let(:offset) { offset }
|
25
|
+
let(:limit) { limit }
|
26
|
+
|
27
|
+
it 'should compile as expected' do
|
28
|
+
subject.sql.should eq(expected)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end # fully compilable
|
34
|
+
|
35
|
+
context 'when immediately uncompilable yet known keys' do
|
36
|
+
let(:operand){
|
37
|
+
Algebra::Operand::Fake.new.with_keys([:sid], [:name])
|
38
|
+
}
|
39
|
+
|
40
|
+
[
|
41
|
+
[ [[:name, :asc]], 2, 8, [[:name, :asc]] ],
|
42
|
+
[ [[:city, :asc]], 2, 8, [[:city, :asc], [:sid, :asc]] ]
|
43
|
+
].each do |ordering, offset, limit, expected|
|
44
|
+
|
45
|
+
context "frame(#{ordering}, #{offset}, #{limit})" do
|
46
|
+
let(:ordering){ ordering }
|
47
|
+
let(:offset) { offset }
|
48
|
+
let(:limit) { limit }
|
49
|
+
|
50
|
+
it{ should be_a(Engine::Take) }
|
51
|
+
|
52
|
+
it 'should have sort with good ordering' do
|
53
|
+
subject.operand.should be_a(Engine::Sort)
|
54
|
+
subject.operand.ordering.should eq(Ordering.new(expected))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when immediately uncompilable yet unknown keys' do
|
62
|
+
let(:operand){
|
63
|
+
Algebra::Operand::Fake.new
|
64
|
+
}
|
65
|
+
|
66
|
+
[
|
67
|
+
[ [[:name, :asc]], 2, 8, [[:name, :asc]] ],
|
68
|
+
[ [[:city, :asc]], 2, 8, [[:city, :asc]] ]
|
69
|
+
].each do |ordering, offset, limit, expected|
|
70
|
+
|
71
|
+
context "frame(#{ordering}, #{offset}, #{limit})" do
|
72
|
+
let(:ordering){ ordering }
|
73
|
+
let(:offset) { offset }
|
74
|
+
let(:limit) { limit }
|
75
|
+
|
76
|
+
it{ should be_a(Engine::Take) }
|
77
|
+
|
78
|
+
it 'should have sort with good ordering' do
|
79
|
+
subject.operand.should be_a(Engine::Sort)
|
80
|
+
subject.operand.ordering.should eq(Ordering.new(expected))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/spec/compiler/test_join.rb
CHANGED
@@ -9,7 +9,15 @@ module Alf
|
|
9
9
|
let(:expr){ join(suppliers, supplies) }
|
10
10
|
|
11
11
|
specify do
|
12
|
-
subject.sql.should eq("SELECT * FROM (SELECT * FROM `suppliers` AS 't1' INNER JOIN (SELECT * FROM `supplies` AS 't2') AS 't3' USING (`sid`)) AS 't3'")
|
12
|
+
subject.sql.should eq("SELECT * FROM (SELECT * FROM (SELECT * FROM `suppliers` AS 't1') AS 't1' INNER JOIN (SELECT * FROM `supplies` AS 't2') AS 't3' USING (`sid`)) AS 't3'")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when the left operand is a projection' do
|
17
|
+
let(:expr){ join(project(suppliers, [:sid]), supplies) }
|
18
|
+
|
19
|
+
specify do
|
20
|
+
subject.sql.should eq("SELECT * FROM (SELECT * FROM (SELECT `t1`.`sid` FROM `suppliers` AS 't1') AS 't1' INNER JOIN (SELECT * FROM `supplies` AS 't2') AS 't3' USING (`sid`)) AS 't3'")
|
13
21
|
end
|
14
22
|
end
|
15
23
|
|
@@ -9,7 +9,7 @@ module Alf
|
|
9
9
|
let(:expr){ matching(suppliers, project(supplies, [:part_id])) }
|
10
10
|
|
11
11
|
specify do
|
12
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (EXISTS (SELECT `t2`.`part_id` FROM `supplies` AS 't2'))")
|
12
|
+
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (EXISTS (SELECT DISTINCT `t2`.`part_id` FROM `supplies` AS 't2'))")
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -9,7 +9,7 @@ module Alf
|
|
9
9
|
let(:expr){ not_matching(suppliers, project(supplies, [:part_id])) }
|
10
10
|
|
11
11
|
specify do
|
12
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE NOT (EXISTS (SELECT `t2`.`part_id` FROM `supplies` AS 't2'))")
|
12
|
+
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE NOT (EXISTS (SELECT DISTINCT `t2`.`part_id` FROM `supplies` AS 't2'))")
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'compiler_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Compiler, "page" do
|
5
|
+
|
6
|
+
subject{ compile(expr) }
|
7
|
+
|
8
|
+
let(:expr){
|
9
|
+
page(operand, ordering, page_index, page_size: 8)
|
10
|
+
}
|
11
|
+
|
12
|
+
context 'when fully compilable' do
|
13
|
+
let(:operand){ suppliers }
|
14
|
+
|
15
|
+
[
|
16
|
+
[ [[:name, :asc]], 2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC LIMIT 8 OFFSET 8" ],
|
17
|
+
[ [[:name, :asc]], -2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` DESC LIMIT 8 OFFSET 8" ],
|
18
|
+
[ [[:city, :asc]], 2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` ASC, `t1`.`sid` ASC LIMIT 8 OFFSET 8" ],
|
19
|
+
[ [[:city, :asc]], -2, "SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`city` DESC, `t1`.`sid` DESC LIMIT 8 OFFSET 8" ],
|
20
|
+
].each do |(ordering,page_index,expected)|
|
21
|
+
|
22
|
+
context "page(#{ordering}, #{page_index})" do
|
23
|
+
let(:ordering) { ordering }
|
24
|
+
let(:page_index){ page_index }
|
25
|
+
|
26
|
+
it 'should compile as expected' do
|
27
|
+
subject.sql.should eq(expected)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end # fully compilable
|
33
|
+
|
34
|
+
context 'when immediately uncompilable yet known keys' do
|
35
|
+
let(:operand){
|
36
|
+
Algebra::Operand::Fake.new.with_keys([:sid], [:name])
|
37
|
+
}
|
38
|
+
|
39
|
+
[
|
40
|
+
[ [[:name, :asc]], 2, [[:name, :asc]] ],
|
41
|
+
[ [[:city, :asc]], 2, [[:city, :asc], [:sid, :asc]] ]
|
42
|
+
].each do |ordering, page_index, expected|
|
43
|
+
|
44
|
+
context "page(#{ordering}, #{page_index})" do
|
45
|
+
let(:ordering) { ordering }
|
46
|
+
let(:page_index){ page_index }
|
47
|
+
|
48
|
+
it{ should be_a(Engine::Take) }
|
49
|
+
|
50
|
+
it 'should have sort with good ordering' do
|
51
|
+
subject.operand.should be_a(Engine::Sort)
|
52
|
+
subject.operand.ordering.should eq(Ordering.new(expected))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when immediately uncompilable yet unknown keys' do
|
60
|
+
let(:operand){
|
61
|
+
Algebra::Operand::Fake.new
|
62
|
+
}
|
63
|
+
|
64
|
+
[
|
65
|
+
[ [[:name, :asc]], 2, [[:name, :asc]] ],
|
66
|
+
[ [[:city, :asc]], 2, [[:city, :asc]] ]
|
67
|
+
].each do |ordering, page_index, expected|
|
68
|
+
|
69
|
+
context "page(#{ordering}, #{page_index})" do
|
70
|
+
let(:ordering) { ordering }
|
71
|
+
let(:page_index){ page_index }
|
72
|
+
|
73
|
+
it{ should be_a(Engine::Take) }
|
74
|
+
|
75
|
+
it 'should have sort with good ordering' do
|
76
|
+
subject.operand.should be_a(Engine::Sort)
|
77
|
+
subject.operand.ordering.should eq(Ordering.new(expected))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alf-sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-10-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 0.
|
53
|
+
version: 0.14.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: 0.14.0
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: sequel
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,11 +111,13 @@ files:
|
|
111
111
|
- spec/compiler/test_clip.rb
|
112
112
|
- spec/compiler/test_compact.rb
|
113
113
|
- spec/compiler/test_extend.rb
|
114
|
+
- spec/compiler/test_frame.rb
|
114
115
|
- spec/compiler/test_intersect.rb
|
115
116
|
- spec/compiler/test_join.rb
|
116
117
|
- spec/compiler/test_leaf_operand.rb
|
117
118
|
- spec/compiler/test_matching.rb
|
118
119
|
- spec/compiler/test_not_matching.rb
|
120
|
+
- spec/compiler/test_page.rb
|
119
121
|
- spec/compiler/test_predicate.rb
|
120
122
|
- spec/compiler/test_project.rb
|
121
123
|
- spec/compiler/test_rename.rb
|
@@ -158,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
158
160
|
version: '0'
|
159
161
|
segments:
|
160
162
|
- 0
|
161
|
-
hash:
|
163
|
+
hash: 3191817765128165623
|
162
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
165
|
none: false
|
164
166
|
requirements:
|