pg 1.2.3 → 1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) 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 +19 -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 +804 -0
  16. data/Manifest.txt +0 -1
  17. data/README.ja.md +266 -0
  18. data/README.md +272 -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 +62 -29
  31. data/ext/pg.h +20 -1
  32. data/ext/pg_binary_decoder.c +1 -1
  33. data/ext/pg_binary_encoder.c +1 -1
  34. data/ext/pg_coder.c +83 -29
  35. data/ext/pg_connection.c +953 -670
  36. data/ext/pg_copy_coder.c +46 -17
  37. data/ext/pg_errors.c +1 -1
  38. data/ext/pg_record_coder.c +46 -16
  39. data/ext/pg_result.c +88 -49
  40. data/ext/pg_text_decoder.c +2 -2
  41. data/ext/pg_text_encoder.c +7 -7
  42. data/ext/pg_tuple.c +50 -30
  43. data/ext/pg_type_map.c +42 -9
  44. data/ext/pg_type_map_all_strings.c +16 -2
  45. data/ext/pg_type_map_by_class.c +50 -25
  46. data/ext/pg_type_map_by_column.c +68 -30
  47. data/ext/pg_type_map_by_mri_type.c +48 -19
  48. data/ext/pg_type_map_by_oid.c +53 -24
  49. data/ext/pg_type_map_in_ruby.c +51 -20
  50. data/ext/pg_util.c +2 -2
  51. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  52. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  53. data/lib/pg/basic_type_map_for_results.rb +81 -0
  54. data/lib/pg/basic_type_registry.rb +301 -0
  55. data/lib/pg/coder.rb +1 -1
  56. data/lib/pg/connection.rb +669 -81
  57. data/lib/pg/exceptions.rb +14 -1
  58. data/lib/pg/version.rb +4 -0
  59. data/lib/pg.rb +45 -36
  60. data/misc/openssl-pg-segfault.rb +31 -0
  61. data/misc/postgres/History.txt +9 -0
  62. data/misc/postgres/Manifest.txt +5 -0
  63. data/misc/postgres/README.txt +21 -0
  64. data/misc/postgres/Rakefile +21 -0
  65. data/misc/postgres/lib/postgres.rb +16 -0
  66. data/misc/ruby-pg/History.txt +9 -0
  67. data/misc/ruby-pg/Manifest.txt +5 -0
  68. data/misc/ruby-pg/README.txt +21 -0
  69. data/misc/ruby-pg/Rakefile +21 -0
  70. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  71. data/pg.gemspec +34 -0
  72. data/rakelib/task_extension.rb +46 -0
  73. data/sample/array_insert.rb +20 -0
  74. data/sample/async_api.rb +102 -0
  75. data/sample/async_copyto.rb +39 -0
  76. data/sample/async_mixed.rb +56 -0
  77. data/sample/check_conn.rb +21 -0
  78. data/sample/copydata.rb +71 -0
  79. data/sample/copyfrom.rb +81 -0
  80. data/sample/copyto.rb +19 -0
  81. data/sample/cursor.rb +21 -0
  82. data/sample/disk_usage_report.rb +177 -0
  83. data/sample/issue-119.rb +94 -0
  84. data/sample/losample.rb +69 -0
  85. data/sample/minimal-testcase.rb +17 -0
  86. data/sample/notify_wait.rb +72 -0
  87. data/sample/pg_statistics.rb +285 -0
  88. data/sample/replication_monitor.rb +222 -0
  89. data/sample/test_binary_values.rb +33 -0
  90. data/sample/wal_shipper.rb +434 -0
  91. data/sample/warehouse_partitions.rb +311 -0
  92. data/translation/.po4a-version +7 -0
  93. data/translation/po/all.pot +875 -0
  94. data/translation/po/ja.po +868 -0
  95. data/translation/po4a.cfg +9 -0
  96. data.tar.gz.sig +0 -0
  97. metadata +120 -206
  98. metadata.gz.sig +0 -0
  99. data/ChangeLog +0 -0
  100. data/History.rdoc +0 -578
  101. data/README.ja.rdoc +0 -13
  102. data/README.rdoc +0 -213
  103. data/lib/pg/basic_type_mapping.rb +0 -522
  104. data/spec/data/expected_trace.out +0 -26
  105. data/spec/data/random_binary_data +0 -0
  106. data/spec/helpers.rb +0 -380
  107. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  108. data/spec/pg/connection_spec.rb +0 -1949
  109. data/spec/pg/connection_sync_spec.rb +0 -41
  110. data/spec/pg/result_spec.rb +0 -681
  111. data/spec/pg/tuple_spec.rb +0 -333
  112. data/spec/pg/type_map_by_class_spec.rb +0 -138
  113. data/spec/pg/type_map_by_column_spec.rb +0 -226
  114. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  115. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  116. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  117. data/spec/pg/type_map_spec.rb +0 -22
  118. data/spec/pg/type_spec.rb +0 -1123
  119. data/spec/pg_spec.rb +0 -50
@@ -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;
@@ -107,7 +107,7 @@ pg_tmbc_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
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,15 +150,17 @@ 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 = {
@@ -171,38 +173,77 @@ const struct pg_typemap_funcs pg_tmbc_funcs = {
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,
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,18 @@ 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);
229
269
  Check_Type(conv_ary, T_ARRAY);
230
- conv_ary_len = RARRAY_LEN(conv_ary);
270
+ conv_ary_len = RARRAY_LENINT(conv_ary);
231
271
  this = xmalloc(sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * conv_ary_len);
232
272
  /* Set nfields to 0 at first, so that GC mark function doesn't access uninitialized memory. */
233
273
  this->nfields = 0;
234
274
  this->typemap.funcs = pg_tmbc_funcs;
235
275
  this->typemap.default_typemap = pg_typemap_all_strings;
236
- DATA_PTR(self) = this;
276
+ RTYPEDDATA_DATA(self) = this;
237
277
 
238
278
  for(i=0; i<conv_ary_len; i++)
239
279
  {
@@ -242,11 +282,9 @@ pg_tmbc_init(VALUE self, VALUE conv_ary)
242
282
  if( obj == Qnil ){
243
283
  /* no type cast */
244
284
  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
285
  } 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 ));
286
+ /* Check argument type and store the coder pointer */
287
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, this->convs[i].cconv);
250
288
  }
251
289
  }
252
290
 
@@ -266,7 +304,7 @@ static VALUE
266
304
  pg_tmbc_coders(VALUE self)
267
305
  {
268
306
  int i;
269
- t_tmbc *this = DATA_PTR( self );
307
+ t_tmbc *this = RTYPEDDATA_DATA( self );
270
308
  VALUE ary_coders = rb_ary_new();
271
309
 
272
310
  for( i=0; i<this->nfields; i++){
@@ -282,7 +320,7 @@ pg_tmbc_coders(VALUE self)
282
320
  }
283
321
 
284
322
  void
285
- init_pg_type_map_by_column()
323
+ init_pg_type_map_by_column(void)
286
324
  {
287
325
  s_id_decode = rb_intern("decode");
288
326
  s_id_encode = rb_intern("encode");
@@ -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
@@ -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
  {
@@ -113,18 +113,18 @@ pg_tmbo_result_value(t_typemap *p_typemap, VALUE result, int tuple, int field)
113
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,
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;
@@ -205,15 +238,11 @@ 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
+ TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, p_coder);
217
246
 
218
247
  if( p_coder->format < 0 || p_coder->format > 1 )
219
248
  rb_raise(rb_eArgError, "invalid format code %d", p_coder->format);
@@ -243,7 +272,7 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
243
272
  {
244
273
  VALUE hash;
245
274
  VALUE coder;
246
- t_tmbo *this = DATA_PTR( self );
275
+ t_tmbo *this = RTYPEDDATA_DATA( self );
247
276
  int i_format = NUM2INT(format);
248
277
  struct pg_tmbo_oid_cache_entry *p_ce;
249
278
 
@@ -269,7 +298,7 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
269
298
  static VALUE
270
299
  pg_tmbo_coders( VALUE self )
271
300
  {
272
- t_tmbo *this = DATA_PTR( self );
301
+ t_tmbo *this = RTYPEDDATA_DATA( self );
273
302
 
274
303
  return rb_ary_concat(
275
304
  rb_funcall(this->format[0].oid_to_coder, rb_intern("values"), 0),
@@ -288,7 +317,7 @@ pg_tmbo_coders( VALUE self )
288
317
  static VALUE
289
318
  pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
290
319
  {
291
- t_tmbo *this = DATA_PTR( self );
320
+ t_tmbo *this = RTYPEDDATA_DATA( self );
292
321
  this->max_rows_for_online_lookup = NUM2INT(value);
293
322
  return value;
294
323
  }
@@ -300,7 +329,7 @@ pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
300
329
  static VALUE
301
330
  pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
302
331
  {
303
- t_tmbo *this = DATA_PTR( self );
332
+ t_tmbo *this = RTYPEDDATA_DATA( self );
304
333
  return INT2NUM(this->max_rows_for_online_lookup);
305
334
  }
306
335
 
@@ -315,7 +344,7 @@ pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
315
344
  static VALUE
316
345
  pg_tmbo_build_column_map( VALUE self, VALUE result )
317
346
  {
318
- t_tmbo *this = DATA_PTR( self );
347
+ t_tmbo *this = RTYPEDDATA_DATA( self );
319
348
 
320
349
  if ( !rb_obj_is_kind_of(result, rb_cPGresult) ) {
321
350
  rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Result)",
@@ -327,7 +356,7 @@ pg_tmbo_build_column_map( VALUE self, VALUE result )
327
356
 
328
357
 
329
358
  void
330
- init_pg_type_map_by_oid()
359
+ init_pg_type_map_by_oid(void)
331
360
  {
332
361
  s_id_decode = rb_intern("decode");
333
362