pg 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
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
+ }