alf-sequel 0.13.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 +4 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +38 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +12 -0
- data/README.md +11 -0
- data/Rakefile +11 -0
- data/lib/alf/sequel/adapter.rb +57 -0
- data/lib/alf/sequel/cog.rb +92 -0
- data/lib/alf/sequel/compiler/predicate.rb +76 -0
- data/lib/alf/sequel/compiler.rb +168 -0
- data/lib/alf/sequel/connection/connection_methods.rb +46 -0
- data/lib/alf/sequel/connection/schema_methods.rb +76 -0
- data/lib/alf/sequel/connection/update_methods.rb +63 -0
- data/lib/alf/sequel/connection.rb +23 -0
- data/lib/alf/sequel/loader.rb +2 -0
- data/lib/alf/sequel/unit_of_work/atomic.rb +35 -0
- data/lib/alf/sequel/unit_of_work/delete.rb +24 -0
- data/lib/alf/sequel/unit_of_work/insert.rb +60 -0
- data/lib/alf/sequel/unit_of_work/update.rb +60 -0
- data/lib/alf/sequel/unit_of_work.rb +11 -0
- data/lib/alf/sequel/version.rb +16 -0
- data/lib/alf/sequel.rb +7 -0
- data/lib/alf-sequel.rb +1 -0
- data/spec/adapter/test_recognize.rb +50 -0
- data/spec/alf.db +0 -0
- data/spec/compiler/test_clip.rb +40 -0
- data/spec/compiler/test_compact.rb +18 -0
- data/spec/compiler/test_extend.rb +16 -0
- data/spec/compiler/test_intersect.rb +18 -0
- data/spec/compiler/test_join.rb +18 -0
- data/spec/compiler/test_leaf_operand.rb +24 -0
- data/spec/compiler/test_matching.rb +34 -0
- data/spec/compiler/test_not_matching.rb +34 -0
- data/spec/compiler/test_predicate.rb +141 -0
- data/spec/compiler/test_project.rb +64 -0
- data/spec/compiler/test_rename.rb +26 -0
- data/spec/compiler/test_restrict.rb +48 -0
- data/spec/compiler/test_sort.rb +18 -0
- data/spec/compiler/test_union.rb +18 -0
- data/spec/compiler_helper.rb +34 -0
- data/spec/connection/test_connection_uri.rb +54 -0
- data/spec/connection/test_delete.rb +20 -0
- data/spec/connection/test_heading.rb +16 -0
- data/spec/connection/test_insert.rb +24 -0
- data/spec/connection/test_keys.rb +24 -0
- data/spec/connection/test_lock.rb +15 -0
- data/spec/connection/test_ping.rb +26 -0
- data/spec/connection/test_relvar.rb +16 -0
- data/spec/connection/test_update.rb +20 -0
- data/spec/fixtures/sap.db +0 -0
- data/spec/fixtures/sap.rb +43 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/test_assumptions.rb +14 -0
- data/spec/test_sequel.rb +10 -0
- data/spec/unit_of_work/atomic/test_run.rb +72 -0
- data/spec/unit_of_work/delete/test_delete.rb +39 -0
- data/spec/unit_of_work/insert/test_run.rb +71 -0
- data/spec/unit_of_work/update/test_run.rb +39 -0
- data/tasks/fixtures.rake +12 -0
- data/tasks/gem.rake +8 -0
- data/tasks/test.rake +6 -0
- metadata +174 -0
@@ -0,0 +1,64 @@
|
|
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
|
@@ -0,0 +1,26 @@
|
|
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
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'compiler_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Compiler, "restrict" do
|
5
|
+
|
6
|
+
subject{ compile(expr) }
|
7
|
+
|
8
|
+
context 'with a native predicate' do
|
9
|
+
let(:expr){ restrict(suppliers, proc{ status > 20 }) }
|
10
|
+
|
11
|
+
it{ should be_a(Engine::Filter) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when the operand is fully compilable' do
|
15
|
+
let(:expr){ restrict(suppliers, :name => "Jones") }
|
16
|
+
|
17
|
+
specify{
|
18
|
+
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (`t1`.`name` = 'Jones')")
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when the operand is a IN (values)' do
|
23
|
+
let(:expr){ restrict(suppliers, Predicate.in(:city, ["London", "Paris"])) }
|
24
|
+
|
25
|
+
specify{
|
26
|
+
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (`t1`.`city` IN ('London', 'Paris'))")
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when the operand is a NOT IN (values)' do
|
31
|
+
let(:expr){ restrict(suppliers, !Predicate.in(:city, ["London", "Paris"])) }
|
32
|
+
|
33
|
+
specify{
|
34
|
+
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' WHERE (`t1`.`city` NOT IN ('London', 'Paris'))")
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when the operand is a renaming' do
|
39
|
+
let(:expr){ restrict(rename(suppliers, :name => :sname), :sname => "Jones") }
|
40
|
+
|
41
|
+
specify{
|
42
|
+
subject.sql.should eq("SELECT * FROM (SELECT `t1`.`name` AS 'sname', `t1`.`sid` AS 'sid', `t1`.`status` AS 'status', `t1`.`city` AS 'city' FROM `suppliers` AS 't1') AS 't2' WHERE (`t2`.`sname` = 'Jones')")
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'compiler_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Compiler, "sort" do
|
5
|
+
|
6
|
+
subject{ compile(expr) }
|
7
|
+
|
8
|
+
context 'when the operand is fully compilable' do
|
9
|
+
let(:expr){ sort(suppliers, [ [:name, :asc], [:status, :desc] ]) }
|
10
|
+
|
11
|
+
specify{
|
12
|
+
subject.sql.should eq("SELECT * FROM `suppliers` AS 't1' ORDER BY `t1`.`name` ASC, `t1`.`status` DESC")
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'compiler_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Compiler, "union" do
|
5
|
+
|
6
|
+
subject{ compile(expr) }
|
7
|
+
|
8
|
+
context 'when the operand is fully compilable' do
|
9
|
+
let(:expr){ union(suppliers, supplies) }
|
10
|
+
|
11
|
+
specify do
|
12
|
+
subject.sql.should eq("SELECT * FROM (SELECT * FROM `suppliers` AS 't1' UNION SELECT * FROM `supplies` AS 't2') AS 't3'")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
module CompilerHelpers
|
4
|
+
include Alf::Lang::Functional
|
5
|
+
|
6
|
+
def suppliers
|
7
|
+
Alf::Algebra.named_operand(:suppliers, sap)
|
8
|
+
end
|
9
|
+
|
10
|
+
def supplies
|
11
|
+
Alf::Algebra.named_operand(:supplies, sap)
|
12
|
+
end
|
13
|
+
|
14
|
+
def parts
|
15
|
+
Alf::Algebra.named_operand(:parts, sap)
|
16
|
+
end
|
17
|
+
|
18
|
+
def _context
|
19
|
+
sap
|
20
|
+
end
|
21
|
+
|
22
|
+
def an_operand
|
23
|
+
Alf::Algebra::Operand::Fake.new(sap)
|
24
|
+
end
|
25
|
+
|
26
|
+
def compile(expr)
|
27
|
+
Alf::Sequel::Compiler.new.call(expr)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
RSpec.configure do |c|
|
33
|
+
c.include CompilerHelpers
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'connection_uri' do
|
5
|
+
|
6
|
+
subject{ conn.connection_uri(with_password) }
|
7
|
+
|
8
|
+
let(:with_password){ false }
|
9
|
+
|
10
|
+
context 'when build with an uri' do
|
11
|
+
let(:conn){ Connection.new("somewhere/to/db.sqlite3") }
|
12
|
+
|
13
|
+
it{ should eq("somewhere/to/db.sqlite3") }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when build with no host on sqlite' do
|
17
|
+
let(:conn){ Connection.new({:adapter => "sqlite", :database => "sap.db"}) }
|
18
|
+
|
19
|
+
it{ should eq("sqlite://sap.db") }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when build with no host on postgres' do
|
23
|
+
let(:conn){ Connection.new({:adapter => "postgres", :database => "sap"}) }
|
24
|
+
|
25
|
+
it{ should eq("postgres://localhost/sap") }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when build with a host but no port' do
|
29
|
+
let(:conn){ Connection.new({:adapter => "postgres", :host => "athena", :database => "sap"}) }
|
30
|
+
|
31
|
+
it{ should eq("postgres://athena/sap") }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when build with a host and a no port' do
|
35
|
+
let(:conn){ Connection.new({:adapter => "postgres", :host => "athena", :port => 1234, :database => "sap"}) }
|
36
|
+
|
37
|
+
it{ should eq("postgres://athena:1234/sap") }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when build with a user/pass and with_password=false' do
|
41
|
+
let(:conn){ Connection.new({:adapter => "postgres", :host => "athena", :user => "buly", :password => "pass", :database => "sap"}) }
|
42
|
+
|
43
|
+
it{ should eq("postgres://buly@athena/sap") }
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when build with a user/pass and with_password=true' do
|
47
|
+
let(:conn){ Connection.new({:adapter => "postgres", :host => "athena", :user => "buly", :password => "pass", :database => "sap"}) }
|
48
|
+
let(:with_password){ true }
|
49
|
+
|
50
|
+
it{ should eq("postgres://buly:pass@athena/sap") }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'delete' do
|
5
|
+
|
6
|
+
let(:conn){ sap_memory }
|
7
|
+
|
8
|
+
subject{ conn.delete(:suppliers, Predicate.tautology) }
|
9
|
+
|
10
|
+
it 'returns a UnitOfWork::Delete' do
|
11
|
+
subject.should be_a(UnitOfWork::Delete)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'is ran' do
|
15
|
+
subject.should be_ran
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'heading' do
|
5
|
+
|
6
|
+
subject{ sap.heading(:suppliers) }
|
7
|
+
|
8
|
+
let(:expected){
|
9
|
+
Heading[:sid => Integer, :name => String, :status => Integer, :city => String]
|
10
|
+
}
|
11
|
+
|
12
|
+
it{ should eq(expected) }
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'insert' do
|
5
|
+
|
6
|
+
let(:conn){ sap_memory }
|
7
|
+
|
8
|
+
subject{ conn.insert(:suppliers, suppliers) }
|
9
|
+
|
10
|
+
let(:suppliers){[
|
11
|
+
{sid: 10, name: "Marcus", status: 20, city: "Ouagadougou"}
|
12
|
+
]}
|
13
|
+
|
14
|
+
it 'returns a UnitOfWork::Insert' do
|
15
|
+
subject.should be_a(UnitOfWork::Insert)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'is ran' do
|
19
|
+
subject.should be_ran
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'keys' do
|
5
|
+
|
6
|
+
context "when only a primary key" do
|
7
|
+
subject{ sap.keys(:parts) }
|
8
|
+
|
9
|
+
let(:expected){ Keys[ [:pid] ] }
|
10
|
+
|
11
|
+
it{ should eq(expected) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when both primary key and unique index" do
|
15
|
+
subject{ sap.keys(:suppliers) }
|
16
|
+
|
17
|
+
let(:expected){ Keys[ [:sid], [:name] ] }
|
18
|
+
|
19
|
+
it{ should eq(expected) }
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, "ping" do
|
5
|
+
|
6
|
+
it "returns true on a file" do
|
7
|
+
Connection.new("#{sequel_database_path}").ping.should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns true on an uri" do
|
11
|
+
Connection.new(sequel_database_uri).ping.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns true on a Path" do
|
15
|
+
Connection.new(sequel_database_path).ping.should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "raises on non existing" do
|
19
|
+
lambda {
|
20
|
+
Connection.new("postgres://non-existing.sqlite3").ping
|
21
|
+
}.should raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'relvar' do
|
5
|
+
|
6
|
+
it "should serve relvars" do
|
7
|
+
sap.relvar(:suppliers).should be_a(Alf::Relvar)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be the correct relation" do
|
11
|
+
sap.relvar(:suppliers).value.size.should eq(5)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
describe Connection, 'update' do
|
5
|
+
|
6
|
+
let(:conn){ sap_memory }
|
7
|
+
|
8
|
+
subject{ conn.update(:suppliers, {status: 10}, Predicate.tautology) }
|
9
|
+
|
10
|
+
it 'returns a UnitOfWork::Update' do
|
11
|
+
subject.should be_a(UnitOfWork::Update)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'is ran' do
|
15
|
+
subject.should be_ran
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
Binary file
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class SAP
|
2
|
+
|
3
|
+
def self.create!(sequel_db)
|
4
|
+
sequel_db = ::Sequel.connect(sequel_db) unless sequel_db.is_a?(::Sequel::Database)
|
5
|
+
sequel_db.tap do |db|
|
6
|
+
db.create_table(:suppliers) do
|
7
|
+
primary_key :sid
|
8
|
+
String :name
|
9
|
+
Integer :status
|
10
|
+
String :city
|
11
|
+
index :name, :unique => true
|
12
|
+
end
|
13
|
+
db.create_table(:parts) do
|
14
|
+
primary_key :pid
|
15
|
+
String :name
|
16
|
+
String :color
|
17
|
+
Float :weight
|
18
|
+
String :city
|
19
|
+
end
|
20
|
+
db.create_table(:supplies) do
|
21
|
+
Integer :sid
|
22
|
+
Integer :pid
|
23
|
+
Integer :qty
|
24
|
+
primary_key [:sid, :pid]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
Alf.connect(sequel_db) do |alf_db|
|
28
|
+
ex = Alf.examples
|
29
|
+
alf_db.relvar(:suppliers).affect ex.query{
|
30
|
+
(extend suppliers, :sid => lambda{ (sid.match /\d+/)[0].to_i })
|
31
|
+
}
|
32
|
+
alf_db.relvar(:parts).affect ex.query{
|
33
|
+
(extend parts, :pid => lambda{ (pid.match /\d+/)[0].to_i })
|
34
|
+
}
|
35
|
+
alf_db.relvar(:supplies).affect ex.query{
|
36
|
+
(extend supplies, :sid => lambda{ (sid.match /\d+/)[0].to_i },
|
37
|
+
:pid => lambda{ (pid.match /\d+/)[0].to_i })
|
38
|
+
}
|
39
|
+
end
|
40
|
+
sequel_db
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require 'alf-sequel'
|
3
|
+
require "rspec"
|
4
|
+
require 'path'
|
5
|
+
require_relative 'fixtures/sap.rb'
|
6
|
+
|
7
|
+
module Helpers
|
8
|
+
|
9
|
+
def sequel_database_path
|
10
|
+
Path.dir/'alf.db'
|
11
|
+
end
|
12
|
+
|
13
|
+
def sequel_database_uri
|
14
|
+
"#{Alf::Sequel::Adapter.sqlite_protocol}://#{sequel_database_path}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def sequel_database_memory
|
18
|
+
"#{Alf::Sequel::Adapter.sqlite_protocol}::memory:"
|
19
|
+
end
|
20
|
+
|
21
|
+
def sap
|
22
|
+
@sap ||= Alf.connect Path.relative("fixtures/sap.db")
|
23
|
+
end
|
24
|
+
|
25
|
+
def sap_memory
|
26
|
+
Alf.connect(SAP.create!(sequel_database_memory), schema_cache: false)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec.configure do |c|
|
32
|
+
c.include Helpers
|
33
|
+
c.extend Helpers
|
34
|
+
c.filter_run_excluding :ruby19 => (RUBY_VERSION < "1.9")
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe "assumptions" do
|
3
|
+
|
4
|
+
context 'sqlite://memory' do
|
5
|
+
let(:db1){ ::Sequel.connect(sequel_database_memory) }
|
6
|
+
let(:db2){ ::Sequel.connect(sequel_database_memory) }
|
7
|
+
|
8
|
+
it 'leads to two different databases' do
|
9
|
+
db1.create_table(:blah){ primary_key :id }
|
10
|
+
db2.create_table(:blah){ primary_key :id }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/spec/test_sequel.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
module UnitOfWork
|
5
|
+
describe Atomic, "run" do
|
6
|
+
|
7
|
+
def build_uow(&bl)
|
8
|
+
Object.new.tap{|uow|
|
9
|
+
uow.extend(Atomic)
|
10
|
+
uow.singleton_class.send(:define_method, :_run, &bl)
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
subject{ uow.run }
|
15
|
+
|
16
|
+
context 'when the block succeeds' do
|
17
|
+
let(:uow){ build_uow{ true } }
|
18
|
+
|
19
|
+
it 'returns itself' do
|
20
|
+
subject.should be(uow)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'sets ran? to true' do
|
24
|
+
subject.should be_ran
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'sets failed? to false' do
|
28
|
+
subject.should_not be_failed
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when the block fails' do
|
33
|
+
let(:uow){ build_uow{ raise ArgumentError, "failed" } }
|
34
|
+
|
35
|
+
it 'raise the error' do
|
36
|
+
lambda{
|
37
|
+
subject
|
38
|
+
}.should raise_error(ArgumentError, "failed")
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'sets ran? to true' do
|
42
|
+
lambda{ subject }.should raise_error
|
43
|
+
uow.should be_ran
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'sets failed? to false' do
|
47
|
+
lambda{ subject }.should raise_error
|
48
|
+
uow.should be_failed
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'sets failure to the error' do
|
52
|
+
lambda{ subject }.should raise_error
|
53
|
+
uow.failure.should be_a(ArgumentError)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when already ran' do
|
58
|
+
let(:uow){ build_uow{ true } }
|
59
|
+
|
60
|
+
before{ uow.run }
|
61
|
+
|
62
|
+
it 'raises an Alf::IllegalStateError' do
|
63
|
+
lambda{
|
64
|
+
subject
|
65
|
+
}.should raise_error(IllegalStateError, /already ran/)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end # module UnitOfWork
|
71
|
+
end # module Sequel
|
72
|
+
end # module Alf
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
module Alf
|
3
|
+
module Sequel
|
4
|
+
module UnitOfWork
|
5
|
+
describe Delete, "run" do
|
6
|
+
|
7
|
+
let(:conn){ sap_memory.adapter_connection }
|
8
|
+
let(:uow){
|
9
|
+
UnitOfWork::Delete.new(conn, relvar_name, predicate)
|
10
|
+
}
|
11
|
+
subject{ uow.run }
|
12
|
+
|
13
|
+
before do
|
14
|
+
subject.should be(uow)
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when predicate is a tautology' do
|
18
|
+
let(:relvar_name){ :suppliers }
|
19
|
+
let(:predicate){ Predicate.tautology }
|
20
|
+
|
21
|
+
it 'removes all tuples' do
|
22
|
+
conn.dataset(relvar_name).should be_empty
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when predicate is not a tautology' do
|
27
|
+
let(:relvar_name){ :suppliers }
|
28
|
+
let(:predicate){ Predicate.eq(sid: 1) }
|
29
|
+
|
30
|
+
it 'removes only targetted tuples' do
|
31
|
+
conn.dataset(relvar_name).should_not be_empty
|
32
|
+
conn.dataset(relvar_name).where(sid: 1).should be_empty
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end # module UnitOfWork
|
38
|
+
end # module Sequel
|
39
|
+
end # module Alf
|