pg 0.15.1-x64-mingw32 → 0.16.0-x64-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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +395 -1
- data/History.rdoc +30 -3
- data/Manifest.txt +4 -0
- data/Rakefile +30 -10
- data/ext/errorcodes.def +931 -0
- data/ext/errorcodes.rb +45 -0
- data/ext/errorcodes.txt +463 -0
- data/ext/extconf.rb +11 -5
- data/ext/gvl_wrappers.c +6 -0
- data/ext/gvl_wrappers.h +47 -21
- data/ext/pg.c +29 -9
- data/ext/pg.h +30 -0
- data/ext/pg_connection.c +104 -44
- data/ext/pg_errors.c +89 -0
- data/ext/pg_result.c +48 -67
- data/lib/2.0/pg_ext.so +0 -0
- data/lib/pg.rb +1 -1
- data/spec/lib/helpers.rb +11 -2
- data/spec/pg/connection_spec.rb +113 -8
- data/spec/pg/result_spec.rb +69 -2
- data/spec/pg_spec.rb +13 -0
- metadata +16 -56
- metadata.gz.sig +0 -0
data/ext/pg_errors.c
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
/*
|
2
|
+
* pg_errors.c - Definition and lookup of error classes.
|
3
|
+
*
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "pg.h"
|
7
|
+
|
8
|
+
VALUE rb_hErrors;
|
9
|
+
VALUE rb_ePGerror;
|
10
|
+
VALUE rb_eServerError;
|
11
|
+
VALUE rb_eUnableToSend;
|
12
|
+
VALUE rb_eConnectionBad;
|
13
|
+
|
14
|
+
static VALUE
|
15
|
+
define_error_class(const char *name, const char *baseclass_code)
|
16
|
+
{
|
17
|
+
VALUE baseclass = rb_eServerError;
|
18
|
+
if(baseclass_code)
|
19
|
+
{
|
20
|
+
baseclass = rb_hash_aref( rb_hErrors, rb_str_new2(baseclass_code) );
|
21
|
+
}
|
22
|
+
return rb_define_class_under( rb_mPG, name, baseclass );
|
23
|
+
}
|
24
|
+
|
25
|
+
static void
|
26
|
+
register_error_class(const char *code, VALUE klass)
|
27
|
+
{
|
28
|
+
rb_hash_aset( rb_hErrors, rb_str_new2(code), klass );
|
29
|
+
}
|
30
|
+
|
31
|
+
/* Find a proper error class for the given SQLSTATE string
|
32
|
+
*/
|
33
|
+
VALUE
|
34
|
+
lookup_error_class(const char *sqlstate)
|
35
|
+
{
|
36
|
+
VALUE klass;
|
37
|
+
|
38
|
+
if(sqlstate)
|
39
|
+
{
|
40
|
+
/* Find the proper error class by the 5-characters SQLSTATE. */
|
41
|
+
klass = rb_hash_aref( rb_hErrors, rb_str_new2(sqlstate) );
|
42
|
+
if(NIL_P(klass))
|
43
|
+
{
|
44
|
+
/* The given SQLSTATE couldn't be found. This might happen, if
|
45
|
+
* the server side uses a newer version than the client.
|
46
|
+
* Try to find a error class by using the 2-characters SQLSTATE.
|
47
|
+
*/
|
48
|
+
klass = rb_hash_aref( rb_hErrors, rb_str_new(sqlstate, 2) );
|
49
|
+
if(NIL_P(klass))
|
50
|
+
{
|
51
|
+
/* Also the 2-characters SQLSTATE is unknown.
|
52
|
+
* Use the generic server error instead.
|
53
|
+
*/
|
54
|
+
klass = rb_eServerError;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
else
|
59
|
+
{
|
60
|
+
/* Unable to retrieve the PG_DIAG_SQLSTATE.
|
61
|
+
* Use the generic error instead.
|
62
|
+
*/
|
63
|
+
klass = rb_eUnableToSend;
|
64
|
+
}
|
65
|
+
|
66
|
+
return klass;
|
67
|
+
}
|
68
|
+
|
69
|
+
void
|
70
|
+
init_pg_errors()
|
71
|
+
{
|
72
|
+
rb_hErrors = rb_hash_new();
|
73
|
+
rb_define_const( rb_mPG, "ERROR_CLASSES", rb_hErrors );
|
74
|
+
|
75
|
+
rb_ePGerror = rb_define_class_under( rb_mPG, "Error", rb_eStandardError );
|
76
|
+
|
77
|
+
/*************************
|
78
|
+
* PG::Error
|
79
|
+
*************************/
|
80
|
+
rb_define_alias( rb_ePGerror, "error", "message" );
|
81
|
+
rb_define_attr( rb_ePGerror, "connection", 1, 0 );
|
82
|
+
rb_define_attr( rb_ePGerror, "result", 1, 0 );
|
83
|
+
|
84
|
+
rb_eServerError = rb_define_class_under( rb_mPG, "ServerError", rb_ePGerror );
|
85
|
+
rb_eUnableToSend = rb_define_class_under( rb_mPG, "UnableToSend", rb_ePGerror );
|
86
|
+
rb_eConnectionBad = rb_define_class_under( rb_mPG, "ConnectionBad", rb_ePGerror );
|
87
|
+
|
88
|
+
#include "errorcodes.def"
|
89
|
+
}
|
data/ext/pg_result.c
CHANGED
@@ -44,13 +44,14 @@ pg_new_result(PGresult *result, VALUE rb_pgconn)
|
|
44
44
|
VALUE
|
45
45
|
pg_result_check( VALUE self )
|
46
46
|
{
|
47
|
-
VALUE error, exception;
|
47
|
+
VALUE error, exception, klass;
|
48
48
|
VALUE rb_pgconn = rb_iv_get( self, "@connection" );
|
49
49
|
PGconn *conn = pg_get_pgconn(rb_pgconn);
|
50
50
|
PGresult *result;
|
51
51
|
#ifdef M17N_SUPPORTED
|
52
52
|
rb_encoding *enc = pg_conn_enc_get( conn );
|
53
53
|
#endif
|
54
|
+
char * sqlstate;
|
54
55
|
|
55
56
|
Data_Get_Struct(self, PGresult, result);
|
56
57
|
|
@@ -87,9 +88,12 @@ pg_result_check( VALUE self )
|
|
87
88
|
#ifdef M17N_SUPPORTED
|
88
89
|
rb_enc_set_index( error, rb_enc_to_index(enc) );
|
89
90
|
#endif
|
90
|
-
|
91
|
+
|
92
|
+
sqlstate = PQresultErrorField( result, PG_DIAG_SQLSTATE );
|
93
|
+
klass = lookup_error_class( sqlstate );
|
94
|
+
exception = rb_exc_new3( klass, error );
|
91
95
|
rb_iv_set( exception, "@connection", rb_pgconn );
|
92
|
-
rb_iv_set( exception, "@result", self );
|
96
|
+
rb_iv_set( exception, "@result", result ? self : Qnil );
|
93
97
|
rb_exc_raise( exception );
|
94
98
|
|
95
99
|
/* Not reached */
|
@@ -245,18 +249,18 @@ pgresult_error_message(VALUE self)
|
|
245
249
|
* conn.exec( "SELECT * FROM nonexistant_table" )
|
246
250
|
* rescue PG::Error => err
|
247
251
|
* p [
|
248
|
-
* result.error_field( PG::Result::PG_DIAG_SEVERITY ),
|
249
|
-
* result.error_field( PG::Result::PG_DIAG_SQLSTATE ),
|
250
|
-
* result.error_field( PG::Result::PG_DIAG_MESSAGE_PRIMARY ),
|
251
|
-
* result.error_field( PG::Result::PG_DIAG_MESSAGE_DETAIL ),
|
252
|
-
* result.error_field( PG::Result::PG_DIAG_MESSAGE_HINT ),
|
253
|
-
* result.error_field( PG::Result::PG_DIAG_STATEMENT_POSITION ),
|
254
|
-
* result.error_field( PG::Result::PG_DIAG_INTERNAL_POSITION ),
|
255
|
-
* result.error_field( PG::Result::PG_DIAG_INTERNAL_QUERY ),
|
256
|
-
* result.error_field( PG::Result::PG_DIAG_CONTEXT ),
|
257
|
-
* result.error_field( PG::Result::PG_DIAG_SOURCE_FILE ),
|
258
|
-
* result.error_field( PG::Result::PG_DIAG_SOURCE_LINE ),
|
259
|
-
* result.error_field( PG::Result::PG_DIAG_SOURCE_FUNCTION ),
|
252
|
+
* err.result.error_field( PG::Result::PG_DIAG_SEVERITY ),
|
253
|
+
* err.result.error_field( PG::Result::PG_DIAG_SQLSTATE ),
|
254
|
+
* err.result.error_field( PG::Result::PG_DIAG_MESSAGE_PRIMARY ),
|
255
|
+
* err.result.error_field( PG::Result::PG_DIAG_MESSAGE_DETAIL ),
|
256
|
+
* err.result.error_field( PG::Result::PG_DIAG_MESSAGE_HINT ),
|
257
|
+
* err.result.error_field( PG::Result::PG_DIAG_STATEMENT_POSITION ),
|
258
|
+
* err.result.error_field( PG::Result::PG_DIAG_INTERNAL_POSITION ),
|
259
|
+
* err.result.error_field( PG::Result::PG_DIAG_INTERNAL_QUERY ),
|
260
|
+
* err.result.error_field( PG::Result::PG_DIAG_CONTEXT ),
|
261
|
+
* err.result.error_field( PG::Result::PG_DIAG_SOURCE_FILE ),
|
262
|
+
* err.result.error_field( PG::Result::PG_DIAG_SOURCE_LINE ),
|
263
|
+
* err.result.error_field( PG::Result::PG_DIAG_SOURCE_FUNCTION ),
|
260
264
|
* ]
|
261
265
|
* end
|
262
266
|
*
|
@@ -510,6 +514,31 @@ pgresult_fsize(VALUE self, VALUE index)
|
|
510
514
|
return INT2NUM(PQfsize(result, i));
|
511
515
|
}
|
512
516
|
|
517
|
+
|
518
|
+
static VALUE
|
519
|
+
pgresult_value(VALUE self, PGresult *result, int tuple_num, int field_num)
|
520
|
+
{
|
521
|
+
VALUE val;
|
522
|
+
if ( PQgetisnull(result, tuple_num, field_num) ) {
|
523
|
+
return Qnil;
|
524
|
+
}
|
525
|
+
else {
|
526
|
+
val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ),
|
527
|
+
PQgetlength(result, tuple_num, field_num) );
|
528
|
+
|
529
|
+
#ifdef M17N_SUPPORTED
|
530
|
+
/* associate client encoding for text format only */
|
531
|
+
if ( 0 == PQfformat(result, field_num) ) {
|
532
|
+
ASSOCIATE_INDEX( val, self );
|
533
|
+
} else {
|
534
|
+
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
535
|
+
}
|
536
|
+
#endif
|
537
|
+
|
538
|
+
return val;
|
539
|
+
}
|
540
|
+
}
|
541
|
+
|
513
542
|
/*
|
514
543
|
* call-seq:
|
515
544
|
* res.getvalue( tup_num, field_num )
|
@@ -520,7 +549,6 @@ pgresult_fsize(VALUE self, VALUE index)
|
|
520
549
|
static VALUE
|
521
550
|
pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
|
522
551
|
{
|
523
|
-
VALUE val;
|
524
552
|
PGresult *result;
|
525
553
|
int i = NUM2INT(tup_num);
|
526
554
|
int j = NUM2INT(field_num);
|
@@ -532,21 +560,7 @@ pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
|
|
532
560
|
if(j < 0 || j >= PQnfields(result)) {
|
533
561
|
rb_raise(rb_eArgError,"invalid field number %d", j);
|
534
562
|
}
|
535
|
-
|
536
|
-
return Qnil;
|
537
|
-
val = rb_tainted_str_new(PQgetvalue(result, i, j),
|
538
|
-
PQgetlength(result, i, j));
|
539
|
-
|
540
|
-
#ifdef M17N_SUPPORTED
|
541
|
-
/* associate client encoding for text format only */
|
542
|
-
if ( 0 == PQfformat(result, j) ) {
|
543
|
-
ASSOCIATE_INDEX( val, self );
|
544
|
-
} else {
|
545
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
546
|
-
}
|
547
|
-
#endif
|
548
|
-
|
549
|
-
return val;
|
563
|
+
return pgresult_value(self, result, i, j);
|
550
564
|
}
|
551
565
|
|
552
566
|
/*
|
@@ -696,7 +710,7 @@ pgresult_aref(VALUE self, VALUE index)
|
|
696
710
|
PGresult *result = pgresult_get(self);
|
697
711
|
int tuple_num = NUM2INT(index);
|
698
712
|
int field_num;
|
699
|
-
VALUE fname
|
713
|
+
VALUE fname;
|
700
714
|
VALUE tuple;
|
701
715
|
|
702
716
|
if ( tuple_num < 0 || tuple_num >= PQntuples(result) )
|
@@ -706,24 +720,7 @@ pgresult_aref(VALUE self, VALUE index)
|
|
706
720
|
for ( field_num = 0; field_num < PQnfields(result); field_num++ ) {
|
707
721
|
fname = rb_tainted_str_new2( PQfname(result,field_num) );
|
708
722
|
ASSOCIATE_INDEX(fname, self);
|
709
|
-
|
710
|
-
rb_hash_aset( tuple, fname, Qnil );
|
711
|
-
}
|
712
|
-
else {
|
713
|
-
val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ),
|
714
|
-
PQgetlength(result, tuple_num, field_num) );
|
715
|
-
|
716
|
-
#ifdef M17N_SUPPORTED
|
717
|
-
/* associate client encoding for text format only */
|
718
|
-
if ( 0 == PQfformat(result, field_num) ) {
|
719
|
-
ASSOCIATE_INDEX( val, self );
|
720
|
-
} else {
|
721
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
722
|
-
}
|
723
|
-
#endif
|
724
|
-
|
725
|
-
rb_hash_aset( tuple, fname, val );
|
726
|
-
}
|
723
|
+
rb_hash_aset( tuple, fname, pgresult_value(self, result, tuple_num, field_num) );
|
727
724
|
}
|
728
725
|
return tuple;
|
729
726
|
}
|
@@ -748,23 +745,7 @@ pgresult_each_row(VALUE self)
|
|
748
745
|
|
749
746
|
/* populate the row */
|
750
747
|
for ( field = 0; field < num_fields; field++ ) {
|
751
|
-
|
752
|
-
rb_ary_store( new_row, field, Qnil );
|
753
|
-
}
|
754
|
-
else {
|
755
|
-
VALUE val = rb_tainted_str_new( PQgetvalue(result, row, field),
|
756
|
-
PQgetlength(result, row, field) );
|
757
|
-
|
758
|
-
#ifdef M17N_SUPPORTED
|
759
|
-
/* associate client encoding for text format only */
|
760
|
-
if ( 0 == PQfformat(result, field) ) {
|
761
|
-
ASSOCIATE_INDEX( val, self );
|
762
|
-
} else {
|
763
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
764
|
-
}
|
765
|
-
#endif
|
766
|
-
rb_ary_store( new_row, field, val );
|
767
|
-
}
|
748
|
+
rb_ary_store( new_row, field, pgresult_value(self, result, row, field) );
|
768
749
|
}
|
769
750
|
rb_yield( new_row );
|
770
751
|
}
|
data/lib/2.0/pg_ext.so
CHANGED
Binary file
|
data/lib/pg.rb
CHANGED
data/spec/lib/helpers.rb
CHANGED
@@ -247,6 +247,13 @@ module PG::TestingHelpers
|
|
247
247
|
end
|
248
248
|
end
|
249
249
|
end
|
250
|
+
|
251
|
+
def connection_string_should_contain_application_name(conn_args, app_name)
|
252
|
+
conn_name = conn_args.match(/application_name='(.*)'/)[1]
|
253
|
+
conn_name.should include(app_name[0..10])
|
254
|
+
conn_name.should include(app_name[-10..-1])
|
255
|
+
conn_name.length.should <= 64
|
256
|
+
end
|
250
257
|
end
|
251
258
|
|
252
259
|
|
@@ -270,9 +277,11 @@ RSpec.configure do |config|
|
|
270
277
|
PG::Connection.instance_methods.map( &:to_sym ).include?( :escape_literal )
|
271
278
|
|
272
279
|
if !PG.respond_to?( :library_version )
|
273
|
-
config.filter_run_excluding( :postgresql_91, :postgresql_92 )
|
280
|
+
config.filter_run_excluding( :postgresql_91, :postgresql_92, :postgresql_93 )
|
274
281
|
elsif PG.library_version < 90200
|
275
|
-
config.filter_run_excluding( :postgresql_92 )
|
282
|
+
config.filter_run_excluding( :postgresql_92, :postgresql_93 )
|
283
|
+
elsif PG.library_version < 90300
|
284
|
+
config.filter_run_excluding( :postgresql_93 )
|
276
285
|
end
|
277
286
|
end
|
278
287
|
|
data/spec/pg/connection_spec.rb
CHANGED
@@ -177,6 +177,11 @@ describe PG::Connection do
|
|
177
177
|
conn.should be_finished()
|
178
178
|
end
|
179
179
|
|
180
|
+
it "raises proper error when sending fails" do
|
181
|
+
conn = described_class.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
|
182
|
+
expect{ conn.exec 'SELECT 1' }.to raise_error(PG::UnableToSend, /no connection/)
|
183
|
+
end
|
184
|
+
|
180
185
|
it "doesn't leave stale server connections after finish" do
|
181
186
|
described_class.connect(@conninfo).finish
|
182
187
|
sleep 0.5
|
@@ -257,6 +262,18 @@ describe PG::Connection do
|
|
257
262
|
error.should == true
|
258
263
|
end
|
259
264
|
|
265
|
+
it "can stop a thread that runs a blocking query" do
|
266
|
+
start = Time.now
|
267
|
+
t = Thread.new do
|
268
|
+
@conn.async_exec( 'select pg_sleep(10)' )
|
269
|
+
end
|
270
|
+
sleep 0.1
|
271
|
+
|
272
|
+
t.kill
|
273
|
+
t.join
|
274
|
+
(Time.now - start).should < 10
|
275
|
+
end
|
276
|
+
|
260
277
|
it "automatically rolls back a transaction started with Connection#transaction if an exception " +
|
261
278
|
"is raised" do
|
262
279
|
# abort the per-example transaction so we can test our own
|
@@ -276,6 +293,16 @@ describe PG::Connection do
|
|
276
293
|
res.ntuples.should == 0
|
277
294
|
end
|
278
295
|
|
296
|
+
it "returns the block result from Connection#transaction" do
|
297
|
+
# abort the per-example transaction so we can test our own
|
298
|
+
@conn.exec( 'ROLLBACK' )
|
299
|
+
|
300
|
+
res = @conn.transaction do
|
301
|
+
"transaction result"
|
302
|
+
end
|
303
|
+
res.should == "transaction result"
|
304
|
+
end
|
305
|
+
|
279
306
|
it "not read past the end of a large object" do
|
280
307
|
@conn.transaction do
|
281
308
|
oid = @conn.lo_create( 0 )
|
@@ -400,6 +427,21 @@ describe PG::Connection do
|
|
400
427
|
@conn.exec( 'UNLISTEN woo' )
|
401
428
|
end
|
402
429
|
|
430
|
+
it "can receive notices while waiting for NOTIFY without exceeding the timeout", :postgresql_90 do
|
431
|
+
notices = []
|
432
|
+
@conn.set_notice_processor do |msg|
|
433
|
+
notices << [msg, Time.now]
|
434
|
+
end
|
435
|
+
st = Time.now
|
436
|
+
@conn.send_query "SELECT pg_sleep(0.5); do $$ BEGIN RAISE NOTICE 'woohoo'; END; $$ LANGUAGE plpgsql;"
|
437
|
+
@conn.wait_for_notify( 1 ).should be_nil
|
438
|
+
notices.first.should_not be_nil
|
439
|
+
et = Time.now
|
440
|
+
(et - notices.first[1]).should >= 0.4
|
441
|
+
(et - st).should >= 0.9
|
442
|
+
(et - st).should < 1.4
|
443
|
+
end
|
444
|
+
|
403
445
|
it "yields the result if block is given to exec" do
|
404
446
|
rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
|
405
447
|
values = []
|
@@ -543,7 +585,7 @@ describe PG::Connection do
|
|
543
585
|
conn = PG.connect( @conninfo )
|
544
586
|
|
545
587
|
conn.finish
|
546
|
-
expect { conn.finish }.to raise_error( PG::
|
588
|
+
expect { conn.finish }.to raise_error( PG::ConnectionBad, /connection is closed/i )
|
547
589
|
end
|
548
590
|
|
549
591
|
it "closes the IO fetched from #socket_io when the connection is closed", :without_transaction, :socket_io do
|
@@ -551,7 +593,7 @@ describe PG::Connection do
|
|
551
593
|
io = conn.socket_io
|
552
594
|
conn.finish
|
553
595
|
io.should be_closed()
|
554
|
-
expect { conn.socket_io }.to raise_error( PG::
|
596
|
+
expect { conn.socket_io }.to raise_error( PG::ConnectionBad, /connection is closed/i )
|
555
597
|
end
|
556
598
|
|
557
599
|
it "closes the IO fetched from #socket_io when the connection is reset", :without_transaction, :socket_io do
|
@@ -563,6 +605,16 @@ describe PG::Connection do
|
|
563
605
|
conn.finish
|
564
606
|
end
|
565
607
|
|
608
|
+
it "block should raise ConnectionBad for a closed connection" do
|
609
|
+
serv = TCPServer.new( '127.0.0.1', 54320 )
|
610
|
+
conn = described_class.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
|
611
|
+
while [PG::CONNECTION_STARTED, PG::CONNECTION_MADE].include?(conn.connect_poll)
|
612
|
+
sleep 0.1
|
613
|
+
end
|
614
|
+
serv.close
|
615
|
+
expect{ conn.block }.to raise_error(PG::ConnectionBad, /server closed the connection unexpectedly/)
|
616
|
+
expect{ conn.block }.to raise_error(PG::ConnectionBad, /can't get socket descriptor/)
|
617
|
+
end
|
566
618
|
|
567
619
|
context "under PostgreSQL 9", :postgresql_90 do
|
568
620
|
|
@@ -571,14 +623,16 @@ describe PG::Connection do
|
|
571
623
|
end
|
572
624
|
|
573
625
|
it "sets the fallback_application_name on new connections" do
|
574
|
-
PG::Connection.parse_connect_args( 'dbname=test' )
|
626
|
+
conn_string = PG::Connection.parse_connect_args( 'dbname=test' )
|
627
|
+
connection_string_should_contain_application_name(conn_string, $0)
|
575
628
|
end
|
576
629
|
|
577
630
|
it "sets a shortened fallback_application_name on new connections" do
|
578
631
|
old_0 = $0
|
579
632
|
begin
|
580
633
|
$0 = "/this/is/a/very/long/path/with/many/directories/to/our/beloved/ruby"
|
581
|
-
PG::Connection.parse_connect_args( 'dbname=test' )
|
634
|
+
conn_string = PG::Connection.parse_connect_args( 'dbname=test' )
|
635
|
+
connection_string_should_contain_application_name(conn_string, $0)
|
582
636
|
ensure
|
583
637
|
$0 = old_0
|
584
638
|
end
|
@@ -874,17 +928,53 @@ describe PG::Connection do
|
|
874
928
|
end
|
875
929
|
|
876
930
|
it "uses the client encoding for escaped string" do
|
877
|
-
original = "string to escape".force_encoding( "
|
931
|
+
original = "string to\0 escape".force_encoding( "iso8859-1" )
|
878
932
|
@conn.set_client_encoding( "euc_jp" )
|
879
933
|
escaped = @conn.escape( original )
|
880
934
|
escaped.encoding.should == Encoding::EUC_JP
|
935
|
+
escaped.should == "string to"
|
881
936
|
end
|
882
937
|
|
883
|
-
it "
|
884
|
-
original = "string to\0 escape"
|
938
|
+
it "uses the client encoding for escaped literal", :postgresql_90 do
|
939
|
+
original = "string to\0 escape".force_encoding( "iso8859-1" )
|
940
|
+
@conn.set_client_encoding( "euc_jp" )
|
885
941
|
escaped = @conn.escape_literal( original )
|
942
|
+
escaped.encoding.should == Encoding::EUC_JP
|
886
943
|
escaped.should == "'string to'"
|
887
944
|
end
|
945
|
+
|
946
|
+
it "uses the client encoding for escaped identifier", :postgresql_90 do
|
947
|
+
original = "string to\0 escape".force_encoding( "iso8859-1" )
|
948
|
+
@conn.set_client_encoding( "euc_jp" )
|
949
|
+
escaped = @conn.escape_identifier( original )
|
950
|
+
escaped.encoding.should == Encoding::EUC_JP
|
951
|
+
escaped.should == "\"string to\""
|
952
|
+
end
|
953
|
+
|
954
|
+
it "uses the client encoding for quote_ident" do
|
955
|
+
original = "string to\0 escape".force_encoding( "iso8859-1" )
|
956
|
+
@conn.set_client_encoding( "euc_jp" )
|
957
|
+
escaped = @conn.quote_ident( original )
|
958
|
+
escaped.encoding.should == Encoding::EUC_JP
|
959
|
+
escaped.should == "\"string to\""
|
960
|
+
end
|
961
|
+
|
962
|
+
it "uses the previous string encoding for escaped string" do
|
963
|
+
original = "string to\0 escape".force_encoding( "iso8859-1" )
|
964
|
+
@conn.set_client_encoding( "euc_jp" )
|
965
|
+
escaped = described_class.escape( original )
|
966
|
+
escaped.encoding.should == Encoding::ISO8859_1
|
967
|
+
escaped.should == "string to"
|
968
|
+
end
|
969
|
+
|
970
|
+
it "uses the previous string encoding for quote_ident" do
|
971
|
+
original = "string to\0 escape".force_encoding( "iso8859-1" )
|
972
|
+
@conn.set_client_encoding( "euc_jp" )
|
973
|
+
escaped = described_class.quote_ident( original )
|
974
|
+
escaped.encoding.should == Encoding::ISO8859_1
|
975
|
+
escaped.should == "\"string to\""
|
976
|
+
end
|
977
|
+
|
888
978
|
end
|
889
979
|
|
890
980
|
|
@@ -1010,7 +1100,7 @@ describe PG::Connection do
|
|
1010
1100
|
end
|
1011
1101
|
|
1012
1102
|
context "OS thread support", :ruby_19 do
|
1013
|
-
it "
|
1103
|
+
it "Connection#exec shouldn't block a second thread" do
|
1014
1104
|
t = Thread.new do
|
1015
1105
|
@conn.exec( "select pg_sleep(1)" )
|
1016
1106
|
end
|
@@ -1019,5 +1109,20 @@ describe PG::Connection do
|
|
1019
1109
|
t.should be_alive()
|
1020
1110
|
t.join
|
1021
1111
|
end
|
1112
|
+
|
1113
|
+
it "Connection.new shouldn't block a second thread" do
|
1114
|
+
serv = nil
|
1115
|
+
t = Thread.new do
|
1116
|
+
serv = TCPServer.new( '127.0.0.1', 54320 )
|
1117
|
+
expect {
|
1118
|
+
described_class.new( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
|
1119
|
+
}.to raise_error(PG::ConnectionBad, /server closed the connection unexpectedly/)
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
sleep 0.5
|
1123
|
+
t.should be_alive()
|
1124
|
+
serv.close
|
1125
|
+
t.join
|
1126
|
+
end
|
1022
1127
|
end
|
1023
1128
|
end
|