pgsql 1.0

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.
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
+