pg_helper 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,192 +1,238 @@
1
1
  require File.expand_path('../../spec_helper', __FILE__)
2
2
  include PgHelper
3
- describe QueryHelper do
3
+
4
+ require 'pg'
5
+ UNIQUE_TABLE_NAME = "pg_helper_test_#{(rand * 100_000_000).to_i}"
6
+ REAL_PARAMS = { host: 'localhost' }
7
+ RSpec.describe QueryHelper do
8
+ after(:all) do
9
+ conn = PGconn.open(REAL_PARAMS)
10
+ conn.exec("drop table if exists #{UNIQUE_TABLE_NAME} ") { true }
11
+ conn.finish
12
+ end
13
+
4
14
  describe 'connection params' do
5
- let(:params) {
15
+ let(:params) do
6
16
  {
7
- :host => 'my host',
8
- :port => 1234,
9
- :username => 'my user',
10
- :password => 'my password',
11
- :dbname => 'my base'
17
+ host: 'my host',
18
+ port: 1234,
19
+ username: 'my user',
20
+ password: 'my password',
21
+ dbname: 'my base'
12
22
  }
13
- }
23
+ end
14
24
 
15
- it 'are stored upon initializetion' do
16
- PGconn.stub!(:open => true)
17
- QueryHelper.new(params).connection_params.should == params
25
+ it 'are stored upon initialization' do
26
+ allow(PGconn).to receive(:open).and_return(true)
27
+ expect(QueryHelper.new(params).connection_params).to eq params
18
28
  end
19
29
 
20
30
  it 'are passed to pgconn' do
21
- mock(:conn).tap do |conn|
22
- PGconn.should_receive(:open).with(params).and_return(conn)
23
- QueryHelper.new(params).pg_connection.should == conn
31
+ double(:conn).tap do |conn|
32
+ allow(PGconn).to receive(:open).with(params).and_return(conn)
33
+ expect(QueryHelper.new(params).pg_connection).to eq conn
24
34
  end
25
35
  end
26
36
  end
27
37
 
28
- def build_result(params={})
29
- mock(:result,
30
- {
31
- :nfields => 1,
32
- :ntuples => 1
33
- }.merge(params)
38
+ def build_result(params = {})
39
+ double(:result,
40
+ {
41
+ nfields: 1,
42
+ ntuples: 1
43
+ }.merge(params)
34
44
  ).as_null_object
35
45
  end
36
-
37
- def mock_result(params = {}, *args)
38
- build_result(params).tap do |result_mock|
46
+
47
+ def double_result(params = {}, *args)
48
+ build_result(params).tap do |result_double|
39
49
  if args.empty?
40
- pg_helper.pg_connection.should_receive(:exec).and_return(result_mock)
50
+ allow(pg_helper.pg_connection)
51
+ .to receive(:exec).and_return(result_double)
41
52
  else
42
- pg_helper.pg_connection.should_receive(:exec).with(*args).and_return(result_mock)
53
+ allow(pg_helper.pg_connection)
54
+ .to receive(:exec).with(*args).and_return(result_double)
43
55
  end
44
56
  end
45
57
  end
46
58
 
47
- let(:pg_helper) { QueryHelper.new({:dbname => 'postgres', :host => 'localhost'})}
59
+ def pg_helper
60
+ @pg_helper ||= QueryHelper.new(REAL_PARAMS)
61
+ end
48
62
 
49
63
  describe 'single value' do
50
64
  it 'is returned as string' do
51
- pg_helper.value('select 1').should == '1'
65
+ expect(pg_helper.value('select 1')).to eq '1'
52
66
  end
53
67
 
54
68
  it 'raises error if gets non array as params' do
55
- lambda {
69
+ expect do
56
70
  pg_helper.value('select 1', 'bar')
57
- }.should raise_error(PgHelperErrorParamsMustBeArrayOfStrings)
71
+ end.to raise_error(PgHelperErrorParamsMustBeArrayOfStrings)
58
72
  end
59
73
 
60
74
  it 'allows to pass params to query' do
61
75
  param = ["foo; > 'bar'"]
62
- pg_helper.value('select $1::text', param).should == "foo; > 'bar'"
76
+ expect(pg_helper.value('select $1::text', param)).to eq "foo; > 'bar'"
63
77
  end
64
78
 
65
79
  it 'raises error if more than 1 row returned' do
66
- lambda {
80
+ expect do
67
81
  pg_helper.value('select 1, 2')
68
- }.should raise_error(PgHelperErrorInvalidColumnCount)
82
+ end.to raise_error(PgHelperErrorInvalidColumnCount)
69
83
  end
70
84
 
71
85
  it 'raises error if more than 1 row returned' do
72
- lambda {
86
+ expect do
73
87
  pg_helper.value('select 1 union select 2')
74
- }.should raise_error(PgHelperErrorInvalidRowCount)
88
+ end.to raise_error(PgHelperErrorInvalidRowCount)
75
89
  end
76
90
 
77
91
  it 'clears pg result on success' do
78
- mock_result.should_receive(:clear)
79
- pg_helper.value('foo')
92
+ expect(double_result).to receive(:clear)
93
+ pg_helper.value('select 1')
80
94
  end
81
95
 
82
96
  it 'clears pg result on failure' do
83
- lambda {
84
- mock_result({:nfields => 2}).should_receive(:clear)
97
+ expect(double_result(nfields: 2))
98
+ .to receive(:clear).and_return(true)
99
+ expect {
85
100
  pg_helper.value('foo')
86
- }
101
+ }.to raise_error
87
102
  end
88
103
  end
89
104
 
90
105
  describe 'array of column values' do
91
106
  it 'returns values of column as array of stirngs' do
92
- pg_helper.get_column( 'select 1 union (select 2 union select 3)').should == ['1','2','3']
107
+ expect(
108
+ pg_helper.get_column(
109
+ 'select 1 union (select 2 union select 3)'
110
+ )
111
+ ).to eq %w(1 2 3)
93
112
  end
94
113
 
95
114
  it 'raises error if gets non array as params' do
96
- lambda {
97
- pg_helper.get_column('select 1', 'bar')
98
- }.should raise_error(PgHelperErrorParamsMustBeArrayOfStrings)
99
- end
115
+ expect do
116
+ pg_helper.get_column('select 1', 'bar')
117
+ end.to raise_error(PgHelperErrorParamsMustBeArrayOfStrings)
118
+ end
100
119
 
101
- it 'allows to pass params to query' do
102
- param = ['foo', ";'bar'"]
103
- pg_helper.get_column('select $1::text as str union select $2::text as str order by str', param).should == [";'bar'", 'foo']
104
- end
120
+ it 'allows to pass params to query' do
121
+ param = ['foo', ";'bar'"]
122
+ expect(
123
+ pg_helper.get_column(
124
+ 'select $1::text as str union select $2::text as str order by str',
125
+ param
126
+ )
127
+ ).to eq [";'bar'", 'foo']
128
+ end
105
129
 
106
130
  it 'raises error if more than one column returned' do
107
- lambda {
131
+ expect do
108
132
  pg_helper.get_column('select 1, 2')
109
- }.should raise_error(PgHelperErrorInvalidColumnCount)
133
+ end.to raise_error(PgHelperErrorInvalidColumnCount)
110
134
  end
111
135
 
112
136
  it 'clears pg result on success' do
113
- mock_result.should_receive(:clear)
137
+ expect(double_result).to receive(:clear)
114
138
  pg_helper.get_column('foo')
115
139
  end
116
140
 
117
141
  it 'clears pg result on failure' do
118
- lambda {
119
- mock_result({:nfields => 2}).should_receive(:clear)
142
+ lambda do
143
+ expect(double_result(nfields: 2)).to receive(:clear)
120
144
  pg_helper.get_column('foo')
121
- }
145
+ end
122
146
  end
123
147
  end
124
148
 
125
149
  describe 'executing operation' do
126
- it 'returns number of rows changed by query' do
127
- pg_helper.modify('select 1').should == 0
150
+ before(:all) do
151
+ helper = pg_helper
152
+ helper.modify(<<-SQL)
153
+ CREATE TABLE IF NOT EXISTS #{UNIQUE_TABLE_NAME}
154
+ (
155
+ test_text text
156
+ )
157
+ SQL
158
+ helper.modify(
159
+ "INSERT INTO #{UNIQUE_TABLE_NAME} (test_text) values ('b')"
160
+ )
161
+ end
162
+
163
+ it 'returns number of rows inserted' do
164
+ expect(pg_helper.modify(<<-SQL)).to eq 12
165
+ INSERT INTO #{UNIQUE_TABLE_NAME} (test_text)
166
+ select n::text
167
+ FROM generate_series(1,12,1) as n
168
+ SQL
169
+ end
170
+
171
+ it 'returns number of rows updated by query' do
172
+ expect(pg_helper.modify(<<-SQL)).to eq 1
173
+ UPDATE #{UNIQUE_TABLE_NAME} SET test_text = 'c' where test_text = 'b'
174
+ SQL
128
175
  end
129
176
 
130
177
  it 'uses cmd_tuples of pg_result internally' do
131
- mock(:value).tap do |value|
132
- mock_result(:cmd_tuples => value)
133
- pg_helper.modify('foo').should == value
178
+ double(:value).tap do |value|
179
+ double_result(cmd_tuples: value)
180
+ expect(pg_helper.modify('foo')).to eq value
134
181
  end
135
182
  end
136
183
 
137
184
  it 'raises error if gets non array as params' do
138
- lambda {
185
+ expect do
139
186
  pg_helper.modify('select 1', 'bar')
140
- }.should raise_error(PgHelperErrorParamsMustBeArrayOfStrings)
187
+ end.to raise_error(PgHelperErrorParamsMustBeArrayOfStrings)
141
188
  end
142
189
 
143
190
  it 'allows to pass params to query' do
144
191
  sql = 'update foo set test_text = $1::text'
145
- mock(:value).tap do |result|
146
- mock_result({:cmd_tuples => result}, sql, ['foo'])
147
- pg_helper.modify(sql, ["foo"]).should == result
192
+ double(:value).tap do |result|
193
+ double_result({ cmd_tuples: result }, sql, ['foo'])
194
+ expect(pg_helper.modify(sql, ['foo'])).to eq result
148
195
  end
149
196
  end
150
197
 
151
-
152
198
  it 'clears pg result on success' do
153
- mock_result.should_receive(:clear)
199
+ expect(double_result).to receive(:clear)
154
200
  pg_helper.modify('foo')
155
201
  end
156
202
 
157
203
  it 'clears pg result on failure' do
158
- lambda {
159
- mock_result.tap do |result|
160
- result.should_receive(:cmd_tuples).and_raise(Exception)
161
- result.should_receive(:clear)
204
+ lambda do
205
+ double_result.tap do |result|
206
+ expect(result).to receive(:cmd_tuples).and_raise(Exception)
207
+ expect(result).to receive(:clear)
162
208
  end
163
209
  pg_helper.modify('foo')
164
- }
210
+ end
165
211
  end
166
212
  end
167
213
 
168
214
  describe 'transaction' do
169
215
  it 'raises error if no block given' do
170
- lambda { pg_helper.transaction}.should raise_error(ArgumentError)
216
+ expect { pg_helper.transaction }.to raise_error(ArgumentError)
171
217
  end
172
218
 
173
219
  it 'allows to rollback' do
174
- pg_helper.transaction do |t|
175
- t.rollback!
176
- end
220
+ pg_helper.transaction(&:rollback!)
177
221
  end
178
222
 
179
223
  it 'does not allow rollback if not in transaction' do
180
- lambda {pg_helper.rollback!}.should raise_error(PgHelperErrorInvalidOutsideTransaction)
224
+ expect { pg_helper.rollback! }
225
+ .to raise_error(PgHelperErrorInvalidOutsideTransaction)
181
226
  end
182
227
 
183
-
184
228
  describe 'using temporary table' do
185
- let(:test_table_name){'pg_helper_test_'+Time.now.to_i.to_s}
229
+ def test_table_name
230
+ @test_table_name ||= 'pg_helper_test_' + Time.now.to_i.to_s
231
+ end
186
232
 
187
233
  before(:all) do
188
234
  sql = <<SQL
189
- CREATE TEMP TABLE #{test_table_name}
235
+ CREATE TABLE #{test_table_name}
190
236
  (
191
237
  test_text text
192
238
  )
@@ -199,14 +245,22 @@ SQL
199
245
  end
200
246
 
201
247
  it 'will rollback on failure' do
202
- lambda {
248
+ expect do
203
249
  pg_helper.transaction do |t|
204
- t.modify( "INSERT INTO #{test_table_name} VALUES ('one'), ('two'), ('three')" )
205
- t.value("SELECT COUNT(*) FROM #{test_table_name}").should == '3'
206
- raise Exception.new('roll it back')
250
+ t.modify(
251
+ "INSERT INTO #{test_table_name} "\
252
+ "VALUES ('one'), ('two'), ('three')"
253
+ )
254
+ expect(
255
+ t.value("SELECT COUNT(*) FROM #{test_table_name}")
256
+ ).to eq '3'
257
+ fail Exception, 'roll it back'
207
258
  end
208
- }.should raise_error('roll it back')
209
- pg_helper.value("SELECT COUNT(*) FROM #{test_table_name}").should == '0'
259
+ end.to raise_error('roll it back')
260
+
261
+ expect(
262
+ pg_helper.value("SELECT COUNT(*) FROM #{test_table_name}")
263
+ ).to eq '0'
210
264
  end
211
265
 
212
266
  it 'will commit in the end' do
@@ -214,16 +268,20 @@ SQL
214
268
  t.modify("INSERT INTO #{test_table_name} VALUES ('pass')")
215
269
  t.modify("INSERT INTO #{test_table_name} VALUES ('correct')")
216
270
  end
217
- pg_helper.get_column("SELECT test_text FROM #{test_table_name} order by test_text").should == ["correct", "pass"]
271
+ expect(
272
+ pg_helper.get_column(
273
+ "SELECT test_text FROM #{test_table_name} order by test_text"
274
+ )
275
+ ).to eq %w(correct pass)
218
276
  end
219
277
  end
220
278
 
221
279
  it 'will not allow nested transaction' do
222
- lambda {
280
+ expect do
223
281
  pg_helper.transaction do |trans|
224
- trans.transaction {nil}
282
+ trans.transaction { nil }
225
283
  end
226
- }.should raise_error(PgHelperErrorNestedTransactionNotAllowed)
284
+ end.to raise_error(PgHelperErrorNestedTransactionNotAllowed)
227
285
  end
228
286
  end
229
287
  end
@@ -0,0 +1,91 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ require 'pg_helper/query_builder.rb'
3
+
4
+ include PgHelper
5
+ RSpec.describe QueryBuilder do
6
+ subject { QueryBuilder.new('table_name') }
7
+
8
+ describe '#to_sql' do
9
+
10
+ it 'builds default' do
11
+ expect(subject.to_sql).to eq('SELECT * FROM table_name')
12
+ end
13
+
14
+ describe '#select' do
15
+ it 'for specific column' do
16
+ expect(
17
+ subject.select('a').to_sql
18
+ ).to eq 'SELECT a FROM table_name'
19
+ end
20
+
21
+ it 'for multiple columns' do
22
+ expect(
23
+ subject
24
+ .select('a as foo')
25
+ .select('b as bar, c')
26
+ .to_sql
27
+ ).to eq('SELECT a as foo,b as bar, c FROM table_name')
28
+ end
29
+ end
30
+
31
+ describe '#where' do
32
+ it 'using single condition' do
33
+ expect(
34
+ subject.where('a = b').to_sql
35
+ ).to eq('SELECT * FROM table_name WHERE a = b')
36
+ end
37
+
38
+ it 'ands multiple conditions' do
39
+ expect(
40
+ subject
41
+ .where('a = 1')
42
+ .where('b = 2')
43
+ .to_sql
44
+ ).to eq('SELECT * FROM table_name WHERE a = 1 AND b = 2')
45
+ end
46
+ end
47
+
48
+ describe '#with' do
49
+ it 'single CTE' do
50
+ expect(
51
+ subject
52
+ .with('foo', 'select bar from foo')
53
+ .to_sql
54
+ ).to eq('WITH foo AS (select bar from foo) SELECT * FROM table_name')
55
+ end
56
+
57
+ it 'multiple CTEs' do
58
+ expect(
59
+ subject
60
+ .with('foo', 'select 1')
61
+ .with('bar', 'select a')
62
+ .to_sql
63
+ ).to eq('WITH foo AS (select 1),'\
64
+ 'bar AS (select a) '\
65
+ 'SELECT * FROM table_name')
66
+ end
67
+ end
68
+
69
+ describe '#join' do
70
+ it 'can join single table' do
71
+ expect(
72
+ subject
73
+ .join('LEFT JOIN bar on bar.id = table_name.id')
74
+ .to_sql
75
+ ).to eq('SELECT * FROM table_name ' \
76
+ 'LEFT JOIN bar on bar.id = table_name.id')
77
+ end
78
+
79
+ it 'can do multiple joins' do
80
+ expect(
81
+ subject
82
+ .join('CROSS JOIN bar')
83
+ .join('INNER JOIN foo using (buz)')
84
+ .to_sql
85
+ ).to eq('SELECT * FROM table_name '\
86
+ 'CROSS JOIN bar ' \
87
+ 'INNER JOIN foo using (buz)')
88
+ end
89
+ end
90
+ end
91
+ end