pg 1.6.3 → 1.7.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +52 -6
- data/Gemfile +1 -0
- data/README.ja.md +81 -30
- data/README.md +14 -7
- data/Rakefile +8 -7
- data/certs/larskanis-2026.pem +24 -0
- data/ext/extconf.rb +18 -28
- data/ext/gvl_wrappers.c +2 -2
- data/ext/gvl_wrappers.h +40 -160
- data/ext/pg.c +8 -12
- data/ext/pg.h +8 -11
- data/ext/pg_binary_decoder.c +6 -2
- data/ext/pg_binary_encoder.c +7 -0
- data/ext/pg_cancel_connection.c +6 -6
- data/ext/pg_coder.c +4 -4
- data/ext/pg_connection.c +196 -159
- data/ext/pg_copy_coder.c +34 -21
- data/ext/pg_record_coder.c +10 -6
- data/ext/pg_result.c +42 -26
- data/ext/pg_text_decoder.c +6 -6
- data/ext/pg_text_encoder.c +7 -2
- data/ext/pg_tuple.c +1 -1
- data/ext/pg_type_map.c +41 -1
- data/ext/pg_type_map_all_strings.c +2 -2
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +2 -2
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/lib/pg/basic_type_map_based_on_result.rb +5 -0
- data/lib/pg/basic_type_map_for_queries.rb +9 -2
- data/lib/pg/basic_type_map_for_results.rb +5 -0
- data/lib/pg/connection.rb +166 -76
- data/lib/pg/text_decoder/date.rb +1 -1
- data/lib/pg/text_decoder/json.rb +1 -1
- data/lib/pg/text_encoder/date.rb +7 -1
- data/lib/pg/text_encoder/json.rb +1 -1
- data/lib/pg/version.rb +1 -1
- data/misc/yugabyte/docker-compose.yml +1 -1
- data/pg.gemspec +1 -1
- data/sample/async_mixed.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +18 -19
- metadata.gz.sig +0 -0
- data/ports/patches/openssl/3.5.2/0001-aarch64-mingw.patch +0 -21
- data/ports/patches/postgresql/18.1/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +0 -52
- /data/ports/patches/krb5/{1.22.1 → 1.22.2}/0001-Allow-static-linking-krb5-library.patch +0 -0
- /data/ports/patches/krb5/{1.22.1 → 1.22.2}/0002-unknown-command-line-option-on-clang.patch +0 -0
- /data/ports/patches/postgresql/{18.1 → 18.6}/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +0 -0
data/ext/pg_copy_coder.c
CHANGED
|
@@ -55,7 +55,7 @@ static const rb_data_type_t pg_copycoder_type = {
|
|
|
55
55
|
},
|
|
56
56
|
&pg_coder_type,
|
|
57
57
|
0,
|
|
58
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
58
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
static VALUE
|
|
@@ -219,20 +219,21 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
219
219
|
{
|
|
220
220
|
t_pg_copycoder *this = (t_pg_copycoder *)conv;
|
|
221
221
|
t_pg_coder_enc_func enc_func;
|
|
222
|
-
|
|
222
|
+
t_pg_coder *p_elem_coder;
|
|
223
223
|
int i;
|
|
224
|
+
VALUE rb_typemap = this->typemap;
|
|
224
225
|
t_typemap *p_typemap;
|
|
225
226
|
char *current_out;
|
|
226
227
|
char *end_capa_ptr;
|
|
227
228
|
|
|
228
|
-
p_typemap = RTYPEDDATA_DATA(
|
|
229
|
-
p_typemap->funcs.fit_to_query(
|
|
229
|
+
p_typemap = RTYPEDDATA_DATA( rb_typemap );
|
|
230
|
+
p_typemap->funcs.fit_to_query( rb_typemap, value );
|
|
230
231
|
|
|
231
232
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
|
232
233
|
PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
|
|
233
234
|
PG_ENCODING_SET_NOCHECK(*intermediate, enc_idx);
|
|
234
235
|
|
|
235
|
-
for( i=0; i<
|
|
236
|
+
for( i=0; i<RARRAY_LENINT(value); i++){
|
|
236
237
|
char *ptr1;
|
|
237
238
|
char *ptr2;
|
|
238
239
|
int strlen;
|
|
@@ -265,7 +266,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
265
266
|
strlen = RSTRING_LENINT(subint);
|
|
266
267
|
|
|
267
268
|
/* size of string assuming the worst case, that every character must be escaped. */
|
|
268
|
-
PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
|
|
269
|
+
PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)strlen * 2, current_out, end_capa_ptr );
|
|
269
270
|
|
|
270
271
|
/* Copy string from subint with backslash escaping */
|
|
271
272
|
for(ptr1 = RSTRING_PTR(subint); ptr1 < RSTRING_PTR(subint) + strlen; ptr1++) {
|
|
@@ -278,7 +279,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
278
279
|
} else {
|
|
279
280
|
/* 2nd pass for writing the data to prepared buffer */
|
|
280
281
|
/* size of string assuming the worst case, that every character must be escaped. */
|
|
281
|
-
PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
|
|
282
|
+
PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)strlen * 2, current_out, end_capa_ptr );
|
|
282
283
|
|
|
283
284
|
/* Place the unescaped string at current output position. */
|
|
284
285
|
strlen = enc_func(p_elem_coder, entry, current_out, &subint, enc_idx);
|
|
@@ -314,6 +315,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
314
315
|
|
|
315
316
|
rb_str_set_len( *intermediate, current_out - RSTRING_PTR(*intermediate) );
|
|
316
317
|
|
|
318
|
+
RB_GC_GUARD(rb_typemap);
|
|
317
319
|
return -1;
|
|
318
320
|
}
|
|
319
321
|
|
|
@@ -366,12 +368,17 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat
|
|
|
366
368
|
{
|
|
367
369
|
t_pg_copycoder *this = (t_pg_copycoder *)conv;
|
|
368
370
|
int i;
|
|
371
|
+
VALUE rb_typemap = this->typemap;
|
|
369
372
|
t_typemap *p_typemap;
|
|
370
373
|
char *current_out;
|
|
371
374
|
char *end_capa_ptr;
|
|
372
375
|
|
|
373
|
-
|
|
374
|
-
|
|
376
|
+
if( RARRAY_LEN(value) >= 32768 ){
|
|
377
|
+
rb_raise( rb_eArgError, "too many columns in array for PG::BinaryEncoder::CopyRow: %ld", RARRAY_LEN(value) );
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
p_typemap = RTYPEDDATA_DATA( rb_typemap );
|
|
381
|
+
p_typemap->funcs.fit_to_query( rb_typemap, value );
|
|
375
382
|
|
|
376
383
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
|
377
384
|
PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
|
|
@@ -382,12 +389,12 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat
|
|
|
382
389
|
write_nbo16(RARRAY_LEN(value), current_out);
|
|
383
390
|
current_out += 2;
|
|
384
391
|
|
|
385
|
-
for( i=0; i<
|
|
392
|
+
for( i=0; i<RARRAY_LENINT(value); i++){
|
|
386
393
|
int strlen;
|
|
387
394
|
VALUE subint;
|
|
388
395
|
VALUE entry;
|
|
389
396
|
t_pg_coder_enc_func enc_func;
|
|
390
|
-
|
|
397
|
+
t_pg_coder *p_elem_coder;
|
|
391
398
|
|
|
392
399
|
entry = rb_ary_entry(value, i);
|
|
393
400
|
|
|
@@ -409,7 +416,7 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat
|
|
|
409
416
|
/* we can directly use String value in subint */
|
|
410
417
|
strlen = RSTRING_LENINT(subint);
|
|
411
418
|
|
|
412
|
-
PG_RB_STR_ENSURE_CAPA( *intermediate, 4 + strlen, current_out, end_capa_ptr );
|
|
419
|
+
PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)4 + strlen, current_out, end_capa_ptr );
|
|
413
420
|
/* 4 bytes length */
|
|
414
421
|
write_nbo32(strlen, current_out);
|
|
415
422
|
current_out += 4;
|
|
@@ -418,7 +425,7 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat
|
|
|
418
425
|
current_out += strlen;
|
|
419
426
|
} else {
|
|
420
427
|
/* 2nd pass for writing the data to prepared buffer */
|
|
421
|
-
PG_RB_STR_ENSURE_CAPA( *intermediate, 4 + strlen, current_out, end_capa_ptr );
|
|
428
|
+
PG_RB_STR_ENSURE_CAPA( *intermediate, (size_t)4 + strlen, current_out, end_capa_ptr );
|
|
422
429
|
/* 4 bytes length */
|
|
423
430
|
write_nbo32(strlen, current_out);
|
|
424
431
|
current_out += 4;
|
|
@@ -432,6 +439,7 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat
|
|
|
432
439
|
|
|
433
440
|
rb_str_set_len( *intermediate, current_out - RSTRING_PTR(*intermediate) );
|
|
434
441
|
|
|
442
|
+
RB_GC_GUARD(rb_typemap);
|
|
435
443
|
return -1;
|
|
436
444
|
}
|
|
437
445
|
|
|
@@ -530,10 +538,11 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
|
|
|
530
538
|
const char *cur_ptr;
|
|
531
539
|
const char *line_end_ptr;
|
|
532
540
|
char *end_capa_ptr;
|
|
541
|
+
VALUE rb_typemap = this->typemap;
|
|
533
542
|
t_typemap *p_typemap;
|
|
534
543
|
|
|
535
|
-
p_typemap = RTYPEDDATA_DATA(
|
|
536
|
-
expected_fields = p_typemap->funcs.fit_to_copy_get(
|
|
544
|
+
p_typemap = RTYPEDDATA_DATA( rb_typemap );
|
|
545
|
+
expected_fields = p_typemap->funcs.fit_to_copy_get( rb_typemap );
|
|
537
546
|
|
|
538
547
|
/* The received input string will probably have this->nfields fields. */
|
|
539
548
|
array = rb_ary_new2(expected_fields);
|
|
@@ -553,7 +562,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
|
|
|
553
562
|
int found_delim = 0;
|
|
554
563
|
const char *start_ptr;
|
|
555
564
|
const char *end_ptr;
|
|
556
|
-
|
|
565
|
+
size_t input_len;
|
|
557
566
|
|
|
558
567
|
/* Remember start of field on input side */
|
|
559
568
|
start_ptr = cur_ptr;
|
|
@@ -688,7 +697,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
|
|
|
688
697
|
|
|
689
698
|
/* Check whether raw input matched null marker */
|
|
690
699
|
input_len = end_ptr - start_ptr;
|
|
691
|
-
if (input_len == RSTRING_LEN(this->null_string) &&
|
|
700
|
+
if (input_len == (size_t)RSTRING_LEN(this->null_string) &&
|
|
692
701
|
strncmp(start_ptr, RSTRING_PTR(this->null_string), input_len) == 0) {
|
|
693
702
|
rb_ary_push(array, Qnil);
|
|
694
703
|
} else {
|
|
@@ -714,11 +723,13 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
|
|
|
714
723
|
break;
|
|
715
724
|
}
|
|
716
725
|
|
|
726
|
+
RB_GC_GUARD(rb_typemap);
|
|
727
|
+
|
|
717
728
|
return array;
|
|
718
729
|
}
|
|
719
730
|
|
|
720
731
|
|
|
721
|
-
static const char BinarySignature[11] =
|
|
732
|
+
static const char BinarySignature[11] = {'P','G','C','O','P','Y','\n','\377','\r','\n','\0'};
|
|
722
733
|
|
|
723
734
|
/*
|
|
724
735
|
* Document-class: PG::BinaryDecoder::CopyRow < PG::CopyDecoder
|
|
@@ -786,10 +797,11 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
|
786
797
|
const char *cur_ptr;
|
|
787
798
|
const char *line_end_ptr;
|
|
788
799
|
char *end_capa_ptr;
|
|
800
|
+
VALUE rb_typemap = this->typemap;
|
|
789
801
|
t_typemap *p_typemap;
|
|
790
802
|
|
|
791
|
-
p_typemap = RTYPEDDATA_DATA(
|
|
792
|
-
expected_fields = p_typemap->funcs.fit_to_copy_get(
|
|
803
|
+
p_typemap = RTYPEDDATA_DATA( rb_typemap );
|
|
804
|
+
expected_fields = p_typemap->funcs.fit_to_copy_get( rb_typemap );
|
|
793
805
|
|
|
794
806
|
/* Allocate a new string with embedded capacity and realloc later with
|
|
795
807
|
* exponential growing size when needed. */
|
|
@@ -830,7 +842,7 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
|
830
842
|
array = rb_ary_new2(expected_fields);
|
|
831
843
|
|
|
832
844
|
for( fieldno = 0; fieldno < nfields; fieldno++){
|
|
833
|
-
|
|
845
|
+
int input_len;
|
|
834
846
|
|
|
835
847
|
/* read field size */
|
|
836
848
|
if (line_end_ptr - cur_ptr < 4 ) goto length_error;
|
|
@@ -871,6 +883,7 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
|
871
883
|
if (cur_ptr < line_end_ptr)
|
|
872
884
|
rb_raise( rb_eArgError, "trailing data after row data at position: %ld", (long)(cur_ptr - input_line) + 1 );
|
|
873
885
|
|
|
886
|
+
RB_GC_GUARD(rb_typemap);
|
|
874
887
|
return array;
|
|
875
888
|
|
|
876
889
|
length_error:
|
data/ext/pg_record_coder.c
CHANGED
|
@@ -47,7 +47,7 @@ static const rb_data_type_t pg_recordcoder_type = {
|
|
|
47
47
|
},
|
|
48
48
|
&pg_coder_type,
|
|
49
49
|
0,
|
|
50
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
50
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
static VALUE
|
|
@@ -179,14 +179,15 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
|
179
179
|
{
|
|
180
180
|
t_pg_recordcoder *this = (t_pg_recordcoder *)conv;
|
|
181
181
|
t_pg_coder_enc_func enc_func;
|
|
182
|
-
|
|
182
|
+
t_pg_coder *p_elem_coder;
|
|
183
183
|
int i;
|
|
184
|
+
VALUE rb_typemap = this->typemap;
|
|
184
185
|
t_typemap *p_typemap;
|
|
185
186
|
char *current_out;
|
|
186
187
|
char *end_capa_ptr;
|
|
187
188
|
|
|
188
|
-
p_typemap = RTYPEDDATA_DATA(
|
|
189
|
-
p_typemap->funcs.fit_to_query(
|
|
189
|
+
p_typemap = RTYPEDDATA_DATA( rb_typemap );
|
|
190
|
+
p_typemap->funcs.fit_to_query( rb_typemap, value );
|
|
190
191
|
|
|
191
192
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
|
192
193
|
PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
|
|
@@ -277,6 +278,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
|
277
278
|
|
|
278
279
|
rb_str_set_len( *intermediate, current_out - RSTRING_PTR(*intermediate) );
|
|
279
280
|
|
|
281
|
+
RB_GC_GUARD(rb_typemap);
|
|
280
282
|
return -1;
|
|
281
283
|
}
|
|
282
284
|
|
|
@@ -387,10 +389,11 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
|
|
|
387
389
|
char *output_ptr;
|
|
388
390
|
char *cur_ptr;
|
|
389
391
|
char *end_capa_ptr;
|
|
392
|
+
VALUE rb_typemap = this->typemap;
|
|
390
393
|
t_typemap *p_typemap;
|
|
391
394
|
|
|
392
|
-
p_typemap = RTYPEDDATA_DATA(
|
|
393
|
-
expected_fields = p_typemap->funcs.fit_to_copy_get(
|
|
395
|
+
p_typemap = RTYPEDDATA_DATA( rb_typemap );
|
|
396
|
+
expected_fields = p_typemap->funcs.fit_to_copy_get( rb_typemap );
|
|
394
397
|
|
|
395
398
|
/* The received input string will probably have this->nfields fields. */
|
|
396
399
|
array = rb_ary_new2(expected_fields);
|
|
@@ -490,6 +493,7 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
|
|
|
490
493
|
if (*cur_ptr)
|
|
491
494
|
rb_raise( rb_eArgError, "malformed record literal: \"%s\" - Junk after right parenthesis.", input_line );
|
|
492
495
|
|
|
496
|
+
RB_GC_GUARD(rb_typemap);
|
|
493
497
|
return array;
|
|
494
498
|
}
|
|
495
499
|
|
data/ext/pg_result.c
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
#include "pg.h"
|
|
8
8
|
|
|
9
9
|
VALUE rb_cPGresult;
|
|
10
|
-
static VALUE sym_symbol, sym_string
|
|
10
|
+
static VALUE sym_symbol, sym_string;
|
|
11
11
|
|
|
12
12
|
static VALUE pgresult_type_map_set( VALUE, VALUE );
|
|
13
13
|
static t_pg_result *pgresult_get_this( VALUE );
|
|
@@ -180,7 +180,7 @@ static const rb_data_type_t pgresult_type = {
|
|
|
180
180
|
pgresult_gc_compact,
|
|
181
181
|
},
|
|
182
182
|
0, 0,
|
|
183
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
183
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
/* Needed by sequel_pg gem, do not delete */
|
|
@@ -315,17 +315,17 @@ pg_result_check( VALUE self )
|
|
|
315
315
|
case PGRES_SINGLE_TUPLE:
|
|
316
316
|
case PGRES_EMPTY_QUERY:
|
|
317
317
|
case PGRES_COMMAND_OK:
|
|
318
|
-
#ifdef
|
|
318
|
+
#ifdef LIBPQ_HAS_PIPELINING
|
|
319
319
|
case PGRES_PIPELINE_SYNC:
|
|
320
320
|
#endif
|
|
321
|
-
#ifdef
|
|
321
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
322
322
|
case PGRES_TUPLES_CHUNK:
|
|
323
323
|
#endif
|
|
324
324
|
return self;
|
|
325
325
|
case PGRES_BAD_RESPONSE:
|
|
326
326
|
case PGRES_FATAL_ERROR:
|
|
327
327
|
case PGRES_NONFATAL_ERROR:
|
|
328
|
-
#ifdef
|
|
328
|
+
#ifdef LIBPQ_HAS_PIPELINING
|
|
329
329
|
case PGRES_PIPELINE_ABORTED:
|
|
330
330
|
#endif
|
|
331
331
|
error = rb_str_new2( PQresultErrorMessage(this->pgresult) );
|
|
@@ -465,9 +465,6 @@ pgresult_get(VALUE self)
|
|
|
465
465
|
static VALUE pg_cstr_to_sym(char *cstr, unsigned int flags, int enc_idx)
|
|
466
466
|
{
|
|
467
467
|
VALUE fname;
|
|
468
|
-
#ifdef TRUFFLERUBY
|
|
469
|
-
if( flags & (PG_RESULT_FIELD_NAMES_SYMBOL | PG_RESULT_FIELD_NAMES_STATIC_SYMBOL) ){
|
|
470
|
-
#else
|
|
471
468
|
if( flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
|
|
472
469
|
rb_encoding *enc = rb_enc_from_index(enc_idx);
|
|
473
470
|
fname = rb_check_symbol_cstr(cstr, strlen(cstr), enc);
|
|
@@ -476,14 +473,9 @@ static VALUE pg_cstr_to_sym(char *cstr, unsigned int flags, int enc_idx)
|
|
|
476
473
|
PG_ENCODING_SET_NOCHECK(fname, enc_idx);
|
|
477
474
|
fname = rb_str_intern(fname);
|
|
478
475
|
}
|
|
479
|
-
} else if( flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
|
|
480
|
-
#endif
|
|
481
|
-
rb_encoding *enc = rb_enc_from_index(enc_idx);
|
|
482
|
-
fname = ID2SYM(rb_intern3(cstr, strlen(cstr), enc));
|
|
483
476
|
} else {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
fname = rb_obj_freeze(fname);
|
|
477
|
+
rb_encoding *enc = rb_enc_from_index(enc_idx);
|
|
478
|
+
fname = rb_enc_interned_str(cstr, strlen(cstr), enc);
|
|
487
479
|
}
|
|
488
480
|
return fname;
|
|
489
481
|
}
|
|
@@ -531,6 +523,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
|
531
523
|
* res.column_values(1) # ["2"]
|
|
532
524
|
* res.each.first # {"a" => "1", "b" => "2", "c" => nil}
|
|
533
525
|
* res.each_row.first # ["1", "2", nil]
|
|
526
|
+
* res.each_tuple.first # #<PG::Tuple a: "1", b: "2", c: nil>
|
|
534
527
|
*
|
|
535
528
|
* Whenever a value is accessed it is casted to a Ruby object by the assigned #type_map which is PG::TypeMapAllStrings by default.
|
|
536
529
|
* Similarly field names can be retrieved either as strings (default) or as symbols which can be switched per #field_name_type= .
|
|
@@ -549,6 +542,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
|
549
542
|
* res.column_values(1) # [2]
|
|
550
543
|
* res.each.first # {a: 1, b: 2, c: nil}
|
|
551
544
|
* res.each_row.first # [1, 2, nil]
|
|
545
|
+
* res.each_tuple.first # #<PG::Tuple a: 1, b: 2, c: nil>
|
|
552
546
|
*
|
|
553
547
|
* Since pg-1.1 the amount of memory in use by a PG::Result object is estimated and passed to ruby's garbage collector.
|
|
554
548
|
* You can invoke the #clear method to force deallocation of memory of the instance when finished with the result for better memory performance.
|
|
@@ -577,7 +571,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
|
577
571
|
* * +PGRES_PIPELINE_SYNC+
|
|
578
572
|
* * +PGRES_PIPELINE_ABORTED+
|
|
579
573
|
*
|
|
580
|
-
* Use
|
|
574
|
+
* Use #res_status or Result.res_status to retrieve the string representation.
|
|
581
575
|
*/
|
|
582
576
|
static VALUE
|
|
583
577
|
pgresult_result_status(VALUE self)
|
|
@@ -589,7 +583,7 @@ pgresult_result_status(VALUE self)
|
|
|
589
583
|
* call-seq:
|
|
590
584
|
* PG::Result.res_status( status ) -> String
|
|
591
585
|
*
|
|
592
|
-
* Returns the string representation of
|
|
586
|
+
* Returns the string representation of #result_status.
|
|
593
587
|
*
|
|
594
588
|
*/
|
|
595
589
|
static VALUE
|
|
@@ -603,7 +597,7 @@ pgresult_s_res_status(VALUE self, VALUE status)
|
|
|
603
597
|
* res.res_status -> String
|
|
604
598
|
* res.res_status( status ) -> String
|
|
605
599
|
*
|
|
606
|
-
* Returns the string representation of the status of the result or of the provided
|
|
600
|
+
* Returns the string representation of the status of the result or of the provided #result_status.
|
|
607
601
|
*
|
|
608
602
|
*/
|
|
609
603
|
static VALUE
|
|
@@ -1430,6 +1424,32 @@ pgresult_each(VALUE self)
|
|
|
1430
1424
|
return self;
|
|
1431
1425
|
}
|
|
1432
1426
|
|
|
1427
|
+
/*
|
|
1428
|
+
* call-seq:
|
|
1429
|
+
* res.each_tuple{ |tuple| ... }
|
|
1430
|
+
*
|
|
1431
|
+
* Yields a PG::Tuple object for each row in the result.
|
|
1432
|
+
*
|
|
1433
|
+
* res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
|
|
1434
|
+
* res.each_tuple.first # #<PG::Tuple a: "1", b: "2", c: nil>
|
|
1435
|
+
*/
|
|
1436
|
+
static VALUE
|
|
1437
|
+
pgresult_each_tuple(VALUE self)
|
|
1438
|
+
{
|
|
1439
|
+
PGresult *result;
|
|
1440
|
+
int tuple_num;
|
|
1441
|
+
|
|
1442
|
+
RETURN_SIZED_ENUMERATOR(self, 0, NULL, pgresult_ntuples_for_enum);
|
|
1443
|
+
|
|
1444
|
+
result = pgresult_get(self);
|
|
1445
|
+
|
|
1446
|
+
for(tuple_num = 0; tuple_num < PQntuples(result); tuple_num++) {
|
|
1447
|
+
VALUE tuple = pgresult_tuple(self, INT2FIX(tuple_num));
|
|
1448
|
+
rb_yield( tuple );
|
|
1449
|
+
}
|
|
1450
|
+
return self;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1433
1453
|
/*
|
|
1434
1454
|
* call-seq:
|
|
1435
1455
|
* res.fields() -> Array
|
|
@@ -1579,7 +1599,7 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
|
1579
1599
|
return self;
|
|
1580
1600
|
rb_raise( rb_eInvalidResultStatus, "PG::Result is not in single row mode");
|
|
1581
1601
|
case PGRES_SINGLE_TUPLE:
|
|
1582
|
-
#ifdef
|
|
1602
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
1583
1603
|
case PGRES_TUPLES_CHUNK:
|
|
1584
1604
|
#endif
|
|
1585
1605
|
break;
|
|
@@ -1597,12 +1617,12 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
|
1597
1617
|
pgresult_clear( this );
|
|
1598
1618
|
}
|
|
1599
1619
|
|
|
1600
|
-
if(
|
|
1620
|
+
if( PQisBusy(pgconn) ){
|
|
1601
1621
|
/* wait for input (without blocking) before reading each result */
|
|
1602
1622
|
pgconn_block( 0, NULL, this->connection );
|
|
1603
1623
|
}
|
|
1604
1624
|
|
|
1605
|
-
pgresult =
|
|
1625
|
+
pgresult = PQgetResult(pgconn);
|
|
1606
1626
|
if( pgresult == NULL )
|
|
1607
1627
|
rb_raise( rb_eNoResultError, "no result received - possibly an intersection with another query");
|
|
1608
1628
|
|
|
@@ -1692,7 +1712,6 @@ pgresult_stream_each_tuple(VALUE self)
|
|
|
1692
1712
|
* It can be set to one of:
|
|
1693
1713
|
* * +:string+ to use String based field names
|
|
1694
1714
|
* * +:symbol+ to use Symbol based field names
|
|
1695
|
-
* * +:static_symbol+ to use pinned Symbol (can not be garbage collected) - Don't use this, it will probably be removed in future.
|
|
1696
1715
|
*
|
|
1697
1716
|
* The default is retrieved from PG::Connection#field_name_type , which defaults to +:string+ .
|
|
1698
1717
|
*
|
|
@@ -1715,7 +1734,6 @@ pgresult_field_name_type_set(VALUE self, VALUE sym)
|
|
|
1715
1734
|
|
|
1716
1735
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
|
1717
1736
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
|
1718
|
-
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
|
1719
1737
|
else if ( sym == sym_string );
|
|
1720
1738
|
else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
|
|
1721
1739
|
|
|
@@ -1736,8 +1754,6 @@ pgresult_field_name_type_get(VALUE self)
|
|
|
1736
1754
|
t_pg_result *this = pgresult_get_this(self);
|
|
1737
1755
|
if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
|
|
1738
1756
|
return sym_symbol;
|
|
1739
|
-
} else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
|
|
1740
|
-
return sym_static_symbol;
|
|
1741
1757
|
} else {
|
|
1742
1758
|
return sym_string;
|
|
1743
1759
|
}
|
|
@@ -1748,7 +1764,6 @@ init_pg_result(void)
|
|
|
1748
1764
|
{
|
|
1749
1765
|
sym_string = ID2SYM(rb_intern("string"));
|
|
1750
1766
|
sym_symbol = ID2SYM(rb_intern("symbol"));
|
|
1751
|
-
sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
|
|
1752
1767
|
|
|
1753
1768
|
rb_cPGresult = rb_define_class_under( rb_mPG, "Result", rb_cObject );
|
|
1754
1769
|
rb_undef_alloc_func(rb_cPGresult);
|
|
@@ -1797,6 +1812,7 @@ init_pg_result(void)
|
|
|
1797
1812
|
rb_define_method(rb_cPGresult, "each", pgresult_each, 0);
|
|
1798
1813
|
rb_define_method(rb_cPGresult, "fields", pgresult_fields, 0);
|
|
1799
1814
|
rb_define_method(rb_cPGresult, "each_row", pgresult_each_row, 0);
|
|
1815
|
+
rb_define_method(rb_cPGresult, "each_tuple", pgresult_each_tuple, 0);
|
|
1800
1816
|
rb_define_method(rb_cPGresult, "values", pgresult_values, 0);
|
|
1801
1817
|
rb_define_method(rb_cPGresult, "column_values", pgresult_column_values, 1);
|
|
1802
1818
|
rb_define_method(rb_cPGresult, "field_values", pgresult_field_values, 1);
|
data/ext/pg_text_decoder.c
CHANGED
|
@@ -942,8 +942,8 @@ static VALUE
|
|
|
942
942
|
init_pg_text_decoder_inet(VALUE rb_mPG_TextDecoder)
|
|
943
943
|
{
|
|
944
944
|
rb_require("ipaddr");
|
|
945
|
+
rb_gc_register_address(&s_IPAddr);
|
|
945
946
|
s_IPAddr = rb_funcall(rb_cObject, rb_intern("const_get"), 1, rb_str_new2("IPAddr"));
|
|
946
|
-
rb_global_variable(&s_IPAddr);
|
|
947
947
|
s_ivar_family = rb_intern("@family");
|
|
948
948
|
s_ivar_addr = rb_intern("@addr");
|
|
949
949
|
s_ivar_mask_addr = rb_intern("@mask_addr");
|
|
@@ -953,10 +953,10 @@ init_pg_text_decoder_inet(VALUE rb_mPG_TextDecoder)
|
|
|
953
953
|
|
|
954
954
|
use_ipaddr_alloc = RTEST(rb_eval_string("IPAddr.new.instance_variables.sort == [:@addr, :@family, :@mask_addr]"));
|
|
955
955
|
|
|
956
|
+
rb_gc_register_address(&s_vmasks4);
|
|
957
|
+
rb_gc_register_address(&s_vmasks6);
|
|
956
958
|
s_vmasks4 = rb_eval_string("a = [0]*33; a[0] = 0; a[32] = 0xffffffff; 31.downto(1){|i| a[i] = a[i+1] - (1 << (31 - i))}; a.freeze");
|
|
957
|
-
rb_global_variable(&s_vmasks4);
|
|
958
959
|
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");
|
|
959
|
-
rb_global_variable(&s_vmasks6);
|
|
960
960
|
|
|
961
961
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Inet", rb_cPG_SimpleDecoder ); */
|
|
962
962
|
pg_define_coder( "Inet", pg_text_dec_inet, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder);
|
|
@@ -973,12 +973,12 @@ init_pg_text_decoder(void)
|
|
|
973
973
|
s_id_utc = rb_intern("utc");
|
|
974
974
|
s_id_getlocal = rb_intern("getlocal");
|
|
975
975
|
|
|
976
|
+
rb_gc_register_address(&s_nan);
|
|
977
|
+
rb_gc_register_address(&s_pos_inf);
|
|
978
|
+
rb_gc_register_address(&s_neg_inf);
|
|
976
979
|
s_nan = rb_eval_string("0.0/0.0");
|
|
977
|
-
rb_global_variable(&s_nan);
|
|
978
980
|
s_pos_inf = rb_eval_string("1.0/0.0");
|
|
979
|
-
rb_global_variable(&s_pos_inf);
|
|
980
981
|
s_neg_inf = rb_eval_string("-1.0/0.0");
|
|
981
|
-
rb_global_variable(&s_neg_inf);
|
|
982
982
|
|
|
983
983
|
/* This module encapsulates all decoder classes with text input format */
|
|
984
984
|
rb_mPG_TextDecoder = rb_define_module_under( rb_mPG, "TextDecoder" );
|
data/ext/pg_text_encoder.c
CHANGED
|
@@ -381,8 +381,8 @@ pg_text_enc_numeric(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
|
381
381
|
static VALUE
|
|
382
382
|
init_pg_text_encoder_numeric(VALUE rb_mPG_TextDecoder)
|
|
383
383
|
{
|
|
384
|
+
rb_gc_register_address(&s_str_F);
|
|
384
385
|
s_str_F = rb_str_freeze(rb_str_new_cstr("F"));
|
|
385
|
-
rb_global_variable(&s_str_F);
|
|
386
386
|
rb_funcall(rb_mPG, rb_intern("require_bigdecimal_without_warning"), 0);
|
|
387
387
|
s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
|
388
388
|
|
|
@@ -430,9 +430,14 @@ pg_text_enc_bytea(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
|
430
430
|
}
|
|
431
431
|
return (int)(optr - out);
|
|
432
432
|
}else{
|
|
433
|
+
long size;
|
|
433
434
|
*intermediate = rb_obj_as_string(value);
|
|
435
|
+
size = RSTRING_LEN(*intermediate);
|
|
436
|
+
|
|
434
437
|
/* The output starts with "\x" and each character is converted to hex. */
|
|
435
|
-
|
|
438
|
+
if( size > INT_MAX / 2 - 2 )
|
|
439
|
+
rb_raise( rb_eArgError, "too large input string for PG::TextEncoder::Bytea: %ld", size );
|
|
440
|
+
return (int)(2 + size * 2);
|
|
436
441
|
}
|
|
437
442
|
}
|
|
438
443
|
|
data/ext/pg_tuple.c
CHANGED
|
@@ -128,7 +128,7 @@ static const rb_data_type_t pg_tuple_type = {
|
|
|
128
128
|
pg_tuple_gc_compact,
|
|
129
129
|
},
|
|
130
130
|
0, 0,
|
|
131
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
131
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
/*
|
data/ext/pg_type_map.c
CHANGED
|
@@ -37,7 +37,7 @@ const rb_data_type_t pg_typemap_type = {
|
|
|
37
37
|
},
|
|
38
38
|
0,
|
|
39
39
|
0,
|
|
40
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
40
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
VALUE rb_cTypeMap;
|
|
@@ -115,6 +115,45 @@ pg_typemap_s_allocate( VALUE klass )
|
|
|
115
115
|
return self;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
/*
|
|
119
|
+
* call-seq:
|
|
120
|
+
* res.query_param_encoders(params)
|
|
121
|
+
*
|
|
122
|
+
* Retrieve the encoders that are used to encode the given values to be submitted to the database server.
|
|
123
|
+
* The selection of the encoders is defined in the derived type map class.
|
|
124
|
+
*
|
|
125
|
+
* +params+ must be an Array of values to be encoded.
|
|
126
|
+
* It's like +params+ given to exec_params .
|
|
127
|
+
*
|
|
128
|
+
* Returns an Array with the same length as +params+.
|
|
129
|
+
*
|
|
130
|
+
*/
|
|
131
|
+
static VALUE
|
|
132
|
+
pg_typemap_query_param_encoders( VALUE self, VALUE params )
|
|
133
|
+
{
|
|
134
|
+
t_typemap *this = RTYPEDDATA_DATA( self );
|
|
135
|
+
int nParams;
|
|
136
|
+
int i=0;
|
|
137
|
+
VALUE res;
|
|
138
|
+
|
|
139
|
+
Check_Type(params, T_ARRAY);
|
|
140
|
+
|
|
141
|
+
this->funcs.fit_to_query( self, params );
|
|
142
|
+
|
|
143
|
+
nParams = RARRAY_LENINT(params);
|
|
144
|
+
res = rb_ary_new2(nParams);
|
|
145
|
+
|
|
146
|
+
for ( i = 0; i < nParams; i++ ) {
|
|
147
|
+
t_pg_coder *conv;
|
|
148
|
+
VALUE param_value = rb_ary_entry(params, i);
|
|
149
|
+
|
|
150
|
+
/* Let the given typemap select a coder for this param */
|
|
151
|
+
conv = this->funcs.typecast_query_param(this, param_value, i);
|
|
152
|
+
rb_ary_push(res, conv ? conv->coder_obj : Qnil);
|
|
153
|
+
}
|
|
154
|
+
return res;
|
|
155
|
+
}
|
|
156
|
+
|
|
118
157
|
/*
|
|
119
158
|
* call-seq:
|
|
120
159
|
* res.default_type_map = typemap
|
|
@@ -194,6 +233,7 @@ init_pg_type_map(void)
|
|
|
194
233
|
*/
|
|
195
234
|
rb_cTypeMap = rb_define_class_under( rb_mPG, "TypeMap", rb_cObject );
|
|
196
235
|
rb_define_alloc_func( rb_cTypeMap, pg_typemap_s_allocate );
|
|
236
|
+
rb_define_method( rb_cTypeMap, "query_param_encoders", pg_typemap_query_param_encoders, 1 );
|
|
197
237
|
|
|
198
238
|
rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable");
|
|
199
239
|
rb_define_method( rb_mDefaultTypeMappable, "default_type_map=", pg_typemap_default_type_map_set, 1 );
|
|
@@ -18,7 +18,7 @@ static const rb_data_type_t pg_tmas_type = {
|
|
|
18
18
|
},
|
|
19
19
|
&pg_typemap_type,
|
|
20
20
|
0,
|
|
21
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
21
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
VALUE rb_cTypeMapAllStrings;
|
|
@@ -125,6 +125,6 @@ init_pg_type_map_all_strings(void)
|
|
|
125
125
|
rb_cTypeMapAllStrings = rb_define_class_under( rb_mPG, "TypeMapAllStrings", rb_cTypeMap );
|
|
126
126
|
rb_define_alloc_func( rb_cTypeMapAllStrings, pg_tmas_s_allocate );
|
|
127
127
|
|
|
128
|
-
pg_typemap_all_strings = rb_obj_freeze( rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 ));
|
|
129
128
|
rb_gc_register_address( &pg_typemap_all_strings );
|
|
129
|
+
pg_typemap_all_strings = rb_obj_freeze( rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 ));
|
|
130
130
|
}
|
data/ext/pg_type_map_by_class.c
CHANGED
|
@@ -157,7 +157,7 @@ static const rb_data_type_t pg_tmbk_type = {
|
|
|
157
157
|
},
|
|
158
158
|
&pg_typemap_type,
|
|
159
159
|
0,
|
|
160
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
160
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
161
161
|
};
|
|
162
162
|
|
|
163
163
|
static VALUE
|
data/ext/pg_type_map_by_column.c
CHANGED
|
@@ -55,7 +55,7 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
|
|
|
55
55
|
t_typemap *default_tm;
|
|
56
56
|
|
|
57
57
|
Check_Type(params, T_ARRAY);
|
|
58
|
-
nfields = (
|
|
58
|
+
nfields = RARRAY_LENINT( params );
|
|
59
59
|
if ( this->nfields != nfields ) {
|
|
60
60
|
rb_raise( rb_eArgError, "number of result fields (%d) does not match number of mapped columns (%d)",
|
|
61
61
|
nfields, this->nfields );
|
|
@@ -233,7 +233,7 @@ static const rb_data_type_t pg_tmbc_type = {
|
|
|
233
233
|
},
|
|
234
234
|
&pg_typemap_type,
|
|
235
235
|
0,
|
|
236
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
236
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
237
237
|
};
|
|
238
238
|
|
|
239
239
|
static VALUE
|
data/ext/pg_type_map_by_oid.c
CHANGED
|
@@ -194,7 +194,7 @@ static const rb_data_type_t pg_tmbo_type = {
|
|
|
194
194
|
},
|
|
195
195
|
&pg_typemap_type,
|
|
196
196
|
0,
|
|
197
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
197
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
198
198
|
};
|
|
199
199
|
|
|
200
200
|
static VALUE
|
data/ext/pg_type_map_in_ruby.c
CHANGED
|
@@ -44,7 +44,7 @@ static const rb_data_type_t pg_tmir_type = {
|
|
|
44
44
|
},
|
|
45
45
|
&pg_typemap_type,
|
|
46
46
|
0,
|
|
47
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED |
|
|
47
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
/*
|