pg 0.11.0pre229 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +5 -2
  3. data/ext/pg.c +9 -113
  4. data/lib/pg.rb +55 -0
  5. data/spec/pgconn_spec.rb +58 -7
  6. metadata +4 -8
  7. metadata.gz.sig +0 -0
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,4 +1,7 @@
1
- 229[master,tip]:228,222 b477174160c8 2011-03-30 06:13 -0700 ged
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[github/master]:214 c3f163bf1ecd 2011-01-22 22:11 -0800 ged
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/03/30 13:13:47 $
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, login, password) -> PGconn
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(argc, argv, self);
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(argc, argv, self);
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
+
@@ -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 "should connect successfully with connection string" do
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 "should connect using 7 arguments converted to strings" do
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 "should connect using hash" do
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 "should connect asynchronously" do
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 "should not leave stale server connections after finish" do
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 "should trace and untrace client-server communication" do
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 "should not read past the end of a large object" do
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: 1923832275
4
+ hash: 51
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 11
9
9
  - 0
10
- - pre
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-03-31 00:00:00 -07:00
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.6.2
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