pg 1.3.0.rc2-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +3 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.gemtest +0 -0
  6. data/.github/workflows/binary-gems.yml +85 -0
  7. data/.github/workflows/source-gem.yml +130 -0
  8. data/.gitignore +13 -0
  9. data/.hgsigs +34 -0
  10. data/.hgtags +41 -0
  11. data/.irbrc +23 -0
  12. data/.pryrc +23 -0
  13. data/.tm_properties +21 -0
  14. data/.travis.yml +49 -0
  15. data/BSDL +22 -0
  16. data/Contributors.rdoc +46 -0
  17. data/Gemfile +14 -0
  18. data/History.rdoc +648 -0
  19. data/LICENSE +56 -0
  20. data/Manifest.txt +72 -0
  21. data/POSTGRES +23 -0
  22. data/README-OS_X.rdoc +68 -0
  23. data/README-Windows.rdoc +56 -0
  24. data/README.ja.rdoc +13 -0
  25. data/README.rdoc +214 -0
  26. data/Rakefile +106 -0
  27. data/Rakefile.cross +300 -0
  28. data/certs/ged.pem +24 -0
  29. data/ext/errorcodes.def +1040 -0
  30. data/ext/errorcodes.rb +45 -0
  31. data/ext/errorcodes.txt +496 -0
  32. data/ext/extconf.rb +165 -0
  33. data/ext/gvl_wrappers.c +21 -0
  34. data/ext/gvl_wrappers.h +264 -0
  35. data/ext/pg.c +732 -0
  36. data/ext/pg.h +385 -0
  37. data/ext/pg_binary_decoder.c +229 -0
  38. data/ext/pg_binary_encoder.c +163 -0
  39. data/ext/pg_coder.c +615 -0
  40. data/ext/pg_connection.c +4415 -0
  41. data/ext/pg_copy_coder.c +628 -0
  42. data/ext/pg_errors.c +95 -0
  43. data/ext/pg_record_coder.c +519 -0
  44. data/ext/pg_result.c +1683 -0
  45. data/ext/pg_text_decoder.c +987 -0
  46. data/ext/pg_text_encoder.c +814 -0
  47. data/ext/pg_tuple.c +575 -0
  48. data/ext/pg_type_map.c +199 -0
  49. data/ext/pg_type_map_all_strings.c +129 -0
  50. data/ext/pg_type_map_by_class.c +269 -0
  51. data/ext/pg_type_map_by_column.c +349 -0
  52. data/ext/pg_type_map_by_mri_type.c +313 -0
  53. data/ext/pg_type_map_by_oid.c +385 -0
  54. data/ext/pg_type_map_in_ruby.c +330 -0
  55. data/ext/pg_util.c +149 -0
  56. data/ext/pg_util.h +65 -0
  57. data/ext/vc/pg.sln +26 -0
  58. data/ext/vc/pg_18/pg.vcproj +216 -0
  59. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  60. data/lib/3.1/pg_ext.so +0 -0
  61. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  62. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  63. data/lib/pg/basic_type_map_for_results.rb +81 -0
  64. data/lib/pg/basic_type_registry.rb +296 -0
  65. data/lib/pg/binary_decoder.rb +23 -0
  66. data/lib/pg/coder.rb +104 -0
  67. data/lib/pg/connection.rb +813 -0
  68. data/lib/pg/constants.rb +12 -0
  69. data/lib/pg/exceptions.rb +12 -0
  70. data/lib/pg/result.rb +43 -0
  71. data/lib/pg/text_decoder.rb +46 -0
  72. data/lib/pg/text_encoder.rb +59 -0
  73. data/lib/pg/tuple.rb +30 -0
  74. data/lib/pg/type_map_by_column.rb +16 -0
  75. data/lib/pg/version.rb +4 -0
  76. data/lib/pg.rb +87 -0
  77. data/lib/x64-mingw-ucrt/libpq.dll +0 -0
  78. data/misc/openssl-pg-segfault.rb +31 -0
  79. data/misc/postgres/History.txt +9 -0
  80. data/misc/postgres/Manifest.txt +5 -0
  81. data/misc/postgres/README.txt +21 -0
  82. data/misc/postgres/Rakefile +21 -0
  83. data/misc/postgres/lib/postgres.rb +16 -0
  84. data/misc/ruby-pg/History.txt +9 -0
  85. data/misc/ruby-pg/Manifest.txt +5 -0
  86. data/misc/ruby-pg/README.txt +21 -0
  87. data/misc/ruby-pg/Rakefile +21 -0
  88. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  89. data/pg.gemspec +32 -0
  90. data/sample/array_insert.rb +20 -0
  91. data/sample/async_api.rb +106 -0
  92. data/sample/async_copyto.rb +39 -0
  93. data/sample/async_mixed.rb +56 -0
  94. data/sample/check_conn.rb +21 -0
  95. data/sample/copydata.rb +71 -0
  96. data/sample/copyfrom.rb +81 -0
  97. data/sample/copyto.rb +19 -0
  98. data/sample/cursor.rb +21 -0
  99. data/sample/disk_usage_report.rb +177 -0
  100. data/sample/issue-119.rb +94 -0
  101. data/sample/losample.rb +69 -0
  102. data/sample/minimal-testcase.rb +17 -0
  103. data/sample/notify_wait.rb +72 -0
  104. data/sample/pg_statistics.rb +285 -0
  105. data/sample/replication_monitor.rb +222 -0
  106. data/sample/test_binary_values.rb +33 -0
  107. data/sample/wal_shipper.rb +434 -0
  108. data/sample/warehouse_partitions.rb +311 -0
  109. data.tar.gz.sig +0 -0
  110. metadata +188 -0
  111. metadata.gz.sig +0 -0
data/ext/pg_type_map.c ADDED
@@ -0,0 +1,199 @@
1
+ /*
2
+ * pg_column_map.c - PG::ColumnMap class extension
3
+ * $Id$
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
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
+
43
+ VALUE rb_cTypeMap;
44
+ VALUE rb_mDefaultTypeMappable;
45
+ static ID s_id_fit_to_query;
46
+ static ID s_id_fit_to_result;
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
+
61
+ VALUE
62
+ pg_typemap_fit_to_result( VALUE self, VALUE result )
63
+ {
64
+ rb_raise( rb_eNotImpError, "type map %s is not suitable to map result values", rb_obj_classname(self) );
65
+ }
66
+
67
+ VALUE
68
+ pg_typemap_fit_to_query( VALUE self, VALUE params )
69
+ {
70
+ rb_raise( rb_eNotImpError, "type map %s is not suitable to map query params", rb_obj_classname(self) );
71
+ }
72
+
73
+ int
74
+ pg_typemap_fit_to_copy_get( VALUE self )
75
+ {
76
+ rb_raise( rb_eNotImpError, "type map %s is not suitable to map get_copy_data results", rb_obj_classname(self) );
77
+ }
78
+
79
+ VALUE
80
+ pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
81
+ {
82
+ rb_raise( rb_eNotImpError, "type map is not suitable to map result values" );
83
+ }
84
+
85
+ t_pg_coder *
86
+ pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
87
+ {
88
+ rb_raise( rb_eNotImpError, "type map is not suitable to map query params" );
89
+ }
90
+
91
+ VALUE
92
+ pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
93
+ {
94
+ rb_raise( rb_eNotImpError, "type map is not suitable to map get_copy_data results" );
95
+ }
96
+
97
+ const struct pg_typemap_funcs pg_typemap_funcs = {
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
104
+ };
105
+
106
+ static VALUE
107
+ pg_typemap_s_allocate( VALUE klass )
108
+ {
109
+ VALUE self;
110
+ t_typemap *this;
111
+
112
+ self = TypedData_Make_Struct( klass, t_typemap, &pg_typemap_type, this );
113
+ this->funcs = pg_typemap_funcs;
114
+
115
+ return self;
116
+ }
117
+
118
+ /*
119
+ * call-seq:
120
+ * res.default_type_map = typemap
121
+ *
122
+ * Set the default TypeMap that is used for values that could not be
123
+ * casted by this type map.
124
+ *
125
+ * +typemap+ must be a kind of PG::TypeMap
126
+ *
127
+ */
128
+ static VALUE
129
+ pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
130
+ {
131
+ t_typemap *this = RTYPEDDATA_DATA( self );
132
+ t_typemap *tm;
133
+ UNUSED(tm);
134
+
135
+ /* Check type of method param */
136
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
137
+ this->default_typemap = typemap;
138
+
139
+ return typemap;
140
+ }
141
+
142
+ /*
143
+ * call-seq:
144
+ * res.default_type_map -> TypeMap
145
+ *
146
+ * Returns the default TypeMap that is currently set for values that could not be
147
+ * casted by this type map.
148
+ *
149
+ * Returns a kind of PG::TypeMap.
150
+ *
151
+ */
152
+ static VALUE
153
+ pg_typemap_default_type_map_get(VALUE self)
154
+ {
155
+ t_typemap *this = RTYPEDDATA_DATA( self );
156
+
157
+ return this->default_typemap;
158
+ }
159
+
160
+ /*
161
+ * call-seq:
162
+ * res.with_default_type_map( typemap )
163
+ *
164
+ * Set the default TypeMap that is used for values that could not be
165
+ * casted by this type map.
166
+ *
167
+ * +typemap+ must be a kind of PG::TypeMap
168
+ *
169
+ * Returns self.
170
+ */
171
+ static VALUE
172
+ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
173
+ {
174
+ pg_typemap_default_type_map_set( self, typemap );
175
+ return self;
176
+ }
177
+
178
+ void
179
+ init_pg_type_map()
180
+ {
181
+ s_id_fit_to_query = rb_intern("fit_to_query");
182
+ s_id_fit_to_result = rb_intern("fit_to_result");
183
+
184
+ /*
185
+ * Document-class: PG::TypeMap < Object
186
+ *
187
+ * This is the base class for type maps.
188
+ * See derived classes for implementations of different type cast strategies
189
+ * ( PG::TypeMapByColumn, PG::TypeMapByOid ).
190
+ *
191
+ */
192
+ rb_cTypeMap = rb_define_class_under( rb_mPG, "TypeMap", rb_cObject );
193
+ rb_define_alloc_func( rb_cTypeMap, pg_typemap_s_allocate );
194
+
195
+ rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable");
196
+ rb_define_method( rb_mDefaultTypeMappable, "default_type_map=", pg_typemap_default_type_map_set, 1 );
197
+ rb_define_method( rb_mDefaultTypeMappable, "default_type_map", pg_typemap_default_type_map_get, 0 );
198
+ rb_define_method( rb_mDefaultTypeMappable, "with_default_type_map", pg_typemap_with_default_type_map, 1 );
199
+ }
@@ -0,0 +1,129 @@
1
+ /*
2
+ * pg_type_map_all_strings.c - PG::TypeMapAllStrings class extension
3
+ * $Id$
4
+ *
5
+ * This is the default typemap.
6
+ *
7
+ */
8
+
9
+ #include "pg.h"
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
+
24
+ VALUE rb_cTypeMapAllStrings;
25
+ VALUE pg_typemap_all_strings;
26
+
27
+ static VALUE
28
+ pg_tmas_fit_to_result( VALUE self, VALUE result )
29
+ {
30
+ return self;
31
+ }
32
+
33
+ static VALUE
34
+ pg_tmas_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
35
+ {
36
+ VALUE ret;
37
+ char * val;
38
+ int len;
39
+ t_pg_result *p_result = pgresult_get_this(result);
40
+
41
+ if (PQgetisnull(p_result->pgresult, tuple, field)) {
42
+ return Qnil;
43
+ }
44
+
45
+ val = PQgetvalue( p_result->pgresult, tuple, field );
46
+ len = PQgetlength( p_result->pgresult, tuple, field );
47
+
48
+ if ( 0 == PQfformat(p_result->pgresult, field) ) {
49
+ ret = pg_text_dec_string(NULL, val, len, tuple, field, p_result->enc_idx);
50
+ } else {
51
+ ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, p_result->enc_idx);
52
+ }
53
+
54
+ return ret;
55
+ }
56
+
57
+ static VALUE
58
+ pg_tmas_fit_to_query( VALUE self, VALUE params )
59
+ {
60
+ return self;
61
+ }
62
+
63
+ static t_pg_coder *
64
+ pg_tmas_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
65
+ {
66
+ return NULL;
67
+ }
68
+
69
+ static int
70
+ pg_tmas_fit_to_copy_get( VALUE self )
71
+ {
72
+ /* We can not predict the number of columns for copy */
73
+ return 0;
74
+ }
75
+
76
+ static VALUE
77
+ pg_tmas_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
78
+ {
79
+ if( format == 0 ){
80
+ PG_ENCODING_SET_NOCHECK( field_str, enc_idx );
81
+ } else {
82
+ PG_ENCODING_SET_NOCHECK( field_str, rb_ascii8bit_encindex() );
83
+ }
84
+ return field_str;
85
+ }
86
+
87
+ static VALUE
88
+ pg_tmas_s_allocate( VALUE klass )
89
+ {
90
+ t_typemap *this;
91
+ VALUE self;
92
+
93
+ self = TypedData_Make_Struct( klass, t_typemap, &pg_tmas_type, this );
94
+
95
+ this->funcs.fit_to_result = pg_tmas_fit_to_result;
96
+ this->funcs.fit_to_query = pg_tmas_fit_to_query;
97
+ this->funcs.fit_to_copy_get = pg_tmas_fit_to_copy_get;
98
+ this->funcs.typecast_result_value = pg_tmas_result_value;
99
+ this->funcs.typecast_query_param = pg_tmas_typecast_query_param;
100
+ this->funcs.typecast_copy_get = pg_tmas_typecast_copy_get;
101
+
102
+ return self;
103
+ }
104
+
105
+
106
+ void
107
+ init_pg_type_map_all_strings()
108
+ {
109
+ /*
110
+ * Document-class: PG::TypeMapAllStrings < PG::TypeMap
111
+ *
112
+ * This type map casts all values received from the database server to Strings
113
+ * and sends all values to the server after conversion to String by +#to_s+ .
114
+ * That means, it is hard coded to PG::TextEncoder::String for value encoding
115
+ * and to PG::TextDecoder::String for text format respectively PG::BinaryDecoder::Bytea
116
+ * for binary format received from the server.
117
+ *
118
+ * It is suitable for type casting query bind parameters, result values and
119
+ * COPY IN/OUT data.
120
+ *
121
+ * This is the default type map for each PG::Connection .
122
+ *
123
+ */
124
+ rb_cTypeMapAllStrings = rb_define_class_under( rb_mPG, "TypeMapAllStrings", rb_cTypeMap );
125
+ rb_define_alloc_func( rb_cTypeMapAllStrings, pg_tmas_s_allocate );
126
+
127
+ pg_typemap_all_strings = rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 );
128
+ rb_gc_register_address( &pg_typemap_all_strings );
129
+ }
@@ -0,0 +1,269 @@
1
+ /*
2
+ * pg_type_map_by_class.c - PG::TypeMapByClass class extension
3
+ * $Id$
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
+
14
+ typedef struct {
15
+ t_typemap typemap;
16
+
17
+ VALUE klass_to_coder;
18
+ VALUE self;
19
+
20
+ struct pg_tmbk_coder_cache_entry {
21
+ VALUE klass;
22
+ t_pg_coder *p_coder;
23
+ } cache_row[0x100];
24
+ } t_tmbk;
25
+
26
+ /*
27
+ * We use 8 Bits of the klass object id as index to a 256 entry cache.
28
+ * This avoids full lookups in most cases.
29
+ */
30
+ #define CACHE_LOOKUP(this, klass) ( &this->cache_row[(((unsigned long)klass) >> 8) & 0xff] )
31
+
32
+
33
+ static t_pg_coder *
34
+ pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
35
+ {
36
+ t_pg_coder *p_coder;
37
+ struct pg_tmbk_coder_cache_entry *p_ce;
38
+
39
+ p_ce = CACHE_LOOKUP(this, klass);
40
+
41
+ /* Is the cache entry for the expected klass? */
42
+ if( p_ce->klass == klass ) {
43
+ p_coder = p_ce->p_coder;
44
+ } else {
45
+ /* No, then do a full lookup based on the ancestors. */
46
+ VALUE obj = rb_hash_lookup( this->klass_to_coder, klass );
47
+
48
+ if( NIL_P(obj) ){
49
+ int i;
50
+ VALUE ancestors = rb_mod_ancestors( klass );
51
+
52
+ Check_Type( ancestors, T_ARRAY );
53
+ /* Don't look at the first element, it's expected to equal klass. */
54
+ for( i=1; i<RARRAY_LEN(ancestors); i++ ){
55
+ obj = rb_hash_lookup( this->klass_to_coder, rb_ary_entry( ancestors, i) );
56
+
57
+ if( !NIL_P(obj) )
58
+ break;
59
+ }
60
+ }
61
+
62
+ if(NIL_P(obj)){
63
+ p_coder = NULL;
64
+ }else if(rb_obj_is_kind_of(obj, rb_cPG_Coder)){
65
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
66
+ }else{
67
+ if( RB_TYPE_P(obj, T_SYMBOL) ){
68
+ /* A Symbol: Call the method with this name. */
69
+ obj = rb_funcall(this->self, SYM2ID(obj), 1, param_value);
70
+ }else{
71
+ /* A Proc object (or something that responds to #call). */
72
+ obj = rb_funcall(obj, rb_intern("call"), 1, param_value);
73
+ }
74
+
75
+ if( NIL_P(obj) ){
76
+ p_coder = NULL;
77
+ }else{
78
+ /* Check retrieved coder type */
79
+ TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
80
+ }
81
+
82
+ /* We can not cache coders retrieved by ruby code, because we can not anticipate
83
+ * the returned Coder object. */
84
+ return p_coder;
85
+ }
86
+
87
+ /* Write the retrieved coder to the cache */
88
+ p_ce->klass = klass;
89
+ p_ce->p_coder = p_coder;
90
+ }
91
+ return p_coder;
92
+ }
93
+
94
+
95
+ static t_pg_coder *
96
+ pg_tmbk_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
97
+ {
98
+ t_tmbk *this = (t_tmbk *)p_typemap;
99
+ t_pg_coder *p_coder;
100
+
101
+ p_coder = pg_tmbk_lookup_klass( this, rb_obj_class(param_value), param_value );
102
+
103
+ if( !p_coder ){
104
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
105
+ return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
106
+ }
107
+
108
+ return p_coder;
109
+ }
110
+
111
+ static VALUE
112
+ pg_tmbk_fit_to_query( VALUE self, VALUE params )
113
+ {
114
+ t_tmbk *this = (t_tmbk *)RTYPEDDATA_DATA(self);
115
+ /* Nothing to check at this typemap, but ensure that the default type map fits. */
116
+ t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
117
+ default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
118
+ return self;
119
+ }
120
+
121
+ static void
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 )
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. */
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,
161
+ };
162
+
163
+ static VALUE
164
+ pg_tmbk_s_allocate( VALUE klass )
165
+ {
166
+ t_tmbk *this;
167
+ VALUE self;
168
+
169
+ self = TypedData_Make_Struct( klass, t_tmbk, &pg_tmbk_type, this );
170
+ this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
171
+ this->typemap.funcs.fit_to_query = pg_tmbk_fit_to_query;
172
+ this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
173
+ this->typemap.funcs.typecast_result_value = pg_typemap_result_value;
174
+ this->typemap.funcs.typecast_query_param = pg_tmbk_typecast_query_param;
175
+ this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
176
+ this->typemap.default_typemap = pg_typemap_all_strings;
177
+
178
+ /* We need to store self in the this-struct, because pg_tmbk_typecast_query_param(),
179
+ * is called with the this-pointer only. */
180
+ this->self = self;
181
+ this->klass_to_coder = rb_hash_new();
182
+
183
+ /* The cache is properly initialized by TypedData_Make_Struct(). */
184
+
185
+ return self;
186
+ }
187
+
188
+ /*
189
+ * call-seq:
190
+ * typemap.[class] = coder
191
+ *
192
+ * Assigns a new PG::Coder object to the type map. The encoder
193
+ * is chosen for all values that are a kind of the given +class+ .
194
+ *
195
+ * +coder+ can be one of the following:
196
+ * * +nil+ - Values are forwarded to the #default_type_map .
197
+ * * a PG::Coder - Values are encoded by the given encoder
198
+ * * a Symbol - The method of this type map (or a derivation) that is called for each value to sent.
199
+ * It must return a PG::Coder or +nil+ .
200
+ * * a Proc - The Proc object is called for each value. It must return a PG::Coder or +nil+ .
201
+ *
202
+ */
203
+ static VALUE
204
+ pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
205
+ {
206
+ t_tmbk *this = RTYPEDDATA_DATA( self );
207
+
208
+ if(NIL_P(coder)){
209
+ rb_hash_delete( this->klass_to_coder, klass );
210
+ }else{
211
+ rb_hash_aset( this->klass_to_coder, klass, coder );
212
+ }
213
+
214
+ /* The cache lookup key can be a derivation of the klass.
215
+ * So we can not expire the cache selectively. */
216
+ memset( &this->cache_row, 0, sizeof(this->cache_row) );
217
+
218
+ return coder;
219
+ }
220
+
221
+ /*
222
+ * call-seq:
223
+ * typemap.[class] -> coder
224
+ *
225
+ * Returns the encoder object for the given +class+
226
+ */
227
+ static VALUE
228
+ pg_tmbk_aref( VALUE self, VALUE klass )
229
+ {
230
+ t_tmbk *this = RTYPEDDATA_DATA( self );
231
+
232
+ return rb_hash_lookup(this->klass_to_coder, klass);
233
+ }
234
+
235
+ /*
236
+ * call-seq:
237
+ * typemap.coders -> Hash
238
+ *
239
+ * Returns all classes and their assigned encoder object.
240
+ */
241
+ static VALUE
242
+ pg_tmbk_coders( VALUE self )
243
+ {
244
+ t_tmbk *this = RTYPEDDATA_DATA( self );
245
+
246
+ return rb_obj_freeze(rb_hash_dup(this->klass_to_coder));
247
+ }
248
+
249
+ void
250
+ init_pg_type_map_by_class()
251
+ {
252
+ /*
253
+ * Document-class: PG::TypeMapByClass < PG::TypeMap
254
+ *
255
+ * This type map casts values based on the class or the ancestors of the given value
256
+ * to be sent.
257
+ *
258
+ * This type map is usable for type casting query bind parameters and COPY data
259
+ * for PG::Connection#put_copy_data . Therefore only encoders might be assigned by
260
+ * the #[]= method.
261
+ */
262
+ rb_cTypeMapByClass = rb_define_class_under( rb_mPG, "TypeMapByClass", rb_cTypeMap );
263
+ rb_define_alloc_func( rb_cTypeMapByClass, pg_tmbk_s_allocate );
264
+ rb_define_method( rb_cTypeMapByClass, "[]=", pg_tmbk_aset, 2 );
265
+ rb_define_method( rb_cTypeMapByClass, "[]", pg_tmbk_aref, 1 );
266
+ rb_define_method( rb_cTypeMapByClass, "coders", pg_tmbk_coders, 0 );
267
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
268
+ rb_include_module( rb_cTypeMapByClass, rb_mDefaultTypeMappable );
269
+ }