pod4 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hgignore +1 -0
- data/.hgtags +1 -0
- data/Gemfile +3 -1
- data/Rakefile +17 -5
- data/lib/pod4/pg_interface.rb +81 -57
- data/lib/pod4/sequel_interface.rb +61 -6
- data/lib/pod4/sql_helper.rb +229 -0
- data/lib/pod4/tds_interface.rb +65 -50
- data/lib/pod4/version.rb +1 -1
- data/md/roadmap.md +81 -25
- data/spec/common/basic_model_spec.rb +5 -0
- data/spec/common/model_spec.rb +49 -7
- data/spec/common/nebulous_interface_spec.rb +2 -0
- data/spec/common/sequel_interface_pg_spec.rb +511 -0
- data/spec/common/sql_helper_spec.rb +299 -0
- data/spec/jruby/sequel_interface_jdbc_ms_spec.rb +525 -0
- data/spec/jruby/sequel_interface_jdbc_pg_spec.rb +520 -0
- data/spec/mri/pg_interface_spec.rb +140 -16
- data/spec/mri/sequel_interface_spec.rb +146 -13
- data/spec/mri/tds_interface_spec.rb +82 -12
- metadata +11 -4
- data/spec/jruby/pg_interface_spec.rb +0 -469
@@ -8,6 +8,9 @@ require_relative '../fixtures/database'
|
|
8
8
|
class TestPgInterface < PgInterface
|
9
9
|
set_table :customer
|
10
10
|
set_id_fld :id
|
11
|
+
|
12
|
+
# We open a lot of connections, unusually
|
13
|
+
def stop; close; end
|
11
14
|
end
|
12
15
|
|
13
16
|
class SchemaPgInterface < PgInterface
|
@@ -24,23 +27,33 @@ class BadPgInterface2 < PgInterface
|
|
24
27
|
set_id_fld :id
|
25
28
|
end
|
26
29
|
|
30
|
+
class ProdPgInterface < PgInterface
|
31
|
+
set_table :product
|
32
|
+
set_id_fld :code
|
33
|
+
end
|
34
|
+
|
27
35
|
|
28
36
|
describe TestPgInterface do
|
29
37
|
|
30
38
|
def db_setup(connect)
|
31
39
|
client = PG.connect(connect)
|
32
40
|
|
33
|
-
client.exec(%Q|drop table if exists customer;|)
|
34
|
-
|
35
41
|
client.exec(%Q|
|
42
|
+
drop table if exists customer;
|
43
|
+
drop table if exists product;
|
44
|
+
|
36
45
|
create table customer (
|
37
|
-
id serial,
|
46
|
+
id serial primary key,
|
38
47
|
name text,
|
39
48
|
level real null,
|
40
49
|
day date null,
|
41
50
|
timestamp timestamp null,
|
42
51
|
price money null,
|
43
|
-
qty numeric null )
|
52
|
+
qty numeric null );
|
53
|
+
|
54
|
+
create table product (
|
55
|
+
code text,
|
56
|
+
name text );| )
|
44
57
|
|
45
58
|
ensure
|
46
59
|
client.finish if client
|
@@ -52,6 +65,11 @@ describe TestPgInterface do
|
|
52
65
|
end
|
53
66
|
|
54
67
|
|
68
|
+
def fill_product_data(ifce)
|
69
|
+
ifce.create( {code: "foo", name: "bar"} )
|
70
|
+
end
|
71
|
+
|
72
|
+
|
55
73
|
before(:all) do
|
56
74
|
@connect_hash = DB[:pg]
|
57
75
|
db_setup(@connect_hash)
|
@@ -82,8 +100,16 @@ describe TestPgInterface do
|
|
82
100
|
|
83
101
|
|
84
102
|
before do
|
85
|
-
|
86
|
-
|
103
|
+
interface.execute(%Q|
|
104
|
+
truncate table customer restart identity;
|
105
|
+
truncate table product;|)
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
after do
|
111
|
+
# We open a lot of connections, unusually
|
112
|
+
interface.stop if interface
|
87
113
|
end
|
88
114
|
|
89
115
|
|
@@ -91,6 +117,10 @@ describe TestPgInterface do
|
|
91
117
|
TestPgInterface.new(@connect_hash)
|
92
118
|
end
|
93
119
|
|
120
|
+
let(:prod_interface) do
|
121
|
+
ProdPgInterface.new(@connect_hash)
|
122
|
+
end
|
123
|
+
|
94
124
|
#####
|
95
125
|
|
96
126
|
|
@@ -212,20 +242,29 @@ describe TestPgInterface do
|
|
212
242
|
expect( interface.read(id).to_h ).to include ot.to_h
|
213
243
|
end
|
214
244
|
|
215
|
-
it '
|
245
|
+
it 'shouldn\'t have a problem with record values of nil' do
|
216
246
|
record = {name: 'Ranger', price: nil}
|
217
247
|
expect{ interface.create(record) }.not_to raise_exception
|
218
248
|
id = interface.create(record)
|
219
249
|
expect( interface.read(id).to_h ).to include(record)
|
220
250
|
end
|
221
251
|
|
222
|
-
it '
|
252
|
+
it 'shouldn\'t have a problem with strings containing special characters' do
|
223
253
|
record = {name: %Q|T'Challa""|, price: nil}
|
224
254
|
expect{ interface.create(record) }.not_to raise_exception
|
225
255
|
id = interface.create(record)
|
226
256
|
expect( interface.read(id).to_h ).to include(record)
|
227
257
|
end
|
228
258
|
|
259
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
260
|
+
hash = {code: "foo", name: "bar"}
|
261
|
+
id = prod_interface.create( Octothorpe.new(hash) )
|
262
|
+
|
263
|
+
expect( id ).to eq "foo"
|
264
|
+
expect{ prod_interface.read("foo") }.not_to raise_exception
|
265
|
+
expect( prod_interface.read("foo").to_h ).to include hash
|
266
|
+
end
|
267
|
+
|
229
268
|
end
|
230
269
|
##
|
231
270
|
|
@@ -284,6 +323,14 @@ describe TestPgInterface do
|
|
284
323
|
expect( price ).to eq @data.first[:price]
|
285
324
|
end
|
286
325
|
|
326
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
327
|
+
# this is a 100% overlap with the create test above...
|
328
|
+
fill_product_data(prod_interface)
|
329
|
+
|
330
|
+
expect{ prod_interface.read("foo") }.not_to raise_exception
|
331
|
+
expect( prod_interface.read("foo").to_h ).to include(code: "foo", name: "bar")
|
332
|
+
end
|
333
|
+
|
287
334
|
end
|
288
335
|
##
|
289
336
|
|
@@ -337,8 +384,6 @@ describe TestPgInterface do
|
|
337
384
|
record = {name: 'Booboo', price: 99.99}
|
338
385
|
interface.update(id, record)
|
339
386
|
|
340
|
-
# It so happens that TinyTds returns money as BigDecimal --
|
341
|
-
# this is a really good thing, even though it screws with our test.
|
342
387
|
expect( float_price( interface.read(id).to_h ) ).to include(record)
|
343
388
|
end
|
344
389
|
|
@@ -354,26 +399,32 @@ describe TestPgInterface do
|
|
354
399
|
|
355
400
|
end
|
356
401
|
|
357
|
-
it '
|
402
|
+
it 'shouldn\'t have a problem with record values of nil' do
|
358
403
|
record = {name: 'Ranger', price: nil}
|
359
404
|
expect{ interface.update(id, record) }.not_to raise_exception
|
360
405
|
expect( interface.read(id).to_h ).to include(record)
|
361
406
|
end
|
362
407
|
|
363
|
-
it '
|
408
|
+
it 'shouldn\'t have a problem with strings containing special characters' do
|
364
409
|
record = {name: %Q|T'Challa""|, price: nil}
|
365
410
|
expect{ interface.update(id, record) }.not_to raise_exception
|
366
411
|
expect( interface.read(id).to_h ).to include(record)
|
367
412
|
end
|
368
413
|
|
414
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
415
|
+
fill_product_data(prod_interface)
|
416
|
+
expect{ prod_interface.update("foo", name: "baz") }.not_to raise_error
|
417
|
+
expect( prod_interface.read("foo").to_h[:name] ).to eq "baz"
|
418
|
+
end
|
419
|
+
|
369
420
|
end
|
370
421
|
##
|
371
422
|
|
372
423
|
|
373
424
|
describe '#delete' do
|
374
425
|
|
375
|
-
def list_contains(id)
|
376
|
-
|
426
|
+
def list_contains(ifce, id)
|
427
|
+
ifce.list.find {|x| x[ifce.id_fld] == id }
|
377
428
|
end
|
378
429
|
|
379
430
|
let(:id) { interface.list.first[:id] }
|
@@ -386,9 +437,16 @@ describe TestPgInterface do
|
|
386
437
|
end
|
387
438
|
|
388
439
|
it 'makes the record at ID go away' do
|
389
|
-
expect( list_contains(id) ).to be_truthy
|
440
|
+
expect( list_contains(interface, id) ).to be_truthy
|
390
441
|
interface.delete(id)
|
391
|
-
expect( list_contains(id) ).to be_falsy
|
442
|
+
expect( list_contains(interface, id) ).to be_falsy
|
443
|
+
end
|
444
|
+
|
445
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
446
|
+
fill_product_data(prod_interface)
|
447
|
+
expect( list_contains(prod_interface, "foo") ).to be_truthy
|
448
|
+
prod_interface.delete("foo")
|
449
|
+
expect( list_contains(prod_interface, "foo") ).to be_falsy
|
392
450
|
end
|
393
451
|
|
394
452
|
end
|
@@ -423,6 +481,34 @@ describe TestPgInterface do
|
|
423
481
|
##
|
424
482
|
|
425
483
|
|
484
|
+
describe '#executep' do
|
485
|
+
|
486
|
+
let(:sql) { 'delete from customer where cast(price as numeric) < %s and name = %s;' }
|
487
|
+
|
488
|
+
before { fill_data(interface) }
|
489
|
+
|
490
|
+
it 'requires an SQL string' do
|
491
|
+
expect{ interface.executep }.to raise_exception ArgumentError
|
492
|
+
expect{ interface.executep(nil) }.to raise_exception ArgumentError
|
493
|
+
expect{ interface.executep(14) }.to raise_exception ArgumentError
|
494
|
+
end
|
495
|
+
|
496
|
+
it 'raises some sort of Pod4 error if it runs into problems' do
|
497
|
+
expect{ interface.executep('delete from not_a_table where foo = %s', 12) }.
|
498
|
+
to raise_exception Pod4Error
|
499
|
+
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'executes the string with the given parameters' do
|
503
|
+
expect{ interface.executep(sql, 12.0, 'Barney') }.not_to raise_exception
|
504
|
+
expect( interface.list.size ).to eq(@data.size - 1)
|
505
|
+
expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
|
506
|
+
end
|
507
|
+
|
508
|
+
end
|
509
|
+
##
|
510
|
+
|
511
|
+
|
426
512
|
describe '#select' do
|
427
513
|
|
428
514
|
before { fill_data(interface) }
|
@@ -462,5 +548,43 @@ describe TestPgInterface do
|
|
462
548
|
##
|
463
549
|
|
464
550
|
|
551
|
+
describe '#selectp' do
|
552
|
+
|
553
|
+
before { fill_data(interface) }
|
554
|
+
|
555
|
+
it 'requires an SQL string' do
|
556
|
+
expect{ interface.selectp }.to raise_exception ArgumentError
|
557
|
+
expect{ interface.selectp(nil) }.to raise_exception ArgumentError
|
558
|
+
expect{ interface.selectp(14) }.to raise_exception ArgumentError
|
559
|
+
end
|
560
|
+
|
561
|
+
it 'raises some sort of Pod4 error if it runs into problems' do
|
562
|
+
expect{ interface.selectp('select * from not_a_table where thingy = %s', 12) }.
|
563
|
+
to raise_exception Pod4Error
|
564
|
+
|
565
|
+
end
|
566
|
+
|
567
|
+
it 'returns the result of the sql' do
|
568
|
+
sql = 'select name from customer where cast(price as numeric) < %s;'
|
569
|
+
|
570
|
+
expect{ interface.selectp(sql, 2.0) }.not_to raise_exception
|
571
|
+
expect( interface.selectp(sql, 2.0) ).to eq( [{name: 'Barney'}] )
|
572
|
+
expect( interface.selectp(sql, 0.0) ).to eq( [] )
|
573
|
+
end
|
574
|
+
|
575
|
+
it 'works if you pass a non-select' do
|
576
|
+
sql = 'delete from customer where cast(price as numeric) < %s;'
|
577
|
+
ret = interface.selectp(sql, 2.0)
|
578
|
+
|
579
|
+
expect( interface.list.size ).to eq(@data.size - 1)
|
580
|
+
expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
|
581
|
+
expect( ret ).to eq( [] )
|
582
|
+
end
|
583
|
+
|
584
|
+
|
585
|
+
end
|
586
|
+
##
|
587
|
+
|
588
|
+
|
465
589
|
end
|
466
590
|
|
@@ -27,6 +27,13 @@ class BadSequelInterface2 < SequelInterface
|
|
27
27
|
set_id_fld :id
|
28
28
|
end
|
29
29
|
|
30
|
+
class ProdSequelInterface < SequelInterface
|
31
|
+
set_table :product
|
32
|
+
set_id_fld :code
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
|
30
37
|
|
31
38
|
describe TestSequelInterface do
|
32
39
|
|
@@ -63,14 +70,18 @@ describe TestSequelInterface do
|
|
63
70
|
data.each{|r| ifce.create(r) }
|
64
71
|
end
|
65
72
|
|
73
|
+
def fill_product_data(ifce)
|
74
|
+
ifce.create( {code: "foo", name: "bar"} )
|
75
|
+
end
|
76
|
+
|
77
|
+
|
66
78
|
# This is stolen almost verbatim from the Sequel Readme. We use an in-memory
|
67
79
|
# sqlite database, and we assume that Sequel is sane and behaves broadly the
|
68
80
|
# same for our limited purposes as it would when talking to TinyTDS or Pg.
|
69
|
-
#
|
70
|
-
# change this. But in any case, we are not in the business of testing Sequel:
|
71
|
-
# just our interface to it.
|
81
|
+
# We test these elsewhere...
|
72
82
|
let (:db) do
|
73
83
|
db = Sequel.sqlite
|
84
|
+
|
74
85
|
db.create_table :customer do
|
75
86
|
primary_key :id
|
76
87
|
String :name
|
@@ -79,10 +90,17 @@ describe TestSequelInterface do
|
|
79
90
|
Time :timestamp
|
80
91
|
BigDecimal :price, :size=>[10.2] # Sequel doesn't support money
|
81
92
|
end
|
93
|
+
|
94
|
+
db.create_table :product do
|
95
|
+
String :code, :primary_key => true
|
96
|
+
String :name
|
97
|
+
end
|
98
|
+
|
82
99
|
db
|
83
100
|
end
|
84
101
|
|
85
|
-
let(:interface)
|
102
|
+
let(:interface) { TestSequelInterface.new(db) }
|
103
|
+
let(:prod_interface) { ProdSequelInterface.new(db) }
|
86
104
|
|
87
105
|
before do
|
88
106
|
fill_data(interface)
|
@@ -108,8 +126,6 @@ describe TestSequelInterface do
|
|
108
126
|
end
|
109
127
|
|
110
128
|
let(:record) { {name: 'Barney', price: 1.11} }
|
111
|
-
#let(:record_id) { 'Barney' }
|
112
|
-
|
113
129
|
end
|
114
130
|
##
|
115
131
|
|
@@ -215,6 +231,7 @@ describe TestSequelInterface do
|
|
215
231
|
# kinda impossible to seperate these two tests
|
216
232
|
id = interface.create(hash)
|
217
233
|
|
234
|
+
expect( id ).not_to be_nil
|
218
235
|
expect{ interface.read(id) }.not_to raise_exception
|
219
236
|
expect( interface.read(id).to_h ).to include hash
|
220
237
|
end
|
@@ -222,6 +239,7 @@ describe TestSequelInterface do
|
|
222
239
|
it 'creates the record when given an Octothorpe' do
|
223
240
|
id = interface.create(ot)
|
224
241
|
|
242
|
+
expect( id ).not_to be_nil
|
225
243
|
expect{ interface.read(id) }.not_to raise_exception
|
226
244
|
expect( interface.read(id).to_h ).to include ot.to_h
|
227
245
|
end
|
@@ -231,20 +249,29 @@ describe TestSequelInterface do
|
|
231
249
|
expect{ interface.create(name: :Booboo) }.not_to raise_exception
|
232
250
|
end
|
233
251
|
|
234
|
-
it '
|
252
|
+
it 'shouldn\'t have a problem with record values of nil' do
|
235
253
|
record = {name: 'Ranger', price: nil}
|
236
254
|
expect{ interface.create(record) }.not_to raise_exception
|
237
255
|
id = interface.create(record)
|
238
256
|
expect( interface.read(id).to_h ).to include(record)
|
239
257
|
end
|
240
258
|
|
241
|
-
it '
|
259
|
+
it 'shouldn\'t have a problem with strings containing special characters' do
|
242
260
|
record = {name: "T'Challa[]", price: nil}
|
243
261
|
expect{ interface.create(record) }.not_to raise_exception
|
244
262
|
id = interface.create(record)
|
245
263
|
expect( interface.read(id).to_h ).to include(record)
|
246
264
|
end
|
247
265
|
|
266
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
267
|
+
hash = {code: "foo", name: "bar"}
|
268
|
+
id = prod_interface.create( Octothorpe.new(hash) )
|
269
|
+
|
270
|
+
expect( id ).to eq "foo"
|
271
|
+
expect{ prod_interface.read("foo") }.not_to raise_exception
|
272
|
+
expect( prod_interface.read("foo").to_h ).to include hash
|
273
|
+
end
|
274
|
+
|
248
275
|
end
|
249
276
|
##
|
250
277
|
|
@@ -293,6 +320,14 @@ describe TestSequelInterface do
|
|
293
320
|
expect( price ).to eq data.first[:price]
|
294
321
|
end
|
295
322
|
|
323
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
324
|
+
# this is a 100% overlap with the create test above...
|
325
|
+
fill_product_data(prod_interface)
|
326
|
+
|
327
|
+
expect{ prod_interface.read("foo") }.not_to raise_exception
|
328
|
+
expect( prod_interface.read("foo").to_h ).to include(code: "foo", name: "bar")
|
329
|
+
end
|
330
|
+
|
296
331
|
end
|
297
332
|
##
|
298
333
|
|
@@ -305,12 +340,31 @@ describe TestSequelInterface do
|
|
305
340
|
expect{ interface.list(name: 'Barney') }.not_to raise_exception
|
306
341
|
end
|
307
342
|
|
343
|
+
=begin
|
308
344
|
it 'returns an array of Octothorpes that match the records' do
|
309
345
|
# convert each OT to a hash and remove the ID key
|
310
346
|
arr = interface.list.map {|ot| x = ot.to_h; x.delete(:id); x }
|
311
347
|
|
312
348
|
expect( arr ).to match_array data
|
313
349
|
end
|
350
|
+
=end
|
351
|
+
|
352
|
+
it 'returns an array of Octothorpes that match the records' do
|
353
|
+
arr = interface.list.map {|ot| x = ot.to_h}
|
354
|
+
|
355
|
+
expect( arr.size ).to eq(data.size)
|
356
|
+
|
357
|
+
data.each do |d|
|
358
|
+
r = arr.find{|x| x[:name] == d[:name] }
|
359
|
+
expect( r ).not_to be_nil
|
360
|
+
expect( r[:level] ).to be_within(0.001).of( d[:level] )
|
361
|
+
expect( r[:day] ).to eq d[:day]
|
362
|
+
expect( r[:timestamp] ).to eq d[:timestamp]
|
363
|
+
expect( r[:qty] ).to eq d[:qty]
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
314
368
|
|
315
369
|
it 'returns a subset of records based on the selection parameter' do
|
316
370
|
expect( interface.list(name: 'Fred').size ).to eq 1
|
@@ -385,14 +439,20 @@ describe TestSequelInterface do
|
|
385
439
|
expect( interface.read(id).to_h ).to include(record)
|
386
440
|
end
|
387
441
|
|
442
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
443
|
+
fill_product_data(prod_interface)
|
444
|
+
expect{ prod_interface.update("foo", name: "baz") }.not_to raise_error
|
445
|
+
expect( prod_interface.read("foo").to_h[:name] ).to eq "baz"
|
446
|
+
end
|
447
|
+
|
388
448
|
end
|
389
449
|
##
|
390
450
|
|
391
451
|
|
392
452
|
describe '#delete' do
|
393
453
|
|
394
|
-
def list_contains(id)
|
395
|
-
|
454
|
+
def list_contains(ifce, id)
|
455
|
+
ifce.list.find {|x| x[ifce.id_fld] == id }
|
396
456
|
end
|
397
457
|
|
398
458
|
let(:id) { interface.list.first[:id] }
|
@@ -403,9 +463,16 @@ describe TestSequelInterface do
|
|
403
463
|
end
|
404
464
|
|
405
465
|
it 'makes the record at ID go away' do
|
406
|
-
expect( list_contains(id) ).to be_truthy
|
466
|
+
expect( list_contains(interface, id) ).to be_truthy
|
407
467
|
interface.delete(id)
|
408
|
-
expect( list_contains(id) ).to be_falsy
|
468
|
+
expect( list_contains(interface, id) ).to be_falsy
|
469
|
+
end
|
470
|
+
|
471
|
+
it 'shouldn\'t have a problem with non-integer keys' do
|
472
|
+
fill_product_data(prod_interface)
|
473
|
+
expect( list_contains(prod_interface, "foo") ).to be_truthy
|
474
|
+
prod_interface.delete("foo")
|
475
|
+
expect( list_contains(prod_interface, "foo") ).to be_falsy
|
409
476
|
end
|
410
477
|
|
411
478
|
end
|
@@ -471,10 +538,76 @@ describe TestSequelInterface do
|
|
471
538
|
expect( ret ).to eq( [] )
|
472
539
|
end
|
473
540
|
|
474
|
-
|
475
541
|
end
|
476
542
|
##
|
477
543
|
|
478
544
|
|
545
|
+
describe "#executep" do
|
546
|
+
# For the time being lets assume that Sequel does its job and the three modes we are calling
|
547
|
+
# actually work
|
548
|
+
|
549
|
+
let(:sql) { 'delete from customer where price < ?;' }
|
550
|
+
|
551
|
+
it 'requires an SQL string and a mode' do
|
552
|
+
expect{ interface.executep }.to raise_exception ArgumentError
|
553
|
+
expect{ interface.executep(nil) }.to raise_exception ArgumentError
|
554
|
+
expect{ interface.executep(14, :update) }.to raise_exception ArgumentError
|
555
|
+
expect{ interface.executep(14, :update, 2) }.to raise_exception ArgumentError
|
556
|
+
end
|
557
|
+
|
558
|
+
it 'requires the mode to be valid' do
|
559
|
+
expect{ interface.executep(sql, :foo, 2) }.to raise_exception ArgumentError
|
560
|
+
end
|
561
|
+
|
562
|
+
it 'raises some sort of Pod4 error if it runs into problems' do
|
563
|
+
expect{ interface.executep('delete from not_a_table where thingy = ?', :delete, 14) }.
|
564
|
+
to raise_exception Pod4Error
|
565
|
+
|
566
|
+
end
|
567
|
+
|
568
|
+
it 'executes the string' do
|
569
|
+
expect{ interface.executep(sql, :delete, 2.0) }.not_to raise_exception
|
570
|
+
expect( interface.list.size ).to eq(data.size - 1)
|
571
|
+
expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
|
572
|
+
end
|
573
|
+
|
574
|
+
end
|
575
|
+
|
576
|
+
|
577
|
+
describe "#selectp" do
|
578
|
+
|
579
|
+
it 'requires an SQL string' do
|
580
|
+
expect{ interface.selectp }.to raise_exception ArgumentError
|
581
|
+
expect{ interface.selectp(nil) }.to raise_exception ArgumentError
|
582
|
+
expect{ interface.selectp(14) }.to raise_exception ArgumentError
|
583
|
+
end
|
584
|
+
|
585
|
+
it 'raises some sort of Pod4 error if it runs into problems' do
|
586
|
+
expect{ interface.selectp('select * from not_a_table where thingy = ?', 14) }.
|
587
|
+
to raise_exception Pod4Error
|
588
|
+
|
589
|
+
end
|
590
|
+
|
591
|
+
it 'returns the result of the sql' do
|
592
|
+
sql = 'select name from customer where price < ?;'
|
593
|
+
|
594
|
+
expect{ interface.selectp(sql, 2.0) }.not_to raise_exception
|
595
|
+
expect( interface.selectp(sql, 2.0) ).to eq( [{name: 'Barney'}] )
|
596
|
+
expect( interface.selectp(sql, 0.0) ).to eq( [] )
|
597
|
+
end
|
598
|
+
|
599
|
+
it 'works if you pass a non-select' do
|
600
|
+
# By which I mean: still executes the SQL; returns []
|
601
|
+
sql = 'delete from customer where price < ?;'
|
602
|
+
ret = interface.selectp(sql, 2.0)
|
603
|
+
|
604
|
+
expect( interface.list.size ).to eq(data.size - 1)
|
605
|
+
expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney'
|
606
|
+
expect( ret ).to eq( [] )
|
607
|
+
end
|
608
|
+
|
609
|
+
end
|
610
|
+
|
611
|
+
|
479
612
|
end
|
480
613
|
|