pg 1.4.6 → 1.6.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/{History.md → CHANGELOG.md} +185 -3
- data/Gemfile +12 -3
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +75 -41
- data/README.md +86 -31
- data/Rakefile +95 -14
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +4 -5
- data/ext/errorcodes.txt +2 -5
- data/ext/extconf.rb +165 -14
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +33 -0
- data/ext/pg.c +28 -35
- data/ext/pg.h +18 -14
- data/ext/pg_binary_decoder.c +231 -0
- data/ext/pg_binary_encoder.c +427 -0
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +70 -12
- data/ext/pg_connection.c +473 -208
- data/ext/pg_copy_coder.c +316 -23
- data/ext/pg_record_coder.c +12 -11
- data/ext/pg_result.c +102 -30
- data/ext/pg_text_decoder.c +31 -10
- data/ext/pg_text_encoder.c +58 -26
- data/ext/pg_tuple.c +36 -33
- data/ext/pg_type_map.c +4 -3
- data/ext/pg_type_map_all_strings.c +3 -3
- data/ext/pg_type_map_by_class.c +6 -4
- data/ext/pg_type_map_by_column.c +9 -4
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +10 -5
- data/ext/pg_type_map_in_ruby.c +6 -3
- data/lib/pg/basic_type_map_based_on_result.rb +21 -1
- data/lib/pg/basic_type_map_for_queries.rb +23 -10
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +46 -36
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +18 -14
- data/lib/pg/connection.rb +387 -172
- data/lib/pg/exceptions.rb +6 -0
- data/lib/pg/text_decoder/date.rb +21 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +17 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +13 -0
- data/lib/pg/text_encoder/inet.rb +31 -0
- data/lib/pg/text_encoder/json.rb +17 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +78 -17
- data/misc/yugabyte/Dockerfile +9 -0
- data/misc/yugabyte/docker-compose.yml +28 -0
- data/misc/yugabyte/pg-test.rb +45 -0
- data/pg.gemspec +9 -5
- data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
- data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data.tar.gz.sig +0 -0
- metadata +61 -49
- metadata.gz.sig +0 -0
- data/.appveyor.yml +0 -42
- data/.gems +0 -6
- data/.gemtest +0 -0
- data/.github/workflows/binary-gems.yml +0 -117
- data/.github/workflows/source-gem.yml +0 -137
- data/.gitignore +0 -19
- data/.hgsigs +0 -34
- data/.hgtags +0 -41
- data/.irbrc +0 -23
- data/.pryrc +0 -23
- data/.tm_properties +0 -21
- data/.travis.yml +0 -49
- data/Manifest.txt +0 -72
- data/Rakefile.cross +0 -298
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
- data/translation/.po4a-version +0 -7
- data/translation/po/all.pot +0 -875
- data/translation/po/ja.po +0 -868
- data/translation/po4a.cfg +0 -9
data/ext/pg_result.c
CHANGED
@@ -147,9 +147,7 @@ pgresult_clear( void *_this )
|
|
147
147
|
t_pg_result *this = (t_pg_result *)_this;
|
148
148
|
if( this->pgresult && !this->autoclear ){
|
149
149
|
PQclear(this->pgresult);
|
150
|
-
#ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
|
151
150
|
rb_gc_adjust_memory_usage(-this->result_size);
|
152
|
-
#endif
|
153
151
|
}
|
154
152
|
this->result_size = 0;
|
155
153
|
this->nfields = -1;
|
@@ -180,10 +178,10 @@ static const rb_data_type_t pgresult_type = {
|
|
180
178
|
pgresult_gc_mark,
|
181
179
|
pgresult_gc_free,
|
182
180
|
pgresult_memsize,
|
183
|
-
|
181
|
+
pgresult_gc_compact,
|
184
182
|
},
|
185
183
|
0, 0,
|
186
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
184
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
187
185
|
};
|
188
186
|
|
189
187
|
/* Needed by sequel_pg gem, do not delete */
|
@@ -208,6 +206,8 @@ pg_new_result2(PGresult *result, VALUE rb_pgconn)
|
|
208
206
|
|
209
207
|
this = (t_pg_result *)xmalloc(sizeof(*this) + sizeof(*this->fnames) * nfields);
|
210
208
|
this->pgresult = result;
|
209
|
+
/* Initialize connection and typemap prior to any object allocations,
|
210
|
+
* to make sure valid objects are marked. */
|
211
211
|
this->connection = rb_pgconn;
|
212
212
|
this->typemap = pg_typemap_all_strings;
|
213
213
|
this->p_typemap = RTYPEDDATA_DATA( this->typemap );
|
@@ -224,7 +224,8 @@ pg_new_result2(PGresult *result, VALUE rb_pgconn)
|
|
224
224
|
t_typemap *p_typemap = RTYPEDDATA_DATA(typemap);
|
225
225
|
|
226
226
|
this->enc_idx = p_conn->enc_idx;
|
227
|
-
|
227
|
+
typemap = p_typemap->funcs.fit_to_result( typemap, self );
|
228
|
+
RB_OBJ_WRITE(self, &this->typemap, typemap);
|
228
229
|
this->p_typemap = RTYPEDDATA_DATA( this->typemap );
|
229
230
|
this->flags = p_conn->flags;
|
230
231
|
} else {
|
@@ -250,9 +251,7 @@ pg_new_result(PGresult *result, VALUE rb_pgconn)
|
|
250
251
|
*/
|
251
252
|
this->result_size = pgresult_approx_size(result);
|
252
253
|
|
253
|
-
#ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
|
254
254
|
rb_gc_adjust_memory_usage(this->result_size);
|
255
|
-
#endif
|
256
255
|
|
257
256
|
return self;
|
258
257
|
}
|
@@ -320,6 +319,9 @@ pg_result_check( VALUE self )
|
|
320
319
|
case PGRES_COMMAND_OK:
|
321
320
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
322
321
|
case PGRES_PIPELINE_SYNC:
|
322
|
+
#endif
|
323
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
324
|
+
case PGRES_TUPLES_CHUNK:
|
323
325
|
#endif
|
324
326
|
return self;
|
325
327
|
case PGRES_BAD_RESPONSE:
|
@@ -374,17 +376,37 @@ VALUE
|
|
374
376
|
pg_result_clear(VALUE self)
|
375
377
|
{
|
376
378
|
t_pg_result *this = pgresult_get_this(self);
|
379
|
+
rb_check_frozen(self);
|
377
380
|
pgresult_clear( this );
|
378
381
|
return Qnil;
|
379
382
|
}
|
380
383
|
|
384
|
+
/*
|
385
|
+
* call-seq:
|
386
|
+
* res.freeze
|
387
|
+
*
|
388
|
+
* Freeze the PG::Result object and unlink the result from the related PG::Connection.
|
389
|
+
*
|
390
|
+
* A frozen PG::Result object doesn't allow any streaming and it can't be cleared.
|
391
|
+
* It also denies setting a type_map or field_name_type.
|
392
|
+
*
|
393
|
+
*/
|
394
|
+
static VALUE
|
395
|
+
pg_result_freeze(VALUE self)
|
396
|
+
{
|
397
|
+
t_pg_result *this = pgresult_get_this(self);
|
398
|
+
|
399
|
+
RB_OBJ_WRITE(self, &this->connection, Qnil);
|
400
|
+
return rb_call_super(0, NULL);
|
401
|
+
}
|
402
|
+
|
381
403
|
/*
|
382
404
|
* call-seq:
|
383
405
|
* res.cleared? -> boolean
|
384
406
|
*
|
385
407
|
* Returns +true+ if the backend result memory has been freed.
|
386
408
|
*/
|
387
|
-
VALUE
|
409
|
+
static VALUE
|
388
410
|
pgresult_cleared_p( VALUE self )
|
389
411
|
{
|
390
412
|
t_pg_result *this = pgresult_get_this(self);
|
@@ -401,7 +423,7 @@ pgresult_cleared_p( VALUE self )
|
|
401
423
|
* All other Result objects are automatically cleared by the GC when the object is no longer in use or manually by PG::Result#clear .
|
402
424
|
*
|
403
425
|
*/
|
404
|
-
VALUE
|
426
|
+
static VALUE
|
405
427
|
pgresult_autoclear_p( VALUE self )
|
406
428
|
{
|
407
429
|
t_pg_result *this = pgresult_get_this(self);
|
@@ -477,7 +499,8 @@ static void pgresult_init_fnames(VALUE self)
|
|
477
499
|
|
478
500
|
for( i=0; i<nfields; i++ ){
|
479
501
|
char *cfname = PQfname(this->pgresult, i);
|
480
|
-
|
502
|
+
VALUE fname = pg_cstr_to_sym(cfname, this->flags, this->enc_idx);
|
503
|
+
RB_OBJ_WRITE(self, &this->fnames[i], fname);
|
481
504
|
this->nfields = i + 1;
|
482
505
|
}
|
483
506
|
this->nfields = nfields;
|
@@ -525,8 +548,11 @@ static void pgresult_init_fnames(VALUE self)
|
|
525
548
|
* * +PGRES_FATAL_ERROR+
|
526
549
|
* * +PGRES_COPY_BOTH+
|
527
550
|
* * +PGRES_SINGLE_TUPLE+
|
551
|
+
* * +PGRES_TUPLES_CHUNK+
|
528
552
|
* * +PGRES_PIPELINE_SYNC+
|
529
553
|
* * +PGRES_PIPELINE_ABORTED+
|
554
|
+
*
|
555
|
+
* Use <tt>res.res_status</tt> to retrieve the string representation.
|
530
556
|
*/
|
531
557
|
static VALUE
|
532
558
|
pgresult_result_status(VALUE self)
|
@@ -536,16 +562,38 @@ pgresult_result_status(VALUE self)
|
|
536
562
|
|
537
563
|
/*
|
538
564
|
* call-seq:
|
539
|
-
*
|
565
|
+
* PG::Result.res_status( status ) -> String
|
540
566
|
*
|
541
567
|
* Returns the string representation of +status+.
|
542
568
|
*
|
543
569
|
*/
|
544
570
|
static VALUE
|
545
|
-
|
571
|
+
pgresult_s_res_status(VALUE self, VALUE status)
|
572
|
+
{
|
573
|
+
return rb_utf8_str_new_cstr(PQresStatus(NUM2INT(status)));
|
574
|
+
}
|
575
|
+
|
576
|
+
/*
|
577
|
+
* call-seq:
|
578
|
+
* res.res_status -> String
|
579
|
+
* res.res_status( status ) -> String
|
580
|
+
*
|
581
|
+
* Returns the string representation of the status of the result or of the provided +status+.
|
582
|
+
*
|
583
|
+
*/
|
584
|
+
static VALUE
|
585
|
+
pgresult_res_status(int argc, VALUE *argv, VALUE self)
|
546
586
|
{
|
547
587
|
t_pg_result *this = pgresult_get_this_safe(self);
|
548
|
-
VALUE ret
|
588
|
+
VALUE ret;
|
589
|
+
|
590
|
+
if( argc == 0 ){
|
591
|
+
ret = rb_str_new2(PQresStatus(PQresultStatus(this->pgresult)));
|
592
|
+
}else if( argc == 1 ){
|
593
|
+
ret = rb_str_new2(PQresStatus(NUM2INT(argv[0])));
|
594
|
+
}else{
|
595
|
+
rb_raise(rb_eArgError, "only 0 or 1 arguments expected");
|
596
|
+
}
|
549
597
|
PG_ENCODING_SET_NOCHECK(ret, this->enc_idx);
|
550
598
|
return ret;
|
551
599
|
}
|
@@ -565,14 +613,12 @@ pgresult_error_message(VALUE self)
|
|
565
613
|
return ret;
|
566
614
|
}
|
567
615
|
|
568
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
569
616
|
/*
|
570
617
|
* call-seq:
|
571
618
|
* res.verbose_error_message( verbosity, show_context ) -> String
|
572
619
|
*
|
573
620
|
* Returns a reformatted version of the error message associated with a PGresult object.
|
574
621
|
*
|
575
|
-
* Available since PostgreSQL-9.6
|
576
622
|
*/
|
577
623
|
static VALUE
|
578
624
|
pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
@@ -591,7 +637,6 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
591
637
|
|
592
638
|
return ret;
|
593
639
|
}
|
594
|
-
#endif
|
595
640
|
|
596
641
|
/*
|
597
642
|
* call-seq:
|
@@ -616,7 +661,7 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
616
661
|
* An example:
|
617
662
|
*
|
618
663
|
* begin
|
619
|
-
* conn.exec( "SELECT * FROM
|
664
|
+
* conn.exec( "SELECT * FROM nonexistent_table" )
|
620
665
|
* rescue PG::Error => err
|
621
666
|
* p [
|
622
667
|
* err.result.error_field( PG::Result::PG_DIAG_SEVERITY ),
|
@@ -636,7 +681,7 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
636
681
|
*
|
637
682
|
* Outputs:
|
638
683
|
*
|
639
|
-
* ["ERROR", "42P01", "relation \"
|
684
|
+
* ["ERROR", "42P01", "relation \"nonexistent_table\" does not exist", nil, nil,
|
640
685
|
* "15", nil, nil, nil, "path/to/parse_relation.c", "857", "parserOpenTable"]
|
641
686
|
*/
|
642
687
|
static VALUE
|
@@ -685,6 +730,21 @@ pgresult_nfields(VALUE self)
|
|
685
730
|
return INT2NUM(PQnfields(pgresult_get(self)));
|
686
731
|
}
|
687
732
|
|
733
|
+
/*
|
734
|
+
* call-seq:
|
735
|
+
* res.binary_tuples() -> Integer
|
736
|
+
*
|
737
|
+
* Returns 1 if the PGresult contains binary data and 0 if it contains text data.
|
738
|
+
*
|
739
|
+
* This function is deprecated (except for its use in connection with COPY), because it is possible for a single PGresult to contain text data in some columns and binary data in others.
|
740
|
+
* Result#fformat is preferred. binary_tuples returns 1 only if all columns of the result are binary (format 1).
|
741
|
+
*/
|
742
|
+
static VALUE
|
743
|
+
pgresult_binary_tuples(VALUE self)
|
744
|
+
{
|
745
|
+
return INT2NUM(PQbinaryTuples(pgresult_get(self)));
|
746
|
+
}
|
747
|
+
|
688
748
|
/*
|
689
749
|
* call-seq:
|
690
750
|
* res.fname( index ) -> String or Symbol
|
@@ -1087,7 +1147,7 @@ pgresult_aref(VALUE self, VALUE index)
|
|
1087
1147
|
}
|
1088
1148
|
/* Store a copy of the filled hash for use at the next row. */
|
1089
1149
|
if( num_tuples > 10 )
|
1090
|
-
this->tuple_hash
|
1150
|
+
RB_OBJ_WRITE(self, &this->tuple_hash, rb_hash_dup(tuple));
|
1091
1151
|
|
1092
1152
|
return tuple;
|
1093
1153
|
}
|
@@ -1269,7 +1329,7 @@ static void ensure_init_for_tuple(VALUE self)
|
|
1269
1329
|
rb_hash_aset(field_map, this->fnames[i], INT2FIX(i));
|
1270
1330
|
}
|
1271
1331
|
rb_obj_freeze(field_map);
|
1272
|
-
this->field_map
|
1332
|
+
RB_OBJ_WRITE(self, &this->field_map, field_map);
|
1273
1333
|
}
|
1274
1334
|
}
|
1275
1335
|
|
@@ -1357,11 +1417,13 @@ pgresult_type_map_set(VALUE self, VALUE typemap)
|
|
1357
1417
|
t_pg_result *this = pgresult_get_this(self);
|
1358
1418
|
t_typemap *p_typemap;
|
1359
1419
|
|
1420
|
+
rb_check_frozen(self);
|
1360
1421
|
/* Check type of method param */
|
1361
1422
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, p_typemap);
|
1362
1423
|
|
1363
|
-
|
1364
|
-
|
1424
|
+
typemap = p_typemap->funcs.fit_to_result( typemap, self );
|
1425
|
+
RB_OBJ_WRITE(self, &this->typemap, typemap);
|
1426
|
+
this->p_typemap = RTYPEDDATA_DATA( typemap );
|
1365
1427
|
|
1366
1428
|
return typemap;
|
1367
1429
|
}
|
@@ -1441,10 +1503,11 @@ VALUE
|
|
1441
1503
|
pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* data)
|
1442
1504
|
{
|
1443
1505
|
t_pg_result *this;
|
1444
|
-
int nfields;
|
1506
|
+
int nfields, nfields2;
|
1445
1507
|
PGconn *pgconn;
|
1446
1508
|
PGresult *pgresult;
|
1447
1509
|
|
1510
|
+
rb_check_frozen(self);
|
1448
1511
|
RETURN_ENUMERATOR(self, 0, NULL);
|
1449
1512
|
|
1450
1513
|
this = pgresult_get_this_safe(self);
|
@@ -1462,11 +1525,20 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1462
1525
|
return self;
|
1463
1526
|
rb_raise( rb_eInvalidResultStatus, "PG::Result is not in single row mode");
|
1464
1527
|
case PGRES_SINGLE_TUPLE:
|
1528
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
1529
|
+
case PGRES_TUPLES_CHUNK:
|
1530
|
+
#endif
|
1465
1531
|
break;
|
1466
1532
|
default:
|
1467
1533
|
pg_result_check( self );
|
1468
1534
|
}
|
1469
1535
|
|
1536
|
+
nfields2 = PQnfields(pgresult);
|
1537
|
+
if( nfields != nfields2 ){
|
1538
|
+
pgresult_clear( this );
|
1539
|
+
rb_raise( rb_eInvalidChangeOfResultFields, "number of fields changed in single row mode from %d to %d - this is a sign for intersection with another query", nfields, nfields2);
|
1540
|
+
}
|
1541
|
+
|
1470
1542
|
if( yielder( self, ntuples, nfields, data ) ){
|
1471
1543
|
pgresult_clear( this );
|
1472
1544
|
}
|
@@ -1480,9 +1552,6 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1480
1552
|
if( pgresult == NULL )
|
1481
1553
|
rb_raise( rb_eNoResultError, "no result received - possibly an intersection with another query");
|
1482
1554
|
|
1483
|
-
if( nfields != PQnfields(pgresult) )
|
1484
|
-
rb_raise( rb_eInvalidChangeOfResultFields, "number of fields changed in single row mode from %d to %d - this is a sign for intersection with another query", nfields, PQnfields(pgresult));
|
1485
|
-
|
1486
1555
|
this->pgresult = pgresult;
|
1487
1556
|
}
|
1488
1557
|
|
@@ -1503,7 +1572,7 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1503
1572
|
* wrapping each row into a dedicated result object, it delivers data in nearly
|
1504
1573
|
* the same speed as with ordinary results.
|
1505
1574
|
*
|
1506
|
-
* The base result must be in status PGRES_SINGLE_TUPLE.
|
1575
|
+
* The base result must be in status PGRES_SINGLE_TUPLE or PGRES_TUPLES_CHUNK.
|
1507
1576
|
* It iterates over all tuples until the status changes to PGRES_TUPLES_OK.
|
1508
1577
|
* A PG::Error is raised for any errors from the server.
|
1509
1578
|
*
|
@@ -1586,6 +1655,8 @@ static VALUE
|
|
1586
1655
|
pgresult_field_name_type_set(VALUE self, VALUE sym)
|
1587
1656
|
{
|
1588
1657
|
t_pg_result *this = pgresult_get_this(self);
|
1658
|
+
|
1659
|
+
rb_check_frozen(self);
|
1589
1660
|
if( this->nfields != -1 ) rb_raise(rb_eArgError, "field names are already materialized");
|
1590
1661
|
|
1591
1662
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
@@ -1632,22 +1703,23 @@ init_pg_result(void)
|
|
1632
1703
|
|
1633
1704
|
/****** PG::Result INSTANCE METHODS: libpq ******/
|
1634
1705
|
rb_define_method(rb_cPGresult, "result_status", pgresult_result_status, 0);
|
1635
|
-
rb_define_method(rb_cPGresult, "res_status", pgresult_res_status, 1);
|
1706
|
+
rb_define_method(rb_cPGresult, "res_status", pgresult_res_status, -1);
|
1707
|
+
rb_define_singleton_method(rb_cPGresult, "res_status", pgresult_s_res_status, 1);
|
1636
1708
|
rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
|
1637
1709
|
rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
|
1638
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
1639
1710
|
rb_define_method(rb_cPGresult, "verbose_error_message", pgresult_verbose_error_message, 2);
|
1640
1711
|
rb_define_alias( rb_cPGresult, "result_verbose_error_message", "verbose_error_message");
|
1641
|
-
#endif
|
1642
1712
|
rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
|
1643
1713
|
rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
|
1644
1714
|
rb_define_method(rb_cPGresult, "clear", pg_result_clear, 0);
|
1715
|
+
rb_define_method(rb_cPGresult, "freeze", pg_result_freeze, 0 );
|
1645
1716
|
rb_define_method(rb_cPGresult, "check", pg_result_check, 0);
|
1646
1717
|
rb_define_alias (rb_cPGresult, "check_result", "check");
|
1647
1718
|
rb_define_method(rb_cPGresult, "ntuples", pgresult_ntuples, 0);
|
1648
1719
|
rb_define_alias(rb_cPGresult, "num_tuples", "ntuples");
|
1649
1720
|
rb_define_method(rb_cPGresult, "nfields", pgresult_nfields, 0);
|
1650
1721
|
rb_define_alias(rb_cPGresult, "num_fields", "nfields");
|
1722
|
+
rb_define_method(rb_cPGresult, "binary_tuples", pgresult_binary_tuples, 0);
|
1651
1723
|
rb_define_method(rb_cPGresult, "fname", pgresult_fname, 1);
|
1652
1724
|
rb_define_method(rb_cPGresult, "fnumber", pgresult_fnumber, 1);
|
1653
1725
|
rb_define_method(rb_cPGresult, "ftable", pgresult_ftable, 1);
|
data/ext/pg_text_decoder.c
CHANGED
@@ -43,7 +43,6 @@
|
|
43
43
|
#include <string.h>
|
44
44
|
|
45
45
|
VALUE rb_mPG_TextDecoder;
|
46
|
-
static ID s_id_decode;
|
47
46
|
static ID s_id_Rational;
|
48
47
|
static ID s_id_new;
|
49
48
|
static ID s_id_utc;
|
@@ -164,6 +163,8 @@ pg_text_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int f
|
|
164
163
|
* This is a decoder class for conversion of PostgreSQL numeric types
|
165
164
|
* to Ruby BigDecimal objects.
|
166
165
|
*
|
166
|
+
* As soon as this class is used, it requires the 'bigdecimal' gem.
|
167
|
+
*
|
167
168
|
*/
|
168
169
|
static VALUE
|
169
170
|
pg_text_dec_numeric(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
@@ -171,6 +172,19 @@ pg_text_dec_numeric(t_pg_coder *conv, const char *val, int len, int tuple, int f
|
|
171
172
|
return rb_funcall(rb_cObject, s_id_BigDecimal, 1, rb_str_new(val, len));
|
172
173
|
}
|
173
174
|
|
175
|
+
/* called per autoload when TextDecoder::Numeric is used */
|
176
|
+
static VALUE
|
177
|
+
init_pg_text_decoder_numeric(VALUE rb_mPG_TextDecoder)
|
178
|
+
{
|
179
|
+
rb_funcall(rb_mPG, rb_intern("require_bigdecimal_without_warning"), 0);
|
180
|
+
s_id_BigDecimal = rb_intern("BigDecimal");
|
181
|
+
|
182
|
+
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Numeric", rb_cPG_SimpleDecoder ); */
|
183
|
+
pg_define_coder( "Numeric", pg_text_dec_numeric, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
|
184
|
+
|
185
|
+
return Qnil;
|
186
|
+
}
|
187
|
+
|
174
188
|
/*
|
175
189
|
* Document-class: PG::TextDecoder::Float < PG::SimpleDecoder
|
176
190
|
*
|
@@ -799,6 +813,7 @@ static VALUE pg_text_dec_timestamp(t_pg_coder *conv, const char *val, int len, i
|
|
799
813
|
* This is a decoder class for conversion of PostgreSQL inet type
|
800
814
|
* to Ruby IPAddr values.
|
801
815
|
*
|
816
|
+
* As soon as this class is used, it requires the ruby standard library 'ipaddr'.
|
802
817
|
*/
|
803
818
|
static VALUE
|
804
819
|
pg_text_dec_inet(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
@@ -922,8 +937,9 @@ pg_text_dec_inet(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
|
|
922
937
|
return ip;
|
923
938
|
}
|
924
939
|
|
925
|
-
|
926
|
-
|
940
|
+
/* called per autoload when TextDecoder::Inet is used */
|
941
|
+
static VALUE
|
942
|
+
init_pg_text_decoder_inet(VALUE rb_mPG_TextDecoder)
|
927
943
|
{
|
928
944
|
rb_require("ipaddr");
|
929
945
|
s_IPAddr = rb_funcall(rb_cObject, rb_intern("const_get"), 1, rb_str_new2("IPAddr"));
|
@@ -942,14 +958,21 @@ init_pg_text_decoder(void)
|
|
942
958
|
s_vmasks6 = rb_eval_string("a = [0]*129; a[0] = 0; a[128] = 0xffffffffffffffffffffffffffffffff; 127.downto(1){|i| a[i] = a[i+1] - (1 << (127 - i))}; a.freeze");
|
943
959
|
rb_global_variable(&s_vmasks6);
|
944
960
|
|
945
|
-
|
961
|
+
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Inet", rb_cPG_SimpleDecoder ); */
|
962
|
+
pg_define_coder( "Inet", pg_text_dec_inet, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder);
|
963
|
+
|
964
|
+
return Qnil;
|
965
|
+
}
|
966
|
+
|
967
|
+
|
968
|
+
void
|
969
|
+
init_pg_text_decoder(void)
|
970
|
+
{
|
946
971
|
s_id_Rational = rb_intern("Rational");
|
947
972
|
s_id_new = rb_intern("new");
|
948
973
|
s_id_utc = rb_intern("utc");
|
949
974
|
s_id_getlocal = rb_intern("getlocal");
|
950
975
|
|
951
|
-
rb_require("bigdecimal");
|
952
|
-
s_id_BigDecimal = rb_intern("BigDecimal");
|
953
976
|
s_nan = rb_eval_string("0.0/0.0");
|
954
977
|
rb_global_variable(&s_nan);
|
955
978
|
s_pos_inf = rb_eval_string("1.0/0.0");
|
@@ -959,6 +982,8 @@ init_pg_text_decoder(void)
|
|
959
982
|
|
960
983
|
/* This module encapsulates all decoder classes with text input format */
|
961
984
|
rb_mPG_TextDecoder = rb_define_module_under( rb_mPG, "TextDecoder" );
|
985
|
+
rb_define_private_method(rb_singleton_class(rb_mPG_TextDecoder), "init_inet", init_pg_text_decoder_inet, 0);
|
986
|
+
rb_define_private_method(rb_singleton_class(rb_mPG_TextDecoder), "init_numeric", init_pg_text_decoder_numeric, 0);
|
962
987
|
|
963
988
|
/* Make RDoc aware of the decoder classes... */
|
964
989
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Boolean", rb_cPG_SimpleDecoder ); */
|
@@ -967,8 +992,6 @@ init_pg_text_decoder(void)
|
|
967
992
|
pg_define_coder( "Integer", pg_text_dec_integer, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
|
968
993
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Float", rb_cPG_SimpleDecoder ); */
|
969
994
|
pg_define_coder( "Float", pg_text_dec_float, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
|
970
|
-
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Numeric", rb_cPG_SimpleDecoder ); */
|
971
|
-
pg_define_coder( "Numeric", pg_text_dec_numeric, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
|
972
995
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "String", rb_cPG_SimpleDecoder ); */
|
973
996
|
pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
|
974
997
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
|
@@ -977,8 +1000,6 @@ init_pg_text_decoder(void)
|
|
977
1000
|
pg_define_coder( "Identifier", pg_text_dec_identifier, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
|
978
1001
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */
|
979
1002
|
pg_define_coder( "Timestamp", pg_text_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder);
|
980
|
-
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Inet", rb_cPG_SimpleDecoder ); */
|
981
|
-
pg_define_coder( "Inet", pg_text_dec_inet, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder);
|
982
1003
|
|
983
1004
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Array", rb_cPG_CompositeDecoder ); */
|
984
1005
|
pg_define_coder( "Array", pg_text_dec_array, rb_cPG_CompositeDecoder, rb_mPG_TextDecoder );
|