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.
Files changed (45) hide show
  1. data/Gemfile +10 -7
  2. data/Gemfile.lock +26 -14
  3. data/README.md +45 -3
  4. data/lib/alf/sequel.rb +1 -0
  5. data/lib/alf/sequel/cog.rb +23 -75
  6. data/lib/alf/sequel/compiler.rb +8 -198
  7. data/lib/alf/sequel/connection.rb +5 -1
  8. data/lib/alf/sequel/connection/connection_methods.rb +4 -2
  9. data/lib/alf/sequel/connection/schema_methods.rb +2 -6
  10. data/lib/alf/sequel/connection/update_methods.rb +1 -1
  11. data/lib/alf/sequel/loader.rb +1 -0
  12. data/lib/alf/sequel/translator.rb +198 -0
  13. data/lib/alf/sequel/unit_of_work/insert.rb +10 -4
  14. data/lib/alf/sequel/unit_of_work/update.rb +3 -3
  15. data/lib/alf/sequel/version.rb +1 -1
  16. data/spec/connection/test_heading.rb +1 -1
  17. data/spec/{fixtures/sap.db → sap.db} +0 -0
  18. data/spec/spec_helper.rb +48 -6
  19. data/spec/unit_of_work/delete/test_delete.rb +2 -2
  20. data/spec/unit_of_work/insert/test_run.rb +12 -14
  21. data/spec/unit_of_work/update/test_run.rb +1 -1
  22. data/tasks/bench.rake +40 -0
  23. data/tasks/test.rake +3 -3
  24. metadata +29 -29
  25. data/lib/alf/sequel/compiler/predicate.rb +0 -76
  26. data/spec/alf.db +0 -0
  27. data/spec/compiler/test_clip.rb +0 -40
  28. data/spec/compiler/test_compact.rb +0 -18
  29. data/spec/compiler/test_extend.rb +0 -16
  30. data/spec/compiler/test_frame.rb +0 -89
  31. data/spec/compiler/test_intersect.rb +0 -18
  32. data/spec/compiler/test_join.rb +0 -26
  33. data/spec/compiler/test_leaf_operand.rb +0 -24
  34. data/spec/compiler/test_matching.rb +0 -34
  35. data/spec/compiler/test_not_matching.rb +0 -34
  36. data/spec/compiler/test_page.rb +0 -86
  37. data/spec/compiler/test_predicate.rb +0 -141
  38. data/spec/compiler/test_project.rb +0 -64
  39. data/spec/compiler/test_rename.rb +0 -26
  40. data/spec/compiler/test_restrict.rb +0 -48
  41. data/spec/compiler/test_sort.rb +0 -18
  42. data/spec/compiler/test_union.rb +0 -18
  43. data/spec/compiler_helper.rb +0 -34
  44. data/spec/fixtures/sap.rb +0 -43
  45. 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
@@ -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
@@ -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