pg 1.2.0-x64-mingw32 → 1.3.0.rc1-x64-mingw32

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +80 -0
  6. data/.github/workflows/source-gem.yml +129 -0
  7. data/.gitignore +13 -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.rdoc +98 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +9 -8
  18. data/Rakefile +31 -140
  19. data/Rakefile.cross +54 -56
  20. data/certs/ged.pem +24 -0
  21. data/ext/errorcodes.def +8 -0
  22. data/ext/errorcodes.txt +3 -1
  23. data/ext/extconf.rb +90 -19
  24. data/ext/gvl_wrappers.c +4 -0
  25. data/ext/gvl_wrappers.h +23 -0
  26. data/ext/pg.c +35 -1
  27. data/ext/pg.h +18 -0
  28. data/ext/pg_coder.c +90 -24
  29. data/ext/pg_connection.c +538 -279
  30. data/ext/pg_copy_coder.c +45 -15
  31. data/ext/pg_record_coder.c +38 -9
  32. data/ext/pg_result.c +70 -34
  33. data/ext/pg_text_decoder.c +1 -1
  34. data/ext/pg_text_encoder.c +6 -6
  35. data/ext/pg_tuple.c +47 -21
  36. data/ext/pg_type_map.c +41 -8
  37. data/ext/pg_type_map_all_strings.c +14 -1
  38. data/ext/pg_type_map_by_class.c +50 -21
  39. data/ext/pg_type_map_by_column.c +64 -28
  40. data/ext/pg_type_map_by_mri_type.c +47 -18
  41. data/ext/pg_type_map_by_oid.c +52 -23
  42. data/ext/pg_type_map_in_ruby.c +50 -19
  43. data/ext/pg_util.c +2 -2
  44. data/lib/2.5/pg_ext.so +0 -0
  45. data/lib/2.6/pg_ext.so +0 -0
  46. data/lib/2.7/pg_ext.so +0 -0
  47. data/lib/3.0/pg_ext.so +0 -0
  48. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  49. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  50. data/lib/pg/basic_type_map_for_results.rb +81 -0
  51. data/lib/pg/basic_type_registry.rb +296 -0
  52. data/lib/pg/coder.rb +1 -1
  53. data/lib/pg/connection.rb +369 -56
  54. data/lib/pg/version.rb +4 -0
  55. data/lib/pg.rb +38 -24
  56. data/lib/x64-mingw32/libpq.dll +0 -0
  57. data/misc/openssl-pg-segfault.rb +31 -0
  58. data/misc/postgres/History.txt +9 -0
  59. data/misc/postgres/Manifest.txt +5 -0
  60. data/misc/postgres/README.txt +21 -0
  61. data/misc/postgres/Rakefile +21 -0
  62. data/misc/postgres/lib/postgres.rb +16 -0
  63. data/misc/ruby-pg/History.txt +9 -0
  64. data/misc/ruby-pg/Manifest.txt +5 -0
  65. data/misc/ruby-pg/README.txt +21 -0
  66. data/misc/ruby-pg/Rakefile +21 -0
  67. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  68. data/pg.gemspec +32 -0
  69. data/sample/array_insert.rb +20 -0
  70. data/sample/async_api.rb +106 -0
  71. data/sample/async_copyto.rb +39 -0
  72. data/sample/async_mixed.rb +56 -0
  73. data/sample/check_conn.rb +21 -0
  74. data/sample/copydata.rb +71 -0
  75. data/sample/copyfrom.rb +81 -0
  76. data/sample/copyto.rb +19 -0
  77. data/sample/cursor.rb +21 -0
  78. data/sample/disk_usage_report.rb +177 -0
  79. data/sample/issue-119.rb +94 -0
  80. data/sample/losample.rb +69 -0
  81. data/sample/minimal-testcase.rb +17 -0
  82. data/sample/notify_wait.rb +72 -0
  83. data/sample/pg_statistics.rb +285 -0
  84. data/sample/replication_monitor.rb +222 -0
  85. data/sample/test_binary_values.rb +33 -0
  86. data/sample/wal_shipper.rb +434 -0
  87. data/sample/warehouse_partitions.rb +311 -0
  88. data.tar.gz.sig +0 -0
  89. metadata +83 -232
  90. metadata.gz.sig +0 -0
  91. data/ChangeLog +0 -0
  92. data/lib/2.2/pg_ext.so +0 -0
  93. data/lib/2.3/pg_ext.so +0 -0
  94. data/lib/2.4/pg_ext.so +0 -0
  95. data/lib/libpq.dll +0 -0
  96. data/lib/pg/basic_type_mapping.rb +0 -522
  97. data/spec/data/expected_trace.out +0 -26
  98. data/spec/data/random_binary_data +0 -0
  99. data/spec/helpers.rb +0 -382
  100. data/spec/pg/basic_type_mapping_spec.rb +0 -645
  101. data/spec/pg/connection_spec.rb +0 -1911
  102. data/spec/pg/connection_sync_spec.rb +0 -41
  103. data/spec/pg/result_spec.rb +0 -681
  104. data/spec/pg/tuple_spec.rb +0 -333
  105. data/spec/pg/type_map_by_class_spec.rb +0 -138
  106. data/spec/pg/type_map_by_column_spec.rb +0 -226
  107. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  108. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  109. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  110. data/spec/pg/type_map_spec.rb +0 -22
  111. data/spec/pg/type_spec.rb +0 -1123
  112. data/spec/pg_spec.rb +0 -50
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,
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,13 +128,12 @@ 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);
135
+ /* Check type of method param */
136
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
104
137
  this->default_typemap = typemap;
105
138
 
106
139
  return typemap;
@@ -119,7 +152,7 @@ pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
119
152
  static VALUE
120
153
  pg_typemap_default_type_map_get(VALUE self)
121
154
  {
122
- t_typemap *this = DATA_PTR( self );
155
+ t_typemap *this = RTYPEDDATA_DATA( self );
123
156
 
124
157
  return this->default_typemap;
125
158
  }
@@ -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,
22
+ };
23
+
11
24
  VALUE rb_cTypeMapAllStrings;
12
25
  VALUE pg_typemap_all_strings;
13
26
 
@@ -77,7 +90,7 @@ pg_tmas_s_allocate( VALUE klass )
77
90
  t_typemap *this;
78
91
  VALUE self;
79
92
 
80
- self = Data_Make_Struct( klass, t_typemap, NULL, -1, this );
93
+ self = TypedData_Make_Struct( klass, t_typemap, &pg_tmas_type, this );
81
94
 
82
95
  this->funcs.fit_to_result = pg_tmas_fit_to_result;
83
96
  this->funcs.fit_to_query = pg_tmas_fit_to_query;
@@ -10,7 +10,6 @@
10
10
  #include "pg.h"
11
11
 
12
12
  static VALUE rb_cTypeMapByClass;
13
- static ID s_id_ancestors;
14
13
 
15
14
  typedef struct {
16
15
  t_typemap typemap;
@@ -48,7 +47,7 @@ pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
48
47
 
49
48
  if( NIL_P(obj) ){
50
49
  int i;
51
- VALUE ancestors = rb_funcall( klass, s_id_ancestors, 0 );
50
+ VALUE ancestors = rb_mod_ancestors( klass );
52
51
 
53
52
  Check_Type( ancestors, T_ARRAY );
54
53
  /* Don't look at the first element, it's expected to equal klass. */
@@ -63,7 +62,7 @@ pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
63
62
  if(NIL_P(obj)){
64
63
  p_coder = NULL;
65
64
  }else if(rb_obj_is_kind_of(obj, rb_cPG_Coder)){
66
- Data_Get_Struct(obj, t_pg_coder, p_coder);
65
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
67
66
  }else{
68
67
  if( RB_TYPE_P(obj, T_SYMBOL) ){
69
68
  /* A Symbol: Call the method with this name. */
@@ -75,11 +74,9 @@ pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
75
74
 
76
75
  if( NIL_P(obj) ){
77
76
  p_coder = NULL;
78
- }else if( rb_obj_is_kind_of(obj, rb_cPG_Coder) ){
79
- Data_Get_Struct(obj, t_pg_coder, p_coder);
80
77
  }else{
81
- rb_raise(rb_eTypeError, "argument has invalid type %s (should be nil or some kind of PG::Coder)",
82
- rb_obj_classname( obj ));
78
+ /* Check retrieved coder type */
79
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
83
80
  }
84
81
 
85
82
  /* We can not cache coders retrieved by ruby code, because we can not anticipate
@@ -104,7 +101,7 @@ pg_tmbk_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field
104
101
  p_coder = pg_tmbk_lookup_klass( this, rb_obj_class(param_value), param_value );
105
102
 
106
103
  if( !p_coder ){
107
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
104
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
108
105
  return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
109
106
  }
110
107
 
@@ -114,28 +111,62 @@ pg_tmbk_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field
114
111
  static VALUE
115
112
  pg_tmbk_fit_to_query( VALUE self, VALUE params )
116
113
  {
117
- t_tmbk *this = (t_tmbk *)DATA_PTR(self);
114
+ t_tmbk *this = (t_tmbk *)RTYPEDDATA_DATA(self);
118
115
  /* Nothing to check at this typemap, but ensure that the default type map fits. */
119
- t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
116
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
120
117
  default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
121
118
  return self;
122
119
  }
123
120
 
124
121
  static void
125
- pg_tmbk_mark( t_tmbk *this )
122
+ pg_tmbk_mark( void *_this )
126
123
  {
127
- rb_gc_mark(this->typemap.default_typemap);
128
- rb_gc_mark(this->klass_to_coder);
129
- /* All coders are in the Hash, so no need to mark the cache. */
124
+ t_tmbk *this = (t_tmbk *)_this;
125
+ pg_typemap_mark(&this->typemap);
126
+ rb_gc_mark_movable(this->klass_to_coder);
127
+ rb_gc_mark_movable(this->self);
130
128
  }
131
129
 
130
+ static size_t
131
+ pg_tmbk_memsize( const void *_this )
132
+ {
133
+ const t_tmbk *this = (const t_tmbk *)_this;
134
+ return sizeof(*this);
135
+ }
136
+
137
+ static void
138
+ pg_tmbk_compact(void *ptr)
139
+ {
140
+ t_tmbk *this = (t_tmbk *)ptr;
141
+
142
+ pg_typemap_compact(&this->typemap);
143
+ pg_gc_location(this->klass_to_coder);
144
+ pg_gc_location(this->self);
145
+
146
+ /* Clear the cache, to be safe from changes of klass VALUE by GC.compact. */
147
+ memset(&this->cache_row, 0, sizeof(this->cache_row));
148
+ }
149
+
150
+ static const rb_data_type_t pg_tmbk_type = {
151
+ "PG::TypeMapByClass",
152
+ {
153
+ pg_tmbk_mark,
154
+ RUBY_TYPED_DEFAULT_FREE,
155
+ pg_tmbk_memsize,
156
+ pg_compact_callback(pg_tmbk_compact),
157
+ },
158
+ &pg_typemap_type,
159
+ 0,
160
+ RUBY_TYPED_FREE_IMMEDIATELY,
161
+ };
162
+
132
163
  static VALUE
133
164
  pg_tmbk_s_allocate( VALUE klass )
134
165
  {
135
166
  t_tmbk *this;
136
167
  VALUE self;
137
168
 
138
- self = Data_Make_Struct( klass, t_tmbk, pg_tmbk_mark, -1, this );
169
+ self = TypedData_Make_Struct( klass, t_tmbk, &pg_tmbk_type, this );
139
170
  this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
140
171
  this->typemap.funcs.fit_to_query = pg_tmbk_fit_to_query;
141
172
  this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
@@ -149,7 +180,7 @@ pg_tmbk_s_allocate( VALUE klass )
149
180
  this->self = self;
150
181
  this->klass_to_coder = rb_hash_new();
151
182
 
152
- /* The cache is properly initialized by Data_Make_Struct(). */
183
+ /* The cache is properly initialized by TypedData_Make_Struct(). */
153
184
 
154
185
  return self;
155
186
  }
@@ -172,7 +203,7 @@ pg_tmbk_s_allocate( VALUE klass )
172
203
  static VALUE
173
204
  pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
174
205
  {
175
- t_tmbk *this = DATA_PTR( self );
206
+ t_tmbk *this = RTYPEDDATA_DATA( self );
176
207
 
177
208
  if(NIL_P(coder)){
178
209
  rb_hash_delete( this->klass_to_coder, klass );
@@ -196,7 +227,7 @@ pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
196
227
  static VALUE
197
228
  pg_tmbk_aref( VALUE self, VALUE klass )
198
229
  {
199
- t_tmbk *this = DATA_PTR( self );
230
+ t_tmbk *this = RTYPEDDATA_DATA( self );
200
231
 
201
232
  return rb_hash_lookup(this->klass_to_coder, klass);
202
233
  }
@@ -210,7 +241,7 @@ pg_tmbk_aref( VALUE self, VALUE klass )
210
241
  static VALUE
211
242
  pg_tmbk_coders( VALUE self )
212
243
  {
213
- t_tmbk *this = DATA_PTR( self );
244
+ t_tmbk *this = RTYPEDDATA_DATA( self );
214
245
 
215
246
  return rb_obj_freeze(rb_hash_dup(this->klass_to_coder));
216
247
  }
@@ -218,8 +249,6 @@ pg_tmbk_coders( VALUE self )
218
249
  void
219
250
  init_pg_type_map_by_class()
220
251
  {
221
- s_id_ancestors = rb_intern("ancestors");
222
-
223
252
  /*
224
253
  * Document-class: PG::TypeMapByClass < PG::TypeMap
225
254
  *
@@ -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
 
@@ -158,7 +158,7 @@ pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, i
158
158
  return field_str;
159
159
  }
160
160
 
161
- return dec_func( p_coder, RSTRING_PTR(field_str), RSTRING_LEN(field_str), 0, fieldno, enc_idx );
161
+ return dec_func( p_coder, RSTRING_PTR(field_str), RSTRING_LENINT(field_str), 0, fieldno, enc_idx );
162
162
  }
163
163
 
164
164
  const struct pg_typemap_funcs pg_tmbc_funcs = {
@@ -171,34 +171,73 @@ const struct pg_typemap_funcs pg_tmbc_funcs = {
171
171
  };
172
172
 
173
173
  static void
174
- pg_tmbc_mark( t_tmbc *this )
174
+ pg_tmbc_mark( void *_this )
175
175
  {
176
+ t_tmbc *this = (t_tmbc *)_this;
176
177
  int i;
177
178
 
178
179
  /* allocated but not initialized ? */
179
180
  if( this == (t_tmbc *)&pg_typemap_funcs ) return;
180
181
 
181
- rb_gc_mark(this->typemap.default_typemap);
182
+ pg_typemap_mark(&this->typemap);
182
183
  for( i=0; i<this->nfields; i++){
183
184
  t_pg_coder *p_coder = this->convs[i].cconv;
184
185
  if( p_coder )
185
- rb_gc_mark(p_coder->coder_obj);
186
+ rb_gc_mark_movable(p_coder->coder_obj);
187
+ }
188
+ }
189
+
190
+ static size_t
191
+ pg_tmbc_memsize( const void *_this )
192
+ {
193
+ const t_tmbc *this = (const t_tmbc *)_this;
194
+ return sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * this->nfields;
195
+ }
196
+
197
+ static void
198
+ pg_tmbc_compact( void *_this )
199
+ {
200
+ t_tmbc *this = (t_tmbc *)_this;
201
+ int i;
202
+
203
+ /* allocated but not initialized ? */
204
+ if( this == (t_tmbc *)&pg_typemap_funcs ) return;
205
+
206
+ pg_typemap_compact(&this->typemap);
207
+ for( i=0; i<this->nfields; i++){
208
+ t_pg_coder *p_coder = this->convs[i].cconv;
209
+ if( p_coder )
210
+ pg_gc_location(p_coder->coder_obj);
186
211
  }
187
212
  }
188
213
 
189
214
  static void
190
- pg_tmbc_free( t_tmbc *this )
215
+ pg_tmbc_free( void *_this )
191
216
  {
217
+ t_tmbc *this = (t_tmbc *)_this;
192
218
  /* allocated but not initialized ? */
193
219
  if( this == (t_tmbc *)&pg_typemap_funcs ) return;
194
220
  xfree( this );
195
221
  }
196
222
 
223
+ static const rb_data_type_t pg_tmbc_type = {
224
+ "PG::TypeMapByColumn",
225
+ {
226
+ pg_tmbc_mark,
227
+ pg_tmbc_free,
228
+ pg_tmbc_memsize,
229
+ pg_compact_callback(pg_tmbc_compact),
230
+ },
231
+ &pg_typemap_type,
232
+ 0,
233
+ RUBY_TYPED_FREE_IMMEDIATELY,
234
+ };
235
+
197
236
  static VALUE
198
237
  pg_tmbc_s_allocate( VALUE klass )
199
238
  {
200
239
  /* 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 );
240
+ return TypedData_Wrap_Struct( klass, &pg_tmbc_type, (t_tmbc *)&pg_typemap_funcs );
202
241
  }
203
242
 
204
243
  VALUE
@@ -221,19 +260,18 @@ pg_tmbc_allocate()
221
260
  static VALUE
222
261
  pg_tmbc_init(VALUE self, VALUE conv_ary)
223
262
  {
224
- int i;
263
+ long i;
225
264
  t_tmbc *this;
226
265
  int conv_ary_len;
227
266
 
228
- Check_Type(self, T_DATA);
229
267
  Check_Type(conv_ary, T_ARRAY);
230
- conv_ary_len = RARRAY_LEN(conv_ary);
268
+ conv_ary_len = RARRAY_LENINT(conv_ary);
231
269
  this = xmalloc(sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * conv_ary_len);
232
270
  /* Set nfields to 0 at first, so that GC mark function doesn't access uninitialized memory. */
233
271
  this->nfields = 0;
234
272
  this->typemap.funcs = pg_tmbc_funcs;
235
273
  this->typemap.default_typemap = pg_typemap_all_strings;
236
- DATA_PTR(self) = this;
274
+ RTYPEDDATA_DATA(self) = this;
237
275
 
238
276
  for(i=0; i<conv_ary_len; i++)
239
277
  {
@@ -242,11 +280,9 @@ pg_tmbc_init(VALUE self, VALUE conv_ary)
242
280
  if( obj == Qnil ){
243
281
  /* no type cast */
244
282
  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
283
  } 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 ));
284
+ /* Check argument type and store the coder pointer */
285
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, this->convs[i].cconv);
250
286
  }
251
287
  }
252
288
 
@@ -266,7 +302,7 @@ static VALUE
266
302
  pg_tmbc_coders(VALUE self)
267
303
  {
268
304
  int i;
269
- t_tmbc *this = DATA_PTR( self );
305
+ t_tmbc *this = RTYPEDDATA_DATA( self );
270
306
  VALUE ary_coders = rb_ary_new();
271
307
 
272
308
  for( i=0; i<this->nfields; i++){
@@ -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 );