pg 0.11.0pre229 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/ChangeLog +5 -2
- data/ext/pg.c +9 -113
- data/lib/pg.rb +55 -0
- data/spec/pgconn_spec.rb +58 -7
- metadata +4 -8
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
230[tip] 24aa7899c696 2011-04-18 16:51 -0700 ged
|
2
|
+
Move connection-parameter parsing into Ruby, and make option-handling more
|
3
|
+
|
4
|
+
229:228,222 b477174160c8 2011-03-30 06:13 -0700 ged
|
2
5
|
Automated merge with ssh://bitbucket.org/larskanis/ruby-pg
|
3
6
|
|
4
7
|
228 cc3a7476465c 2011-03-15 13:21 +0100 kanis
|
@@ -31,7 +34,7 @@
|
|
31
34
|
219 1c3a1ca9f0cd 2011-01-22 04:41 +0800 ghazel
|
32
35
|
for windows support, duplicate the sockets from libpq and create temporary CRT fds
|
33
36
|
|
34
|
-
218
|
37
|
+
218:214 c3f163bf1ecd 2011-01-22 22:11 -0800 ged
|
35
38
|
Pulling fixes for Windows from ghazel on Github
|
36
39
|
|
37
40
|
217 18f413081e0c 2011-02-10 16:19 -0800 ged
|
data/ext/pg.c
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
modified at: Wed Jan 20 16:41:51 1999
|
10
10
|
|
11
11
|
$Author: ged $
|
12
|
-
$Date: 2011/
|
12
|
+
$Date: 2011/04/18 23:51:05 $
|
13
13
|
************************************************/
|
14
14
|
|
15
15
|
#include "pg.h"
|
@@ -77,34 +77,6 @@ static PQnoticeReceiver default_notice_receiver = NULL;
|
|
77
77
|
static PQnoticeProcessor default_notice_processor = NULL;
|
78
78
|
|
79
79
|
|
80
|
-
/*
|
81
|
-
* Used to quote the values passed in a Hash to PGconn.init
|
82
|
-
* when building the connection string.
|
83
|
-
*/
|
84
|
-
static VALUE
|
85
|
-
pgconn_s_quote_connstr(VALUE string)
|
86
|
-
{
|
87
|
-
char *str,*ptr;
|
88
|
-
int i,j=0,len;
|
89
|
-
VALUE result;
|
90
|
-
|
91
|
-
Check_Type(string, T_STRING);
|
92
|
-
|
93
|
-
ptr = RSTRING_PTR(string);
|
94
|
-
len = RSTRING_LEN(string);
|
95
|
-
str = ALLOC_N(char, len * 2 + 2 + 1);
|
96
|
-
str[j++] = '\'';
|
97
|
-
for(i = 0; i < len; i++) {
|
98
|
-
if(ptr[i] == '\'' || ptr[i] == '\\')
|
99
|
-
str[j++] = '\\';
|
100
|
-
str[j++] = ptr[i];
|
101
|
-
}
|
102
|
-
str[j++] = '\'';
|
103
|
-
result = rb_str_new(str, j);
|
104
|
-
xfree(str);
|
105
|
-
return result;
|
106
|
-
}
|
107
|
-
|
108
80
|
static void
|
109
81
|
free_pgconn(PGconn *conn)
|
110
82
|
{
|
@@ -223,87 +195,6 @@ notice_processor_proxy(void *arg, const char *message)
|
|
223
195
|
return;
|
224
196
|
}
|
225
197
|
|
226
|
-
/*
|
227
|
-
* Appends key='val' to conninfo_rstr
|
228
|
-
*/
|
229
|
-
static void
|
230
|
-
build_key_value_string(VALUE conninfo_rstr, char *key, VALUE val)
|
231
|
-
{
|
232
|
-
if(val != Qnil) {
|
233
|
-
if(RSTRING_LEN(conninfo_rstr) > 0)
|
234
|
-
rb_str_cat2(conninfo_rstr, " ");
|
235
|
-
rb_str_cat2(conninfo_rstr, key);
|
236
|
-
rb_str_cat2(conninfo_rstr, "=");
|
237
|
-
rb_str_concat(conninfo_rstr,
|
238
|
-
pgconn_s_quote_connstr(rb_obj_as_string(val)));
|
239
|
-
}
|
240
|
-
return;
|
241
|
-
}
|
242
|
-
|
243
|
-
static VALUE
|
244
|
-
parse_connect_args(int argc, VALUE *argv, VALUE self)
|
245
|
-
{
|
246
|
-
VALUE args,arg;
|
247
|
-
VALUE conninfo_rstr = rb_str_new("",0);
|
248
|
-
char *host, *port, *opt, *tty, *dbname, *login, *pwd;
|
249
|
-
host = port = opt = tty = dbname = login = pwd = NULL;
|
250
|
-
|
251
|
-
rb_scan_args(argc, argv, "0*", &args);
|
252
|
-
if (RARRAY_LEN(args) == 1) {
|
253
|
-
arg = rb_ary_entry(args,0);
|
254
|
-
if(TYPE(arg) == T_HASH) {
|
255
|
-
build_key_value_string(conninfo_rstr, "host",
|
256
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("host"))));
|
257
|
-
build_key_value_string(conninfo_rstr, "hostaddr",
|
258
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("hostaddr"))));
|
259
|
-
build_key_value_string(conninfo_rstr, "port",
|
260
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("port"))));
|
261
|
-
build_key_value_string(conninfo_rstr, "dbname",
|
262
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("dbname"))));
|
263
|
-
build_key_value_string(conninfo_rstr, "user",
|
264
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("user"))));
|
265
|
-
build_key_value_string(conninfo_rstr, "password",
|
266
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("password"))));
|
267
|
-
build_key_value_string(conninfo_rstr, "connect_timeout",
|
268
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("connect_timeout"))));
|
269
|
-
build_key_value_string(conninfo_rstr, "options",
|
270
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("options"))));
|
271
|
-
build_key_value_string(conninfo_rstr, "tty",
|
272
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("tty"))));
|
273
|
-
build_key_value_string(conninfo_rstr, "sslmode",
|
274
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("sslmode"))));
|
275
|
-
build_key_value_string(conninfo_rstr, "krbsrvname",
|
276
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("krbsrvname"))));
|
277
|
-
build_key_value_string(conninfo_rstr, "gsslib",
|
278
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("gsslib"))));
|
279
|
-
build_key_value_string(conninfo_rstr, "service",
|
280
|
-
rb_hash_aref(arg, ID2SYM(rb_intern("service"))));
|
281
|
-
}
|
282
|
-
else if(TYPE(arg) == T_STRING) {
|
283
|
-
conninfo_rstr = arg;
|
284
|
-
}
|
285
|
-
else {
|
286
|
-
rb_raise(rb_eArgError,
|
287
|
-
"Expecting String or Hash as single argument");
|
288
|
-
}
|
289
|
-
}
|
290
|
-
else if (RARRAY_LEN(args) == 7) {
|
291
|
-
build_key_value_string(conninfo_rstr, "host", rb_ary_entry(args,0));
|
292
|
-
build_key_value_string(conninfo_rstr, "port", rb_ary_entry(args,1));
|
293
|
-
build_key_value_string(conninfo_rstr, "options", rb_ary_entry(args,2));
|
294
|
-
build_key_value_string(conninfo_rstr, "tty", rb_ary_entry(args,3));
|
295
|
-
build_key_value_string(conninfo_rstr, "dbname", rb_ary_entry(args,4));
|
296
|
-
build_key_value_string(conninfo_rstr, "user", rb_ary_entry(args,5));
|
297
|
-
build_key_value_string(conninfo_rstr, "password", rb_ary_entry(args,6));
|
298
|
-
}
|
299
|
-
else {
|
300
|
-
rb_raise( rb_eArgError,
|
301
|
-
"Expected connection info string, hash, or 7 separate arguments, got a %s.",
|
302
|
-
RSTRING_PTR(rb_obj_classname( args )) );
|
303
|
-
}
|
304
|
-
|
305
|
-
return conninfo_rstr;
|
306
|
-
}
|
307
198
|
|
308
199
|
/********************************************************************
|
309
200
|
*
|
@@ -351,9 +242,10 @@ pgconn_alloc(VALUE klass)
|
|
351
242
|
* Document-method: new
|
352
243
|
*
|
353
244
|
* call-seq:
|
245
|
+
* PGconn.new -> PGconn
|
354
246
|
* PGconn.new(connection_hash) -> PGconn
|
355
247
|
* PGconn.new(connection_string) -> PGconn
|
356
|
-
* PGconn.new(host, port, options, tty, dbname,
|
248
|
+
* PGconn.new(host, port, options, tty, dbname, user, password) -> PGconn
|
357
249
|
*
|
358
250
|
* Create a connection to the specified server.
|
359
251
|
*
|
@@ -386,6 +278,9 @@ pgconn_alloc(VALUE klass)
|
|
386
278
|
*
|
387
279
|
* Examples:
|
388
280
|
*
|
281
|
+
* # Connect using all defaults
|
282
|
+
* PGconn.connect
|
283
|
+
*
|
389
284
|
* # As a Hash
|
390
285
|
* PGconn.connect( :dbname => 'test', :port => 5432 )
|
391
286
|
*
|
@@ -411,7 +306,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
411
306
|
const char *encname;
|
412
307
|
#endif
|
413
308
|
|
414
|
-
conninfo = parse_connect_args
|
309
|
+
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
415
310
|
conn = PQconnectdb(StringValuePtr(conninfo));
|
416
311
|
|
417
312
|
if(conn == NULL)
|
@@ -473,7 +368,7 @@ pgconn_s_connect_start(int argc, VALUE *argv, VALUE self)
|
|
473
368
|
*/
|
474
369
|
rb_conn = pgconn_alloc(rb_cPGconn);
|
475
370
|
|
476
|
-
conninfo = parse_connect_args
|
371
|
+
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
477
372
|
conn = PQconnectStart(StringValuePtr(conninfo));
|
478
373
|
|
479
374
|
if(conn == NULL)
|
@@ -4109,6 +4004,7 @@ Init_pg_ext()
|
|
4109
4004
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4110
4005
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4111
4006
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4007
|
+
|
4112
4008
|
|
4113
4009
|
/****** PGconn CLASS CONSTANTS: Connection Status ******/
|
4114
4010
|
|
data/lib/pg.rb
CHANGED
@@ -14,3 +14,58 @@ rescue LoadError => err
|
|
14
14
|
|
15
15
|
end
|
16
16
|
|
17
|
+
### The PG connection class.
|
18
|
+
class PGconn
|
19
|
+
|
20
|
+
# The order the options are passed to the ::connect method.
|
21
|
+
CONNECT_ARGUMENT_ORDER = %w[host port options tty dbname user password]
|
22
|
+
|
23
|
+
|
24
|
+
### Quote the given +value+ for use in a connection-parameter string.
|
25
|
+
### @param [String] value the option value to be quoted.
|
26
|
+
### @return [String]
|
27
|
+
def self::quote_connstr( value )
|
28
|
+
return "'" + value.to_s.gsub( /[\\']/ ) {|m| '\\' + m } + "'"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
### Parse the connection +args+ into a connection-parameter string
|
33
|
+
### @param [Array<String>] args the connection parameters
|
34
|
+
### @return [String] a connection parameters string
|
35
|
+
def self::parse_connect_args( *args )
|
36
|
+
return '' if args.empty?
|
37
|
+
|
38
|
+
# This will be swapped soon for code that makes options like those required for
|
39
|
+
# PQconnectdbParams()/PQconnectStartParams(). For now, stick to an options string for
|
40
|
+
# PQconnectdb()/PQconnectStart().
|
41
|
+
connopts = []
|
42
|
+
|
43
|
+
# Handle an options hash first
|
44
|
+
if args.last.is_a?( Hash )
|
45
|
+
opthash = args.pop
|
46
|
+
opthash.each do |key, val|
|
47
|
+
connopts.push( "%s=%s" % [key, PGconn.quote_connstr(val)] )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Option string style
|
52
|
+
if args.length == 1 && args.first.to_s.index( '=' )
|
53
|
+
connopts.unshift( args.first )
|
54
|
+
|
55
|
+
# Append positional parameters
|
56
|
+
else
|
57
|
+
args.each_with_index do |val, i|
|
58
|
+
next unless val # Skip nil placeholders
|
59
|
+
|
60
|
+
key = CONNECT_ARGUMENT_ORDER[ i ] or
|
61
|
+
raise ArgumentError, "Extra positional parameter %d: %p" % [ i+1, val ]
|
62
|
+
connopts.push( "%s=%s" % [key, PGconn.quote_connstr(val.to_s)] )
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
return connopts.join(' ')
|
67
|
+
end
|
68
|
+
|
69
|
+
end # class PGconn
|
70
|
+
|
71
|
+
|
data/spec/pgconn_spec.rb
CHANGED
@@ -30,20 +30,64 @@ describe PGconn do
|
|
30
30
|
@conn.exec( 'BEGIN' )
|
31
31
|
end
|
32
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
|
33
77
|
|
34
|
-
it "
|
78
|
+
it "connects successfully with connection string" do
|
35
79
|
tmpconn = PGconn.connect(@conninfo)
|
36
80
|
tmpconn.status.should== PGconn::CONNECTION_OK
|
37
81
|
tmpconn.finish
|
38
82
|
end
|
39
83
|
|
40
|
-
it "
|
84
|
+
it "connects using 7 arguments converted to strings" do
|
41
85
|
tmpconn = PGconn.connect('localhost', @port, nil, nil, :test, nil, nil)
|
42
86
|
tmpconn.status.should== PGconn::CONNECTION_OK
|
43
87
|
tmpconn.finish
|
44
88
|
end
|
45
89
|
|
46
|
-
it "
|
90
|
+
it "connects using a hash of connection parameters" do
|
47
91
|
tmpconn = PGconn.connect(
|
48
92
|
:host => 'localhost',
|
49
93
|
:port => @port,
|
@@ -52,7 +96,14 @@ describe PGconn do
|
|
52
96
|
tmpconn.finish
|
53
97
|
end
|
54
98
|
|
55
|
-
it "
|
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
|
56
107
|
tmpconn = PGconn.connect_start(@conninfo)
|
57
108
|
socket = IO.for_fd(tmpconn.socket)
|
58
109
|
status = tmpconn.connect_poll
|
@@ -72,7 +123,7 @@ describe PGconn do
|
|
72
123
|
tmpconn.finish
|
73
124
|
end
|
74
125
|
|
75
|
-
it "
|
126
|
+
it "doesn't leave stale server connections after finish" do
|
76
127
|
PGconn.connect(@conninfo).finish
|
77
128
|
sleep 0.5
|
78
129
|
res = @conn.exec(%[SELECT COUNT(*) AS n FROM pg_stat_activity
|
@@ -112,7 +163,7 @@ describe PGconn do
|
|
112
163
|
}.gsub( /^\t{2}/, '' ).lstrip
|
113
164
|
|
114
165
|
unless RUBY_PLATFORM =~ /mswin|mingw/
|
115
|
-
it "
|
166
|
+
it "trace and untrace client-server communication" do
|
116
167
|
# be careful to explicitly close files so that the
|
117
168
|
# directory can be removed and we don't have to wait for
|
118
169
|
# the GC to run.
|
@@ -173,7 +224,7 @@ describe PGconn do
|
|
173
224
|
res.ntuples.should == 0
|
174
225
|
end
|
175
226
|
|
176
|
-
it "
|
227
|
+
it "not read past the end of a large object" do
|
177
228
|
@conn.transaction do
|
178
229
|
oid = @conn.lo_create( 0 )
|
179
230
|
fd = @conn.lo_open( oid, PGconn::INV_READ|PGconn::INV_WRITE )
|
metadata
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 11
|
9
9
|
- 0
|
10
|
-
|
11
|
-
- 229
|
12
|
-
version: 0.11.0pre229
|
10
|
+
version: 0.11.0
|
13
11
|
platform: ruby
|
14
12
|
authors:
|
15
13
|
- Jeff Davis
|
@@ -38,8 +36,7 @@ cert_chain:
|
|
38
36
|
cmlhXe46pZNJgWKbxZah85jIjx95hR8vOI+NAM5iH9kOqK13DrxacTKPhqj5PjwF
|
39
37
|
-----END CERTIFICATE-----
|
40
38
|
|
41
|
-
date: 2011-
|
42
|
-
default_executable:
|
39
|
+
date: 2011-04-19 00:00:00 Z
|
43
40
|
dependencies: []
|
44
41
|
|
45
42
|
description: |-
|
@@ -98,7 +95,6 @@ files:
|
|
98
95
|
- Rakefile.local
|
99
96
|
- spec/data/expected_trace.out
|
100
97
|
- spec/data/random_binary_data
|
101
|
-
has_rdoc: true
|
102
98
|
homepage: http://bitbucket.org/ged/ruby-pg/
|
103
99
|
licenses:
|
104
100
|
- Ruby
|
@@ -138,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
134
|
requirements:
|
139
135
|
- PostgreSQL >=7.4
|
140
136
|
rubyforge_project:
|
141
|
-
rubygems_version: 1.
|
137
|
+
rubygems_version: 1.7.2
|
142
138
|
signing_key:
|
143
139
|
specification_version: 3
|
144
140
|
summary: A Ruby interface to the PostgreSQL RDBMS
|
metadata.gz.sig
CHANGED
Binary file
|