pg 1.2.3 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +42 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +117 -0
  6. data/.github/workflows/source-gem.yml +137 -0
  7. data/.gitignore +22 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/Gemfile +14 -0
  15. data/History.md +876 -0
  16. data/Manifest.txt +0 -1
  17. data/README.ja.md +276 -0
  18. data/README.md +286 -0
  19. data/Rakefile +33 -135
  20. data/Rakefile.cross +12 -13
  21. data/certs/ged.pem +24 -0
  22. data/certs/larskanis-2022.pem +26 -0
  23. data/certs/larskanis-2023.pem +24 -0
  24. data/ext/errorcodes.def +12 -0
  25. data/ext/errorcodes.rb +0 -0
  26. data/ext/errorcodes.txt +4 -1
  27. data/ext/extconf.rb +100 -25
  28. data/ext/gvl_wrappers.c +4 -0
  29. data/ext/gvl_wrappers.h +23 -0
  30. data/ext/pg.c +72 -57
  31. data/ext/pg.h +28 -4
  32. data/ext/pg_binary_decoder.c +80 -1
  33. data/ext/pg_binary_encoder.c +225 -1
  34. data/ext/pg_coder.c +96 -33
  35. data/ext/pg_connection.c +996 -697
  36. data/ext/pg_copy_coder.c +351 -33
  37. data/ext/pg_errors.c +1 -1
  38. data/ext/pg_record_coder.c +50 -19
  39. data/ext/pg_result.c +177 -64
  40. data/ext/pg_text_decoder.c +29 -11
  41. data/ext/pg_text_encoder.c +29 -16
  42. data/ext/pg_tuple.c +83 -60
  43. data/ext/pg_type_map.c +44 -10
  44. data/ext/pg_type_map_all_strings.c +17 -3
  45. data/ext/pg_type_map_by_class.c +54 -27
  46. data/ext/pg_type_map_by_column.c +73 -31
  47. data/ext/pg_type_map_by_mri_type.c +48 -19
  48. data/ext/pg_type_map_by_oid.c +59 -27
  49. data/ext/pg_type_map_in_ruby.c +55 -21
  50. data/ext/pg_util.c +2 -2
  51. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  52. data/lib/pg/basic_type_map_for_queries.rb +198 -0
  53. data/lib/pg/basic_type_map_for_results.rb +104 -0
  54. data/lib/pg/basic_type_registry.rb +299 -0
  55. data/lib/pg/binary_decoder/date.rb +9 -0
  56. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  57. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  58. data/lib/pg/coder.rb +15 -13
  59. data/lib/pg/connection.rb +743 -83
  60. data/lib/pg/exceptions.rb +14 -1
  61. data/lib/pg/text_decoder/date.rb +18 -0
  62. data/lib/pg/text_decoder/inet.rb +9 -0
  63. data/lib/pg/text_decoder/json.rb +14 -0
  64. data/lib/pg/text_decoder/numeric.rb +9 -0
  65. data/lib/pg/text_decoder/timestamp.rb +30 -0
  66. data/lib/pg/text_encoder/date.rb +12 -0
  67. data/lib/pg/text_encoder/inet.rb +28 -0
  68. data/lib/pg/text_encoder/json.rb +14 -0
  69. data/lib/pg/text_encoder/numeric.rb +9 -0
  70. data/lib/pg/text_encoder/timestamp.rb +24 -0
  71. data/lib/pg/version.rb +4 -0
  72. data/lib/pg.rb +94 -39
  73. data/misc/openssl-pg-segfault.rb +31 -0
  74. data/misc/postgres/History.txt +9 -0
  75. data/misc/postgres/Manifest.txt +5 -0
  76. data/misc/postgres/README.txt +21 -0
  77. data/misc/postgres/Rakefile +21 -0
  78. data/misc/postgres/lib/postgres.rb +16 -0
  79. data/misc/ruby-pg/History.txt +9 -0
  80. data/misc/ruby-pg/Manifest.txt +5 -0
  81. data/misc/ruby-pg/README.txt +21 -0
  82. data/misc/ruby-pg/Rakefile +21 -0
  83. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  84. data/pg.gemspec +34 -0
  85. data/rakelib/task_extension.rb +46 -0
  86. data/sample/array_insert.rb +20 -0
  87. data/sample/async_api.rb +102 -0
  88. data/sample/async_copyto.rb +39 -0
  89. data/sample/async_mixed.rb +56 -0
  90. data/sample/check_conn.rb +21 -0
  91. data/sample/copydata.rb +71 -0
  92. data/sample/copyfrom.rb +81 -0
  93. data/sample/copyto.rb +19 -0
  94. data/sample/cursor.rb +21 -0
  95. data/sample/disk_usage_report.rb +177 -0
  96. data/sample/issue-119.rb +94 -0
  97. data/sample/losample.rb +69 -0
  98. data/sample/minimal-testcase.rb +17 -0
  99. data/sample/notify_wait.rb +72 -0
  100. data/sample/pg_statistics.rb +285 -0
  101. data/sample/replication_monitor.rb +222 -0
  102. data/sample/test_binary_values.rb +33 -0
  103. data/sample/wal_shipper.rb +434 -0
  104. data/sample/warehouse_partitions.rb +311 -0
  105. data/translation/.po4a-version +7 -0
  106. data/translation/po/all.pot +910 -0
  107. data/translation/po/ja.po +1047 -0
  108. data/translation/po4a.cfg +12 -0
  109. data.tar.gz.sig +0 -0
  110. metadata +142 -210
  111. metadata.gz.sig +0 -0
  112. data/ChangeLog +0 -0
  113. data/History.rdoc +0 -578
  114. data/README.ja.rdoc +0 -13
  115. data/README.rdoc +0 -213
  116. data/lib/pg/basic_type_mapping.rb +0 -522
  117. data/lib/pg/binary_decoder.rb +0 -23
  118. data/lib/pg/constants.rb +0 -12
  119. data/lib/pg/text_decoder.rb +0 -46
  120. data/lib/pg/text_encoder.rb +0 -59
  121. data/spec/data/expected_trace.out +0 -26
  122. data/spec/data/random_binary_data +0 -0
  123. data/spec/helpers.rb +0 -380
  124. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  125. data/spec/pg/connection_spec.rb +0 -1949
  126. data/spec/pg/connection_sync_spec.rb +0 -41
  127. data/spec/pg/result_spec.rb +0 -681
  128. data/spec/pg/tuple_spec.rb +0 -333
  129. data/spec/pg/type_map_by_class_spec.rb +0 -138
  130. data/spec/pg/type_map_by_column_spec.rb +0 -226
  131. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  132. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  133. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  134. data/spec/pg/type_map_spec.rb +0 -22
  135. data/spec/pg/type_spec.rb +0 -1123
  136. data/spec/pg_spec.rb +0 -50
@@ -191,7 +191,7 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
191
191
  if (neg)
192
192
  *out++ = '-';
193
193
 
194
- len = out - start;
194
+ len = (int)(out - start);
195
195
 
196
196
  /* Reverse string. */
197
197
  out--;
@@ -252,7 +252,7 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
252
252
  }
253
253
 
254
254
  /*
255
- * The following computaion is roughly a conversion kind of
255
+ * The following computation is roughly a conversion kind of
256
256
  * sprintf( out, "%.16E", dvalue);
257
257
  */
258
258
 
@@ -371,6 +371,21 @@ pg_text_enc_numeric(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
371
371
  }
372
372
  }
373
373
 
374
+ /* called per autoload when TextEncoder::Numeric is used */
375
+ static VALUE
376
+ init_pg_text_encoder_numeric(VALUE rb_mPG_TextDecoder)
377
+ {
378
+ s_str_F = rb_str_freeze(rb_str_new_cstr("F"));
379
+ rb_global_variable(&s_str_F);
380
+ rb_require("bigdecimal");
381
+ s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
382
+
383
+ /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Numeric", rb_cPG_SimpleEncoder ); */
384
+ pg_define_coder( "Numeric", pg_text_enc_numeric, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
385
+
386
+ return Qnil;
387
+ }
388
+
374
389
 
375
390
  static const char hextab[] = {
376
391
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
@@ -383,8 +398,12 @@ static const char hextab[] = {
383
398
  *
384
399
  * The binary String is converted to hexadecimal representation for transmission
385
400
  * in text format. For query bind parameters it is recommended to use
386
- * PG::BinaryEncoder::Bytea instead, in order to decrease network traffic and
387
- * CPU usage.
401
+ * PG::BinaryEncoder::Bytea or the hash form <tt>{value: binary_string, format: 1}</tt> instead,
402
+ * in order to decrease network traffic and CPU usage.
403
+ * See PG::Connection#exec_params for using the hash form.
404
+ *
405
+ * This encoder is particular useful when PG::TextEncoder::CopyRow is used with the COPY command.
406
+ * In this case there's no way to change the format of a single column to binary, so that the data have to be converted to bytea hex representation.
388
407
  *
389
408
  */
390
409
  static int
@@ -403,11 +422,11 @@ pg_text_enc_bytea(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
403
422
  *optr++ = hextab[c >> 4];
404
423
  *optr++ = hextab[c & 0xf];
405
424
  }
406
- return optr - out;
425
+ return (int)(optr - out);
407
426
  }else{
408
427
  *intermediate = rb_obj_as_string(value);
409
428
  /* The output starts with "\x" and each character is converted to hex. */
410
- return 2 + RSTRING_LEN(*intermediate) * 2;
429
+ return 2 + RSTRING_LENINT(*intermediate) * 2;
411
430
  }
412
431
  }
413
432
 
@@ -610,8 +629,8 @@ quote_identifier( VALUE value, VALUE out_string, char *current_out ){
610
629
  static char *
611
630
  pg_text_enc_array_identifier(VALUE value, VALUE string, char *out, int enc_idx)
612
631
  {
613
- int i;
614
- int nr_elems;
632
+ long i;
633
+ long nr_elems;
615
634
 
616
635
  Check_Type(value, T_ARRAY);
617
636
  nr_elems = RARRAY_LEN(value);
@@ -775,19 +794,15 @@ pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedi
775
794
 
776
795
 
777
796
  void
778
- init_pg_text_encoder()
797
+ init_pg_text_encoder(void)
779
798
  {
780
799
  s_id_encode = rb_intern("encode");
781
800
  s_id_to_i = rb_intern("to_i");
782
801
  s_id_to_s = rb_intern("to_s");
783
- s_str_F = rb_str_freeze(rb_str_new_cstr("F"));
784
- rb_global_variable(&s_str_F);
785
- rb_require("bigdecimal");
786
- s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
787
-
788
802
 
789
803
  /* This module encapsulates all encoder classes with text output format */
790
804
  rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" );
805
+ rb_define_private_method(rb_singleton_class(rb_mPG_TextEncoder), "init_numeric", init_pg_text_encoder_numeric, 0);
791
806
 
792
807
  /* Make RDoc aware of the encoder classes... */
793
808
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Boolean", rb_cPG_SimpleEncoder ); */
@@ -796,8 +811,6 @@ init_pg_text_encoder()
796
811
  pg_define_coder( "Integer", pg_text_enc_integer, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
797
812
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Float", rb_cPG_SimpleEncoder ); */
798
813
  pg_define_coder( "Float", pg_text_enc_float, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
799
- /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Numeric", rb_cPG_SimpleEncoder ); */
800
- pg_define_coder( "Numeric", pg_text_enc_numeric, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
801
814
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "String", rb_cPG_SimpleEncoder ); */
802
815
  pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
803
816
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
data/ext/pg_tuple.c CHANGED
@@ -52,57 +52,83 @@ typedef struct {
52
52
  VALUE values[0];
53
53
  } t_pg_tuple;
54
54
 
55
- static inline VALUE
56
- pg_tuple_get_field_names( t_pg_tuple *this )
55
+ static inline VALUE *
56
+ pg_tuple_get_field_names_ptr( t_pg_tuple *this )
57
57
  {
58
58
  if( this->num_fields != (int)RHASH_SIZE(this->field_map) ){
59
- return this->values[this->num_fields];
59
+ return &this->values[this->num_fields];
60
60
  } else {
61
- return Qfalse;
61
+ static VALUE f = Qfalse;
62
+ return &f;
62
63
  }
63
64
  }
64
65
 
66
+ static inline VALUE
67
+ pg_tuple_get_field_names( t_pg_tuple *this )
68
+ {
69
+ return *pg_tuple_get_field_names_ptr(this);
70
+ }
71
+
65
72
  static void
66
- pg_tuple_gc_mark( t_pg_tuple *this )
73
+ pg_tuple_gc_mark( void *_this )
67
74
  {
75
+ t_pg_tuple *this = (t_pg_tuple *)_this;
68
76
  int i;
69
77
 
70
78
  if( !this ) return;
71
- rb_gc_mark( this->result );
72
- rb_gc_mark( this->typemap );
73
- rb_gc_mark( this->field_map );
79
+ rb_gc_mark_movable( this->result );
80
+ rb_gc_mark_movable( this->typemap );
81
+ rb_gc_mark_movable( this->field_map );
74
82
 
75
83
  for( i = 0; i < this->num_fields; i++ ){
76
- rb_gc_mark( this->values[i] );
84
+ rb_gc_mark_movable( this->values[i] );
77
85
  }
78
- rb_gc_mark( pg_tuple_get_field_names(this) );
86
+ rb_gc_mark_movable( pg_tuple_get_field_names(this) );
79
87
  }
80
88
 
81
89
  static void
82
- pg_tuple_gc_free( t_pg_tuple *this )
90
+ pg_tuple_gc_compact( void *_this )
83
91
  {
92
+ t_pg_tuple *this = (t_pg_tuple *)_this;
93
+ int i;
94
+
95
+ if( !this ) return;
96
+ pg_gc_location( this->result );
97
+ pg_gc_location( this->typemap );
98
+ pg_gc_location( this->field_map );
99
+
100
+ for( i = 0; i < this->num_fields; i++ ){
101
+ pg_gc_location( this->values[i] );
102
+ }
103
+ pg_gc_location( *pg_tuple_get_field_names_ptr(this) );
104
+ }
105
+
106
+ static void
107
+ pg_tuple_gc_free( void *_this )
108
+ {
109
+ t_pg_tuple *this = (t_pg_tuple *)_this;
84
110
  if( !this ) return;
85
111
  xfree(this);
86
112
  }
87
113
 
88
114
  static size_t
89
- pg_tuple_memsize( t_pg_tuple *this )
115
+ pg_tuple_memsize( const void *_this )
90
116
  {
117
+ const t_pg_tuple *this = (const t_pg_tuple *)_this;
91
118
  if( this==NULL ) return 0;
92
119
  return sizeof(*this) + sizeof(*this->values) * this->num_fields;
93
120
  }
94
121
 
95
122
  static const rb_data_type_t pg_tuple_type = {
96
- "pg",
123
+ "PG::Tuple",
97
124
  {
98
- (void (*)(void*))pg_tuple_gc_mark,
99
- (void (*)(void*))pg_tuple_gc_free,
100
- (size_t (*)(const void *))pg_tuple_memsize,
125
+ pg_tuple_gc_mark,
126
+ pg_tuple_gc_free,
127
+ pg_tuple_memsize,
128
+ pg_compact_callback(pg_tuple_gc_compact),
101
129
  },
102
130
  0, 0,
103
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
104
- RUBY_TYPED_FREE_IMMEDIATELY,
105
- #endif
131
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
106
132
  };
107
133
 
108
134
  /*
@@ -133,9 +159,9 @@ pg_tuple_new(VALUE result, int row_num)
133
159
  sizeof(*this->values) * num_fields +
134
160
  sizeof(*this->values) * (dup_names ? 1 : 0));
135
161
 
136
- this->result = result;
137
- this->typemap = p_result->typemap;
138
- this->field_map = field_map;
162
+ RB_OBJ_WRITE(self, &this->result, result);
163
+ RB_OBJ_WRITE(self, &this->typemap, p_result->typemap);
164
+ RB_OBJ_WRITE(self, &this->field_map, field_map);
139
165
  this->row_num = row_num;
140
166
  this->num_fields = num_fields;
141
167
 
@@ -147,7 +173,8 @@ pg_tuple_new(VALUE result, int row_num)
147
173
  /* Some of the column names are duplicated -> we need the keys as Array in addition.
148
174
  * Store it behind the values to save the space in the common case of no dups.
149
175
  */
150
- this->values[num_fields] = rb_obj_freeze(rb_ary_new4(num_fields, p_result->fnames));
176
+ VALUE keys_array = rb_obj_freeze(rb_ary_new4(num_fields, p_result->fnames));
177
+ RB_OBJ_WRITE(self, &this->values[num_fields], keys_array);
151
178
  }
152
179
 
153
180
  RTYPEDDATA_DATA(self) = this;
@@ -167,38 +194,41 @@ pg_tuple_get_this( VALUE self )
167
194
  }
168
195
 
169
196
  static VALUE
170
- pg_tuple_materialize_field(t_pg_tuple *this, int col)
197
+ pg_tuple_materialize_field(VALUE self, int col)
171
198
  {
199
+ t_pg_tuple *this = RTYPEDDATA_DATA( self );
172
200
  VALUE value = this->values[col];
173
201
 
174
202
  if( value == Qundef ){
175
- t_typemap *p_typemap = DATA_PTR( this->typemap );
203
+ t_typemap *p_typemap = RTYPEDDATA_DATA( this->typemap );
176
204
 
177
205
  pgresult_get(this->result); /* make sure we have a valid PGresult object */
178
206
  value = p_typemap->funcs.typecast_result_value(p_typemap, this->result, this->row_num, col);
179
- this->values[col] = value;
207
+ RB_OBJ_WRITE(self, &this->values[col], value);
180
208
  }
181
209
 
182
210
  return value;
183
211
  }
184
212
 
185
213
  static void
186
- pg_tuple_detach(t_pg_tuple *this)
214
+ pg_tuple_detach(VALUE self)
187
215
  {
188
- this->result = Qnil;
189
- this->typemap = Qnil;
216
+ t_pg_tuple *this = RTYPEDDATA_DATA( self );
217
+ RB_OBJ_WRITE(self, &this->result, Qnil);
218
+ RB_OBJ_WRITE(self, &this->typemap, Qnil);
190
219
  this->row_num = -1;
191
220
  }
192
221
 
193
222
  static void
194
- pg_tuple_materialize(t_pg_tuple *this)
223
+ pg_tuple_materialize(VALUE self)
195
224
  {
225
+ t_pg_tuple *this = RTYPEDDATA_DATA( self );
196
226
  int field_num;
197
227
  for(field_num = 0; field_num < this->num_fields; field_num++) {
198
- pg_tuple_materialize_field(this, field_num);
228
+ pg_tuple_materialize_field(self, field_num);
199
229
  }
200
230
 
201
- pg_tuple_detach(this);
231
+ pg_tuple_detach(self);
202
232
  }
203
233
 
204
234
  /*
@@ -260,7 +290,7 @@ pg_tuple_fetch(int argc, VALUE *argv, VALUE self)
260
290
  field_num = NUM2INT(index);
261
291
  }
262
292
 
263
- return pg_tuple_materialize_field(this, field_num);
293
+ return pg_tuple_materialize_field(self, field_num);
264
294
  }
265
295
 
266
296
  /*
@@ -298,7 +328,7 @@ pg_tuple_aref(VALUE self, VALUE key)
298
328
  field_num = NUM2INT(index);
299
329
  }
300
330
 
301
- return pg_tuple_materialize_field(this, field_num);
331
+ return pg_tuple_materialize_field(self, field_num);
302
332
  }
303
333
 
304
334
  static VALUE
@@ -309,10 +339,9 @@ pg_tuple_num_fields_for_enum(VALUE self, VALUE args, VALUE eobj)
309
339
  }
310
340
 
311
341
  static int
312
- pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE _this)
342
+ pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE self)
313
343
  {
314
- t_pg_tuple *this = (t_pg_tuple *)_this;
315
- VALUE value = pg_tuple_materialize_field(this, NUM2INT(index));
344
+ VALUE value = pg_tuple_materialize_field(self, NUM2INT(index));
316
345
  rb_yield_values(2, key, value);
317
346
  return ST_CONTINUE;
318
347
  }
@@ -334,16 +363,16 @@ pg_tuple_each(VALUE self)
334
363
  field_names = pg_tuple_get_field_names(this);
335
364
 
336
365
  if( field_names == Qfalse ){
337
- rb_hash_foreach(this->field_map, pg_tuple_yield_key_value, (VALUE)this);
366
+ rb_hash_foreach(this->field_map, pg_tuple_yield_key_value, self);
338
367
  } else {
339
368
  int i;
340
369
  for( i = 0; i < this->num_fields; i++ ){
341
- VALUE value = pg_tuple_materialize_field(this, i);
370
+ VALUE value = pg_tuple_materialize_field(self, i);
342
371
  rb_yield_values(2, RARRAY_AREF(field_names, i), value);
343
372
  }
344
373
  }
345
374
 
346
- pg_tuple_detach(this);
375
+ pg_tuple_detach(self);
347
376
  return self;
348
377
  }
349
378
 
@@ -362,11 +391,11 @@ pg_tuple_each_value(VALUE self)
362
391
  RETURN_SIZED_ENUMERATOR(self, 0, NULL, pg_tuple_num_fields_for_enum);
363
392
 
364
393
  for(field_num = 0; field_num < this->num_fields; field_num++) {
365
- VALUE value = pg_tuple_materialize_field(this, field_num);
394
+ VALUE value = pg_tuple_materialize_field(self, field_num);
366
395
  rb_yield(value);
367
396
  }
368
397
 
369
- pg_tuple_detach(this);
398
+ pg_tuple_detach(self);
370
399
  return self;
371
400
  }
372
401
 
@@ -383,7 +412,7 @@ pg_tuple_values(VALUE self)
383
412
  {
384
413
  t_pg_tuple *this = pg_tuple_get_this(self);
385
414
 
386
- pg_tuple_materialize(this);
415
+ pg_tuple_materialize(self);
387
416
  return rb_ary_new4(this->num_fields, &this->values[0]);
388
417
  }
389
418
 
@@ -436,7 +465,7 @@ pg_tuple_dump(VALUE self)
436
465
  VALUE a;
437
466
  t_pg_tuple *this = pg_tuple_get_this(self);
438
467
 
439
- pg_tuple_materialize(this);
468
+ pg_tuple_materialize(self);
440
469
 
441
470
  field_names = pg_tuple_get_field_names(this);
442
471
  if( field_names == Qfalse )
@@ -445,10 +474,7 @@ pg_tuple_dump(VALUE self)
445
474
  values = rb_ary_new4(this->num_fields, &this->values[0]);
446
475
  a = rb_ary_new3(2, field_names, values);
447
476
 
448
- if (FL_TEST(self, FL_EXIVAR)) {
449
- rb_copy_generic_ivar(a, self);
450
- FL_SET(a, FL_EXIVAR);
451
- }
477
+ rb_copy_generic_ivar(a, self);
452
478
 
453
479
  return a;
454
480
  }
@@ -479,9 +505,9 @@ pg_tuple_load(VALUE self, VALUE a)
479
505
  rb_obj_freeze(field_names);
480
506
  values = RARRAY_AREF(a, 1);
481
507
  Check_Type(values, T_ARRAY);
482
- num_fields = RARRAY_LEN(values);
508
+ num_fields = RARRAY_LENINT(values);
483
509
 
484
- if (RARRAY_LEN(field_names) != num_fields)
510
+ if (RARRAY_LENINT(field_names) != num_fields)
485
511
  rb_raise(rb_eTypeError, "different number of fields and values");
486
512
 
487
513
  field_map = rb_hash_new();
@@ -497,35 +523,32 @@ pg_tuple_load(VALUE self, VALUE a)
497
523
  sizeof(*this->values) * num_fields +
498
524
  sizeof(*this->values) * (dup_names ? 1 : 0));
499
525
 
500
- this->result = Qnil;
501
- this->typemap = Qnil;
526
+ RB_OBJ_WRITE(self, &this->result, Qnil);
527
+ RB_OBJ_WRITE(self, &this->typemap, Qnil);
502
528
  this->row_num = -1;
503
529
  this->num_fields = num_fields;
504
- this->field_map = field_map;
530
+ RB_OBJ_WRITE(self, &this->field_map, field_map);
505
531
 
506
532
  for( i = 0; i < num_fields; i++ ){
507
533
  VALUE v = RARRAY_AREF(values, i);
508
534
  if( v == Qundef )
509
535
  rb_raise(rb_eTypeError, "field %d is not materialized", i);
510
- this->values[i] = v;
536
+ RB_OBJ_WRITE(self, &this->values[i], v);
511
537
  }
512
538
 
513
539
  if( dup_names ){
514
- this->values[num_fields] = field_names;
540
+ RB_OBJ_WRITE(self, &this->values[num_fields], field_names);
515
541
  }
516
542
 
517
543
  RTYPEDDATA_DATA(self) = this;
518
544
 
519
- if (FL_TEST(a, FL_EXIVAR)) {
520
- rb_copy_generic_ivar(self, a);
521
- FL_SET(self, FL_EXIVAR);
522
- }
545
+ rb_copy_generic_ivar(self, a);
523
546
 
524
547
  return self;
525
548
  }
526
549
 
527
550
  void
528
- init_pg_tuple()
551
+ init_pg_tuple(void)
529
552
  {
530
553
  rb_cPG_Tuple = rb_define_class_under( rb_mPG, "Tuple", rb_cObject );
531
554
  rb_define_alloc_func( rb_cPG_Tuple, pg_tuple_s_allocate );
data/ext/pg_type_map.c CHANGED
@@ -6,6 +6,40 @@
6
6
 
7
7
  #include "pg.h"
8
8
 
9
+ void
10
+ pg_typemap_mark( void *_this )
11
+ {
12
+ t_typemap *this = (t_typemap *)_this;
13
+ rb_gc_mark_movable(this->default_typemap);
14
+ }
15
+
16
+ size_t
17
+ pg_typemap_memsize( const void *_this )
18
+ {
19
+ t_typemap *this = (t_typemap *)_this;
20
+ return sizeof(*this);
21
+ }
22
+
23
+ void
24
+ pg_typemap_compact( void *_this )
25
+ {
26
+ t_typemap *this = (t_typemap *)_this;
27
+ pg_gc_location(this->default_typemap);
28
+ }
29
+
30
+ const rb_data_type_t pg_typemap_type = {
31
+ "PG::TypeMap",
32
+ {
33
+ pg_typemap_mark,
34
+ RUBY_TYPED_DEFAULT_FREE,
35
+ pg_typemap_memsize,
36
+ pg_compact_callback(pg_typemap_compact),
37
+ },
38
+ 0,
39
+ 0,
40
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
41
+ };
42
+
9
43
  VALUE rb_cTypeMap;
10
44
  VALUE rb_mDefaultTypeMappable;
11
45
  static ID s_id_fit_to_query;
@@ -75,7 +109,7 @@ pg_typemap_s_allocate( VALUE klass )
75
109
  VALUE self;
76
110
  t_typemap *this;
77
111
 
78
- self = Data_Make_Struct( klass, t_typemap, NULL, -1, this );
112
+ self = TypedData_Make_Struct( klass, t_typemap, &pg_typemap_type, this );
79
113
  this->funcs = pg_typemap_funcs;
80
114
 
81
115
  return self;
@@ -94,14 +128,14 @@ pg_typemap_s_allocate( VALUE klass )
94
128
  static VALUE
95
129
  pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
96
130
  {
97
- t_typemap *this = DATA_PTR( self );
131
+ t_typemap *this = RTYPEDDATA_DATA( self );
132
+ t_typemap *tm;
133
+ UNUSED(tm);
98
134
 
99
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
100
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
101
- rb_obj_classname( typemap ) );
102
- }
103
- Check_Type(typemap, T_DATA);
104
- this->default_typemap = typemap;
135
+ rb_check_frozen(self);
136
+ /* Check type of method param */
137
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
138
+ RB_OBJ_WRITE(self, &this->default_typemap, typemap);
105
139
 
106
140
  return typemap;
107
141
  }
@@ -119,7 +153,7 @@ pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
119
153
  static VALUE
120
154
  pg_typemap_default_type_map_get(VALUE self)
121
155
  {
122
- t_typemap *this = DATA_PTR( self );
156
+ t_typemap *this = RTYPEDDATA_DATA( self );
123
157
 
124
158
  return this->default_typemap;
125
159
  }
@@ -143,7 +177,7 @@ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
143
177
  }
144
178
 
145
179
  void
146
- init_pg_type_map()
180
+ init_pg_type_map(void)
147
181
  {
148
182
  s_id_fit_to_query = rb_intern("fit_to_query");
149
183
  s_id_fit_to_result = rb_intern("fit_to_result");
@@ -8,6 +8,19 @@
8
8
 
9
9
  #include "pg.h"
10
10
 
11
+ static const rb_data_type_t pg_tmas_type = {
12
+ "PG::TypeMapAllStrings",
13
+ {
14
+ pg_typemap_mark,
15
+ RUBY_TYPED_DEFAULT_FREE,
16
+ pg_typemap_memsize,
17
+ pg_compact_callback(pg_typemap_compact),
18
+ },
19
+ &pg_typemap_type,
20
+ 0,
21
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
22
+ };
23
+
11
24
  VALUE rb_cTypeMapAllStrings;
12
25
  VALUE pg_typemap_all_strings;
13
26
 
@@ -63,6 +76,7 @@ pg_tmas_fit_to_copy_get( VALUE self )
63
76
  static VALUE
64
77
  pg_tmas_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
65
78
  {
79
+ rb_str_modify(field_str);
66
80
  if( format == 0 ){
67
81
  PG_ENCODING_SET_NOCHECK( field_str, enc_idx );
68
82
  } else {
@@ -77,7 +91,7 @@ pg_tmas_s_allocate( VALUE klass )
77
91
  t_typemap *this;
78
92
  VALUE self;
79
93
 
80
- self = Data_Make_Struct( klass, t_typemap, NULL, -1, this );
94
+ self = TypedData_Make_Struct( klass, t_typemap, &pg_tmas_type, this );
81
95
 
82
96
  this->funcs.fit_to_result = pg_tmas_fit_to_result;
83
97
  this->funcs.fit_to_query = pg_tmas_fit_to_query;
@@ -91,7 +105,7 @@ pg_tmas_s_allocate( VALUE klass )
91
105
 
92
106
 
93
107
  void
94
- init_pg_type_map_all_strings()
108
+ init_pg_type_map_all_strings(void)
95
109
  {
96
110
  /*
97
111
  * Document-class: PG::TypeMapAllStrings < PG::TypeMap
@@ -111,6 +125,6 @@ init_pg_type_map_all_strings()
111
125
  rb_cTypeMapAllStrings = rb_define_class_under( rb_mPG, "TypeMapAllStrings", rb_cTypeMap );
112
126
  rb_define_alloc_func( rb_cTypeMapAllStrings, pg_tmas_s_allocate );
113
127
 
114
- pg_typemap_all_strings = rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 );
128
+ pg_typemap_all_strings = rb_obj_freeze( rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 ));
115
129
  rb_gc_register_address( &pg_typemap_all_strings );
116
130
  }