pg 0.21.0-x86-mingw32 → 1.0.0-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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +62 -82
- data/History.rdoc +28 -0
- data/Manifest.txt +0 -1
- data/README.rdoc +3 -4
- data/Rakefile +3 -4
- data/Rakefile.cross +16 -20
- data/ext/errorcodes.def +8 -0
- data/ext/errorcodes.txt +3 -1
- data/ext/extconf.rb +12 -32
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -39
- data/ext/pg.c +15 -48
- data/ext/pg.h +7 -77
- data/ext/pg_binary_decoder.c +1 -1
- data/ext/pg_binary_encoder.c +1 -1
- data/ext/pg_connection.c +91 -130
- data/ext/pg_result.c +5 -9
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +1 -1
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +1 -1
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +1 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/util.c +1 -1
- data/lib/2.0/pg_ext.so +0 -0
- data/lib/2.1/pg_ext.so +0 -0
- data/lib/2.2/pg_ext.so +0 -0
- data/lib/2.3/pg_ext.so +0 -0
- data/lib/2.4/pg_ext.so +0 -0
- data/lib/2.5/pg_ext.so +0 -0
- data/lib/libpq.dll +0 -0
- data/lib/pg.rb +2 -6
- data/lib/pg/connection.rb +7 -2
- data/spec/helpers.rb +8 -12
- data/spec/pg/connection_spec.rb +228 -185
- data/spec/pg/result_spec.rb +3 -3
- data/spec/pg/type_spec.rb +1 -1
- data/spec/pg_spec.rb +1 -1
- metadata +36 -24
- metadata.gz.sig +0 -0
- data/lib/pg/deprecated_constants.rb +0 -21
data/ext/pg_result.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_result.c - PG::Result class extension
|
3
|
-
* $Id$
|
3
|
+
* $Id: pg_result.c,v 7c5d9608349f 2018/01/03 16:11:52 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -92,12 +92,8 @@ pg_result_check( VALUE self )
|
|
92
92
|
case PGRES_TUPLES_OK:
|
93
93
|
case PGRES_COPY_OUT:
|
94
94
|
case PGRES_COPY_IN:
|
95
|
-
#ifdef HAVE_CONST_PGRES_COPY_BOTH
|
96
95
|
case PGRES_COPY_BOTH:
|
97
|
-
#endif
|
98
|
-
#ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
|
99
96
|
case PGRES_SINGLE_TUPLE:
|
100
|
-
#endif
|
101
97
|
case PGRES_EMPTY_QUERY:
|
102
98
|
case PGRES_COMMAND_OK:
|
103
99
|
return self;
|
@@ -1056,7 +1052,6 @@ pgresult_type_map_get(VALUE self)
|
|
1056
1052
|
return this->typemap;
|
1057
1053
|
}
|
1058
1054
|
|
1059
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1060
1055
|
/*
|
1061
1056
|
* call-seq:
|
1062
1057
|
* res.stream_each{ |tuple| ... }
|
@@ -1087,6 +1082,8 @@ pgresult_type_map_get(VALUE self)
|
|
1087
1082
|
* # do something with the received row of the second query
|
1088
1083
|
* end
|
1089
1084
|
* conn.get_result # => nil (no more results)
|
1085
|
+
*
|
1086
|
+
* Available since PostgreSQL-9.2
|
1090
1087
|
*/
|
1091
1088
|
static VALUE
|
1092
1089
|
pgresult_stream_each(VALUE self)
|
@@ -1150,6 +1147,8 @@ pgresult_stream_each(VALUE self)
|
|
1150
1147
|
*
|
1151
1148
|
* This method works equally to #stream_each , but yields an Array of
|
1152
1149
|
* values.
|
1150
|
+
*
|
1151
|
+
* Available since PostgreSQL-9.2
|
1153
1152
|
*/
|
1154
1153
|
static VALUE
|
1155
1154
|
pgresult_stream_each_row(VALUE self)
|
@@ -1210,7 +1209,6 @@ pgresult_stream_each_row(VALUE self)
|
|
1210
1209
|
/* never reached */
|
1211
1210
|
return self;
|
1212
1211
|
}
|
1213
|
-
#endif
|
1214
1212
|
|
1215
1213
|
|
1216
1214
|
void
|
@@ -1267,11 +1265,9 @@ init_pg_result()
|
|
1267
1265
|
rb_define_method(rb_cPGresult, "type_map=", pgresult_type_map_set, 1);
|
1268
1266
|
rb_define_method(rb_cPGresult, "type_map", pgresult_type_map_get, 0);
|
1269
1267
|
|
1270
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1271
1268
|
/****** PG::Result INSTANCE METHODS: streaming ******/
|
1272
1269
|
rb_define_method(rb_cPGresult, "stream_each", pgresult_stream_each, 0);
|
1273
1270
|
rb_define_method(rb_cPGresult, "stream_each_row", pgresult_stream_each_row, 0);
|
1274
|
-
#endif
|
1275
1271
|
}
|
1276
1272
|
|
1277
1273
|
|
data/ext/pg_text_decoder.c
CHANGED
data/ext/pg_text_encoder.c
CHANGED
data/ext/pg_type_map.c
CHANGED
data/ext/pg_type_map_by_class.c
CHANGED
data/ext/pg_type_map_by_column.c
CHANGED
data/ext/pg_type_map_by_oid.c
CHANGED
data/ext/pg_type_map_in_ruby.c
CHANGED
data/ext/util.c
CHANGED
data/lib/2.0/pg_ext.so
CHANGED
Binary file
|
data/lib/2.1/pg_ext.so
CHANGED
Binary file
|
data/lib/2.2/pg_ext.so
CHANGED
Binary file
|
data/lib/2.3/pg_ext.so
CHANGED
Binary file
|
data/lib/2.4/pg_ext.so
CHANGED
Binary file
|
data/lib/2.5/pg_ext.so
ADDED
Binary file
|
data/lib/libpq.dll
CHANGED
Binary file
|
data/lib/pg.rb
CHANGED
@@ -35,10 +35,10 @@ end
|
|
35
35
|
module PG
|
36
36
|
|
37
37
|
# Library version
|
38
|
-
VERSION = '0.
|
38
|
+
VERSION = '1.0.0'
|
39
39
|
|
40
40
|
# VCS revision
|
41
|
-
REVISION = %q$Revision$
|
41
|
+
REVISION = %q$Revision: fef434914848 $
|
42
42
|
|
43
43
|
class NotAllCopyDataRetrieved < PG::Error
|
44
44
|
end
|
@@ -70,7 +70,3 @@ module PG
|
|
70
70
|
end # module PG
|
71
71
|
|
72
72
|
|
73
|
-
autoload :PGError, 'pg/deprecated_constants'
|
74
|
-
autoload :PGconn, 'pg/deprecated_constants'
|
75
|
-
autoload :PGresult, 'pg/deprecated_constants'
|
76
|
-
|
data/lib/pg/connection.rb
CHANGED
@@ -47,7 +47,7 @@ class PG::Connection
|
|
47
47
|
|
48
48
|
if args.length == 1
|
49
49
|
case args.first
|
50
|
-
when URI, URI.regexp
|
50
|
+
when URI, /\A#{URI.regexp}\z/
|
51
51
|
uri = URI(args.first)
|
52
52
|
options.merge!( Hash[URI.decode_www_form( uri.query )] ) if uri.query
|
53
53
|
when /=/
|
@@ -85,7 +85,7 @@ class PG::Connection
|
|
85
85
|
|
86
86
|
|
87
87
|
# call-seq:
|
88
|
-
# conn.copy_data( sql ) {|sql_result| ... } -> PG::Result
|
88
|
+
# conn.copy_data( sql [, coder] ) {|sql_result| ... } -> PG::Result
|
89
89
|
#
|
90
90
|
# Execute a copy process for transfering data to or from the server.
|
91
91
|
#
|
@@ -109,6 +109,11 @@ class PG::Connection
|
|
109
109
|
# of blocking mode of operation, #copy_data is preferred to raw calls
|
110
110
|
# of #put_copy_data, #get_copy_data and #put_copy_end.
|
111
111
|
#
|
112
|
+
# _coder_ can be a PG::Coder derivation
|
113
|
+
# (typically PG::TextEncoder::CopyRow or PG::TextDecoder::CopyRow).
|
114
|
+
# This enables encoding of data fields given to #put_copy_data
|
115
|
+
# or decoding of fields received by #get_copy_data.
|
116
|
+
#
|
112
117
|
# Example with CSV input format:
|
113
118
|
# conn.exec "create table my_table (a text,b text,c text,d text)"
|
114
119
|
# conn.copy_data "COPY my_table FROM STDIN CSV" do
|
data/spec/helpers.rb
CHANGED
@@ -5,7 +5,9 @@ require 'rspec'
|
|
5
5
|
require 'shellwords'
|
6
6
|
require 'pg'
|
7
7
|
|
8
|
-
|
8
|
+
DEFAULT_TEST_DIR_STR = File.join(Dir.pwd, "tmp_test_specs")
|
9
|
+
TEST_DIR_STR = ENV['RUBY_PG_TEST_DIR'] || DEFAULT_TEST_DIR_STR
|
10
|
+
TEST_DIRECTORY = Pathname.new(TEST_DIR_STR)
|
9
11
|
|
10
12
|
module PG::TestingHelpers
|
11
13
|
|
@@ -251,7 +253,7 @@ module PG::TestingHelpers
|
|
251
253
|
|
252
254
|
def check_for_lingering_connections( conn )
|
253
255
|
conn.exec( "SELECT * FROM pg_stat_activity" ) do |res|
|
254
|
-
conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid }
|
256
|
+
conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid && ["client backend", nil].include?(row["backend_type"]) }
|
255
257
|
unless conns.empty?
|
256
258
|
puts "Lingering connections remain:"
|
257
259
|
conns.each do |row|
|
@@ -339,14 +341,8 @@ RSpec.configure do |config|
|
|
339
341
|
config.filter_run_excluding :socket_io unless
|
340
342
|
PG::Connection.instance_methods.map( &:to_sym ).include?( :socket_io )
|
341
343
|
|
342
|
-
if PG.library_version <
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
elsif PG.library_version < 90400
|
347
|
-
config.filter_run_excluding( :postgresql_94, :postgresql_95 )
|
348
|
-
elsif PG.library_version < 90500
|
349
|
-
config.filter_run_excluding( :postgresql_95 )
|
350
|
-
end
|
344
|
+
config.filter_run_excluding( :postgresql_93 ) if PG.library_version < 90300
|
345
|
+
config.filter_run_excluding( :postgresql_94 ) if PG.library_version < 90400
|
346
|
+
config.filter_run_excluding( :postgresql_95 ) if PG.library_version < 90500
|
347
|
+
config.filter_run_excluding( :postgresql_10 ) if PG.library_version < 100000
|
351
348
|
end
|
352
|
-
|
data/spec/pg/connection_spec.rb
CHANGED
@@ -118,6 +118,19 @@ describe PG::Connection do
|
|
118
118
|
expect( described_class.parse_connect_args ).to eq( '' )
|
119
119
|
end
|
120
120
|
|
121
|
+
it "connects successfully with connection string" do
|
122
|
+
conninfo_with_colon_in_password = "host=localhost user=a port=555 dbname=test password=a:a"
|
123
|
+
|
124
|
+
string = described_class.parse_connect_args( conninfo_with_colon_in_password )
|
125
|
+
|
126
|
+
expect( string ).to be_a( String )
|
127
|
+
expect( string ).to match( %r{(^|\s)user=a} )
|
128
|
+
expect( string ).to match( %r{(^|\s)password=a:a} )
|
129
|
+
expect( string ).to match( %r{(^|\s)host=localhost} )
|
130
|
+
expect( string ).to match( %r{(^|\s)port=555} )
|
131
|
+
expect( string ).to match( %r{(^|\s)dbname=test} )
|
132
|
+
end
|
133
|
+
|
121
134
|
it "connects successfully with connection string" do
|
122
135
|
tmpconn = described_class.connect( @conninfo )
|
123
136
|
expect( tmpconn.status ).to eq( PG::CONNECTION_OK )
|
@@ -139,7 +152,7 @@ describe PG::Connection do
|
|
139
152
|
tmpconn.finish
|
140
153
|
end
|
141
154
|
|
142
|
-
it "connects using a hash of optional connection parameters"
|
155
|
+
it "connects using a hash of optional connection parameters" do
|
143
156
|
tmpconn = described_class.connect(
|
144
157
|
:host => 'localhost',
|
145
158
|
:port => @port,
|
@@ -219,7 +232,7 @@ describe PG::Connection do
|
|
219
232
|
described_class.connect(@conninfo).finish
|
220
233
|
sleep 0.5
|
221
234
|
res = @conn.exec(%[SELECT COUNT(*) AS n FROM pg_stat_activity
|
222
|
-
WHERE usename IS NOT NULL])
|
235
|
+
WHERE usename IS NOT NULL AND application_name != ''])
|
223
236
|
# there's still the global @conn, but should be no more
|
224
237
|
expect( res[0]['n'] ).to eq( '1' )
|
225
238
|
end
|
@@ -524,7 +537,7 @@ describe PG::Connection do
|
|
524
537
|
@conn.exec( 'UNLISTEN woo' )
|
525
538
|
end
|
526
539
|
|
527
|
-
it "can receive notices while waiting for NOTIFY without exceeding the timeout"
|
540
|
+
it "can receive notices while waiting for NOTIFY without exceeding the timeout" do
|
528
541
|
notices = []
|
529
542
|
@conn.set_notice_processor do |msg|
|
530
543
|
notices << [msg, Time.now]
|
@@ -586,7 +599,7 @@ describe PG::Connection do
|
|
586
599
|
expect( @conn ).to still_be_usable
|
587
600
|
end
|
588
601
|
|
589
|
-
it "can handle server errors in #copy_data for output"
|
602
|
+
it "can handle server errors in #copy_data for output" do
|
590
603
|
@conn.exec "ROLLBACK"
|
591
604
|
@conn.transaction do
|
592
605
|
@conn.exec( "CREATE FUNCTION errfunc() RETURNS int AS $$ BEGIN RAISE 'test-error'; END; $$ LANGUAGE plpgsql;" )
|
@@ -718,11 +731,6 @@ describe PG::Connection do
|
|
718
731
|
expect( (finish - start) ).to be_within( 0.2 ).of( 0.3 )
|
719
732
|
end
|
720
733
|
|
721
|
-
|
722
|
-
it "can encrypt a string given a password and username" do
|
723
|
-
expect( described_class.encrypt_password("postgres", "postgres") ).to match( /\S+/ )
|
724
|
-
end
|
725
|
-
|
726
734
|
it "can return the default connection options" do
|
727
735
|
expect( described_class.conndefaults ).to be_a( Array )
|
728
736
|
expect( described_class.conndefaults ).to all( be_a(Hash) )
|
@@ -779,18 +787,52 @@ describe PG::Connection do
|
|
779
787
|
end
|
780
788
|
end
|
781
789
|
|
790
|
+
describe "deprecated password encryption method" do
|
791
|
+
it "can encrypt password for a given user" do
|
792
|
+
expect( described_class.encrypt_password("postgres", "postgres") ).to match( /\S+/ )
|
793
|
+
end
|
782
794
|
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
795
|
+
it "raises an appropriate error if either of the required arguments is not valid" do
|
796
|
+
expect {
|
797
|
+
described_class.encrypt_password( nil, nil )
|
798
|
+
}.to raise_error( TypeError )
|
799
|
+
expect {
|
800
|
+
described_class.encrypt_password( "postgres", nil )
|
801
|
+
}.to raise_error( TypeError )
|
802
|
+
expect {
|
803
|
+
described_class.encrypt_password( nil, "postgres" )
|
804
|
+
}.to raise_error( TypeError )
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
describe "password encryption method", :postgresql_10 do
|
809
|
+
it "can encrypt without algorithm" do
|
810
|
+
expect( @conn.encrypt_password("postgres", "postgres") ).to match( /\S+/ )
|
811
|
+
expect( @conn.encrypt_password("postgres", "postgres", nil) ).to match( /\S+/ )
|
812
|
+
end
|
813
|
+
|
814
|
+
it "can encrypt with algorithm" do
|
815
|
+
expect( @conn.encrypt_password("postgres", "postgres", "md5") ).to match( /md5\S+/i )
|
816
|
+
expect( @conn.encrypt_password("postgres", "postgres", "scram-sha-256") ).to match( /SCRAM-SHA-256\S+/i )
|
817
|
+
end
|
818
|
+
|
819
|
+
it "raises an appropriate error if either of the required arguments is not valid" do
|
820
|
+
expect {
|
821
|
+
@conn.encrypt_password( nil, nil )
|
822
|
+
}.to raise_error( TypeError )
|
823
|
+
expect {
|
824
|
+
@conn.encrypt_password( "postgres", nil )
|
825
|
+
}.to raise_error( TypeError )
|
826
|
+
expect {
|
827
|
+
@conn.encrypt_password( nil, "postgres" )
|
828
|
+
}.to raise_error( TypeError )
|
829
|
+
expect {
|
830
|
+
@conn.encrypt_password( "postgres", "postgres", :invalid )
|
831
|
+
}.to raise_error( TypeError )
|
832
|
+
expect {
|
833
|
+
@conn.encrypt_password( "postgres", "postgres", "invalid" )
|
834
|
+
}.to raise_error( PG::Error, /unrecognized/ )
|
835
|
+
end
|
794
836
|
end
|
795
837
|
|
796
838
|
|
@@ -889,155 +931,147 @@ describe PG::Connection do
|
|
889
931
|
expect{ conn.block }.to raise_error(PG::ConnectionBad, /can't get socket descriptor/)
|
890
932
|
end
|
891
933
|
|
892
|
-
|
934
|
+
it "sets the fallback_application_name on new connections" do
|
935
|
+
conn_string = PG::Connection.parse_connect_args( 'dbname=test' )
|
893
936
|
|
894
|
-
|
895
|
-
|
896
|
-
|
937
|
+
conn_name = conn_string[ /application_name='(.*?)'/, 1 ]
|
938
|
+
expect( conn_name ).to include( $0[0..10] )
|
939
|
+
expect( conn_name ).to include( $0[-10..-1] )
|
940
|
+
expect( conn_name.length ).to be <= 64
|
941
|
+
end
|
897
942
|
|
898
|
-
|
943
|
+
it "sets a shortened fallback_application_name on new connections" do
|
944
|
+
old_0 = $0
|
945
|
+
begin
|
946
|
+
$0 = "/this/is/a/very/long/path/with/many/directories/to/our/beloved/ruby"
|
899
947
|
conn_string = PG::Connection.parse_connect_args( 'dbname=test' )
|
900
|
-
|
901
948
|
conn_name = conn_string[ /application_name='(.*?)'/, 1 ]
|
902
949
|
expect( conn_name ).to include( $0[0..10] )
|
903
950
|
expect( conn_name ).to include( $0[-10..-1] )
|
904
951
|
expect( conn_name.length ).to be <= 64
|
952
|
+
ensure
|
953
|
+
$0 = old_0
|
905
954
|
end
|
955
|
+
end
|
906
956
|
|
907
|
-
|
908
|
-
|
909
|
-
begin
|
910
|
-
$0 = "/this/is/a/very/long/path/with/many/directories/to/our/beloved/ruby"
|
911
|
-
conn_string = PG::Connection.parse_connect_args( 'dbname=test' )
|
912
|
-
conn_name = conn_string[ /application_name='(.*?)'/, 1 ]
|
913
|
-
expect( conn_name ).to include( $0[0..10] )
|
914
|
-
expect( conn_name ).to include( $0[-10..-1] )
|
915
|
-
expect( conn_name.length ).to be <= 64
|
916
|
-
ensure
|
917
|
-
$0 = old_0
|
918
|
-
end
|
919
|
-
end
|
920
|
-
|
921
|
-
it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
|
922
|
-
"any number of arguments" do
|
923
|
-
|
924
|
-
@conn.exec( 'ROLLBACK' )
|
925
|
-
@conn.exec( 'LISTEN knees' )
|
957
|
+
it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
|
958
|
+
"any number of arguments" do
|
926
959
|
|
927
|
-
|
928
|
-
|
929
|
-
conn.finish
|
960
|
+
@conn.exec( 'ROLLBACK' )
|
961
|
+
@conn.exec( 'LISTEN knees' )
|
930
962
|
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
end
|
935
|
-
@conn.exec( 'UNLISTEN knees' )
|
963
|
+
conn = described_class.connect( @conninfo )
|
964
|
+
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
965
|
+
conn.finish
|
936
966
|
|
937
|
-
|
938
|
-
|
939
|
-
|
967
|
+
event, pid, msg = nil
|
968
|
+
@conn.wait_for_notify( 10 ) do |*args|
|
969
|
+
event, pid, msg = *args
|
940
970
|
end
|
971
|
+
@conn.exec( 'UNLISTEN knees' )
|
941
972
|
|
942
|
-
|
943
|
-
|
944
|
-
|
973
|
+
expect( event ).to eq( 'knees' )
|
974
|
+
expect( pid ).to be_a_kind_of( Integer )
|
975
|
+
expect( msg ).to eq( 'skirt and boots' )
|
976
|
+
end
|
945
977
|
|
946
|
-
|
947
|
-
|
948
|
-
|
978
|
+
it "accepts nil as the timeout in #wait_for_notify " do
|
979
|
+
@conn.exec( 'ROLLBACK' )
|
980
|
+
@conn.exec( 'LISTEN knees' )
|
949
981
|
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
end
|
954
|
-
@conn.exec( 'UNLISTEN knees' )
|
982
|
+
conn = described_class.connect( @conninfo )
|
983
|
+
conn.exec( %Q{NOTIFY knees} )
|
984
|
+
conn.finish
|
955
985
|
|
956
|
-
|
957
|
-
|
986
|
+
event, pid = nil
|
987
|
+
@conn.wait_for_notify( nil ) do |*args|
|
988
|
+
event, pid = *args
|
958
989
|
end
|
990
|
+
@conn.exec( 'UNLISTEN knees' )
|
959
991
|
|
960
|
-
|
961
|
-
|
962
|
-
|
992
|
+
expect( event ).to eq( 'knees' )
|
993
|
+
expect( pid ).to be_a_kind_of( Integer )
|
994
|
+
end
|
963
995
|
|
964
|
-
|
965
|
-
|
966
|
-
|
996
|
+
it "sends nil as the payload if the notification wasn't given one" do
|
997
|
+
@conn.exec( 'ROLLBACK' )
|
998
|
+
@conn.exec( 'LISTEN knees' )
|
967
999
|
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
end
|
972
|
-
@conn.exec( 'UNLISTEN knees' )
|
1000
|
+
conn = described_class.connect( @conninfo )
|
1001
|
+
conn.exec( %Q{NOTIFY knees} )
|
1002
|
+
conn.finish
|
973
1003
|
|
974
|
-
|
1004
|
+
payload = :notnil
|
1005
|
+
@conn.wait_for_notify( nil ) do |*args|
|
1006
|
+
payload = args[ 2 ]
|
975
1007
|
end
|
1008
|
+
@conn.exec( 'UNLISTEN knees' )
|
976
1009
|
|
977
|
-
|
978
|
-
|
1010
|
+
expect( payload ).to be_nil()
|
1011
|
+
end
|
979
1012
|
|
980
|
-
|
981
|
-
|
1013
|
+
it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
|
1014
|
+
"two arguments" do
|
982
1015
|
|
983
|
-
|
984
|
-
|
985
|
-
conn.finish
|
1016
|
+
@conn.exec( 'ROLLBACK' )
|
1017
|
+
@conn.exec( 'LISTEN knees' )
|
986
1018
|
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
end
|
991
|
-
@conn.exec( 'UNLISTEN knees' )
|
1019
|
+
conn = described_class.connect( @conninfo )
|
1020
|
+
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
1021
|
+
conn.finish
|
992
1022
|
|
993
|
-
|
994
|
-
|
995
|
-
|
1023
|
+
event, pid, msg = nil
|
1024
|
+
@conn.wait_for_notify( 10 ) do |arg1, arg2|
|
1025
|
+
event, pid, msg = arg1, arg2
|
996
1026
|
end
|
1027
|
+
@conn.exec( 'UNLISTEN knees' )
|
997
1028
|
|
998
|
-
|
999
|
-
|
1029
|
+
expect( event ).to eq( 'knees' )
|
1030
|
+
expect( pid ).to be_a_kind_of( Integer )
|
1031
|
+
expect( msg ).to be_nil()
|
1032
|
+
end
|
1000
1033
|
|
1001
|
-
|
1002
|
-
|
1034
|
+
it "calls the block supplied to wait_for_notify with the notify payload if it " +
|
1035
|
+
"doesn't accept arguments" do
|
1003
1036
|
|
1004
|
-
|
1005
|
-
|
1006
|
-
conn.finish
|
1037
|
+
@conn.exec( 'ROLLBACK' )
|
1038
|
+
@conn.exec( 'LISTEN knees' )
|
1007
1039
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
end
|
1012
|
-
@conn.exec( 'UNLISTEN knees' )
|
1040
|
+
conn = described_class.connect( @conninfo )
|
1041
|
+
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
1042
|
+
conn.finish
|
1013
1043
|
|
1014
|
-
|
1044
|
+
notification_received = false
|
1045
|
+
@conn.wait_for_notify( 10 ) do
|
1046
|
+
notification_received = true
|
1015
1047
|
end
|
1048
|
+
@conn.exec( 'UNLISTEN knees' )
|
1016
1049
|
|
1017
|
-
|
1018
|
-
|
1050
|
+
expect( notification_received ).to be_truthy()
|
1051
|
+
end
|
1019
1052
|
|
1020
|
-
|
1021
|
-
|
1053
|
+
it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
|
1054
|
+
"three arguments" do
|
1022
1055
|
|
1023
|
-
|
1024
|
-
|
1025
|
-
conn.finish
|
1056
|
+
@conn.exec( 'ROLLBACK' )
|
1057
|
+
@conn.exec( 'LISTEN knees' )
|
1026
1058
|
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
end
|
1031
|
-
@conn.exec( 'UNLISTEN knees' )
|
1059
|
+
conn = described_class.connect( @conninfo )
|
1060
|
+
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
1061
|
+
conn.finish
|
1032
1062
|
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1063
|
+
event, pid, msg = nil
|
1064
|
+
@conn.wait_for_notify( 10 ) do |arg1, arg2, arg3|
|
1065
|
+
event, pid, msg = arg1, arg2, arg3
|
1036
1066
|
end
|
1067
|
+
@conn.exec( 'UNLISTEN knees' )
|
1037
1068
|
|
1069
|
+
expect( event ).to eq( 'knees' )
|
1070
|
+
expect( pid ).to be_a_kind_of( Integer )
|
1071
|
+
expect( msg ).to eq( 'skirt and boots' )
|
1038
1072
|
end
|
1039
1073
|
|
1040
|
-
context "
|
1074
|
+
context "server ping", :without_transaction do
|
1041
1075
|
|
1042
1076
|
it "pings successfully with connection string" do
|
1043
1077
|
ping = described_class.ping(@conninfo)
|
@@ -1070,71 +1104,69 @@ describe PG::Connection do
|
|
1070
1104
|
expect( ping ).to eq( PG::PQPING_NO_ATTEMPT )
|
1071
1105
|
end
|
1072
1106
|
|
1073
|
-
|
1074
1107
|
end
|
1075
1108
|
|
1076
|
-
|
1077
|
-
describe "set_single_row_mode" do
|
1109
|
+
describe "set_single_row_mode" do
|
1078
1110
|
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1111
|
+
it "raises an error when called at the wrong time" do
|
1112
|
+
expect {
|
1113
|
+
@conn.set_single_row_mode
|
1114
|
+
}.to raise_error(PG::Error)
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
it "should work in single row mode" do
|
1118
|
+
@conn.send_query( "SELECT generate_series(1,10)" )
|
1119
|
+
@conn.set_single_row_mode
|
1120
|
+
|
1121
|
+
results = []
|
1122
|
+
loop do
|
1123
|
+
@conn.block
|
1124
|
+
res = @conn.get_result or break
|
1125
|
+
results << res
|
1083
1126
|
end
|
1127
|
+
expect( results.length ).to eq( 11 )
|
1128
|
+
results[0..-2].each do |res|
|
1129
|
+
expect( res.result_status ).to eq( PG::PGRES_SINGLE_TUPLE )
|
1130
|
+
values = res.field_values('generate_series')
|
1131
|
+
expect( values.length ).to eq( 1 )
|
1132
|
+
expect( values.first.to_i ).to be > 0
|
1133
|
+
end
|
1134
|
+
expect( results.last.result_status ).to eq( PG::PGRES_TUPLES_OK )
|
1135
|
+
expect( results.last.ntuples ).to eq( 0 )
|
1136
|
+
end
|
1084
1137
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1138
|
+
it "should receive rows before entire query is finished" do
|
1139
|
+
@conn.send_query( "SELECT generate_series(0,999), NULL UNION ALL SELECT 1000, pg_sleep(1);" )
|
1140
|
+
@conn.set_single_row_mode
|
1088
1141
|
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
expect( results.length ).to eq( 11 )
|
1096
|
-
results[0..-2].each do |res|
|
1097
|
-
expect( res.result_status ).to eq( PG::PGRES_SINGLE_TUPLE )
|
1098
|
-
values = res.field_values('generate_series')
|
1099
|
-
expect( values.length ).to eq( 1 )
|
1100
|
-
expect( values.first.to_i ).to be > 0
|
1101
|
-
end
|
1102
|
-
expect( results.last.result_status ).to eq( PG::PGRES_TUPLES_OK )
|
1103
|
-
expect( results.last.ntuples ).to eq( 0 )
|
1142
|
+
start_time = Time.now
|
1143
|
+
first_row_time = nil
|
1144
|
+
loop do
|
1145
|
+
res = @conn.get_result or break
|
1146
|
+
res.check
|
1147
|
+
first_row_time = Time.now unless first_row_time
|
1104
1148
|
end
|
1149
|
+
expect( (Time.now - start_time) ).to be >= 0.9
|
1150
|
+
expect( (first_row_time - start_time) ).to be < 0.9
|
1151
|
+
end
|
1105
1152
|
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1153
|
+
it "should receive rows before entire query fails" do
|
1154
|
+
@conn.exec( "CREATE FUNCTION errfunc() RETURNS int AS $$ BEGIN RAISE 'test-error'; END; $$ LANGUAGE plpgsql;" )
|
1155
|
+
@conn.send_query( "SELECT generate_series(0,999), NULL UNION ALL SELECT 1000, errfunc();" )
|
1156
|
+
@conn.set_single_row_mode
|
1109
1157
|
|
1110
|
-
|
1111
|
-
|
1158
|
+
first_result = nil
|
1159
|
+
expect do
|
1112
1160
|
loop do
|
1113
1161
|
res = @conn.get_result or break
|
1114
1162
|
res.check
|
1115
|
-
|
1163
|
+
first_result ||= res
|
1116
1164
|
end
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
it "should receive rows before entire query fails" do
|
1122
|
-
@conn.exec( "CREATE FUNCTION errfunc() RETURNS int AS $$ BEGIN RAISE 'test-error'; END; $$ LANGUAGE plpgsql;" )
|
1123
|
-
@conn.send_query( "SELECT generate_series(0,999), NULL UNION ALL SELECT 1000, errfunc();" )
|
1124
|
-
@conn.set_single_row_mode
|
1125
|
-
|
1126
|
-
first_result = nil
|
1127
|
-
expect do
|
1128
|
-
loop do
|
1129
|
-
res = @conn.get_result or break
|
1130
|
-
res.check
|
1131
|
-
first_result ||= res
|
1132
|
-
end
|
1133
|
-
end.to raise_error(PG::Error)
|
1134
|
-
expect( first_result.kind_of?(PG::Result) ).to be_truthy
|
1135
|
-
expect( first_result.result_status ).to eq( PG::PGRES_SINGLE_TUPLE )
|
1136
|
-
end
|
1165
|
+
end.to raise_error(PG::Error)
|
1166
|
+
expect( first_result.kind_of?(PG::Result) ).to be_truthy
|
1167
|
+
expect( first_result.result_status ).to eq( PG::PGRES_SINGLE_TUPLE )
|
1137
1168
|
end
|
1169
|
+
|
1138
1170
|
end
|
1139
1171
|
|
1140
1172
|
context "multinationalization support", :ruby_19 do
|
@@ -1201,7 +1233,7 @@ describe PG::Connection do
|
|
1201
1233
|
expect( escaped ).to eq( "Möhre to".encode(Encoding::EUC_JP) )
|
1202
1234
|
end
|
1203
1235
|
|
1204
|
-
it "uses the client encoding for escaped literal"
|
1236
|
+
it "uses the client encoding for escaped literal" do
|
1205
1237
|
original = "Möhre to\0 escape".encode( "utf-16be" )
|
1206
1238
|
@conn.set_client_encoding( "euc_jp" )
|
1207
1239
|
escaped = @conn.escape_literal( original )
|
@@ -1209,7 +1241,7 @@ describe PG::Connection do
|
|
1209
1241
|
expect( escaped ).to eq( "'Möhre to'".encode(Encoding::EUC_JP) )
|
1210
1242
|
end
|
1211
1243
|
|
1212
|
-
it "uses the client encoding for escaped identifier"
|
1244
|
+
it "uses the client encoding for escaped identifier" do
|
1213
1245
|
original = "Möhre to\0 escape".encode( "utf-16le" )
|
1214
1246
|
@conn.set_client_encoding( "euc_jp" )
|
1215
1247
|
escaped = @conn.escape_identifier( original )
|
@@ -1240,6 +1272,12 @@ describe PG::Connection do
|
|
1240
1272
|
expect( escaped.encoding ).to eq( Encoding::ISO8859_1 )
|
1241
1273
|
expect( escaped.encode ).to eq( "\"Möhre to\"".encode(Encoding::ISO8859_1) )
|
1242
1274
|
end
|
1275
|
+
|
1276
|
+
it "raises appropriate error if set_client_encoding is called with invalid arguments" do
|
1277
|
+
expect { @conn.set_client_encoding( "invalid" ) }.to raise_error(PG::Error, /invalid value/)
|
1278
|
+
expect { @conn.set_client_encoding( :invalid ) }.to raise_error(TypeError)
|
1279
|
+
expect { @conn.set_client_encoding( nil ) }.to raise_error(TypeError)
|
1280
|
+
end
|
1243
1281
|
end
|
1244
1282
|
|
1245
1283
|
describe "respect and convert character encoding of input strings" do
|
@@ -1408,7 +1446,7 @@ describe PG::Connection do
|
|
1408
1446
|
conn.finish if conn
|
1409
1447
|
end
|
1410
1448
|
|
1411
|
-
it "handles clearing result in or after set_notice_receiver"
|
1449
|
+
it "handles clearing result in or after set_notice_receiver" do
|
1412
1450
|
r = nil
|
1413
1451
|
@conn.set_notice_receiver do |result|
|
1414
1452
|
r = result
|
@@ -1423,7 +1461,7 @@ describe PG::Connection do
|
|
1423
1461
|
@conn.set_notice_receiver
|
1424
1462
|
end
|
1425
1463
|
|
1426
|
-
it "receives properly encoded messages in the notice callbacks"
|
1464
|
+
it "receives properly encoded messages in the notice callbacks" do
|
1427
1465
|
[:receiver, :processor].each do |kind|
|
1428
1466
|
notices = []
|
1429
1467
|
@conn.internal_encoding = 'utf-8'
|
@@ -1451,7 +1489,7 @@ describe PG::Connection do
|
|
1451
1489
|
end
|
1452
1490
|
end
|
1453
1491
|
|
1454
|
-
it "receives properly encoded text from wait_for_notify"
|
1492
|
+
it "receives properly encoded text from wait_for_notify" do
|
1455
1493
|
@conn.internal_encoding = 'utf-8'
|
1456
1494
|
@conn.exec( 'ROLLBACK' )
|
1457
1495
|
@conn.exec( 'LISTEN "Möhre"' )
|
@@ -1468,7 +1506,7 @@ describe PG::Connection do
|
|
1468
1506
|
expect( msg.encoding ).to eq( Encoding::UTF_8 )
|
1469
1507
|
end
|
1470
1508
|
|
1471
|
-
it "returns properly encoded text from notifies"
|
1509
|
+
it "returns properly encoded text from notifies" do
|
1472
1510
|
@conn.internal_encoding = 'utf-8'
|
1473
1511
|
@conn.exec( 'ROLLBACK' )
|
1474
1512
|
@conn.exec( 'LISTEN "Möhre"' )
|
@@ -1524,9 +1562,14 @@ describe PG::Connection do
|
|
1524
1562
|
end
|
1525
1563
|
|
1526
1564
|
it "shouldn't type map params unless requested" do
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1565
|
+
if @conn.server_version < 100000
|
1566
|
+
expect{
|
1567
|
+
@conn.exec_params( "SELECT $1", [5] )
|
1568
|
+
}.to raise_error(PG::IndeterminateDatatype)
|
1569
|
+
else
|
1570
|
+
# PostgreSQL-10 maps to TEXT type (OID 25)
|
1571
|
+
expect( @conn.exec_params( "SELECT $1", [5] ).ftype(0)).to eq(25)
|
1572
|
+
end
|
1530
1573
|
end
|
1531
1574
|
|
1532
1575
|
it "should raise an error on invalid encoder to put_copy_data" do
|