pg 1.2.3 → 1.4.4

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 (110) 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 +86 -0
  6. data/.github/workflows/source-gem.yml +131 -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 +209 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +31 -11
  18. data/Rakefile +27 -138
  19. data/Rakefile.cross +8 -5
  20. data/certs/ged.pem +24 -0
  21. data/certs/larskanis-2022.pem +26 -0
  22. data/ext/errorcodes.def +8 -0
  23. data/ext/errorcodes.rb +0 -0
  24. data/ext/errorcodes.txt +3 -1
  25. data/ext/extconf.rb +100 -25
  26. data/ext/gvl_wrappers.c +4 -0
  27. data/ext/gvl_wrappers.h +23 -0
  28. data/ext/pg.c +59 -29
  29. data/ext/pg.h +20 -1
  30. data/ext/pg_binary_decoder.c +1 -1
  31. data/ext/pg_binary_encoder.c +1 -1
  32. data/ext/pg_coder.c +83 -29
  33. data/ext/pg_connection.c +856 -656
  34. data/ext/pg_copy_coder.c +46 -17
  35. data/ext/pg_errors.c +1 -1
  36. data/ext/pg_record_coder.c +46 -16
  37. data/ext/pg_result.c +88 -49
  38. data/ext/pg_text_decoder.c +2 -2
  39. data/ext/pg_text_encoder.c +7 -7
  40. data/ext/pg_tuple.c +50 -30
  41. data/ext/pg_type_map.c +42 -9
  42. data/ext/pg_type_map_all_strings.c +16 -2
  43. data/ext/pg_type_map_by_class.c +50 -25
  44. data/ext/pg_type_map_by_column.c +68 -30
  45. data/ext/pg_type_map_by_mri_type.c +48 -19
  46. data/ext/pg_type_map_by_oid.c +53 -24
  47. data/ext/pg_type_map_in_ruby.c +51 -20
  48. data/ext/pg_util.c +2 -2
  49. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  50. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  51. data/lib/pg/basic_type_map_for_results.rb +81 -0
  52. data/lib/pg/basic_type_registry.rb +301 -0
  53. data/lib/pg/coder.rb +1 -1
  54. data/lib/pg/connection.rb +655 -69
  55. data/lib/pg/exceptions.rb +7 -1
  56. data/lib/pg/version.rb +4 -0
  57. data/lib/pg.rb +47 -32
  58. data/misc/openssl-pg-segfault.rb +31 -0
  59. data/misc/postgres/History.txt +9 -0
  60. data/misc/postgres/Manifest.txt +5 -0
  61. data/misc/postgres/README.txt +21 -0
  62. data/misc/postgres/Rakefile +21 -0
  63. data/misc/postgres/lib/postgres.rb +16 -0
  64. data/misc/ruby-pg/History.txt +9 -0
  65. data/misc/ruby-pg/Manifest.txt +5 -0
  66. data/misc/ruby-pg/README.txt +21 -0
  67. data/misc/ruby-pg/Rakefile +21 -0
  68. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  69. data/pg.gemspec +32 -0
  70. data/rakelib/task_extension.rb +46 -0
  71. data/sample/array_insert.rb +20 -0
  72. data/sample/async_api.rb +102 -0
  73. data/sample/async_copyto.rb +39 -0
  74. data/sample/async_mixed.rb +56 -0
  75. data/sample/check_conn.rb +21 -0
  76. data/sample/copydata.rb +71 -0
  77. data/sample/copyfrom.rb +81 -0
  78. data/sample/copyto.rb +19 -0
  79. data/sample/cursor.rb +21 -0
  80. data/sample/disk_usage_report.rb +177 -0
  81. data/sample/issue-119.rb +94 -0
  82. data/sample/losample.rb +69 -0
  83. data/sample/minimal-testcase.rb +17 -0
  84. data/sample/notify_wait.rb +72 -0
  85. data/sample/pg_statistics.rb +285 -0
  86. data/sample/replication_monitor.rb +222 -0
  87. data/sample/test_binary_values.rb +33 -0
  88. data/sample/wal_shipper.rb +434 -0
  89. data/sample/warehouse_partitions.rb +311 -0
  90. data.tar.gz.sig +0 -0
  91. metadata +81 -224
  92. metadata.gz.sig +0 -0
  93. data/ChangeLog +0 -0
  94. data/lib/pg/basic_type_mapping.rb +0 -522
  95. data/spec/data/expected_trace.out +0 -26
  96. data/spec/data/random_binary_data +0 -0
  97. data/spec/helpers.rb +0 -380
  98. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  99. data/spec/pg/connection_spec.rb +0 -1949
  100. data/spec/pg/connection_sync_spec.rb +0 -41
  101. data/spec/pg/result_spec.rb +0 -681
  102. data/spec/pg/tuple_spec.rb +0 -333
  103. data/spec/pg/type_map_by_class_spec.rb +0 -138
  104. data/spec/pg/type_map_by_column_spec.rb +0 -226
  105. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  106. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  107. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  108. data/spec/pg/type_map_spec.rb +0 -22
  109. data/spec/pg/type_spec.rb +0 -1123
  110. data/spec/pg_spec.rb +0 -50
@@ -191,7 +191,7 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
191
191
  if (neg)
192
192
  *out++ = '-';
193
193
 
194
- len = out - start;
194
+ len = (int)(out - start);
195
195
 
196
196
  /* Reverse string. */
197
197
  out--;
@@ -252,7 +252,7 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
252
252
  }
253
253
 
254
254
  /*
255
- * The following computaion is roughly a conversion kind of
255
+ * The following computation is roughly a conversion kind of
256
256
  * sprintf( out, "%.16E", dvalue);
257
257
  */
258
258
 
@@ -403,11 +403,11 @@ pg_text_enc_bytea(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
403
403
  *optr++ = hextab[c >> 4];
404
404
  *optr++ = hextab[c & 0xf];
405
405
  }
406
- return optr - out;
406
+ return (int)(optr - out);
407
407
  }else{
408
408
  *intermediate = rb_obj_as_string(value);
409
409
  /* The output starts with "\x" and each character is converted to hex. */
410
- return 2 + RSTRING_LEN(*intermediate) * 2;
410
+ return 2 + RSTRING_LENINT(*intermediate) * 2;
411
411
  }
412
412
  }
413
413
 
@@ -610,8 +610,8 @@ quote_identifier( VALUE value, VALUE out_string, char *current_out ){
610
610
  static char *
611
611
  pg_text_enc_array_identifier(VALUE value, VALUE string, char *out, int enc_idx)
612
612
  {
613
- int i;
614
- int nr_elems;
613
+ long i;
614
+ long nr_elems;
615
615
 
616
616
  Check_Type(value, T_ARRAY);
617
617
  nr_elems = RARRAY_LEN(value);
@@ -775,7 +775,7 @@ pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedi
775
775
 
776
776
 
777
777
  void
778
- init_pg_text_encoder()
778
+ init_pg_text_encoder(void)
779
779
  {
780
780
  s_id_encode = rb_intern("encode");
781
781
  s_id_to_i = rb_intern("to_i");
data/ext/pg_tuple.c CHANGED
@@ -52,57 +52,83 @@ typedef struct {
52
52
  VALUE values[0];
53
53
  } t_pg_tuple;
54
54
 
55
- static inline VALUE
56
- pg_tuple_get_field_names( t_pg_tuple *this )
55
+ static inline VALUE *
56
+ pg_tuple_get_field_names_ptr( t_pg_tuple *this )
57
57
  {
58
58
  if( this->num_fields != (int)RHASH_SIZE(this->field_map) ){
59
- return this->values[this->num_fields];
59
+ return &this->values[this->num_fields];
60
60
  } else {
61
- return Qfalse;
61
+ static VALUE f = Qfalse;
62
+ return &f;
63
+ }
64
+ }
65
+
66
+ static inline VALUE
67
+ pg_tuple_get_field_names( t_pg_tuple *this )
68
+ {
69
+ return *pg_tuple_get_field_names_ptr(this);
70
+ }
71
+
72
+ static void
73
+ pg_tuple_gc_mark( void *_this )
74
+ {
75
+ t_pg_tuple *this = (t_pg_tuple *)_this;
76
+ int i;
77
+
78
+ if( !this ) return;
79
+ rb_gc_mark_movable( this->result );
80
+ rb_gc_mark_movable( this->typemap );
81
+ rb_gc_mark_movable( this->field_map );
82
+
83
+ for( i = 0; i < this->num_fields; i++ ){
84
+ rb_gc_mark_movable( this->values[i] );
62
85
  }
86
+ rb_gc_mark_movable( pg_tuple_get_field_names(this) );
63
87
  }
64
88
 
65
89
  static void
66
- pg_tuple_gc_mark( t_pg_tuple *this )
90
+ pg_tuple_gc_compact( void *_this )
67
91
  {
92
+ t_pg_tuple *this = (t_pg_tuple *)_this;
68
93
  int i;
69
94
 
70
95
  if( !this ) return;
71
- rb_gc_mark( this->result );
72
- rb_gc_mark( this->typemap );
73
- rb_gc_mark( this->field_map );
96
+ pg_gc_location( this->result );
97
+ pg_gc_location( this->typemap );
98
+ pg_gc_location( this->field_map );
74
99
 
75
100
  for( i = 0; i < this->num_fields; i++ ){
76
- rb_gc_mark( this->values[i] );
101
+ pg_gc_location( this->values[i] );
77
102
  }
78
- rb_gc_mark( pg_tuple_get_field_names(this) );
103
+ pg_gc_location( *pg_tuple_get_field_names_ptr(this) );
79
104
  }
80
105
 
81
106
  static void
82
- pg_tuple_gc_free( t_pg_tuple *this )
107
+ pg_tuple_gc_free( void *_this )
83
108
  {
109
+ t_pg_tuple *this = (t_pg_tuple *)_this;
84
110
  if( !this ) return;
85
111
  xfree(this);
86
112
  }
87
113
 
88
114
  static size_t
89
- pg_tuple_memsize( t_pg_tuple *this )
115
+ pg_tuple_memsize( const void *_this )
90
116
  {
117
+ const t_pg_tuple *this = (const t_pg_tuple *)_this;
91
118
  if( this==NULL ) return 0;
92
119
  return sizeof(*this) + sizeof(*this->values) * this->num_fields;
93
120
  }
94
121
 
95
122
  static const rb_data_type_t pg_tuple_type = {
96
- "pg",
123
+ "PG::Tuple",
97
124
  {
98
- (void (*)(void*))pg_tuple_gc_mark,
99
- (void (*)(void*))pg_tuple_gc_free,
100
- (size_t (*)(const void *))pg_tuple_memsize,
125
+ pg_tuple_gc_mark,
126
+ pg_tuple_gc_free,
127
+ pg_tuple_memsize,
128
+ pg_compact_callback(pg_tuple_gc_compact),
101
129
  },
102
130
  0, 0,
103
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
104
131
  RUBY_TYPED_FREE_IMMEDIATELY,
105
- #endif
106
132
  };
107
133
 
108
134
  /*
@@ -172,7 +198,7 @@ pg_tuple_materialize_field(t_pg_tuple *this, int col)
172
198
  VALUE value = this->values[col];
173
199
 
174
200
  if( value == Qundef ){
175
- t_typemap *p_typemap = DATA_PTR( this->typemap );
201
+ t_typemap *p_typemap = RTYPEDDATA_DATA( this->typemap );
176
202
 
177
203
  pgresult_get(this->result); /* make sure we have a valid PGresult object */
178
204
  value = p_typemap->funcs.typecast_result_value(p_typemap, this->result, this->row_num, col);
@@ -445,10 +471,7 @@ pg_tuple_dump(VALUE self)
445
471
  values = rb_ary_new4(this->num_fields, &this->values[0]);
446
472
  a = rb_ary_new3(2, field_names, values);
447
473
 
448
- if (FL_TEST(self, FL_EXIVAR)) {
449
- rb_copy_generic_ivar(a, self);
450
- FL_SET(a, FL_EXIVAR);
451
- }
474
+ rb_copy_generic_ivar(a, self);
452
475
 
453
476
  return a;
454
477
  }
@@ -479,9 +502,9 @@ pg_tuple_load(VALUE self, VALUE a)
479
502
  rb_obj_freeze(field_names);
480
503
  values = RARRAY_AREF(a, 1);
481
504
  Check_Type(values, T_ARRAY);
482
- num_fields = RARRAY_LEN(values);
505
+ num_fields = RARRAY_LENINT(values);
483
506
 
484
- if (RARRAY_LEN(field_names) != num_fields)
507
+ if (RARRAY_LENINT(field_names) != num_fields)
485
508
  rb_raise(rb_eTypeError, "different number of fields and values");
486
509
 
487
510
  field_map = rb_hash_new();
@@ -516,16 +539,13 @@ pg_tuple_load(VALUE self, VALUE a)
516
539
 
517
540
  RTYPEDDATA_DATA(self) = this;
518
541
 
519
- if (FL_TEST(a, FL_EXIVAR)) {
520
- rb_copy_generic_ivar(self, a);
521
- FL_SET(self, FL_EXIVAR);
522
- }
542
+ rb_copy_generic_ivar(self, a);
523
543
 
524
544
  return self;
525
545
  }
526
546
 
527
547
  void
528
- init_pg_tuple()
548
+ init_pg_tuple(void)
529
549
  {
530
550
  rb_cPG_Tuple = rb_define_class_under( rb_mPG, "Tuple", rb_cObject );
531
551
  rb_define_alloc_func( rb_cPG_Tuple, pg_tuple_s_allocate );
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
  }
@@ -143,7 +176,7 @@ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
143
176
  }
144
177
 
145
178
  void
146
- init_pg_type_map()
179
+ init_pg_type_map(void)
147
180
  {
148
181
  s_id_fit_to_query = rb_intern("fit_to_query");
149
182
  s_id_fit_to_result = rb_intern("fit_to_result");
@@ -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
 
@@ -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
@@ -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,32 +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
- rb_gc_mark(this->self);
130
- /* Clear the cache, to be safe from changes of klass VALUE by GC.compact.
131
- * TODO: Move cache clearing to compactation callback provided by Ruby-2.7+.
132
- */
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 )
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. */
133
147
  memset(&this->cache_row, 0, sizeof(this->cache_row));
134
148
  }
135
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
+
136
163
  static VALUE
137
164
  pg_tmbk_s_allocate( VALUE klass )
138
165
  {
139
166
  t_tmbk *this;
140
167
  VALUE self;
141
168
 
142
- self = Data_Make_Struct( klass, t_tmbk, pg_tmbk_mark, -1, this );
169
+ self = TypedData_Make_Struct( klass, t_tmbk, &pg_tmbk_type, this );
143
170
  this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
144
171
  this->typemap.funcs.fit_to_query = pg_tmbk_fit_to_query;
145
172
  this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
@@ -153,7 +180,7 @@ pg_tmbk_s_allocate( VALUE klass )
153
180
  this->self = self;
154
181
  this->klass_to_coder = rb_hash_new();
155
182
 
156
- /* The cache is properly initialized by Data_Make_Struct(). */
183
+ /* The cache is properly initialized by TypedData_Make_Struct(). */
157
184
 
158
185
  return self;
159
186
  }
@@ -176,7 +203,7 @@ pg_tmbk_s_allocate( VALUE klass )
176
203
  static VALUE
177
204
  pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
178
205
  {
179
- t_tmbk *this = DATA_PTR( self );
206
+ t_tmbk *this = RTYPEDDATA_DATA( self );
180
207
 
181
208
  if(NIL_P(coder)){
182
209
  rb_hash_delete( this->klass_to_coder, klass );
@@ -200,7 +227,7 @@ pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
200
227
  static VALUE
201
228
  pg_tmbk_aref( VALUE self, VALUE klass )
202
229
  {
203
- t_tmbk *this = DATA_PTR( self );
230
+ t_tmbk *this = RTYPEDDATA_DATA( self );
204
231
 
205
232
  return rb_hash_lookup(this->klass_to_coder, klass);
206
233
  }
@@ -214,16 +241,14 @@ pg_tmbk_aref( VALUE self, VALUE klass )
214
241
  static VALUE
215
242
  pg_tmbk_coders( VALUE self )
216
243
  {
217
- t_tmbk *this = DATA_PTR( self );
244
+ t_tmbk *this = RTYPEDDATA_DATA( self );
218
245
 
219
246
  return rb_obj_freeze(rb_hash_dup(this->klass_to_coder));
220
247
  }
221
248
 
222
249
  void
223
- init_pg_type_map_by_class()
250
+ init_pg_type_map_by_class(void)
224
251
  {
225
- s_id_ancestors = rb_intern("ancestors");
226
-
227
252
  /*
228
253
  * Document-class: PG::TypeMapByClass < PG::TypeMap
229
254
  *