pgsql 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/conn.h ADDED
@@ -0,0 +1,42 @@
1
+ /*
2
+ * conn.h -- PostgreSQL connection
3
+ */
4
+
5
+ #ifndef __CONN_H
6
+ #define __CONN_H
7
+
8
+ #include "module.h"
9
+
10
+
11
+ #ifdef HAVE_FUNC_RB_LOCALE_ENCODING
12
+ #define RUBY_ENCODING
13
+ #endif
14
+
15
+
16
+ struct pgconn_data {
17
+ PGconn *conn;
18
+ #ifdef RUBY_ENCODING
19
+ VALUE external;
20
+ VALUE internal;
21
+ #endif
22
+ VALUE notice;
23
+ };
24
+
25
+
26
+ extern VALUE rb_cPgConn;
27
+
28
+
29
+ extern void pg_check_conninvalid( struct pgconn_data *c);
30
+
31
+
32
+ extern struct pgconn_data *get_pgconn( VALUE obj);
33
+
34
+ extern const char *pgconn_destring( struct pgconn_data *ptr, VALUE str, int *len);
35
+ extern VALUE pgconn_mkstring( struct pgconn_data *ptr, const char *str);
36
+ extern VALUE pgconn_mkstringn( struct pgconn_data *ptr, const char *str, int len);
37
+
38
+ extern void Init_pgsql_conn( void);
39
+
40
+
41
+ #endif
42
+
data/lib/conn_exec.c ADDED
@@ -0,0 +1,869 @@
1
+ /*
2
+ * conn_exec.c -- PostgreSQL connection, command execution
3
+ */
4
+
5
+
6
+ #include "conn_exec.h"
7
+
8
+ #include "conn_quote.h"
9
+ #include "result.h"
10
+
11
+
12
+ #ifdef HAVE_FUNC_RB_ERRINFO
13
+ #define RB_ERRINFO (rb_errinfo())
14
+ #else
15
+ #define RB_ERRINFO ruby_errinfo
16
+ #endif
17
+
18
+
19
+ static void pg_raise_connexec( struct pgconn_data *c);
20
+
21
+ static VALUE pg_statement_exec( VALUE conn, VALUE cmd, VALUE par);
22
+ static void pg_statement_send( VALUE conn, VALUE cmd, VALUE par);
23
+ static char **params_to_strings( VALUE conn, VALUE params, int *len);
24
+ static void free_strings( char **strs, int len);
25
+ static void pg_parse_parameters( int argc, VALUE *argv, VALUE *cmd, VALUE *par);
26
+
27
+ static VALUE pgconn_exec( int argc, VALUE *argv, VALUE obj);
28
+ static VALUE pgconn_send( int argc, VALUE *argv, VALUE obj);
29
+ static VALUE pgconn_fetch( VALUE obj);
30
+ static VALUE yield_or_return_result( VALUE res);
31
+ static VALUE clear_resultqueue( VALUE self);
32
+
33
+ static VALUE pgconn_query( int argc, VALUE *argv, VALUE self);
34
+ static VALUE pgconn_select_one( int argc, VALUE *argv, VALUE self);
35
+ static VALUE pgconn_select_value( int argc, VALUE *argv, VALUE self);
36
+ static VALUE pgconn_select_values( int argc, VALUE *argv, VALUE self);
37
+ static VALUE pgconn_get_notify( VALUE self);
38
+
39
+ static VALUE pgconn_transaction( int argc, VALUE *argv, VALUE self);
40
+ static VALUE rescue_transaction( VALUE self);
41
+ static VALUE yield_transaction( VALUE self);
42
+ static VALUE pgconn_subtransaction( int argc, VALUE *argv, VALUE self);
43
+ static VALUE rescue_subtransaction( VALUE ary);
44
+ static VALUE yield_subtransaction( VALUE ary);
45
+ static VALUE pgconn_transaction_status( VALUE self);
46
+
47
+
48
+ static VALUE pgconn_copy_stdin( int argc, VALUE *argv, VALUE self);
49
+ static VALUE put_end( VALUE conn);
50
+ static VALUE pgconn_putline( VALUE self, VALUE str);
51
+ static VALUE pgconn_copy_stdout( int argc, VALUE *argv, VALUE self);
52
+ static VALUE get_end( VALUE conn);
53
+ static VALUE pgconn_getline( int argc, VALUE *argv, VALUE self);
54
+ static VALUE pgconn_each_line( VALUE self);
55
+
56
+
57
+
58
+ static VALUE rb_ePgConnExec;
59
+ static VALUE rb_ePgConnTrans;
60
+ static VALUE rb_ePgConnCopy;
61
+
62
+ static ID id_to_a;
63
+
64
+
65
+ void
66
+ pg_raise_connexec( struct pgconn_data *c)
67
+ {
68
+ rb_raise( rb_ePgConnExec, PQerrorMessage( c->conn));
69
+ }
70
+
71
+
72
+ VALUE
73
+ pg_statement_exec( VALUE conn, VALUE cmd, VALUE par)
74
+ {
75
+ struct pgconn_data *c;
76
+ PGresult *result;
77
+
78
+ Data_Get_Struct( conn, struct pgconn_data, c);
79
+ pg_check_conninvalid( c);
80
+ if (NIL_P( par))
81
+ result = PQexec( c->conn, pgconn_destring( c, cmd, NULL));
82
+ else {
83
+ char **v;
84
+ int len;
85
+
86
+ v = params_to_strings( conn, par, &len);
87
+ result = PQexecParams( c->conn, pgconn_destring( c, cmd, NULL), len,
88
+ NULL, (const char **) v, NULL, NULL, 0);
89
+ free_strings( v, len);
90
+ }
91
+ if (result == NULL)
92
+ pg_raise_connexec( c);
93
+ return pgresult_new( result, c, cmd, par);
94
+ }
95
+
96
+
97
+ void
98
+ pg_statement_send( VALUE conn, VALUE cmd, VALUE par)
99
+ {
100
+ struct pgconn_data *c;
101
+ int res;
102
+
103
+ Data_Get_Struct( conn, struct pgconn_data, c);
104
+ pg_check_conninvalid( c);
105
+ if (NIL_P( par))
106
+ res = PQsendQuery( c->conn, pgconn_destring( c, cmd, NULL));
107
+ else {
108
+ char **v;
109
+ int len;
110
+
111
+ v = params_to_strings( conn, par, &len);
112
+ res = PQsendQueryParams( c->conn, pgconn_destring( c, cmd, NULL), len,
113
+ NULL, (const char **) v, NULL, NULL, 0);
114
+ free_strings( v, len);
115
+ }
116
+ if (res <= 0)
117
+ pg_raise_connexec( c);
118
+ }
119
+
120
+ char **
121
+ params_to_strings( VALUE conn, VALUE params, int *len)
122
+ {
123
+ struct pgconn_data *c;
124
+ VALUE *ptr;
125
+ int l;
126
+ char **values, **v;
127
+ char *a;
128
+
129
+ Data_Get_Struct( conn, struct pgconn_data, c);
130
+ ptr = RARRAY_PTR( params);
131
+ *len = l = RARRAY_LEN( params);
132
+ values = ALLOC_N( char *, l);
133
+ for (v = values; l; v++, ptr++, l--)
134
+ if (NIL_P( *ptr))
135
+ *v = NULL;
136
+ else {
137
+ const char *q;
138
+ char *p;
139
+ int n;
140
+
141
+ q = pgconn_destring( c, pgconn_stringize( conn, *ptr), &n);
142
+ a = ALLOC_N( char, n + 1);
143
+ for (p = a; *p = n ? *q : '\0'; ++p, ++q, --n)
144
+ ;
145
+ *v = a;
146
+ }
147
+ return values;
148
+ }
149
+
150
+ void
151
+ free_strings( char **strs, int len)
152
+ {
153
+ char **p;
154
+ int l;
155
+
156
+ for (p = strs, l = len; l; --l, ++p)
157
+ xfree( *p);
158
+ xfree( strs);
159
+ }
160
+
161
+
162
+ void
163
+ pg_parse_parameters( int argc, VALUE *argv, VALUE *cmd, VALUE *par)
164
+ {
165
+ int len;
166
+
167
+ rb_scan_args( argc, argv, "1*", cmd, par);
168
+ StringValue( *cmd);
169
+ if (RARRAY_LEN( *par) <= 0)
170
+ *par = Qnil;
171
+ }
172
+
173
+
174
+ /*
175
+ * call-seq:
176
+ * conn.exec( sql, *bind_values) -> result
177
+ *
178
+ * Sends SQL query request specified by +sql+ to the PostgreSQL.
179
+ * Returns a Pg::Result instance.
180
+ *
181
+ * +bind_values+ represents values for the PostgreSQL bind parameters found in
182
+ * the +sql+. PostgreSQL bind parameters are presented as $1, $1, $2, etc.
183
+ */
184
+ VALUE
185
+ pgconn_exec( int argc, VALUE *argv, VALUE self)
186
+ {
187
+ VALUE cmd, par;
188
+ VALUE res;
189
+
190
+ pg_parse_parameters( argc, argv, &cmd, &par);
191
+ res = pg_statement_exec( self, cmd, par);
192
+ return yield_or_return_result( res);
193
+ }
194
+
195
+
196
+ /*
197
+ * call-seq:
198
+ * conn.send( sql, *bind_values) { |conn| ... } -> nil
199
+ *
200
+ * Sends an asynchronous SQL query request specified by +sql+ to the
201
+ * PostgreSQL server.
202
+ *
203
+ * Use Pg::Conn#fetch to fetch the results after you waited for data.
204
+ *
205
+ * Pg::Conn.connect do |conn|
206
+ * conn.send "select pg_sleep(3), * from t;" do
207
+ * ins = [ conn.socket]
208
+ * loop do
209
+ * r = IO.select ins, nil, nil, 0.5
210
+ * break if r
211
+ * puts Time.now
212
+ * end
213
+ * res = conn.fetch
214
+ * res.each { |w| puts w.inspect }
215
+ * end
216
+ * end
217
+ */
218
+ VALUE
219
+ pgconn_send( int argc, VALUE *argv, VALUE self)
220
+ {
221
+ VALUE cmd, par;
222
+
223
+ pg_parse_parameters( argc, argv, &cmd, &par);
224
+ pg_statement_send( self, cmd, par);
225
+ return rb_ensure( rb_yield, self, clear_resultqueue, self);
226
+ }
227
+
228
+ /*
229
+ * call-seq:
230
+ * conn.fetch() -> result or nil
231
+ * conn.fetch() { |result| ... } -> obj
232
+ *
233
+ * Fetches the results of the previous Pg::Conn#send call.
234
+ * See there for an example.
235
+ *
236
+ * The result will be +nil+ if there are no more results.
237
+ */
238
+ VALUE
239
+ pgconn_fetch( VALUE self)
240
+ {
241
+ struct pgconn_data *c;
242
+ PGresult *result;
243
+ VALUE res;
244
+
245
+ Data_Get_Struct( self, struct pgconn_data, c);
246
+ pg_check_conninvalid( c);
247
+ if (PQconsumeInput( c->conn) == 0)
248
+ pg_raise_connexec( c);
249
+ if (PQisBusy( c->conn) > 0)
250
+ return Qnil;
251
+ result = PQgetResult( c->conn);
252
+ return result == NULL ? Qnil :
253
+ yield_or_return_result( pgresult_new( result, c, Qnil, Qnil));
254
+ }
255
+
256
+ VALUE
257
+ yield_or_return_result( VALUE result)
258
+ {
259
+ struct pgresult_data *r;
260
+
261
+ Data_Get_Struct( result, struct pgresult_data, r);
262
+ return rb_block_given_p() ?
263
+ rb_ensure( rb_yield, result, pgresult_clear, result) : result;
264
+ }
265
+
266
+ VALUE
267
+ clear_resultqueue( VALUE self)
268
+ {
269
+ struct pgconn_data *c;
270
+ PGresult *result;
271
+
272
+ Data_Get_Struct( self, struct pgconn_data, c);
273
+ while ((result = PQgetResult( c->conn)) != NULL)
274
+ PQclear( result);
275
+ return Qnil;
276
+ }
277
+
278
+
279
+
280
+
281
+ /*
282
+ * call-seq:
283
+ * conn.query( sql, *bind_values) -> rows
284
+ * conn.query( sql, *bind_values) { |row| ... } -> int or nil
285
+ *
286
+ * This is almost the same as Pg::Conn#exec except that it will yield or return
287
+ * rows skipping the result object.
288
+ *
289
+ * If given a block, the nonzero number of rows will be returned or nil
290
+ * otherwise.
291
+ */
292
+ VALUE
293
+ pgconn_query( int argc, VALUE *argv, VALUE self)
294
+ {
295
+ VALUE cmd, par;
296
+ VALUE res;
297
+
298
+ pg_parse_parameters( argc, argv, &cmd, &par);
299
+ res = pg_statement_exec( self, cmd, par);
300
+ if (rb_block_given_p())
301
+ return rb_ensure( pgresult_each, res, pgresult_clear, res);
302
+ else {
303
+ VALUE ret;
304
+
305
+ if (!id_to_a)
306
+ id_to_a = rb_intern( "to_a");
307
+ ret = rb_funcall( res, id_to_a, 0);
308
+ pgresult_clear( res);
309
+ return ret;
310
+ }
311
+ }
312
+
313
+ /*
314
+ * call-seq:
315
+ * conn.select_one( query, *bind_values)
316
+ *
317
+ * Return the first row of the query results.
318
+ * Equivalent to <code>conn.query( query, *bind_values).first</code>.
319
+ */
320
+ VALUE
321
+ pgconn_select_one( int argc, VALUE *argv, VALUE self)
322
+ {
323
+ VALUE cmd, par;
324
+ VALUE res;
325
+ struct pgresult_data *r;
326
+
327
+ pg_parse_parameters( argc, argv, &cmd, &par);
328
+ res = pg_statement_exec( self, cmd, par);
329
+
330
+ Data_Get_Struct( res, struct pgresult_data, r);
331
+ return pg_fetchrow( r, 0);
332
+ }
333
+
334
+ /*
335
+ * call-seq:
336
+ * conn.select_value( query, *bind_values)
337
+ *
338
+ * Return the first value of the first row of the query results.
339
+ * Equivalent to conn.query( query, *bind_values).first.first
340
+ */
341
+ VALUE
342
+ pgconn_select_value( int argc, VALUE *argv, VALUE self)
343
+ {
344
+ VALUE cmd, par;
345
+ VALUE res;
346
+ struct pgresult_data *r;
347
+
348
+ pg_parse_parameters( argc, argv, &cmd, &par);
349
+ res = pg_statement_exec( self, cmd, par);
350
+
351
+ Data_Get_Struct( res, struct pgresult_data, r);
352
+ return PQntuples( r->res) > 0 && PQnfields( r->res) > 0 ?
353
+ pg_fetchresult( r, 0, 0) : Qnil;
354
+ }
355
+
356
+ /*
357
+ * call-seq:
358
+ * conn.select_values( query, *bind_values)
359
+ *
360
+ * Equivalent to conn.query( query, *bind_values).flatten
361
+ */
362
+ VALUE
363
+ pgconn_select_values( int argc, VALUE *argv, VALUE self)
364
+ {
365
+ VALUE cmd, par;
366
+ VALUE res;
367
+ struct pgresult_data *r;
368
+ int n, m, n_, l;
369
+ int i, j, k;
370
+ VALUE ret;
371
+
372
+ pg_parse_parameters( argc, argv, &cmd, &par);
373
+ res = pg_statement_exec( self, cmd, par);
374
+
375
+ Data_Get_Struct( res, struct pgresult_data, r);
376
+ m = PQntuples( r->res), n = PQnfields( r->res);
377
+ l = m * n;
378
+ if (l == 0)
379
+ return Qnil;
380
+ ret = rb_ary_new2( l);
381
+ n_ = n;
382
+ for (k = 0, j = 0; m; ++j, --m) {
383
+ for (i = 0; n; ++i, --n, ++k)
384
+ rb_ary_store( ret, k, pg_fetchresult( r, j, i));
385
+ n = n_;
386
+ }
387
+ return ret;
388
+ }
389
+
390
+ /*
391
+ * call-seq:
392
+ * conn.get_notify() -> ary or nil
393
+ * conn.get_notify() { |rel,pid,msg| .... } -> obj
394
+ *
395
+ * Returns a notifier. If there is no unprocessed notifier, it returns +nil+.
396
+ */
397
+ VALUE
398
+ pgconn_get_notify( VALUE self)
399
+ {
400
+ struct pgconn_data *c;
401
+ PGnotify *notify;
402
+ VALUE rel, pid, ext;
403
+ VALUE ret;
404
+
405
+ Data_Get_Struct( self, struct pgconn_data, c);
406
+ if (PQconsumeInput( c->conn) == 0)
407
+ pg_raise_connexec( c);
408
+ notify = PQnotifies( c->conn);
409
+ if (notify == NULL)
410
+ return Qnil;
411
+ rel = pgconn_mkstring( c, notify->relname);
412
+ pid = INT2FIX( notify->be_pid),
413
+ ext = pgconn_mkstring( c, notify->extra);
414
+ ret = rb_ary_new3( 3, rel, pid, ext);
415
+ PQfreemem( notify);
416
+ return rb_block_given_p() ? rb_yield( ret) : ret;
417
+ }
418
+
419
+
420
+
421
+
422
+ /*
423
+ * call-seq:
424
+ * conn.transaction( ser = nil, ro = nil) { |conn| ... }
425
+ *
426
+ * Open and close a transaction block. The isolation level will be
427
+ * 'serializable' if +ser+ is true, else 'repeatable read'.
428
+ * +ro+ means 'read only'.
429
+ *
430
+ * (In C++ terms, +ro+ is const, and +ser+ is not volatile.)
431
+ *
432
+ */
433
+ VALUE
434
+ pgconn_transaction( int argc, VALUE *argv, VALUE self)
435
+ {
436
+ struct pgconn_data *c;
437
+ VALUE ser, ro;
438
+ VALUE cmd;
439
+ int p;
440
+
441
+ rb_scan_args( argc, argv, "02", &ser, &ro);
442
+ cmd = rb_str_buf_new2( "begin");
443
+ p = 0;
444
+ if (!NIL_P( ser)) {
445
+ rb_str_buf_cat2( cmd, " isolation level ");
446
+ rb_str_buf_cat2( cmd, RTEST(ser) ? "serializable" : "read committed");
447
+ p++;
448
+ }
449
+ if (!NIL_P( ro)) {
450
+ if (p) rb_str_buf_cat2( cmd, ",");
451
+ rb_str_buf_cat2( cmd, " read ");
452
+ rb_str_buf_cat2( cmd, (RTEST(ro) ? "only" : "write"));
453
+ }
454
+ rb_str_buf_cat2( cmd, ";");
455
+
456
+ Data_Get_Struct( self, struct pgconn_data, c);
457
+ if (PQtransactionStatus( c->conn) > PQTRANS_IDLE)
458
+ rb_raise( rb_ePgConnTrans,
459
+ "Nested transaction block. Use Conn#subtransaction.");
460
+ pgresult_clear( pg_statement_exec( self, cmd, Qnil));
461
+ return rb_rescue( yield_transaction, self, rescue_transaction, self);
462
+ }
463
+
464
+ VALUE
465
+ rescue_transaction( VALUE self)
466
+ {
467
+ pgresult_clear( pg_statement_exec( self, rb_str_new2( "rollback;"), Qnil));
468
+ rb_exc_raise( RB_ERRINFO);
469
+ return Qnil;
470
+ }
471
+
472
+ VALUE
473
+ yield_transaction( VALUE self)
474
+ {
475
+ VALUE r;
476
+
477
+ r = rb_yield( self);
478
+ pgresult_clear( pg_statement_exec( self, rb_str_new2( "commit;"), Qnil));
479
+ return r;
480
+ }
481
+
482
+
483
+ /*
484
+ * call-seq:
485
+ * conn.subtransaction( name, *args) { |conn,sp| ... }
486
+ *
487
+ * Open and close a transaction savepoint. The savepoints name +nam+ may
488
+ * contain % directives that will be expanded by +args+.
489
+ */
490
+ VALUE
491
+ pgconn_subtransaction( int argc, VALUE *argv, VALUE self)
492
+ {
493
+ struct pgconn_data *c;
494
+ int a;
495
+ VALUE sp, par, cmd, ya;
496
+ const char *q;
497
+ char *p;
498
+ int n;
499
+
500
+ Data_Get_Struct( self, struct pgconn_data, c);
501
+ a = rb_scan_args( argc, argv, "1*", &sp, &par);
502
+ StringValue( sp);
503
+ if (a > 1)
504
+ sp = rb_str_format(RARRAY_LEN(par), RARRAY_PTR(par), sp);
505
+
506
+ cmd = rb_str_buf_new2( "savepoint ");
507
+ q = pgconn_destring( c, sp, &n);
508
+ p = PQescapeIdentifier( c->conn, q, n);
509
+ rb_str_buf_cat2( cmd, p);
510
+ ya = rb_ary_new3( 2, self, rb_str_new2( p));
511
+ PQfreemem( p);
512
+ rb_str_buf_cat2( cmd, ";");
513
+
514
+ pgresult_clear( pg_statement_exec( self, cmd, Qnil));
515
+ return rb_rescue( yield_subtransaction, ya, rescue_subtransaction, ya);
516
+ }
517
+
518
+ VALUE
519
+ rescue_subtransaction( VALUE ary)
520
+ {
521
+ VALUE cmd;
522
+
523
+ cmd = rb_str_buf_new2( "rollback to savepoint ");
524
+ rb_str_buf_append( cmd, rb_ary_entry( ary, 1));
525
+ rb_str_buf_cat2( cmd, ";");
526
+ pgresult_clear( pg_statement_exec( rb_ary_entry( ary, 0), cmd, Qnil));
527
+ rb_exc_raise( RB_ERRINFO);
528
+ return Qnil;
529
+ }
530
+
531
+ VALUE
532
+ yield_subtransaction( VALUE ary)
533
+ {
534
+ VALUE r, cmd;
535
+
536
+ r = rb_yield( ary);
537
+ cmd = rb_str_buf_new2( "release savepoint ");
538
+ rb_str_buf_append( cmd, rb_ary_entry( ary, 1));
539
+ rb_str_buf_cat2( cmd, ";");
540
+ pgresult_clear( pg_statement_exec( rb_ary_entry( ary, 0), cmd, Qnil));
541
+ return r;
542
+ }
543
+
544
+
545
+
546
+
547
+ /*
548
+ * call-seq:
549
+ * conn.transaction_status() -> int
550
+ *
551
+ * returns one of the following statuses:
552
+ *
553
+ * PQTRANS_IDLE = 0 (connection idle)
554
+ * PQTRANS_ACTIVE = 1 (command in progress)
555
+ * PQTRANS_INTRANS = 2 (idle, within transaction block)
556
+ * PQTRANS_INERROR = 3 (idle, within failed transaction)
557
+ * PQTRANS_UNKNOWN = 4 (cannot determine status)
558
+ */
559
+ VALUE
560
+ pgconn_transaction_status( VALUE self)
561
+ {
562
+ struct pgconn_data *c;
563
+
564
+ Data_Get_Struct( self, struct pgconn_data, c);
565
+ return INT2FIX( PQtransactionStatus( c->conn));
566
+ }
567
+
568
+
569
+
570
+ /*
571
+ * call-seq:
572
+ * conn.copy_stdin( sql, *bind_values) { |result| ... } -> nil
573
+ *
574
+ * Write lines into a +COPY+ command. See +stringize_line+ for how to build
575
+ * standard lines.
576
+ *
577
+ * conn.copy_stdin "copy t from stdin;" do
578
+ * ary = ...
579
+ * l = stringize_line ary
580
+ * conn.put l
581
+ * end
582
+ *
583
+ * You may write a "\\." yourself if you like it.
584
+ */
585
+ VALUE
586
+ pgconn_copy_stdin( int argc, VALUE *argv, VALUE self)
587
+ {
588
+ VALUE cmd, par;
589
+ VALUE res;
590
+
591
+ pg_parse_parameters( argc, argv, &cmd, &par);
592
+ res = pg_statement_exec( self, cmd, par);
593
+ return rb_ensure( rb_yield, res, put_end, self);
594
+ }
595
+
596
+
597
+ VALUE
598
+ put_end( VALUE self)
599
+ {
600
+ struct pgconn_data *c;
601
+ int r;
602
+ PGresult *res;
603
+
604
+ Data_Get_Struct( self, struct pgconn_data, c);
605
+ /*
606
+ * I would like to hand over something like
607
+ * RSTRING_PTR( rb_obj_as_string( RB_ERRINFO))
608
+ * here but when execution is inside a rescue block
609
+ * the error info will be non-null even though the
610
+ * exception just has been caught.
611
+ */
612
+ while ((r = PQputCopyEnd( c->conn, NULL)) == 0)
613
+ ;
614
+ if (r < 0)
615
+ rb_raise( rb_ePgConnCopy, "Copy from stdin failed to finish.");
616
+ while ((res = PQgetResult( c->conn)) != NULL)
617
+ pgresult_new( res, c, Qnil, Qnil);
618
+ return Qnil;
619
+ }
620
+
621
+ /*
622
+ * call-seq:
623
+ * conn.putline( str) -> nil
624
+ * conn.putline( ary) -> nil
625
+ * conn.putline( str) { ... } -> nil
626
+ *
627
+ * Sends the string to the backend server.
628
+ * You have to open the stream with a +COPY+ command using +copy_stdin+.
629
+ *
630
+ * If +str+ doesn't end in a newline, one is appended. If the argument
631
+ * is +ary+, a line will be built using +stringize_line+.
632
+ *
633
+ * If the connection is in nonblocking mode and no data could be sent
634
+ * the closure will be called and its value will be returned.
635
+ */
636
+ VALUE
637
+ pgconn_putline( VALUE self, VALUE arg)
638
+ {
639
+ struct pgconn_data *c;
640
+ VALUE str;
641
+ const char *p;
642
+ int l;
643
+ int r;
644
+
645
+ switch (TYPE( arg)) {
646
+ case T_STRING:
647
+ str = arg;
648
+ break;
649
+ case T_ARRAY:
650
+ str = pgconn_stringize_line( self, arg);
651
+ break;
652
+ default:
653
+ str = rb_obj_as_string( arg);
654
+ break;
655
+ }
656
+ if (RSTRING_PTR( str)[ RSTRING_LEN( str) - 1] != '\n') {
657
+ VALUE t;
658
+
659
+ t = rb_str_dup( str);
660
+ rb_str_buf_cat( t, "\n", 1);
661
+ str = t;
662
+ }
663
+
664
+ Data_Get_Struct( self, struct pgconn_data, c);
665
+ p = pgconn_destring( c, str, &l);
666
+ r = PQputCopyData( c->conn, p, l);
667
+ if (r < 0)
668
+ rb_raise( rb_ePgConnCopy, "Copy from stdin failed.");
669
+ else if (r == 0)
670
+ return rb_yield( Qnil);
671
+ return Qnil;
672
+ }
673
+
674
+
675
+ /*
676
+ * call-seq:
677
+ * conn.copy_stdout( sql, *bind_values) { ... } -> nil
678
+ *
679
+ * Read lines from a +COPY+ command. The form of the lines depends
680
+ * on the statement's parameters.
681
+ *
682
+ * conn.copy_stdout "copy t to stdout;" do
683
+ * l = conn.getline
684
+ * ary = l.split /\t/
685
+ * ary.map! { |x|
686
+ * unless x == "\\N" then
687
+ * x.gsub! /\\(.)/ do
688
+ * case $1
689
+ * when "t" then "\t"
690
+ * when "n" then "\n"
691
+ * when "\\" then "\\"
692
+ * end
693
+ * end
694
+ * end
695
+ * }
696
+ * ...
697
+ * end
698
+ */
699
+ VALUE
700
+ pgconn_copy_stdout( int argc, VALUE *argv, VALUE self)
701
+ {
702
+ VALUE cmd, par;
703
+ VALUE res;
704
+
705
+ pg_parse_parameters( argc, argv, &cmd, &par);
706
+ res = pg_statement_exec( self, cmd, par);
707
+ return rb_ensure( rb_yield, res, get_end, self);
708
+ }
709
+
710
+ VALUE
711
+ get_end( VALUE self)
712
+ {
713
+ struct pgconn_data *c;
714
+ PGresult *res;
715
+
716
+ Data_Get_Struct( self, struct pgconn_data, c);
717
+ if ((res = PQgetResult( c->conn)) != NULL)
718
+ pgresult_new( res, c, Qnil, Qnil);
719
+ return Qnil;
720
+ }
721
+
722
+ /*
723
+ * call-seq:
724
+ * conn.getline( async = nil) -> str
725
+ * conn.getline( async = nil) { ... } -> str
726
+ *
727
+ * Reads a line from the backend server after a +COPY+ command.
728
+ * Returns +nil+ for EOF.
729
+ *
730
+ * If async is +true+ and no data is available then the block will be called
731
+ * and its value will be returned.
732
+ *
733
+ * Call this method inside a block passed to +copy_stdout+. See
734
+ * there for an example.
735
+ */
736
+ VALUE
737
+ pgconn_getline( int argc, VALUE *argv, VALUE self)
738
+ {
739
+ struct pgconn_data *c;
740
+ VALUE as;
741
+ int async;
742
+ char *b;
743
+ int r;
744
+
745
+ async = rb_scan_args( argc, argv, "01", &as) > 0 && !NIL_P( as) ? 1 : 0;
746
+
747
+ Data_Get_Struct( self, struct pgconn_data, c);
748
+ r = PQgetCopyData( c->conn, &b, async);
749
+ if (r > 0) {
750
+ VALUE ret;
751
+
752
+ ret = pgconn_mkstringn( c, b, r);
753
+ PQfreemem( b);
754
+ rb_lastline_set( ret);
755
+ return ret;
756
+ } else if (r == 0)
757
+ return rb_yield( Qnil);
758
+ else {
759
+ /* PQgetResult() will be called in the ensure block. */
760
+ }
761
+ return Qnil;
762
+ }
763
+
764
+ /*
765
+ * call-seq:
766
+ * conn.each_line() { |line| ... } -> nil
767
+ *
768
+ * Reads line after line from a +COPY+ command.
769
+ *
770
+ * Call this method inside a block passed to +copy_stdout+. See
771
+ * there for an example.
772
+ */
773
+ VALUE
774
+ pgconn_each_line( VALUE self)
775
+ {
776
+ struct pgconn_data *c;
777
+ char *b;
778
+ int r;
779
+ VALUE s;
780
+
781
+ Data_Get_Struct( self, struct pgconn_data, c);
782
+ for (; (r = PQgetCopyData( c->conn, &b, 0)) > 0;) {
783
+ s = pgconn_mkstringn( c, b, r);
784
+ PQfreemem( b);
785
+ rb_yield( s);
786
+ }
787
+ return Qnil;
788
+ }
789
+
790
+
791
+
792
+
793
+
794
+
795
+
796
+
797
+ /********************************************************************
798
+ *
799
+ * Document-class: Pg::Conn::ExecError
800
+ *
801
+ * Error while querying from a PostgreSQL connection.
802
+ */
803
+
804
+
805
+ /********************************************************************
806
+ *
807
+ * Document-class: Pg::Conn::TransactionError
808
+ *
809
+ * Nested transaction blocks. Use savepoints.
810
+ */
811
+
812
+
813
+ /********************************************************************
814
+ *
815
+ * Document-class: Pg::Conn::CopyError
816
+ *
817
+ * Nested transaction blocks. Use savepoints.
818
+ */
819
+
820
+
821
+ void
822
+ Init_pgsql_conn_exec( void)
823
+ {
824
+
825
+ #ifdef RDOC_NEEDS_THIS
826
+ rb_cPgConn = rb_define_class_under( rb_mPg, "Conn", rb_cObject);
827
+ #endif
828
+
829
+ rb_ePgConnExec = rb_define_class_under( rb_cPgConn, "ExecError", rb_ePgError);
830
+ rb_ePgConnTrans = rb_define_class_under( rb_cPgConn, "TransactionError", rb_ePgError);
831
+ rb_ePgConnCopy = rb_define_class_under( rb_cPgConn, "CopyError", rb_ePgError);
832
+
833
+ rb_define_method( rb_cPgConn, "exec", &pgconn_exec, -1);
834
+ rb_define_method( rb_cPgConn, "send", &pgconn_send, -1);
835
+ rb_define_method( rb_cPgConn, "fetch", &pgconn_fetch, 0);
836
+
837
+ rb_define_method( rb_cPgConn, "query", &pgconn_query, -1);
838
+ rb_define_method( rb_cPgConn, "select_one", &pgconn_select_one, -1);
839
+ rb_define_method( rb_cPgConn, "select_value", &pgconn_select_value, -1);
840
+ rb_define_method( rb_cPgConn, "select_values", &pgconn_select_values, -1);
841
+ rb_define_method( rb_cPgConn, "get_notify", &pgconn_get_notify, 0);
842
+
843
+
844
+
845
+ #define TRANS_DEF( c) rb_define_const( rb_cPgConn, "T_" #c, INT2FIX( PQTRANS_ ## c))
846
+ TRANS_DEF( IDLE);
847
+ TRANS_DEF( ACTIVE);
848
+ TRANS_DEF( INTRANS);
849
+ TRANS_DEF( INERROR);
850
+ TRANS_DEF( UNKNOWN);
851
+ #undef TRANS_DEF
852
+
853
+ rb_define_method( rb_cPgConn, "transaction", &pgconn_transaction, -1);
854
+ rb_define_method( rb_cPgConn, "subtransaction", &pgconn_subtransaction, -1);
855
+ rb_define_alias( rb_cPgConn, "savepoint", "subtransaction");
856
+ rb_define_method( rb_cPgConn, "transaction_status", &pgconn_transaction_status, 0);
857
+
858
+
859
+ rb_define_method( rb_cPgConn, "copy_stdin", &pgconn_copy_stdin, -1);
860
+ rb_define_method( rb_cPgConn, "putline", &pgconn_putline, 1);
861
+ rb_define_alias( rb_cPgConn, "put", "putline");
862
+ rb_define_method( rb_cPgConn, "copy_stdout", &pgconn_copy_stdout, -1);
863
+ rb_define_method( rb_cPgConn, "getline", &pgconn_getline, -1);
864
+ rb_define_alias( rb_cPgConn, "get", "getline");
865
+ rb_define_method( rb_cPgConn, "each_line", &pgconn_each_line, 0);
866
+
867
+ ID id_to_a = 0;
868
+ }
869
+