pg 0.18.2 → 1.5.3

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 (139) 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 +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/BSDL +2 -2
  15. data/Gemfile +14 -0
  16. data/History.md +876 -0
  17. data/Manifest.txt +8 -21
  18. data/README-Windows.rdoc +17 -28
  19. data/README.ja.md +276 -0
  20. data/README.md +286 -0
  21. data/Rakefile +40 -131
  22. data/Rakefile.cross +88 -70
  23. data/certs/ged.pem +24 -0
  24. data/certs/larskanis-2022.pem +26 -0
  25. data/certs/larskanis-2023.pem +24 -0
  26. data/ext/errorcodes.def +113 -0
  27. data/ext/errorcodes.rb +1 -1
  28. data/ext/errorcodes.txt +36 -2
  29. data/ext/extconf.rb +120 -54
  30. data/ext/gvl_wrappers.c +8 -0
  31. data/ext/gvl_wrappers.h +44 -33
  32. data/ext/pg.c +226 -200
  33. data/ext/pg.h +99 -99
  34. data/ext/pg_binary_decoder.c +164 -16
  35. data/ext/pg_binary_encoder.c +249 -22
  36. data/ext/pg_coder.c +189 -44
  37. data/ext/pg_connection.c +1866 -1173
  38. data/ext/pg_copy_coder.c +398 -42
  39. data/ext/pg_errors.c +1 -1
  40. data/ext/pg_record_coder.c +522 -0
  41. data/ext/pg_result.c +727 -232
  42. data/ext/pg_text_decoder.c +629 -43
  43. data/ext/pg_text_encoder.c +269 -102
  44. data/ext/pg_tuple.c +572 -0
  45. data/ext/pg_type_map.c +64 -23
  46. data/ext/pg_type_map_all_strings.c +21 -7
  47. data/ext/pg_type_map_by_class.c +59 -27
  48. data/ext/pg_type_map_by_column.c +86 -43
  49. data/ext/pg_type_map_by_mri_type.c +49 -20
  50. data/ext/pg_type_map_by_oid.c +62 -29
  51. data/ext/pg_type_map_in_ruby.c +56 -22
  52. data/ext/{util.c → pg_util.c} +12 -12
  53. data/ext/{util.h → pg_util.h} +2 -2
  54. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  55. data/lib/pg/basic_type_map_for_queries.rb +198 -0
  56. data/lib/pg/basic_type_map_for_results.rb +104 -0
  57. data/lib/pg/basic_type_registry.rb +299 -0
  58. data/lib/pg/binary_decoder/date.rb +9 -0
  59. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  60. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  61. data/lib/pg/coder.rb +36 -13
  62. data/lib/pg/connection.rb +797 -77
  63. data/lib/pg/exceptions.rb +16 -2
  64. data/lib/pg/result.rb +24 -7
  65. data/lib/pg/text_decoder/date.rb +18 -0
  66. data/lib/pg/text_decoder/inet.rb +9 -0
  67. data/lib/pg/text_decoder/json.rb +14 -0
  68. data/lib/pg/text_decoder/numeric.rb +9 -0
  69. data/lib/pg/text_decoder/timestamp.rb +30 -0
  70. data/lib/pg/text_encoder/date.rb +12 -0
  71. data/lib/pg/text_encoder/inet.rb +28 -0
  72. data/lib/pg/text_encoder/json.rb +14 -0
  73. data/lib/pg/text_encoder/numeric.rb +9 -0
  74. data/lib/pg/text_encoder/timestamp.rb +24 -0
  75. data/lib/pg/tuple.rb +30 -0
  76. data/lib/pg/type_map_by_column.rb +3 -2
  77. data/lib/pg/version.rb +4 -0
  78. data/lib/pg.rb +106 -41
  79. data/misc/openssl-pg-segfault.rb +31 -0
  80. data/misc/postgres/History.txt +9 -0
  81. data/misc/postgres/Manifest.txt +5 -0
  82. data/misc/postgres/README.txt +21 -0
  83. data/misc/postgres/Rakefile +21 -0
  84. data/misc/postgres/lib/postgres.rb +16 -0
  85. data/misc/ruby-pg/History.txt +9 -0
  86. data/misc/ruby-pg/Manifest.txt +5 -0
  87. data/misc/ruby-pg/README.txt +21 -0
  88. data/misc/ruby-pg/Rakefile +21 -0
  89. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  90. data/pg.gemspec +34 -0
  91. data/rakelib/task_extension.rb +46 -0
  92. data/sample/array_insert.rb +1 -1
  93. data/sample/async_api.rb +4 -8
  94. data/sample/async_copyto.rb +1 -1
  95. data/sample/async_mixed.rb +1 -1
  96. data/sample/check_conn.rb +1 -1
  97. data/sample/copydata.rb +71 -0
  98. data/sample/copyfrom.rb +1 -1
  99. data/sample/copyto.rb +1 -1
  100. data/sample/cursor.rb +1 -1
  101. data/sample/disk_usage_report.rb +6 -15
  102. data/sample/issue-119.rb +2 -2
  103. data/sample/losample.rb +1 -1
  104. data/sample/minimal-testcase.rb +2 -2
  105. data/sample/notify_wait.rb +1 -1
  106. data/sample/pg_statistics.rb +6 -15
  107. data/sample/replication_monitor.rb +9 -18
  108. data/sample/test_binary_values.rb +1 -1
  109. data/sample/wal_shipper.rb +2 -2
  110. data/sample/warehouse_partitions.rb +8 -17
  111. data/translation/.po4a-version +7 -0
  112. data/translation/po/all.pot +910 -0
  113. data/translation/po/ja.po +1047 -0
  114. data/translation/po4a.cfg +12 -0
  115. data.tar.gz.sig +0 -0
  116. metadata +137 -204
  117. metadata.gz.sig +0 -0
  118. data/ChangeLog +0 -5545
  119. data/History.rdoc +0 -313
  120. data/README.ja.rdoc +0 -14
  121. data/README.rdoc +0 -161
  122. data/lib/pg/basic_type_mapping.rb +0 -399
  123. data/lib/pg/constants.rb +0 -11
  124. data/lib/pg/text_decoder.rb +0 -42
  125. data/lib/pg/text_encoder.rb +0 -27
  126. data/spec/data/expected_trace.out +0 -26
  127. data/spec/data/random_binary_data +0 -0
  128. data/spec/helpers.rb +0 -355
  129. data/spec/pg/basic_type_mapping_spec.rb +0 -251
  130. data/spec/pg/connection_spec.rb +0 -1535
  131. data/spec/pg/result_spec.rb +0 -449
  132. data/spec/pg/type_map_by_class_spec.rb +0 -138
  133. data/spec/pg/type_map_by_column_spec.rb +0 -222
  134. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  135. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  136. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  137. data/spec/pg/type_map_spec.rb +0 -22
  138. data/spec/pg/type_spec.rb +0 -688
  139. data/spec/pg_spec.rb +0 -50
data/ext/pg_type_map.c CHANGED
@@ -1,65 +1,106 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_type_map.c,v c99d26015e3c 2014/12/12 20:58:25 lars $
3
+ * $Id$
4
4
  *
5
5
  */
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;
12
46
  static ID s_id_fit_to_result;
13
47
 
48
+ NORETURN( VALUE
49
+ pg_typemap_fit_to_result( VALUE self, VALUE result ));
50
+ NORETURN( VALUE
51
+ pg_typemap_fit_to_query( VALUE self, VALUE params ));
52
+ NORETURN( int
53
+ pg_typemap_fit_to_copy_get( VALUE self ));
54
+ NORETURN( VALUE
55
+ pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field ));
56
+ NORETURN( t_pg_coder *
57
+ pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field ));
58
+ NORETURN( VALUE
59
+ pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ));
60
+
14
61
  VALUE
15
62
  pg_typemap_fit_to_result( VALUE self, VALUE result )
16
63
  {
17
64
  rb_raise( rb_eNotImpError, "type map %s is not suitable to map result values", rb_obj_classname(self) );
18
- return Qnil;
19
65
  }
20
66
 
21
67
  VALUE
22
68
  pg_typemap_fit_to_query( VALUE self, VALUE params )
23
69
  {
24
70
  rb_raise( rb_eNotImpError, "type map %s is not suitable to map query params", rb_obj_classname(self) );
25
- return Qnil;
26
71
  }
27
72
 
28
73
  int
29
74
  pg_typemap_fit_to_copy_get( VALUE self )
30
75
  {
31
76
  rb_raise( rb_eNotImpError, "type map %s is not suitable to map get_copy_data results", rb_obj_classname(self) );
32
- return Qnil;
33
77
  }
34
78
 
35
79
  VALUE
36
80
  pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
37
81
  {
38
82
  rb_raise( rb_eNotImpError, "type map is not suitable to map result values" );
39
- return Qnil;
40
83
  }
41
84
 
42
85
  t_pg_coder *
43
86
  pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
44
87
  {
45
88
  rb_raise( rb_eNotImpError, "type map is not suitable to map query params" );
46
- return NULL;
47
89
  }
48
90
 
49
91
  VALUE
50
92
  pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
51
93
  {
52
94
  rb_raise( rb_eNotImpError, "type map is not suitable to map get_copy_data results" );
53
- return Qnil;
54
95
  }
55
96
 
56
97
  const struct pg_typemap_funcs pg_typemap_funcs = {
57
- .fit_to_result = pg_typemap_fit_to_result,
58
- .fit_to_query = pg_typemap_fit_to_query,
59
- .fit_to_copy_get = pg_typemap_fit_to_copy_get,
60
- .typecast_result_value = pg_typemap_result_value,
61
- .typecast_query_param = pg_typemap_typecast_query_param,
62
- .typecast_copy_get = pg_typemap_typecast_copy_get
98
+ pg_typemap_fit_to_result,
99
+ pg_typemap_fit_to_query,
100
+ pg_typemap_fit_to_copy_get,
101
+ pg_typemap_result_value,
102
+ pg_typemap_typecast_query_param,
103
+ pg_typemap_typecast_copy_get
63
104
  };
64
105
 
65
106
  static VALUE
@@ -68,7 +109,7 @@ pg_typemap_s_allocate( VALUE klass )
68
109
  VALUE self;
69
110
  t_typemap *this;
70
111
 
71
- self = Data_Make_Struct( klass, t_typemap, NULL, -1, this );
112
+ self = TypedData_Make_Struct( klass, t_typemap, &pg_typemap_type, this );
72
113
  this->funcs = pg_typemap_funcs;
73
114
 
74
115
  return self;
@@ -87,14 +128,14 @@ pg_typemap_s_allocate( VALUE klass )
87
128
  static VALUE
88
129
  pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
89
130
  {
90
- t_typemap *this = DATA_PTR( self );
131
+ t_typemap *this = RTYPEDDATA_DATA( self );
132
+ t_typemap *tm;
133
+ UNUSED(tm);
91
134
 
92
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
93
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
94
- rb_obj_classname( typemap ) );
95
- }
96
- Check_Type(typemap, T_DATA);
97
- 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);
98
139
 
99
140
  return typemap;
100
141
  }
@@ -112,7 +153,7 @@ pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
112
153
  static VALUE
113
154
  pg_typemap_default_type_map_get(VALUE self)
114
155
  {
115
- t_typemap *this = DATA_PTR( self );
156
+ t_typemap *this = RTYPEDDATA_DATA( self );
116
157
 
117
158
  return this->default_typemap;
118
159
  }
@@ -136,7 +177,7 @@ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
136
177
  }
137
178
 
138
179
  void
139
- init_pg_type_map()
180
+ init_pg_type_map(void)
140
181
  {
141
182
  s_id_fit_to_query = rb_intern("fit_to_query");
142
183
  s_id_fit_to_result = rb_intern("fit_to_result");
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_all_strings.c - PG::TypeMapAllStrings class extension
3
- * $Id: pg_type_map_all_strings.c,v c53f993a4254 2014/12/12 21:57:29 lars $
3
+ * $Id$
4
4
  *
5
5
  * This is the default typemap.
6
6
  *
@@ -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
 
@@ -33,9 +46,9 @@ pg_tmas_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
33
46
  len = PQgetlength( p_result->pgresult, tuple, field );
34
47
 
35
48
  if ( 0 == PQfformat(p_result->pgresult, field) ) {
36
- ret = pg_text_dec_string(NULL, val, len, tuple, field, ENCODING_GET(result));
49
+ ret = pg_text_dec_string(NULL, val, len, tuple, field, p_result->enc_idx);
37
50
  } else {
38
- ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, ENCODING_GET(result));
51
+ ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, p_result->enc_idx);
39
52
  }
40
53
 
41
54
  return ret;
@@ -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
@@ -99,7 +113,7 @@ init_pg_type_map_all_strings()
99
113
  * This type map casts all values received from the database server to Strings
100
114
  * and sends all values to the server after conversion to String by +#to_s+ .
101
115
  * That means, it is hard coded to PG::TextEncoder::String for value encoding
102
- * and to PG::TextDecoder::String for text format respectivly PG::BinaryDecoder::Bytea
116
+ * and to PG::TextDecoder::String for text format respectively PG::BinaryDecoder::Bytea
103
117
  * for binary format received from the server.
104
118
  *
105
119
  * It is suitable for type casting query bind parameters, result values and
@@ -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
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_by_class.c - PG::TypeMapByClass class extension
3
- * $Id: pg_type_map_by_class.c,v eeb8a82c5328 2014/11/10 19:34:02 lars $
3
+ * $Id$
4
4
  *
5
5
  * This type map can be used to select value encoders based on the class
6
6
  * of the given value to be send.
@@ -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;
@@ -28,7 +27,7 @@ typedef struct {
28
27
  * We use 8 Bits of the klass object id as index to a 256 entry cache.
29
28
  * This avoids full lookups in most cases.
30
29
  */
31
- #define CACHE_LOOKUP(this, klass) ( &this->cache_row[(klass >> 8) & 0xff] )
30
+ #define CACHE_LOOKUP(this, klass) ( &this->cache_row[(((unsigned long)klass) >> 8) & 0xff] )
32
31
 
33
32
 
34
33
  static t_pg_coder *
@@ -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,10 +62,10 @@ 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
- /* A Proc object (or something that responds to #call). */
68
+ /* A Symbol: Call the method with this name. */
70
69
  obj = rb_funcall(this->self, SYM2ID(obj), 1, param_value);
71
70
  }else{
72
71
  /* A Proc object (or something that responds to #call). */
@@ -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,42 +111,76 @@ 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 )
123
+ {
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);
128
+ }
129
+
130
+ static size_t
131
+ pg_tmbk_memsize( const void *_this )
126
132
  {
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. */
133
+ const t_tmbk *this = (const t_tmbk *)_this;
134
+ return sizeof(*this);
130
135
  }
131
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 | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
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;
142
173
  this->typemap.funcs.typecast_result_value = pg_typemap_result_value;
143
174
  this->typemap.funcs.typecast_query_param = pg_tmbk_typecast_query_param;
144
175
  this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
145
- this->typemap.default_typemap = pg_typemap_all_strings;
176
+ RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
146
177
 
147
178
  /* We need to store self in the this-struct, because pg_tmbk_typecast_query_param(),
148
179
  * is called with the this-pointer only. */
149
180
  this->self = self;
150
- this->klass_to_coder = rb_hash_new();
181
+ RB_OBJ_WRITE(self, &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,9 @@ 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 );
207
+
208
+ rb_check_frozen(self);
176
209
 
177
210
  if(NIL_P(coder)){
178
211
  rb_hash_delete( this->klass_to_coder, klass );
@@ -196,7 +229,7 @@ pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
196
229
  static VALUE
197
230
  pg_tmbk_aref( VALUE self, VALUE klass )
198
231
  {
199
- t_tmbk *this = DATA_PTR( self );
232
+ t_tmbk *this = RTYPEDDATA_DATA( self );
200
233
 
201
234
  return rb_hash_lookup(this->klass_to_coder, klass);
202
235
  }
@@ -210,16 +243,14 @@ pg_tmbk_aref( VALUE self, VALUE klass )
210
243
  static VALUE
211
244
  pg_tmbk_coders( VALUE self )
212
245
  {
213
- t_tmbk *this = DATA_PTR( self );
246
+ t_tmbk *this = RTYPEDDATA_DATA( self );
214
247
 
215
248
  return rb_obj_freeze(rb_hash_dup(this->klass_to_coder));
216
249
  }
217
250
 
218
251
  void
219
- init_pg_type_map_by_class()
252
+ init_pg_type_map_by_class(void)
220
253
  {
221
- s_id_ancestors = rb_intern("ancestors");
222
-
223
254
  /*
224
255
  * Document-class: PG::TypeMapByClass < PG::TypeMap
225
256
  *
@@ -235,5 +266,6 @@ init_pg_type_map_by_class()
235
266
  rb_define_method( rb_cTypeMapByClass, "[]=", pg_tmbk_aset, 2 );
236
267
  rb_define_method( rb_cTypeMapByClass, "[]", pg_tmbk_aref, 1 );
237
268
  rb_define_method( rb_cTypeMapByClass, "coders", pg_tmbk_coders, 0 );
269
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
238
270
  rb_include_module( rb_cTypeMapByClass, rb_mDefaultTypeMappable );
239
271
  }