pg 1.1.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 (77) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +3 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gemtest +0 -0
  5. data/BSDL +22 -0
  6. data/ChangeLog +6595 -0
  7. data/Contributors.rdoc +46 -0
  8. data/History.rdoc +492 -0
  9. data/LICENSE +56 -0
  10. data/Manifest.txt +72 -0
  11. data/POSTGRES +23 -0
  12. data/README-OS_X.rdoc +68 -0
  13. data/README-Windows.rdoc +56 -0
  14. data/README.ja.rdoc +14 -0
  15. data/README.rdoc +178 -0
  16. data/Rakefile +215 -0
  17. data/Rakefile.cross +298 -0
  18. data/ext/errorcodes.def +968 -0
  19. data/ext/errorcodes.rb +45 -0
  20. data/ext/errorcodes.txt +478 -0
  21. data/ext/extconf.rb +94 -0
  22. data/ext/gvl_wrappers.c +17 -0
  23. data/ext/gvl_wrappers.h +241 -0
  24. data/ext/pg.c +640 -0
  25. data/ext/pg.h +365 -0
  26. data/ext/pg_binary_decoder.c +229 -0
  27. data/ext/pg_binary_encoder.c +162 -0
  28. data/ext/pg_coder.c +549 -0
  29. data/ext/pg_connection.c +4252 -0
  30. data/ext/pg_copy_coder.c +596 -0
  31. data/ext/pg_errors.c +95 -0
  32. data/ext/pg_result.c +1501 -0
  33. data/ext/pg_text_decoder.c +981 -0
  34. data/ext/pg_text_encoder.c +682 -0
  35. data/ext/pg_tuple.c +541 -0
  36. data/ext/pg_type_map.c +166 -0
  37. data/ext/pg_type_map_all_strings.c +116 -0
  38. data/ext/pg_type_map_by_class.c +239 -0
  39. data/ext/pg_type_map_by_column.c +312 -0
  40. data/ext/pg_type_map_by_mri_type.c +284 -0
  41. data/ext/pg_type_map_by_oid.c +355 -0
  42. data/ext/pg_type_map_in_ruby.c +299 -0
  43. data/ext/util.c +149 -0
  44. data/ext/util.h +65 -0
  45. data/ext/vc/pg.sln +26 -0
  46. data/ext/vc/pg_18/pg.vcproj +216 -0
  47. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  48. data/lib/pg.rb +74 -0
  49. data/lib/pg/basic_type_mapping.rb +459 -0
  50. data/lib/pg/binary_decoder.rb +22 -0
  51. data/lib/pg/coder.rb +83 -0
  52. data/lib/pg/connection.rb +291 -0
  53. data/lib/pg/constants.rb +11 -0
  54. data/lib/pg/exceptions.rb +11 -0
  55. data/lib/pg/result.rb +31 -0
  56. data/lib/pg/text_decoder.rb +47 -0
  57. data/lib/pg/text_encoder.rb +69 -0
  58. data/lib/pg/tuple.rb +30 -0
  59. data/lib/pg/type_map_by_column.rb +15 -0
  60. data/spec/data/expected_trace.out +26 -0
  61. data/spec/data/random_binary_data +0 -0
  62. data/spec/helpers.rb +380 -0
  63. data/spec/pg/basic_type_mapping_spec.rb +508 -0
  64. data/spec/pg/connection_spec.rb +1872 -0
  65. data/spec/pg/connection_sync_spec.rb +41 -0
  66. data/spec/pg/result_spec.rb +491 -0
  67. data/spec/pg/tuple_spec.rb +280 -0
  68. data/spec/pg/type_map_by_class_spec.rb +138 -0
  69. data/spec/pg/type_map_by_column_spec.rb +222 -0
  70. data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
  71. data/spec/pg/type_map_by_oid_spec.rb +149 -0
  72. data/spec/pg/type_map_in_ruby_spec.rb +164 -0
  73. data/spec/pg/type_map_spec.rb +22 -0
  74. data/spec/pg/type_spec.rb +949 -0
  75. data/spec/pg_spec.rb +50 -0
  76. metadata +322 -0
  77. metadata.gz.sig +0 -0
@@ -0,0 +1,166 @@
1
+ /*
2
+ * pg_column_map.c - PG::ColumnMap class extension
3
+ * $Id: pg_type_map.c,v 2af122820861 2017/01/14 19:56:36 lars $
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+
9
+ VALUE rb_cTypeMap;
10
+ VALUE rb_mDefaultTypeMappable;
11
+ static ID s_id_fit_to_query;
12
+ static ID s_id_fit_to_result;
13
+
14
+ NORETURN( VALUE
15
+ pg_typemap_fit_to_result( VALUE self, VALUE result ));
16
+ NORETURN( VALUE
17
+ pg_typemap_fit_to_query( VALUE self, VALUE params ));
18
+ NORETURN( int
19
+ pg_typemap_fit_to_copy_get( VALUE self ));
20
+ NORETURN( VALUE
21
+ pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field ));
22
+ NORETURN( t_pg_coder *
23
+ pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field ));
24
+ NORETURN( VALUE
25
+ pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ));
26
+
27
+ VALUE
28
+ pg_typemap_fit_to_result( VALUE self, VALUE result )
29
+ {
30
+ rb_raise( rb_eNotImpError, "type map %s is not suitable to map result values", rb_obj_classname(self) );
31
+ }
32
+
33
+ VALUE
34
+ pg_typemap_fit_to_query( VALUE self, VALUE params )
35
+ {
36
+ rb_raise( rb_eNotImpError, "type map %s is not suitable to map query params", rb_obj_classname(self) );
37
+ }
38
+
39
+ int
40
+ pg_typemap_fit_to_copy_get( VALUE self )
41
+ {
42
+ rb_raise( rb_eNotImpError, "type map %s is not suitable to map get_copy_data results", rb_obj_classname(self) );
43
+ }
44
+
45
+ VALUE
46
+ pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
47
+ {
48
+ rb_raise( rb_eNotImpError, "type map is not suitable to map result values" );
49
+ }
50
+
51
+ t_pg_coder *
52
+ pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
53
+ {
54
+ rb_raise( rb_eNotImpError, "type map is not suitable to map query params" );
55
+ }
56
+
57
+ VALUE
58
+ pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
59
+ {
60
+ rb_raise( rb_eNotImpError, "type map is not suitable to map get_copy_data results" );
61
+ }
62
+
63
+ const struct pg_typemap_funcs pg_typemap_funcs = {
64
+ pg_typemap_fit_to_result,
65
+ pg_typemap_fit_to_query,
66
+ pg_typemap_fit_to_copy_get,
67
+ pg_typemap_result_value,
68
+ pg_typemap_typecast_query_param,
69
+ pg_typemap_typecast_copy_get
70
+ };
71
+
72
+ static VALUE
73
+ pg_typemap_s_allocate( VALUE klass )
74
+ {
75
+ VALUE self;
76
+ t_typemap *this;
77
+
78
+ self = Data_Make_Struct( klass, t_typemap, NULL, -1, this );
79
+ this->funcs = pg_typemap_funcs;
80
+
81
+ return self;
82
+ }
83
+
84
+ /*
85
+ * call-seq:
86
+ * res.default_type_map = typemap
87
+ *
88
+ * Set the default TypeMap that is used for values that could not be
89
+ * casted by this type map.
90
+ *
91
+ * +typemap+ must be a kind of PG::TypeMap
92
+ *
93
+ */
94
+ static VALUE
95
+ pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
96
+ {
97
+ t_typemap *this = DATA_PTR( self );
98
+
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);
104
+ this->default_typemap = typemap;
105
+
106
+ return typemap;
107
+ }
108
+
109
+ /*
110
+ * call-seq:
111
+ * res.default_type_map -> TypeMap
112
+ *
113
+ * Returns the default TypeMap that is currently set for values that could not be
114
+ * casted by this type map.
115
+ *
116
+ * Returns a kind of PG::TypeMap.
117
+ *
118
+ */
119
+ static VALUE
120
+ pg_typemap_default_type_map_get(VALUE self)
121
+ {
122
+ t_typemap *this = DATA_PTR( self );
123
+
124
+ return this->default_typemap;
125
+ }
126
+
127
+ /*
128
+ * call-seq:
129
+ * res.with_default_type_map( typemap )
130
+ *
131
+ * Set the default TypeMap that is used for values that could not be
132
+ * casted by this type map.
133
+ *
134
+ * +typemap+ must be a kind of PG::TypeMap
135
+ *
136
+ * Returns self.
137
+ */
138
+ static VALUE
139
+ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
140
+ {
141
+ pg_typemap_default_type_map_set( self, typemap );
142
+ return self;
143
+ }
144
+
145
+ void
146
+ init_pg_type_map()
147
+ {
148
+ s_id_fit_to_query = rb_intern("fit_to_query");
149
+ s_id_fit_to_result = rb_intern("fit_to_result");
150
+
151
+ /*
152
+ * Document-class: PG::TypeMap < Object
153
+ *
154
+ * This is the base class for type maps.
155
+ * See derived classes for implementations of different type cast strategies
156
+ * ( PG::TypeMapByColumn, PG::TypeMapByOid ).
157
+ *
158
+ */
159
+ rb_cTypeMap = rb_define_class_under( rb_mPG, "TypeMap", rb_cObject );
160
+ rb_define_alloc_func( rb_cTypeMap, pg_typemap_s_allocate );
161
+
162
+ rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable");
163
+ rb_define_method( rb_mDefaultTypeMappable, "default_type_map=", pg_typemap_default_type_map_set, 1 );
164
+ rb_define_method( rb_mDefaultTypeMappable, "default_type_map", pg_typemap_default_type_map_get, 0 );
165
+ rb_define_method( rb_mDefaultTypeMappable, "with_default_type_map", pg_typemap_with_default_type_map, 1 );
166
+ }
@@ -0,0 +1,116 @@
1
+ /*
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 $
4
+ *
5
+ * This is the default typemap.
6
+ *
7
+ */
8
+
9
+ #include "pg.h"
10
+
11
+ VALUE rb_cTypeMapAllStrings;
12
+ VALUE pg_typemap_all_strings;
13
+
14
+ static VALUE
15
+ pg_tmas_fit_to_result( VALUE self, VALUE result )
16
+ {
17
+ return self;
18
+ }
19
+
20
+ static VALUE
21
+ pg_tmas_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
22
+ {
23
+ VALUE ret;
24
+ char * val;
25
+ int len;
26
+ t_pg_result *p_result = pgresult_get_this(result);
27
+
28
+ if (PQgetisnull(p_result->pgresult, tuple, field)) {
29
+ return Qnil;
30
+ }
31
+
32
+ val = PQgetvalue( p_result->pgresult, tuple, field );
33
+ len = PQgetlength( p_result->pgresult, tuple, field );
34
+
35
+ if ( 0 == PQfformat(p_result->pgresult, field) ) {
36
+ ret = pg_text_dec_string(NULL, val, len, tuple, field, ENCODING_GET(result));
37
+ } else {
38
+ ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, ENCODING_GET(result));
39
+ }
40
+
41
+ return ret;
42
+ }
43
+
44
+ static VALUE
45
+ pg_tmas_fit_to_query( VALUE self, VALUE params )
46
+ {
47
+ return self;
48
+ }
49
+
50
+ static t_pg_coder *
51
+ pg_tmas_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
52
+ {
53
+ return NULL;
54
+ }
55
+
56
+ static int
57
+ pg_tmas_fit_to_copy_get( VALUE self )
58
+ {
59
+ /* We can not predict the number of columns for copy */
60
+ return 0;
61
+ }
62
+
63
+ static VALUE
64
+ pg_tmas_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
65
+ {
66
+ if( format == 0 ){
67
+ PG_ENCODING_SET_NOCHECK( field_str, enc_idx );
68
+ } else {
69
+ PG_ENCODING_SET_NOCHECK( field_str, rb_ascii8bit_encindex() );
70
+ }
71
+ return field_str;
72
+ }
73
+
74
+ static VALUE
75
+ pg_tmas_s_allocate( VALUE klass )
76
+ {
77
+ t_typemap *this;
78
+ VALUE self;
79
+
80
+ self = Data_Make_Struct( klass, t_typemap, NULL, -1, this );
81
+
82
+ this->funcs.fit_to_result = pg_tmas_fit_to_result;
83
+ this->funcs.fit_to_query = pg_tmas_fit_to_query;
84
+ this->funcs.fit_to_copy_get = pg_tmas_fit_to_copy_get;
85
+ this->funcs.typecast_result_value = pg_tmas_result_value;
86
+ this->funcs.typecast_query_param = pg_tmas_typecast_query_param;
87
+ this->funcs.typecast_copy_get = pg_tmas_typecast_copy_get;
88
+
89
+ return self;
90
+ }
91
+
92
+
93
+ void
94
+ init_pg_type_map_all_strings()
95
+ {
96
+ /*
97
+ * Document-class: PG::TypeMapAllStrings < PG::TypeMap
98
+ *
99
+ * This type map casts all values received from the database server to Strings
100
+ * and sends all values to the server after conversion to String by +#to_s+ .
101
+ * 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
103
+ * for binary format received from the server.
104
+ *
105
+ * It is suitable for type casting query bind parameters, result values and
106
+ * COPY IN/OUT data.
107
+ *
108
+ * This is the default type map for each PG::Connection .
109
+ *
110
+ */
111
+ rb_cTypeMapAllStrings = rb_define_class_under( rb_mPG, "TypeMapAllStrings", rb_cTypeMap );
112
+ rb_define_alloc_func( rb_cTypeMapAllStrings, pg_tmas_s_allocate );
113
+
114
+ pg_typemap_all_strings = rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 );
115
+ rb_gc_register_address( &pg_typemap_all_strings );
116
+ }
@@ -0,0 +1,239 @@
1
+ /*
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 $
4
+ *
5
+ * This type map can be used to select value encoders based on the class
6
+ * of the given value to be send.
7
+ *
8
+ */
9
+
10
+ #include "pg.h"
11
+
12
+ static VALUE rb_cTypeMapByClass;
13
+ static ID s_id_ancestors;
14
+
15
+ typedef struct {
16
+ t_typemap typemap;
17
+
18
+ VALUE klass_to_coder;
19
+ VALUE self;
20
+
21
+ struct pg_tmbk_coder_cache_entry {
22
+ VALUE klass;
23
+ t_pg_coder *p_coder;
24
+ } cache_row[0x100];
25
+ } t_tmbk;
26
+
27
+ /*
28
+ * We use 8 Bits of the klass object id as index to a 256 entry cache.
29
+ * This avoids full lookups in most cases.
30
+ */
31
+ #define CACHE_LOOKUP(this, klass) ( &this->cache_row[(klass >> 8) & 0xff] )
32
+
33
+
34
+ static t_pg_coder *
35
+ pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
36
+ {
37
+ t_pg_coder *p_coder;
38
+ struct pg_tmbk_coder_cache_entry *p_ce;
39
+
40
+ p_ce = CACHE_LOOKUP(this, klass);
41
+
42
+ /* Is the cache entry for the expected klass? */
43
+ if( p_ce->klass == klass ) {
44
+ p_coder = p_ce->p_coder;
45
+ } else {
46
+ /* No, then do a full lookup based on the ancestors. */
47
+ VALUE obj = rb_hash_lookup( this->klass_to_coder, klass );
48
+
49
+ if( NIL_P(obj) ){
50
+ int i;
51
+ VALUE ancestors = rb_funcall( klass, s_id_ancestors, 0 );
52
+
53
+ Check_Type( ancestors, T_ARRAY );
54
+ /* Don't look at the first element, it's expected to equal klass. */
55
+ for( i=1; i<RARRAY_LEN(ancestors); i++ ){
56
+ obj = rb_hash_lookup( this->klass_to_coder, rb_ary_entry( ancestors, i) );
57
+
58
+ if( !NIL_P(obj) )
59
+ break;
60
+ }
61
+ }
62
+
63
+ if(NIL_P(obj)){
64
+ p_coder = NULL;
65
+ }else if(rb_obj_is_kind_of(obj, rb_cPG_Coder)){
66
+ Data_Get_Struct(obj, t_pg_coder, p_coder);
67
+ }else{
68
+ if( RB_TYPE_P(obj, T_SYMBOL) ){
69
+ /* A Proc object (or something that responds to #call). */
70
+ obj = rb_funcall(this->self, SYM2ID(obj), 1, param_value);
71
+ }else{
72
+ /* A Proc object (or something that responds to #call). */
73
+ obj = rb_funcall(obj, rb_intern("call"), 1, param_value);
74
+ }
75
+
76
+ if( NIL_P(obj) ){
77
+ 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
+ }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 ));
83
+ }
84
+
85
+ /* We can not cache coders retrieved by ruby code, because we can not anticipate
86
+ * the returned Coder object. */
87
+ return p_coder;
88
+ }
89
+
90
+ /* Write the retrieved coder to the cache */
91
+ p_ce->klass = klass;
92
+ p_ce->p_coder = p_coder;
93
+ }
94
+ return p_coder;
95
+ }
96
+
97
+
98
+ static t_pg_coder *
99
+ pg_tmbk_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
100
+ {
101
+ t_tmbk *this = (t_tmbk *)p_typemap;
102
+ t_pg_coder *p_coder;
103
+
104
+ p_coder = pg_tmbk_lookup_klass( this, rb_obj_class(param_value), param_value );
105
+
106
+ if( !p_coder ){
107
+ t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap );
108
+ return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
109
+ }
110
+
111
+ return p_coder;
112
+ }
113
+
114
+ static VALUE
115
+ pg_tmbk_fit_to_query( VALUE self, VALUE params )
116
+ {
117
+ t_tmbk *this = (t_tmbk *)DATA_PTR(self);
118
+ /* 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 );
120
+ default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
121
+ return self;
122
+ }
123
+
124
+ static void
125
+ pg_tmbk_mark( t_tmbk *this )
126
+ {
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. */
130
+ }
131
+
132
+ static VALUE
133
+ pg_tmbk_s_allocate( VALUE klass )
134
+ {
135
+ t_tmbk *this;
136
+ VALUE self;
137
+
138
+ self = Data_Make_Struct( klass, t_tmbk, pg_tmbk_mark, -1, this );
139
+ this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
140
+ this->typemap.funcs.fit_to_query = pg_tmbk_fit_to_query;
141
+ this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
142
+ this->typemap.funcs.typecast_result_value = pg_typemap_result_value;
143
+ this->typemap.funcs.typecast_query_param = pg_tmbk_typecast_query_param;
144
+ this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
145
+ this->typemap.default_typemap = pg_typemap_all_strings;
146
+
147
+ /* We need to store self in the this-struct, because pg_tmbk_typecast_query_param(),
148
+ * is called with the this-pointer only. */
149
+ this->self = self;
150
+ this->klass_to_coder = rb_hash_new();
151
+
152
+ /* The cache is properly initialized by Data_Make_Struct(). */
153
+
154
+ return self;
155
+ }
156
+
157
+ /*
158
+ * call-seq:
159
+ * typemap.[class] = coder
160
+ *
161
+ * Assigns a new PG::Coder object to the type map. The encoder
162
+ * is chosen for all values that are a kind of the given +class+ .
163
+ *
164
+ * +coder+ can be one of the following:
165
+ * * +nil+ - Values are forwarded to the #default_type_map .
166
+ * * a PG::Coder - Values are encoded by the given encoder
167
+ * * a Symbol - The method of this type map (or a derivation) that is called for each value to sent.
168
+ * It must return a PG::Coder or +nil+ .
169
+ * * a Proc - The Proc object is called for each value. It must return a PG::Coder or +nil+ .
170
+ *
171
+ */
172
+ static VALUE
173
+ pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
174
+ {
175
+ t_tmbk *this = DATA_PTR( self );
176
+
177
+ if(NIL_P(coder)){
178
+ rb_hash_delete( this->klass_to_coder, klass );
179
+ }else{
180
+ rb_hash_aset( this->klass_to_coder, klass, coder );
181
+ }
182
+
183
+ /* The cache lookup key can be a derivation of the klass.
184
+ * So we can not expire the cache selectively. */
185
+ memset( &this->cache_row, 0, sizeof(this->cache_row) );
186
+
187
+ return coder;
188
+ }
189
+
190
+ /*
191
+ * call-seq:
192
+ * typemap.[class] -> coder
193
+ *
194
+ * Returns the encoder object for the given +class+
195
+ */
196
+ static VALUE
197
+ pg_tmbk_aref( VALUE self, VALUE klass )
198
+ {
199
+ t_tmbk *this = DATA_PTR( self );
200
+
201
+ return rb_hash_lookup(this->klass_to_coder, klass);
202
+ }
203
+
204
+ /*
205
+ * call-seq:
206
+ * typemap.coders -> Hash
207
+ *
208
+ * Returns all classes and their assigned encoder object.
209
+ */
210
+ static VALUE
211
+ pg_tmbk_coders( VALUE self )
212
+ {
213
+ t_tmbk *this = DATA_PTR( self );
214
+
215
+ return rb_obj_freeze(rb_hash_dup(this->klass_to_coder));
216
+ }
217
+
218
+ void
219
+ init_pg_type_map_by_class()
220
+ {
221
+ s_id_ancestors = rb_intern("ancestors");
222
+
223
+ /*
224
+ * Document-class: PG::TypeMapByClass < PG::TypeMap
225
+ *
226
+ * This type map casts values based on the class or the ancestors of the given value
227
+ * to be sent.
228
+ *
229
+ * This type map is usable for type casting query bind parameters and COPY data
230
+ * for PG::Connection#put_copy_data . Therefore only encoders might be assigned by
231
+ * the #[]= method.
232
+ */
233
+ rb_cTypeMapByClass = rb_define_class_under( rb_mPG, "TypeMapByClass", rb_cTypeMap );
234
+ rb_define_alloc_func( rb_cTypeMapByClass, pg_tmbk_s_allocate );
235
+ rb_define_method( rb_cTypeMapByClass, "[]=", pg_tmbk_aset, 2 );
236
+ rb_define_method( rb_cTypeMapByClass, "[]", pg_tmbk_aref, 1 );
237
+ rb_define_method( rb_cTypeMapByClass, "coders", pg_tmbk_coders, 0 );
238
+ rb_include_module( rb_cTypeMapByClass, rb_mDefaultTypeMappable );
239
+ }