mao 0.0.8 → 0.1.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.
- 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 [](http://travis-ci.org/kivikakk/mao) [](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.
|