pg 0.18.1 → 0.18.2
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 +169 -2
- data/History.rdoc +16 -0
- data/README.rdoc +1 -1
- data/ext/extconf.rb +4 -1
- data/ext/pg.c +3 -3
- data/ext/pg.h +10 -0
- data/ext/pg_connection.c +12 -40
- data/ext/pg_result.c +4 -4
- data/ext/pg_text_decoder.c +7 -10
- data/ext/pg_text_encoder.c +37 -40
- data/ext/pg_type_map_by_mri_type.c +2 -2
- data/ext/pg_type_map_in_ruby.c +4 -7
- data/ext/util.c +2 -2
- data/ext/util.h +1 -1
- data/lib/pg.rb +2 -2
- data/lib/pg/connection.rb +37 -27
- data/lib/pg/text_decoder.rb +2 -2
- data/spec/pg/connection_spec.rb +82 -6
- data/spec/pg/type_spec.rb +53 -30
- metadata +32 -32
- metadata.gz.sig +0 -0
data/ext/pg_text_encoder.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_text_encoder.c - PG::TextEncoder module
|
3
|
-
* $Id: pg_text_encoder.c,v
|
3
|
+
* $Id: pg_text_encoder.c,v b859963462b2 2015/03/13 17:39:35 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -299,7 +299,7 @@ quote_array_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
299
299
|
/* count data plus backslashes; detect chars needing quotes */
|
300
300
|
if (strlen == 0)
|
301
301
|
needquote = 1; /* force quotes for empty string */
|
302
|
-
else if (strlen == 4 &&
|
302
|
+
else if (strlen == 4 && rbpg_strncasecmp(p_in, "NULL", strlen) == 0)
|
303
303
|
needquote = 1; /* force quotes for literal NULL */
|
304
304
|
else
|
305
305
|
needquote = 0;
|
@@ -455,39 +455,34 @@ pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
|
455
455
|
}
|
456
456
|
}
|
457
457
|
|
458
|
-
static
|
459
|
-
|
458
|
+
static char *
|
459
|
+
quote_identifier( VALUE value, VALUE out_string, char *current_out ){
|
460
|
+
char *p_in = RSTRING_PTR(value);
|
460
461
|
char *ptr1;
|
461
|
-
|
462
|
-
|
462
|
+
size_t strlen = RSTRING_LEN(value);
|
463
|
+
char *end_capa = current_out;
|
463
464
|
|
464
|
-
|
465
|
+
PG_RB_STR_ENSURE_CAPA( out_string, strlen + 2, current_out, end_capa );
|
466
|
+
*current_out++ = '"';
|
465
467
|
for(ptr1 = p_in; ptr1 != p_in + strlen; ptr1++) {
|
466
|
-
|
467
|
-
|
468
|
+
char c = *ptr1;
|
469
|
+
if (c == '"'){
|
470
|
+
strlen++;
|
471
|
+
PG_RB_STR_ENSURE_CAPA( out_string, p_in - ptr1 + strlen + 1, current_out, end_capa );
|
472
|
+
*current_out++ = '"';
|
473
|
+
} else if (c == 0){
|
474
|
+
break;
|
468
475
|
}
|
476
|
+
*current_out++ = c;
|
469
477
|
}
|
478
|
+
PG_RB_STR_ENSURE_CAPA( out_string, 1, current_out, end_capa );
|
479
|
+
*current_out++ = '"';
|
470
480
|
|
471
|
-
|
472
|
-
ptr2 = p_out + strlen + backslashs + 2;
|
473
|
-
/* Write end quote */
|
474
|
-
*--ptr2 = '"';
|
475
|
-
|
476
|
-
/* Then store the escaped string on the final position, walking
|
477
|
-
* right to left, until all backslashs are placed. */
|
478
|
-
while( ptr1 != p_in ) {
|
479
|
-
*--ptr2 = *--ptr1;
|
480
|
-
if(*ptr2 == '"'){
|
481
|
-
*--ptr2 = '"';
|
482
|
-
}
|
483
|
-
}
|
484
|
-
/* Write start quote */
|
485
|
-
*p_out = '"';
|
486
|
-
return strlen + backslashs + 2;
|
481
|
+
return current_out;
|
487
482
|
}
|
488
483
|
|
489
484
|
static char *
|
490
|
-
pg_text_enc_array_identifier(
|
485
|
+
pg_text_enc_array_identifier(VALUE value, VALUE string, char *out)
|
491
486
|
{
|
492
487
|
int i;
|
493
488
|
int nr_elems;
|
@@ -498,7 +493,7 @@ pg_text_enc_array_identifier(t_pg_composite_coder *this, VALUE value, VALUE stri
|
|
498
493
|
for( i=0; i<nr_elems; i++){
|
499
494
|
VALUE entry = rb_ary_entry(value, i);
|
500
495
|
|
501
|
-
out =
|
496
|
+
out = quote_identifier(entry, string, out);
|
502
497
|
if( i < nr_elems-1 ){
|
503
498
|
out = pg_rb_str_ensure_capa( string, 1, out, NULL );
|
504
499
|
*out++ = '.';
|
@@ -508,27 +503,29 @@ pg_text_enc_array_identifier(t_pg_composite_coder *this, VALUE value, VALUE stri
|
|
508
503
|
}
|
509
504
|
|
510
505
|
/*
|
511
|
-
* Document-class: PG::TextEncoder::Identifier < PG::
|
506
|
+
* Document-class: PG::TextEncoder::Identifier < PG::SimpleEncoder
|
512
507
|
*
|
513
508
|
* This is the encoder class for PostgreSQL identifiers.
|
514
509
|
*
|
515
510
|
* An Array value can be used for "schema.table.column" type identifiers:
|
516
511
|
* PG::TextEncoder::Identifier.new.encode(['schema', 'table', 'column'])
|
517
|
-
* => "schema"."table"."column"
|
512
|
+
* => '"schema"."table"."column"'
|
518
513
|
*
|
514
|
+
* This encoder can also be used per PG::Connection#quote_ident .
|
519
515
|
*/
|
520
|
-
|
521
|
-
pg_text_enc_identifier(t_pg_coder *
|
516
|
+
int
|
517
|
+
pg_text_enc_identifier(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate)
|
522
518
|
{
|
523
|
-
|
524
|
-
|
525
|
-
*intermediate = rb_str_new(NULL, 0);
|
526
|
-
out = RSTRING_PTR(*intermediate);
|
527
|
-
|
519
|
+
UNUSED( this );
|
528
520
|
if( TYPE(value) == T_ARRAY){
|
529
|
-
|
521
|
+
*intermediate = rb_str_new(NULL, 0);
|
522
|
+
out = RSTRING_PTR(*intermediate);
|
523
|
+
out = pg_text_enc_array_identifier(value, *intermediate, out);
|
530
524
|
} else {
|
531
|
-
|
525
|
+
StringValue(value);
|
526
|
+
*intermediate = rb_str_new(NULL, RSTRING_LEN(value) + 2);
|
527
|
+
out = RSTRING_PTR(*intermediate);
|
528
|
+
out = quote_identifier(value, *intermediate, out);
|
532
529
|
}
|
533
530
|
rb_str_set_len( *intermediate, out - RSTRING_PTR(*intermediate) );
|
534
531
|
return -1;
|
@@ -651,11 +648,11 @@ init_pg_text_encoder()
|
|
651
648
|
pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
|
652
649
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
|
653
650
|
pg_define_coder( "Bytea", pg_text_enc_bytea, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
|
651
|
+
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Identifier", rb_cPG_SimpleEncoder ); */
|
652
|
+
pg_define_coder( "Identifier", pg_text_enc_identifier, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
|
654
653
|
|
655
654
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Array", rb_cPG_CompositeEncoder ); */
|
656
655
|
pg_define_coder( "Array", pg_text_enc_array, rb_cPG_CompositeEncoder, rb_mPG_TextEncoder );
|
657
|
-
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Identifier", rb_cPG_CompositeEncoder ); */
|
658
|
-
pg_define_coder( "Identifier", pg_text_enc_identifier, rb_cPG_CompositeEncoder, rb_mPG_TextEncoder );
|
659
656
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "QuotedLiteral", rb_cPG_CompositeEncoder ); */
|
660
657
|
pg_define_coder( "QuotedLiteral", pg_text_enc_quoted_literal, rb_cPG_CompositeEncoder, rb_mPG_TextEncoder );
|
661
658
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "ToBase64", rb_cPG_CompositeEncoder ); */
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_type_map_by_mri_type.c - PG::TypeMapByMriType class extension
|
3
|
-
* $Id: pg_type_map_by_mri_type.c,v
|
3
|
+
* $Id: pg_type_map_by_mri_type.c,v 1269b8ad77b8 2015/02/06 16:38:23 lars $
|
4
4
|
*
|
5
5
|
* This type map can be used to select value encoders based on the MRI-internal
|
6
6
|
* value type code.
|
@@ -39,7 +39,7 @@ static VALUE rb_cTypeMapByMriType;
|
|
39
39
|
typedef struct {
|
40
40
|
t_typemap typemap;
|
41
41
|
struct pg_tmbmt_converter {
|
42
|
-
FOR_EACH_MRI_TYPE( DECLARE_CODER )
|
42
|
+
FOR_EACH_MRI_TYPE( DECLARE_CODER )
|
43
43
|
} coders;
|
44
44
|
} t_tmbmt;
|
45
45
|
|
data/ext/pg_type_map_in_ruby.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_type_map_in_ruby.c - PG::TypeMapInRuby class extension
|
3
|
-
* $Id: pg_type_map_in_ruby.c,v
|
3
|
+
* $Id: pg_type_map_in_ruby.c,v 3d89d3aae4fd 2015/01/05 16:19:41 kanis $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -212,12 +212,9 @@ pg_tmir_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format
|
|
212
212
|
rb_encoding *p_encoding = rb_enc_from_index(enc_idx);
|
213
213
|
VALUE enc = rb_enc_from_encoding(p_encoding);
|
214
214
|
/* field_str is reused in-place by pg_text_dec_copy_row(), so we need to make
|
215
|
-
* a copy of the string buffer
|
216
|
-
|
217
|
-
|
218
|
-
VALUE field_str_copy = rb_str_new(RSTRING_PTR(field_str), RSTRING_LEN(field_str));
|
219
|
-
PG_ENCODING_SET_NOCHECK(field_str_copy, ENCODING_GET(field_str));
|
220
|
-
OBJ_INFECT(field_str_copy, field_str);
|
215
|
+
* a copy of the string buffer for use in ruby space. */
|
216
|
+
VALUE field_str_copy = rb_str_dup(field_str);
|
217
|
+
rb_str_modify(field_str_copy);
|
221
218
|
|
222
219
|
return rb_funcall( this->self, s_id_typecast_copy_get, 4, field_str_copy, INT2NUM(fieldno), INT2NUM(format), enc );
|
223
220
|
}
|
data/ext/util.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* util.c - Utils for ruby-pg
|
3
|
-
* $Id: util.c,v
|
3
|
+
* $Id: util.c,v b859963462b2 2015/03/13 17:39:35 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -124,7 +124,7 @@ base64_decode( char *out, char *in, unsigned int len)
|
|
124
124
|
* At most n bytes will be examined from each string.
|
125
125
|
*/
|
126
126
|
int
|
127
|
-
|
127
|
+
rbpg_strncasecmp(const char *s1, const char *s2, size_t n)
|
128
128
|
{
|
129
129
|
while (n-- > 0)
|
130
130
|
{
|
data/ext/util.h
CHANGED
@@ -60,6 +60,6 @@
|
|
60
60
|
void base64_encode( char *out, char *in, int len);
|
61
61
|
int base64_decode( char *out, char *in, unsigned int len);
|
62
62
|
|
63
|
-
int
|
63
|
+
int rbpg_strncasecmp(const char *s1, const char *s2, size_t n);
|
64
64
|
|
65
65
|
#endif /* end __utils_h */
|
data/lib/pg.rb
CHANGED
data/lib/pg/connection.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'pg' unless defined?( PG )
|
4
|
+
require 'uri'
|
4
5
|
|
5
6
|
# The PostgreSQL connection class. The interface for this class is based on
|
6
7
|
# {libpq}[http://www.postgresql.org/docs/9.2/interactive/libpq.html], the C
|
@@ -34,46 +35,55 @@ class PG::Connection
|
|
34
35
|
def self::parse_connect_args( *args )
|
35
36
|
return '' if args.empty?
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
hash_arg = args.last.is_a?( Hash ) ? args.pop : {}
|
39
|
+
option_string = ''
|
40
|
+
options = {}
|
40
41
|
|
41
42
|
# Parameter 'fallback_application_name' was introduced in PostgreSQL 9.0
|
42
43
|
# together with PQescapeLiteral().
|
43
|
-
if PG::Connection.instance_methods.find{|m| m.to_sym == :escape_literal }
|
44
|
-
|
45
|
-
appname = PG::Connection.quote_connstr( appname )
|
46
|
-
connopts = ["fallback_application_name=#{appname}"]
|
47
|
-
else
|
48
|
-
connopts = []
|
44
|
+
if PG::Connection.instance_methods.find {|m| m.to_sym == :escape_literal }
|
45
|
+
options[:fallback_application_name] = $0.sub( /^(.{30}).{4,}(.{30})$/ ){ $1+"..."+$2 }
|
49
46
|
end
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
if args.length == 1
|
49
|
+
case args.first
|
50
|
+
when URI, URI.regexp
|
51
|
+
uri = URI(args.first)
|
52
|
+
options.merge!( Hash[URI.decode_www_form( uri.query )] ) if uri.query
|
53
|
+
when /=/
|
54
|
+
# Option string style
|
55
|
+
option_string = args.first.to_s
|
56
|
+
else
|
57
|
+
# Positional parameters
|
58
|
+
options[CONNECT_ARGUMENT_ORDER.first.to_sym] = args.first
|
56
59
|
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Option string style
|
60
|
-
if args.length == 1 && args.first.to_s.index( '=' )
|
61
|
-
connopts.unshift( args.first )
|
62
|
-
|
63
|
-
# Append positional parameters
|
64
60
|
else
|
65
|
-
|
66
|
-
|
61
|
+
max = CONNECT_ARGUMENT_ORDER.length
|
62
|
+
raise ArgumentError,
|
63
|
+
"Extra positional parameter %d: %p" % [ max + 1, args[max] ] if args.length > max
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
connopts.push( "%s=%s" % [key, PG::Connection.quote_connstr(val.to_s)] )
|
65
|
+
CONNECT_ARGUMENT_ORDER.zip( args ) do |(k,v)|
|
66
|
+
options[ k.to_sym ] = v if v
|
71
67
|
end
|
72
68
|
end
|
73
69
|
|
74
|
-
|
70
|
+
options.merge!( hash_arg )
|
71
|
+
|
72
|
+
if uri
|
73
|
+
uri.host = nil if options[:host]
|
74
|
+
uri.port = nil if options[:port]
|
75
|
+
uri.user = nil if options[:user]
|
76
|
+
uri.password = nil if options[:password]
|
77
|
+
uri.path = '' if options[:dbname]
|
78
|
+
uri.query = URI.encode_www_form( options )
|
79
|
+
return uri.to_s.sub( /^#{uri.scheme}:(?!\/\/)/, "#{uri.scheme}://" )
|
80
|
+
else
|
81
|
+
option_string += ' ' unless option_string.empty? && options.empty?
|
82
|
+
return option_string + options.map { |k,v| "#{k}=#{quote_connstr(v)}" }.join( ' ' )
|
83
|
+
end
|
75
84
|
end
|
76
85
|
|
86
|
+
|
77
87
|
# call-seq:
|
78
88
|
# conn.copy_data( sql ) {|sql_result| ... } -> PG::Result
|
79
89
|
#
|
data/lib/pg/text_decoder.rb
CHANGED
@@ -27,11 +27,11 @@ module PG
|
|
27
27
|
end
|
28
28
|
|
29
29
|
class TimestampWithTimeZone < SimpleDecoder
|
30
|
-
ISO_DATETIME_WITH_TIMEZONE = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?([-\+]\d\d)\z/
|
30
|
+
ISO_DATETIME_WITH_TIMEZONE = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?([-\+]\d\d):?(\d\d)?:?(\d\d)?\z/
|
31
31
|
|
32
32
|
def decode(string, tuple=nil, field=nil)
|
33
33
|
if string =~ ISO_DATETIME_WITH_TIMEZONE
|
34
|
-
Time.new $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, "#{$6}#{$7}".to_r, "#{$8}
|
34
|
+
Time.new $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, "#{$6}#{$7}".to_r, "#{$8}:#{$9 || '00'}:#{$10 || '00'}"
|
35
35
|
else
|
36
36
|
string
|
37
37
|
end
|
data/spec/pg/connection_spec.rb
CHANGED
@@ -45,6 +45,14 @@ describe PG::Connection do
|
|
45
45
|
expect( optstring ).to match( /(^|\s)user='jrandom'/ )
|
46
46
|
end
|
47
47
|
|
48
|
+
it "can create a connection option string from an option string and a hash" do
|
49
|
+
optstring = described_class.parse_connect_args( 'dbname=original', :user => 'jrandom' )
|
50
|
+
|
51
|
+
expect( optstring ).to be_a( String )
|
52
|
+
expect( optstring ).to match( /(^|\s)dbname=original/ )
|
53
|
+
expect( optstring ).to match( /(^|\s)user='jrandom'/ )
|
54
|
+
end
|
55
|
+
|
48
56
|
it "escapes single quotes and backslashes in connection parameters" do
|
49
57
|
expect(
|
50
58
|
described_class.parse_connect_args( "DB 'browser' \\" )
|
@@ -52,18 +60,72 @@ describe PG::Connection do
|
|
52
60
|
|
53
61
|
end
|
54
62
|
|
63
|
+
let(:uri) { 'postgresql://user:pass@pgsql.example.com:222/db01?sslmode=require' }
|
64
|
+
|
65
|
+
it "can connect using a URI" do
|
66
|
+
string = described_class.parse_connect_args( uri )
|
67
|
+
|
68
|
+
expect( string ).to be_a( String )
|
69
|
+
expect( string ).to match( %r{^postgresql://user:pass@pgsql.example.com:222/db01\?} )
|
70
|
+
expect( string ).to match( %r{\?.*sslmode=require} )
|
71
|
+
|
72
|
+
string = described_class.parse_connect_args( URI.parse(uri) )
|
73
|
+
|
74
|
+
expect( string ).to be_a( String )
|
75
|
+
expect( string ).to match( %r{^postgresql://user:pass@pgsql.example.com:222/db01\?} )
|
76
|
+
expect( string ).to match( %r{\?.*sslmode=require} )
|
77
|
+
end
|
78
|
+
|
79
|
+
it "can create a connection URI from a URI and a hash" do
|
80
|
+
string = described_class.parse_connect_args( uri, :connect_timeout => 2 )
|
81
|
+
|
82
|
+
expect( string ).to be_a( String )
|
83
|
+
expect( string ).to match( %r{^postgresql://user:pass@pgsql.example.com:222/db01\?} )
|
84
|
+
expect( string ).to match( %r{\?.*sslmode=require} )
|
85
|
+
expect( string ).to match( %r{\?.*connect_timeout=2} )
|
86
|
+
|
87
|
+
string = described_class.parse_connect_args( uri,
|
88
|
+
:user => 'a',
|
89
|
+
:password => 'b',
|
90
|
+
:host => 'localhost',
|
91
|
+
:port => 555,
|
92
|
+
:dbname => 'x' )
|
93
|
+
|
94
|
+
expect( string ).to be_a( String )
|
95
|
+
expect( string ).to match( %r{^postgresql://\?} )
|
96
|
+
expect( string ).to match( %r{\?.*user=a} )
|
97
|
+
expect( string ).to match( %r{\?.*password=b} )
|
98
|
+
expect( string ).to match( %r{\?.*host=localhost} )
|
99
|
+
expect( string ).to match( %r{\?.*port=555} )
|
100
|
+
expect( string ).to match( %r{\?.*dbname=x} )
|
101
|
+
end
|
102
|
+
|
103
|
+
it "can create a connection URI with a non-standard domain socket directory" do
|
104
|
+
string = described_class.parse_connect_args( 'postgresql://%2Fvar%2Flib%2Fpostgresql/dbname' )
|
105
|
+
|
106
|
+
expect( string ).to be_a( String )
|
107
|
+
expect( string ).to match( %r{^postgresql://%2Fvar%2Flib%2Fpostgresql/dbname} )
|
108
|
+
|
109
|
+
string = described_class.
|
110
|
+
parse_connect_args( 'postgresql:///dbname', :host => '/var/lib/postgresql' )
|
111
|
+
|
112
|
+
expect( string ).to be_a( String )
|
113
|
+
expect( string ).to match( %r{^postgresql:///dbname\?} )
|
114
|
+
expect( string ).to match( %r{\?.*host=%2Fvar%2Flib%2Fpostgresql} )
|
115
|
+
end
|
116
|
+
|
55
117
|
it "connects with defaults if no connection parameters are given" do
|
56
118
|
expect( described_class.parse_connect_args ).to eq( '' )
|
57
119
|
end
|
58
120
|
|
59
121
|
it "connects successfully with connection string" do
|
60
|
-
tmpconn = described_class.connect(@conninfo)
|
122
|
+
tmpconn = described_class.connect( @conninfo )
|
61
123
|
expect( tmpconn.status ).to eq( PG::CONNECTION_OK )
|
62
124
|
tmpconn.finish
|
63
125
|
end
|
64
126
|
|
65
127
|
it "connects using 7 arguments converted to strings" do
|
66
|
-
tmpconn = described_class.connect('localhost', @port, nil, nil, :test, nil, nil)
|
128
|
+
tmpconn = described_class.connect( 'localhost', @port, nil, nil, :test, nil, nil )
|
67
129
|
expect( tmpconn.status ).to eq( PG::CONNECTION_OK )
|
68
130
|
tmpconn.finish
|
69
131
|
end
|
@@ -89,8 +151,13 @@ describe PG::Connection do
|
|
89
151
|
|
90
152
|
it "raises an exception when connecting with an invalid number of arguments" do
|
91
153
|
expect {
|
92
|
-
described_class.connect( 1, 2, 3, 4, 5, 6, 7, 'extra' )
|
93
|
-
}.to raise_error
|
154
|
+
described_class.connect( 1, 2, 3, 4, 5, 6, 7, 'the-extra-arg' )
|
155
|
+
}.to raise_error do |error|
|
156
|
+
expect( error ).to be_an( ArgumentError )
|
157
|
+
expect( error.message ).to match( /extra positional parameter/i )
|
158
|
+
expect( error.message ).to match( /8/ )
|
159
|
+
expect( error.message ).to match( /the-extra-arg/ )
|
160
|
+
end
|
94
161
|
end
|
95
162
|
|
96
163
|
it "can connect asynchronously", :socket_io do
|
@@ -162,8 +229,6 @@ describe PG::Connection do
|
|
162
229
|
expect( @conn.user ).to be_a_kind_of( String )
|
163
230
|
expect( @conn.pass ).to eq( "" )
|
164
231
|
expect( @conn.host ).to eq( "localhost" )
|
165
|
-
# TODO: Not sure why libpq returns a NULL ptr instead of "127.0.0.1"
|
166
|
-
expect( @conn.hostaddr ).to eq( nil ) if @conn.server_version >= 9_04_00
|
167
232
|
expect( @conn.port ).to eq( 54321 )
|
168
233
|
expect( @conn.tty ).to eq( "" )
|
169
234
|
expect( @conn.options ).to eq( "" )
|
@@ -1128,9 +1193,20 @@ describe PG::Connection do
|
|
1128
1193
|
expect( escaped.encoding ).to eq( Encoding::ISO8859_1 )
|
1129
1194
|
expect( escaped ).to eq( "\"string to\"" )
|
1130
1195
|
end
|
1196
|
+
end
|
1131
1197
|
|
1198
|
+
it "can quote bigger strings with quote_ident" do
|
1199
|
+
original = "'01234567\"" * 100
|
1200
|
+
escaped = described_class.quote_ident( original + "\0afterzero" )
|
1201
|
+
expect( escaped ).to eq( "\"" + original.gsub("\"", "\"\"") + "\"" )
|
1132
1202
|
end
|
1133
1203
|
|
1204
|
+
it "can quote Arrays with quote_ident" do
|
1205
|
+
original = "'01234567\""
|
1206
|
+
escaped = described_class.quote_ident( [original]*3 )
|
1207
|
+
expected = ["\"" + original.gsub("\"", "\"\"") + "\""] * 3
|
1208
|
+
expect( escaped ).to eq( expected.join(".") )
|
1209
|
+
end
|
1134
1210
|
|
1135
1211
|
describe "Ruby 1.9.x default_internal encoding" do
|
1136
1212
|
|