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_tuple.c
CHANGED
@@ -52,64 +52,90 @@ typedef struct {
|
|
52
52
|
VALUE values[0];
|
53
53
|
} t_pg_tuple;
|
54
54
|
|
55
|
-
static inline VALUE
|
56
|
-
|
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
|
-
|
61
|
+
static VALUE f = Qfalse;
|
62
|
+
return &f;
|
62
63
|
}
|
63
64
|
}
|
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
|
+
|
65
72
|
static void
|
66
|
-
pg_tuple_gc_mark(
|
73
|
+
pg_tuple_gc_mark( void *_this )
|
67
74
|
{
|
75
|
+
t_pg_tuple *this = (t_pg_tuple *)_this;
|
68
76
|
int i;
|
69
77
|
|
70
78
|
if( !this ) return;
|
71
|
-
|
72
|
-
|
73
|
-
|
79
|
+
rb_gc_mark_movable( this->result );
|
80
|
+
rb_gc_mark_movable( this->typemap );
|
81
|
+
rb_gc_mark_movable( this->field_map );
|
74
82
|
|
75
83
|
for( i = 0; i < this->num_fields; i++ ){
|
76
|
-
|
84
|
+
rb_gc_mark_movable( this->values[i] );
|
77
85
|
}
|
78
|
-
|
86
|
+
rb_gc_mark_movable( pg_tuple_get_field_names(this) );
|
79
87
|
}
|
80
88
|
|
81
89
|
static void
|
82
|
-
|
90
|
+
pg_tuple_gc_compact( void *_this )
|
83
91
|
{
|
92
|
+
t_pg_tuple *this = (t_pg_tuple *)_this;
|
93
|
+
int i;
|
94
|
+
|
95
|
+
if( !this ) return;
|
96
|
+
pg_gc_location( this->result );
|
97
|
+
pg_gc_location( this->typemap );
|
98
|
+
pg_gc_location( this->field_map );
|
99
|
+
|
100
|
+
for( i = 0; i < this->num_fields; i++ ){
|
101
|
+
pg_gc_location( this->values[i] );
|
102
|
+
}
|
103
|
+
pg_gc_location( *pg_tuple_get_field_names_ptr(this) );
|
104
|
+
}
|
105
|
+
|
106
|
+
static void
|
107
|
+
pg_tuple_gc_free( void *_this )
|
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(
|
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
|
-
"
|
123
|
+
"PG::Tuple",
|
97
124
|
{
|
98
|
-
|
99
|
-
|
100
|
-
|
125
|
+
pg_tuple_gc_mark,
|
126
|
+
pg_tuple_gc_free,
|
127
|
+
pg_tuple_memsize,
|
128
|
+
pg_tuple_gc_compact,
|
101
129
|
},
|
102
130
|
0, 0,
|
103
|
-
|
104
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
105
|
-
#endif
|
131
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
106
132
|
};
|
107
133
|
|
108
134
|
/*
|
109
135
|
* Document-method: allocate
|
110
136
|
*
|
111
137
|
* call-seq:
|
112
|
-
* PG::
|
138
|
+
* PG::Tuple.allocate -> obj
|
113
139
|
*/
|
114
140
|
static VALUE
|
115
141
|
pg_tuple_s_allocate( VALUE klass )
|
@@ -133,9 +159,9 @@ pg_tuple_new(VALUE result, int row_num)
|
|
133
159
|
sizeof(*this->values) * num_fields +
|
134
160
|
sizeof(*this->values) * (dup_names ? 1 : 0));
|
135
161
|
|
136
|
-
this->result
|
137
|
-
this->typemap
|
138
|
-
this->field_map
|
162
|
+
RB_OBJ_WRITE(self, &this->result, result);
|
163
|
+
RB_OBJ_WRITE(self, &this->typemap, p_result->typemap);
|
164
|
+
RB_OBJ_WRITE(self, &this->field_map, field_map);
|
139
165
|
this->row_num = row_num;
|
140
166
|
this->num_fields = num_fields;
|
141
167
|
|
@@ -147,7 +173,8 @@ pg_tuple_new(VALUE result, int row_num)
|
|
147
173
|
/* Some of the column names are duplicated -> we need the keys as Array in addition.
|
148
174
|
* Store it behind the values to save the space in the common case of no dups.
|
149
175
|
*/
|
150
|
-
|
176
|
+
VALUE keys_array = rb_obj_freeze(rb_ary_new4(num_fields, p_result->fnames));
|
177
|
+
RB_OBJ_WRITE(self, &this->values[num_fields], keys_array);
|
151
178
|
}
|
152
179
|
|
153
180
|
RTYPEDDATA_DATA(self) = this;
|
@@ -167,38 +194,41 @@ pg_tuple_get_this( VALUE self )
|
|
167
194
|
}
|
168
195
|
|
169
196
|
static VALUE
|
170
|
-
pg_tuple_materialize_field(
|
197
|
+
pg_tuple_materialize_field(VALUE self, int col)
|
171
198
|
{
|
199
|
+
t_pg_tuple *this = RTYPEDDATA_DATA( self );
|
172
200
|
VALUE value = this->values[col];
|
173
201
|
|
174
202
|
if( value == Qundef ){
|
175
|
-
t_typemap *p_typemap =
|
203
|
+
t_typemap *p_typemap = RTYPEDDATA_DATA( this->typemap );
|
176
204
|
|
177
205
|
pgresult_get(this->result); /* make sure we have a valid PGresult object */
|
178
206
|
value = p_typemap->funcs.typecast_result_value(p_typemap, this->result, this->row_num, col);
|
179
|
-
this->values[col]
|
207
|
+
RB_OBJ_WRITE(self, &this->values[col], value);
|
180
208
|
}
|
181
209
|
|
182
210
|
return value;
|
183
211
|
}
|
184
212
|
|
185
213
|
static void
|
186
|
-
pg_tuple_detach(
|
214
|
+
pg_tuple_detach(VALUE self)
|
187
215
|
{
|
188
|
-
this
|
189
|
-
this->
|
216
|
+
t_pg_tuple *this = RTYPEDDATA_DATA( self );
|
217
|
+
RB_OBJ_WRITE(self, &this->result, Qnil);
|
218
|
+
RB_OBJ_WRITE(self, &this->typemap, Qnil);
|
190
219
|
this->row_num = -1;
|
191
220
|
}
|
192
221
|
|
193
222
|
static void
|
194
|
-
pg_tuple_materialize(
|
223
|
+
pg_tuple_materialize(VALUE self)
|
195
224
|
{
|
225
|
+
t_pg_tuple *this = RTYPEDDATA_DATA( self );
|
196
226
|
int field_num;
|
197
227
|
for(field_num = 0; field_num < this->num_fields; field_num++) {
|
198
|
-
pg_tuple_materialize_field(
|
228
|
+
pg_tuple_materialize_field(self, field_num);
|
199
229
|
}
|
200
230
|
|
201
|
-
pg_tuple_detach(
|
231
|
+
pg_tuple_detach(self);
|
202
232
|
}
|
203
233
|
|
204
234
|
/*
|
@@ -260,7 +290,7 @@ pg_tuple_fetch(int argc, VALUE *argv, VALUE self)
|
|
260
290
|
field_num = NUM2INT(index);
|
261
291
|
}
|
262
292
|
|
263
|
-
return pg_tuple_materialize_field(
|
293
|
+
return pg_tuple_materialize_field(self, field_num);
|
264
294
|
}
|
265
295
|
|
266
296
|
/*
|
@@ -298,7 +328,7 @@ pg_tuple_aref(VALUE self, VALUE key)
|
|
298
328
|
field_num = NUM2INT(index);
|
299
329
|
}
|
300
330
|
|
301
|
-
return pg_tuple_materialize_field(
|
331
|
+
return pg_tuple_materialize_field(self, field_num);
|
302
332
|
}
|
303
333
|
|
304
334
|
static VALUE
|
@@ -309,10 +339,9 @@ pg_tuple_num_fields_for_enum(VALUE self, VALUE args, VALUE eobj)
|
|
309
339
|
}
|
310
340
|
|
311
341
|
static int
|
312
|
-
pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE
|
342
|
+
pg_tuple_yield_key_value(VALUE key, VALUE index, VALUE self)
|
313
343
|
{
|
314
|
-
|
315
|
-
VALUE value = pg_tuple_materialize_field(this, NUM2INT(index));
|
344
|
+
VALUE value = pg_tuple_materialize_field(self, NUM2INT(index));
|
316
345
|
rb_yield_values(2, key, value);
|
317
346
|
return ST_CONTINUE;
|
318
347
|
}
|
@@ -334,16 +363,16 @@ pg_tuple_each(VALUE self)
|
|
334
363
|
field_names = pg_tuple_get_field_names(this);
|
335
364
|
|
336
365
|
if( field_names == Qfalse ){
|
337
|
-
rb_hash_foreach(this->field_map, pg_tuple_yield_key_value,
|
366
|
+
rb_hash_foreach(this->field_map, pg_tuple_yield_key_value, self);
|
338
367
|
} else {
|
339
368
|
int i;
|
340
369
|
for( i = 0; i < this->num_fields; i++ ){
|
341
|
-
VALUE value = pg_tuple_materialize_field(
|
370
|
+
VALUE value = pg_tuple_materialize_field(self, i);
|
342
371
|
rb_yield_values(2, RARRAY_AREF(field_names, i), value);
|
343
372
|
}
|
344
373
|
}
|
345
374
|
|
346
|
-
pg_tuple_detach(
|
375
|
+
pg_tuple_detach(self);
|
347
376
|
return self;
|
348
377
|
}
|
349
378
|
|
@@ -362,11 +391,11 @@ pg_tuple_each_value(VALUE self)
|
|
362
391
|
RETURN_SIZED_ENUMERATOR(self, 0, NULL, pg_tuple_num_fields_for_enum);
|
363
392
|
|
364
393
|
for(field_num = 0; field_num < this->num_fields; field_num++) {
|
365
|
-
VALUE value = pg_tuple_materialize_field(
|
394
|
+
VALUE value = pg_tuple_materialize_field(self, field_num);
|
366
395
|
rb_yield(value);
|
367
396
|
}
|
368
397
|
|
369
|
-
pg_tuple_detach(
|
398
|
+
pg_tuple_detach(self);
|
370
399
|
return self;
|
371
400
|
}
|
372
401
|
|
@@ -383,7 +412,7 @@ pg_tuple_values(VALUE self)
|
|
383
412
|
{
|
384
413
|
t_pg_tuple *this = pg_tuple_get_this(self);
|
385
414
|
|
386
|
-
pg_tuple_materialize(
|
415
|
+
pg_tuple_materialize(self);
|
387
416
|
return rb_ary_new4(this->num_fields, &this->values[0]);
|
388
417
|
}
|
389
418
|
|
@@ -436,7 +465,7 @@ pg_tuple_dump(VALUE self)
|
|
436
465
|
VALUE a;
|
437
466
|
t_pg_tuple *this = pg_tuple_get_this(self);
|
438
467
|
|
439
|
-
pg_tuple_materialize(
|
468
|
+
pg_tuple_materialize(self);
|
440
469
|
|
441
470
|
field_names = pg_tuple_get_field_names(this);
|
442
471
|
if( field_names == Qfalse )
|
@@ -445,10 +474,7 @@ pg_tuple_dump(VALUE self)
|
|
445
474
|
values = rb_ary_new4(this->num_fields, &this->values[0]);
|
446
475
|
a = rb_ary_new3(2, field_names, values);
|
447
476
|
|
448
|
-
|
449
|
-
rb_copy_generic_ivar(a, self);
|
450
|
-
FL_SET(a, FL_EXIVAR);
|
451
|
-
}
|
477
|
+
rb_copy_generic_ivar(a, self);
|
452
478
|
|
453
479
|
return a;
|
454
480
|
}
|
@@ -479,9 +505,9 @@ pg_tuple_load(VALUE self, VALUE a)
|
|
479
505
|
rb_obj_freeze(field_names);
|
480
506
|
values = RARRAY_AREF(a, 1);
|
481
507
|
Check_Type(values, T_ARRAY);
|
482
|
-
num_fields =
|
508
|
+
num_fields = RARRAY_LENINT(values);
|
483
509
|
|
484
|
-
if (
|
510
|
+
if (RARRAY_LENINT(field_names) != num_fields)
|
485
511
|
rb_raise(rb_eTypeError, "different number of fields and values");
|
486
512
|
|
487
513
|
field_map = rb_hash_new();
|
@@ -497,35 +523,32 @@ pg_tuple_load(VALUE self, VALUE a)
|
|
497
523
|
sizeof(*this->values) * num_fields +
|
498
524
|
sizeof(*this->values) * (dup_names ? 1 : 0));
|
499
525
|
|
500
|
-
this->result
|
501
|
-
this->typemap
|
526
|
+
RB_OBJ_WRITE(self, &this->result, Qnil);
|
527
|
+
RB_OBJ_WRITE(self, &this->typemap, Qnil);
|
502
528
|
this->row_num = -1;
|
503
529
|
this->num_fields = num_fields;
|
504
|
-
this->field_map
|
530
|
+
RB_OBJ_WRITE(self, &this->field_map, field_map);
|
505
531
|
|
506
532
|
for( i = 0; i < num_fields; i++ ){
|
507
533
|
VALUE v = RARRAY_AREF(values, i);
|
508
534
|
if( v == Qundef )
|
509
535
|
rb_raise(rb_eTypeError, "field %d is not materialized", i);
|
510
|
-
this->values[i]
|
536
|
+
RB_OBJ_WRITE(self, &this->values[i], v);
|
511
537
|
}
|
512
538
|
|
513
539
|
if( dup_names ){
|
514
|
-
this->values[num_fields]
|
540
|
+
RB_OBJ_WRITE(self, &this->values[num_fields], field_names);
|
515
541
|
}
|
516
542
|
|
517
543
|
RTYPEDDATA_DATA(self) = this;
|
518
544
|
|
519
|
-
|
520
|
-
rb_copy_generic_ivar(self, a);
|
521
|
-
FL_SET(self, FL_EXIVAR);
|
522
|
-
}
|
545
|
+
rb_copy_generic_ivar(self, a);
|
523
546
|
|
524
547
|
return self;
|
525
548
|
}
|
526
549
|
|
527
550
|
void
|
528
|
-
init_pg_tuple()
|
551
|
+
init_pg_tuple(void)
|
529
552
|
{
|
530
553
|
rb_cPG_Tuple = rb_define_class_under( rb_mPG, "Tuple", rb_cObject );
|
531
554
|
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_typemap_compact,
|
37
|
+
},
|
38
|
+
0,
|
39
|
+
0,
|
40
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
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 =
|
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,14 +128,14 @@ 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 =
|
131
|
+
t_typemap *this = RTYPEDDATA_DATA( self );
|
132
|
+
t_typemap *tm;
|
133
|
+
UNUSED(tm);
|
98
134
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
Check_Type(typemap, T_DATA);
|
104
|
-
this->default_typemap = typemap;
|
135
|
+
rb_check_frozen(self);
|
136
|
+
/* Check type of method param */
|
137
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
138
|
+
RB_OBJ_WRITE(self, &this->default_typemap, typemap);
|
105
139
|
|
106
140
|
return typemap;
|
107
141
|
}
|
@@ -119,7 +153,7 @@ pg_typemap_default_type_map_set(VALUE self, VALUE typemap)
|
|
119
153
|
static VALUE
|
120
154
|
pg_typemap_default_type_map_get(VALUE self)
|
121
155
|
{
|
122
|
-
t_typemap *this =
|
156
|
+
t_typemap *this = RTYPEDDATA_DATA( self );
|
123
157
|
|
124
158
|
return this->default_typemap;
|
125
159
|
}
|
@@ -143,7 +177,7 @@ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
|
|
143
177
|
}
|
144
178
|
|
145
179
|
void
|
146
|
-
init_pg_type_map()
|
180
|
+
init_pg_type_map(void)
|
147
181
|
{
|
148
182
|
s_id_fit_to_query = rb_intern("fit_to_query");
|
149
183
|
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_typemap_compact,
|
18
|
+
},
|
19
|
+
&pg_typemap_type,
|
20
|
+
0,
|
21
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
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 =
|
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
|
@@ -111,6 +125,6 @@ init_pg_type_map_all_strings()
|
|
111
125
|
rb_cTypeMapAllStrings = rb_define_class_under( rb_mPG, "TypeMapAllStrings", rb_cTypeMap );
|
112
126
|
rb_define_alloc_func( rb_cTypeMapAllStrings, pg_tmas_s_allocate );
|
113
127
|
|
114
|
-
pg_typemap_all_strings = rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 );
|
128
|
+
pg_typemap_all_strings = rb_obj_freeze( rb_funcall( rb_cTypeMapAllStrings, rb_intern("new"), 0 ));
|
115
129
|
rb_gc_register_address( &pg_typemap_all_strings );
|
116
130
|
}
|
data/ext/pg_type_map_by_class.c
CHANGED
@@ -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 =
|
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
|
-
|
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
|
-
|
82
|
-
|
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 =
|
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,46 +111,76 @@ 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 *)
|
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 =
|
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(
|
122
|
+
pg_tmbk_mark( void *_this )
|
126
123
|
{
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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_tmbk_compact,
|
157
|
+
},
|
158
|
+
&pg_typemap_type,
|
159
|
+
0,
|
160
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
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 =
|
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;
|
146
173
|
this->typemap.funcs.typecast_result_value = pg_typemap_result_value;
|
147
174
|
this->typemap.funcs.typecast_query_param = pg_tmbk_typecast_query_param;
|
148
175
|
this->typemap.funcs.typecast_copy_get = pg_typemap_typecast_copy_get;
|
149
|
-
this->typemap.default_typemap
|
176
|
+
RB_OBJ_WRITE(self, &this->typemap.default_typemap, pg_typemap_all_strings);
|
150
177
|
|
151
178
|
/* We need to store self in the this-struct, because pg_tmbk_typecast_query_param(),
|
152
179
|
* is called with the this-pointer only. */
|
153
180
|
this->self = self;
|
154
|
-
this->klass_to_coder
|
181
|
+
RB_OBJ_WRITE(self, &this->klass_to_coder, rb_hash_new());
|
155
182
|
|
156
|
-
/* The cache is properly initialized by
|
183
|
+
/* The cache is properly initialized by TypedData_Make_Struct(). */
|
157
184
|
|
158
185
|
return self;
|
159
186
|
}
|
@@ -176,7 +203,9 @@ 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 =
|
206
|
+
t_tmbk *this = RTYPEDDATA_DATA( self );
|
207
|
+
|
208
|
+
rb_check_frozen(self);
|
180
209
|
|
181
210
|
if(NIL_P(coder)){
|
182
211
|
rb_hash_delete( this->klass_to_coder, klass );
|
@@ -200,7 +229,7 @@ pg_tmbk_aset( VALUE self, VALUE klass, VALUE coder )
|
|
200
229
|
static VALUE
|
201
230
|
pg_tmbk_aref( VALUE self, VALUE klass )
|
202
231
|
{
|
203
|
-
t_tmbk *this =
|
232
|
+
t_tmbk *this = RTYPEDDATA_DATA( self );
|
204
233
|
|
205
234
|
return rb_hash_lookup(this->klass_to_coder, klass);
|
206
235
|
}
|
@@ -214,16 +243,14 @@ pg_tmbk_aref( VALUE self, VALUE klass )
|
|
214
243
|
static VALUE
|
215
244
|
pg_tmbk_coders( VALUE self )
|
216
245
|
{
|
217
|
-
t_tmbk *this =
|
246
|
+
t_tmbk *this = RTYPEDDATA_DATA( self );
|
218
247
|
|
219
248
|
return rb_obj_freeze(rb_hash_dup(this->klass_to_coder));
|
220
249
|
}
|
221
250
|
|
222
251
|
void
|
223
|
-
init_pg_type_map_by_class()
|
252
|
+
init_pg_type_map_by_class(void)
|
224
253
|
{
|
225
|
-
s_id_ancestors = rb_intern("ancestors");
|
226
|
-
|
227
254
|
/*
|
228
255
|
* Document-class: PG::TypeMapByClass < PG::TypeMap
|
229
256
|
*
|