pgsql 1.6 → 1.9.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5906425e386ca8404df02a1d14dec2ec92e730cabd03c8192f624112d537c3d2
4
- data.tar.gz: 5bc40a7923bc2076aef6cdd8a2af71b679f01bee63fed44bbc475bf8e3a12dbb
3
+ metadata.gz: d735e83feb39d55f95efc1a196d433800c523fd0e73538b2c6415edd098f405c
4
+ data.tar.gz: e8e6e0b0526a73de32bf227effe13337ef125ea9f69d05099401aae4455c4288
5
5
  SHA512:
6
- metadata.gz: a32d74928d3a5c2d04dd30d4453e11a346ce7f4bb24db40665d375776b6caa89dabed59fa87774ab52fdb1d09a9d37e3e8eca13118e04a35572c33c8e827856c
7
- data.tar.gz: c405985704ae2c8a1bb52d957965a9b6ad4811bec41fe9785b3c56dba79c463fe1569ab27426a5853bfb1c5dfea4b10ae85505f7944bf5f6cdb6a0595174b895
6
+ metadata.gz: bbccf68542f27fc341ed1b517109655d5dd96b9d8cb21ac94e9d874f54d40eec9b3f50652967bb592cf04da68804c1351e01598ab8e4f3487ecc50b706dee65a
7
+ data.tar.gz: 388001a630086ddb47acb19672291ebe1cbd95f0349038e97189ff676e246047c4ce055bc726d065a9aea399cfdf1ff8d1e62d293178ebc6b8c131b10e4b951a
data/lib/Rakefile CHANGED
@@ -17,7 +17,7 @@ DLs = {
17
17
  }
18
18
 
19
19
  DLs.each { |k,v|
20
- task k => v do |t|
20
+ file k => v do |t|
21
21
  l.cc t.name, t.prerequisites
22
22
  end
23
23
  }
data/lib/conn.c CHANGED
@@ -26,11 +26,11 @@ extern VALUE pgconn_mkstring( struct pgconn_data *ptr, const char *str);
26
26
  extern VALUE pgconn_mkstringn( struct pgconn_data *ptr, const char *str, int len);
27
27
  static VALUE pgconn_alloc( VALUE cls);
28
28
  static VALUE pgconn_s_connect( int argc, VALUE *argv, VALUE cls);
29
- static VALUE pgconn_s_parse( VALUE cls, VALUE str);
30
29
  static VALUE pgconn_init( int argc, VALUE *argv, VALUE self);
31
30
  static int set_connect_params( st_data_t key, st_data_t val, st_data_t args);
32
- static void connstr_to_hash( VALUE params, VALUE str);
33
- static void connstr_passwd( VALUE self, VALUE params);
31
+ static VALUE connstr_sym_dbname( void);
32
+ static VALUE connstr_sym_password( void);
33
+ static void connstr_passwd( VALUE self, VALUE orig_params, VALUE *params);
34
34
  static VALUE connstr_getparam( RB_BLOCK_CALL_FUNC_ARGLIST( yielded, params));
35
35
 
36
36
  static VALUE pgconn_close( VALUE self);
@@ -71,6 +71,10 @@ VALUE rb_cPgConn;
71
71
  static VALUE rb_ePgConnFailed;
72
72
  static VALUE rb_ePgConnInvalid;
73
73
 
74
+ static VALUE sym_dbname = Qundef;
75
+ static VALUE sym_password = Qundef;
76
+
77
+ static ID id_to_s;
74
78
 
75
79
 
76
80
  void
@@ -221,24 +225,6 @@ pgconn_s_connect( int argc, VALUE *argv, VALUE cls)
221
225
  rb_ensure( rb_yield, pgconn, pgconn_close, pgconn) : pgconn;
222
226
  }
223
227
 
224
- /*
225
- * call-seq:
226
- * Pg::Conn.parse( str) -> hash
227
- *
228
- * Parse a connection string and return a hash with keys <code>:dbname</code>,
229
- * <code>:user</code>, <code>:host</code>, etc.
230
- *
231
- */
232
- VALUE
233
- pgconn_s_parse( VALUE cls, VALUE str)
234
- {
235
- VALUE params;
236
-
237
- params = rb_hash_new();
238
- connstr_to_hash( params, str);
239
- return params;
240
- }
241
-
242
228
 
243
229
  /*
244
230
  * Document-method: Pg::Conn.new
@@ -252,23 +238,39 @@ pgconn_s_parse( VALUE cls, VALUE str)
252
238
  *
253
239
  * c = Pg::Conn.new :dbname => "movies", :host => "jupiter", ...
254
240
  *
255
- * The most common parameters may be given in a URL-like
256
- * connection string:
241
+ * If the +str+ argument is given but no further parameters,
242
+ * the PQconnectdb() (not PQconnectdbParams()) function will be called.
243
+ * If further arguments are present, the +str+ argument will be made into
244
+ * the "dbname" parameter, but without overwriting an existing one.
245
+ *
246
+ * The "dbname" parameter may be a +conninfo+ string as described in the
247
+ * PostgreSQL documentation:
257
248
  *
258
- * "user:password@host:port/dbname"
249
+ * c = Pg::Conn.new "postgresql://user:password@host:port/dbname"
250
+ * c = Pg::Conn.new "postgres://user:password@host:port/dbname"
251
+ * c = Pg::Conn.new "dbname=... host=... user=..."
259
252
  *
260
- * Any of these parts may be omitted. If there is no slash, the part after the
261
- * @ sign will be read as database name.
253
+ * The password may be specified as an extra parameter:
254
+ *
255
+ * c = Pg::Conn.new "postgresql://user@host/dbname", password: "verysecret"
262
256
  *
263
257
  * If the password is the empty string, and there is either an instance method
264
258
  * or a class method <code>password?</code>, that method will be asked. This
265
259
  * method may ask <code>yield :user</code> or <code>yield :dbname</code> and so
266
260
  * on to get the connection parameters.
267
261
  *
262
+ * class Pg::Conn
263
+ * def password?
264
+ * "tercesyrev".reverse
265
+ * end
266
+ * end
267
+ * c = Pg::Conn.new "postgresql://user@host/dbname", password: ""
268
+ *
268
269
  * See the PostgreSQL documentation for a full list:
269
270
  * [http://www.postgresql.org/docs/current/interactive/libpq-connect.html#LIBPQ-PQCONNECTDBPARAMS]
270
271
  *
271
272
  * On failure, a +Pg::Error+ exception will be raised.
273
+ *
272
274
  */
273
275
  VALUE
274
276
  pgconn_init( int argc, VALUE *argv, VALUE self)
@@ -280,32 +282,43 @@ pgconn_init( int argc, VALUE *argv, VALUE self)
280
282
  struct pgconn_data *c;
281
283
 
282
284
  if (rb_scan_args( argc, argv, "02", &str, &params) < 2)
283
- if (TYPE( str) != T_STRING) {
285
+ if (TYPE( str) == T_HASH) {
284
286
  params = str;
285
287
  str = Qnil;
286
288
  }
287
- if (NIL_P( params))
288
- params = rb_hash_new();
289
- else if (TYPE( params) != T_HASH)
290
- params = rb_convert_type( params, T_HASH, "Hash", "to_hash");
291
- else
292
- params = rb_obj_dup( params);
293
- if (!NIL_P( str))
294
- connstr_to_hash( params, str);
295
- connstr_passwd( self, params);
296
289
 
297
290
  Data_Get_Struct( self, struct pgconn_data, c);
298
291
 
299
- l = RHASH_SIZE( params) + 1;
300
- keywords = (const char **) ALLOCA_N( char *, l);
301
- values = (const char **) ALLOCA_N( char *, l);
302
- ptrs[ 0] = keywords;
303
- ptrs[ 1] = values;
304
- ptrs[ 2] = (const char **) c;
305
- st_foreach( RHASH_TBL( params), &set_connect_params, (st_data_t) ptrs);
306
- *(ptrs[ 0]) = *(ptrs[ 1]) = NULL;
307
-
308
- c->conn = PQconnectdbParams( keywords, values, 1);
292
+ if (NIL_P( params)) {
293
+ c->conn = PQconnectdb( RSTRING_PTR( rb_funcall( str, id_to_s, 0)));
294
+ } else {
295
+ int expand_dbname;
296
+ VALUE orig_params = params;
297
+
298
+ if (TYPE( params) != T_HASH)
299
+ params = rb_convert_type( params, T_HASH, "Hash", "to_hash");
300
+
301
+ if (!NIL_P( str) && NIL_P( rb_hash_aref( params, connstr_sym_dbname()))) {
302
+ if (params == orig_params)
303
+ params = rb_obj_dup( params);
304
+ rb_hash_aset( params, sym_dbname, str);
305
+ expand_dbname = 1;
306
+ } else
307
+ expand_dbname = 0;
308
+
309
+ connstr_passwd( self, orig_params, &params);
310
+
311
+ l = RHASH_SIZE( params) + 1;
312
+ keywords = (const char **) ALLOCA_N( char *, l);
313
+ values = (const char **) ALLOCA_N( char *, l);
314
+ ptrs[ 0] = keywords;
315
+ ptrs[ 1] = values;
316
+ ptrs[ 2] = (const char **) c;
317
+ st_foreach( RHASH_TBL( params), &set_connect_params, (st_data_t) ptrs);
318
+ *(ptrs[ 0]) = *(ptrs[ 1]) = NULL;
319
+
320
+ c->conn = PQconnectdbParams( keywords, values, expand_dbname);
321
+ }
309
322
  if (PQstatus( c->conn) == CONNECTION_BAD)
310
323
  rb_exc_raise( pgconnfailederror_new( c, params));
311
324
 
@@ -331,50 +344,29 @@ set_connect_params( st_data_t key, st_data_t val, st_data_t args)
331
344
  return ST_CONTINUE;
332
345
  }
333
346
 
334
- static const char re_connstr[] =
335
- "\\A"
336
- "(?:(.*?)(?::(.*))?@)?" /* user:passwd@ */
337
- "(?:(.*?)(?::(\\d+))?/)?(?:(.+))?" /* host:port/dbname */
338
- "\\z"
339
- ;
340
-
341
- #define KEY_USER "user"
342
- #define KEY_PASSWORD "password"
343
- #define KEY_HOST "host"
344
- #define KEY_PORT "port"
345
- #define KEY_DBNAME "dbname"
347
+ VALUE
348
+ connstr_sym_dbname( void)
349
+ {
350
+ if (sym_dbname == Qundef)
351
+ sym_dbname = ID2SYM( rb_intern( "dbname"));
352
+ return sym_dbname;
353
+ }
346
354
 
347
- void
348
- connstr_to_hash( VALUE params, VALUE str)
349
- {
350
- VALUE re, match, k, m;
351
-
352
- re = rb_reg_new( re_connstr, sizeof re_connstr - 1, 0);
353
- if (RTEST( rb_reg_match( re, str))) {
354
- match = rb_backref_get();
355
- #define ADD_TO_RES( key, n) \
356
- k = ID2SYM( rb_intern( key)); m = rb_reg_nth_match( n, match); \
357
- if (NIL_P( rb_hash_aref( params, k)) && !NIL_P(m)) \
358
- rb_hash_aset( params, k, m)
359
- ADD_TO_RES( KEY_USER, 1);
360
- ADD_TO_RES( KEY_PASSWORD, 2);
361
- ADD_TO_RES( KEY_HOST, 3);
362
- ADD_TO_RES( KEY_PORT, 4);
363
- ADD_TO_RES( KEY_DBNAME, 5);
364
- #undef ADD_TO_RES
365
- } else
366
- rb_raise( rb_eArgError, "Invalid connection: %s", RSTRING_PTR( str));
355
+ VALUE
356
+ connstr_sym_password( void)
357
+ {
358
+ if (sym_password == Qundef)
359
+ sym_password = ID2SYM( rb_intern( "password"));
360
+ return sym_password;
367
361
  }
368
362
 
363
+
369
364
  void
370
- connstr_passwd( VALUE self, VALUE params)
365
+ connstr_passwd( VALUE self, VALUE orig_params, VALUE *params)
371
366
  {
372
- static VALUE sym_password = Qundef;
373
367
  VALUE pw;
374
368
 
375
- if (sym_password == Qundef)
376
- sym_password = ID2SYM( rb_intern( KEY_PASSWORD));
377
- pw = rb_hash_aref( params, sym_password);
369
+ pw = rb_hash_aref( *params, connstr_sym_password());
378
370
  if (TYPE( pw) == T_STRING && RSTRING_LEN( pw) == 0) {
379
371
  static ID id_password_q = 0;
380
372
  VALUE pwobj;
@@ -386,10 +378,13 @@ connstr_passwd( VALUE self, VALUE params)
386
378
  pwobj = self;
387
379
  if (rb_respond_to( CLASS_OF( self), id_password_q))
388
380
  pwobj = CLASS_OF( self);
389
- if (pwobj != Qundef)
390
- rb_hash_aset( params, sym_password,
381
+ if (pwobj != Qundef) {
382
+ if (*params == orig_params)
383
+ *params = rb_obj_dup( *params);
384
+ rb_hash_aset( *params, sym_password,
391
385
  rb_block_call( pwobj, id_password_q, 0, NULL,
392
- &connstr_getparam, params));
386
+ &connstr_getparam, *params));
387
+ }
393
388
  }
394
389
  }
395
390
 
@@ -866,7 +861,6 @@ Init_pgsql_conn( void)
866
861
  rb_define_alloc_func( rb_cPgConn, pgconn_alloc);
867
862
  rb_define_singleton_method( rb_cPgConn, "connect", pgconn_s_connect, -1);
868
863
  rb_define_alias( rb_singleton_class( rb_cPgConn), "open", "connect");
869
- rb_define_singleton_method( rb_cPgConn, "parse", pgconn_s_parse, 1);
870
864
  rb_define_method( rb_cPgConn, "initialize", &pgconn_init, -1);
871
865
  rb_define_method( rb_cPgConn, "close", &pgconn_close, 0);
872
866
  rb_define_alias( rb_cPgConn, "finish", "close");
@@ -906,6 +900,8 @@ Init_pgsql_conn( void)
906
900
 
907
901
  rb_define_method( rb_cPgConn, "on_notice", &pgconn_on_notice, 0);
908
902
 
903
+ id_to_s = rb_intern( "to_s");
904
+
909
905
  Init_pgsql_conn_quote();
910
906
  Init_pgsql_conn_exec();
911
907
  }
data/lib/conn_exec.c CHANGED
@@ -8,6 +8,8 @@
8
8
  #include "conn_quote.h"
9
9
  #include "result.h"
10
10
 
11
+ #include <math.h>
12
+
11
13
 
12
14
  static void pg_raise_connexec( struct pgconn_data *c);
13
15
 
@@ -18,21 +20,24 @@ static void free_strings( char **strs, int len);
18
20
  static void pg_parse_parameters( int argc, VALUE *argv, VALUE *cmd, VALUE *par);
19
21
 
20
22
  static VALUE pgconn_exec( int argc, VALUE *argv, VALUE obj);
21
- static VALUE pgconn_send( int argc, VALUE *argv, VALUE obj);
22
- static VALUE pgconn_fetch( VALUE obj);
23
23
  static VALUE yield_or_return_result( VALUE res);
24
+ static VALUE pgconn_send( int argc, VALUE *argv, VALUE obj);
25
+ static VALUE pgconn_fetch( int argc, VALUE *argv, VALUE conn);
26
+ static void wait_for_pgsocket( PGconn *c, VALUE to);
24
27
  static VALUE clear_resultqueue( VALUE self);
28
+ static VALUE pgconn_fetch_rows( int argc, VALUE *argv, VALUE conn);
29
+ static VALUE fetch_result_each( RB_BLOCK_CALL_FUNC_ARGLIST( res, arg));
25
30
 
26
31
  static VALUE pgconn_query( int argc, VALUE *argv, VALUE self);
27
- static VALUE pgconn_select_one( int argc, VALUE *argv, VALUE self);
32
+ static VALUE pgconn_select_row( int argc, VALUE *argv, VALUE self);
28
33
  static VALUE pgconn_select_value( int argc, VALUE *argv, VALUE self);
29
34
  static VALUE pgconn_select_values( int argc, VALUE *argv, VALUE self);
30
35
  static VALUE pgconn_get_notify( VALUE self);
31
36
 
32
37
  static VALUE pgconn_transaction( int argc, VALUE *argv, VALUE self);
33
- static VALUE rollback_transaction( VALUE self, VALUE err);
38
+ static VALUE rollback_transaction( VALUE conn, VALUE err);
34
39
  static VALUE commit_transaction( VALUE self);
35
- static VALUE yield_transaction( VALUE self);
40
+ static VALUE yield_transaction( VALUE conn);
36
41
  static VALUE pgconn_subtransaction( int argc, VALUE *argv, VALUE self);
37
42
  static VALUE rollback_subtransaction( VALUE ary, VALUE err);
38
43
  static VALUE release_subtransaction( VALUE ary);
@@ -53,10 +58,12 @@ static VALUE backup_end( VALUE conn);
53
58
 
54
59
 
55
60
  static VALUE rb_ePgConnExec;
61
+ static VALUE rb_ePgConnTimeout;
56
62
  static VALUE rb_ePgConnTrans;
57
63
  static VALUE rb_ePgConnCopy;
58
64
 
59
65
  static ID id_to_a;
66
+ static ID id_fetch;
60
67
 
61
68
 
62
69
  void
@@ -72,8 +79,7 @@ pg_statement_exec( VALUE conn, VALUE cmd, VALUE par)
72
79
  struct pgconn_data *c;
73
80
  PGresult *result;
74
81
 
75
- Data_Get_Struct( conn, struct pgconn_data, c);
76
- pg_check_conninvalid( c);
82
+ c = get_pgconn( conn);
77
83
  if (NIL_P( par))
78
84
  result = PQexec( c->conn, pgconn_destring( c, cmd, NULL));
79
85
  else {
@@ -97,8 +103,7 @@ pg_statement_send( VALUE conn, VALUE cmd, VALUE par)
97
103
  struct pgconn_data *c;
98
104
  int res;
99
105
 
100
- Data_Get_Struct( conn, struct pgconn_data, c);
101
- pg_check_conninvalid( c);
106
+ c = get_pgconn( conn);
102
107
  if (NIL_P( par))
103
108
  res = PQsendQuery( c->conn, pgconn_destring( c, cmd, NULL));
104
109
  else {
@@ -112,6 +117,7 @@ pg_statement_send( VALUE conn, VALUE cmd, VALUE par)
112
117
  }
113
118
  if (res <= 0)
114
119
  pg_raise_connexec( c);
120
+ PQsetSingleRowMode( c->conn);
115
121
  }
116
122
 
117
123
  char **
@@ -123,7 +129,7 @@ params_to_strings( VALUE conn, VALUE params, int *len)
123
129
  char **values, **v;
124
130
  char *a;
125
131
 
126
- Data_Get_Struct( conn, struct pgconn_data, c);
132
+ c = get_pgconn( conn);
127
133
  ptr = RARRAY_PTR( params);
128
134
  *len = l = RARRAY_LEN( params);
129
135
  values = ALLOC_N( char *, l);
@@ -187,6 +193,13 @@ pgconn_exec( int argc, VALUE *argv, VALUE self)
187
193
  return yield_or_return_result( res);
188
194
  }
189
195
 
196
+ VALUE
197
+ yield_or_return_result( VALUE result)
198
+ {
199
+ return rb_block_given_p() ?
200
+ rb_ensure( rb_yield, result, pgresult_clear, result) : result;
201
+ }
202
+
190
203
 
191
204
  /*
192
205
  * call-seq:
@@ -195,18 +208,28 @@ pgconn_exec( int argc, VALUE *argv, VALUE self)
195
208
  * Sends an asynchronous SQL query request specified by +sql+ to the
196
209
  * PostgreSQL server.
197
210
  *
211
+ * This sets the query into single row mode. You have to call +Pg::Conn#fetch+
212
+ * what will yield one-row results. You may cancel the delivery by breaking
213
+ * the loop.
214
+ *
198
215
  * Use Pg::Conn#fetch to fetch the results after you waited for data.
199
216
  *
200
217
  * Pg::Conn.connect do |conn|
201
218
  * conn.send "SELECT pg_sleep(3), * FROM t;" do
202
- * ins = [ conn.socket]
203
- * loop do
204
- * r = IO.select ins, nil, nil, 0.5
205
- * break if r
206
- * puts Time.now
207
- * end
208
- * res = conn.fetch
209
- * res.each { |w| puts w.inspect }
219
+ * conn.fetch { |res|
220
+ * puts res.first.inspect
221
+ * break if (rand 3) < 1
222
+ * }
223
+ * end
224
+ * end
225
+ *
226
+ * Multiple select statements will be separated by an empty result.
227
+ *
228
+ * Pg::Conn.connect do |conn|
229
+ * conn.send "SELECT 33; SELECT 'foo';" do
230
+ * conn.fetch { |res|
231
+ * puts res.first.inspect
232
+ * }
210
233
  * end
211
234
  * end
212
235
  */
@@ -222,51 +245,140 @@ pgconn_send( int argc, VALUE *argv, VALUE self)
222
245
 
223
246
  /*
224
247
  * call-seq:
225
- * conn.fetch() -> result or nil
226
- * conn.fetch() { |result| ... } -> obj
248
+ * conn.fetch( timeout = nil) { |result| ... } -> obj
227
249
  *
228
250
  * Fetches the results of the previous Pg::Conn#send call.
229
251
  * See there for an example.
230
252
  *
231
- * The result will be +nil+ if there are no more results.
232
253
  */
233
254
  VALUE
234
- pgconn_fetch( VALUE self)
255
+ pgconn_fetch( int argc, VALUE *argv, VALUE conn)
235
256
  {
236
257
  struct pgconn_data *c;
237
258
  PGresult *result;
259
+ VALUE to;
260
+
261
+ rb_scan_args( argc, argv, "01", &to);
238
262
 
239
- Data_Get_Struct( self, struct pgconn_data, c);
240
- pg_check_conninvalid( c);
263
+ c = get_pgconn( conn);
264
+ wait_for_pgsocket( c->conn, to);
241
265
  if (PQconsumeInput( c->conn) == 0)
242
266
  pg_raise_connexec( c);
243
- if (PQisBusy( c->conn) > 0)
244
- return Qnil;
245
- result = PQgetResult( c->conn);
246
- return result == NULL ? Qnil :
247
- yield_or_return_result( pgresult_new( result, c, Qnil, Qnil));
267
+ if (PQisBusy( c->conn) == 0)
268
+ while ((result = PQgetResult( c->conn)) != NULL) {
269
+ VALUE res;
270
+
271
+ res = pgresult_new( result, c, Qnil, Qnil);
272
+ rb_ensure( rb_yield, res, pgresult_clear, res);
273
+ }
274
+ return Qnil;
248
275
  }
249
276
 
250
- VALUE
251
- yield_or_return_result( VALUE result)
252
- {
253
- return rb_block_given_p() ?
254
- rb_ensure( rb_yield, result, pgresult_clear, result) : result;
277
+ void
278
+ wait_for_pgsocket( PGconn *c, VALUE to)
279
+ {
280
+ int fd;
281
+ fd_set readset;
282
+ struct timeval tv, *ptv;
283
+
284
+ fd = PQsocket( c);
285
+
286
+ FD_ZERO(&readset);
287
+ FD_SET(fd, &readset);
288
+
289
+ ptv = NULL;
290
+ if (!NIL_P( to)) {
291
+ int type = TYPE( to);
292
+ if (type == T_FIXNUM) {
293
+ tv.tv_sec = FIX2LONG( to);
294
+ tv.tv_usec = 0;
295
+ } else {
296
+ double x;
297
+ switch (type) {
298
+ case T_FLOAT:
299
+ x = RFLOAT_VALUE( to);
300
+ break;
301
+ case T_BIGNUM:
302
+ x = rb_big2dbl( to);
303
+ break;
304
+ case T_RATIONAL:
305
+ x = rb_num2dbl( to);
306
+ break;
307
+ default:
308
+ x = RFLOAT_VALUE( rb_funcall( to, rb_intern( "to_f"), 0));
309
+ break;
310
+ }
311
+ tv.tv_sec = floor( x);
312
+ tv.tv_usec = round( (x-tv.tv_sec)*1000000);
313
+ }
314
+ ptv = &tv;
315
+ }
316
+
317
+ if (select( fd+1, &readset, NULL, NULL, ptv) < 0 || !FD_ISSET( fd, &readset))
318
+ rb_raise( rb_ePgConnTimeout, "Wait for data timed out.");
255
319
  }
256
320
 
257
321
  VALUE
258
- clear_resultqueue( VALUE self)
322
+ clear_resultqueue( VALUE conn)
259
323
  {
260
324
  struct pgconn_data *c;
261
325
  PGresult *result;
326
+ int cancelled;
262
327
 
263
- Data_Get_Struct( self, struct pgconn_data, c);
264
- while ((result = PQgetResult( c->conn)) != NULL)
328
+ c = get_pgconn( conn);
329
+ cancelled = 0;
330
+ while ((result = PQgetResult( c->conn)) != NULL) {
265
331
  PQclear( result);
332
+ if (!cancelled) {
333
+ char errbuf[ 256];
334
+ PGcancel *cancel;
335
+ int ret;
336
+
337
+ cancel = PQgetCancel( c->conn);
338
+ if (cancel == NULL)
339
+ rb_raise( rb_ePgConnTrans, "Could not get cancel object.");
340
+ ret = PQcancel( cancel, errbuf, sizeof errbuf);
341
+ PQfreeCancel( cancel);
342
+ if (ret == 0)
343
+ rb_raise( rb_ePgConnTrans, "Cancel of sent query failed: %s", errbuf);
344
+ cancelled = 1;
345
+ }
346
+ }
266
347
  return Qnil;
267
348
  }
268
349
 
269
350
 
351
+ /*
352
+ * call-seq:
353
+ * conn.fetch_rows( timeout = nil) { |row| ... } -> obj
354
+ *
355
+ * Fetches the results of the previous Pg::Conn#send call as an array.
356
+ *
357
+ * Multiple select statements will _not_ be separated by an empty array or
358
+ * something similar. Query twice or call +#fetch+ if you want to separate
359
+ * them.
360
+ *
361
+ * Pg::Conn.connect do |conn|
362
+ * conn.send "SELECT 33; SELECT 'foo';" do
363
+ * conn.fetch { |row|
364
+ * puts row.inspect
365
+ * }
366
+ * end
367
+ * end
368
+ */
369
+ VALUE
370
+ pgconn_fetch_rows( int argc, VALUE *argv, VALUE conn)
371
+ {
372
+ if (!id_fetch)
373
+ id_fetch = rb_intern( "fetch");
374
+ return rb_block_call( conn, id_fetch, argc, argv, fetch_result_each, Qnil);
375
+ }
376
+
377
+ VALUE
378
+ fetch_result_each( RB_BLOCK_CALL_FUNC_ARGLIST( res, arg))
379
+ {
380
+ return pgresult_each( res);
381
+ }
270
382
 
271
383
 
272
384
  /*
@@ -303,13 +415,13 @@ pgconn_query( int argc, VALUE *argv, VALUE self)
303
415
 
304
416
  /*
305
417
  * call-seq:
306
- * conn.select_one( query, *bind_values)
418
+ * conn.select_row( query, *bind_values)
307
419
  *
308
420
  * Return the first row of the query results.
309
421
  * Equivalent to <code>conn.query( query, *bind_values).first</code>.
310
422
  */
311
423
  VALUE
312
- pgconn_select_one( int argc, VALUE *argv, VALUE self)
424
+ pgconn_select_row( int argc, VALUE *argv, VALUE self)
313
425
  {
314
426
  VALUE cmd, par;
315
427
  VALUE res;
@@ -327,7 +439,7 @@ pgconn_select_one( int argc, VALUE *argv, VALUE self)
327
439
  * conn.select_value( query, *bind_values)
328
440
  *
329
441
  * Return the first value of the first row of the query results.
330
- * Equivalent to conn.query( query, *bind_values).first.first
442
+ * Equivalent to conn.query( query, *bind_values).first&.first
331
443
  */
332
444
  VALUE
333
445
  pgconn_select_value( int argc, VALUE *argv, VALUE self)
@@ -348,6 +460,7 @@ pgconn_select_value( int argc, VALUE *argv, VALUE self)
348
460
  * call-seq:
349
461
  * conn.select_values( query, *bind_values)
350
462
  *
463
+ * Return the all values over all rows as one array.
351
464
  * Equivalent to conn.query( query, *bind_values).flatten
352
465
  */
353
466
  VALUE
@@ -386,14 +499,14 @@ pgconn_select_values( int argc, VALUE *argv, VALUE self)
386
499
  * Returns a notifier. If there is no unprocessed notifier, it returns +nil+.
387
500
  */
388
501
  VALUE
389
- pgconn_get_notify( VALUE self)
502
+ pgconn_get_notify( VALUE conn)
390
503
  {
391
504
  struct pgconn_data *c;
392
505
  PGnotify *notify;
393
506
  VALUE rel, pid, ext;
394
507
  VALUE ret;
395
508
 
396
- Data_Get_Struct( self, struct pgconn_data, c);
509
+ c = get_pgconn( conn);
397
510
  if (PQconsumeInput( c->conn) == 0)
398
511
  pg_raise_connexec( c);
399
512
  notify = PQnotifies( c->conn);
@@ -422,7 +535,7 @@ pgconn_get_notify( VALUE self)
422
535
  *
423
536
  */
424
537
  VALUE
425
- pgconn_transaction( int argc, VALUE *argv, VALUE self)
538
+ pgconn_transaction( int argc, VALUE *argv, VALUE conn)
426
539
  {
427
540
  struct pgconn_data *c;
428
541
  VALUE ser, ro;
@@ -430,50 +543,50 @@ pgconn_transaction( int argc, VALUE *argv, VALUE self)
430
543
  int p;
431
544
 
432
545
  rb_scan_args( argc, argv, "02", &ser, &ro);
433
- cmd = rb_str_buf_new2( "begin");
546
+ cmd = rb_str_buf_new2( "BEGIN");
434
547
  p = 0;
435
548
  if (!NIL_P( ser)) {
436
- rb_str_buf_cat2( cmd, " isolation level ");
437
- rb_str_buf_cat2( cmd, RTEST(ser) ? "serializable" : "read committed");
549
+ rb_str_buf_cat2( cmd, " ISOLATION LEVEL ");
550
+ rb_str_buf_cat2( cmd, RTEST(ser) ? "SERIALIZABLE" : "READ COMMITTED");
438
551
  p++;
439
552
  }
440
553
  if (!NIL_P( ro)) {
441
554
  if (p) rb_str_buf_cat2( cmd, ",");
442
- rb_str_buf_cat2( cmd, " read ");
443
- rb_str_buf_cat2( cmd, (RTEST(ro) ? "only" : "write"));
555
+ rb_str_buf_cat2( cmd, " READ ");
556
+ rb_str_buf_cat2( cmd, (RTEST(ro) ? "ONLY" : "WRITE"));
444
557
  }
445
558
  rb_str_buf_cat2( cmd, ";");
446
559
 
447
- Data_Get_Struct( self, struct pgconn_data, c);
560
+ c = get_pgconn( conn);
448
561
  if (PQtransactionStatus( c->conn) > PQTRANS_IDLE)
449
562
  rb_raise( rb_ePgConnTrans,
450
563
  "Nested transaction block. Use Conn#subtransaction.");
451
- pgresult_clear( pg_statement_exec( self, cmd, Qnil));
452
- return rb_ensure( yield_transaction, self, commit_transaction, self);
564
+ pgresult_clear( pg_statement_exec( conn, cmd, Qnil));
565
+ return rb_ensure( yield_transaction, conn, commit_transaction, conn);
453
566
  }
454
567
 
455
568
  VALUE
456
- yield_transaction( VALUE self)
569
+ yield_transaction( VALUE conn)
457
570
  {
458
- return rb_rescue( rb_yield, self, rollback_transaction, self);
571
+ return rb_rescue( rb_yield, conn, rollback_transaction, conn);
459
572
  }
460
573
 
461
574
  VALUE
462
- rollback_transaction( VALUE self, VALUE err)
575
+ rollback_transaction( VALUE conn, VALUE err)
463
576
  {
464
- pgresult_clear( pg_statement_exec( self, rb_str_new2( "ROLLBACK;"), Qnil));
577
+ pgresult_clear( pg_statement_exec( conn, rb_str_new2( "ROLLBACK;"), Qnil));
465
578
  rb_exc_raise( err);
466
579
  return Qnil;
467
580
  }
468
581
 
469
582
  VALUE
470
- commit_transaction( VALUE self)
583
+ commit_transaction( VALUE conn)
471
584
  {
472
585
  struct pgconn_data *c;
473
586
 
474
- Data_Get_Struct( self, struct pgconn_data, c);
587
+ c = get_pgconn( conn);
475
588
  if (PQtransactionStatus( c->conn) > PQTRANS_IDLE)
476
- pgresult_clear( pg_statement_exec( self, rb_str_new2( "COMMIT;"), Qnil));
589
+ pgresult_clear( pg_statement_exec( conn, rb_str_new2( "COMMIT;"), Qnil));
477
590
  return Qnil;
478
591
  }
479
592
 
@@ -495,13 +608,13 @@ pgconn_subtransaction( int argc, VALUE *argv, VALUE self)
495
608
  char *p;
496
609
  int n;
497
610
 
498
- Data_Get_Struct( self, struct pgconn_data, c);
611
+ c = get_pgconn( self);
499
612
  a = rb_scan_args( argc, argv, "1*", &sp, &par);
500
613
  StringValue( sp);
501
614
  if (a > 1)
502
615
  sp = rb_str_format(RARRAY_LEN(par), RARRAY_PTR(par), sp);
503
616
 
504
- cmd = rb_str_buf_new2( "savepoint ");
617
+ cmd = rb_str_buf_new2( "SAVEPOINT ");
505
618
  q = pgconn_destring( c, sp, &n);
506
619
  p = PQescapeIdentifier( c->conn, q, n);
507
620
  rb_str_buf_cat2( cmd, p);
@@ -524,7 +637,7 @@ rollback_subtransaction( VALUE ary, VALUE err)
524
637
  {
525
638
  VALUE cmd;
526
639
 
527
- cmd = rb_str_buf_new2( "rollback to savepoint ");
640
+ cmd = rb_str_buf_new2( "ROLLBACK TO SAVEPOINT ");
528
641
  rb_str_buf_append( cmd, rb_ary_entry( ary, 1));
529
642
  rb_str_buf_cat2( cmd, ";");
530
643
  pgresult_clear( pg_statement_exec( rb_ary_entry( ary, 0), cmd, Qnil));
@@ -541,7 +654,7 @@ release_subtransaction( VALUE ary)
541
654
 
542
655
  n = rb_ary_entry( ary, 1);
543
656
  if (!NIL_P( n)) {
544
- cmd = rb_str_buf_new2( "release savepoint ");
657
+ cmd = rb_str_buf_new2( "RELEASE SAVEPOINT ");
545
658
  rb_str_buf_append( cmd, n);
546
659
  rb_str_buf_cat2( cmd, ";");
547
660
  pgresult_clear( pg_statement_exec( rb_ary_entry( ary, 0), cmd, Qnil));
@@ -569,7 +682,7 @@ pgconn_transaction_status( VALUE self)
569
682
  {
570
683
  struct pgconn_data *c;
571
684
 
572
- Data_Get_Struct( self, struct pgconn_data, c);
685
+ c = get_pgconn( self);
573
686
  return INT2FIX( PQtransactionStatus( c->conn));
574
687
  }
575
688
 
@@ -584,7 +697,7 @@ pgconn_transaction_status( VALUE self)
584
697
  *
585
698
  * conn.copy_stdin "COPY t FROM STDIN;" do
586
699
  * ary = ...
587
- * l = stringize_line ary
700
+ * l = conn.stringize_line ary
588
701
  * conn.put l
589
702
  * end
590
703
  *
@@ -609,7 +722,7 @@ put_end( VALUE self)
609
722
  int r;
610
723
  PGresult *res;
611
724
 
612
- Data_Get_Struct( self, struct pgconn_data, c);
725
+ c = get_pgconn( self);
613
726
  /*
614
727
  * I would like to hand over something like
615
728
  * RSTRING_PTR( rb_obj_as_string( rb_errinfo()))
@@ -669,7 +782,7 @@ pgconn_putline( VALUE self, VALUE arg)
669
782
  str = t;
670
783
  }
671
784
 
672
- Data_Get_Struct( self, struct pgconn_data, c);
785
+ c = get_pgconn( self);
673
786
  p = pgconn_destring( c, str, &l);
674
787
  r = PQputCopyData( c->conn, p, l);
675
788
  if (r < 0)
@@ -721,7 +834,7 @@ get_end( VALUE self)
721
834
  struct pgconn_data *c;
722
835
  PGresult *res;
723
836
 
724
- Data_Get_Struct( self, struct pgconn_data, c);
837
+ c = get_pgconn( self);
725
838
  if ((res = PQgetResult( c->conn)) != NULL)
726
839
  pgresult_new( res, c, Qnil, Qnil);
727
840
  return Qnil;
@@ -752,7 +865,7 @@ pgconn_getline( int argc, VALUE *argv, VALUE self)
752
865
 
753
866
  async = rb_scan_args( argc, argv, "01", &as) > 0 && !NIL_P( as) ? 1 : 0;
754
867
 
755
- Data_Get_Struct( self, struct pgconn_data, c);
868
+ c = get_pgconn( self);
756
869
  r = PQgetCopyData( c->conn, &b, async);
757
870
  if (r > 0) {
758
871
  VALUE ret;
@@ -786,7 +899,7 @@ pgconn_each_line( VALUE self)
786
899
  int r;
787
900
  VALUE s;
788
901
 
789
- Data_Get_Struct( self, struct pgconn_data, c);
902
+ c = get_pgconn( self);
790
903
  for (; (r = PQgetCopyData( c->conn, &b, 0)) > 0;) {
791
904
  s = pgconn_mkstringn( c, b, r);
792
905
  PQfreemem( b);
@@ -856,16 +969,18 @@ Init_pgsql_conn_exec( void)
856
969
  rb_cPgConn = rb_define_class_under( rb_mPg, "Conn", rb_cObject);
857
970
  #endif
858
971
 
859
- rb_ePgConnExec = rb_define_class_under( rb_cPgConn, "ExecError", rb_ePgError);
860
- rb_ePgConnTrans = rb_define_class_under( rb_cPgConn, "TransactionError", rb_ePgError);
861
- rb_ePgConnCopy = rb_define_class_under( rb_cPgConn, "CopyError", rb_ePgError);
972
+ rb_ePgConnExec = rb_define_class_under( rb_cPgConn, "ExecError", rb_ePgError);
973
+ rb_ePgConnTimeout = rb_define_class_under( rb_cPgConn, "Timeout", rb_ePgError);
974
+ rb_ePgConnTrans = rb_define_class_under( rb_cPgConn, "TransactionError", rb_ePgError);
975
+ rb_ePgConnCopy = rb_define_class_under( rb_cPgConn, "CopyError", rb_ePgError);
862
976
 
863
977
  rb_define_method( rb_cPgConn, "exec", &pgconn_exec, -1);
864
978
  rb_define_method( rb_cPgConn, "send", &pgconn_send, -1);
865
- rb_define_method( rb_cPgConn, "fetch", &pgconn_fetch, 0);
979
+ rb_define_method( rb_cPgConn, "fetch", &pgconn_fetch, -1);
980
+ rb_define_method( rb_cPgConn, "fetch_rows", &pgconn_fetch_rows, -1);
866
981
 
867
982
  rb_define_method( rb_cPgConn, "query", &pgconn_query, -1);
868
- rb_define_method( rb_cPgConn, "select_one", &pgconn_select_one, -1);
983
+ rb_define_method( rb_cPgConn, "select_row", &pgconn_select_row, -1);
869
984
  rb_define_method( rb_cPgConn, "select_value", &pgconn_select_value, -1);
870
985
  rb_define_method( rb_cPgConn, "select_values", &pgconn_select_values, -1);
871
986
  rb_define_method( rb_cPgConn, "get_notify", &pgconn_get_notify, 0);
@@ -895,6 +1010,7 @@ Init_pgsql_conn_exec( void)
895
1010
 
896
1011
  rb_define_method( rb_cPgConn, "backup", &pgconn_backup, 1);
897
1012
 
898
- id_to_a = 0;
1013
+ id_to_a = 0;
1014
+ id_fetch = 0;
899
1015
  }
900
1016
 
data/lib/conn_quote.c CHANGED
@@ -355,7 +355,7 @@ pgconn_for_copy( VALUE self, VALUE obj)
355
355
  rb_global_variable( &pg_escape_regex);
356
356
  }
357
357
  if (RTEST( rb_reg_match( pg_escape_regex, ret)))
358
- ret = rb_block_call( ret, id_gsub, 1, &pg_escape_regex, gsub_escape_i, Qnil);
358
+ ret = rb_block_call( ret, id_gsub, 1, &pg_escape_regex, &gsub_escape_i, Qnil);
359
359
  }
360
360
  return ret;
361
361
  }
@@ -472,7 +472,7 @@ gsub_escape_i( RB_BLOCK_CALL_FUNC_ARGLIST( c, arg))
472
472
  * This method is to prevent you from saying something like <code>"insert into
473
473
  * ... (E'#{conn.stringize obj}', ...);"</code>. It is more efficient to say
474
474
  *
475
- * conn.exec "insert into ... (#{conn.quote obj}, ...);"
475
+ * conn.exec "INSERT INTO ... (#{conn.quote obj}, ...);"
476
476
  *
477
477
  * Your self-defined classes will be checked whether they have a method named
478
478
  * +to_postgres+. If that doesn't exist the object will be converted by
@@ -517,25 +517,25 @@ VALUE pgconn_quote( VALUE self, VALUE obj)
517
517
  co = CLASS_OF( obj);
518
518
  if (co == rb_cTime) {
519
519
  res = rb_funcall( obj, id_iso8601, 0);
520
- type = "timestamptz";
520
+ type = "TIMESTAMPTZ";
521
521
  } else if (co == rb_cDate) {
522
522
  res = rb_obj_as_string( obj);
523
- type = "date";
523
+ type = "DATE";
524
524
  } else if (co == rb_cDateTime) {
525
525
  res = rb_obj_as_string( obj);
526
- type = "timestamptz";
526
+ type = "TIMESTAMPTZ";
527
527
  } else if (co == pg_monetary_class() &&
528
528
  rb_respond_to( obj, id_raw)) {
529
529
  res = rb_funcall( obj, id_raw, 0);
530
530
  StringValue( res);
531
- type = "money";
531
+ type = "MONEY";
532
532
  } else if (rb_respond_to( obj, id_to_postgres)) {
533
533
  res = rb_funcall( obj, id_to_postgres, 0);
534
534
  StringValue( res);
535
535
  type = NULL;
536
536
  } else {
537
537
  res = rb_obj_as_string( obj);
538
- type = "unknown";
538
+ type = "UNKNOWN";
539
539
  }
540
540
  res = quote_string( self, res);
541
541
  if (type != NULL) {
data/lib/module.c CHANGED
@@ -8,7 +8,7 @@
8
8
  #include "result.h"
9
9
 
10
10
 
11
- #define PGSQL_VERSION "1.6"
11
+ #define PGSQL_VERSION "1.9.1"
12
12
 
13
13
 
14
14
  VALUE rb_mPg;
data/lib/result.c CHANGED
@@ -241,6 +241,8 @@ pgresult_new( PGresult *result, struct pgconn_data *conn, VALUE cmd, VALUE par)
241
241
  case PGRES_TUPLES_OK:
242
242
  case PGRES_COPY_OUT:
243
243
  case PGRES_COPY_IN:
244
+ case PGRES_COPY_BOTH:
245
+ case PGRES_SINGLE_TUPLE:
244
246
  break;
245
247
  case PGRES_BAD_RESPONSE:
246
248
  case PGRES_NONFATAL_ERROR:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgsql
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.6'
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bertram Scharpf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-04 00:00:00.000000000 Z
11
+ date: 2021-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: autorake