pg 1.2.3 → 1.6.1
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +986 -0
- data/Gemfile +23 -0
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +300 -0
- data/README.md +327 -0
- data/Rakefile +123 -144
- data/certs/ged.pem +24 -0
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +16 -5
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +5 -5
- data/ext/extconf.rb +259 -33
- data/ext/gvl_wrappers.c +17 -2
- data/ext/gvl_wrappers.h +56 -0
- data/ext/pg.c +89 -63
- data/ext/pg.h +31 -8
- data/ext/pg_binary_decoder.c +232 -1
- data/ext/pg_binary_encoder.c +428 -1
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +148 -36
- data/ext/pg_connection.c +1365 -817
- data/ext/pg_copy_coder.c +360 -38
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +56 -25
- data/ext/pg_result.c +187 -76
- data/ext/pg_text_decoder.c +32 -11
- data/ext/pg_text_encoder.c +65 -33
- data/ext/pg_tuple.c +84 -61
- data/ext/pg_type_map.c +44 -10
- data/ext/pg_type_map_all_strings.c +17 -3
- data/ext/pg_type_map_by_class.c +54 -27
- data/ext/pg_type_map_by_column.c +74 -31
- data/ext/pg_type_map_by_mri_type.c +48 -19
- data/ext/pg_type_map_by_oid.c +61 -27
- data/ext/pg_type_map_in_ruby.c +55 -21
- data/ext/pg_util.c +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +67 -0
- data/lib/pg/basic_type_map_for_queries.rb +206 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +311 -0
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +18 -14
- data/lib/pg/connection.rb +894 -91
- data/lib/pg/exceptions.rb +20 -1
- data/lib/pg/text_decoder/date.rb +21 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +17 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +13 -0
- data/lib/pg/text_encoder/inet.rb +31 -0
- data/lib/pg/text_encoder/json.rb +17 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +109 -39
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/misc/yugabyte/Dockerfile +9 -0
- data/misc/yugabyte/docker-compose.yml +28 -0
- data/misc/yugabyte/pg-test.rb +45 -0
- data/pg.gemspec +38 -0
- data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
- data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +102 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data.tar.gz.sig +0 -0
- metadata +139 -213
- metadata.gz.sig +0 -0
- data/.gemtest +0 -0
- data/ChangeLog +0 -0
- data/History.rdoc +0 -578
- data/Manifest.txt +0 -73
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -213
- data/Rakefile.cross +0 -299
- data/lib/pg/basic_type_mapping.rb +0 -522
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -380
- data/spec/pg/basic_type_mapping_spec.rb +0 -630
- data/spec/pg/connection_spec.rb +0 -1949
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -681
- data/spec/pg/tuple_spec.rb +0 -333
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -226
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -1123
- data/spec/pg_spec.rb +0 -50
data/ext/pg_type_map_by_column.c
CHANGED
@@ -16,7 +16,7 @@ static VALUE
|
|
16
16
|
pg_tmbc_fit_to_result( VALUE self, VALUE result )
|
17
17
|
{
|
18
18
|
int nfields;
|
19
|
-
t_tmbc *this =
|
19
|
+
t_tmbc *this = RTYPEDDATA_DATA( self );
|
20
20
|
t_typemap *default_tm;
|
21
21
|
VALUE sub_typemap;
|
22
22
|
|
@@ -26,8 +26,8 @@ pg_tmbc_fit_to_result( VALUE self, VALUE result )
|
|
26
26
|
nfields, this->nfields );
|
27
27
|
}
|
28
28
|
|
29
|
-
/* Ensure that the default type map fits
|
30
|
-
default_tm =
|
29
|
+
/* Ensure that the default type map fits equally. */
|
30
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
31
31
|
sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );
|
32
32
|
|
33
33
|
/* Did the default type return the same object ? */
|
@@ -42,7 +42,7 @@ pg_tmbc_fit_to_result( VALUE self, VALUE result )
|
|
42
42
|
|
43
43
|
memcpy( p_new_typemap, this, struct_size );
|
44
44
|
p_new_typemap->typemap.default_typemap = sub_typemap;
|
45
|
-
|
45
|
+
RTYPEDDATA_DATA(new_typemap) = p_new_typemap;
|
46
46
|
return new_typemap;
|
47
47
|
}
|
48
48
|
}
|
@@ -51,17 +51,18 @@ static VALUE
|
|
51
51
|
pg_tmbc_fit_to_query( VALUE self, VALUE params )
|
52
52
|
{
|
53
53
|
int nfields;
|
54
|
-
t_tmbc *this =
|
54
|
+
t_tmbc *this = RTYPEDDATA_DATA( self );
|
55
55
|
t_typemap *default_tm;
|
56
56
|
|
57
|
+
Check_Type(params, T_ARRAY);
|
57
58
|
nfields = (int)RARRAY_LEN( params );
|
58
59
|
if ( this->nfields != nfields ) {
|
59
60
|
rb_raise( rb_eArgError, "number of result fields (%d) does not match number of mapped columns (%d)",
|
60
61
|
nfields, this->nfields );
|
61
62
|
}
|
62
63
|
|
63
|
-
/* Ensure that the default type map fits
|
64
|
-
default_tm =
|
64
|
+
/* Ensure that the default type map fits equally. */
|
65
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
65
66
|
default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
|
66
67
|
|
67
68
|
return self;
|
@@ -70,10 +71,10 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
|
|
70
71
|
static int
|
71
72
|
pg_tmbc_fit_to_copy_get( VALUE self )
|
72
73
|
{
|
73
|
-
t_tmbc *this =
|
74
|
+
t_tmbc *this = RTYPEDDATA_DATA( self );
|
74
75
|
|
75
|
-
/* Ensure that the default type map fits
|
76
|
-
t_typemap *default_tm =
|
76
|
+
/* Ensure that the default type map fits equally. */
|
77
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
77
78
|
default_tm->funcs.fit_to_copy_get( this->typemap.default_typemap );
|
78
79
|
|
79
80
|
return this->nfields;
|
@@ -107,7 +108,7 @@ pg_tmbc_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
|
|
107
108
|
}
|
108
109
|
}
|
109
110
|
|
110
|
-
default_tm =
|
111
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
111
112
|
return default_tm->funcs.typecast_result_value( default_tm, result, tuple, field );
|
112
113
|
}
|
113
114
|
|
@@ -120,7 +121,7 @@ pg_tmbc_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field
|
|
120
121
|
t_pg_coder *p_coder = this->convs[field].cconv;
|
121
122
|
|
122
123
|
if( !p_coder ){
|
123
|
-
t_typemap *default_tm =
|
124
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
124
125
|
return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
|
125
126
|
}
|
126
127
|
|
@@ -142,7 +143,7 @@ pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, i
|
|
142
143
|
p_coder = this->convs[fieldno].cconv;
|
143
144
|
|
144
145
|
if( !p_coder ){
|
145
|
-
t_typemap *default_tm =
|
146
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
146
147
|
return default_tm->funcs.typecast_copy_get( default_tm, field_str, fieldno, format, enc_idx );
|
147
148
|
}
|
148
149
|
|
@@ -150,15 +151,17 @@ pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, i
|
|
150
151
|
|
151
152
|
/* Is it a pure String conversion? Then we can directly send field_str to the user. */
|
152
153
|
if( dec_func == pg_text_dec_string ){
|
154
|
+
rb_str_modify(field_str);
|
153
155
|
PG_ENCODING_SET_NOCHECK( field_str, enc_idx );
|
154
156
|
return field_str;
|
155
157
|
}
|
156
158
|
if( dec_func == pg_bin_dec_bytea ){
|
159
|
+
rb_str_modify(field_str);
|
157
160
|
PG_ENCODING_SET_NOCHECK( field_str, rb_ascii8bit_encindex() );
|
158
161
|
return field_str;
|
159
162
|
}
|
160
163
|
|
161
|
-
return dec_func( p_coder, RSTRING_PTR(field_str),
|
164
|
+
return dec_func( p_coder, RSTRING_PTR(field_str), RSTRING_LENINT(field_str), 0, fieldno, enc_idx );
|
162
165
|
}
|
163
166
|
|
164
167
|
const struct pg_typemap_funcs pg_tmbc_funcs = {
|
@@ -171,38 +174,77 @@ const struct pg_typemap_funcs pg_tmbc_funcs = {
|
|
171
174
|
};
|
172
175
|
|
173
176
|
static void
|
174
|
-
pg_tmbc_mark(
|
177
|
+
pg_tmbc_mark( void *_this )
|
175
178
|
{
|
179
|
+
t_tmbc *this = (t_tmbc *)_this;
|
176
180
|
int i;
|
177
181
|
|
178
182
|
/* allocated but not initialized ? */
|
179
183
|
if( this == (t_tmbc *)&pg_typemap_funcs ) return;
|
180
184
|
|
181
|
-
|
185
|
+
pg_typemap_mark(&this->typemap);
|
182
186
|
for( i=0; i<this->nfields; i++){
|
183
187
|
t_pg_coder *p_coder = this->convs[i].cconv;
|
184
188
|
if( p_coder )
|
185
|
-
|
189
|
+
rb_gc_mark_movable(p_coder->coder_obj);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
static size_t
|
194
|
+
pg_tmbc_memsize( const void *_this )
|
195
|
+
{
|
196
|
+
const t_tmbc *this = (const t_tmbc *)_this;
|
197
|
+
return sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * this->nfields;
|
198
|
+
}
|
199
|
+
|
200
|
+
static void
|
201
|
+
pg_tmbc_compact( void *_this )
|
202
|
+
{
|
203
|
+
t_tmbc *this = (t_tmbc *)_this;
|
204
|
+
int i;
|
205
|
+
|
206
|
+
/* allocated but not initialized ? */
|
207
|
+
if( this == (t_tmbc *)&pg_typemap_funcs ) return;
|
208
|
+
|
209
|
+
pg_typemap_compact(&this->typemap);
|
210
|
+
for( i=0; i<this->nfields; i++){
|
211
|
+
t_pg_coder *p_coder = this->convs[i].cconv;
|
212
|
+
if( p_coder )
|
213
|
+
pg_gc_location(p_coder->coder_obj);
|
186
214
|
}
|
187
215
|
}
|
188
216
|
|
189
217
|
static void
|
190
|
-
pg_tmbc_free(
|
218
|
+
pg_tmbc_free( void *_this )
|
191
219
|
{
|
220
|
+
t_tmbc *this = (t_tmbc *)_this;
|
192
221
|
/* allocated but not initialized ? */
|
193
222
|
if( this == (t_tmbc *)&pg_typemap_funcs ) return;
|
194
223
|
xfree( this );
|
195
224
|
}
|
196
225
|
|
226
|
+
static const rb_data_type_t pg_tmbc_type = {
|
227
|
+
"PG::TypeMapByColumn",
|
228
|
+
{
|
229
|
+
pg_tmbc_mark,
|
230
|
+
pg_tmbc_free,
|
231
|
+
pg_tmbc_memsize,
|
232
|
+
pg_tmbc_compact,
|
233
|
+
},
|
234
|
+
&pg_typemap_type,
|
235
|
+
0,
|
236
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
237
|
+
};
|
238
|
+
|
197
239
|
static VALUE
|
198
240
|
pg_tmbc_s_allocate( VALUE klass )
|
199
241
|
{
|
200
242
|
/* Use pg_typemap_funcs as interim struct until #initialize is called. */
|
201
|
-
return
|
243
|
+
return TypedData_Wrap_Struct( klass, &pg_tmbc_type, (t_tmbc *)&pg_typemap_funcs );
|
202
244
|
}
|
203
245
|
|
204
246
|
VALUE
|
205
|
-
pg_tmbc_allocate()
|
247
|
+
pg_tmbc_allocate(void)
|
206
248
|
{
|
207
249
|
return pg_tmbc_s_allocate(rb_cTypeMapByColumn);
|
208
250
|
}
|
@@ -221,19 +263,19 @@ pg_tmbc_allocate()
|
|
221
263
|
static VALUE
|
222
264
|
pg_tmbc_init(VALUE self, VALUE conv_ary)
|
223
265
|
{
|
224
|
-
|
266
|
+
long i;
|
225
267
|
t_tmbc *this;
|
226
268
|
int conv_ary_len;
|
227
269
|
|
228
|
-
|
270
|
+
rb_check_frozen(self);
|
229
271
|
Check_Type(conv_ary, T_ARRAY);
|
230
|
-
conv_ary_len =
|
272
|
+
conv_ary_len = RARRAY_LENINT(conv_ary);
|
231
273
|
this = xmalloc(sizeof(t_tmbc) + sizeof(struct pg_tmbc_converter) * conv_ary_len);
|
232
274
|
/* Set nfields to 0 at first, so that GC mark function doesn't access uninitialized memory. */
|
233
275
|
this->nfields = 0;
|
234
276
|
this->typemap.funcs = pg_tmbc_funcs;
|
235
|
-
this->typemap.default_typemap
|
236
|
-
|
277
|
+
RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
|
278
|
+
RTYPEDDATA_DATA(self) = this;
|
237
279
|
|
238
280
|
for(i=0; i<conv_ary_len; i++)
|
239
281
|
{
|
@@ -242,11 +284,12 @@ pg_tmbc_init(VALUE self, VALUE conv_ary)
|
|
242
284
|
if( obj == Qnil ){
|
243
285
|
/* no type cast */
|
244
286
|
this->convs[i].cconv = NULL;
|
245
|
-
} else if( rb_obj_is_kind_of(obj, rb_cPG_Coder) ){
|
246
|
-
Data_Get_Struct(obj, t_pg_coder, this->convs[i].cconv);
|
247
287
|
} else {
|
248
|
-
|
249
|
-
|
288
|
+
t_pg_coder *p_coder;
|
289
|
+
/* Check argument type and store the coder pointer */
|
290
|
+
TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
|
291
|
+
RB_OBJ_WRITTEN(self, Qnil, p_coder->coder_obj);
|
292
|
+
this->convs[i].cconv = p_coder;
|
250
293
|
}
|
251
294
|
}
|
252
295
|
|
@@ -266,7 +309,7 @@ static VALUE
|
|
266
309
|
pg_tmbc_coders(VALUE self)
|
267
310
|
{
|
268
311
|
int i;
|
269
|
-
t_tmbc *this =
|
312
|
+
t_tmbc *this = RTYPEDDATA_DATA( self );
|
270
313
|
VALUE ary_coders = rb_ary_new();
|
271
314
|
|
272
315
|
for( i=0; i<this->nfields; i++){
|
@@ -282,7 +325,7 @@ pg_tmbc_coders(VALUE self)
|
|
282
325
|
}
|
283
326
|
|
284
327
|
void
|
285
|
-
init_pg_type_map_by_column()
|
328
|
+
init_pg_type_map_by_column(void)
|
286
329
|
{
|
287
330
|
s_id_decode = rb_intern("decode");
|
288
331
|
s_id_encode = rb_intern("encode");
|
@@ -71,16 +71,12 @@ pg_tmbmt_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int fiel
|
|
71
71
|
|
72
72
|
obj = rb_funcall(ask_for_coder, rb_intern("call"), 1, param_value);
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
}else{
|
77
|
-
rb_raise(rb_eTypeError, "argument %d has invalid type %s (should be nil or some kind of PG::Coder)",
|
78
|
-
field+1, rb_obj_classname( obj ));
|
79
|
-
}
|
74
|
+
/* Check argument type and store the coder pointer */
|
75
|
+
TypedData_Get_Struct(obj, t_pg_coder, &pg_coder_type, p_coder);
|
80
76
|
}
|
81
77
|
|
82
78
|
if( !p_coder ){
|
83
|
-
t_typemap *default_tm =
|
79
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
84
80
|
return default_tm->funcs.typecast_query_param( default_tm, param_value, field );
|
85
81
|
}
|
86
82
|
|
@@ -90,24 +86,57 @@ pg_tmbmt_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int fiel
|
|
90
86
|
static VALUE
|
91
87
|
pg_tmbmt_fit_to_query( VALUE self, VALUE params )
|
92
88
|
{
|
93
|
-
t_tmbmt *this = (t_tmbmt *)
|
89
|
+
t_tmbmt *this = (t_tmbmt *)RTYPEDDATA_DATA(self);
|
94
90
|
/* Nothing to check at this typemap, but ensure that the default type map fits. */
|
95
|
-
t_typemap *default_tm =
|
91
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
96
92
|
default_tm->funcs.fit_to_query( this->typemap.default_typemap, params );
|
97
93
|
return self;
|
98
94
|
}
|
99
95
|
|
100
96
|
#define GC_MARK_AS_USED(type) \
|
101
|
-
|
102
|
-
|
97
|
+
rb_gc_mark_movable( this->coders.ask_##type ); \
|
98
|
+
rb_gc_mark_movable( this->coders.coder_obj_##type );
|
103
99
|
|
104
100
|
static void
|
105
|
-
pg_tmbmt_mark(
|
101
|
+
pg_tmbmt_mark( void *_this )
|
106
102
|
{
|
107
|
-
|
103
|
+
t_tmbmt *this = (t_tmbmt *)_this;
|
104
|
+
pg_typemap_mark(&this->typemap);
|
108
105
|
FOR_EACH_MRI_TYPE( GC_MARK_AS_USED );
|
109
106
|
}
|
110
107
|
|
108
|
+
static size_t
|
109
|
+
pg_tmbmt_memsize( const void *_this )
|
110
|
+
{
|
111
|
+
const t_tmbmt *this = (const t_tmbmt *)_this;
|
112
|
+
return sizeof(*this);
|
113
|
+
}
|
114
|
+
|
115
|
+
#define GC_COMPACT(type) \
|
116
|
+
pg_gc_location( this->coders.ask_##type ); \
|
117
|
+
pg_gc_location( this->coders.coder_obj_##type );
|
118
|
+
|
119
|
+
static void
|
120
|
+
pg_tmbmt_compact( void *_this )
|
121
|
+
{
|
122
|
+
t_tmbmt *this = (t_tmbmt *)_this;
|
123
|
+
pg_typemap_compact(&this->typemap);
|
124
|
+
FOR_EACH_MRI_TYPE( GC_COMPACT );
|
125
|
+
}
|
126
|
+
|
127
|
+
static const rb_data_type_t pg_tmbmt_type = {
|
128
|
+
"PG::TypeMapByMriType",
|
129
|
+
{
|
130
|
+
pg_tmbmt_mark,
|
131
|
+
RUBY_TYPED_DEFAULT_FREE,
|
132
|
+
pg_tmbmt_memsize,
|
133
|
+
pg_tmbmt_compact,
|
134
|
+
},
|
135
|
+
&pg_typemap_type,
|
136
|
+
0,
|
137
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
138
|
+
};
|
139
|
+
|
111
140
|
#define INIT_VARIABLES(type) \
|
112
141
|
this->coders.coder_##type = NULL; \
|
113
142
|
this->coders.ask_##type = Qnil; \
|
@@ -119,7 +148,7 @@ pg_tmbmt_s_allocate( VALUE klass )
|
|
119
148
|
t_tmbmt *this;
|
120
149
|
VALUE self;
|
121
150
|
|
122
|
-
self =
|
151
|
+
self = TypedData_Make_Struct( klass, t_tmbmt, &pg_tmbmt_type, this );
|
123
152
|
this->typemap.funcs.fit_to_result = pg_typemap_fit_to_result;
|
124
153
|
this->typemap.funcs.fit_to_query = pg_tmbmt_fit_to_query;
|
125
154
|
this->typemap.funcs.fit_to_copy_get = pg_typemap_fit_to_copy_get;
|
@@ -140,7 +169,7 @@ pg_tmbmt_s_allocate( VALUE klass )
|
|
140
169
|
this->coders.coder_##type = NULL; \
|
141
170
|
this->coders.ask_##type = Qnil; \
|
142
171
|
}else if(rb_obj_is_kind_of(coder, rb_cPG_Coder)){ \
|
143
|
-
|
172
|
+
TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, this->coders.coder_##type); \
|
144
173
|
this->coders.ask_##type = Qnil; \
|
145
174
|
}else if(RB_TYPE_P(coder, T_SYMBOL)){ \
|
146
175
|
this->coders.coder_##type = NULL; \
|
@@ -188,7 +217,7 @@ pg_tmbmt_s_allocate( VALUE klass )
|
|
188
217
|
static VALUE
|
189
218
|
pg_tmbmt_aset( VALUE self, VALUE mri_type, VALUE coder )
|
190
219
|
{
|
191
|
-
t_tmbmt *this =
|
220
|
+
t_tmbmt *this = RTYPEDDATA_DATA( self );
|
192
221
|
char *p_mri_type;
|
193
222
|
|
194
223
|
p_mri_type = StringValueCStr(mri_type);
|
@@ -220,7 +249,7 @@ static VALUE
|
|
220
249
|
pg_tmbmt_aref( VALUE self, VALUE mri_type )
|
221
250
|
{
|
222
251
|
VALUE coder;
|
223
|
-
t_tmbmt *this =
|
252
|
+
t_tmbmt *this = RTYPEDDATA_DATA( self );
|
224
253
|
char *p_mri_type;
|
225
254
|
|
226
255
|
p_mri_type = StringValueCStr(mri_type);
|
@@ -248,7 +277,7 @@ pg_tmbmt_aref( VALUE self, VALUE mri_type )
|
|
248
277
|
static VALUE
|
249
278
|
pg_tmbmt_coders( VALUE self )
|
250
279
|
{
|
251
|
-
t_tmbmt *this =
|
280
|
+
t_tmbmt *this = RTYPEDDATA_DATA( self );
|
252
281
|
VALUE hash_coders = rb_hash_new();
|
253
282
|
|
254
283
|
FOR_EACH_MRI_TYPE( ADD_TO_HASH );
|
@@ -257,7 +286,7 @@ pg_tmbmt_coders( VALUE self )
|
|
257
286
|
}
|
258
287
|
|
259
288
|
void
|
260
|
-
init_pg_type_map_by_mri_type()
|
289
|
+
init_pg_type_map_by_mri_type(void)
|
261
290
|
{
|
262
291
|
/*
|
263
292
|
* Document-class: PG::TypeMapByMriType < PG::TypeMap
|
data/ext/pg_type_map_by_oid.c
CHANGED
@@ -46,7 +46,7 @@ pg_tmbo_lookup_oid(t_tmbo *this, int format, Oid oid)
|
|
46
46
|
} else {
|
47
47
|
VALUE obj = rb_hash_lookup( this->format[format].oid_to_coder, UINT2NUM( oid ));
|
48
48
|
/* obj must be nil or some kind of PG::Coder, this is checked at insertion */
|
49
|
-
conv = NIL_P(obj) ? NULL :
|
49
|
+
conv = NIL_P(obj) ? NULL : RTYPEDDATA_DATA(obj);
|
50
50
|
/* Write the retrieved coder to the cache */
|
51
51
|
p_ce->oid = oid;
|
52
52
|
p_ce->p_coder = conv;
|
@@ -70,7 +70,7 @@ pg_tmbo_build_type_map_for_result2( t_tmbo *this, PGresult *pgresult )
|
|
70
70
|
p_colmap->typemap.default_typemap = pg_typemap_all_strings;
|
71
71
|
|
72
72
|
colmap = pg_tmbc_allocate();
|
73
|
-
|
73
|
+
RTYPEDDATA_DATA(colmap) = p_colmap;
|
74
74
|
|
75
75
|
for(i=0; i<nfields; i++)
|
76
76
|
{
|
@@ -113,18 +113,18 @@ pg_tmbo_result_value(t_typemap *p_typemap, VALUE result, int tuple, int field)
|
|
113
113
|
return dec_func( p_coder, val, len, tuple, field, p_result->enc_idx );
|
114
114
|
}
|
115
115
|
|
116
|
-
default_tm =
|
116
|
+
default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
117
117
|
return default_tm->funcs.typecast_result_value( default_tm, result, tuple, field );
|
118
118
|
}
|
119
119
|
|
120
120
|
static VALUE
|
121
121
|
pg_tmbo_fit_to_result( VALUE self, VALUE result )
|
122
122
|
{
|
123
|
-
t_tmbo *this =
|
123
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
124
124
|
PGresult *pgresult = pgresult_get( result );
|
125
125
|
|
126
|
-
/* Ensure that the default type map fits
|
127
|
-
t_typemap *default_tm =
|
126
|
+
/* Ensure that the default type map fits equally. */
|
127
|
+
t_typemap *default_tm = RTYPEDDATA_DATA( this->typemap.default_typemap );
|
128
128
|
VALUE sub_typemap = default_tm->funcs.fit_to_result( this->typemap.default_typemap, result );
|
129
129
|
|
130
130
|
if( PQntuples( pgresult ) <= this->max_rows_for_online_lookup ){
|
@@ -137,7 +137,7 @@ pg_tmbo_fit_to_result( VALUE self, VALUE result )
|
|
137
137
|
/* The default type map built a new object, so we need to propagate it
|
138
138
|
* and build a copy of this type map. */
|
139
139
|
VALUE new_typemap = pg_tmbo_s_allocate( rb_cTypeMapByOid );
|
140
|
-
t_tmbo *p_new_typemap =
|
140
|
+
t_tmbo *p_new_typemap = RTYPEDDATA_DATA(new_typemap);
|
141
141
|
*p_new_typemap = *this;
|
142
142
|
p_new_typemap->typemap.default_typemap = sub_typemap;
|
143
143
|
return new_typemap;
|
@@ -147,23 +147,56 @@ pg_tmbo_fit_to_result( VALUE self, VALUE result )
|
|
147
147
|
* uses a fast array lookup.
|
148
148
|
*/
|
149
149
|
VALUE new_typemap = pg_tmbo_build_type_map_for_result2( this, pgresult );
|
150
|
-
t_tmbo *p_new_typemap =
|
150
|
+
t_tmbo *p_new_typemap = RTYPEDDATA_DATA(new_typemap);
|
151
151
|
p_new_typemap->typemap.default_typemap = sub_typemap;
|
152
152
|
return new_typemap;
|
153
153
|
}
|
154
154
|
}
|
155
155
|
|
156
156
|
static void
|
157
|
-
pg_tmbo_mark(
|
157
|
+
pg_tmbo_mark( void *_this )
|
158
158
|
{
|
159
|
+
t_tmbo *this = (t_tmbo *)_this;
|
159
160
|
int i;
|
160
161
|
|
161
|
-
|
162
|
+
pg_typemap_mark(&this->typemap);
|
162
163
|
for( i=0; i<2; i++){
|
163
|
-
|
164
|
+
rb_gc_mark_movable(this->format[i].oid_to_coder);
|
164
165
|
}
|
165
166
|
}
|
166
167
|
|
168
|
+
static size_t
|
169
|
+
pg_tmbo_memsize( const void *_this )
|
170
|
+
{
|
171
|
+
const t_tmbo *this = (const t_tmbo *)_this;
|
172
|
+
return sizeof(*this);
|
173
|
+
}
|
174
|
+
|
175
|
+
static void
|
176
|
+
pg_tmbo_compact( void *_this )
|
177
|
+
{
|
178
|
+
t_tmbo *this = (t_tmbo *)_this;
|
179
|
+
int i;
|
180
|
+
|
181
|
+
pg_typemap_compact(&this->typemap);
|
182
|
+
for( i=0; i<2; i++){
|
183
|
+
pg_gc_location(this->format[i].oid_to_coder);
|
184
|
+
}
|
185
|
+
}
|
186
|
+
|
187
|
+
static const rb_data_type_t pg_tmbo_type = {
|
188
|
+
"PG::TypeMapByOid",
|
189
|
+
{
|
190
|
+
pg_tmbo_mark,
|
191
|
+
RUBY_TYPED_DEFAULT_FREE,
|
192
|
+
pg_tmbo_memsize,
|
193
|
+
pg_tmbo_compact,
|
194
|
+
},
|
195
|
+
&pg_typemap_type,
|
196
|
+
0,
|
197
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
198
|
+
};
|
199
|
+
|
167
200
|
static VALUE
|
168
201
|
pg_tmbo_s_allocate( VALUE klass )
|
169
202
|
{
|
@@ -171,7 +204,7 @@ pg_tmbo_s_allocate( VALUE klass )
|
|
171
204
|
VALUE self;
|
172
205
|
int i;
|
173
206
|
|
174
|
-
self =
|
207
|
+
self = TypedData_Make_Struct( klass, t_tmbo, &pg_tmbo_type, this );
|
175
208
|
|
176
209
|
this->typemap.funcs.fit_to_result = pg_tmbo_fit_to_result;
|
177
210
|
this->typemap.funcs.fit_to_query = pg_typemap_fit_to_query;
|
@@ -179,11 +212,11 @@ pg_tmbo_s_allocate( VALUE klass )
|
|
179
212
|
this->typemap.funcs.typecast_result_value = pg_tmbo_result_value;
|
180
213
|
this->typemap.funcs.typecast_query_param = pg_typemap_typecast_query_param;
|
181
214
|
this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
|
182
|
-
this->typemap.default_typemap
|
215
|
+
RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
|
183
216
|
this->max_rows_for_online_lookup = 10;
|
184
217
|
|
185
218
|
for( i=0; i<2; i++){
|
186
|
-
this->format[i].oid_to_coder
|
219
|
+
RB_OBJ_WRITE(self, &this->format[i].oid_to_coder, rb_hash_new());
|
187
220
|
}
|
188
221
|
|
189
222
|
return self;
|
@@ -205,15 +238,12 @@ static VALUE
|
|
205
238
|
pg_tmbo_add_coder( VALUE self, VALUE coder )
|
206
239
|
{
|
207
240
|
VALUE hash;
|
208
|
-
t_tmbo *this =
|
241
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
209
242
|
t_pg_coder *p_coder;
|
210
243
|
struct pg_tmbo_oid_cache_entry *p_ce;
|
211
244
|
|
212
|
-
|
213
|
-
|
214
|
-
rb_obj_classname( coder ));
|
215
|
-
|
216
|
-
Data_Get_Struct(coder, t_pg_coder, p_coder);
|
245
|
+
rb_check_frozen(self);
|
246
|
+
TypedData_Get_Struct(coder, t_pg_coder, &pg_coder_type, p_coder);
|
217
247
|
|
218
248
|
if( p_coder->format < 0 || p_coder->format > 1 )
|
219
249
|
rb_raise(rb_eArgError, "invalid format code %d", p_coder->format);
|
@@ -243,10 +273,11 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
|
|
243
273
|
{
|
244
274
|
VALUE hash;
|
245
275
|
VALUE coder;
|
246
|
-
t_tmbo *this =
|
276
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
247
277
|
int i_format = NUM2INT(format);
|
248
278
|
struct pg_tmbo_oid_cache_entry *p_ce;
|
249
279
|
|
280
|
+
rb_check_frozen(self);
|
250
281
|
if( i_format < 0 || i_format > 1 )
|
251
282
|
rb_raise(rb_eArgError, "invalid format code %d", i_format);
|
252
283
|
|
@@ -269,7 +300,7 @@ pg_tmbo_rm_coder( VALUE self, VALUE format, VALUE oid )
|
|
269
300
|
static VALUE
|
270
301
|
pg_tmbo_coders( VALUE self )
|
271
302
|
{
|
272
|
-
t_tmbo *this =
|
303
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
273
304
|
|
274
305
|
return rb_ary_concat(
|
275
306
|
rb_funcall(this->format[0].oid_to_coder, rb_intern("values"), 0),
|
@@ -284,11 +315,14 @@ pg_tmbo_coders( VALUE self )
|
|
284
315
|
* The type map will do Hash lookups for each result value, if the number of rows
|
285
316
|
* is below or equal +number+.
|
286
317
|
*
|
318
|
+
* Default is 10.
|
319
|
+
*
|
287
320
|
*/
|
288
321
|
static VALUE
|
289
322
|
pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
290
323
|
{
|
291
|
-
t_tmbo *this =
|
324
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
325
|
+
rb_check_frozen(self);
|
292
326
|
this->max_rows_for_online_lookup = NUM2INT(value);
|
293
327
|
return value;
|
294
328
|
}
|
@@ -300,7 +334,7 @@ pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
|
300
334
|
static VALUE
|
301
335
|
pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
|
302
336
|
{
|
303
|
-
t_tmbo *this =
|
337
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
304
338
|
return INT2NUM(this->max_rows_for_online_lookup);
|
305
339
|
}
|
306
340
|
|
@@ -309,13 +343,13 @@ pg_tmbo_max_rows_for_online_lookup_get( VALUE self )
|
|
309
343
|
* typemap.build_column_map( result )
|
310
344
|
*
|
311
345
|
* This builds a PG::TypeMapByColumn that fits to the given PG::Result object
|
312
|
-
* based on it's type OIDs.
|
346
|
+
* based on it's type OIDs and binary/text format.
|
313
347
|
*
|
314
348
|
*/
|
315
349
|
static VALUE
|
316
350
|
pg_tmbo_build_column_map( VALUE self, VALUE result )
|
317
351
|
{
|
318
|
-
t_tmbo *this =
|
352
|
+
t_tmbo *this = RTYPEDDATA_DATA( self );
|
319
353
|
|
320
354
|
if ( !rb_obj_is_kind_of(result, rb_cPGresult) ) {
|
321
355
|
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Result)",
|
@@ -327,7 +361,7 @@ pg_tmbo_build_column_map( VALUE self, VALUE result )
|
|
327
361
|
|
328
362
|
|
329
363
|
void
|
330
|
-
init_pg_type_map_by_oid()
|
364
|
+
init_pg_type_map_by_oid(void)
|
331
365
|
{
|
332
366
|
s_id_decode = rb_intern("decode");
|
333
367
|
|