pg 0.12.0 → 0.16.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 (67) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +2 -0
  3. data/BSDL +22 -0
  4. data/ChangeLog +1504 -11
  5. data/Contributors.rdoc +7 -0
  6. data/History.rdoc +181 -3
  7. data/LICENSE +12 -14
  8. data/Manifest.txt +29 -15
  9. data/{BSD → POSTGRES} +0 -0
  10. data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
  11. data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
  12. data/README.ja.rdoc +10 -3
  13. data/README.rdoc +54 -28
  14. data/Rakefile +53 -26
  15. data/Rakefile.cross +235 -196
  16. data/ext/errorcodes.def +931 -0
  17. data/ext/errorcodes.rb +45 -0
  18. data/ext/errorcodes.txt +463 -0
  19. data/ext/extconf.rb +37 -7
  20. data/ext/gvl_wrappers.c +19 -0
  21. data/ext/gvl_wrappers.h +211 -0
  22. data/ext/pg.c +317 -4277
  23. data/ext/pg.h +124 -21
  24. data/ext/pg_connection.c +3642 -0
  25. data/ext/pg_errors.c +89 -0
  26. data/ext/pg_result.c +920 -0
  27. data/lib/pg/connection.rb +86 -0
  28. data/lib/pg/constants.rb +11 -0
  29. data/lib/pg/exceptions.rb +11 -0
  30. data/lib/pg/result.rb +16 -0
  31. data/lib/pg.rb +26 -43
  32. data/sample/array_insert.rb +20 -0
  33. data/sample/async_api.rb +21 -24
  34. data/sample/async_copyto.rb +2 -2
  35. data/sample/async_mixed.rb +56 -0
  36. data/sample/check_conn.rb +21 -0
  37. data/sample/copyfrom.rb +1 -1
  38. data/sample/copyto.rb +1 -1
  39. data/sample/cursor.rb +2 -2
  40. data/sample/disk_usage_report.rb +186 -0
  41. data/sample/issue-119.rb +94 -0
  42. data/sample/losample.rb +6 -6
  43. data/sample/minimal-testcase.rb +17 -0
  44. data/sample/notify_wait.rb +51 -22
  45. data/sample/pg_statistics.rb +294 -0
  46. data/sample/replication_monitor.rb +231 -0
  47. data/sample/test_binary_values.rb +4 -6
  48. data/sample/wal_shipper.rb +434 -0
  49. data/sample/warehouse_partitions.rb +320 -0
  50. data/spec/lib/helpers.rb +70 -23
  51. data/spec/pg/connection_spec.rb +1128 -0
  52. data/spec/{pgresult_spec.rb → pg/result_spec.rb} +142 -47
  53. data/spec/pg_spec.rb +44 -0
  54. data.tar.gz.sig +0 -0
  55. metadata +145 -100
  56. metadata.gz.sig +0 -0
  57. data/GPL +0 -340
  58. data/ext/compat.c +0 -541
  59. data/ext/compat.h +0 -184
  60. data/misc/openssl-pg-segfault.rb +0 -31
  61. data/sample/psql.rb +0 -1181
  62. data/sample/psqlHelp.rb +0 -158
  63. data/sample/test1.rb +0 -60
  64. data/sample/test2.rb +0 -44
  65. data/sample/test4.rb +0 -71
  66. data/spec/m17n_spec.rb +0 -151
  67. data/spec/pgconn_spec.rb +0 -643
data/spec/pgconn_spec.rb DELETED
@@ -1,643 +0,0 @@
1
- #!/usr/bin/env rspec
2
- # encoding: utf-8
3
-
4
- BEGIN {
5
- require 'pathname'
6
- require 'rbconfig'
7
-
8
- basedir = Pathname( __FILE__ ).dirname.parent
9
- libdir = basedir + 'lib'
10
- archlib = libdir + Config::CONFIG['sitearch']
11
-
12
- $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
13
- $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
14
- $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
15
- }
16
-
17
- require 'rspec'
18
- require 'spec/lib/helpers'
19
- require 'pg'
20
- require 'timeout'
21
-
22
- describe PGconn do
23
- include PgTestingHelpers
24
-
25
- before( :all ) do
26
- @conn = setup_testing_db( "PGconn" )
27
- end
28
-
29
- before( :each ) do
30
- @conn.exec( 'BEGIN' )
31
- end
32
-
33
- it "can create a connection option string from a Hash of options" do
34
- optstring = PGconn.parse_connect_args(
35
- :host => 'pgsql.example.com',
36
- :dbname => 'db01',
37
- 'sslmode' => 'require'
38
- )
39
-
40
- optstring.should be_a( String )
41
- optstring.should =~ /(^|\s)host='pgsql.example.com'/
42
- optstring.should =~ /(^|\s)dbname='db01'/
43
- optstring.should =~ /(^|\s)sslmode='require'/
44
- end
45
-
46
- it "can create a connection option string from positional parameters" do
47
- optstring = PGconn.parse_connect_args( 'pgsql.example.com', nil, '-c geqo=off', nil,
48
- 'sales' )
49
-
50
- optstring.should be_a( String )
51
- optstring.should =~ /(^|\s)host='pgsql.example.com'/
52
- optstring.should =~ /(^|\s)dbname='sales'/
53
- optstring.should =~ /(^|\s)options='-c geqo=off'/
54
-
55
- optstring.should_not =~ /port=/
56
- optstring.should_not =~ /tty=/
57
- end
58
-
59
- it "can create a connection option string from a mix of positional and hash parameters" do
60
- optstring = PGconn.parse_connect_args( 'pgsql.example.com',
61
- :dbname => 'licensing', :user => 'jrandom' )
62
-
63
- optstring.should be_a( String )
64
- optstring.should =~ /(^|\s)host='pgsql.example.com'/
65
- optstring.should =~ /(^|\s)dbname='licensing'/
66
- optstring.should =~ /(^|\s)user='jrandom'/
67
- end
68
-
69
- it "escapes single quotes and backslashes in connection parameters" do
70
- PGconn.parse_connect_args( "DB 'browser' \\" ).should == "host='DB \\'browser\\' \\\\'"
71
-
72
- end
73
-
74
- it "connects with defaults if no connection parameters are given" do
75
- PGconn.parse_connect_args.should == ''
76
- end
77
-
78
- it "connects successfully with connection string" do
79
- tmpconn = PGconn.connect(@conninfo)
80
- tmpconn.status.should== PGconn::CONNECTION_OK
81
- tmpconn.finish
82
- end
83
-
84
- it "connects using 7 arguments converted to strings" do
85
- tmpconn = PGconn.connect('localhost', @port, nil, nil, :test, nil, nil)
86
- tmpconn.status.should== PGconn::CONNECTION_OK
87
- tmpconn.finish
88
- end
89
-
90
- it "connects using a hash of connection parameters" do
91
- tmpconn = PGconn.connect(
92
- :host => 'localhost',
93
- :port => @port,
94
- :dbname => :test)
95
- tmpconn.status.should== PGconn::CONNECTION_OK
96
- tmpconn.finish
97
- end
98
-
99
- it "raises an exception when connecting with an invalid number of arguments" do
100
- expect {
101
- PGconn.connect( 1, 2, 3, 4, 5, 6, 7, 'extra' )
102
- }.to raise_error( ArgumentError, /extra positional parameter/i )
103
- end
104
-
105
-
106
- it "can connect asynchronously" do
107
- tmpconn = PGconn.connect_start(@conninfo)
108
- socket = IO.for_fd(tmpconn.socket)
109
- status = tmpconn.connect_poll
110
- while(status != PGconn::PGRES_POLLING_OK) do
111
- if(status == PGconn::PGRES_POLLING_READING)
112
- if(not select([socket],[],[],5.0))
113
- raise "Asynchronous connection timed out!"
114
- end
115
- elsif(status == PGconn::PGRES_POLLING_WRITING)
116
- if(not select([],[socket],[],5.0))
117
- raise "Asynchronous connection timed out!"
118
- end
119
- end
120
- status = tmpconn.connect_poll
121
- end
122
- tmpconn.status.should== PGconn::CONNECTION_OK
123
- tmpconn.finish
124
- end
125
-
126
- it "doesn't leave stale server connections after finish" do
127
- PGconn.connect(@conninfo).finish
128
- sleep 0.5
129
- res = @conn.exec(%[SELECT COUNT(*) AS n FROM pg_stat_activity
130
- WHERE usename IS NOT NULL])
131
- # there's still the global @conn, but should be no more
132
- res[0]['n'].should == '1'
133
- end
134
-
135
-
136
- EXPECTED_TRACE_OUTPUT = %{
137
- To backend> Msg Q
138
- To backend> "SELECT 1 AS one"
139
- To backend> Msg complete, length 21
140
- From backend> T
141
- From backend (#4)> 28
142
- From backend (#2)> 1
143
- From backend> "one"
144
- From backend (#4)> 0
145
- From backend (#2)> 0
146
- From backend (#4)> 23
147
- From backend (#2)> 4
148
- From backend (#4)> -1
149
- From backend (#2)> 0
150
- From backend> D
151
- From backend (#4)> 11
152
- From backend (#2)> 1
153
- From backend (#4)> 1
154
- From backend (1)> 1
155
- From backend> C
156
- From backend (#4)> 13
157
- From backend> "SELECT 1"
158
- From backend> Z
159
- From backend (#4)> 5
160
- From backend> Z
161
- From backend (#4)> 5
162
- From backend> T
163
- }.gsub( /^\t{2}/, '' ).lstrip
164
-
165
- unless RUBY_PLATFORM =~ /mswin|mingw/
166
- it "trace and untrace client-server communication" do
167
- # be careful to explicitly close files so that the
168
- # directory can be removed and we don't have to wait for
169
- # the GC to run.
170
- trace_file = TEST_DIRECTORY + "test_trace.out"
171
- trace_io = trace_file.open( 'w', 0600 )
172
- @conn.trace( trace_io )
173
- trace_io.close
174
-
175
- res = @conn.exec("SELECT 1 AS one")
176
- @conn.untrace
177
-
178
- res = @conn.exec("SELECT 2 AS two")
179
-
180
- trace_data = trace_file.read
181
-
182
- expected_trace_output = EXPECTED_TRACE_OUTPUT.dup
183
- # For PostgreSQL < 9.0, the output will be different:
184
- # -From backend (#4)> 13
185
- # -From backend> "SELECT 1"
186
- # +From backend (#4)> 11
187
- # +From backend> "SELECT"
188
- if @conn.server_version < 90000
189
- expected_trace_output.sub!( /From backend \(#4\)> 13/, 'From backend (#4)> 11' )
190
- expected_trace_output.sub!( /From backend> "SELECT 1"/, 'From backend> "SELECT"' )
191
- end
192
-
193
- trace_data.should == expected_trace_output
194
- end
195
- end
196
-
197
- it "allows a query to be cancelled" do
198
- error = false
199
- @conn.send_query("SELECT pg_sleep(1000)")
200
- @conn.cancel
201
- tmpres = @conn.get_result
202
- if(tmpres.result_status != PGresult::PGRES_TUPLES_OK)
203
- error = true
204
- end
205
- error.should == true
206
- end
207
-
208
- it "automatically rolls back a transaction started with PGconn#transaction if an exception " +
209
- "is raised" do
210
- # abort the per-example transaction so we can test our own
211
- @conn.exec( 'ROLLBACK' )
212
-
213
- res = nil
214
- @conn.exec( "CREATE TABLE pie ( flavor TEXT )" )
215
-
216
- expect {
217
- res = @conn.transaction do
218
- @conn.exec( "INSERT INTO pie VALUES ('rhubarb'), ('cherry'), ('schizophrenia')" )
219
- raise "Oh noes! All pie is gone!"
220
- end
221
- }.to raise_exception( RuntimeError, /all pie is gone/i )
222
-
223
- res = @conn.exec( "SELECT * FROM pie" )
224
- res.ntuples.should == 0
225
- end
226
-
227
- it "not read past the end of a large object" do
228
- @conn.transaction do
229
- oid = @conn.lo_create( 0 )
230
- fd = @conn.lo_open( oid, PGconn::INV_READ|PGconn::INV_WRITE )
231
- @conn.lo_write( fd, "foobar" )
232
- @conn.lo_read( fd, 10 ).should be_nil()
233
- @conn.lo_lseek( fd, 0, PGconn::SEEK_SET )
234
- @conn.lo_read( fd, 10 ).should == 'foobar'
235
- end
236
- end
237
-
238
-
239
- it "can wait for NOTIFY events" do
240
- @conn.exec( 'ROLLBACK' )
241
- @conn.exec( 'LISTEN woo' )
242
-
243
- pid = fork do
244
- begin
245
- conn = PGconn.connect( @conninfo )
246
- sleep 1
247
- conn.exec( 'NOTIFY woo' )
248
- ensure
249
- conn.finish
250
- exit!
251
- end
252
- end
253
-
254
- @conn.wait_for_notify( 10 ).should == 'woo'
255
- @conn.exec( 'UNLISTEN woo' )
256
-
257
- Process.wait( pid )
258
- end
259
-
260
- it "calls a block for NOTIFY events if one is given" do
261
- @conn.exec( 'ROLLBACK' )
262
- @conn.exec( 'LISTEN woo' )
263
-
264
- pid = fork do
265
- begin
266
- conn = PGconn.connect( @conninfo )
267
- sleep 1
268
- conn.exec( 'NOTIFY woo' )
269
- ensure
270
- conn.finish
271
- exit!
272
- end
273
- end
274
-
275
- eventpid = event = nil
276
- @conn.wait_for_notify( 10 ) {|*args| event, eventpid = args }
277
- event.should == 'woo'
278
- eventpid.should be_an( Integer )
279
-
280
- @conn.exec( 'UNLISTEN woo' )
281
-
282
- Process.wait( pid )
283
- end
284
-
285
- it "doesn't collapse sequential notifications" do
286
- @conn.exec( 'ROLLBACK' )
287
- @conn.exec( 'LISTEN woo' )
288
- @conn.exec( 'LISTEN war' )
289
- @conn.exec( 'LISTEN woz' )
290
-
291
- pid = fork do
292
- begin
293
- conn = PGconn.connect( @conninfo )
294
- conn.exec( 'NOTIFY woo' )
295
- conn.exec( 'NOTIFY war' )
296
- conn.exec( 'NOTIFY woz' )
297
- ensure
298
- conn.finish
299
- exit!
300
- end
301
- end
302
-
303
- Process.wait( pid )
304
-
305
- channels = []
306
- 3.times do
307
- channels << @conn.wait_for_notify( 2 )
308
- end
309
-
310
- channels.should have( 3 ).members
311
- channels.should include( 'woo', 'war', 'woz' )
312
-
313
- @conn.exec( 'UNLISTEN woz' )
314
- @conn.exec( 'UNLISTEN war' )
315
- @conn.exec( 'UNLISTEN woo' )
316
- end
317
-
318
- it "returns notifications which are already in the queue before wait_for_notify is called " +
319
- "without waiting for the socket to become readable" do
320
- @conn.exec( 'ROLLBACK' )
321
- @conn.exec( 'LISTEN woo' )
322
-
323
- pid = fork do
324
- begin
325
- conn = PGconn.connect( @conninfo )
326
- conn.exec( 'NOTIFY woo' )
327
- ensure
328
- conn.finish
329
- exit!
330
- end
331
- end
332
-
333
- # Wait for the forked child to send the notification
334
- Process.wait( pid )
335
-
336
- # Cause the notification to buffer, but not be read yet
337
- @conn.exec( 'SELECT 1' )
338
-
339
- @conn.wait_for_notify( 10 ).should == 'woo'
340
- @conn.exec( 'UNLISTEN woo' )
341
- end
342
-
343
- context "under PostgreSQL 9" do
344
-
345
- before( :each ) do
346
- pending "only works under PostgreSQL 9" if @conn.server_version < 9_00_00
347
- end
348
-
349
- it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
350
- "any number of arguments" do
351
-
352
- @conn.exec( 'ROLLBACK' )
353
- @conn.exec( 'LISTEN knees' )
354
-
355
- pid = fork do
356
- conn = PGconn.connect( @conninfo )
357
- conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
358
- conn.finish
359
- exit!
360
- end
361
-
362
- Process.wait( pid )
363
-
364
- event, pid, msg = nil
365
- @conn.wait_for_notify( 10 ) do |*args|
366
- event, pid, msg = *args
367
- end
368
- @conn.exec( 'UNLISTEN knees' )
369
-
370
- event.should == 'knees'
371
- pid.should be_a_kind_of( Integer )
372
- msg.should == 'skirt and boots'
373
- end
374
-
375
- it "accepts nil as the timeout in #wait_for_notify " do
376
- @conn.exec( 'ROLLBACK' )
377
- @conn.exec( 'LISTEN knees' )
378
-
379
- pid = fork do
380
- conn = PGconn.connect( @conninfo )
381
- conn.exec( %Q{NOTIFY knees} )
382
- conn.finish
383
- exit!
384
- end
385
-
386
- Process.wait( pid )
387
-
388
- event, pid = nil
389
- @conn.wait_for_notify( nil ) do |*args|
390
- event, pid = *args
391
- end
392
- @conn.exec( 'UNLISTEN knees' )
393
-
394
- event.should == 'knees'
395
- pid.should be_a_kind_of( Integer )
396
- end
397
-
398
- it "sends nil as the payload if the notification wasn't given one" do
399
- @conn.exec( 'ROLLBACK' )
400
- @conn.exec( 'LISTEN knees' )
401
-
402
- pid = fork do
403
- conn = PGconn.connect( @conninfo )
404
- conn.exec( %Q{NOTIFY knees} )
405
- conn.finish
406
- exit!
407
- end
408
-
409
- Process.wait( pid )
410
-
411
- payload = :notnil
412
- @conn.wait_for_notify( nil ) do |*args|
413
- payload = args[ 2 ]
414
- end
415
- @conn.exec( 'UNLISTEN knees' )
416
-
417
- payload.should be_nil()
418
- end
419
-
420
- it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
421
- "two arguments" do
422
-
423
- @conn.exec( 'ROLLBACK' )
424
- @conn.exec( 'LISTEN knees' )
425
-
426
- pid = fork do
427
- conn = PGconn.connect( @conninfo )
428
- conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
429
- conn.finish
430
- exit!
431
- end
432
-
433
- Process.wait( pid )
434
-
435
- event, pid, msg = nil
436
- @conn.wait_for_notify( 10 ) do |arg1, arg2|
437
- event, pid, msg = arg1, arg2
438
- end
439
- @conn.exec( 'UNLISTEN knees' )
440
-
441
- event.should == 'knees'
442
- pid.should be_a_kind_of( Integer )
443
- msg.should be_nil()
444
- end
445
-
446
- it "calls the block supplied to wait_for_notify with the notify payload if it " +
447
- "doesn't accept arguments" do
448
-
449
- @conn.exec( 'ROLLBACK' )
450
- @conn.exec( 'LISTEN knees' )
451
-
452
- pid = fork do
453
- conn = PGconn.connect( @conninfo )
454
- conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
455
- conn.finish
456
- exit!
457
- end
458
-
459
- Process.wait( pid )
460
-
461
- notification_received = false
462
- @conn.wait_for_notify( 10 ) do
463
- notification_received = true
464
- end
465
- @conn.exec( 'UNLISTEN knees' )
466
-
467
- notification_received.should be_true()
468
- end
469
-
470
- it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
471
- "three arguments" do
472
-
473
- @conn.exec( 'ROLLBACK' )
474
- @conn.exec( 'LISTEN knees' )
475
-
476
- pid = fork do
477
- conn = PGconn.connect( @conninfo )
478
- conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
479
- conn.finish
480
- exit!
481
- end
482
-
483
- Process.wait( pid )
484
-
485
- event, pid, msg = nil
486
- @conn.wait_for_notify( 10 ) do |arg1, arg2, arg3|
487
- event, pid, msg = arg1, arg2, arg3
488
- end
489
- @conn.exec( 'UNLISTEN knees' )
490
-
491
- event.should == 'knees'
492
- pid.should be_a_kind_of( Integer )
493
- msg.should == 'skirt and boots'
494
- end
495
-
496
- end
497
-
498
- it "yields the result if block is given to exec" do
499
- rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
500
- values = []
501
- result.should be_kind_of( PGresult )
502
- result.ntuples.should == 2
503
- result.each do |tuple|
504
- values << tuple['a']
505
- end
506
- values
507
- end
508
-
509
- rval.should have( 2 ).members
510
- rval.should include( '5678', '1234' )
511
- end
512
-
513
-
514
- it "correctly finishes COPY queries passed to #async_exec" do
515
- @conn.async_exec( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" )
516
-
517
- results = []
518
- begin
519
- data = @conn.get_copy_data( true )
520
- if false == data
521
- @conn.block( 2.0 )
522
- data = @conn.get_copy_data( true )
523
- end
524
- results << data if data
525
- end until data.nil?
526
-
527
- results.should have( 2 ).members
528
- results.should include( "1\n", "2\n" )
529
- end
530
-
531
-
532
- it "PGconn#block shouldn't block a second thread" do
533
- t = Thread.new do
534
- @conn.send_query( "select pg_sleep(3)" )
535
- @conn.block
536
- end
537
-
538
- # :FIXME: There's a race here, but hopefully it's pretty small.
539
- t.should be_alive()
540
-
541
- @conn.cancel
542
- t.join
543
- end
544
-
545
- it "PGconn#block should allow a timeout" do
546
- @conn.send_query( "select pg_sleep(3)" )
547
-
548
- start = Time.now
549
- @conn.block( 0.1 )
550
- finish = Time.now
551
-
552
- (finish - start).should be_within( 0.05 ).of( 0.1 )
553
- end
554
-
555
-
556
- it "can encrypt a string given a password and username" do
557
- PGconn.encrypt_password("postgres", "postgres").
558
- should =~ /\S+/
559
- end
560
-
561
-
562
- it "raises an appropriate error if either of the required arguments for encrypt_password " +
563
- "is not valid" do
564
- expect {
565
- PGconn.encrypt_password( nil, nil )
566
- }.to raise_error( TypeError )
567
- expect {
568
- PGconn.encrypt_password( "postgres", nil )
569
- }.to raise_error( TypeError )
570
- expect {
571
- PGconn.encrypt_password( nil, "postgres" )
572
- }.to raise_error( TypeError )
573
- end
574
-
575
-
576
- it "allows fetching a column of values from a result by column number" do
577
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
578
- res.column_values( 0 ).should == %w[1 2 3]
579
- res.column_values( 1 ).should == %w[2 3 4]
580
- end
581
-
582
-
583
- it "allows fetching a column of values from a result by field name" do
584
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
585
- res.field_values( 'column1' ).should == %w[1 2 3]
586
- res.field_values( 'column2' ).should == %w[2 3 4]
587
- end
588
-
589
-
590
- it "raises an error if selecting an invalid column index" do
591
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
592
- expect {
593
- res.column_values( 20 )
594
- }.to raise_error( IndexError )
595
- end
596
-
597
-
598
- it "raises an error if selecting an invalid field name" do
599
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
600
- expect {
601
- res.field_values( 'hUUuurrg' )
602
- }.to raise_error( IndexError )
603
- end
604
-
605
-
606
- it "raises an error if column index is not a number" do
607
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
608
- expect {
609
- res.column_values( 'hUUuurrg' )
610
- }.to raise_error( TypeError )
611
- end
612
-
613
-
614
- it "can connect asynchronously" do
615
- serv = TCPServer.new( '127.0.0.1', 54320 )
616
- conn = PGconn.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
617
- conn.connect_poll.should == PGconn::PGRES_POLLING_WRITING
618
- select( nil, [IO.for_fd(conn.socket)], nil, 0.2 )
619
- serv.close
620
- if conn.connect_poll == PGconn::PGRES_POLLING_READING
621
- select( [IO.for_fd(conn.socket)], nil, nil, 0.2 )
622
- end
623
- conn.connect_poll.should == PGconn::PGRES_POLLING_FAILED
624
- end
625
-
626
- it "discards previous results (if any) before waiting on an #async_exec"
627
-
628
- it "calls the block if one is provided to #async_exec" do
629
- result = nil
630
- @conn.async_exec( "select 47 as one" ) do |pg_res|
631
- result = pg_res[0]
632
- end
633
- result.should == { 'one' => '47' }
634
- end
635
-
636
- after( :each ) do
637
- @conn.exec( 'ROLLBACK' )
638
- end
639
-
640
- after( :all ) do
641
- teardown_testing_db( @conn )
642
- end
643
- end