pg_helper 0.3.1 → 0.4.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.
@@ -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