pg 0.18.1 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +5 -5
  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 +141 -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/BSDL +2 -2
  15. data/Gemfile +17 -0
  16. data/History.md +901 -0
  17. data/Manifest.txt +8 -21
  18. data/README-Windows.rdoc +17 -28
  19. data/README.ja.md +300 -0
  20. data/README.md +286 -0
  21. data/Rakefile +43 -131
  22. data/Rakefile.cross +89 -70
  23. data/certs/ged.pem +24 -0
  24. data/certs/kanis@comcard.de.pem +20 -0
  25. data/certs/larskanis-2022.pem +26 -0
  26. data/certs/larskanis-2023.pem +24 -0
  27. data/certs/larskanis-2024.pem +24 -0
  28. data/ext/errorcodes.def +113 -0
  29. data/ext/errorcodes.rb +1 -1
  30. data/ext/errorcodes.txt +36 -2
  31. data/ext/extconf.rb +128 -55
  32. data/ext/gvl_wrappers.c +8 -0
  33. data/ext/gvl_wrappers.h +44 -33
  34. data/ext/pg.c +228 -202
  35. data/ext/pg.h +108 -99
  36. data/ext/pg_binary_decoder.c +164 -16
  37. data/ext/pg_binary_encoder.c +249 -22
  38. data/ext/pg_coder.c +189 -44
  39. data/ext/pg_connection.c +1889 -1195
  40. data/ext/pg_copy_coder.c +398 -42
  41. data/ext/pg_errors.c +1 -1
  42. data/ext/pg_record_coder.c +522 -0
  43. data/ext/pg_result.c +729 -234
  44. data/ext/pg_text_decoder.c +635 -52
  45. data/ext/pg_text_encoder.c +294 -130
  46. data/ext/pg_tuple.c +572 -0
  47. data/ext/pg_type_map.c +64 -23
  48. data/ext/pg_type_map_all_strings.c +21 -7
  49. data/ext/pg_type_map_by_class.c +59 -27
  50. data/ext/pg_type_map_by_column.c +86 -43
  51. data/ext/pg_type_map_by_mri_type.c +50 -21
  52. data/ext/pg_type_map_by_oid.c +62 -29
  53. data/ext/pg_type_map_in_ruby.c +59 -28
  54. data/ext/{util.c → pg_util.c} +13 -13
  55. data/ext/{util.h → pg_util.h} +3 -3
  56. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  57. data/lib/pg/basic_type_map_for_queries.rb +202 -0
  58. data/lib/pg/basic_type_map_for_results.rb +104 -0
  59. data/lib/pg/basic_type_registry.rb +303 -0
  60. data/lib/pg/binary_decoder/date.rb +9 -0
  61. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  62. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  63. data/lib/pg/coder.rb +36 -13
  64. data/lib/pg/connection.rb +813 -74
  65. data/lib/pg/exceptions.rb +16 -2
  66. data/lib/pg/result.rb +24 -7
  67. data/lib/pg/text_decoder/date.rb +18 -0
  68. data/lib/pg/text_decoder/inet.rb +9 -0
  69. data/lib/pg/text_decoder/json.rb +14 -0
  70. data/lib/pg/text_decoder/numeric.rb +9 -0
  71. data/lib/pg/text_decoder/timestamp.rb +30 -0
  72. data/lib/pg/text_encoder/date.rb +12 -0
  73. data/lib/pg/text_encoder/inet.rb +28 -0
  74. data/lib/pg/text_encoder/json.rb +14 -0
  75. data/lib/pg/text_encoder/numeric.rb +9 -0
  76. data/lib/pg/text_encoder/timestamp.rb +24 -0
  77. data/lib/pg/tuple.rb +30 -0
  78. data/lib/pg/type_map_by_column.rb +3 -2
  79. data/lib/pg/version.rb +4 -0
  80. data/lib/pg.rb +106 -41
  81. data/misc/openssl-pg-segfault.rb +31 -0
  82. data/misc/postgres/History.txt +9 -0
  83. data/misc/postgres/Manifest.txt +5 -0
  84. data/misc/postgres/README.txt +21 -0
  85. data/misc/postgres/Rakefile +21 -0
  86. data/misc/postgres/lib/postgres.rb +16 -0
  87. data/misc/ruby-pg/History.txt +9 -0
  88. data/misc/ruby-pg/Manifest.txt +5 -0
  89. data/misc/ruby-pg/README.txt +21 -0
  90. data/misc/ruby-pg/Rakefile +21 -0
  91. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  92. data/pg.gemspec +34 -0
  93. data/rakelib/task_extension.rb +46 -0
  94. data/sample/array_insert.rb +1 -1
  95. data/sample/async_api.rb +4 -8
  96. data/sample/async_copyto.rb +1 -1
  97. data/sample/async_mixed.rb +1 -1
  98. data/sample/check_conn.rb +1 -1
  99. data/sample/copydata.rb +71 -0
  100. data/sample/copyfrom.rb +1 -1
  101. data/sample/copyto.rb +1 -1
  102. data/sample/cursor.rb +1 -1
  103. data/sample/disk_usage_report.rb +6 -15
  104. data/sample/issue-119.rb +2 -2
  105. data/sample/losample.rb +1 -1
  106. data/sample/minimal-testcase.rb +2 -2
  107. data/sample/notify_wait.rb +1 -1
  108. data/sample/pg_statistics.rb +6 -15
  109. data/sample/replication_monitor.rb +9 -18
  110. data/sample/test_binary_values.rb +1 -1
  111. data/sample/wal_shipper.rb +2 -2
  112. data/sample/warehouse_partitions.rb +8 -17
  113. data.tar.gz.sig +0 -0
  114. metadata +135 -207
  115. metadata.gz.sig +0 -0
  116. data/ChangeLog +0 -5378
  117. data/History.rdoc +0 -297
  118. data/README.ja.rdoc +0 -14
  119. data/README.rdoc +0 -161
  120. data/lib/pg/basic_type_mapping.rb +0 -399
  121. data/lib/pg/constants.rb +0 -11
  122. data/lib/pg/text_decoder.rb +0 -42
  123. data/lib/pg/text_encoder.rb +0 -27
  124. data/spec/data/expected_trace.out +0 -26
  125. data/spec/data/random_binary_data +0 -0
  126. data/spec/helpers.rb +0 -355
  127. data/spec/pg/basic_type_mapping_spec.rb +0 -251
  128. data/spec/pg/connection_spec.rb +0 -1459
  129. data/spec/pg/result_spec.rb +0 -449
  130. data/spec/pg/type_map_by_class_spec.rb +0 -138
  131. data/spec/pg/type_map_by_column_spec.rb +0 -222
  132. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  133. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  134. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  135. data/spec/pg/type_map_spec.rb +0 -22
  136. data/spec/pg/type_spec.rb +0 -665
  137. data/spec/pg_spec.rb +0 -50
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_type_map_by_column.c,v d369d31e8fe3 2014/10/22 08:47:29 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -16,7 +16,7 @@ static VALUE
16
16
  pg_tmbc_fit_to_result( VALUE self, VALUE result )
17
17
  {
18
18
  int nfields;
19
- t_tmbc *this = DATA_PTR( self );
19
+ t_tmbc *this = RTYPEDDATA_DATA( self );
20
20
  t_typemap *default_tm;
21
21
  VALUE sub_typemap;
22
22
 
@@ -26,8 +26,8 @@ pg_tmbc_fit_to_result( VALUE self, VALUE result )
26
26
  nfields, this->nfields );
27
27
  }
28
28
 
29
- /* Ensure that the default type map fits equaly. */
30
- default_tm = DATA_PTR( this->typemap.default_typemap );
29
+ /* Ensure that the default type map fits equally. */
30
+ default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
31
31
  sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );
32
32
 
33
33
  /* Did the default type return the same object ? */
@@ -42,7 +42,7 @@ pg_tmbc_fit_to_result( VALUE self, VALUE result )
42
42
 
43
43
  memcpy( p_new_typemap, this, struct_size );
44
44
  p_new_typemap->typemap.default_typemap = sub_typemap;
45
- DATA_PTR(new_typemap) = p_new_typemap;
45
+ RTYPEDDATA_DATA(new_typemap) = p_new_typemap;
46
46
  return new_typemap;
47
47
  }
48
48
  }
@@ -51,7 +51,7 @@ static VALUE
51
51
  pg_tmbc_fit_to_query( VALUE self, VALUE params )
52
52
  {
53
53
  int nfields;
54
- t_tmbc *this = DATA_PTR( self );
54
+ t_tmbc *this = RTYPEDDATA_DATA( self );
55
55
  t_typemap *default_tm;
56
56
 
57
57
  nfields = (int)RARRAY_LEN( params );
@@ -60,8 +60,8 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
60
60
  nfields, this->nfields );
61
61
  }
62
62
 
63
- /* Ensure that the default type map fits equaly. */
64
- default_tm = DATA_PTR( this->typemap.default_typemap );
63
+ /* Ensure that the default type map fits equally. */
64
+ default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
65
65
  default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
66
66
 
67
67
  return self;
@@ -70,10 +70,10 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
70
70
  static int
71
71
  pg_tmbc_fit_to_copy_get( VALUE self )
72
72
  {
73
- t_tmbc *this = DATA_PTR( self );
73
+ t_tmbc *this = RTYPEDDATA_DATA( self );
74
74
 
75
- /* Ensure that the default type map fits equaly. */
76
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
75
+ /* Ensure that the default type map fits equally. */
76
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
77
77
  default_tm->funcs.fit_to_copy_get( this->typemap.default_typemap );
78
78
 
79
79
  return this->nfields;
@@ -99,15 +99,15 @@ pg_tmbc_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
99
99
  int len = PQgetlength( p_result->pgresult, tuple, field );
100
100
 
101
101
  if( p_coder->dec_func ){
102
- return p_coder->dec_func(p_coder, val, len, tuple, field, ENCODING_GET(result));
102
+ return p_coder->dec_func(p_coder, val, len, tuple, field, p_result->enc_idx);
103
103
  } else {
104
104
  t_pg_coder_dec_func dec_func;
105
105
  dec_func = pg_coder_dec_func( p_coder, PQfformat(p_result->pgresult, field) );
106
- return dec_func(p_coder, val, len, tuple, field, ENCODING_GET(result));
106
+ return dec_func(p_coder, val, len, tuple, field, p_result->enc_idx);
107
107
  }
108
108
  }
109
109
 
110
- default_tm = DATA_PTR( this->typemap.default_typemap );
110
+ default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
111
111
  return default_tm->funcs.typecast_result_value( default_tm, result, tuple, field );
112
112
  }
113
113
 
@@ -120,7 +120,7 @@ pg_tmbc_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field
120
120
  t_pg_coder *p_coder = this->convs[field].cconv;
121
121
 
122
122
  if( !p_coder ){
123
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
123
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
124
124
  return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
125
125
  }
126
126
 
@@ -142,7 +142,7 @@ pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, i
142
142
  p_coder = this->convs[fieldno].cconv;
143
143
 
144
144
  if( !p_coder ){
145
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
145
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
146
146
  return default_tm->funcs.typecast_copy_get( default_tm, field_str, fieldno, format, enc_idx );
147
147
  }
148
148
 
@@ -150,59 +150,100 @@ pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, i
150
150
 
151
151
  /* Is it a pure String conversion? Then we can directly send field_str to the user. */
152
152
  if( dec_func == pg_text_dec_string ){
153
+ rb_str_modify(field_str);
153
154
  PG_ENCODING_SET_NOCHECK( field_str, enc_idx );
154
155
  return field_str;
155
156
  }
156
157
  if( dec_func == pg_bin_dec_bytea ){
158
+ rb_str_modify(field_str);
157
159
  PG_ENCODING_SET_NOCHECK( field_str, rb_ascii8bit_encindex() );
158
160
  return field_str;
159
161
  }
160
162
 
161
- return dec_func( p_coder, RSTRING_PTR(field_str), RSTRING_LEN(field_str), 0, fieldno, enc_idx );
163
+ return dec_func( p_coder, RSTRING_PTR(field_str), RSTRING_LENINT(field_str), 0, fieldno, enc_idx );
162
164
  }
163
165
 
164
166
  const struct pg_typemap_funcs pg_tmbc_funcs = {
165
- .fit_to_result = pg_tmbc_fit_to_result,
166
- .fit_to_query = pg_tmbc_fit_to_query,
167
- .fit_to_copy_get = pg_tmbc_fit_to_copy_get,
168
- .typecast_result_value = pg_tmbc_result_value,
169
- .typecast_query_param = pg_tmbc_typecast_query_param,
170
- .typecast_copy_get = pg_tmbc_typecast_copy_get
167
+ pg_tmbc_fit_to_result,
168
+ pg_tmbc_fit_to_query,
169
+ pg_tmbc_fit_to_copy_get,
170
+ pg_tmbc_result_value,
171
+ pg_tmbc_typecast_query_param,
172
+ pg_tmbc_typecast_copy_get
171
173
  };
172
174
 
173
175
  static void
174
- pg_tmbc_mark( t_tmbc *this )
176
+ pg_tmbc_mark( void *_this )
175
177
  {
178
+ t_tmbc *this = (t_tmbc *)_this;
176
179
  int i;
177
180
 
178
181
  /* allocated but not initialized ? */
179
182
  if( this == (t_tmbc *)&pg_typemap_funcs ) return;
180
183
 
181
- rb_gc_mark(this->typemap.default_typemap);
184
+ pg_typemap_mark(&this->typemap);
182
185
  for( i=0; i<this->nfields; i++){
183
186
  t_pg_coder *p_coder = this->convs[i].cconv;
184
187
  if( p_coder )
185
- rb_gc_mark(p_coder->coder_obj);
188
+ rb_gc_mark_movable(p_coder->coder_obj);
189
+ }
190
+ }
191
+
192
+ static size_t
193
+ pg_tmbc_memsize( const void *_this )
194
+ {
195
+ const t_tmbc *this = (const t_tmbc *)_this;
196
+ return sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * this->nfields;
197
+ }
198
+
199
+ static void
200
+ pg_tmbc_compact( void *_this )
201
+ {
202
+ t_tmbc *this = (t_tmbc *)_this;
203
+ int i;
204
+
205
+ /* allocated but not initialized ? */
206
+ if( this == (t_tmbc *)&pg_typemap_funcs ) return;
207
+
208
+ pg_typemap_compact(&this->typemap);
209
+ for( i=0; i<this->nfields; i++){
210
+ t_pg_coder *p_coder = this->convs[i].cconv;
211
+ if( p_coder )
212
+ pg_gc_location(p_coder->coder_obj);
186
213
  }
187
214
  }
188
215
 
189
216
  static void
190
- pg_tmbc_free( t_tmbc *this )
217
+ pg_tmbc_free( void *_this )
191
218
  {
219
+ t_tmbc *this = (t_tmbc *)_this;
192
220
  /* allocated but not initialized ? */
193
221
  if( this == (t_tmbc *)&pg_typemap_funcs ) return;
194
222
  xfree( this );
195
223
  }
196
224
 
225
+ static const rb_data_type_t pg_tmbc_type = {
226
+ "PG::TypeMapByColumn",
227
+ {
228
+ pg_tmbc_mark,
229
+ pg_tmbc_free,
230
+ pg_tmbc_memsize,
231
+ pg_compact_callback(pg_tmbc_compact),
232
+ },
233
+ &pg_typemap_type,
234
+ 0,
235
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
236
+ };
237
+
197
238
  static VALUE
198
239
  pg_tmbc_s_allocate( VALUE klass )
199
240
  {
200
241
  /* Use pg_typemap_funcs as interim struct until #initialize is called. */
201
- return Data_Wrap_Struct( klass, pg_tmbc_mark, pg_tmbc_free, (t_tmbc *)&pg_typemap_funcs );
242
+ return TypedData_Wrap_Struct( klass, &pg_tmbc_type, (t_tmbc *)&pg_typemap_funcs );
202
243
  }
203
244
 
204
245
  VALUE
205
- pg_tmbc_allocate()
246
+ pg_tmbc_allocate(void)
206
247
  {
207
248
  return pg_tmbc_s_allocate(rb_cTypeMapByColumn);
208
249
  }
@@ -221,19 +262,19 @@ pg_tmbc_allocate()
221
262
  static VALUE
222
263
  pg_tmbc_init(VALUE self, VALUE conv_ary)
223
264
  {
224
- int i;
265
+ long i;
225
266
  t_tmbc *this;
226
267
  int conv_ary_len;
227
268
 
228
- Check_Type(self, T_DATA);
269
+ rb_check_frozen(self);
229
270
  Check_Type(conv_ary, T_ARRAY);
230
- conv_ary_len = RARRAY_LEN(conv_ary);
271
+ conv_ary_len = RARRAY_LENINT(conv_ary);
231
272
  this = xmalloc(sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * conv_ary_len);
232
273
  /* Set nfields to 0 at first, so that GC mark function doesn't access uninitialized memory. */
233
274
  this->nfields = 0;
234
275
  this->typemap.funcs = pg_tmbc_funcs;
235
- this->typemap.default_typemap = pg_typemap_all_strings;
236
- DATA_PTR(self) = this;
276
+ RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
277
+ RTYPEDDATA_DATA(self) = this;
237
278
 
238
279
  for(i=0; i<conv_ary_len; i++)
239
280
  {
@@ -242,11 +283,12 @@ pg_tmbc_init(VALUE self, VALUE conv_ary)
242
283
  if( obj == Qnil ){
243
284
  /* no type cast */
244
285
  this->convs[i].cconv = NULL;
245
- } else if( rb_obj_is_kind_of(obj, rb_cPG_Coder) ){
246
- Data_Get_Struct(obj, t_pg_coder, this->convs[i].cconv);
247
286
  } else {
248
- rb_raise(rb_eArgError, "argument %d has invalid type %s (should be nil or some kind of PG::Coder)",
249
- i+1, rb_obj_classname( obj ));
287
+ t_pg_coder *p_coder;
288
+ /* Check argument type and store the coder pointer */
289
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
290
+ RB_OBJ_WRITTEN(self, Qnil, p_coder->coder_obj);
291
+ this->convs[i].cconv = p_coder;
250
292
  }
251
293
  }
252
294
 
@@ -266,7 +308,7 @@ static VALUE
266
308
  pg_tmbc_coders(VALUE self)
267
309
  {
268
310
  int i;
269
- t_tmbc *this = DATA_PTR( self );
311
+ t_tmbc *this = RTYPEDDATA_DATA( self );
270
312
  VALUE ary_coders = rb_ary_new();
271
313
 
272
314
  for( i=0; i<this->nfields; i++){
@@ -282,7 +324,7 @@ pg_tmbc_coders(VALUE self)
282
324
  }
283
325
 
284
326
  void
285
- init_pg_type_map_by_column()
327
+ init_pg_type_map_by_column(void)
286
328
  {
287
329
  s_id_decode = rb_intern("decode");
288
330
  s_id_encode = rb_intern("encode");
@@ -292,13 +334,13 @@ init_pg_type_map_by_column()
292
334
  *
293
335
  * This type map casts values by a coder assigned per field/column.
294
336
  *
295
- * Each PG:TypeMapByColumn has a fixed list of either encoders or decoders,
296
- * that is defined at #new . A type map with encoders is usable for type casting
337
+ * Each PG::TypeMapByColumn has a fixed list of either encoders or decoders,
338
+ * that is defined at TypeMapByColumn.new . A type map with encoders is usable for type casting
297
339
  * query bind parameters and COPY data for PG::Connection#put_copy_data .
298
340
  * A type map with decoders is usable for type casting of result values and
299
341
  * COPY data from PG::Connection#get_copy_data .
300
342
  *
301
- * PG::TypeMapByColumns are in particular useful in conjunction with prepared statements,
343
+ * PG::TypeMapByColumn objects are in particular useful in conjunction with prepared statements,
302
344
  * since they can be cached alongside with the statement handle.
303
345
  *
304
346
  * This type map strategy is also used internally by PG::TypeMapByOid, when the
@@ -308,5 +350,6 @@ init_pg_type_map_by_column()
308
350
  rb_define_alloc_func( rb_cTypeMapByColumn, pg_tmbc_s_allocate );
309
351
  rb_define_method( rb_cTypeMapByColumn, "initialize", pg_tmbc_init, 1 );
310
352
  rb_define_method( rb_cTypeMapByColumn, "coders", pg_tmbc_coders, 0 );
353
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
311
354
  rb_include_module( rb_cTypeMapByColumn, rb_mDefaultTypeMappable );
312
355
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_by_mri_type.c - PG::TypeMapByMriType class extension
3
- * $Id: pg_type_map_by_mri_type.c,v 27987dbd0b32 2014/11/07 20:55:52 lars $
3
+ * $Id$
4
4
  *
5
5
  * This type map can be used to select value encoders based on the MRI-internal
6
6
  * value type code.
@@ -39,7 +39,7 @@ static VALUE rb_cTypeMapByMriType;
39
39
  typedef struct {
40
40
  t_typemap typemap;
41
41
  struct pg_tmbmt_converter {
42
- FOR_EACH_MRI_TYPE( DECLARE_CODER );
42
+ FOR_EACH_MRI_TYPE( DECLARE_CODER )
43
43
  } coders;
44
44
  } t_tmbmt;
45
45
 
@@ -71,16 +71,12 @@ pg_tmbmt_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int fiel
71
71
 
72
72
  obj = rb_funcall(ask_for_coder, rb_intern("call"), 1, param_value);
73
73
 
74
- if( rb_obj_is_kind_of(obj, rb_cPG_Coder) ){
75
- Data_Get_Struct(obj, t_pg_coder, p_coder);
76
- }else{
77
- rb_raise(rb_eTypeError, "argument %d has invalid type %s (should be nil or some kind of PG::Coder)",
78
- field+1, rb_obj_classname( obj ));
79
- }
74
+ /* Check argument type and store the coder pointer */
75
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
80
76
  }
81
77
 
82
78
  if( !p_coder ){
83
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
79
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
84
80
  return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
85
81
  }
86
82
 
@@ -90,24 +86,57 @@ pg_tmbmt_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int fiel
90
86
  static VALUE
91
87
  pg_tmbmt_fit_to_query( VALUE self, VALUE params )
92
88
  {
93
- t_tmbmt *this = (t_tmbmt *)DATA_PTR(self);
89
+ t_tmbmt *this = (t_tmbmt *)RTYPEDDATA_DATA(self);
94
90
  /* Nothing to check at this typemap, but ensure that the default type map fits. */
95
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
91
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
96
92
  default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
97
93
  return self;
98
94
  }
99
95
 
100
96
  #define GC_MARK_AS_USED(type) \
101
- rb_gc_mark( this->coders.ask_##type ); \
102
- rb_gc_mark( this->coders.coder_obj_##type );
97
+ rb_gc_mark_movable( this->coders.ask_##type ); \
98
+ rb_gc_mark_movable( this->coders.coder_obj_##type );
103
99
 
104
100
  static void
105
- pg_tmbmt_mark( t_tmbmt *this )
101
+ pg_tmbmt_mark( void *_this )
106
102
  {
107
- rb_gc_mark(this->typemap.default_typemap);
103
+ t_tmbmt *this = (t_tmbmt *)_this;
104
+ pg_typemap_mark(&this->typemap);
108
105
  FOR_EACH_MRI_TYPE( GC_MARK_AS_USED );
109
106
  }
110
107
 
108
+ static size_t
109
+ pg_tmbmt_memsize( const void *_this )
110
+ {
111
+ const t_tmbmt *this = (const t_tmbmt *)_this;
112
+ return sizeof(*this);
113
+ }
114
+
115
+ #define GC_COMPACT(type) \
116
+ pg_gc_location( this->coders.ask_##type ); \
117
+ pg_gc_location( this->coders.coder_obj_##type );
118
+
119
+ static void
120
+ pg_tmbmt_compact( void *_this )
121
+ {
122
+ t_tmbmt *this = (t_tmbmt *)_this;
123
+ pg_typemap_compact(&this->typemap);
124
+ FOR_EACH_MRI_TYPE( GC_COMPACT );
125
+ }
126
+
127
+ static const rb_data_type_t pg_tmbmt_type = {
128
+ "PG::TypeMapByMriType",
129
+ {
130
+ pg_tmbmt_mark,
131
+ RUBY_TYPED_DEFAULT_FREE,
132
+ pg_tmbmt_memsize,
133
+ pg_compact_callback(pg_tmbmt_compact),
134
+ },
135
+ &pg_typemap_type,
136
+ 0,
137
+ RUBY_TYPED_FREE_IMMEDIATELY,
138
+ };
139
+
111
140
  #define INIT_VARIABLES(type) \
112
141
  this->coders.coder_##type = NULL; \
113
142
  this->coders.ask_##type = Qnil; \
@@ -119,7 +148,7 @@ pg_tmbmt_s_allocate( VALUE klass )
119
148
  t_tmbmt *this;
120
149
  VALUE self;
121
150
 
122
- self = Data_Make_Struct( klass, t_tmbmt, pg_tmbmt_mark, -1, this );
151
+ self = TypedData_Make_Struct( klass, t_tmbmt, &pg_tmbmt_type, this );
123
152
  this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
124
153
  this->typemap.funcs.fit_to_query = pg_tmbmt_fit_to_query;
125
154
  this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
@@ -140,7 +169,7 @@ pg_tmbmt_s_allocate( VALUE klass )
140
169
  this->coders.coder_##type = NULL; \
141
170
  this->coders.ask_##type = Qnil; \
142
171
  }else if(rb_obj_is_kind_of(coder, rb_cPG_Coder)){ \
143
- Data_Get_Struct(coder, t_pg_coder, this->coders.coder_##type); \
172
+ TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, this->coders.coder_##type); \
144
173
  this->coders.ask_##type = Qnil; \
145
174
  }else if(RB_TYPE_P(coder, T_SYMBOL)){ \
146
175
  this->coders.coder_##type = NULL; \
@@ -188,7 +217,7 @@ pg_tmbmt_s_allocate( VALUE klass )
188
217
  static VALUE
189
218
  pg_tmbmt_aset( VALUE self, VALUE mri_type, VALUE coder )
190
219
  {
191
- t_tmbmt *this = DATA_PTR( self );
220
+ t_tmbmt *this = RTYPEDDATA_DATA( self );
192
221
  char *p_mri_type;
193
222
 
194
223
  p_mri_type = StringValueCStr(mri_type);
@@ -220,7 +249,7 @@ static VALUE
220
249
  pg_tmbmt_aref( VALUE self, VALUE mri_type )
221
250
  {
222
251
  VALUE coder;
223
- t_tmbmt *this = DATA_PTR( self );
252
+ t_tmbmt *this = RTYPEDDATA_DATA( self );
224
253
  char *p_mri_type;
225
254
 
226
255
  p_mri_type = StringValueCStr(mri_type);
@@ -248,7 +277,7 @@ pg_tmbmt_aref( VALUE self, VALUE mri_type )
248
277
  static VALUE
249
278
  pg_tmbmt_coders( VALUE self )
250
279
  {
251
- t_tmbmt *this = DATA_PTR( self );
280
+ t_tmbmt *this = RTYPEDDATA_DATA( self );
252
281
  VALUE hash_coders = rb_hash_new();
253
282
 
254
283
  FOR_EACH_MRI_TYPE( ADD_TO_HASH );
@@ -257,7 +286,7 @@ pg_tmbmt_coders( VALUE self )
257
286
  }
258
287
 
259
288
  void
260
- init_pg_type_map_by_mri_type()
289
+ init_pg_type_map_by_mri_type(void)
261
290
  {
262
291
  /*
263
292
  * Document-class: PG::TypeMapByMriType < PG::TypeMap
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_by_oid.c - PG::TypeMapByOid class extension
3
- * $Id: pg_type_map_by_oid.c,v c99d26015e3c 2014/12/12 20:58:25 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -46,7 +46,7 @@ pg_tmbo_lookup_oid(t_tmbo *this, int format, Oid oid)
46
46
  } else {
47
47
  VALUE obj = rb_hash_lookup( this->format[format].oid_to_coder, UINT2NUM( oid ));
48
48
  /* obj must be nil or some kind of PG::Coder, this is checked at insertion */
49
- conv = NIL_P(obj) ? NULL : DATA_PTR(obj);
49
+ conv = NIL_P(obj) ? NULL : RTYPEDDATA_DATA(obj);
50
50
  /* Write the retrieved coder to the cache */
51
51
  p_ce->oid = oid;
52
52
  p_ce->p_coder = conv;
@@ -70,7 +70,7 @@ pg_tmbo_build_type_map_for_result2( t_tmbo *this, PGresult *pgresult )
70
70
  p_colmap->typemap.default_typemap = pg_typemap_all_strings;
71
71
 
72
72
  colmap = pg_tmbc_allocate();
73
- DATA_PTR(colmap) = p_colmap;
73
+ RTYPEDDATA_DATA(colmap) = p_colmap;
74
74
 
75
75
  for(i=0; i<nfields; i++)
76
76
  {
@@ -110,21 +110,21 @@ pg_tmbo_result_value(t_typemap *p_typemap, VALUE result, int tuple, int field)
110
110
  char * val = PQgetvalue( p_result->pgresult, tuple, field );
111
111
  int len = PQgetlength( p_result->pgresult, tuple, field );
112
112
  t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, format );
113
- return dec_func( p_coder, val, len, tuple, field, ENCODING_GET(result) );
113
+ return dec_func( p_coder, val, len, tuple, field, p_result->enc_idx );
114
114
  }
115
115
 
116
- default_tm = DATA_PTR( this->typemap.default_typemap );
116
+ default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
117
117
  return default_tm->funcs.typecast_result_value( default_tm, result, tuple, field );
118
118
  }
119
119
 
120
120
  static VALUE
121
121
  pg_tmbo_fit_to_result( VALUE self, VALUE result )
122
122
  {
123
- t_tmbo *this = DATA_PTR( self );
123
+ t_tmbo *this = RTYPEDDATA_DATA( self );
124
124
  PGresult *pgresult = pgresult_get( result );
125
125
 
126
- /* Ensure that the default type map fits equaly. */
127
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
126
+ /* Ensure that the default type map fits equally. */
127
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
128
128
  VALUE sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );
129
129
 
130
130
  if( PQntuples( pgresult ) <= this->max_rows_for_online_lookup ){
@@ -137,7 +137,7 @@ pg_tmbo_fit_to_result( VALUE self, VALUE result )
137
137
  /* The default type map built a new object, so we need to propagate it
138
138
  * and build a copy of this type map. */
139
139
  VALUE new_typemap = pg_tmbo_s_allocate( rb_cTypeMapByOid );
140
- t_tmbo *p_new_typemap = DATA_PTR(new_typemap);
140
+ t_tmbo *p_new_typemap = RTYPEDDATA_DATA(new_typemap);
141
141
  *p_new_typemap = *this;
142
142
  p_new_typemap->typemap.default_typemap = sub_typemap;
143
143
  return new_typemap;
@@ -147,23 +147,56 @@ pg_tmbo_fit_to_result( VALUE self, VALUE result )
147
147
  * uses a fast array lookup.
148
148
  */
149
149
  VALUE new_typemap = pg_tmbo_build_type_map_for_result2( this, pgresult );
150
- t_tmbo *p_new_typemap = DATA_PTR(new_typemap);
150
+ t_tmbo *p_new_typemap = RTYPEDDATA_DATA(new_typemap);
151
151
  p_new_typemap->typemap.default_typemap = sub_typemap;
152
152
  return new_typemap;
153
153
  }
154
154
  }
155
155
 
156
156
  static void
157
- pg_tmbo_mark( t_tmbo *this )
157
+ pg_tmbo_mark( void *_this )
158
158
  {
159
+ t_tmbo *this = (t_tmbo *)_this;
159
160
  int i;
160
161
 
161
- rb_gc_mark(this->typemap.default_typemap);
162
+ pg_typemap_mark(&this->typemap);
162
163
  for( i=0; i<2; i++){
163
- rb_gc_mark(this->format[i].oid_to_coder);
164
+ rb_gc_mark_movable(this->format[i].oid_to_coder);
164
165
  }
165
166
  }
166
167
 
168
+ static size_t
169
+ pg_tmbo_memsize( const void *_this )
170
+ {
171
+ const t_tmbo *this = (const t_tmbo *)_this;
172
+ return sizeof(*this);
173
+ }
174
+
175
+ static void
176
+ pg_tmbo_compact( void *_this )
177
+ {
178
+ t_tmbo *this = (t_tmbo *)_this;
179
+ int i;
180
+
181
+ pg_typemap_compact(&this->typemap);
182
+ for( i=0; i<2; i++){
183
+ pg_gc_location(this->format[i].oid_to_coder);
184
+ }
185
+ }
186
+
187
+ static const rb_data_type_t pg_tmbo_type = {
188
+ "PG::TypeMapByOid",
189
+ {
190
+ pg_tmbo_mark,
191
+ RUBY_TYPED_DEFAULT_FREE,
192
+ pg_tmbo_memsize,
193
+ pg_compact_callback(pg_tmbo_compact),
194
+ },
195
+ &pg_typemap_type,
196
+ 0,
197
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
198
+ };
199
+
167
200
  static VALUE
168
201
  pg_tmbo_s_allocate( VALUE klass )
169
202
  {
@@ -171,7 +204,7 @@ pg_tmbo_s_allocate( VALUE klass )
171
204
  VALUE self;
172
205
  int i;
173
206
 
174
- self = Data_Make_Struct( klass, t_tmbo, pg_tmbo_mark, -1, this );
207
+ self = TypedData_Make_Struct( klass, t_tmbo, &pg_tmbo_type, this );
175
208
 
176
209
  this->typemap.funcs.fit_to_result = pg_tmbo_fit_to_result;
177
210
  this->typemap.funcs.fit_to_query = pg_typemap_fit_to_query;
@@ -179,11 +212,11 @@ pg_tmbo_s_allocate( VALUE klass )
179
212
  this->typemap.funcs.typecast_result_value = pg_tmbo_result_value;
180
213
  this->typemap.funcs.typecast_query_param = pg_typemap_typecast_query_param;
181
214
  this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
182
- this->typemap.default_typemap = pg_typemap_all_strings;
215
+ RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
183
216
  this->max_rows_for_online_lookup = 10;
184
217
 
185
218
  for( i=0; i<2; i++){
186
- this->format[i].oid_to_coder = rb_hash_new();
219
+ RB_OBJ_WRITE(self, &this->format[i].oid_to_coder, rb_hash_new());
187
220
  }
188
221
 
189
222
  return self;
@@ -205,15 +238,12 @@ static VALUE
205
238
  pg_tmbo_add_coder( VALUE self, VALUE coder )
206
239
  {
207
240
  VALUE hash;
208
- t_tmbo *this = DATA_PTR( self );
241
+ t_tmbo *this = RTYPEDDATA_DATA( self );
209
242
  t_pg_coder *p_coder;
210
243
  struct pg_tmbo_oid_cache_entry *p_ce;
211
244
 
212
- if( !rb_obj_is_kind_of(coder, rb_cPG_Coder) )
213
- rb_raise(rb_eArgError, "invalid type %s (should be some kind of PG::Coder)",
214
- rb_obj_classname( coder ));
215
-
216
- Data_Get_Struct(coder, t_pg_coder, p_coder);
245
+ rb_check_frozen(self);
246
+ TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, p_coder);
217
247
 
218
248
  if( p_coder->format < 0 || p_coder->format > 1 )
219
249
  rb_raise(rb_eArgError, "invalid format code %d", p_coder->format);
@@ -243,10 +273,11 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
243
273
  {
244
274
  VALUE hash;
245
275
  VALUE coder;
246
- t_tmbo *this = DATA_PTR( self );
276
+ t_tmbo *this = RTYPEDDATA_DATA( self );
247
277
  int i_format = NUM2INT(format);
248
278
  struct pg_tmbo_oid_cache_entry *p_ce;
249
279
 
280
+ rb_check_frozen(self);
250
281
  if( i_format < 0 || i_format > 1 )
251
282
  rb_raise(rb_eArgError, "invalid format code %d", i_format);
252
283
 
@@ -269,7 +300,7 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
269
300
  static VALUE
270
301
  pg_tmbo_coders( VALUE self )
271
302
  {
272
- t_tmbo *this = DATA_PTR( self );
303
+ t_tmbo *this = RTYPEDDATA_DATA( self );
273
304
 
274
305
  return rb_ary_concat(
275
306
  rb_funcall(this->format[0].oid_to_coder, rb_intern("values"), 0),
@@ -288,7 +319,8 @@ pg_tmbo_coders( VALUE self )
288
319
  static VALUE
289
320
  pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
290
321
  {
291
- t_tmbo *this = DATA_PTR( self );
322
+ t_tmbo *this = RTYPEDDATA_DATA( self );
323
+ rb_check_frozen(self);
292
324
  this->max_rows_for_online_lookup = NUM2INT(value);
293
325
  return value;
294
326
  }
@@ -300,7 +332,7 @@ pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
300
332
  static VALUE
301
333
  pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
302
334
  {
303
- t_tmbo *this = DATA_PTR( self );
335
+ t_tmbo *this = RTYPEDDATA_DATA( self );
304
336
  return INT2NUM(this->max_rows_for_online_lookup);
305
337
  }
306
338
 
@@ -309,13 +341,13 @@ pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
309
341
  * typemap.build_column_map( result )
310
342
  *
311
343
  * This builds a PG::TypeMapByColumn that fits to the given PG::Result object
312
- * based on it's type OIDs.
344
+ * based on it's type OIDs and binary/text format.
313
345
  *
314
346
  */
315
347
  static VALUE
316
348
  pg_tmbo_build_column_map( VALUE self, VALUE result )
317
349
  {
318
- t_tmbo *this = DATA_PTR( self );
350
+ t_tmbo *this = RTYPEDDATA_DATA( self );
319
351
 
320
352
  if ( !rb_obj_is_kind_of(result, rb_cPGresult) ) {
321
353
  rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Result)",
@@ -327,7 +359,7 @@ pg_tmbo_build_column_map( VALUE self, VALUE result )
327
359
 
328
360
 
329
361
  void
330
- init_pg_type_map_by_oid()
362
+ init_pg_type_map_by_oid(void)
331
363
  {
332
364
  s_id_decode = rb_intern("decode");
333
365
 
@@ -351,5 +383,6 @@ init_pg_type_map_by_oid()
351
383
  rb_define_method( rb_cTypeMapByOid, "max_rows_for_online_lookup=", pg_tmbo_max_rows_for_online_lookup_set, 1 );
352
384
  rb_define_method( rb_cTypeMapByOid, "max_rows_for_online_lookup", pg_tmbo_max_rows_for_online_lookup_get, 0 );
353
385
  rb_define_method( rb_cTypeMapByOid, "build_column_map", pg_tmbo_build_column_map, 1 );
386
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
354
387
  rb_include_module( rb_cTypeMapByOid, rb_mDefaultTypeMappable );
355
388
  }