pg 1.2.3 → 1.5.3
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/.appveyor.yml +42 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +117 -0
- data/.github/workflows/source-gem.yml +137 -0
- data/.gitignore +22 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.md +876 -0
- data/Manifest.txt +0 -1
- data/README.ja.md +276 -0
- data/README.md +286 -0
- data/Rakefile +33 -135
- data/Rakefile.cross +12 -13
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +12 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +4 -1
- data/ext/extconf.rb +100 -25
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +72 -57
- data/ext/pg.h +28 -4
- data/ext/pg_binary_decoder.c +80 -1
- data/ext/pg_binary_encoder.c +225 -1
- data/ext/pg_coder.c +96 -33
- data/ext/pg_connection.c +996 -697
- data/ext/pg_copy_coder.c +351 -33
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +50 -19
- data/ext/pg_result.c +177 -64
- data/ext/pg_text_decoder.c +29 -11
- data/ext/pg_text_encoder.c +29 -16
- data/ext/pg_tuple.c +83 -60
- 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 +73 -31
- data/ext/pg_type_map_by_mri_type.c +48 -19
- data/ext/pg_type_map_by_oid.c +59 -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 +198 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +299 -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/coder.rb +15 -13
- data/lib/pg/connection.rb +743 -83
- data/lib/pg/exceptions.rb +14 -1
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -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 +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -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 +94 -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/pg.gemspec +34 -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/translation/.po4a-version +7 -0
- data/translation/po/all.pot +910 -0
- data/translation/po/ja.po +1047 -0
- data/translation/po4a.cfg +12 -0
- data.tar.gz.sig +0 -0
- metadata +142 -210
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/History.rdoc +0 -578
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -213
- 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_binary_encoder.c
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
#endif
|
|
12
12
|
|
|
13
13
|
VALUE rb_mPG_BinaryEncoder;
|
|
14
|
+
static ID s_id_year;
|
|
15
|
+
static ID s_id_month;
|
|
16
|
+
static ID s_id_day;
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
/*
|
|
@@ -93,6 +96,215 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
|
|
|
93
96
|
return 8;
|
|
94
97
|
}
|
|
95
98
|
|
|
99
|
+
/*
|
|
100
|
+
* Document-class: PG::BinaryEncoder::Float4 < PG::SimpleEncoder
|
|
101
|
+
*
|
|
102
|
+
* This is the binary encoder class for the PostgreSQL +float4+ type.
|
|
103
|
+
*
|
|
104
|
+
*/
|
|
105
|
+
static int
|
|
106
|
+
pg_bin_enc_float4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
107
|
+
{
|
|
108
|
+
union {
|
|
109
|
+
float f;
|
|
110
|
+
int32_t i;
|
|
111
|
+
} swap4;
|
|
112
|
+
|
|
113
|
+
if(out){
|
|
114
|
+
swap4.f = NUM2DBL(*intermediate);
|
|
115
|
+
write_nbo32(swap4.i, out);
|
|
116
|
+
}else{
|
|
117
|
+
*intermediate = value;
|
|
118
|
+
}
|
|
119
|
+
return 4;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/*
|
|
123
|
+
* Document-class: PG::BinaryEncoder::Float8 < PG::SimpleEncoder
|
|
124
|
+
*
|
|
125
|
+
* This is the binary encoder class for the PostgreSQL +float8+ type.
|
|
126
|
+
*
|
|
127
|
+
*/
|
|
128
|
+
static int
|
|
129
|
+
pg_bin_enc_float8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
130
|
+
{
|
|
131
|
+
union {
|
|
132
|
+
double f;
|
|
133
|
+
int64_t i;
|
|
134
|
+
} swap8;
|
|
135
|
+
|
|
136
|
+
if(out){
|
|
137
|
+
swap8.f = NUM2DBL(*intermediate);
|
|
138
|
+
write_nbo64(swap8.i, out);
|
|
139
|
+
}else{
|
|
140
|
+
*intermediate = value;
|
|
141
|
+
}
|
|
142
|
+
return 8;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
|
|
146
|
+
#define PG_INT32_MAX (0x7FFFFFFF)
|
|
147
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
|
148
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
|
149
|
+
|
|
150
|
+
/*
|
|
151
|
+
* Document-class: PG::BinaryEncoder::Timestamp < PG::SimpleEncoder
|
|
152
|
+
*
|
|
153
|
+
* This is a encoder class for conversion of Ruby Time objects to PostgreSQL binary timestamps.
|
|
154
|
+
*
|
|
155
|
+
* The following flags can be used to specify timezone interpretation:
|
|
156
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Send timestamp as UTC time (default)
|
|
157
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Send timestamp as local time (slower)
|
|
158
|
+
*
|
|
159
|
+
* Example:
|
|
160
|
+
* enco = PG::BinaryEncoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC)
|
|
161
|
+
* enco.encode(Time.utc(2000, 1, 1)) # => "\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
162
|
+
*
|
|
163
|
+
* String values are expected to contain a binary data with a length of 8 byte.
|
|
164
|
+
*
|
|
165
|
+
*/
|
|
166
|
+
static int
|
|
167
|
+
pg_bin_enc_timestamp(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
168
|
+
{
|
|
169
|
+
if(out){
|
|
170
|
+
int64_t timestamp;
|
|
171
|
+
struct timespec ts;
|
|
172
|
+
|
|
173
|
+
/* second call -> write data to *out */
|
|
174
|
+
switch(TYPE(*intermediate)){
|
|
175
|
+
case T_STRING:
|
|
176
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
177
|
+
case T_TRUE:
|
|
178
|
+
write_nbo64(PG_INT64_MAX, out);
|
|
179
|
+
return 8;
|
|
180
|
+
case T_FALSE:
|
|
181
|
+
write_nbo64(PG_INT64_MIN, out);
|
|
182
|
+
return 8;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
ts = rb_time_timespec(*intermediate);
|
|
186
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
|
187
|
+
* Adjust the 30 years difference. */
|
|
188
|
+
timestamp = (ts.tv_sec - 10957L * 24L * 3600L) * 1000000 + (ts.tv_nsec / 1000);
|
|
189
|
+
|
|
190
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
|
191
|
+
/* send as local time */
|
|
192
|
+
timestamp += NUM2LL(rb_funcall(*intermediate, rb_intern("utc_offset"), 0)) * 1000000;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
write_nbo64(timestamp, out);
|
|
196
|
+
}else{
|
|
197
|
+
/* first call -> determine the required length */
|
|
198
|
+
if(TYPE(value) == T_STRING){
|
|
199
|
+
char *pstr = RSTRING_PTR(value);
|
|
200
|
+
if(RSTRING_LEN(value) >= 1){
|
|
201
|
+
switch(pstr[0]) {
|
|
202
|
+
case 'I':
|
|
203
|
+
case 'i':
|
|
204
|
+
*intermediate = Qtrue;
|
|
205
|
+
return 8;
|
|
206
|
+
case '-':
|
|
207
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
|
208
|
+
*intermediate = Qfalse;
|
|
209
|
+
return 8;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
|
218
|
+
/* make a local time, so that utc_offset is set */
|
|
219
|
+
value = rb_funcall(value, rb_intern("getlocal"), 0);
|
|
220
|
+
}
|
|
221
|
+
*intermediate = value;
|
|
222
|
+
}
|
|
223
|
+
return 8;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
|
|
227
|
+
int
|
|
228
|
+
date2j(int year, int month, int day)
|
|
229
|
+
{
|
|
230
|
+
int julian;
|
|
231
|
+
int century;
|
|
232
|
+
|
|
233
|
+
if (month > 2)
|
|
234
|
+
{
|
|
235
|
+
month += 1;
|
|
236
|
+
year += 4800;
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
{
|
|
240
|
+
month += 13;
|
|
241
|
+
year += 4799;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
century = year / 100;
|
|
245
|
+
julian = year * 365 - 32167;
|
|
246
|
+
julian += year / 4 - century + century / 4;
|
|
247
|
+
julian += 7834 * month / 256 + day;
|
|
248
|
+
|
|
249
|
+
return julian;
|
|
250
|
+
} /* date2j() */
|
|
251
|
+
|
|
252
|
+
/*
|
|
253
|
+
* Document-class: PG::BinaryEncoder::Date < PG::SimpleEncoder
|
|
254
|
+
*
|
|
255
|
+
* This is a encoder class for conversion of Ruby Date objects to PostgreSQL binary date.
|
|
256
|
+
*
|
|
257
|
+
* String values are expected to contain a binary data with a length of 4 byte.
|
|
258
|
+
*
|
|
259
|
+
*/
|
|
260
|
+
static int
|
|
261
|
+
pg_bin_enc_date(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
262
|
+
{
|
|
263
|
+
if(out){
|
|
264
|
+
/* second call -> write data to *out */
|
|
265
|
+
switch(TYPE(*intermediate)){
|
|
266
|
+
case T_STRING:
|
|
267
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
268
|
+
case T_TRUE:
|
|
269
|
+
write_nbo32(PG_INT32_MAX, out);
|
|
270
|
+
return 4;
|
|
271
|
+
case T_FALSE:
|
|
272
|
+
write_nbo32(PG_INT32_MIN, out);
|
|
273
|
+
return 4;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
VALUE year = rb_funcall(value, s_id_year, 0);
|
|
277
|
+
VALUE month = rb_funcall(value, s_id_month, 0);
|
|
278
|
+
VALUE day = rb_funcall(value, s_id_day, 0);
|
|
279
|
+
int jday = date2j(NUM2INT(year), NUM2INT(month), NUM2INT(day)) - POSTGRES_EPOCH_JDATE;
|
|
280
|
+
write_nbo32(jday, out);
|
|
281
|
+
|
|
282
|
+
}else{
|
|
283
|
+
/* first call -> determine the required length */
|
|
284
|
+
if(TYPE(value) == T_STRING){
|
|
285
|
+
char *pstr = RSTRING_PTR(value);
|
|
286
|
+
if(RSTRING_LEN(value) >= 1){
|
|
287
|
+
switch(pstr[0]) {
|
|
288
|
+
case 'I':
|
|
289
|
+
case 'i':
|
|
290
|
+
*intermediate = Qtrue;
|
|
291
|
+
return 4;
|
|
292
|
+
case '-':
|
|
293
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
|
294
|
+
*intermediate = Qfalse;
|
|
295
|
+
return 4;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
*intermediate = value;
|
|
304
|
+
}
|
|
305
|
+
return 4;
|
|
306
|
+
}
|
|
307
|
+
|
|
96
308
|
/*
|
|
97
309
|
* Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
|
|
98
310
|
*
|
|
@@ -139,8 +351,12 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
|
|
|
139
351
|
}
|
|
140
352
|
|
|
141
353
|
void
|
|
142
|
-
init_pg_binary_encoder()
|
|
354
|
+
init_pg_binary_encoder(void)
|
|
143
355
|
{
|
|
356
|
+
s_id_year = rb_intern("year");
|
|
357
|
+
s_id_month = rb_intern("month");
|
|
358
|
+
s_id_day = rb_intern("day");
|
|
359
|
+
|
|
144
360
|
/* This module encapsulates all encoder classes with binary output format */
|
|
145
361
|
rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
|
|
146
362
|
|
|
@@ -153,10 +369,18 @@ init_pg_binary_encoder()
|
|
|
153
369
|
pg_define_coder( "Int4", pg_bin_enc_int4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
154
370
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int8", rb_cPG_SimpleEncoder ); */
|
|
155
371
|
pg_define_coder( "Int8", pg_bin_enc_int8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
372
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float4", rb_cPG_SimpleEncoder ); */
|
|
373
|
+
pg_define_coder( "Float4", pg_bin_enc_float4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
374
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float8", rb_cPG_SimpleEncoder ); */
|
|
375
|
+
pg_define_coder( "Float8", pg_bin_enc_float8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
156
376
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "String", rb_cPG_SimpleEncoder ); */
|
|
157
377
|
pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
158
378
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
|
|
159
379
|
pg_define_coder( "Bytea", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
380
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Timestamp", rb_cPG_SimpleEncoder ); */
|
|
381
|
+
pg_define_coder( "Timestamp", pg_bin_enc_timestamp, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
382
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Date", rb_cPG_SimpleEncoder ); */
|
|
383
|
+
pg_define_coder( "Date", pg_bin_enc_date, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
160
384
|
|
|
161
385
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "FromBase64", rb_cPG_CompositeEncoder ); */
|
|
162
386
|
pg_define_coder( "FromBase64", pg_bin_enc_from_base64, rb_cPG_CompositeEncoder, rb_mPG_BinaryEncoder );
|
data/ext/pg_coder.c
CHANGED
|
@@ -26,16 +26,16 @@ pg_coder_allocate( VALUE klass )
|
|
|
26
26
|
void
|
|
27
27
|
pg_coder_init_encoder( VALUE self )
|
|
28
28
|
{
|
|
29
|
-
t_pg_coder *this =
|
|
29
|
+
t_pg_coder *this = RTYPEDDATA_DATA( self );
|
|
30
30
|
VALUE klass = rb_class_of(self);
|
|
31
31
|
if( rb_const_defined( klass, s_id_CFUNC ) ){
|
|
32
32
|
VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
|
|
33
|
-
this->enc_func =
|
|
33
|
+
this->enc_func = RTYPEDDATA_DATA(cfunc);
|
|
34
34
|
} else {
|
|
35
35
|
this->enc_func = NULL;
|
|
36
36
|
}
|
|
37
37
|
this->dec_func = NULL;
|
|
38
|
-
this->coder_obj
|
|
38
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
|
39
39
|
this->oid = 0;
|
|
40
40
|
this->format = 0;
|
|
41
41
|
this->flags = 0;
|
|
@@ -45,48 +45,92 @@ pg_coder_init_encoder( VALUE self )
|
|
|
45
45
|
void
|
|
46
46
|
pg_coder_init_decoder( VALUE self )
|
|
47
47
|
{
|
|
48
|
-
t_pg_coder *this =
|
|
48
|
+
t_pg_coder *this = RTYPEDDATA_DATA( self );
|
|
49
49
|
VALUE klass = rb_class_of(self);
|
|
50
50
|
this->enc_func = NULL;
|
|
51
51
|
if( rb_const_defined( klass, s_id_CFUNC ) ){
|
|
52
52
|
VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
|
|
53
|
-
this->dec_func =
|
|
53
|
+
this->dec_func = RTYPEDDATA_DATA(cfunc);
|
|
54
54
|
} else {
|
|
55
55
|
this->dec_func = NULL;
|
|
56
56
|
}
|
|
57
|
-
this->coder_obj
|
|
57
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
|
58
58
|
this->oid = 0;
|
|
59
59
|
this->format = 0;
|
|
60
60
|
this->flags = 0;
|
|
61
61
|
rb_iv_set( self, "@name", Qnil );
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
static size_t
|
|
65
|
+
pg_coder_memsize(const void *_this)
|
|
66
|
+
{
|
|
67
|
+
const t_pg_coder *this = (const t_pg_coder *)_this;
|
|
68
|
+
return sizeof(*this);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static size_t
|
|
72
|
+
pg_composite_coder_memsize(const void *_this)
|
|
73
|
+
{
|
|
74
|
+
const t_pg_composite_coder *this = (const t_pg_composite_coder *)_this;
|
|
75
|
+
return sizeof(*this);
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
void
|
|
65
|
-
|
|
79
|
+
pg_coder_compact(void *_this)
|
|
66
80
|
{
|
|
67
|
-
|
|
81
|
+
t_pg_coder *this = (t_pg_coder *)_this;
|
|
82
|
+
pg_gc_location(this->coder_obj);
|
|
68
83
|
}
|
|
69
84
|
|
|
70
85
|
static void
|
|
71
|
-
|
|
86
|
+
pg_composite_coder_compact(void *_this)
|
|
72
87
|
{
|
|
73
|
-
|
|
88
|
+
t_pg_composite_coder *this = (t_pg_composite_coder *)_this;
|
|
89
|
+
pg_coder_compact(&this->comp);
|
|
74
90
|
}
|
|
75
91
|
|
|
92
|
+
const rb_data_type_t pg_coder_type = {
|
|
93
|
+
"PG::Coder",
|
|
94
|
+
{
|
|
95
|
+
(RUBY_DATA_FUNC) NULL,
|
|
96
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
97
|
+
pg_coder_memsize,
|
|
98
|
+
pg_compact_callback(pg_coder_compact),
|
|
99
|
+
},
|
|
100
|
+
0,
|
|
101
|
+
0,
|
|
102
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
|
103
|
+
// macro to update VALUE references, as to trigger write barriers.
|
|
104
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
|
105
|
+
};
|
|
106
|
+
|
|
76
107
|
static VALUE
|
|
77
108
|
pg_simple_encoder_allocate( VALUE klass )
|
|
78
109
|
{
|
|
79
110
|
t_pg_coder *this;
|
|
80
|
-
VALUE self =
|
|
111
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
|
|
81
112
|
pg_coder_init_encoder( self );
|
|
82
113
|
return self;
|
|
83
114
|
}
|
|
84
115
|
|
|
116
|
+
static const rb_data_type_t pg_composite_coder_type = {
|
|
117
|
+
"PG::CompositeCoder",
|
|
118
|
+
{
|
|
119
|
+
(RUBY_DATA_FUNC) NULL,
|
|
120
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
121
|
+
pg_composite_coder_memsize,
|
|
122
|
+
pg_compact_callback(pg_composite_coder_compact),
|
|
123
|
+
},
|
|
124
|
+
&pg_coder_type,
|
|
125
|
+
0,
|
|
126
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
|
127
|
+
};
|
|
128
|
+
|
|
85
129
|
static VALUE
|
|
86
130
|
pg_composite_encoder_allocate( VALUE klass )
|
|
87
131
|
{
|
|
88
132
|
t_pg_composite_coder *this;
|
|
89
|
-
VALUE self =
|
|
133
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
|
|
90
134
|
pg_coder_init_encoder( self );
|
|
91
135
|
this->elem = NULL;
|
|
92
136
|
this->needs_quotation = 1;
|
|
@@ -99,7 +143,7 @@ static VALUE
|
|
|
99
143
|
pg_simple_decoder_allocate( VALUE klass )
|
|
100
144
|
{
|
|
101
145
|
t_pg_coder *this;
|
|
102
|
-
VALUE self =
|
|
146
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
|
|
103
147
|
pg_coder_init_decoder( self );
|
|
104
148
|
return self;
|
|
105
149
|
}
|
|
@@ -108,7 +152,7 @@ static VALUE
|
|
|
108
152
|
pg_composite_decoder_allocate( VALUE klass )
|
|
109
153
|
{
|
|
110
154
|
t_pg_composite_coder *this;
|
|
111
|
-
VALUE self =
|
|
155
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
|
|
112
156
|
pg_coder_init_decoder( self );
|
|
113
157
|
this->elem = NULL;
|
|
114
158
|
this->needs_quotation = 1;
|
|
@@ -135,7 +179,7 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
|
|
|
135
179
|
VALUE value;
|
|
136
180
|
int len, len2;
|
|
137
181
|
int enc_idx;
|
|
138
|
-
t_pg_coder *this =
|
|
182
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
139
183
|
|
|
140
184
|
if(argc < 1 || argc > 2){
|
|
141
185
|
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
|
|
@@ -192,7 +236,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
|
192
236
|
int tuple = -1;
|
|
193
237
|
int field = -1;
|
|
194
238
|
VALUE res;
|
|
195
|
-
t_pg_coder *this =
|
|
239
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
196
240
|
|
|
197
241
|
if(argc < 1 || argc > 3){
|
|
198
242
|
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..3)", argc);
|
|
@@ -213,7 +257,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
|
213
257
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
|
214
258
|
}
|
|
215
259
|
|
|
216
|
-
res = this->dec_func(this, val,
|
|
260
|
+
res = this->dec_func(this, val, RSTRING_LENINT(argv[0]), tuple, field, ENCODING_GET(argv[0]));
|
|
217
261
|
|
|
218
262
|
return res;
|
|
219
263
|
}
|
|
@@ -230,7 +274,8 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
|
230
274
|
static VALUE
|
|
231
275
|
pg_coder_oid_set(VALUE self, VALUE oid)
|
|
232
276
|
{
|
|
233
|
-
t_pg_coder *this =
|
|
277
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
278
|
+
rb_check_frozen(self);
|
|
234
279
|
this->oid = NUM2UINT(oid);
|
|
235
280
|
return oid;
|
|
236
281
|
}
|
|
@@ -245,7 +290,7 @@ pg_coder_oid_set(VALUE self, VALUE oid)
|
|
|
245
290
|
static VALUE
|
|
246
291
|
pg_coder_oid_get(VALUE self)
|
|
247
292
|
{
|
|
248
|
-
t_pg_coder *this =
|
|
293
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
249
294
|
return UINT2NUM(this->oid);
|
|
250
295
|
}
|
|
251
296
|
|
|
@@ -261,7 +306,8 @@ pg_coder_oid_get(VALUE self)
|
|
|
261
306
|
static VALUE
|
|
262
307
|
pg_coder_format_set(VALUE self, VALUE format)
|
|
263
308
|
{
|
|
264
|
-
t_pg_coder *this =
|
|
309
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
310
|
+
rb_check_frozen(self);
|
|
265
311
|
this->format = NUM2INT(format);
|
|
266
312
|
return format;
|
|
267
313
|
}
|
|
@@ -276,7 +322,7 @@ pg_coder_format_set(VALUE self, VALUE format)
|
|
|
276
322
|
static VALUE
|
|
277
323
|
pg_coder_format_get(VALUE self)
|
|
278
324
|
{
|
|
279
|
-
t_pg_coder *this =
|
|
325
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
280
326
|
return INT2NUM(this->format);
|
|
281
327
|
}
|
|
282
328
|
|
|
@@ -292,7 +338,8 @@ pg_coder_format_get(VALUE self)
|
|
|
292
338
|
static VALUE
|
|
293
339
|
pg_coder_flags_set(VALUE self, VALUE flags)
|
|
294
340
|
{
|
|
295
|
-
t_pg_coder *this =
|
|
341
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
342
|
+
rb_check_frozen(self);
|
|
296
343
|
this->flags = NUM2INT(flags);
|
|
297
344
|
return flags;
|
|
298
345
|
}
|
|
@@ -306,7 +353,7 @@ pg_coder_flags_set(VALUE self, VALUE flags)
|
|
|
306
353
|
static VALUE
|
|
307
354
|
pg_coder_flags_get(VALUE self)
|
|
308
355
|
{
|
|
309
|
-
t_pg_coder *this =
|
|
356
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
310
357
|
return INT2NUM(this->flags);
|
|
311
358
|
}
|
|
312
359
|
|
|
@@ -323,7 +370,8 @@ pg_coder_flags_get(VALUE self)
|
|
|
323
370
|
static VALUE
|
|
324
371
|
pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
|
325
372
|
{
|
|
326
|
-
t_pg_composite_coder *this =
|
|
373
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
374
|
+
rb_check_frozen(self);
|
|
327
375
|
this->needs_quotation = RTEST(needs_quotation);
|
|
328
376
|
return needs_quotation;
|
|
329
377
|
}
|
|
@@ -338,7 +386,7 @@ pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
|
|
338
386
|
static VALUE
|
|
339
387
|
pg_coder_needs_quotation_get(VALUE self)
|
|
340
388
|
{
|
|
341
|
-
t_pg_composite_coder *this =
|
|
389
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
342
390
|
return this->needs_quotation ? Qtrue : Qfalse;
|
|
343
391
|
}
|
|
344
392
|
|
|
@@ -353,7 +401,8 @@ pg_coder_needs_quotation_get(VALUE self)
|
|
|
353
401
|
static VALUE
|
|
354
402
|
pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
|
355
403
|
{
|
|
356
|
-
t_pg_composite_coder *this =
|
|
404
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
405
|
+
rb_check_frozen(self);
|
|
357
406
|
StringValue(delimiter);
|
|
358
407
|
if(RSTRING_LEN(delimiter) != 1)
|
|
359
408
|
rb_raise( rb_eArgError, "delimiter size must be one byte");
|
|
@@ -370,7 +419,7 @@ pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
|
|
370
419
|
static VALUE
|
|
371
420
|
pg_coder_delimiter_get(VALUE self)
|
|
372
421
|
{
|
|
373
|
-
t_pg_composite_coder *this =
|
|
422
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
374
423
|
return rb_str_new(&this->delimiter, 1);
|
|
375
424
|
}
|
|
376
425
|
|
|
@@ -386,12 +435,13 @@ pg_coder_delimiter_get(VALUE self)
|
|
|
386
435
|
static VALUE
|
|
387
436
|
pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
388
437
|
{
|
|
389
|
-
t_pg_composite_coder *this =
|
|
438
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
|
|
390
439
|
|
|
440
|
+
rb_check_frozen(self);
|
|
391
441
|
if ( NIL_P(elem_type) ){
|
|
392
442
|
this->elem = NULL;
|
|
393
443
|
} else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
|
|
394
|
-
this->elem =
|
|
444
|
+
this->elem = RTYPEDDATA_DATA( elem_type );
|
|
395
445
|
} else {
|
|
396
446
|
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::Coder)",
|
|
397
447
|
rb_obj_classname( elem_type ) );
|
|
@@ -401,10 +451,22 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
|
401
451
|
return elem_type;
|
|
402
452
|
}
|
|
403
453
|
|
|
404
|
-
|
|
454
|
+
static const rb_data_type_t pg_coder_cfunc_type = {
|
|
455
|
+
"PG::Coder::CFUNC",
|
|
456
|
+
{
|
|
457
|
+
(RUBY_DATA_FUNC)NULL,
|
|
458
|
+
(RUBY_DATA_FUNC)NULL,
|
|
459
|
+
(size_t (*)(const void *))NULL,
|
|
460
|
+
},
|
|
461
|
+
0,
|
|
462
|
+
0,
|
|
463
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
VALUE
|
|
405
467
|
pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
406
468
|
{
|
|
407
|
-
VALUE cfunc_obj =
|
|
469
|
+
VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
|
|
408
470
|
VALUE coder_klass = rb_define_class_under( nsp, name, base_klass );
|
|
409
471
|
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
|
|
410
472
|
rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
|
|
@@ -414,9 +476,10 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
|
414
476
|
if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
|
|
415
477
|
rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
|
|
416
478
|
|
|
417
|
-
rb_define_const( coder_klass, "CFUNC", cfunc_obj );
|
|
479
|
+
rb_define_const( coder_klass, "CFUNC", rb_obj_freeze(cfunc_obj) );
|
|
418
480
|
|
|
419
481
|
RB_GC_GUARD(cfunc_obj);
|
|
482
|
+
return coder_klass;
|
|
420
483
|
}
|
|
421
484
|
|
|
422
485
|
|
|
@@ -483,7 +546,7 @@ pg_coder_dec_func(t_pg_coder *this, int binary)
|
|
|
483
546
|
|
|
484
547
|
|
|
485
548
|
void
|
|
486
|
-
init_pg_coder()
|
|
549
|
+
init_pg_coder(void)
|
|
487
550
|
{
|
|
488
551
|
s_id_encode = rb_intern("encode");
|
|
489
552
|
s_id_decode = rb_intern("decode");
|