mao 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.autotest +0 -0
- data/.gitignore +2 -0
- data/.rspec +0 -0
- data/.travis.yml +0 -0
- data/Gemfile +0 -0
- data/README.md +1 -1
- data/Rakefile +0 -0
- data/TODO +0 -0
- data/lib/mao/filter.rb +0 -0
- data/lib/mao/query.rb +0 -0
- data/lib/mao/version.rb +1 -1
- data/lib/mao.rb +0 -0
- data/mao.gemspec +3 -3
- data/spec/filter_spec.rb +69 -58
- data/spec/fixture.sql +0 -0
- data/spec/mao_spec.rb +104 -104
- data/spec/query_spec.rb +212 -108
- data/spec/spec_helper.rb +0 -0
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77c4066b8df0f753d381b77e61e32efefb480d9a
|
4
|
+
data.tar.gz: 6dc61214eb92e8d9e8778019ae2288cbd4d40e87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bd7e041fcd8ae0a095397dc7f03e7ca720d64f28ab3a89817d73167206a62c9f2f34330c540be6440fc8276dac1973efc4a53551ae064867acee4c4ca91bf35
|
7
|
+
data.tar.gz: 59551232080705659ab3aec1859e3936ef9437984c7032aa20b40a6eb75a49ed281458542e938a62cc80a7dabe95d49d93940a2481bc7e01590eb7b975e477d3
|
data/.autotest
CHANGED
File without changes
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
File without changes
|
data/.travis.yml
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Mao [![Build Status](https://secure.travis-ci.org/
|
1
|
+
# Mao [![Build Status](https://secure.travis-ci.org/kivikakk/mao.png)](http://travis-ci.org/kivikakk/mao) [![Dependency Status](https://gemnasium.com/kivikakk/mao.png)](https://gemnasium.com/kivikakk/mao)
|
2
2
|
|
3
3
|
**Mao Ain't an ORM.**
|
4
4
|
|
data/Rakefile
CHANGED
File without changes
|
data/TODO
CHANGED
File without changes
|
data/lib/mao/filter.rb
CHANGED
File without changes
|
data/lib/mao/query.rb
CHANGED
File without changes
|
data/lib/mao/version.rb
CHANGED
data/lib/mao.rb
CHANGED
File without changes
|
data/mao.gemspec
CHANGED
@@ -5,11 +5,11 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.email = ["allen.timothy.email@gmail.com", "rubygems@kivikakk.ee"]
|
6
6
|
gem.description = %q{Mao Ain't an ORM}
|
7
7
|
gem.summary = %q{A database access layer. Currently supports PG.}
|
8
|
-
gem.homepage = "https://github.com/
|
8
|
+
gem.homepage = "https://github.com/kivikakk/mao"
|
9
9
|
|
10
|
-
gem.add_dependency('pg', '~> 0.
|
10
|
+
gem.add_dependency('pg', '~> 0.18.4')
|
11
11
|
gem.add_development_dependency('rake')
|
12
|
-
gem.add_development_dependency('rspec')
|
12
|
+
gem.add_development_dependency('rspec', '~> 3.0')
|
13
13
|
|
14
14
|
gem.files = `git ls-files`.split($\)
|
15
15
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/spec/filter_spec.rb
CHANGED
@@ -8,120 +8,120 @@ describe Mao::Filter do
|
|
8
8
|
|
9
9
|
describe ".finalize_or_literal" do
|
10
10
|
context "with Mao::Filter" do
|
11
|
-
before { col_x.
|
11
|
+
before { expect(col_x).to receive(:finalize).
|
12
12
|
with(no_args).and_return("blah") }
|
13
|
-
it { Mao::Filter.finalize_or_literal(col_x).
|
13
|
+
it { expect(Mao::Filter.finalize_or_literal(col_x)).to eq "blah" }
|
14
14
|
end
|
15
15
|
|
16
16
|
context "with non-Mao::Filter" do
|
17
|
-
before { Mao.
|
17
|
+
before { expect(Mao).to receive(:escape_literal).
|
18
18
|
with(42).and_return("ha") }
|
19
|
-
it { Mao::Filter.finalize_or_literal(42).
|
19
|
+
it { expect(Mao::Filter.finalize_or_literal(42)).to eq "ha" }
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
describe ".sql" do
|
24
24
|
context "Arrays" do
|
25
25
|
let(:klass) { double("klass") }
|
26
|
-
before { Mao::Filter.
|
26
|
+
before { expect(Mao::Filter).to receive(:const_get).
|
27
27
|
with(:Hullo).and_return(klass) }
|
28
|
-
before { klass.
|
29
|
-
it { Mao::Filter.sql([:Hullo, :mao]).
|
28
|
+
before { expect(klass).to receive(:sql).with(:mao).and_return :dengxiaoping }
|
29
|
+
it { expect(Mao::Filter.sql([:Hullo, :mao])).to eq :dengxiaoping }
|
30
30
|
end
|
31
31
|
|
32
32
|
context "Strings" do
|
33
|
-
it { Mao::Filter.sql("BATTLE ROYALE").
|
33
|
+
it { expect(Mao::Filter.sql("BATTLE ROYALE")).to eq "BATTLE ROYALE" }
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
describe "#and" do
|
38
38
|
subject { col_x.and(col_y) }
|
39
39
|
|
40
|
-
it {
|
41
|
-
it { subject.options[:op].
|
42
|
-
it { subject.options[:lhs].
|
43
|
-
it { subject.options[:rhs].
|
40
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
41
|
+
it { expect(subject.options[:op]).to eq "AND" }
|
42
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
43
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "#or" do
|
47
47
|
subject { col_x.or(col_y) }
|
48
48
|
|
49
|
-
it {
|
50
|
-
it { subject.options[:op].
|
51
|
-
it { subject.options[:lhs].
|
52
|
-
it { subject.options[:rhs].
|
49
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
50
|
+
it { expect(subject.options[:op]).to eq "OR" }
|
51
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
52
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "#==" do
|
56
56
|
subject { col_x == col_y }
|
57
57
|
|
58
|
-
it {
|
59
|
-
it { subject.options[:op].
|
60
|
-
it { subject.options[:lhs].
|
61
|
-
it { subject.options[:rhs].
|
58
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
59
|
+
it { expect(subject.options[:op]).to eq "=" }
|
60
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
61
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
62
62
|
end
|
63
63
|
|
64
64
|
describe "#!=" do
|
65
65
|
subject { col_x != col_y }
|
66
66
|
|
67
|
-
it {
|
68
|
-
it { subject.options[:op].
|
69
|
-
it { subject.options[:lhs].
|
70
|
-
it { subject.options[:rhs].
|
67
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
68
|
+
it { expect(subject.options[:op]).to eq "<>" }
|
69
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
70
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
71
71
|
end
|
72
72
|
|
73
73
|
describe "#>" do
|
74
74
|
subject { col_x > col_y }
|
75
75
|
|
76
|
-
it {
|
77
|
-
it { subject.options[:op].
|
78
|
-
it { subject.options[:lhs].
|
79
|
-
it { subject.options[:rhs].
|
76
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
77
|
+
it { expect(subject.options[:op]).to eq ">" }
|
78
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
79
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
80
80
|
end
|
81
81
|
|
82
82
|
describe "#>=" do
|
83
83
|
subject { col_x >= col_y }
|
84
84
|
|
85
|
-
it {
|
86
|
-
it { subject.options[:op].
|
87
|
-
it { subject.options[:lhs].
|
88
|
-
it { subject.options[:rhs].
|
85
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
86
|
+
it { expect(subject.options[:op]).to eq ">=" }
|
87
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
88
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
89
89
|
end
|
90
90
|
|
91
91
|
describe "#<" do
|
92
92
|
subject { col_x < col_y }
|
93
93
|
|
94
|
-
it {
|
95
|
-
it { subject.options[:op].
|
96
|
-
it { subject.options[:lhs].
|
97
|
-
it { subject.options[:rhs].
|
94
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
95
|
+
it { expect(subject.options[:op]).to eq "<" }
|
96
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
97
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
98
98
|
end
|
99
99
|
|
100
100
|
describe "#<=" do
|
101
101
|
subject { col_x <= col_y }
|
102
102
|
|
103
|
-
it {
|
104
|
-
it { subject.options[:op].
|
105
|
-
it { subject.options[:lhs].
|
106
|
-
it { subject.options[:rhs].
|
103
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
104
|
+
it { expect(subject.options[:op]).to eq "<=" }
|
105
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
106
|
+
it { expect(subject.options[:rhs]).to be col_y }
|
107
107
|
end
|
108
108
|
|
109
109
|
describe "#null?" do
|
110
110
|
subject { col_x.null? }
|
111
111
|
|
112
|
-
it {
|
113
|
-
it { subject.options[:op].
|
114
|
-
it { subject.options[:lhs].
|
115
|
-
it { subject.options[:rhs].
|
112
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
113
|
+
it { expect(subject.options[:op]).to eq "IS" }
|
114
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
115
|
+
it { expect(subject.options[:rhs]).to be_nil }
|
116
116
|
end
|
117
117
|
|
118
118
|
describe "#in" do
|
119
119
|
subject { col_x.in([1, 2, 3]) }
|
120
120
|
|
121
|
-
it {
|
122
|
-
it { subject.options[:op].
|
123
|
-
it { subject.options[:lhs].
|
124
|
-
it { subject.options[:rhs].
|
121
|
+
it { is_expected.to be_an_instance_of Mao::Filter::Binary }
|
122
|
+
it { expect(subject.options[:op]).to eq "IN" }
|
123
|
+
it { expect(subject.options[:lhs]).to be col_x }
|
124
|
+
it { expect(subject.options[:rhs]).to eq [1, 2, 3] }
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -130,14 +130,22 @@ describe Mao::Filter::Column do
|
|
130
130
|
|
131
131
|
context "without table" do
|
132
132
|
subject { Mao::Filter::Column.new(:name => :Margorth) }
|
133
|
-
|
134
|
-
|
133
|
+
|
134
|
+
describe '#finalize' do
|
135
|
+
subject { super().finalize }
|
136
|
+
it { is_expected.to eq [:Column, :Margorth] }
|
137
|
+
end
|
138
|
+
it { expect(Mao::Filter.sql(subject.finalize)).to eq '"Margorth"' }
|
135
139
|
end
|
136
140
|
|
137
141
|
context "with table" do
|
138
142
|
subject { Mao::Filter::Column.new(:table => :Lol, :name => :Margorth) }
|
139
|
-
|
140
|
-
|
143
|
+
|
144
|
+
describe '#finalize' do
|
145
|
+
subject { super().finalize }
|
146
|
+
it { is_expected.to eq [:Column, :Lol, :Margorth] }
|
147
|
+
end
|
148
|
+
it { expect(Mao::Filter.sql(subject.finalize)).to eq '"Lol"."Margorth"' }
|
141
149
|
end
|
142
150
|
end
|
143
151
|
|
@@ -145,8 +153,11 @@ describe Mao::Filter::Binary do
|
|
145
153
|
before { prepare_spec }
|
146
154
|
subject { Mao::Filter::Binary.new(:lhs => 42, :op => '=', :rhs => 42) }
|
147
155
|
|
148
|
-
|
149
|
-
|
156
|
+
describe '#finalize' do
|
157
|
+
subject { super().finalize }
|
158
|
+
it { is_expected.to eq [:Binary, '=', "42", "42"] }
|
159
|
+
end
|
160
|
+
it { expect(Mao::Filter.sql(subject.finalize)).to eq "(42 = 42)" }
|
150
161
|
end
|
151
162
|
|
152
163
|
describe Mao::Filter::Table do
|
@@ -154,14 +165,14 @@ describe Mao::Filter::Table do
|
|
154
165
|
|
155
166
|
context "non-explicit" do
|
156
167
|
let(:some) { Mao::Filter::Table.new(Mao.query(:some), false) }
|
157
|
-
it { some.value.
|
158
|
-
it { some.value.finalize.
|
168
|
+
it { expect(some.value).to be_an_instance_of Mao::Filter::Column }
|
169
|
+
it { expect(some.value.finalize).to eq [:Column, :value] }
|
159
170
|
end
|
160
171
|
|
161
172
|
context "explicit" do
|
162
173
|
let(:some) { Mao::Filter::Table.new(Mao.query(:some), true) }
|
163
|
-
it { some.value.
|
164
|
-
it { some.value.finalize.
|
174
|
+
it { expect(some.value).to be_an_instance_of Mao::Filter::Column }
|
175
|
+
it { expect(some.value.finalize).to eq [:Column, :some, :value] }
|
165
176
|
end
|
166
177
|
|
167
178
|
context "non-extant" do
|
data/spec/fixture.sql
CHANGED
File without changes
|
data/spec/mao_spec.rb
CHANGED
@@ -7,117 +7,117 @@ describe Mao do
|
|
7
7
|
describe ".connect!" do
|
8
8
|
let(:options) { double("options") }
|
9
9
|
let(:conn) { double("conn") }
|
10
|
-
before { PG.
|
11
|
-
before { conn.
|
10
|
+
before { expect(PG).to receive(:connect).with(options).and_return(conn) }
|
11
|
+
before { expect(conn).to receive(:internal_encoding=).with(Encoding::UTF_8) }
|
12
12
|
before { Mao.disconnect! rescue false }
|
13
13
|
it { Mao.connect!(options) }
|
14
14
|
after { Mao.instance_variable_set("@conn", nil) }
|
15
15
|
end
|
16
16
|
|
17
17
|
describe ".disconnect!" do
|
18
|
-
before { PG::Connection.
|
18
|
+
before { expect_any_instance_of(PG::Connection).to receive(:close) }
|
19
19
|
it { Mao.disconnect! }
|
20
20
|
end
|
21
21
|
|
22
22
|
describe ".sql" do
|
23
|
-
before { PG::Connection.
|
23
|
+
before { expect_any_instance_of(PG::Connection).to receive(:exec).
|
24
24
|
with(:x).and_return(:y) }
|
25
|
-
it { Mao.sql(:x).
|
25
|
+
it { expect(Mao.sql(:x)).to eq :y }
|
26
26
|
end
|
27
27
|
|
28
28
|
describe ".quote_ident" do
|
29
29
|
context "pass-thru" do
|
30
|
-
before { PG::Connection.
|
30
|
+
before { expect_any_instance_of(PG::Connection).to receive(:quote_ident).
|
31
31
|
with("table").and_return(%q{"table"}) }
|
32
|
-
it { Mao.quote_ident("table").
|
32
|
+
it { expect(Mao.quote_ident("table")).to eq %q{"table"} }
|
33
33
|
end
|
34
34
|
|
35
35
|
context "Symbols" do
|
36
|
-
before { PG::Connection.
|
36
|
+
before { expect_any_instance_of(PG::Connection).to receive(:quote_ident).
|
37
37
|
with("table").and_return(%q{"table"}) }
|
38
|
-
it { Mao.quote_ident(:table).
|
38
|
+
it { expect(Mao.quote_ident(:table)).to eq %q{"table"} }
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
describe ".escape_literal" do
|
43
43
|
describe "verify pass-thru String" do
|
44
|
-
before { PG::Connection.
|
44
|
+
before { expect_any_instance_of(PG::Connection).to receive(:escape_literal).
|
45
45
|
with("table").and_return(%q{'table'}) }
|
46
|
-
it { Mao.escape_literal("table").
|
46
|
+
it { expect(Mao.escape_literal("table")).to eq %q{'table'} }
|
47
47
|
end
|
48
48
|
|
49
49
|
describe "verify not pass-thru others" do
|
50
|
-
before { PG::Connection.
|
51
|
-
|
52
|
-
it { Mao.escape_literal(nil).
|
50
|
+
before { expect_any_instance_of(PG::Connection).
|
51
|
+
not_to receive(:escape_literal) }
|
52
|
+
it { expect(Mao.escape_literal(nil)).to eq "null" }
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "verify escape_literal-less PG::Connection" do
|
56
|
-
before { PG::Connection.
|
56
|
+
before { expect_any_instance_of(PG::Connection).to receive(:respond_to?).
|
57
57
|
with(:escape_literal).and_return(false) }
|
58
|
-
before { PG::Connection.
|
58
|
+
before { expect_any_instance_of(PG::Connection).to receive(:escape_string).
|
59
59
|
with("xyz'hah").and_return("xyz''hah") }
|
60
|
-
it { Mao.escape_literal("xyz'hah").
|
60
|
+
it { expect(Mao.escape_literal("xyz'hah")).to eq %q{'xyz''hah'} }
|
61
61
|
end
|
62
62
|
|
63
63
|
describe "actual values" do
|
64
|
-
it { Mao.escape_literal("table").
|
65
|
-
it { Mao.escape_literal(42).
|
66
|
-
it { Mao.escape_literal(true).
|
67
|
-
it { Mao.escape_literal(false).
|
68
|
-
it { Mao.escape_literal(nil).
|
69
|
-
it { Mao.escape_literal([]).
|
70
|
-
it { Mao.escape_literal([1]).
|
71
|
-
it { Mao.escape_literal([1, "xzy"]).
|
72
|
-
it { Mao.escape_literal(Mao::Query.raw("\n\"'%")).
|
64
|
+
it { expect(Mao.escape_literal("table")).to eq %q{'table'} }
|
65
|
+
it { expect(Mao.escape_literal(42)).to eq %q{42} }
|
66
|
+
it { expect(Mao.escape_literal(true)).to eq %q{true} }
|
67
|
+
it { expect(Mao.escape_literal(false)).to eq %q{false} }
|
68
|
+
it { expect(Mao.escape_literal(nil)).to eq %q{null} }
|
69
|
+
it { expect(Mao.escape_literal([])).to eq %q{(null)} }
|
70
|
+
it { expect(Mao.escape_literal([1])).to eq %q{(1)} }
|
71
|
+
it { expect(Mao.escape_literal([1, "xzy"])).to eq %q{(1, 'xzy')} }
|
72
|
+
it { expect(Mao.escape_literal(Mao::Query.raw("\n\"'%"))).to eq "\n\"'%" }
|
73
73
|
|
74
74
|
# Times are escaped to UTC always.
|
75
|
-
it { Mao.escape_literal(Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600)).
|
76
|
-
|
77
|
-
it { Mao.escape_literal(Time.new(2012, 11, 10, 19, 45, 0, 0)).
|
78
|
-
|
79
|
-
it { Mao.escape_literal(Time.new(2012, 11, 10, 19, 45, 0.1, 0)).
|
80
|
-
|
75
|
+
it { expect(Mao.escape_literal(Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600))).
|
76
|
+
to eq %q{'2012-11-10 19:45:00.000000'} }
|
77
|
+
it { expect(Mao.escape_literal(Time.new(2012, 11, 10, 19, 45, 0, 0))).
|
78
|
+
to eq %q{'2012-11-10 19:45:00.000000'} }
|
79
|
+
it { expect(Mao.escape_literal(Time.new(2012, 11, 10, 19, 45, 0.1, 0))).
|
80
|
+
to eq %q{'2012-11-10 19:45:00.100000'} }
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
describe ".query" do
|
85
85
|
subject { Mao.query(:empty) }
|
86
|
-
it {
|
87
|
-
it {
|
86
|
+
it { is_expected.to be_an_instance_of Mao::Query }
|
87
|
+
it { is_expected.to be_frozen }
|
88
88
|
end
|
89
89
|
|
90
90
|
describe ".transaction" do
|
91
91
|
context "empty" do
|
92
|
-
before { PG::Connection.
|
92
|
+
before { expect_any_instance_of(PG::Connection).to receive(:exec).
|
93
93
|
with("BEGIN") }
|
94
|
-
before { PG::Connection.
|
94
|
+
before { expect_any_instance_of(PG::Connection).to receive(:exec).
|
95
95
|
with("COMMIT") }
|
96
96
|
it { Mao.transaction {} }
|
97
97
|
end
|
98
98
|
|
99
99
|
context "success" do
|
100
|
-
before { Mao.
|
101
|
-
before { Mao.
|
102
|
-
before { Mao.
|
103
|
-
it { Mao.transaction { Mao.sql(:some_sql) }.
|
104
|
-
|
100
|
+
before { expect(Mao).to receive(:sql).with("BEGIN") }
|
101
|
+
before { expect(Mao).to receive(:sql).with(:some_sql).and_return :ok }
|
102
|
+
before { expect(Mao).to receive(:sql).with("COMMIT") }
|
103
|
+
it { expect(Mao.transaction { Mao.sql(:some_sql) }).
|
104
|
+
to eq :ok }
|
105
105
|
end
|
106
106
|
|
107
107
|
context "failure" do
|
108
|
-
before { Mao.
|
109
|
-
before { Mao.
|
108
|
+
before { expect(Mao).to receive(:sql).with("BEGIN") }
|
109
|
+
before { expect(Mao).to receive(:sql).with(:some_sql).
|
110
110
|
and_raise(Exception.new) }
|
111
|
-
before { Mao.
|
111
|
+
before { expect(Mao).to receive(:sql).with("ROLLBACK") }
|
112
112
|
it { expect { Mao.transaction { Mao.sql(:some_sql) }
|
113
|
-
}.to raise_exception }
|
113
|
+
}.to raise_exception Exception}
|
114
114
|
end
|
115
115
|
|
116
116
|
context "rollback" do
|
117
|
-
before { Mao.
|
118
|
-
before { Mao.
|
117
|
+
before { expect(Mao).to receive(:sql).with("BEGIN") }
|
118
|
+
before { expect(Mao).to receive(:sql).with(:some_sql).
|
119
119
|
and_raise(Mao::Rollback) }
|
120
|
-
before { Mao.
|
120
|
+
before { expect(Mao).to receive(:sql).with("ROLLBACK") }
|
121
121
|
it { expect { Mao.transaction { Mao.sql(:some_sql) }
|
122
122
|
}.to_not raise_exception }
|
123
123
|
end
|
@@ -125,102 +125,102 @@ describe Mao do
|
|
125
125
|
context "nested transactions" do
|
126
126
|
# Currently not supported: the inner transactions don't add transactions
|
127
127
|
# at all.
|
128
|
-
before { Mao.
|
129
|
-
before { Mao.
|
128
|
+
before { expect(Mao).to receive(:sql).with("BEGIN").once }
|
129
|
+
before { expect(Mao).to receive(:sql).with("ROLLBACK").once }
|
130
130
|
|
131
131
|
it do
|
132
|
-
Mao.transaction { Mao.transaction { raise Mao::Rollback } }.
|
133
|
-
|
132
|
+
expect(Mao.transaction { Mao.transaction { raise Mao::Rollback } }).
|
133
|
+
to be_falsey
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
138
|
describe ".normalize_result" do
|
139
|
-
before { Mao.
|
139
|
+
before { expect(Mao).to receive(:convert_type).
|
140
140
|
with("y", "zzz").and_return("q") }
|
141
|
-
it { Mao.normalize_result({"x" => "y"}, {:x => "zzz"}).
|
142
|
-
|
141
|
+
it { expect(Mao.normalize_result({"x" => "y"}, {:x => "zzz"})).
|
142
|
+
to eq({:x => "q"}) }
|
143
143
|
end
|
144
144
|
|
145
145
|
describe ".normalize_join_result" do
|
146
146
|
let(:from) { double("from") }
|
147
147
|
let(:to) { double("to") }
|
148
148
|
|
149
|
-
before { from.
|
150
|
-
before { from.
|
151
|
-
before { to.
|
152
|
-
before { to.
|
149
|
+
before { expect(from).to receive(:table).and_return(:from) }
|
150
|
+
before { expect(from).to receive(:col_types).and_return({:a => "integer"}) }
|
151
|
+
before { expect(to).to receive(:table).and_return(:to) }
|
152
|
+
before { expect(to).to receive(:col_types).
|
153
153
|
and_return({:b => "character varying"}) }
|
154
154
|
|
155
|
-
it { Mao.normalize_join_result(
|
156
|
-
{"c1" => "1", "c2" => "2"}, from, to).
|
157
|
-
|
155
|
+
it { expect(Mao.normalize_join_result(
|
156
|
+
{"c1" => "1", "c2" => "2"}, from, to)).
|
157
|
+
to eq({:from => {:a => 1},
|
158
158
|
:to => {:b => "2"}}) }
|
159
159
|
|
160
|
-
it { Mao.normalize_join_result(
|
161
|
-
{"c1" => "1"}, from, to).
|
162
|
-
|
160
|
+
it { expect(Mao.normalize_join_result(
|
161
|
+
{"c1" => "1"}, from, to)).
|
162
|
+
to eq({:from => {:a => 1}}) }
|
163
163
|
end
|
164
164
|
|
165
165
|
describe ".convert_type" do
|
166
166
|
context "integers" do
|
167
|
-
it { Mao.convert_type(nil, "integer").
|
168
|
-
it { Mao.convert_type("42", "integer").
|
169
|
-
it { Mao.convert_type("42", "smallint").
|
170
|
-
it { Mao.convert_type("42", "bigint").
|
171
|
-
it { Mao.convert_type("42", "serial").
|
172
|
-
it { Mao.convert_type("42", "bigserial").
|
167
|
+
it { expect(Mao.convert_type(nil, "integer")).to be_nil }
|
168
|
+
it { expect(Mao.convert_type("42", "integer")).to eq 42 }
|
169
|
+
it { expect(Mao.convert_type("42", "smallint")).to eq 42 }
|
170
|
+
it { expect(Mao.convert_type("42", "bigint")).to eq 42 }
|
171
|
+
it { expect(Mao.convert_type("42", "serial")).to eq 42 }
|
172
|
+
it { expect(Mao.convert_type("42", "bigserial")).to eq 42 }
|
173
173
|
end
|
174
174
|
|
175
175
|
context "character" do
|
176
|
-
it { Mao.convert_type(nil, "character varying").
|
177
|
-
it { Mao.convert_type("blah", "character varying").
|
178
|
-
|
179
|
-
it { Mao.convert_type("blah", "character varying").encoding.
|
180
|
-
|
176
|
+
it { expect(Mao.convert_type(nil, "character varying")).to be_nil }
|
177
|
+
it { expect(Mao.convert_type("blah", "character varying")).
|
178
|
+
to eq "blah" }
|
179
|
+
it { expect(Mao.convert_type("blah", "character varying").encoding).
|
180
|
+
to be Encoding::UTF_8 }
|
181
181
|
|
182
|
-
it { Mao.convert_type(nil, "character varying(200)").
|
183
|
-
it { Mao.convert_type("blah", "character varying(200)").
|
184
|
-
|
185
|
-
it { Mao.convert_type("blah", "character varying(200)").encoding.
|
186
|
-
|
182
|
+
it { expect(Mao.convert_type(nil, "character varying(200)")).to be_nil }
|
183
|
+
it { expect(Mao.convert_type("blah", "character varying(200)")).
|
184
|
+
to eq "blah" }
|
185
|
+
it { expect(Mao.convert_type("blah", "character varying(200)").encoding).
|
186
|
+
to be Encoding::UTF_8 }
|
187
187
|
|
188
|
-
it { Mao.convert_type(nil, "text").
|
189
|
-
it { Mao.convert_type("blah", "text").
|
190
|
-
|
191
|
-
it { Mao.convert_type("blah", "text").encoding.
|
192
|
-
|
188
|
+
it { expect(Mao.convert_type(nil, "text")).to be_nil }
|
189
|
+
it { expect(Mao.convert_type("blah", "text")).
|
190
|
+
to eq "blah" }
|
191
|
+
it { expect(Mao.convert_type("blah", "text").encoding).
|
192
|
+
to be Encoding::UTF_8 }
|
193
193
|
end
|
194
194
|
|
195
195
|
context "dates" do
|
196
|
-
it { Mao.convert_type(nil, "timestamp without time zone").
|
197
|
-
|
196
|
+
it { expect(Mao.convert_type(nil, "timestamp without time zone")).
|
197
|
+
to be_nil }
|
198
198
|
# Note: without timezone is assumed to be in UTC.
|
199
|
-
it { Mao.convert_type("2012-11-10 19:45:00",
|
200
|
-
"timestamp without time zone").
|
201
|
-
|
202
|
-
it { Mao.convert_type("2012-11-10 19:45:00.1",
|
203
|
-
"timestamp without time zone").
|
204
|
-
|
199
|
+
it { expect(Mao.convert_type("2012-11-10 19:45:00",
|
200
|
+
"timestamp without time zone")).
|
201
|
+
to eq Time.new(2012, 11, 10, 19, 45, 0, 0) }
|
202
|
+
it { expect(Mao.convert_type("2012-11-10 19:45:00.1",
|
203
|
+
"timestamp without time zone")).
|
204
|
+
to eq Time.new(2012, 11, 10, 19, 45, 0.1, 0) }
|
205
205
|
end
|
206
206
|
|
207
207
|
context "booleans" do
|
208
|
-
it { Mao.convert_type(nil, "boolean").
|
209
|
-
it { Mao.convert_type("t", "boolean").
|
210
|
-
it { Mao.convert_type("f", "boolean").
|
208
|
+
it { expect(Mao.convert_type(nil, "boolean")).to be_nil }
|
209
|
+
it { expect(Mao.convert_type("t", "boolean")).to eq true }
|
210
|
+
it { expect(Mao.convert_type("f", "boolean")).to eq false }
|
211
211
|
end
|
212
212
|
|
213
213
|
context "bytea" do
|
214
|
-
it { Mao.convert_type(nil, "bytea").
|
215
|
-
it { Mao.convert_type("\\x5748415400", "bytea").
|
216
|
-
it { Mao.convert_type("\\x5748415400", "bytea").encoding.
|
217
|
-
|
214
|
+
it { expect(Mao.convert_type(nil, "bytea")).to be_nil }
|
215
|
+
it { expect(Mao.convert_type("\\x5748415400", "bytea")).to eq "WHAT\x00" }
|
216
|
+
it { expect(Mao.convert_type("\\x5748415400", "bytea").encoding).
|
217
|
+
to eq Encoding::ASCII_8BIT }
|
218
218
|
end
|
219
219
|
|
220
220
|
context "numeric" do
|
221
|
-
it { Mao.convert_type(nil, "numeric").
|
222
|
-
it { Mao.convert_type("1234567890123456.789", "numeric").
|
223
|
-
|
221
|
+
it { expect(Mao.convert_type(nil, "numeric")).to be_nil }
|
222
|
+
it { expect(Mao.convert_type("1234567890123456.789", "numeric")).
|
223
|
+
to eq BigDecimal.new("1234567890123456.789") }
|
224
224
|
end
|
225
225
|
end
|
226
226
|
end
|
data/spec/query_spec.rb
CHANGED
@@ -14,9 +14,20 @@ describe Mao::Query do
|
|
14
14
|
describe ".new" do
|
15
15
|
subject { Mao::Query.new(:table, {}, {}) }
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
describe '#table' do
|
18
|
+
subject { super().table }
|
19
|
+
it { is_expected.to be_an_instance_of Symbol }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#options' do
|
23
|
+
subject { super().options }
|
24
|
+
it { is_expected.to be_frozen }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#col_types' do
|
28
|
+
subject { super().col_types }
|
29
|
+
it { is_expected.to be_frozen }
|
30
|
+
end
|
20
31
|
|
21
32
|
context "no such table" do
|
22
33
|
it { expect { Mao::Query.new("nonextant")
|
@@ -27,15 +38,29 @@ describe Mao::Query do
|
|
27
38
|
describe "#with_options" do
|
28
39
|
subject { one.with_options(:blah => 99) }
|
29
40
|
|
30
|
-
|
31
|
-
|
41
|
+
describe '#table' do
|
42
|
+
subject { super().table }
|
43
|
+
it { is_expected.to be one.table }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#options' do
|
47
|
+
subject { super().options }
|
48
|
+
it { is_expected.to eq({:blah => 99}) }
|
49
|
+
end
|
32
50
|
end
|
33
51
|
|
34
52
|
describe "#limit" do
|
35
53
|
subject { some.limit(2) }
|
36
54
|
|
37
|
-
|
38
|
-
|
55
|
+
describe '#options' do
|
56
|
+
subject { super().options }
|
57
|
+
it { is_expected.to include(:limit => 2) }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#sql' do
|
61
|
+
subject { super().sql }
|
62
|
+
it { is_expected.to eq 'SELECT * FROM "some" LIMIT 2' }
|
63
|
+
end
|
39
64
|
|
40
65
|
context "invalid argument" do
|
41
66
|
it { expect { some.limit("2")
|
@@ -48,12 +73,12 @@ describe Mao::Query do
|
|
48
73
|
|
49
74
|
describe "#order" do
|
50
75
|
let(:asc) { some.order(:id, :asc) }
|
51
|
-
it { asc.options.
|
52
|
-
it { asc.sql.
|
76
|
+
it { expect(asc.options).to include(:order => [:id, 'ASC']) }
|
77
|
+
it { expect(asc.sql).to eq 'SELECT * FROM "some" ORDER BY "id" ASC' }
|
53
78
|
|
54
79
|
let(:desc) { one.order(:value, :desc) }
|
55
|
-
it { desc.options.
|
56
|
-
it { desc.sql.
|
80
|
+
it { expect(desc.options).to include(:order => [:value, 'DESC']) }
|
81
|
+
it { expect(desc.sql).to eq 'SELECT * FROM "one" ORDER BY "value" DESC' }
|
57
82
|
|
58
83
|
it { expect { one.order(:huh, :asc) }.to raise_exception(ArgumentError) }
|
59
84
|
it { expect { one.order(:value) }.to raise_exception(ArgumentError) }
|
@@ -64,8 +89,15 @@ describe Mao::Query do
|
|
64
89
|
describe "#only" do
|
65
90
|
subject { some.only(:id, [:value]) }
|
66
91
|
|
67
|
-
|
68
|
-
|
92
|
+
describe '#options' do
|
93
|
+
subject { super().options }
|
94
|
+
it { is_expected.to include(:only => [:id, :value]) }
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#sql' do
|
98
|
+
subject { super().sql }
|
99
|
+
it { is_expected.to eq 'SELECT "id", "value" FROM "some"' }
|
100
|
+
end
|
69
101
|
|
70
102
|
context "invalid argument" do
|
71
103
|
it { expect { some.only(42)
|
@@ -85,12 +117,22 @@ describe Mao::Query do
|
|
85
117
|
subject { some.join(:one) { one.value == some.value }.
|
86
118
|
only(:one => [:id]) }
|
87
119
|
|
88
|
-
|
89
|
-
|
120
|
+
describe '#options' do
|
121
|
+
subject { super().options }
|
122
|
+
it { is_expected.to include(:only => {:one => [:id]}) }
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#sql' do
|
126
|
+
subject { super().sql }
|
127
|
+
it { is_expected.to eq 'SELECT "one"."id" "c3" ' +
|
90
128
|
'FROM "some" ' +
|
91
129
|
'INNER JOIN "one" ' +
|
92
130
|
'ON ("one"."value" = "some"."value")' }
|
93
|
-
|
131
|
+
end
|
132
|
+
describe '#select!' do
|
133
|
+
subject { super().select! }
|
134
|
+
it { is_expected.to eq [{:one => {:id => 42}}] }
|
135
|
+
end
|
94
136
|
|
95
137
|
context "before #join" do
|
96
138
|
it { expect { some.only(:some => [:id])
|
@@ -108,9 +150,16 @@ describe Mao::Query do
|
|
108
150
|
subject { some.returning([:id], :value).
|
109
151
|
with_options(:insert => [{:value => "q"}]) }
|
110
152
|
|
111
|
-
|
112
|
-
|
153
|
+
describe '#options' do
|
154
|
+
subject { super().options }
|
155
|
+
it { is_expected.to include(:returning => [:id, :value]) }
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#sql' do
|
159
|
+
subject { super().sql }
|
160
|
+
it { is_expected.to eq 'INSERT INTO "some" ("value") ' +
|
113
161
|
'VALUES (\'q\') RETURNING "id", "value"' }
|
162
|
+
end
|
114
163
|
|
115
164
|
context "invalid argument" do
|
116
165
|
it { expect { some.returning(42)
|
@@ -130,15 +179,21 @@ describe Mao::Query do
|
|
130
179
|
describe "#where" do
|
131
180
|
subject { some.where { (id == 1).or(id > 10_000) } }
|
132
181
|
|
133
|
-
|
134
|
-
|
182
|
+
describe '#options' do
|
183
|
+
subject { super().options }
|
184
|
+
it do
|
185
|
+
is_expected.to include(:where => [:Binary,
|
135
186
|
'OR',
|
136
187
|
[:Binary, '=', [:Column, :id], "1"],
|
137
188
|
[:Binary, '>', [:Column, :id], "10000"]])
|
138
189
|
end
|
190
|
+
end
|
139
191
|
|
140
|
-
|
192
|
+
describe '#sql' do
|
193
|
+
subject { super().sql }
|
194
|
+
it { is_expected.to eq 'SELECT * FROM "some" WHERE ' \
|
141
195
|
'(("id" = 1) OR ("id" > 10000))' }
|
196
|
+
end
|
142
197
|
|
143
198
|
context "non-extant column" do
|
144
199
|
it { expect { some.where { non_extant_column == 42 }
|
@@ -149,11 +204,16 @@ describe Mao::Query do
|
|
149
204
|
subject { some.join(:one) { one.value == some.value }.
|
150
205
|
where { one.id == 42 } }
|
151
206
|
|
152
|
-
|
207
|
+
describe '#options' do
|
208
|
+
subject { super().options }
|
209
|
+
it { is_expected.to include(:where => [:Binary,
|
153
210
|
'=',
|
154
211
|
[:Column, :one, :id],
|
155
212
|
"42"]) }
|
156
|
-
|
213
|
+
end
|
214
|
+
describe '#sql' do
|
215
|
+
subject { super().sql }
|
216
|
+
it { is_expected.to eq 'SELECT "some"."id" "c1", ' +
|
157
217
|
'"some"."value" "c2", ' +
|
158
218
|
'"one"."id" "c3", ' +
|
159
219
|
'"one"."value" "c4" ' +
|
@@ -161,69 +221,78 @@ describe Mao::Query do
|
|
161
221
|
'INNER JOIN "one" ' +
|
162
222
|
'ON ("one"."value" = "some"."value") ' +
|
163
223
|
'WHERE ("one"."id" = 42)' }
|
224
|
+
end
|
164
225
|
|
165
|
-
|
226
|
+
describe '#select!' do
|
227
|
+
subject { super().select! }
|
228
|
+
it { is_expected.to eq(
|
166
229
|
[{:some => {:id => 3, :value => "你好, Dave."},
|
167
230
|
:one => {:id => 42, :value => "你好, Dave."}}]) }
|
231
|
+
end
|
168
232
|
end
|
169
233
|
|
170
234
|
context "with time values" do
|
171
|
-
it { times.select_first
|
235
|
+
it { expect(times.select_first!).to eq(
|
172
236
|
{:id => 1, :time => Time.new(2012, 11, 10, 19, 45, 0, 0)}) }
|
173
237
|
|
174
|
-
it { times.where { time == Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600) }.
|
175
|
-
select!.length.
|
176
|
-
it { times.where { time == Time.new(2012, 11, 10, 19, 45, 0, 0) }.
|
177
|
-
select!.length.
|
178
|
-
it { times.where { time == "2012-11-10 19:45:00" }.
|
179
|
-
select!.length.
|
180
|
-
it { times.where { time == "2012-11-10 19:45:00 Z" }.
|
181
|
-
select!.length.
|
182
|
-
it { times.where { time == "2012-11-10 19:45:00 +00" }.
|
183
|
-
select!.length.
|
184
|
-
it { times.where { time == "2012-11-10 19:45:00 +00:00" }.
|
185
|
-
select!.length.
|
186
|
-
it { times.where { time == "2012-11-10 19:45:00 -00" }.
|
187
|
-
select!.length.
|
188
|
-
it { times.where { time == "2012-11-10 19:45:00 -00:00" }.
|
189
|
-
select!.length.
|
190
|
-
|
191
|
-
it { times.where { time < Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600) }.
|
192
|
-
select!.length.
|
238
|
+
it { expect(times.where { time == Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600) }.
|
239
|
+
select!.length).to eq 1 }
|
240
|
+
it { expect(times.where { time == Time.new(2012, 11, 10, 19, 45, 0, 0) }.
|
241
|
+
select!.length).to eq 1 }
|
242
|
+
it { expect(times.where { time == "2012-11-10 19:45:00" }.
|
243
|
+
select!.length).to eq 1 }
|
244
|
+
it { expect(times.where { time == "2012-11-10 19:45:00 Z" }.
|
245
|
+
select!.length).to eq 1 }
|
246
|
+
it { expect(times.where { time == "2012-11-10 19:45:00 +00" }.
|
247
|
+
select!.length).to eq 1 }
|
248
|
+
it { expect(times.where { time == "2012-11-10 19:45:00 +00:00" }.
|
249
|
+
select!.length).to eq 1 }
|
250
|
+
it { expect(times.where { time == "2012-11-10 19:45:00 -00" }.
|
251
|
+
select!.length).to eq 1 }
|
252
|
+
it { expect(times.where { time == "2012-11-10 19:45:00 -00:00" }.
|
253
|
+
select!.length).to eq 1 }
|
254
|
+
|
255
|
+
it { expect(times.where { time < Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600) }.
|
256
|
+
select!.length).to eq 0 }
|
193
257
|
context "surprising results" do
|
194
258
|
# Timestamps are IGNORED for comparisons with "timestamp without time
|
195
259
|
# zone". See:
|
196
260
|
# http://postgresql.org/docs/9.1/static/datatype-datetime.html#AEN5714
|
197
|
-
it { times.where { time < "2012-11-11 6:45:00 +11" }.
|
198
|
-
select!.length.
|
199
|
-
it { times.where { time < "2012-11-11 6:45:00 +1100" }.
|
200
|
-
select!.length.
|
201
|
-
it { times.where { time < "2012-11-11 6:45:00 +11:00" }.
|
202
|
-
select!.length.
|
261
|
+
it { expect(times.where { time < "2012-11-11 6:45:00 +11" }.
|
262
|
+
select!.length).to eq 1 }
|
263
|
+
it { expect(times.where { time < "2012-11-11 6:45:00 +1100" }.
|
264
|
+
select!.length).to eq 1 }
|
265
|
+
it { expect(times.where { time < "2012-11-11 6:45:00 +11:00" }.
|
266
|
+
select!.length).to eq 1 }
|
203
267
|
end
|
204
|
-
it { times.where { time <= Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600) }.
|
205
|
-
select!.length.
|
206
|
-
it { times.where { time <= "2012-11-11 6:45:00 +11" }.
|
207
|
-
select!.length.
|
208
|
-
it { times.where { time <= "2012-11-11 6:45:00 +1100" }.
|
209
|
-
select!.length.
|
210
|
-
it { times.where { time <= "2012-11-11 6:45:00 +11:00" }.
|
211
|
-
select!.length.
|
268
|
+
it { expect(times.where { time <= Time.new(2012, 11, 11, 6, 45, 0, 11 * 3600) }.
|
269
|
+
select!.length).to eq 1 }
|
270
|
+
it { expect(times.where { time <= "2012-11-11 6:45:00 +11" }.
|
271
|
+
select!.length).to eq 1 }
|
272
|
+
it { expect(times.where { time <= "2012-11-11 6:45:00 +1100" }.
|
273
|
+
select!.length).to eq 1 }
|
274
|
+
it { expect(times.where { time <= "2012-11-11 6:45:00 +11:00" }.
|
275
|
+
select!.length).to eq 1 }
|
212
276
|
end
|
213
277
|
end
|
214
278
|
|
215
279
|
describe "#join" do
|
216
280
|
subject { some.join(:one) { one.value == some.value } }
|
217
281
|
|
218
|
-
|
219
|
-
|
282
|
+
describe '#options' do
|
283
|
+
subject { super().options }
|
284
|
+
it do
|
285
|
+
is_expected.to include(:join => [:one,
|
220
286
|
[:Binary,
|
221
287
|
'=',
|
222
288
|
[:Column, :one, :value],
|
223
289
|
[:Column, :some, :value]]])
|
224
290
|
end
|
291
|
+
end
|
225
292
|
|
226
|
-
|
293
|
+
describe '#sql' do
|
294
|
+
subject { super().sql }
|
295
|
+
it { is_expected.to eq(
|
227
296
|
'SELECT ' +
|
228
297
|
'"some"."id" "c1", ' +
|
229
298
|
'"some"."value" "c2", ' +
|
@@ -232,22 +301,29 @@ describe Mao::Query do
|
|
232
301
|
'FROM "some" ' +
|
233
302
|
'INNER JOIN "one" ' +
|
234
303
|
'ON ("one"."value" = "some"."value")') }
|
304
|
+
end
|
235
305
|
|
236
|
-
|
306
|
+
describe '#select!' do
|
307
|
+
subject { super().select! }
|
308
|
+
it { is_expected.to eq [{:some => {:id => 3,
|
237
309
|
:value => "你好, Dave."},
|
238
310
|
:one => {:id => 42,
|
239
311
|
:value => "你好, Dave."}}] }
|
312
|
+
end
|
240
313
|
|
241
314
|
context "simple Hash joins" do
|
242
315
|
subject { some.join({:one => {:value => :id}}) }
|
243
316
|
|
244
|
-
|
245
|
-
|
317
|
+
describe '#options' do
|
318
|
+
subject { super().options }
|
319
|
+
it do
|
320
|
+
is_expected.to include(:join => [:one,
|
246
321
|
[:Binary,
|
247
322
|
'=',
|
248
323
|
[:Column, :some, :value],
|
249
324
|
[:Column, :one, :id]]])
|
250
325
|
end
|
326
|
+
end
|
251
327
|
end
|
252
328
|
end
|
253
329
|
|
@@ -260,51 +336,79 @@ describe Mao::Query do
|
|
260
336
|
{}) }
|
261
337
|
let(:empty_sure) { double("empty_sure") }
|
262
338
|
let(:empty_sql) { double("empty_sql") }
|
263
|
-
before { empty.
|
339
|
+
before { expect(empty).to receive(:with_options).
|
264
340
|
with(:update => nil).
|
265
341
|
and_return(empty_sure) }
|
266
|
-
before { empty_sure.
|
342
|
+
before { expect(empty_sure).to receive(:sql).
|
267
343
|
and_return(empty_sql) }
|
268
|
-
before { PG::Connection.
|
344
|
+
before { expect_any_instance_of(PG::Connection).to receive(:exec).
|
269
345
|
with(empty_sql).and_return(:ok) }
|
270
|
-
it { empty.select
|
346
|
+
it { expect(empty.select!).to eq :ok }
|
271
347
|
end
|
272
348
|
|
273
349
|
context "no results" do
|
274
|
-
it { empty.select
|
350
|
+
it { expect(empty.select!).to eq [] }
|
275
351
|
end
|
276
352
|
|
277
353
|
context "one result" do
|
278
354
|
subject { one.select! }
|
279
355
|
|
280
|
-
it {
|
281
|
-
it
|
282
|
-
|
356
|
+
it { is_expected.to be_an_instance_of Array }
|
357
|
+
it 'has 1 item' do
|
358
|
+
expect(subject.size).to eq(1)
|
359
|
+
end
|
360
|
+
|
361
|
+
describe '[0]' do
|
362
|
+
subject { super()[0] }
|
363
|
+
it { is_expected.to eq({:id => 42, :value => "你好, Dave."}) }
|
364
|
+
end
|
283
365
|
end
|
284
366
|
|
285
367
|
context "some results" do
|
286
368
|
subject { some.select! }
|
287
369
|
|
288
|
-
it {
|
289
|
-
it
|
370
|
+
it { is_expected.to be_an_instance_of Array }
|
371
|
+
it 'has 3 items' do
|
372
|
+
expect(subject.size).to eq(3)
|
373
|
+
end
|
374
|
+
|
375
|
+
describe '[0]' do
|
376
|
+
subject { super()[0] }
|
377
|
+
it { is_expected.to eq({:id => 1, :value => "Bah"}) }
|
378
|
+
end
|
379
|
+
|
380
|
+
describe '[1]' do
|
381
|
+
subject { super()[1] }
|
382
|
+
it { is_expected.to eq({:id => 2, :value => "Hah"}) }
|
383
|
+
end
|
290
384
|
|
291
|
-
|
292
|
-
|
293
|
-
|
385
|
+
describe '[2]' do
|
386
|
+
subject { super()[2] }
|
387
|
+
it { is_expected.to eq({:id => 3, :value => "你好, Dave."}) }
|
388
|
+
end
|
294
389
|
end
|
295
390
|
|
296
391
|
context "various types" do
|
297
392
|
subject { typey.select! }
|
298
393
|
|
299
|
-
it
|
300
|
-
|
394
|
+
it 'has 2 items' do
|
395
|
+
expect(subject.size).to eq(2)
|
396
|
+
end
|
397
|
+
|
398
|
+
describe '[0]' do
|
399
|
+
subject { super()[0] }
|
400
|
+
it { is_expected.to eq(
|
301
401
|
{:korea => true,
|
302
402
|
:japan => BigDecimal.new("1234567890123456.789"),
|
303
403
|
:china => "WHAT\x00".force_encoding(Encoding::ASCII_8BIT)}) }
|
304
|
-
|
404
|
+
end
|
405
|
+
describe '[1]' do
|
406
|
+
subject { super()[1] }
|
407
|
+
it { is_expected.to eq(
|
305
408
|
{:korea => false,
|
306
409
|
:japan => BigDecimal.new("-1234567890123456.789"),
|
307
410
|
:china => "HUH\x01\x02".force_encoding(Encoding::ASCII_8BIT)}) }
|
411
|
+
end
|
308
412
|
end
|
309
413
|
end
|
310
414
|
|
@@ -314,9 +418,9 @@ describe Mao::Query do
|
|
314
418
|
let(:empty) { Mao::Query.new("empty",
|
315
419
|
{},
|
316
420
|
{}) }
|
317
|
-
before { empty.
|
318
|
-
before { empty.
|
319
|
-
it { empty.select_first
|
421
|
+
before { expect(empty).to receive(:limit).with(1).and_return(empty) }
|
422
|
+
before { expect(empty).to receive(:select!).and_return([:ok]) }
|
423
|
+
it { expect(empty.select_first!).to eq :ok }
|
320
424
|
end
|
321
425
|
|
322
426
|
describe "#update!" do
|
@@ -326,22 +430,22 @@ describe Mao::Query do
|
|
326
430
|
{}) }
|
327
431
|
let(:empty_update) { double("empty_update") }
|
328
432
|
let(:empty_sql) { double("empty_sql") }
|
329
|
-
before { empty.
|
433
|
+
before { expect(empty).to receive(:with_options).
|
330
434
|
with(:update => {:x => :y}).
|
331
435
|
and_return(empty_update) }
|
332
|
-
before { empty_update.
|
333
|
-
before { PG::Connection.
|
436
|
+
before { expect(empty_update).to receive(:sql).and_return(empty_sql) }
|
437
|
+
before { expect_any_instance_of(PG::Connection).to receive(:exec).
|
334
438
|
with(empty_sql).and_return(:ok) }
|
335
|
-
it { empty.update!(:x => :y).
|
439
|
+
it { expect(empty.update!(:x => :y)).to eq :ok }
|
336
440
|
end
|
337
441
|
|
338
442
|
context "#sql result" do
|
339
443
|
subject { empty.with_options(:update => {:id => 44}).sql }
|
340
|
-
it {
|
444
|
+
it { is_expected.to eq 'UPDATE "empty" SET "id" = 44' }
|
341
445
|
end
|
342
446
|
|
343
447
|
context "no matches" do
|
344
|
-
it { empty.update!(:value => "y").
|
448
|
+
it { expect(empty.update!(:value => "y")).to eq 0 }
|
345
449
|
end
|
346
450
|
|
347
451
|
context "no such column" do
|
@@ -350,7 +454,7 @@ describe Mao::Query do
|
|
350
454
|
end
|
351
455
|
|
352
456
|
context "some matches" do
|
353
|
-
it { some.where { id <= 2 }.update!(:value => 'Meh').
|
457
|
+
it { expect(some.where { id <= 2 }.update!(:value => 'Meh')).to eq 2 }
|
354
458
|
end
|
355
459
|
end
|
356
460
|
|
@@ -361,46 +465,46 @@ describe Mao::Query do
|
|
361
465
|
{}) }
|
362
466
|
let(:empty_insert) { double("empty_insert") }
|
363
467
|
let(:empty_sql) { double("empty_sql") }
|
364
|
-
before { empty.
|
468
|
+
before { expect(empty).to receive(:with_options).
|
365
469
|
with(:insert => [{:x => :y}]).
|
366
470
|
and_return(empty_insert) }
|
367
|
-
before { empty_insert.
|
368
|
-
before { PG::Connection.
|
471
|
+
before { expect(empty_insert).to receive(:sql).and_return(empty_sql) }
|
472
|
+
before { expect_any_instance_of(PG::Connection).to receive(:exec).
|
369
473
|
with(empty_sql).and_return(:ok) }
|
370
|
-
it { empty.insert!([:x => :y]).
|
474
|
+
it { expect(empty.insert!([:x => :y])).to eq :ok }
|
371
475
|
end
|
372
476
|
|
373
477
|
context "#sql result" do
|
374
478
|
context "all columns alike" do
|
375
479
|
subject { empty.with_options(
|
376
480
|
:insert => [{:id => 44}, {:id => 38}]).sql }
|
377
|
-
it {
|
481
|
+
it { is_expected.to eq 'INSERT INTO "empty" ("id") VALUES (44), (38)' }
|
378
482
|
end
|
379
483
|
|
380
484
|
context "not all columns alike" do
|
381
485
|
subject { empty.with_options(
|
382
486
|
:insert => [{:id => 1}, {:value => 'z', :id => 2}]).sql }
|
383
|
-
it {
|
487
|
+
it { is_expected.to eq 'INSERT INTO "empty" ("id", "value") ' +
|
384
488
|
'VALUES (1, DEFAULT), (2, \'z\')' }
|
385
489
|
end
|
386
490
|
end
|
387
491
|
|
388
492
|
context "result" do
|
389
493
|
context "number of rows" do
|
390
|
-
it { autoid.insert!(:value => "quox").
|
391
|
-
it { autoid.insert!({:value => "lol"}, {:value => "x"}).
|
494
|
+
it { expect(autoid.insert!(:value => "quox")).to eq 1 }
|
495
|
+
it { expect(autoid.insert!({:value => "lol"}, {:value => "x"})).to eq 2 }
|
392
496
|
end
|
393
497
|
|
394
498
|
context "#returning" do
|
395
499
|
it do
|
396
|
-
autoid.returning(:id).insert!(:value => "nanana").
|
397
|
-
|
398
|
-
autoid.returning(:id).insert!(:value => "ha").
|
399
|
-
|
400
|
-
autoid.returning(:id).insert!(:value => "bah").
|
401
|
-
|
402
|
-
autoid.returning(:id).insert!({:value => "a"}, {:value => "b"}).
|
403
|
-
|
500
|
+
expect(autoid.returning(:id).insert!(:value => "nanana")).
|
501
|
+
to eq([{:id => 1}])
|
502
|
+
expect(autoid.returning(:id).insert!(:value => "ha")).
|
503
|
+
to eq([{:id => 2}])
|
504
|
+
expect(autoid.returning(:id).insert!(:value => "bah")).
|
505
|
+
to eq([{:id => 3}])
|
506
|
+
expect(autoid.returning(:id).insert!({:value => "a"}, {:value => "b"})).
|
507
|
+
to eq([{:id => 4}, {:id => 5}])
|
404
508
|
end
|
405
509
|
end
|
406
510
|
end
|
@@ -408,8 +512,8 @@ describe Mao::Query do
|
|
408
512
|
|
409
513
|
describe "reconnection" do
|
410
514
|
it do
|
411
|
-
Mao.query(:one).select
|
412
|
-
|
515
|
+
expect(Mao.query(:one).select!).to be_an_instance_of Array
|
516
|
+
skip
|
413
517
|
end
|
414
518
|
end
|
415
519
|
end
|
data/spec/spec_helper.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mao
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothy Leslie Allen
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-11-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pg
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ~>
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.
|
20
|
+
version: 0.18.4
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.
|
27
|
+
version: 0.18.4
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rake
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -43,16 +43,16 @@ dependencies:
|
|
43
43
|
name: rspec
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - ~>
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '0'
|
48
|
+
version: '3.0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ~>
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '0'
|
55
|
+
version: '3.0'
|
56
56
|
description: Mao Ain't an ORM
|
57
57
|
email:
|
58
58
|
- allen.timothy.email@gmail.com
|
@@ -79,7 +79,7 @@ files:
|
|
79
79
|
- spec/mao_spec.rb
|
80
80
|
- spec/query_spec.rb
|
81
81
|
- spec/spec_helper.rb
|
82
|
-
homepage: https://github.com/
|
82
|
+
homepage: https://github.com/kivikakk/mao
|
83
83
|
licenses: []
|
84
84
|
metadata: {}
|
85
85
|
post_install_message:
|
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
98
|
version: '0'
|
99
99
|
requirements: []
|
100
100
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.0.
|
101
|
+
rubygems_version: 2.0.14
|
102
102
|
signing_key:
|
103
103
|
specification_version: 4
|
104
104
|
summary: A database access layer. Currently supports PG.
|