pod4 0.10.6 → 1.0.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.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/.bugs/bugs +2 -1
  3. data/.bugs/details/b5368c7ef19065fc597b5692314da71772660963.txt +53 -0
  4. data/.hgtags +1 -0
  5. data/Gemfile +5 -5
  6. data/README.md +157 -46
  7. data/lib/pod4/basic_model.rb +9 -22
  8. data/lib/pod4/connection.rb +67 -0
  9. data/lib/pod4/connection_pool.rb +154 -0
  10. data/lib/pod4/errors.rb +20 -0
  11. data/lib/pod4/interface.rb +34 -12
  12. data/lib/pod4/model.rb +32 -27
  13. data/lib/pod4/nebulous_interface.rb +25 -30
  14. data/lib/pod4/null_interface.rb +22 -16
  15. data/lib/pod4/pg_interface.rb +84 -104
  16. data/lib/pod4/sequel_interface.rb +138 -82
  17. data/lib/pod4/tds_interface.rb +83 -70
  18. data/lib/pod4/tweaking.rb +105 -0
  19. data/lib/pod4/version.rb +1 -1
  20. data/md/breaking_changes.md +80 -0
  21. data/spec/common/basic_model_spec.rb +67 -70
  22. data/spec/common/connection_pool_parallelism_spec.rb +154 -0
  23. data/spec/common/connection_pool_spec.rb +246 -0
  24. data/spec/common/connection_spec.rb +129 -0
  25. data/spec/common/model_ai_missing_id_spec.rb +256 -0
  26. data/spec/common/model_plus_encrypting_spec.rb +16 -4
  27. data/spec/common/model_plus_tweaking_spec.rb +128 -0
  28. data/spec/common/model_plus_typecasting_spec.rb +10 -4
  29. data/spec/common/model_spec.rb +283 -363
  30. data/spec/common/nebulous_interface_spec.rb +159 -108
  31. data/spec/common/null_interface_spec.rb +88 -65
  32. data/spec/common/sequel_interface_pg_spec.rb +217 -161
  33. data/spec/common/shared_examples_for_interface.rb +50 -50
  34. data/spec/jruby/sequel_encrypting_jdbc_pg_spec.rb +1 -1
  35. data/spec/jruby/sequel_interface_jdbc_ms_spec.rb +3 -3
  36. data/spec/jruby/sequel_interface_jdbc_pg_spec.rb +3 -23
  37. data/spec/mri/pg_encrypting_spec.rb +1 -1
  38. data/spec/mri/pg_interface_spec.rb +311 -223
  39. data/spec/mri/sequel_encrypting_spec.rb +1 -1
  40. data/spec/mri/sequel_interface_spec.rb +177 -180
  41. data/spec/mri/tds_encrypting_spec.rb +1 -1
  42. data/spec/mri/tds_interface_spec.rb +296 -212
  43. data/tags +340 -174
  44. metadata +19 -11
  45. data/md/fixme.md +0 -3
  46. data/md/roadmap.md +0 -125
  47. data/md/typecasting.md +0 -80
  48. data/spec/common/model_new_validate_spec.rb +0 -204
@@ -63,7 +63,7 @@ describe "(writing encrypted data via tds_interface)" do
63
63
  include Pod4::Encrypting
64
64
 
65
65
  encrypted_columns :name, :ailment
66
- set_key "dflkasdgklajndgnalkghlgasdgasdghaalsdg"
66
+ set_key "dflkasdgklajndgn"
67
67
  set_iv_column :nonce
68
68
  end
69
69
  end
@@ -1,53 +1,14 @@
1
- require 'pod4/tds_interface'
1
+ require "pod4/tds_interface"
2
2
 
3
- require 'tiny_tds'
4
- require 'date'
3
+ require "tiny_tds"
4
+ require "date"
5
5
 
6
- require_relative '../common/shared_examples_for_interface'
7
- require_relative '../fixtures/database'
6
+ require_relative "../common/shared_examples_for_interface"
7
+ require_relative "../fixtures/database"
8
8
 
9
9
 
10
10
  describe "TdsInterface" do
11
11
 
12
- let(:tds_interface_class) do
13
- Class.new TdsInterface do
14
- set_db :pod4_test
15
- set_table :customer
16
- set_id_fld :id
17
- end
18
- end
19
-
20
- let(:schema_interface_class) do
21
- Class.new TdsInterface do
22
- set_db :pod4_test
23
- set_schema :public
24
- set_table :customer
25
- set_id_fld :id
26
- end
27
- end
28
-
29
- let(:bad_interface_class1) do
30
- Class.new TdsInterface do
31
- set_db :pod4_test
32
- set_table :customer
33
- end
34
- end
35
-
36
- let(:bad_interface_class2) do
37
- Class.new TdsInterface do
38
- set_db :pod4_test
39
- set_id_fld :id
40
- end
41
- end
42
-
43
- let(:prod_interface_class) do
44
- Class.new TdsInterface do
45
- set_db :pod4_test
46
- set_table :product
47
- set_id_fld :code
48
- end
49
- end
50
-
51
12
  def db_setup(connect)
52
13
  client = TinyTds::Client.new(connect)
53
14
  client.execute(%Q|use [pod4_test];|).do
@@ -82,7 +43,6 @@ describe "TdsInterface" do
82
43
  client.close if client
83
44
  end
84
45
 
85
-
86
46
  def fill_data(ifce)
87
47
  @data.each{|r| ifce.create(r) }
88
48
  end
@@ -91,185 +51,261 @@ describe "TdsInterface" do
91
51
  ifce.create( {code: "foo", name: "bar"} )
92
52
  end
93
53
 
54
+ def float_price(row)
55
+ row[:price] = row[:price].to_f
56
+ row
57
+ end
58
+
59
+ def list_contains(ifce, id)
60
+ ifce.list.find {|x| x[ifce.id_fld] == id }
61
+ end
62
+
63
+ let(:tds_interface_class) do
64
+ Class.new TdsInterface do
65
+ set_db :pod4_test
66
+ set_table :customer
67
+ set_id_fld :id
68
+ end
69
+ end
70
+
71
+ let(:schema_interface_class) do
72
+ Class.new TdsInterface do
73
+ set_db :pod4_test
74
+ set_schema :public
75
+ set_table :customer
76
+ set_id_fld :id, autoincrement: true
77
+ end
78
+ end
79
+
80
+ let(:bad_interface_class1) do
81
+ Class.new TdsInterface do
82
+ set_table :customer
83
+ end
84
+ end
85
+
86
+ let(:bad_interface_class2) do
87
+ Class.new TdsInterface do
88
+ set_db :pod4_test
89
+ set_id_fld :id
90
+ end
91
+ end
92
+
93
+ let(:prod_interface_class) do
94
+ Class.new TdsInterface do
95
+ set_db :pod4_test
96
+ set_table :product
97
+ set_id_fld :code, autoincrement: false
98
+ end
99
+ end
100
+
101
+ let(:interface) do
102
+ tds_interface_class.new(@connect_hash)
103
+ end
104
+
105
+ let(:prod_interface) do
106
+ prod_interface_class.new(@connect_hash)
107
+ end
94
108
 
95
109
  before(:all) do
96
110
  @connect_hash = DB[:tds]
97
111
  db_setup(@connect_hash)
98
112
 
99
113
  @data = []
100
- @data << { name: 'Barney',
114
+ @data << { name: "Barney",
101
115
  level: 1.23,
102
116
  day: Date.parse("2016-01-01"),
103
- timestamp: Time.parse('2015-01-01 12:11'),
117
+ timestamp: Time.parse("2015-01-01 12:11"),
104
118
  price: BigDecimal("1.24"),
105
119
  qty: BigDecimal("1.25") }
106
120
 
107
- @data << { name: 'Fred',
121
+ @data << { name: "Fred",
108
122
  level: 2.34,
109
123
  day: Date.parse("2016-02-02"),
110
- timestamp: Time.parse('2015-01-02 12:22'),
124
+ timestamp: Time.parse("2015-01-02 12:22"),
111
125
  price: BigDecimal("2.35"),
112
126
  qty: BigDecimal("2.36") }
113
127
 
114
- @data << { name: 'Betty',
128
+ @data << { name: "Betty",
115
129
  level: 3.45,
116
130
  day: Date.parse("2016-03-03"),
117
- timestamp: Time.parse('2015-01-03 12:33'),
131
+ timestamp: Time.parse("2015-01-03 12:33"),
118
132
  price: BigDecimal("3.46"),
119
133
  qty: BigDecimal("3.47") }
120
134
 
121
135
  end
122
136
 
123
-
124
- before do
137
+ before(:each) do
125
138
  # TRUNCATE TABLE also resets the identity counter
126
139
  interface.execute(%Q|truncate table customer;|)
127
140
  end
128
141
 
129
142
 
130
- let(:interface) do
131
- tds_interface_class.new(@connect_hash)
132
- end
133
-
134
- let(:prod_interface) do
135
- prod_interface_class.new(@connect_hash)
136
- end
137
-
138
- #####
139
-
140
-
141
- it_behaves_like 'an interface' do
142
143
 
144
+ it_behaves_like "an interface" do
143
145
  let(:interface) do
144
146
  tds_interface_class.new(@connect_hash)
145
147
  end
146
148
 
147
-
148
- let(:record) { {name: 'Barney'} }
149
+ let(:record) { {name: "Barney"} }
149
150
 
150
151
  end
151
- ##
152
152
 
153
153
 
154
- describe 'TdsInterface.set_db' do
155
- it 'takes one argument' do
154
+ describe "TdsInterface.set_db" do
155
+
156
+ it "takes one argument" do
156
157
  expect( TdsInterface ).to respond_to(:set_db).with(1).argument
157
158
  end
159
+
158
160
  end
159
- ##
160
161
 
161
162
 
162
- describe 'TdsInterface.db' do
163
- it 'returns the table' do
163
+ describe "TdsInterface.db" do
164
+
165
+ it "returns the table" do
164
166
  expect( tds_interface_class.db ).to eq :pod4_test
165
167
  end
168
+
166
169
  end
167
- ##
168
170
 
169
171
 
170
- describe 'TdsInterface.set_schema' do
171
- it 'takes one argument' do
172
+ describe "TdsInterface.set_schema" do
173
+
174
+ it "takes one argument" do
172
175
  expect( TdsInterface ).to respond_to(:set_schema).with(1).argument
173
176
  end
177
+
174
178
  end
175
- ##
176
179
 
177
180
 
178
- describe 'TdsInterface.schema' do
179
- it 'returns the schema' do
181
+ describe "TdsInterface.schema" do
182
+
183
+ it "returns the schema" do
180
184
  expect( schema_interface_class.schema ).to eq :public
181
185
  end
182
186
 
183
- it 'is optional' do
187
+ it "is optional" do
184
188
  expect{ tds_interface_class.schema }.not_to raise_exception
185
189
  expect( tds_interface_class.schema ).to eq nil
186
190
  end
191
+
187
192
  end
188
- ##
189
193
 
190
194
 
191
- describe 'TdsInterface.set_table' do
192
- it 'takes one argument' do
195
+ describe "TdsInterface.set_table" do
196
+
197
+ it "takes one argument" do
193
198
  expect( TdsInterface ).to respond_to(:set_table).with(1).argument
194
199
  end
200
+
195
201
  end
196
- ##
197
202
 
198
203
 
199
- describe 'TdsInterface.table' do
200
- it 'returns the table' do
204
+ describe "TdsInterface.table" do
205
+
206
+ it "returns the table" do
201
207
  expect( tds_interface_class.table ).to eq :customer
202
208
  end
209
+
203
210
  end
204
- ##
205
211
 
206
212
 
207
- describe 'TdsInterface.set_id_fld' do
208
- it 'takes one argument' do
213
+ describe "TdsInterface.set_id_fld" do
214
+
215
+ it "takes one argument" do
209
216
  expect( TdsInterface ).to respond_to(:set_id_fld).with(1).argument
210
217
  end
218
+
219
+ it "takes an optional second 'autoincrement' argument" do
220
+ expect{ TdsInterface.set_id_fld(:foo, autoincrement: false) }.not_to raise_error
221
+ end
222
+
211
223
  end
212
- ##
213
224
 
214
225
 
215
- describe 'TdsInterface.id_fld' do
216
- it 'returns the ID field name' do
226
+ describe "TdsInterface.id_ai" do
227
+
228
+ it "returns true if autoincrement is true" do
229
+ expect( schema_interface_class.id_ai ).to eq true
230
+ end
231
+
232
+ it "returns false if autoincrement is false" do
233
+ expect( prod_interface_class.id_ai ).to eq false
234
+ end
235
+
236
+ it "returns true if autoincrement is not specified" do
237
+ expect( tds_interface_class.id_ai ).to eq true
238
+ end
239
+
240
+ end # of PgInterface.id_ai
241
+
242
+
243
+ describe "TdsInterface.id_fld" do
244
+
245
+ it "returns the ID field name" do
217
246
  expect( tds_interface_class.id_fld ).to eq :id
218
247
  end
219
- end
220
- ##
221
248
 
249
+ end
222
250
 
223
- describe '#new' do
224
251
 
225
- it 'requires a TinyTds connection string' do
226
- expect{ tds_interface_class.new }.to raise_exception ArgumentError
227
- expect{ tds_interface_class.new(nil) }.to raise_exception ArgumentError
228
- expect{ tds_interface_class.new('foo') }.to raise_exception ArgumentError
252
+ describe "#new" do
229
253
 
230
- expect{ tds_interface_class.new(@connect_hash) }.not_to raise_exception
254
+ it "creates a ConnectionPool when passed a TDS connection hash" do
255
+ ifce = tds_interface_class.new(@connect_hash)
256
+ expect( ifce._connection ).to be_a ConnectionPool
231
257
  end
232
258
 
233
- it 'requires the table and id field to be defined in the class' do
234
- expect{ TdsInterface.new(@connect_hash) }.to raise_exception Pod4Error
259
+ it "uses the ConnectionPool when given one" do
260
+ pool = ConnectionPool.new(interface: tds_interface_class)
261
+ ifce = tds_interface_class.new(pool)
235
262
 
236
- expect{ bad_interface_class1.new(@connect_hash) }.
237
- to raise_exception Pod4Error
263
+ expect( ifce._connection ).to eq pool
264
+ end
238
265
 
239
- expect{ bad_interface_class2.new(@connect_hash) }.
240
- to raise_exception Pod4Error
266
+ it "raises ArgumentError when passed something else" do
267
+ expect{ tds_interface_class.new }.to raise_exception ArgumentError
268
+ expect{ tds_interface_class.new(nil) }.to raise_exception ArgumentError
269
+ expect{ tds_interface_class.new("foo") }.to raise_exception ArgumentError
270
+ end
241
271
 
272
+ it "requires the table and id field to be defined in the class" do
273
+ expect{ TdsInterface.new(@connect_hash) }.to raise_exception Pod4Error
274
+ expect{ bad_interface_class1.new(@connect_hash) }.to raise_exception Pod4Error
275
+ expect{ bad_interface_class2.new(@connect_hash) }.to raise_exception Pod4Error
242
276
  end
243
277
 
244
- end
245
- ##
278
+ end # of #new
246
279
 
247
280
 
248
- describe '#quoted_table' do
281
+ describe "#quoted_table" do
249
282
 
250
- it 'returns just the table when the schema is not set' do
283
+ it "returns just the table when the schema is not set" do
251
284
  expect( interface.quoted_table ).to eq( %Q|[customer]| )
252
285
  end
253
286
 
254
- it 'returns the schema plus table when the schema is set' do
287
+ it "returns the schema plus table when the schema is set" do
255
288
  ifce = schema_interface_class.new(@connect_hash)
256
289
  expect( ifce.quoted_table ).to eq( %|[public].[customer]| )
257
290
  end
258
291
 
259
- end
260
- ##
292
+ end # of #quoted_table
261
293
 
262
294
 
263
- describe '#create' do
295
+ describe "#create" do
296
+ let(:hash) { {name: "Bam-Bam", price: 4.44} }
297
+ let(:ot) { Octothorpe.new(name: "Wilma", price: 5.55) }
264
298
 
265
- let(:hash) { {name: 'Bam-Bam', price: 4.44} }
266
- let(:ot) { Octothorpe.new(name: 'Wilma', price: 5.55) }
299
+ it "raises a Pod4::DatabaseError if anything goes wrong" do
300
+ expect{ interface.create(one: "two") }.to raise_exception DatabaseError
301
+ end
267
302
 
268
- it 'raises a Pod4::DatabaseError if anything goes wrong' do
269
- expect{ interface.create(one: 'two') }.to raise_exception DatabaseError
303
+ it "raises an ArgumentError if ID field is missing in hash and not AI" do
304
+ hash = {name: "bar"}
305
+ expect{ prod_interface.create(Octothorpe.new hash) }.to raise_error ArgumentError
270
306
  end
271
307
 
272
- it 'creates the record when given a hash' do
308
+ it "creates the record when given a hash" do
273
309
  # kinda impossible to seperate these two tests
274
310
  id = interface.create(hash)
275
311
 
@@ -277,28 +313,28 @@ describe "TdsInterface" do
277
313
  expect( interface.read(id).to_h ).to include hash
278
314
  end
279
315
 
280
- it 'creates the record when given an Octothorpe' do
316
+ it "creates the record when given an Octothorpe" do
281
317
  id = interface.create(ot)
282
318
 
283
319
  expect{ interface.read(id) }.not_to raise_exception
284
320
  expect( interface.read(id).to_h ).to include ot.to_h
285
321
  end
286
322
 
287
- it 'shouldn\'t have a problem with record values of nil' do
288
- hash2 = {name: 'Ranger', price: nil}
323
+ it "has no problem with record values of nil" do
324
+ hash2 = {name: "Ranger", price: nil}
289
325
  expect{ interface.create(hash2) }.not_to raise_exception
290
326
  id = interface.create(hash2)
291
327
  expect( interface.read(id).to_h ).to include(hash2)
292
328
  end
293
329
 
294
- it 'shouldn\'t have a problem with strings containing special characters' do
330
+ it "has no problem with strings containing special characters" do
295
331
  hash2 = {name: "T'Challa[]", price: nil}
296
332
  expect{ interface.create(hash2) }.not_to raise_exception
297
333
  id = interface.create(hash2)
298
334
  expect( interface.read(id).to_h ).to include(hash2)
299
335
  end
300
336
 
301
- it 'shouldn\'t have a problem with non-integer keys' do
337
+ it "has no problem with non-integer keys" do
302
338
  hash = {code: "foo", name: "bar"}
303
339
  id = prod_interface.create( Octothorpe.new(hash) )
304
340
 
@@ -307,37 +343,51 @@ describe "TdsInterface" do
307
343
  expect( prod_interface.read("foo").to_h ).to include hash
308
344
  end
309
345
 
310
- end
311
- ##
346
+ it "calls ConnectionPool#client" do
347
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
348
+ interface.create(ot)
349
+ end
312
350
 
351
+ it "copes with an OT with the ID field in it when the ID field autoincrements" do
352
+ h = {id: nil, name: "Bam-Bam", qty: 4.44}
353
+ expect{ interface.create(h) }.not_to raise_error
313
354
 
314
- describe '#read' do
315
- before { fill_data(interface) }
355
+ id = interface.create(h)
356
+ expect( id ).not_to be_nil
357
+ expect{ interface.read(id) }.not_to raise_exception
358
+ expect( interface.read(id).to_h ).to include( {name: "Bam-Bam", qty: 4.44} )
359
+ end
316
360
 
317
- it 'returns the record for the id as an Octothorpe' do
361
+ end # of #create
362
+
363
+
364
+ describe "#read" do
365
+ before(:each) { fill_data(interface) }
366
+
367
+ it "returns the record for the id as an Octothorpe" do
318
368
  rec = interface.read(2)
319
369
  expect( rec ).to be_a_kind_of Octothorpe
320
- expect( rec.>>.name ).to eq 'Fred'
370
+ expect( rec.>>.name ).to eq "Fred"
321
371
  end
322
372
 
323
- it 'raises a Pod4::CantContinue if anything goes wrong with the ID' do
373
+ it "raises a Pod4::CantContinue if anything goes wrong with the ID" do
324
374
  expect{ interface.read(:foo) }.to raise_exception CantContinue
325
375
  end
326
376
 
327
- it 'returns an empty Octothorpe if no record matches the ID' do
377
+ it "returns an empty Octothorpe if no record matches the ID" do
328
378
  expect{ interface.read(99) }.not_to raise_exception
329
379
  expect( interface.read(99) ).to be_a_kind_of Octothorpe
330
380
  expect( interface.read(99) ).to be_empty
331
381
  end
332
382
 
333
- it 'returns real fields as Float' do
383
+ it "returns real fields as Float" do
334
384
  level = interface.read(1).>>.level
335
385
 
336
386
  expect( level ).to be_a_kind_of Float
337
387
  expect( level ).to be_within(0.001).of( @data.first[:level] )
338
388
  end
339
389
 
340
- it 'returns date fields as Date' do
390
+ it "returns date fields as Date" do
341
391
  skip "not supported by TinyTds ¬_¬ "
342
392
  date = interface.read(1).>>.day
343
393
 
@@ -345,28 +395,28 @@ describe "TdsInterface" do
345
395
  expect( date ).to eq @data.first[:day]
346
396
  end
347
397
 
348
- it 'returns datetime fields as Time' do
398
+ it "returns datetime fields as Time" do
349
399
  timestamp = interface.read(1).>>.timestamp
350
400
 
351
401
  expect( timestamp ).to be_a_kind_of Time
352
402
  expect( timestamp ).to eq @data.first[:timestamp]
353
403
  end
354
404
 
355
- it 'returns numeric fields as BigDecimal' do
405
+ it "returns numeric fields as BigDecimal" do
356
406
  qty = interface.read(1).>>.qty
357
407
 
358
408
  expect( qty ).to be_a_kind_of BigDecimal
359
409
  expect( qty ).to eq @data.first[:qty]
360
410
  end
361
411
 
362
- it 'returns money fields as BigDecimal' do
412
+ it "returns money fields as BigDecimal" do
363
413
  price = interface.read(1).>>.price
364
414
 
365
415
  expect( price ).to be_a_kind_of BigDecimal
366
416
  expect( price ).to eq @data.first[:price]
367
417
  end
368
418
 
369
- it 'shouldn\'t have a problem with non-integer keys' do
419
+ it "has no problem with non-integer keys" do
370
420
  # this is a 100% overlap with the create test above...
371
421
  fill_product_data(prod_interface)
372
422
 
@@ -374,57 +424,60 @@ describe "TdsInterface" do
374
424
  expect( prod_interface.read("foo").to_h ).to include(code: "foo", name: "bar")
375
425
  end
376
426
 
377
- end
378
- ##
427
+ it "calls ConnectionPool#client" do
428
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
429
+ interface.read(2)
430
+ end
379
431
 
432
+ end # of #read
380
433
 
381
- describe '#list' do
382
- before { fill_data(interface) }
383
434
 
384
- it 'has an optional selection parameter, a hash' do
435
+ describe "#list" do
436
+ before(:each) { fill_data(interface) }
437
+
438
+ it "has an optional selection parameter, a hash" do
385
439
  # Actually it does not have to be a hash, but FTTB we only support that.
386
- expect{ interface.list(name: 'Barney') }.not_to raise_exception
440
+ expect{ interface.list(name: "Barney") }.not_to raise_exception
387
441
  end
388
442
 
389
- it 'returns an array of Octothorpes that match the records' do
443
+ it "returns an array of Octothorpes that match the records" do
390
444
  list = interface.list
391
445
 
392
446
  expect( list.first ).to be_a_kind_of Octothorpe
393
447
  expect( list.map{|x| x.>>.name} ).to match_array @data.map{|y| y[:name]}
394
448
  end
395
449
 
396
- it 'returns a subset of records based on the selection parameter' do
397
- expect( interface.list(name: 'Fred').size ).to eq 1
450
+ it "returns a subset of records based on the selection parameter" do
451
+ expect( interface.list(name: "Fred").size ).to eq 1
398
452
 
399
- expect( interface.list(name: 'Betty').first.to_h ).
400
- to include(name: 'Betty', price: 3.46)
453
+ expect( interface.list(name: "Betty").first.to_h ).
454
+ to include(name: "Betty", price: 3.46)
401
455
 
402
456
  end
403
457
 
404
- it 'returns an empty Array if nothing matches' do
405
- expect( interface.list(name: 'Yogi') ).to eq([])
458
+ it "returns an empty Array if nothing matches" do
459
+ expect( interface.list(name: "Yogi") ).to eq([])
406
460
  end
407
461
 
408
- it 'raises DatabaseError if the selection criteria is nonsensical' do
409
- expect{ interface.list('foo') }.to raise_exception Pod4::DatabaseError
462
+ it "raises DatabaseError if the selection criteria is nonsensical" do
463
+ expect{ interface.list("foo") }.to raise_exception Pod4::DatabaseError
410
464
  end
411
465
 
412
- end
413
- ##
466
+ it "calls ConnectionPool#client" do
467
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
468
+ interface.list
469
+ end
470
+
471
+ end # of #list
414
472
 
415
473
 
416
- describe '#update' do
417
- before { fill_data(interface) }
474
+ describe "#update" do
475
+ before(:each) { fill_data(interface) }
418
476
 
419
477
  let(:id) { interface.list.first[:id] }
420
478
 
421
- def float_price(row)
422
- row[:price] = row[:price].to_f
423
- row
424
- end
425
-
426
- it 'updates the record at ID with record parameter' do
427
- record = {name: 'Booboo', price: 99.99}
479
+ it "updates the record at ID with record parameter" do
480
+ record = {name: "Booboo", price: 99.99}
428
481
  interface.update(id, record)
429
482
 
430
483
  # It so happens that TinyTds returns money as BigDecimal --
@@ -432,138 +485,148 @@ describe "TdsInterface" do
432
485
  expect( float_price( interface.read(id).to_h ) ).to include(record)
433
486
  end
434
487
 
435
- it 'raises a CantContinue if anything weird happens with the ID' do
436
- expect{ interface.update(99, name: 'Booboo') }.
488
+ it "raises a CantContinue if anything weird happens with the ID" do
489
+ expect{ interface.update(99, name: "Booboo") }.
437
490
  to raise_exception CantContinue
438
491
 
439
492
  end
440
493
 
441
- it 'raises a DatabaseError if anything weird happens with the record' do
442
- expect{ interface.update(id, smarts: 'more') }.
494
+ it "raises a DatabaseError if anything weird happens with the record" do
495
+ expect{ interface.update(id, smarts: "more") }.
443
496
  to raise_exception DatabaseError
444
497
 
445
498
  end
446
499
 
447
- it 'shouldn\'t have a problem with record values of nil' do
448
- record = {name: 'Ranger', price: nil}
500
+ it "has no problem with record values of nil" do
501
+ record = {name: "Ranger", price: nil}
449
502
  expect{ interface.update(id, record) }.not_to raise_exception
450
503
  expect( interface.read(id).to_h ).to include(record)
451
504
  end
452
505
 
453
- it 'shouldn\'t have a problem with strings containing special characters' do
506
+ it "has no problem with strings containing special characters" do
454
507
  record = {name: "T'Challa[]", price: nil}
455
508
  expect{ interface.update(id, record) }.not_to raise_exception
456
509
  expect( interface.read(id).to_h ).to include(record)
457
510
  end
458
511
 
459
- it 'shouldn\'t have a problem with non-integer keys' do
512
+ it "has no problem with non-integer keys" do
460
513
  fill_product_data(prod_interface)
461
514
  expect{ prod_interface.update("foo", name: "baz") }.not_to raise_error
462
515
  expect( prod_interface.read("foo").to_h[:name] ).to eq "baz"
463
516
  end
464
517
 
465
- end
466
- ##
467
-
518
+ it "calls ConnectionPool#client" do
519
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
520
+ record = {name: "Booboo", price: 99.99}
521
+ interface.update(id, record)
522
+ end
468
523
 
469
- describe '#delete' do
524
+ end # of #update
470
525
 
471
- def list_contains(ifce, id)
472
- ifce.list.find {|x| x[ifce.id_fld] == id }
473
- end
474
526
 
527
+ describe "#delete" do
475
528
  let(:id) { interface.list.first[:id] }
476
529
 
477
- before { fill_data(interface) }
530
+ before(:each) { fill_data(interface) }
478
531
 
479
- it 'raises CantContinue if anything hinky happens with the ID' do
532
+ it "raises CantContinue if anything hinky happens with the ID" do
480
533
  expect{ interface.delete(:foo) }.to raise_exception CantContinue
481
534
  expect{ interface.delete(99) }.to raise_exception CantContinue
482
535
  end
483
536
 
484
- it 'makes the record at ID go away' do
537
+ it "makes the record at ID go away" do
485
538
  expect( list_contains(interface, id) ).to be_truthy
486
539
  interface.delete(id)
487
540
  expect( list_contains(interface, id) ).to be_falsy
488
541
  end
489
542
 
490
- it 'shouldn\'t have a problem with non-integer keys' do
543
+ it "has no problem with non-integer keys" do
491
544
  fill_product_data(prod_interface)
492
545
  expect( list_contains(prod_interface, "foo") ).to be_truthy
493
546
  prod_interface.delete("foo")
494
547
  expect( list_contains(prod_interface, "foo") ).to be_falsy
495
548
  end
496
549
 
497
- end
498
- ##
550
+ it "calls ConnectionPool#client" do
551
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
552
+ interface.delete(id)
553
+ end
499
554
 
555
+ end # of #delete
500
556
 
501
- describe '#execute' do
502
557
 
503
- let(:sql) { 'delete from customer where price < 2.0;' }
558
+ describe "#execute" do
559
+ let(:sql) { "delete from customer where price < 2.0;" }
504
560
 
505
- before { fill_data(interface) }
561
+ before(:each) { fill_data(interface) }
506
562
 
507
- it 'requires an SQL string' do
563
+ it "requires an SQL string" do
508
564
  expect{ interface.execute }.to raise_exception ArgumentError
509
565
  expect{ interface.execute(nil) }.to raise_exception ArgumentError
510
566
  expect{ interface.execute(14) }.to raise_exception ArgumentError
511
567
  end
512
568
 
513
- it 'raises some sort of Pod4 error if it runs into problems' do
514
- expect{ interface.execute('delete from not_a_table') }.
569
+ it "raises some sort of Pod4 error if it runs into problems" do
570
+ expect{ interface.execute("delete from not_a_table") }.
515
571
  to raise_exception Pod4Error
516
572
 
517
573
  end
518
574
 
519
- it 'executes the string' do
575
+ it "executes the string" do
520
576
  expect{ interface.execute(sql) }.not_to raise_exception
521
577
  expect( interface.list.size ).to eq(@data.size - 1)
522
- expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
578
+ expect( interface.list.map{|r| r[:name] } ).not_to include "Barney"
523
579
  end
524
580
 
525
- end
526
- ##
581
+ it "calls ConnectionPool#client" do
582
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
583
+ interface.execute(sql)
584
+ end
527
585
 
586
+ end # of #execute
528
587
 
529
- describe '#select' do
530
588
 
531
- before { fill_data(interface) }
589
+ describe "#select" do
590
+ before(:each) { fill_data(interface) }
532
591
 
533
- it 'requires an SQL string' do
592
+ it "requires an SQL string" do
534
593
  expect{ interface.select }.to raise_exception ArgumentError
535
594
  expect{ interface.select(nil) }.to raise_exception ArgumentError
536
595
  expect{ interface.select(14) }.to raise_exception ArgumentError
537
596
  end
538
597
 
539
- it 'raises some sort of Pod4 error if it runs into problems' do
540
- expect{ interface.select('select * from not_a_table') }.
598
+ it "raises some sort of Pod4 error if it runs into problems" do
599
+ expect{ interface.select("select * from not_a_table") }.
541
600
  to raise_exception Pod4Error
542
601
 
543
602
  end
544
603
 
545
- it 'returns the result of the sql' do
546
- sql1 = 'select name from customer where price < 2.0;'
547
- sql2 = 'select name from customer where price < 0.0;'
604
+ it "returns the result of the sql" do
605
+ sql1 = "select name from customer where price < 2.0;"
606
+ sql2 = "select name from customer where price < 0.0;"
548
607
 
549
608
  expect{ interface.select(sql1) }.not_to raise_exception
550
- expect( interface.select(sql1) ).to eq( [{name: 'Barney'}] )
609
+ expect( interface.select(sql1) ).to eq( [{name: "Barney"}] )
551
610
  expect( interface.select(sql2) ).to eq( [] )
552
611
  end
553
612
 
554
- it 'works if you pass a non-select' do
613
+ it "works if you pass a non-select" do
555
614
  # By which I mean: still executes the SQL; returns []
556
- sql = 'delete from customer where price < 2.0;'
615
+ sql = "delete from customer where price < 2.0;"
557
616
  ret = interface.select(sql)
558
617
 
559
618
  expect( interface.list.size ).to eq(@data.size - 1)
560
- expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
619
+ expect( interface.list.map{|r| r[:name] } ).not_to include "Barney"
561
620
  expect( ret ).to eq( [] )
562
621
  end
563
622
 
623
+ it "calls ConnectionPool#client" do
624
+ expect( interface._connection ).to receive(:client).at_least(:once).and_call_original
625
+ sql = "delete from customer where price < 2.0;"
626
+ interface.select(sql)
627
+ end
564
628
 
565
- end
566
- ##
629
+ end # of #select
567
630
 
568
631
 
569
632
  describe "#escape" do
@@ -579,9 +642,30 @@ describe "TdsInterface" do
579
642
  expect( interface.escape "G'Kar" ).to eq %Q|G''Kar|
580
643
  end
581
644
 
582
- end
583
- ##
645
+ end # of #escape
646
+
647
+
648
+ describe "#new_connection" do
649
+
650
+ it "returns a PG Client object" do
651
+ expect( interface.new_connection @connect_hash ).to be_a TinyTds::Client
652
+ end
653
+
654
+ end # of #new_connection
655
+
656
+
657
+ describe "#close_connection" do
658
+
659
+ it "closes the given PG Client object" do
660
+ client = interface.new_connection(@connect_hash)
661
+
662
+ expect( client ).to receive(:close)
663
+
664
+ interface.close_connection(client)
665
+ end
666
+
667
+ end # of #close_connection
668
+
584
669
 
585
-
586
670
  end
587
671