pg 0.18.2 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
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 +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 +14 -0
  16. data/History.md +884 -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 +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 +124 -54
  30. data/ext/gvl_wrappers.c +8 -0
  31. data/ext/gvl_wrappers.h +44 -33
  32. data/ext/pg.c +227 -201
  33. data/ext/pg.h +99 -100
  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 +1874 -1174
  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 +936 -0
  113. data/translation/po/ja.po +1036 -0
  114. data/translation/po4a.cfg +12 -0
  115. data.tar.gz.sig +0 -0
  116. metadata +130 -201
  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
  }