alf-sequel 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|