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_quote.h ADDED
@@ -0,0 +1,27 @@
1
+ /*
2
+ * conn_quote.h -- PostgreSQL connection, string handling
3
+ */
4
+
5
+ #ifndef __CONN_QUOTE_H
6
+ #define __CONN_QUOTE_H
7
+
8
+ #include "conn.h"
9
+
10
+
11
+ extern VALUE rb_cDate;
12
+ extern VALUE rb_cDateTime;
13
+ extern VALUE rb_cCurrency;
14
+
15
+
16
+ extern VALUE pg_currency_class( void);
17
+
18
+
19
+ extern VALUE pgconn_stringize( VALUE self, VALUE obj);
20
+ extern VALUE pgconn_stringize_line( VALUE self, VALUE ary);
21
+
22
+
23
+ extern void Init_pgsql_conn_quote( void);
24
+
25
+
26
+ #endif
27
+
data/lib/mkrf_conf ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #
4
+ # mkrf_conf -- configure Ruby-PgSQL
5
+ #
6
+
7
+ require "autorake/mkconfig"
8
+
9
+ Autorake.configure {
10
+
11
+ extending_ruby
12
+
13
+ if RUBY_VERSION < "1.9" then
14
+ have_header "ruby.h"
15
+ have_header "rubyio.h"
16
+ have_header "st.h"
17
+ else
18
+ have_header "ruby/ruby.h"
19
+ have_header "ruby/io.h"
20
+ end
21
+
22
+ incdir :postgres, `pg_config --pkgincludedir`
23
+ incdir :postgres_server, `pg_config --includedir-server`
24
+
25
+ have_library "crypto"
26
+ have_library "ssl"
27
+ have_library "pq"
28
+
29
+ have_header "postgres.h"
30
+ have_header "libpq-fe.h"
31
+ have_header "catalog/pg_type.h"
32
+
33
+ have_func "rb_errinfo"
34
+ have_func "rb_io_stdio_file"
35
+ have_func "rb_locale_encoding"
36
+
37
+ }
38
+
data/lib/module.c ADDED
@@ -0,0 +1,47 @@
1
+ /*
2
+ * module.c -- Pg module
3
+ */
4
+
5
+ #include "module.h"
6
+
7
+ #include "conn.h"
8
+
9
+
10
+ #define PGSQL_VERSION "1.0"
11
+
12
+
13
+ VALUE rb_mPg;
14
+ VALUE rb_ePgError;
15
+
16
+
17
+ /********************************************************************
18
+ *
19
+ * Document-module: Pg
20
+ *
21
+ * The module to enclose everything.
22
+ *
23
+ * See the Pg::Conn class for information on how to open a database
24
+ * connection.
25
+ */
26
+
27
+ /********************************************************************
28
+ *
29
+ * Document-class: Pg::Error
30
+ *
31
+ * Generic PostgreSQL error.
32
+ */
33
+
34
+ void
35
+ Init_pgsql( void)
36
+ {
37
+ rb_mPg = rb_define_module( "Pg");
38
+
39
+ rb_define_const( rb_mPg, "VERSION",
40
+ rb_obj_freeze( rb_str_new2( PGSQL_VERSION)));
41
+
42
+ rb_ePgError = rb_define_class_under( rb_mPg, "Error", rb_eStandardError);
43
+
44
+ Init_pgsql_conn();
45
+ Init_pgsql_result();
46
+ }
47
+
data/lib/module.h ADDED
@@ -0,0 +1,39 @@
1
+ /*
2
+ * module.h -- Pg module
3
+ */
4
+
5
+ #ifndef __MODULE_H
6
+ #define __MODULE_H
7
+
8
+
9
+ #if defined( HAVE_HEADER_RUBY_H)
10
+ #include <ruby.h>
11
+ #elif defined( HAVE_HEADER_RUBY_RUBY_H)
12
+ #include <ruby/ruby.h>
13
+ #endif
14
+ #if defined( HAVE_HEADER_RUBYIO_H)
15
+ #include "rubyio.h"
16
+ #elif defined( HAVE_HEADER_RUBY_IO_H)
17
+ #include "ruby/io.h"
18
+ #endif
19
+ #include "undef.h"
20
+
21
+ #ifdef HAVE_HEADER_POSTGRES_H
22
+ #include <postgres.h>
23
+ #endif
24
+ #ifdef HAVE_HEADER_LIBPQ_FE_H
25
+ #include <libpq-fe.h>
26
+ #endif
27
+ #ifdef HAVE_HEADER_CATALOG_PG_TYPE_H
28
+ #include <catalog/pg_type.h>
29
+ #endif
30
+ #include "undef.h"
31
+
32
+
33
+ extern VALUE rb_mPg;
34
+ extern VALUE rb_ePgError;
35
+
36
+ extern void Init_pgsql( void);
37
+
38
+ #endif
39
+
data/lib/result.c ADDED
@@ -0,0 +1,891 @@
1
+ /*
2
+ * result.c -- Pg query results
3
+ */
4
+
5
+
6
+ #include "result.h"
7
+
8
+ #include "conn_quote.h"
9
+
10
+
11
+ static void pgresult_init( struct pgresult_data *r, PGresult *result, struct pgconn_data *conn);
12
+ static VALUE pgreserror_new( VALUE result, VALUE cmd, VALUE par);
13
+
14
+ static VALUE pgreserror_command( VALUE self);
15
+ static VALUE pgreserror_params( VALUE self);
16
+
17
+ static struct pgresult_data *pgreserror_result( VALUE self);
18
+ static VALUE pgreserror_status( VALUE self);
19
+ static VALUE pgreserror_sqlst( VALUE self);
20
+ static VALUE pgreserror_primary( VALUE self);
21
+ static VALUE pgreserror_detail( VALUE self);
22
+ static VALUE pgreserror_hint( VALUE self);
23
+ static VALUE pgreserror_diag( VALUE self, VALUE field);
24
+
25
+
26
+ static VALUE pgresult_s_translate_results_set( VALUE cls, VALUE fact);
27
+
28
+ static void pgresult_mark( struct pgresult_data *ptr);
29
+ static void pgresult_free( struct pgresult_data *ptr);
30
+ extern VALUE pgresult_new( PGresult *result, struct pgconn_data *conn, VALUE cmd, VALUE par);
31
+
32
+ extern VALUE pgresult_clear( VALUE self);
33
+
34
+ static VALUE pgresult_status( VALUE self);
35
+
36
+ static VALUE pgresult_fields( VALUE self);
37
+ static VALUE pgresult_field_indices( VALUE self);
38
+ static VALUE pgresult_num_fields( VALUE self);
39
+ static VALUE pgresult_fieldname( VALUE self, VALUE index);
40
+ static VALUE pgresult_fieldnum( VALUE self, VALUE name);
41
+
42
+ extern VALUE pgresult_each( VALUE self);
43
+ static VALUE pgresult_aref( int argc, VALUE *argv, VALUE self);
44
+ extern VALUE pg_fetchrow( struct pgresult_data *r, int num);
45
+ extern VALUE pg_fetchresult( struct pgresult_data *r, int row, int col);
46
+ static VALUE pgresult_num_tuples( VALUE self);
47
+
48
+ static VALUE pgresult_type( VALUE self, VALUE index);
49
+ static VALUE pgresult_size( VALUE self, VALUE index);
50
+ static VALUE pgresult_getvalue( VALUE self, VALUE row, VALUE col);
51
+ static VALUE pgresult_getlength( VALUE self, VALUE row, VALUE col);
52
+ static VALUE pgresult_getisnull( VALUE self, VALUE row, VALUE col);
53
+ static VALUE pgresult_getvalue_byname( VALUE self, VALUE row, VALUE field_name);
54
+
55
+ static VALUE pgresult_cmdtuples( VALUE self);
56
+ static VALUE pgresult_cmdstatus( VALUE self);
57
+ static VALUE pgresult_oid( VALUE self);
58
+
59
+
60
+ static VALUE rb_cBigDecimal;
61
+
62
+ static VALUE rb_cPgResult;
63
+ static VALUE rb_ePgResError;
64
+
65
+ static ID id_new;
66
+ static ID id_parse;
67
+ static ID id_result;
68
+
69
+ static int translate_results = 1;
70
+
71
+
72
+
73
+
74
+ VALUE
75
+ pgreserror_new( VALUE result, VALUE cmd, VALUE par)
76
+ {
77
+ struct pgresult_data *r;
78
+ VALUE rse, msg;
79
+
80
+ Data_Get_Struct( result, struct pgresult_data, r);
81
+ msg = pgconn_mkstring( r->conn, PQresultErrorMessage( r->res));
82
+ rse = rb_class_new_instance( 1, &msg, rb_ePgResError);
83
+ rb_ivar_set( rse, id_result, result);
84
+ rb_ivar_set( rse, rb_intern( "@command"), cmd);
85
+ rb_ivar_set( rse, rb_intern( "@parameters"), par);
86
+ return rse;
87
+ }
88
+
89
+
90
+
91
+ static struct pgresult_data *
92
+ pgreserror_result( VALUE self)
93
+ {
94
+ struct pgresult_data *r;
95
+
96
+ Data_Get_Struct( rb_ivar_get( self, id_result), struct pgresult_data, r);
97
+ return r;
98
+ }
99
+
100
+ /*
101
+ * call-seq:
102
+ * pgqe.status() => num
103
+ *
104
+ * Forward PostgreSQL's error code.
105
+ *
106
+ */
107
+ VALUE
108
+ pgreserror_status( VALUE self)
109
+ {
110
+ struct pgresult_data *r;
111
+
112
+ r = pgreserror_result( self);
113
+ return INT2FIX( PQresultStatus( r->res));
114
+ }
115
+
116
+ /*
117
+ * call-seq:
118
+ * pgqe.sqlstate() => string
119
+ *
120
+ * Forward PostgreSQL's error code.
121
+ *
122
+ */
123
+ VALUE
124
+ pgreserror_sqlst( VALUE self)
125
+ {
126
+ struct pgresult_data *r;
127
+
128
+ r = pgreserror_result( self);
129
+ return pgconn_mkstring( r->conn, PQresultErrorField( r->res, PG_DIAG_SQLSTATE));
130
+ }
131
+
132
+ /*
133
+ * call-seq:
134
+ * pgqe.primary() => string
135
+ *
136
+ * Forward PostgreSQL's primary error message.
137
+ *
138
+ */
139
+ VALUE
140
+ pgreserror_primary( VALUE self)
141
+ {
142
+ struct pgresult_data *r;
143
+
144
+ r = pgreserror_result( self);
145
+ return pgconn_mkstring( r->conn, PQresultErrorField( r->res, PG_DIAG_MESSAGE_PRIMARY));
146
+ }
147
+
148
+
149
+ /*
150
+ * call-seq:
151
+ * pgqe.details() => string
152
+ *
153
+ * Forward PostgreSQL's error details.
154
+ *
155
+ */
156
+ VALUE
157
+ pgreserror_detail( VALUE self)
158
+ {
159
+ struct pgresult_data *r;
160
+
161
+ r = pgreserror_result( self);
162
+ return pgconn_mkstring( r->conn, PQresultErrorField( r->res, PG_DIAG_MESSAGE_DETAIL));
163
+ }
164
+
165
+
166
+ /*
167
+ * call-seq:
168
+ * pgqe.hint() => string
169
+ *
170
+ * Forward PostgreSQL's error hint.
171
+ *
172
+ */
173
+ VALUE
174
+ pgreserror_hint( VALUE self)
175
+ {
176
+ struct pgresult_data *r;
177
+
178
+ r = pgreserror_result( self);
179
+ return pgconn_mkstring( r->conn, PQresultErrorField( r->res, PG_DIAG_MESSAGE_HINT));
180
+ }
181
+
182
+
183
+ /*
184
+ * call-seq:
185
+ * pgqe.diag( field) => string
186
+ *
187
+ * Error diagnose message. Give one of the PG_DIAG_* constants
188
+ * to specify a field.
189
+ *
190
+ */
191
+ VALUE
192
+ pgreserror_diag( VALUE self, VALUE field)
193
+ {
194
+ struct pgresult_data *r;
195
+
196
+ r = pgreserror_result( self);
197
+ return pgconn_mkstring( r->conn, PQresultErrorField( r->res, NUM2INT( field)));
198
+ }
199
+
200
+
201
+
202
+ /*
203
+ * call-seq:
204
+ * Pg::Conn.translate_results = boolean
205
+ *
206
+ * When true (default), results are translated to an appropriate Ruby class.
207
+ * When false, results are returned as +Strings+.
208
+ *
209
+ */
210
+ VALUE
211
+ pgresult_s_translate_results_set( VALUE cls, VALUE fact)
212
+ {
213
+ translate_results = RTEST( fact) ? 1 : 0;
214
+ return Qnil;
215
+ }
216
+
217
+
218
+
219
+ void
220
+ pgresult_mark( struct pgresult_data *ptr)
221
+ {
222
+ rb_gc_mark( ptr->fields);
223
+ rb_gc_mark( ptr->indices);
224
+ }
225
+
226
+ void
227
+ pgresult_free( struct pgresult_data *ptr)
228
+ {
229
+ if (ptr->res != NULL)
230
+ PQclear( ptr->res);
231
+ free( ptr);
232
+ }
233
+
234
+ void
235
+ pgresult_init( struct pgresult_data *r, PGresult *result, struct pgconn_data *conn)
236
+ {
237
+ r->res = result;
238
+ r->conn = conn;
239
+ r->fields = Qnil;
240
+ r->indices = Qnil;
241
+ }
242
+
243
+ VALUE
244
+ pgresult_new( PGresult *result, struct pgconn_data *conn, VALUE cmd, VALUE par)
245
+ {
246
+ struct pgresult_data *r;
247
+ VALUE res;
248
+
249
+ res = Data_Make_Struct( rb_cPgResult, struct pgresult_data, 0, &pgresult_free, r);
250
+ pgresult_init( r, result, conn);
251
+ switch (PQresultStatus( result)) {
252
+ case PGRES_EMPTY_QUERY:
253
+ case PGRES_COMMAND_OK:
254
+ case PGRES_TUPLES_OK:
255
+ case PGRES_COPY_OUT:
256
+ case PGRES_COPY_IN:
257
+ break;
258
+ case PGRES_BAD_RESPONSE:
259
+ case PGRES_NONFATAL_ERROR:
260
+ case PGRES_FATAL_ERROR:
261
+ rb_exc_raise( pgreserror_new( res, cmd, par));
262
+ break;
263
+ default:
264
+ rb_raise( rb_ePgError, "internal error: unknown result status.");
265
+ break;
266
+ }
267
+ return res;
268
+ }
269
+
270
+ /*
271
+ * call-seq:
272
+ * res.clear()
273
+ *
274
+ * Clears the Pg::Result object as the result of the query.
275
+ */
276
+ VALUE
277
+ pgresult_clear( VALUE self)
278
+ {
279
+ struct pgresult_data *r;
280
+
281
+ Data_Get_Struct( self, struct pgresult_data, r);
282
+ if (r->res != NULL) {
283
+ PQclear( r->res);
284
+ r->res = NULL;
285
+ }
286
+ return Qnil;
287
+ }
288
+
289
+
290
+ /*
291
+ * call-seq:
292
+ * res.status() -> int
293
+ *
294
+ * Returns the status of the query. The status value is one of:
295
+ * * +EMPTY_QUERY+
296
+ * * +COMMAND_OK+
297
+ * * +TUPLES_OK+
298
+ * * +COPY_OUT+
299
+ * * +COPY_IN+
300
+ */
301
+ VALUE
302
+ pgresult_status( VALUE self)
303
+ {
304
+ struct pgresult_data *r;
305
+
306
+ Data_Get_Struct( self, struct pgresult_data, r);
307
+ return INT2FIX( PQresultStatus( r->res));
308
+ }
309
+
310
+
311
+
312
+ /*
313
+ * call-seq:
314
+ * res.fields()
315
+ *
316
+ * Returns an array of Strings representing the names of the fields in the
317
+ * result.
318
+ *
319
+ * res = conn.exec( "SELECT foo, bar AS biggles, jim, jam FROM mytable")
320
+ * res.fields => [ 'foo', 'biggles', 'jim', 'jam']
321
+ */
322
+ VALUE
323
+ pgresult_fields( VALUE self)
324
+ {
325
+ struct pgresult_data *r;
326
+
327
+ Data_Get_Struct( self, struct pgresult_data, r);
328
+ if (NIL_P( r->fields)) {
329
+ VALUE ary;
330
+ int n, i;
331
+ VALUE str;
332
+
333
+ n = PQnfields( r->res);
334
+ ary = rb_ary_new2( n);
335
+ for (i = 0; n; i++, n--) {
336
+ str = pgconn_mkstring( r->conn, PQfname( r->res, i));
337
+ rb_str_freeze( str);
338
+ rb_ary_push( ary, str);
339
+ }
340
+ rb_ary_freeze( ary);
341
+ r->fields = ary;
342
+ }
343
+ return r->fields;
344
+ }
345
+
346
+ /*
347
+ * call-seq:
348
+ * res.field_indices()
349
+ *
350
+ * Returns a hash that points to field numbers.
351
+ * result.
352
+ *
353
+ * res = conn.exec( "SELECT foo, bar AS biggles FROM mytable")
354
+ * res.field_indices => { 'foo' => 0, 'biggles' => 1 }
355
+ */
356
+ VALUE
357
+ pgresult_field_indices( VALUE self)
358
+ {
359
+ struct pgresult_data *r;
360
+
361
+ Data_Get_Struct( self, struct pgresult_data, r);
362
+ if (NIL_P( r->indices)) {
363
+ VALUE hsh;
364
+ int n, i;
365
+ VALUE str;
366
+
367
+ n = PQnfields( r->res);
368
+ hsh = rb_hash_new();
369
+ for (i = 0; n; i++, n--) {
370
+ str = pgconn_mkstring( r->conn, PQfname( r->res, i));
371
+ rb_str_freeze( str);
372
+ rb_hash_aset( hsh, str, INT2FIX( i));
373
+ }
374
+ rb_hash_freeze( hsh);
375
+ r->indices = hsh;
376
+ }
377
+ return r->indices;
378
+ }
379
+
380
+ /*
381
+ * call-seq:
382
+ * res.num_fields()
383
+ *
384
+ * Returns the number of fields (columns) in the query result.
385
+ *
386
+ * Similar to <code>res.result[0].length</code> (but faster).
387
+ */
388
+ VALUE
389
+ pgresult_num_fields( VALUE self)
390
+ {
391
+ struct pgresult_data *r;
392
+
393
+ Data_Get_Struct( self, struct pgresult_data, r);
394
+ return INT2FIX( PQnfields( r->res));
395
+ }
396
+
397
+ /*
398
+ * call-seq:
399
+ * res.fieldname( index)
400
+ *
401
+ * Returns the name of the field (column) corresponding to the index.
402
+ *
403
+ * res = conn.exec "SELECT foo, bar AS biggles, jim, jam FROM mytable"
404
+ * res.fieldname 2 #=> 'jim'
405
+ * res.fieldname 1 #=> 'biggles'
406
+ *
407
+ * Equivalent to <code>res.fields[_index_]</code>.
408
+ */
409
+ VALUE
410
+ pgresult_fieldname( VALUE self, VALUE index)
411
+ {
412
+ struct pgresult_data *r;
413
+
414
+ Data_Get_Struct( self, struct pgresult_data, r);
415
+ return pgconn_mkstring( r->conn, PQfname( r->res, NUM2INT( index)));
416
+ }
417
+
418
+ /*
419
+ * call-seq:
420
+ * res.fieldnum( name)
421
+ *
422
+ * Returns the index of the field specified by the string _name_.
423
+ *
424
+ * res = conn.exec "SELECT foo, bar AS biggles, jim, jam FROM mytable"
425
+ * res.fieldnum 'foo' #=> 0
426
+ *
427
+ * Raises an ArgumentError if the specified _name_ isn't one of the field
428
+ * names; raises a TypeError if _name_ is not a String.
429
+ */
430
+ VALUE
431
+ pgresult_fieldnum( VALUE self, VALUE name)
432
+ {
433
+ struct pgresult_data *r;
434
+ int n;
435
+
436
+ StringValue( name);
437
+ Data_Get_Struct( self, struct pgresult_data, r);
438
+ n = PQfnumber( r->res, pgconn_destring( r->conn, name, NULL));
439
+ if (n == -1)
440
+ rb_raise( rb_eArgError, "Unknown field: %s", RSTRING_PTR( name));
441
+ return INT2FIX( n);
442
+ }
443
+
444
+
445
+
446
+
447
+ /*
448
+ * call-seq:
449
+ * res.each { |tuple| ... } -> nil or int
450
+ *
451
+ * Invokes the block for each tuple (row) in the result.
452
+ *
453
+ * Return the number of rows the query resulted in, or +nil+ if there
454
+ * wasn't any (like <code>Numeric#nonzero?</code>).
455
+ */
456
+ VALUE
457
+ pgresult_each( VALUE self)
458
+ {
459
+ struct pgresult_data *r;
460
+ int m, j;
461
+
462
+ Data_Get_Struct( self, struct pgresult_data, r);
463
+ for (j = 0, m = PQntuples( r->res); m; j++, m--)
464
+ rb_yield( pg_fetchrow( r, j));
465
+ return m ? INT2FIX( m) : Qnil;
466
+ }
467
+
468
+ /*
469
+ * call-seq:
470
+ * res[ n] -> ary
471
+ * res[ n, m] -> obj
472
+ *
473
+ * Returns the tuple (row) corresponding to _n_. Returns +nil+ if <code>_n_ >=
474
+ * res.num_tuples</code>.
475
+ *
476
+ * Equivalent to <code>res.result[n]</code>.
477
+ */
478
+ VALUE
479
+ pgresult_aref( int argc, VALUE *argv, VALUE self)
480
+ {
481
+ struct pgresult_data *r;
482
+ int a;
483
+ VALUE aj, ai;
484
+ int j, i;
485
+
486
+ Data_Get_Struct( self, struct pgresult_data, r);
487
+ a = rb_scan_args( argc, argv, "11", &aj, &ai);
488
+ j = NUM2INT( aj);
489
+ if (j < PQntuples( r->res)) {
490
+ if (a == 1) {
491
+ return pg_fetchrow( r, j);
492
+ } else {
493
+ if (TYPE( ai) == T_STRING) {
494
+ ai = rb_hash_aref( pgresult_field_indices( self), ai);
495
+ if (NIL_P( ai))
496
+ return Qnil;
497
+ }
498
+ i = NUM2INT( ai);
499
+ if (i < PQnfields( r->res))
500
+ return pg_fetchresult( r, j, i);
501
+ }
502
+ }
503
+ return Qnil;
504
+ }
505
+
506
+
507
+ VALUE
508
+ pg_fetchrow( struct pgresult_data *r, int num)
509
+ {
510
+ VALUE row;
511
+ int n, i;
512
+
513
+ n = PQnfields( r->res);
514
+ if (num < PQntuples( r->res)) {
515
+ row = rb_ary_new2( n);
516
+ for (i = 0, n; n; ++i, --n)
517
+ rb_ary_store( row, i, pg_fetchresult( r, num, i));
518
+ } else
519
+ row = Qnil;
520
+ return row;
521
+ }
522
+
523
+ VALUE
524
+ pg_fetchresult( struct pgresult_data *r, int row, int col)
525
+ {
526
+ char *string;
527
+ Oid typ;
528
+ VALUE ret;
529
+
530
+ if (PQgetisnull( r->res, row, col))
531
+ return Qnil;
532
+
533
+ string = PQgetvalue( r->res, row, col);
534
+ if (string == NULL)
535
+ return Qnil;
536
+
537
+ if (!translate_results)
538
+ return pgconn_mkstring( r->conn, string);
539
+
540
+ typ = PQftype( r->res, col);
541
+ switch (typ) {
542
+ case NUMERICOID:
543
+ {
544
+ int typmod;
545
+
546
+ typmod = PQfmod( r->res, col);
547
+ if (typmod == -1 || (typmod - VARHDRSZ) & 0xffff)
548
+ break;
549
+ }
550
+ /* if scale == 0 fall through and return inum */
551
+ case INT8OID:
552
+ case INT4OID:
553
+ case INT2OID:
554
+ case OIDOID:
555
+ return rb_cstr_to_inum( string, 10, 0);
556
+ case FLOAT8OID:
557
+ case FLOAT4OID:
558
+ return rb_float_new( rb_cstr_to_dbl( string, Qfalse));
559
+ case BOOLOID:
560
+ return *string == 't' ? Qtrue : Qfalse;
561
+ /* strchr( "tTyY", *string) != NULL */
562
+ case BYTEAOID:
563
+ return rb_str_new2( string);
564
+ default:
565
+ break;
566
+ }
567
+ ret = pgconn_mkstring( r->conn, string);
568
+ switch (typ) {
569
+ case NUMERICOID:
570
+ return rb_funcall( rb_cBigDecimal, id_new, 1, ret);
571
+ case DATEOID:
572
+ return rb_funcall( rb_cDate, id_parse, 1, ret);
573
+ case TIMEOID:
574
+ case TIMETZOID:
575
+ return rb_funcall( rb_cTime, id_parse, 1, ret);
576
+ case TIMESTAMPOID:
577
+ case TIMESTAMPTZOID:
578
+ return rb_funcall( rb_cDateTime, id_parse, 1, ret);
579
+ case CASHOID:
580
+ return RTEST( pg_currency_class()) ?
581
+ rb_funcall( rb_cCurrency, id_parse, 1, ret) : ret;
582
+ default:
583
+ return ret;
584
+ }
585
+ }
586
+
587
+ /*
588
+ * call-seq:
589
+ * res.num_tuples()
590
+ *
591
+ * Returns the number of tuples (rows) in the query result.
592
+ *
593
+ * Similar to <code>res.rows.length</code> (but faster).
594
+ */
595
+ VALUE
596
+ pgresult_num_tuples( VALUE self)
597
+ {
598
+ struct pgresult_data *r;
599
+
600
+ Data_Get_Struct( self, struct pgresult_data, r);
601
+ return INT2FIX( PQntuples( r->res));
602
+ }
603
+
604
+
605
+
606
+ /*
607
+ * call-seq:
608
+ * res.type( index)
609
+ *
610
+ * Returns the data type associated with the given column number.
611
+ *
612
+ * The integer returned is the internal +OID+ number (in PostgreSQL) of the
613
+ * type. If you have the PostgreSQL source available, you can see the OIDs for
614
+ * every column type in the file <code>src/include/catalog/pg_type.h</code>.
615
+ */
616
+ VALUE
617
+ pgresult_type( VALUE self, VALUE index)
618
+ {
619
+ struct pgresult_data *r;
620
+ int n;
621
+
622
+ Data_Get_Struct( self, struct pgresult_data, r);
623
+ n = PQftype( r->res, NUM2INT( index));
624
+ return n ? INT2FIX( n) : Qnil;
625
+ }
626
+
627
+ /*
628
+ * call-seq:
629
+ * res.size( index)
630
+ *
631
+ * Returns the size of the field type in bytes. Returns <code>-1</code> if the
632
+ * field is variable sized.
633
+ *
634
+ * res = conn.exec "SELECT myInt, myVarChar50 FROM foo"
635
+ * res.size 0 #=> 4
636
+ * res.size 1 #=> -1
637
+ */
638
+ VALUE
639
+ pgresult_size( VALUE self, VALUE index)
640
+ {
641
+ struct pgresult_data *r;
642
+ int n;
643
+
644
+ Data_Get_Struct( self, struct pgresult_data, r);
645
+ n = PQfsize( r->res, NUM2INT( index));
646
+ return n ? INT2FIX( n) : Qnil;
647
+ }
648
+
649
+ /*
650
+ * call-seq:
651
+ * res.value( row, col)
652
+ *
653
+ * Returns the value in tuple number <i>row</i>, field number
654
+ * <i>col</i>. (Row <i>row</i>, column <i>col</i>.)
655
+ *
656
+ * Equivalent to <code>res.row[<i>row</i>][<i>col</i>]</code> (but
657
+ * faster).
658
+ */
659
+ VALUE
660
+ pgresult_getvalue( VALUE self, VALUE row, VALUE col)
661
+ {
662
+ struct pgresult_data *r;
663
+
664
+ Data_Get_Struct( self, struct pgresult_data, r);
665
+ return pg_fetchresult( r, NUM2INT( row), NUM2INT( col));
666
+ }
667
+
668
+
669
+ /*
670
+ * call-seq:
671
+ * res.getlength( row, col) -> int
672
+ *
673
+ * Returns the (String) length of the field in bytes.
674
+ *
675
+ * Equivalent to
676
+ * <code>res.value(<i>row</i>,<i>col</i>).length</code>.
677
+ */
678
+ VALUE
679
+ pgresult_getlength( VALUE self, VALUE row, VALUE col)
680
+ {
681
+ struct pgresult_data *r;
682
+
683
+ Data_Get_Struct( self, struct pgresult_data, r);
684
+ return INT2FIX( PQgetlength( r->res, NUM2INT( row), NUM2INT( col)));
685
+ }
686
+
687
+ /*
688
+ * call-seq:
689
+ * res.getisnull( row, col) -> boolean
690
+ *
691
+ * Returns +true+ if the specified value is +nil+; +false+ otherwise.
692
+ *
693
+ * Equivalent to
694
+ * <code>res.value(<i>row</i>,<i>col</i>)==+nil+</code>.
695
+ */
696
+ VALUE
697
+ pgresult_getisnull( VALUE self, VALUE row, VALUE col)
698
+ {
699
+ struct pgresult_data *r;
700
+
701
+ Data_Get_Struct( self, struct pgresult_data, r);
702
+ return PQgetisnull( r->res, NUM2INT( row), NUM2INT( col)) ? Qtrue : Qfalse;
703
+ }
704
+
705
+ /*
706
+ * call-seq:
707
+ * res.value_byname( row, field_name )
708
+ *
709
+ * Returns the value in tuple number <i>row</i>, for the field named
710
+ * <i>field_name</i>.
711
+ *
712
+ * Equivalent to (but faster than) either of:
713
+ *
714
+ * res.row[<i>row</i>][ res.fieldnum(<i>field_name</i>) ]
715
+ * res.value( <i>row</i>, res.fieldnum(<i>field_name</i>) )
716
+ *
717
+ * <i>(This method internally calls #value as like the second example above;
718
+ * it is slower than using the field index directly.)</i>
719
+ */
720
+ VALUE
721
+ pgresult_getvalue_byname( VALUE self, VALUE row, VALUE field)
722
+ {
723
+ return pgresult_getvalue( self, row, pgresult_fieldnum( self, field));
724
+ }
725
+
726
+
727
+
728
+ /*
729
+ * call-seq:
730
+ * res.cmdtuples()
731
+ *
732
+ * Returns the number of tuples (rows) affected by the SQL command.
733
+ *
734
+ * If the SQL command that generated the Pg::Result was not one of +INSERT+,
735
+ * +UPDATE+, +DELETE+, +MOVE+, or +FETCH+, or if no tuples (rows) were
736
+ * affected, <code>0</code> is returned.
737
+ */
738
+ VALUE
739
+ pgresult_cmdtuples( VALUE self)
740
+ {
741
+ struct pgresult_data *r;
742
+ char *n;
743
+
744
+ Data_Get_Struct( self, struct pgresult_data, r);
745
+ n = PQcmdTuples( r->res);
746
+ return *n ? rb_cstr_to_inum( n, 10, 0) : Qnil;
747
+ }
748
+
749
+ /*
750
+ * call-seq:
751
+ * res.cmdstatus()
752
+ *
753
+ * Returns the status string of the last query command.
754
+ */
755
+ VALUE
756
+ pgresult_cmdstatus( VALUE self)
757
+ {
758
+ struct pgresult_data *r;
759
+ char *n;
760
+
761
+ Data_Get_Struct( self, struct pgresult_data, r);
762
+ n = PQcmdStatus( r->res);
763
+ return n ? pgconn_mkstring( r->conn, n) : Qnil;
764
+ }
765
+
766
+ /*
767
+ * call-seq:
768
+ * res.oid() -> int
769
+ *
770
+ * Returns the +oid+.
771
+ */
772
+ VALUE
773
+ pgresult_oid( VALUE self)
774
+ {
775
+ struct pgresult_data *r;
776
+ Oid n;
777
+
778
+ Data_Get_Struct( self, struct pgresult_data, r);
779
+ n = PQoidValue( r->res);
780
+ return n == InvalidOid ? Qnil : INT2FIX( n);
781
+ }
782
+
783
+
784
+
785
+
786
+ /********************************************************************
787
+ *
788
+ * Document-class: Pg::Result
789
+ *
790
+ * The class to represent the query result tuples (rows).
791
+ * An instance of this class is created as the result of every query.
792
+ * You may need to invoke the #clear method of the instance when finished with
793
+ * the result for better memory performance.
794
+ */
795
+
796
+ /********************************************************************
797
+ *
798
+ * Document-class: Pg::Result::Error
799
+ *
800
+ * The information in a result that is an error.
801
+ */
802
+
803
+ void
804
+ Init_pgsql_result( void)
805
+ {
806
+ rb_require( "bigdecimal");
807
+ rb_cBigDecimal = rb_const_get( rb_cObject, rb_intern( "BigDecimal"));
808
+
809
+ rb_cPgResult = rb_define_class_under( rb_mPg, "Result", rb_cObject);
810
+
811
+
812
+ rb_ePgResError = rb_define_class_under( rb_cPgResult, "Error", rb_ePgError);
813
+ rb_undef_method( CLASS_OF( rb_ePgResError), "new");
814
+
815
+ rb_define_attr( rb_ePgResError, "command", 1, 0);
816
+ rb_define_attr( rb_ePgResError, "parameters", 1, 0);
817
+
818
+ rb_define_method( rb_ePgResError, "status", &pgreserror_status, 0);
819
+ rb_define_method( rb_ePgResError, "sqlstate", &pgreserror_sqlst, 0);
820
+ rb_define_alias( rb_ePgResError, "errcode", "sqlstate");
821
+ rb_define_method( rb_ePgResError, "primary", &pgreserror_primary, 0);
822
+ rb_define_method( rb_ePgResError, "details", &pgreserror_detail, 0);
823
+ rb_define_method( rb_ePgResError, "hint", &pgreserror_hint, 0);
824
+
825
+ rb_define_method( rb_ePgResError, "diag", &pgreserror_diag, 1);
826
+
827
+ #define PGD_DEF( c) rb_define_const( rb_ePgResError, #c, INT2FIX( PG_DIAG_ ## c))
828
+ PGD_DEF( SEVERITY);
829
+ PGD_DEF( SQLSTATE);
830
+ PGD_DEF( MESSAGE_PRIMARY);
831
+ PGD_DEF( MESSAGE_DETAIL);
832
+ PGD_DEF( MESSAGE_HINT);
833
+ PGD_DEF( STATEMENT_POSITION);
834
+ PGD_DEF( INTERNAL_POSITION);
835
+ PGD_DEF( INTERNAL_QUERY);
836
+ PGD_DEF( CONTEXT);
837
+ PGD_DEF( SOURCE_FILE);
838
+ PGD_DEF( SOURCE_LINE);
839
+ PGD_DEF( SOURCE_FUNCTION);
840
+ #undef PGD_DEF
841
+
842
+ rb_define_singleton_method( rb_cPgResult, "translate_results=", pgresult_s_translate_results_set, 1);
843
+
844
+ rb_undef_method( CLASS_OF( rb_cPgResult), "new");
845
+ rb_define_method( rb_cPgResult, "clear", &pgresult_clear, 0);
846
+ rb_define_alias( rb_cPgResult, "close", "clear");
847
+
848
+ rb_define_method( rb_cPgResult, "status", &pgresult_status, 0);
849
+
850
+ rb_define_method( rb_cPgResult, "fields", &pgresult_fields, 0);
851
+ rb_define_method( rb_cPgResult, "field_indices", &pgresult_field_indices, 0);
852
+ rb_define_alias( rb_cPgResult, "indices", "field_indices");
853
+ rb_define_method( rb_cPgResult, "num_fields", &pgresult_num_fields, 0);
854
+ rb_define_method( rb_cPgResult, "fieldname", &pgresult_fieldname, 1);
855
+ rb_define_method( rb_cPgResult, "fieldnum", &pgresult_fieldnum, 1);
856
+
857
+ rb_define_method( rb_cPgResult, "each", &pgresult_each, 0);
858
+ rb_include_module( rb_cPgResult, rb_mEnumerable);
859
+ rb_define_alias( rb_cPgResult, "rows", "entries");
860
+ rb_define_alias( rb_cPgResult, "result", "entries");
861
+ rb_define_method( rb_cPgResult, "[]", &pgresult_aref, -1);
862
+ rb_define_method( rb_cPgResult, "num_tuples", &pgresult_num_tuples, 0);
863
+
864
+ rb_define_method( rb_cPgResult, "type", &pgresult_type, 1);
865
+ rb_define_method( rb_cPgResult, "size", &pgresult_size, 1);
866
+ rb_define_method( rb_cPgResult, "getvalue", &pgresult_getvalue, 2);
867
+ rb_define_method( rb_cPgResult, "getlength", &pgresult_getlength, 2);
868
+ rb_define_method( rb_cPgResult, "getisnull", &pgresult_getisnull, 2);
869
+ rb_define_method( rb_cPgResult, "getvalue_byname", &pgresult_getvalue_byname, 2);
870
+
871
+ #define RESC_DEF( c) rb_define_const( rb_cPgResult, #c, INT2FIX( PGRES_ ## c))
872
+ RESC_DEF( EMPTY_QUERY);
873
+ RESC_DEF( COMMAND_OK);
874
+ RESC_DEF( TUPLES_OK);
875
+ RESC_DEF( COPY_OUT);
876
+ RESC_DEF( COPY_IN);
877
+ RESC_DEF( BAD_RESPONSE);
878
+ RESC_DEF( NONFATAL_ERROR);
879
+ RESC_DEF( FATAL_ERROR);
880
+ #undef RESC_DEF
881
+
882
+ rb_define_method( rb_cPgResult, "cmdtuples", &pgresult_cmdtuples, 0);
883
+ rb_define_method( rb_cPgResult, "cmdstatus", &pgresult_cmdstatus, 0);
884
+ rb_define_method( rb_cPgResult, "oid", &pgresult_oid, 0);
885
+
886
+
887
+ id_new = rb_intern( "new");
888
+ id_parse = rb_intern( "parse");
889
+ id_result = rb_intern( "result");
890
+ }
891
+