pg 0.13.2-x86-mingw32 → 0.14.0.pre.353-x86-mingw32

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.
@@ -239,6 +239,11 @@ RSpec.configure do |config|
239
239
  config.treat_symbols_as_metadata_keys_with_true_values = true
240
240
 
241
241
  config.mock_with :rspec
242
- config.filter_run_excluding :ruby_19 => true if ruby_version_vec <= [1,9,1].pack( "N*" )
242
+ config.filter_run_excluding :ruby_19 if ruby_version_vec <= [1,9,1].pack( "N*" )
243
+
244
+ config.filter_run_excluding :postgresql_90 unless
245
+ PG::Connection.instance_methods.map( &:to_sym ).include?( :escape_literal )
246
+ config.filter_run_excluding :postgresql_91 unless
247
+ PG.respond_to?( :library_version )
243
248
  end
244
249
 
@@ -86,13 +86,13 @@ describe PG::Connection do
86
86
 
87
87
  it "connects successfully with connection string" do
88
88
  tmpconn = described_class.connect(@conninfo)
89
- tmpconn.status.should== PG::CONNECTION_OK
89
+ tmpconn.status.should == PG::CONNECTION_OK
90
90
  tmpconn.finish
91
91
  end
92
92
 
93
93
  it "connects using 7 arguments converted to strings" do
94
94
  tmpconn = described_class.connect('localhost', @port, nil, nil, :test, nil, nil)
95
- tmpconn.status.should== PG::CONNECTION_OK
95
+ tmpconn.status.should == PG::CONNECTION_OK
96
96
  tmpconn.finish
97
97
  end
98
98
 
@@ -101,7 +101,17 @@ describe PG::Connection do
101
101
  :host => 'localhost',
102
102
  :port => @port,
103
103
  :dbname => :test)
104
- tmpconn.status.should== PG::CONNECTION_OK
104
+ tmpconn.status.should == PG::CONNECTION_OK
105
+ tmpconn.finish
106
+ end
107
+
108
+ it "connects using a hash of optional connection parameters" do
109
+ tmpconn = described_class.connect(
110
+ :host => 'localhost',
111
+ :port => @port,
112
+ :dbname => :test,
113
+ :keepalives => 1)
114
+ tmpconn.status.should == PG::CONNECTION_OK
105
115
  tmpconn.finish
106
116
  end
107
117
 
@@ -111,7 +121,6 @@ describe PG::Connection do
111
121
  }.to raise_error( ArgumentError, /extra positional parameter/i )
112
122
  end
113
123
 
114
-
115
124
  it "can connect asynchronously" do
116
125
  tmpconn = described_class.connect_start( @conninfo )
117
126
  tmpconn.should be_a( described_class )
@@ -379,10 +388,156 @@ describe PG::Connection do
379
388
  @conn.exec( 'UNLISTEN woo' )
380
389
  end
381
390
 
382
- context "under PostgreSQL 9" do
391
+ it "yields the result if block is given to exec" do
392
+ rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
393
+ values = []
394
+ result.should be_kind_of( PG::Result )
395
+ result.ntuples.should == 2
396
+ result.each do |tuple|
397
+ values << tuple['a']
398
+ end
399
+ values
400
+ end
401
+
402
+ rval.should have( 2 ).members
403
+ rval.should include( '5678', '1234' )
404
+ end
405
+
406
+
407
+ it "correctly finishes COPY queries passed to #async_exec" do
408
+ @conn.async_exec( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" )
409
+
410
+ results = []
411
+ begin
412
+ data = @conn.get_copy_data( true )
413
+ if false == data
414
+ @conn.block( 2.0 )
415
+ data = @conn.get_copy_data( true )
416
+ end
417
+ results << data if data
418
+ end until data.nil?
419
+
420
+ results.should have( 2 ).members
421
+ results.should include( "1\n", "2\n" )
422
+ end
423
+
424
+
425
+ it "described_class#block shouldn't block a second thread" do
426
+ t = Thread.new do
427
+ @conn.send_query( "select pg_sleep(3)" )
428
+ @conn.block
429
+ end
430
+
431
+ # :FIXME: There's a race here, but hopefully it's pretty small.
432
+ t.should be_alive()
433
+
434
+ @conn.cancel
435
+ t.join
436
+ end
437
+
438
+ it "described_class#block should allow a timeout" do
439
+ @conn.send_query( "select pg_sleep(3)" )
440
+
441
+ start = Time.now
442
+ @conn.block( 0.1 )
443
+ finish = Time.now
444
+
445
+ (finish - start).should be_within( 0.05 ).of( 0.1 )
446
+ end
447
+
448
+
449
+ it "can encrypt a string given a password and username" do
450
+ described_class.encrypt_password("postgres", "postgres").
451
+ should =~ /\S+/
452
+ end
453
+
454
+
455
+ it "raises an appropriate error if either of the required arguments for encrypt_password " +
456
+ "is not valid" do
457
+ expect {
458
+ described_class.encrypt_password( nil, nil )
459
+ }.to raise_error( TypeError )
460
+ expect {
461
+ described_class.encrypt_password( "postgres", nil )
462
+ }.to raise_error( TypeError )
463
+ expect {
464
+ described_class.encrypt_password( nil, "postgres" )
465
+ }.to raise_error( TypeError )
466
+ end
467
+
468
+
469
+ it "allows fetching a column of values from a result by column number" do
470
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
471
+ res.column_values( 0 ).should == %w[1 2 3]
472
+ res.column_values( 1 ).should == %w[2 3 4]
473
+ end
474
+
475
+
476
+ it "allows fetching a column of values from a result by field name" do
477
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
478
+ res.field_values( 'column1' ).should == %w[1 2 3]
479
+ res.field_values( 'column2' ).should == %w[2 3 4]
480
+ end
481
+
482
+
483
+ it "raises an error if selecting an invalid column index" do
484
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
485
+ expect {
486
+ res.column_values( 20 )
487
+ }.to raise_error( IndexError )
488
+ end
489
+
490
+
491
+ it "raises an error if selecting an invalid field name" do
492
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
493
+ expect {
494
+ res.field_values( 'hUUuurrg' )
495
+ }.to raise_error( IndexError )
496
+ end
497
+
498
+
499
+ it "raises an error if column index is not a number" do
500
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
501
+ expect {
502
+ res.column_values( 'hUUuurrg' )
503
+ }.to raise_error( TypeError )
504
+ end
505
+
506
+
507
+ it "can connect asynchronously" do
508
+ serv = TCPServer.new( '127.0.0.1', 54320 )
509
+ conn = described_class.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
510
+ conn.connect_poll.should == PG::PGRES_POLLING_WRITING
511
+ select( nil, [IO.for_fd(conn.socket)], nil, 0.2 )
512
+ serv.close
513
+ if conn.connect_poll == PG::PGRES_POLLING_READING
514
+ select( [IO.for_fd(conn.socket)], nil, nil, 0.2 )
515
+ end
516
+ conn.connect_poll.should == PG::PGRES_POLLING_FAILED
517
+ end
518
+
519
+ it "discards previous results (if any) before waiting on an #async_exec"
520
+
521
+ it "calls the block if one is provided to #async_exec" do
522
+ result = nil
523
+ @conn.async_exec( "select 47 as one" ) do |pg_res|
524
+ result = pg_res[0]
525
+ end
526
+ result.should == { 'one' => '47' }
527
+ end
528
+
529
+ it "raises a rescue-able error if #finish is called twice", :without_transaction do
530
+ conn = PG.connect( @conninfo )
531
+
532
+ conn.finish
533
+ expect { conn.finish }.to raise_error( PG::Error, /connection is closed/i )
534
+ end
535
+
536
+
537
+ context "under PostgreSQL 9", :postgresql_90 do
383
538
 
384
539
  before( :each ) do
385
- pending "only works under PostgreSQL 9" if @conn.server_version < 9_00_00
540
+ pending "only works with a PostgreSQL >= 9.0 server" if @conn.server_version < 9_00_00
386
541
  end
387
542
 
388
543
  it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
@@ -534,153 +689,43 @@ describe PG::Connection do
534
689
 
535
690
  end
536
691
 
537
- it "yields the result if block is given to exec" do
538
- rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
539
- values = []
540
- result.should be_kind_of( PG::Result )
541
- result.ntuples.should == 2
542
- result.each do |tuple|
543
- values << tuple['a']
544
- end
545
- values
546
- end
547
-
548
- rval.should have( 2 ).members
549
- rval.should include( '5678', '1234' )
550
- end
551
-
552
-
553
- it "correctly finishes COPY queries passed to #async_exec" do
554
- @conn.async_exec( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" )
555
-
556
- results = []
557
- begin
558
- data = @conn.get_copy_data( true )
559
- if false == data
560
- @conn.block( 2.0 )
561
- data = @conn.get_copy_data( true )
562
- end
563
- results << data if data
564
- end until data.nil?
565
-
566
- results.should have( 2 ).members
567
- results.should include( "1\n", "2\n" )
568
- end
569
-
692
+ context "under PostgreSQL 9.1 client library", :postgresql_91, :without_transaction do
570
693
 
571
- it "described_class#block shouldn't block a second thread" do
572
- t = Thread.new do
573
- @conn.send_query( "select pg_sleep(3)" )
574
- @conn.block
694
+ it "pings successfully with connection string" do
695
+ ping = described_class.ping(@conninfo)
696
+ ping.should == PG::PQPING_OK
575
697
  end
576
698
 
577
- # :FIXME: There's a race here, but hopefully it's pretty small.
578
- t.should be_alive()
579
-
580
- @conn.cancel
581
- t.join
582
- end
583
-
584
- it "described_class#block should allow a timeout" do
585
- @conn.send_query( "select pg_sleep(3)" )
586
-
587
- start = Time.now
588
- @conn.block( 0.1 )
589
- finish = Time.now
590
-
591
- (finish - start).should be_within( 0.05 ).of( 0.1 )
592
- end
593
-
594
-
595
- it "can encrypt a string given a password and username" do
596
- described_class.encrypt_password("postgres", "postgres").
597
- should =~ /\S+/
598
- end
599
-
600
-
601
- it "raises an appropriate error if either of the required arguments for encrypt_password " +
602
- "is not valid" do
603
- expect {
604
- described_class.encrypt_password( nil, nil )
605
- }.to raise_error( TypeError )
606
- expect {
607
- described_class.encrypt_password( "postgres", nil )
608
- }.to raise_error( TypeError )
609
- expect {
610
- described_class.encrypt_password( nil, "postgres" )
611
- }.to raise_error( TypeError )
612
- end
613
-
614
-
615
- it "allows fetching a column of values from a result by column number" do
616
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
617
- res.column_values( 0 ).should == %w[1 2 3]
618
- res.column_values( 1 ).should == %w[2 3 4]
619
- end
620
-
621
-
622
- it "allows fetching a column of values from a result by field name" do
623
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
624
- res.field_values( 'column1' ).should == %w[1 2 3]
625
- res.field_values( 'column2' ).should == %w[2 3 4]
626
- end
627
-
628
-
629
- it "raises an error if selecting an invalid column index" do
630
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
631
- expect {
632
- res.column_values( 20 )
633
- }.to raise_error( IndexError )
634
- end
635
-
636
-
637
- it "raises an error if selecting an invalid field name" do
638
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
639
- expect {
640
- res.field_values( 'hUUuurrg' )
641
- }.to raise_error( IndexError )
642
- end
643
-
644
-
645
- it "raises an error if column index is not a number" do
646
- res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
647
- expect {
648
- res.column_values( 'hUUuurrg' )
649
- }.to raise_error( TypeError )
650
- end
651
-
699
+ it "pings using 7 arguments converted to strings" do
700
+ ping = described_class.ping('localhost', @port, nil, nil, :test, nil, nil)
701
+ ping.should == PG::PQPING_OK
702
+ end
652
703
 
653
- it "can connect asynchronously" do
654
- serv = TCPServer.new( '127.0.0.1', 54320 )
655
- conn = described_class.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
656
- conn.connect_poll.should == PG::PGRES_POLLING_WRITING
657
- select( nil, [IO.for_fd(conn.socket)], nil, 0.2 )
658
- serv.close
659
- if conn.connect_poll == PG::PGRES_POLLING_READING
660
- select( [IO.for_fd(conn.socket)], nil, nil, 0.2 )
704
+ it "pings using a hash of connection parameters" do
705
+ ping = described_class.ping(
706
+ :host => 'localhost',
707
+ :port => @port,
708
+ :dbname => :test)
709
+ ping.should == PG::PQPING_OK
661
710
  end
662
- conn.connect_poll.should == PG::PGRES_POLLING_FAILED
663
- end
664
711
 
665
- it "discards previous results (if any) before waiting on an #async_exec"
712
+ it "returns correct response when ping connection cannot be established" do
713
+ ping = described_class.ping(
714
+ :host => 'localhost',
715
+ :port => 9999,
716
+ :dbname => :test)
717
+ ping.should == PG::PQPING_NO_RESPONSE
718
+ end
666
719
 
667
- it "calls the block if one is provided to #async_exec" do
668
- result = nil
669
- @conn.async_exec( "select 47 as one" ) do |pg_res|
670
- result = pg_res[0]
720
+ it "returns correct response when ping connection arguments are wrong" do
721
+ ping = described_class.ping('localhost', 'localhost', nil, nil, :test, nil, nil)
722
+ ping.should == PG::PQPING_NO_ATTEMPT
671
723
  end
672
- result.should == { 'one' => '47' }
673
- end
674
724
 
675
- it "raises a rescue-able error if #finish is called twice", :without_transaction do
676
- conn = PG.connect( @conninfo )
677
725
 
678
- conn.finish
679
- expect { conn.finish }.to raise_error( PG::Error, /connection is closed/i )
680
726
  end
681
727
 
682
-
683
- describe "multinationalization support", :ruby_19 => true do
728
+ context "multinationalization support", :ruby_19 do
684
729
 
685
730
  it "should return the same bytes in text format that are sent as inline text" do
686
731
  binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
@@ -771,6 +816,12 @@ describe PG::Connection do
771
816
  escaped = @conn.escape( original )
772
817
  escaped.encoding.should == Encoding::EUC_JP
773
818
  end
819
+
820
+ it "escapes string as literal" do
821
+ original = "string to\0 escape"
822
+ escaped = @conn.escape_literal( original )
823
+ escaped.should == "'string to'"
824
+ end
774
825
  end
775
826
 
776
827
 
@@ -797,6 +848,19 @@ describe PG::Connection do
797
848
  end
798
849
  end
799
850
 
851
+ it "allows users of the async interface to set the client_encoding to the default_internal" do
852
+ begin
853
+ prev_encoding = Encoding.default_internal
854
+ Encoding.default_internal = Encoding::KOI8_U
855
+
856
+ @conn.set_default_encoding
857
+
858
+ @conn.internal_encoding.should == Encoding::KOI8_U
859
+ ensure
860
+ Encoding.default_internal = prev_encoding
861
+ end
862
+ end
863
+
800
864
  end
801
865
 
802
866
 
@@ -92,16 +92,20 @@ describe PG::Result do
92
92
  res = @conn.exec('VALUES ($1::bytea)',
93
93
  [ { :value => bytes, :format => 1 } ], 1)
94
94
  res[0]['column1'].should== bytes
95
+ res.getvalue(0,0).should == bytes
96
+ res.values[0][0].should == bytes
97
+ res.column_values(0)[0].should == bytes
95
98
  end
96
99
 
97
100
  it "should return the same bytes in binary format that are sent as inline text" do
98
101
  binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
99
- in_bytes = File.open(binary_file, 'rb').read
100
- out_bytes = nil
102
+ bytes = File.open(binary_file, 'rb').read
101
103
  @conn.exec("SET standard_conforming_strings=on")
102
- res = @conn.exec("VALUES ('#{PG::Connection.escape_bytea(in_bytes)}'::bytea)", [], 1)
103
- out_bytes = res[0]['column1']
104
- out_bytes.should == in_bytes
104
+ res = @conn.exec("VALUES ('#{PG::Connection.escape_bytea(bytes)}'::bytea)", [], 1)
105
+ res[0]['column1'].should == bytes
106
+ res.getvalue(0,0).should == bytes
107
+ res.values[0][0].should == bytes
108
+ res.column_values(0)[0].should == bytes
105
109
  end
106
110
 
107
111
  it "should return the same bytes in text format that are sent in binary format" do
@@ -123,7 +127,7 @@ describe PG::Result do
123
127
  out_bytes.should == in_bytes
124
128
  end
125
129
 
126
- it "should return the parameter type of the specified prepared statment parameter" do
130
+ it "should return the parameter type of the specified prepared statement parameter" do
127
131
  query = 'SELECT * FROM pg_stat_activity WHERE user = $1::name AND current_query = $2::text'
128
132
  @conn.prepare( 'queryfinder', query )
129
133
  res = @conn.describe_prepared( 'queryfinder' )
@@ -248,4 +252,12 @@ describe PG::Result do
248
252
  res.ftablecol(1).should == 0 # and it shouldn't raise an exception, either
249
253
  end
250
254
 
255
+ it "can be manually checked for failed result status (async API)" do
256
+ @conn.send_query( "SELECT * FROM nonexistant_table" )
257
+ res = @conn.get_result
258
+ expect {
259
+ res.check
260
+ }.to raise_error( PG::Error, /relation "nonexistant_table" does not exist/ )
261
+ end
262
+
251
263
  end