alf-sequel 0.14.0 → 0.15.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/Gemfile +10 -7
- data/Gemfile.lock +26 -14
- data/README.md +45 -3
- data/lib/alf/sequel.rb +1 -0
- data/lib/alf/sequel/cog.rb +23 -75
- data/lib/alf/sequel/compiler.rb +8 -198
- data/lib/alf/sequel/connection.rb +5 -1
- data/lib/alf/sequel/connection/connection_methods.rb +4 -2
- data/lib/alf/sequel/connection/schema_methods.rb +2 -6
- data/lib/alf/sequel/connection/update_methods.rb +1 -1
- data/lib/alf/sequel/loader.rb +1 -0
- data/lib/alf/sequel/translator.rb +198 -0
- data/lib/alf/sequel/unit_of_work/insert.rb +10 -4
- data/lib/alf/sequel/unit_of_work/update.rb +3 -3
- data/lib/alf/sequel/version.rb +1 -1
- data/spec/connection/test_heading.rb +1 -1
- data/spec/{fixtures/sap.db → sap.db} +0 -0
- data/spec/spec_helper.rb +48 -6
- data/spec/unit_of_work/delete/test_delete.rb +2 -2
- data/spec/unit_of_work/insert/test_run.rb +12 -14
- data/spec/unit_of_work/update/test_run.rb +1 -1
- data/tasks/bench.rake +40 -0
- data/tasks/test.rake +3 -3
- metadata +29 -29
- data/lib/alf/sequel/compiler/predicate.rb +0 -76
- data/spec/alf.db +0 -0
- data/spec/compiler/test_clip.rb +0 -40
- data/spec/compiler/test_compact.rb +0 -18
- data/spec/compiler/test_extend.rb +0 -16
- data/spec/compiler/test_frame.rb +0 -89
- data/spec/compiler/test_intersect.rb +0 -18
- data/spec/compiler/test_join.rb +0 -26
- data/spec/compiler/test_leaf_operand.rb +0 -24
- data/spec/compiler/test_matching.rb +0 -34
- data/spec/compiler/test_not_matching.rb +0 -34
- data/spec/compiler/test_page.rb +0 -86
- data/spec/compiler/test_predicate.rb +0 -141
- data/spec/compiler/test_project.rb +0 -64
- data/spec/compiler/test_rename.rb +0 -26
- data/spec/compiler/test_restrict.rb +0 -48
- data/spec/compiler/test_sort.rb +0 -18
- data/spec/compiler/test_union.rb +0 -18
- data/spec/compiler_helper.rb +0 -34
- data/spec/fixtures/sap.rb +0 -43
- data/tasks/fixtures.rake +0 -12
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "intersect" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'when the operand is fully compilable' do
|
9
|
-
let(:expr){ intersect(suppliers, supplies) }
|
10
|
-
|
11
|
-
specify do
|
12
|
-
subject.sql.should eq("SELECT * FROM (SELECT * FROM `suppliers` AS 't1' INTERSECT SELECT * FROM `supplies` AS 't2') AS 't3'")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/spec/compiler/test_join.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "join" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'when the operand is fully compilable' do
|
9
|
-
let(:expr){ join(suppliers, supplies) }
|
10
|
-
|
11
|
-
specify do
|
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'")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "leaf_operand" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'on the proper context' do
|
9
|
-
let(:expr){ suppliers }
|
10
|
-
|
11
|
-
it{ should be_a(Cog) }
|
12
|
-
end
|
13
|
-
|
14
|
-
context 'on another context' do
|
15
|
-
let(:expr){ Algebra.named_operand(:suppliers, self) }
|
16
|
-
|
17
|
-
pending "support for multiple context is needed" do
|
18
|
-
it{ should_not be_a(Cog) }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "matching" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'when no common attributes' do
|
9
|
-
let(:expr){ matching(suppliers, project(supplies, [:part_id])) }
|
10
|
-
|
11
|
-
specify do
|
12
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (EXISTS (SELECT DISTINCT `t2`.`part_id` FROM `supplies` AS 't2'))")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when only one common attributes' do
|
17
|
-
let(:expr){ matching(suppliers, supplies) }
|
18
|
-
|
19
|
-
specify do
|
20
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (`t1`.`sid` IN (SELECT `t2`.`sid` FROM `supplies` AS 't2'))")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when many common attributes' do
|
25
|
-
let(:expr){ matching(suppliers, parts) }
|
26
|
-
|
27
|
-
specify do
|
28
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (EXISTS (SELECT * FROM `parts` AS 't2' WHERE ((`t1`.`name` = `t2`.`name`) AND (`t1`.`city` = `t2`.`city`))))")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "not_matching" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'when no common attributes' do
|
9
|
-
let(:expr){ not_matching(suppliers, project(supplies, [:part_id])) }
|
10
|
-
|
11
|
-
specify do
|
12
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE NOT (EXISTS (SELECT DISTINCT `t2`.`part_id` FROM `supplies` AS 't2'))")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when only one common attributes' do
|
17
|
-
let(:expr){ not_matching(suppliers, supplies) }
|
18
|
-
|
19
|
-
specify do
|
20
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (`t1`.`sid` NOT IN (SELECT `t2`.`sid` FROM `supplies` AS 't2'))")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when many common attributes' do
|
25
|
-
let(:expr){ not_matching(suppliers, parts) }
|
26
|
-
|
27
|
-
specify do
|
28
|
-
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE NOT (EXISTS (SELECT * FROM `parts` AS 't2' WHERE ((`t1`.`name` = `t2`.`name`) AND (`t1`.`city` = `t2`.`city`))))")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
data/spec/compiler/test_page.rb
DELETED
@@ -1,86 +0,0 @@
|
|
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
|
@@ -1,141 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
class Compiler
|
5
|
-
describe Predicate do
|
6
|
-
|
7
|
-
let(:p) { Alf::Predicate }
|
8
|
-
let(:compiler) { Predicate.new }
|
9
|
-
let(:dataset) { sap.cog(:suppliers).dataset }
|
10
|
-
let(:compiled) { compiler.call(expr) }
|
11
|
-
|
12
|
-
subject{ dataset.literal(compiled) }
|
13
|
-
|
14
|
-
context 'tautology' do
|
15
|
-
let(:expr){ p.tautology }
|
16
|
-
|
17
|
-
it{ should eq("(1 = 1)") }
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'contradiction' do
|
21
|
-
let(:expr){ p.contradiction }
|
22
|
-
|
23
|
-
it{ should eq("(1 = 0)") }
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'var_ref' do
|
27
|
-
let(:expr){ p.var_ref(:x) }
|
28
|
-
|
29
|
-
it{ should eq("`x`") }
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'literal' do
|
33
|
-
let(:expr){ p.literal(12) }
|
34
|
-
|
35
|
-
it{ should eq("12") }
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'eq(var, literal)' do
|
39
|
-
let(:expr){ p.eq(:x, 12) }
|
40
|
-
|
41
|
-
it{ should eq("(`x` = 12)") }
|
42
|
-
end
|
43
|
-
|
44
|
-
context 'neq(var, literal)' do
|
45
|
-
let(:expr){ p.neq(:x, 12) }
|
46
|
-
|
47
|
-
it{ should eq("(`x` != 12)") }
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'eq(var, nil)' do
|
51
|
-
let(:expr){ p.eq(:x, nil) }
|
52
|
-
|
53
|
-
it{ should eq("(`x` IS NULL)") }
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'eq(var, var)' do
|
57
|
-
let(:expr){ p.eq(:x, :y) }
|
58
|
-
|
59
|
-
it{ should eq("(`x` = `y`)") }
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'lt(var, literal)' do
|
63
|
-
let(:expr){ p.lt(:x, 2) }
|
64
|
-
|
65
|
-
it{ should eq("(`x` < 2)") }
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'lte(var, literal)' do
|
69
|
-
let(:expr){ p.lte(:x, 2) }
|
70
|
-
|
71
|
-
it{ should eq("(`x` <= 2)") }
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'gt(var, literal)' do
|
75
|
-
let(:expr){ p.gt(:x, 2) }
|
76
|
-
|
77
|
-
it{ should eq("(`x` > 2)") }
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'gte(var, literal)' do
|
81
|
-
let(:expr){ p.gte(:x, 2) }
|
82
|
-
|
83
|
-
it{ should eq("(`x` >= 2)") }
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'not(var)' do
|
87
|
-
let(:expr){ p.not(:x) }
|
88
|
-
|
89
|
-
it{ should eq("NOT `x`") }
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'not(tautology)' do
|
93
|
-
let(:expr){ p.not(true) }
|
94
|
-
|
95
|
-
it{ should eq("(1 = 0)") }
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'and' do
|
99
|
-
let(:expr){ p.eq(:x, 2) & p.eq(:y, 3) }
|
100
|
-
|
101
|
-
it{ should eq("((`x` = 2) AND (`y` = 3))") }
|
102
|
-
end
|
103
|
-
|
104
|
-
context 'or' do
|
105
|
-
let(:expr){ p.eq(:x, 2) | p.eq(:y, 3) }
|
106
|
-
|
107
|
-
it{ should eq("((`x` = 2) OR (`y` = 3))") }
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'comp' do
|
111
|
-
let(:expr){ p.comp(:lt, :x => 2, :y => 3) }
|
112
|
-
|
113
|
-
it{ should eq("((`x` < 2) AND (`y` < 3))") }
|
114
|
-
end
|
115
|
-
|
116
|
-
context 'in' do
|
117
|
-
let(:expr){ p.in(:x, [2, 3]) }
|
118
|
-
|
119
|
-
it{ should eq("(`x` IN (2, 3))") }
|
120
|
-
end
|
121
|
-
|
122
|
-
context 'in with a dataset at right' do
|
123
|
-
let(:expr){ p.in(:x, dataset) }
|
124
|
-
|
125
|
-
it{ should eq("(`x` IN (SELECT * FROM `suppliers`))") }
|
126
|
-
end
|
127
|
-
|
128
|
-
context 'native' do
|
129
|
-
let(:expr){ p.native(lambda{}) }
|
130
|
-
|
131
|
-
specify{
|
132
|
-
lambda{
|
133
|
-
subject
|
134
|
-
}.should throw_symbol(:pass)
|
135
|
-
}
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "project" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'when the operand is fully compilable' do
|
9
|
-
let(:expr){ project(suppliers, [:sid, :name]) }
|
10
|
-
|
11
|
-
specify{
|
12
|
-
subject.sql.should eq("SELECT `t1`.`sid`, `t1`.`name` FROM `suppliers` AS 't1'")
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when the operand is fully compilable (distinct needed)' do
|
17
|
-
let(:expr){ project(suppliers, [:city]) }
|
18
|
-
|
19
|
-
specify{
|
20
|
-
subject.sql.should eq("SELECT DISTINCT `t1`.`city` FROM `suppliers` AS 't1'")
|
21
|
-
}
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when the operand is a restriction on a key part' do
|
25
|
-
let(:expr){ project(restrict(supplies, Predicate.eq(:sid, 1)), [:pid]) }
|
26
|
-
|
27
|
-
specify{
|
28
|
-
subject.sql.should eq("SELECT `t1`.`pid` FROM `supplies` AS 't1' WHERE (`t1`.`sid` = 1)")
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'when the operand is a restriction on the key' do
|
33
|
-
let(:expr){ project(restrict(suppliers, Predicate.eq(:sid, 1)), [:sid]) }
|
34
|
-
|
35
|
-
specify{
|
36
|
-
subject.sql.should eq("SELECT `t1`.`sid` FROM `suppliers` AS 't1' WHERE (`t1`.`sid` = 1)")
|
37
|
-
}
|
38
|
-
end
|
39
|
-
|
40
|
-
context 'when the operand is fully compilable (allbut, distinct)' do
|
41
|
-
let(:expr){ project(suppliers, [:sid, :name, :status], :allbut => true) }
|
42
|
-
|
43
|
-
specify{
|
44
|
-
subject.sql.should eq("SELECT DISTINCT `t1`.`city` FROM `suppliers` AS 't1'")
|
45
|
-
}
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'when the operand is a renaming' do
|
49
|
-
let(:expr){ project(rename(suppliers, :sid => :supplier_id), [:supplier_id]) }
|
50
|
-
|
51
|
-
specify{
|
52
|
-
subject.sql.should eq("SELECT `t2`.`supplier_id` AS 'supplier_id' FROM (SELECT `t1`.`sid` AS 'supplier_id', `t1`.`name` AS 'name', `t1`.`status` AS 'status', `t1`.`city` AS 'city' FROM `suppliers` AS 't1') AS 't2'")
|
53
|
-
}
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'when the operand is not compilable' do
|
57
|
-
let(:expr){ project(an_operand, [:sid, :name]) }
|
58
|
-
|
59
|
-
it{ should be_a(Engine::Cog) }
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'compiler_helper'
|
2
|
-
module Alf
|
3
|
-
module Sequel
|
4
|
-
describe Compiler, "rename" do
|
5
|
-
|
6
|
-
subject{ compile(expr) }
|
7
|
-
|
8
|
-
context 'when the operand is fully compilable' do
|
9
|
-
let(:expr){ rename(suppliers, :sid => :id) }
|
10
|
-
|
11
|
-
specify{
|
12
|
-
subject.sql.should eq("SELECT * FROM (SELECT `t1`.`sid` AS 'id', `t1`.`name` AS 'name', `t1`.`status` AS 'status', `t1`.`city` AS 'city' FROM `suppliers` AS 't1') AS 't2'")
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'when the operand is another renaming' do
|
17
|
-
let(:expr){ rename(rename(suppliers, :sid => :id), :id => :foo) }
|
18
|
-
|
19
|
-
specify{
|
20
|
-
subject.sql.should eq("SELECT * FROM (SELECT `t2`.`id` AS 'foo', `t2`.`name` AS 'name', `t2`.`status` AS 'status', `t2`.`city` AS 'city' FROM (SELECT `t1`.`sid` AS 'id', `t1`.`name` AS 'name', `t1`.`status` AS 'status', `t1`.`city` AS 'city' FROM `suppliers` AS 't1') AS 't2') AS 't3'")
|
21
|
-
}
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|