pg 0.18.2 → 1.4.5

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.
Files changed (119) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +86 -0
  6. data/.github/workflows/source-gem.yml +131 -0
  7. data/.gitignore +13 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/BSDL +2 -2
  15. data/Gemfile +14 -0
  16. data/History.rdoc +480 -4
  17. data/Manifest.txt +8 -21
  18. data/README-Windows.rdoc +17 -28
  19. data/README.ja.rdoc +1 -2
  20. data/README.rdoc +92 -20
  21. data/Rakefile +33 -133
  22. data/Rakefile.cross +89 -67
  23. data/certs/ged.pem +24 -0
  24. data/certs/larskanis-2022.pem +26 -0
  25. data/ext/errorcodes.def +113 -0
  26. data/ext/errorcodes.rb +1 -1
  27. data/ext/errorcodes.txt +36 -2
  28. data/ext/extconf.rb +120 -54
  29. data/ext/gvl_wrappers.c +8 -0
  30. data/ext/gvl_wrappers.h +44 -33
  31. data/ext/pg.c +216 -172
  32. data/ext/pg.h +93 -98
  33. data/ext/pg_binary_decoder.c +85 -16
  34. data/ext/pg_binary_encoder.c +25 -22
  35. data/ext/pg_coder.c +176 -40
  36. data/ext/pg_connection.c +1735 -1138
  37. data/ext/pg_copy_coder.c +95 -28
  38. data/ext/pg_errors.c +1 -1
  39. data/ext/pg_record_coder.c +521 -0
  40. data/ext/pg_result.c +642 -221
  41. data/ext/pg_text_decoder.c +609 -41
  42. data/ext/pg_text_encoder.c +254 -100
  43. data/ext/pg_tuple.c +569 -0
  44. data/ext/pg_type_map.c +62 -22
  45. data/ext/pg_type_map_all_strings.c +20 -6
  46. data/ext/pg_type_map_by_class.c +55 -25
  47. data/ext/pg_type_map_by_column.c +81 -42
  48. data/ext/pg_type_map_by_mri_type.c +49 -20
  49. data/ext/pg_type_map_by_oid.c +56 -26
  50. data/ext/pg_type_map_in_ruby.c +52 -21
  51. data/ext/{util.c → pg_util.c} +12 -12
  52. data/ext/{util.h → pg_util.h} +2 -2
  53. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  54. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  55. data/lib/pg/basic_type_map_for_results.rb +81 -0
  56. data/lib/pg/basic_type_registry.rb +301 -0
  57. data/lib/pg/binary_decoder.rb +23 -0
  58. data/lib/pg/coder.rb +24 -3
  59. data/lib/pg/connection.rb +711 -64
  60. data/lib/pg/constants.rb +2 -1
  61. data/lib/pg/exceptions.rb +9 -2
  62. data/lib/pg/result.rb +24 -7
  63. data/lib/pg/text_decoder.rb +27 -23
  64. data/lib/pg/text_encoder.rb +40 -8
  65. data/lib/pg/tuple.rb +30 -0
  66. data/lib/pg/type_map_by_column.rb +3 -2
  67. data/lib/pg/version.rb +4 -0
  68. data/lib/pg.rb +61 -36
  69. data/misc/openssl-pg-segfault.rb +31 -0
  70. data/misc/postgres/History.txt +9 -0
  71. data/misc/postgres/Manifest.txt +5 -0
  72. data/misc/postgres/README.txt +21 -0
  73. data/misc/postgres/Rakefile +21 -0
  74. data/misc/postgres/lib/postgres.rb +16 -0
  75. data/misc/ruby-pg/History.txt +9 -0
  76. data/misc/ruby-pg/Manifest.txt +5 -0
  77. data/misc/ruby-pg/README.txt +21 -0
  78. data/misc/ruby-pg/Rakefile +21 -0
  79. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  80. data/pg.gemspec +32 -0
  81. data/rakelib/task_extension.rb +46 -0
  82. data/sample/array_insert.rb +1 -1
  83. data/sample/async_api.rb +4 -8
  84. data/sample/async_copyto.rb +1 -1
  85. data/sample/async_mixed.rb +1 -1
  86. data/sample/check_conn.rb +1 -1
  87. data/sample/copydata.rb +71 -0
  88. data/sample/copyfrom.rb +1 -1
  89. data/sample/copyto.rb +1 -1
  90. data/sample/cursor.rb +1 -1
  91. data/sample/disk_usage_report.rb +6 -15
  92. data/sample/issue-119.rb +2 -2
  93. data/sample/losample.rb +1 -1
  94. data/sample/minimal-testcase.rb +2 -2
  95. data/sample/notify_wait.rb +1 -1
  96. data/sample/pg_statistics.rb +6 -15
  97. data/sample/replication_monitor.rb +9 -18
  98. data/sample/test_binary_values.rb +1 -1
  99. data/sample/wal_shipper.rb +2 -2
  100. data/sample/warehouse_partitions.rb +8 -17
  101. data.tar.gz.sig +0 -0
  102. metadata +74 -216
  103. metadata.gz.sig +0 -0
  104. data/ChangeLog +0 -5545
  105. data/lib/pg/basic_type_mapping.rb +0 -399
  106. data/spec/data/expected_trace.out +0 -26
  107. data/spec/data/random_binary_data +0 -0
  108. data/spec/helpers.rb +0 -355
  109. data/spec/pg/basic_type_mapping_spec.rb +0 -251
  110. data/spec/pg/connection_spec.rb +0 -1535
  111. data/spec/pg/result_spec.rb +0 -449
  112. data/spec/pg/type_map_by_class_spec.rb +0 -138
  113. data/spec/pg/type_map_by_column_spec.rb +0 -222
  114. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  115. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  116. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  117. data/spec/pg/type_map_spec.rb +0 -22
  118. data/spec/pg/type_spec.rb +0 -688
  119. data/spec/pg_spec.rb +0 -50
data/ext/pg_coder.c CHANGED
@@ -26,11 +26,11 @@ pg_coder_allocate( VALUE klass )
26
26
  void
27
27
  pg_coder_init_encoder( VALUE self )
28
28
  {
29
- t_pg_coder *this = DATA_PTR( self );
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 = DATA_PTR(cfunc);
33
+ this->enc_func = RTYPEDDATA_DATA(cfunc);
34
34
  } else {
35
35
  this->enc_func = NULL;
36
36
  }
@@ -38,41 +38,97 @@ pg_coder_init_encoder( VALUE self )
38
38
  this->coder_obj = self;
39
39
  this->oid = 0;
40
40
  this->format = 0;
41
+ this->flags = 0;
41
42
  rb_iv_set( self, "@name", Qnil );
42
43
  }
43
44
 
44
45
  void
45
46
  pg_coder_init_decoder( VALUE self )
46
47
  {
47
- t_pg_coder *this = DATA_PTR( self );
48
+ t_pg_coder *this = RTYPEDDATA_DATA( self );
48
49
  VALUE klass = rb_class_of(self);
49
50
  this->enc_func = NULL;
50
51
  if( rb_const_defined( klass, s_id_CFUNC ) ){
51
52
  VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
52
- this->dec_func = DATA_PTR(cfunc);
53
+ this->dec_func = RTYPEDDATA_DATA(cfunc);
53
54
  } else {
54
55
  this->dec_func = NULL;
55
56
  }
56
57
  this->coder_obj = self;
57
58
  this->oid = 0;
58
59
  this->format = 0;
60
+ this->flags = 0;
59
61
  rb_iv_set( self, "@name", Qnil );
60
62
  }
61
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
+
78
+ void
79
+ pg_coder_compact(void *_this)
80
+ {
81
+ t_pg_coder *this = (t_pg_coder *)_this;
82
+ pg_gc_location(this->coder_obj);
83
+ }
84
+
85
+ static void
86
+ pg_composite_coder_compact(void *_this)
87
+ {
88
+ t_pg_composite_coder *this = (t_pg_composite_coder *)_this;
89
+ pg_coder_compact(&this->comp);
90
+ }
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
+ RUBY_TYPED_FREE_IMMEDIATELY,
103
+ };
104
+
62
105
  static VALUE
63
106
  pg_simple_encoder_allocate( VALUE klass )
64
107
  {
65
108
  t_pg_coder *this;
66
- VALUE self = Data_Make_Struct( klass, t_pg_coder, NULL, -1, this );
109
+ VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
67
110
  pg_coder_init_encoder( self );
68
111
  return self;
69
112
  }
70
113
 
114
+ static const rb_data_type_t pg_composite_coder_type = {
115
+ "PG::CompositeCoder",
116
+ {
117
+ (RUBY_DATA_FUNC) NULL,
118
+ RUBY_TYPED_DEFAULT_FREE,
119
+ pg_composite_coder_memsize,
120
+ pg_compact_callback(pg_composite_coder_compact),
121
+ },
122
+ &pg_coder_type,
123
+ 0,
124
+ RUBY_TYPED_FREE_IMMEDIATELY,
125
+ };
126
+
71
127
  static VALUE
72
128
  pg_composite_encoder_allocate( VALUE klass )
73
129
  {
74
130
  t_pg_composite_coder *this;
75
- VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, NULL, -1, this );
131
+ VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
76
132
  pg_coder_init_encoder( self );
77
133
  this->elem = NULL;
78
134
  this->needs_quotation = 1;
@@ -85,7 +141,7 @@ static VALUE
85
141
  pg_simple_decoder_allocate( VALUE klass )
86
142
  {
87
143
  t_pg_coder *this;
88
- VALUE self = Data_Make_Struct( klass, t_pg_coder, NULL, -1, this );
144
+ VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
89
145
  pg_coder_init_decoder( self );
90
146
  return self;
91
147
  }
@@ -94,7 +150,7 @@ static VALUE
94
150
  pg_composite_decoder_allocate( VALUE klass )
95
151
  {
96
152
  t_pg_composite_coder *this;
97
- VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, NULL, -1, this );
153
+ VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
98
154
  pg_coder_init_decoder( self );
99
155
  this->elem = NULL;
100
156
  this->needs_quotation = 1;
@@ -105,7 +161,7 @@ pg_composite_decoder_allocate( VALUE klass )
105
161
 
106
162
  /*
107
163
  * call-seq:
108
- * coder.encode( value )
164
+ * coder.encode( value [, encoding] )
109
165
  *
110
166
  * Encodes the given Ruby object into string representation, without
111
167
  * sending data to/from the database server.
@@ -114,12 +170,23 @@ pg_composite_decoder_allocate( VALUE klass )
114
170
  *
115
171
  */
116
172
  static VALUE
117
- pg_coder_encode(VALUE self, VALUE value)
173
+ pg_coder_encode(int argc, VALUE *argv, VALUE self)
118
174
  {
119
175
  VALUE res;
120
176
  VALUE intermediate;
177
+ VALUE value;
121
178
  int len, len2;
122
- t_pg_coder *this = DATA_PTR(self);
179
+ int enc_idx;
180
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
181
+
182
+ if(argc < 1 || argc > 2){
183
+ rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
184
+ }else if(argc == 1){
185
+ enc_idx = rb_ascii8bit_encindex();
186
+ }else{
187
+ enc_idx = rb_to_encoding_index(argv[1]);
188
+ }
189
+ value = argv[0];
123
190
 
124
191
  if( NIL_P(value) )
125
192
  return Qnil;
@@ -128,22 +195,21 @@ pg_coder_encode(VALUE self, VALUE value)
128
195
  rb_raise(rb_eRuntimeError, "no encoder function defined");
129
196
  }
130
197
 
131
- len = this->enc_func( this, value, NULL, &intermediate );
198
+ len = this->enc_func( this, value, NULL, &intermediate, enc_idx );
132
199
 
133
200
  if( len == -1 ){
134
201
  /* The intermediate value is a String that can be used directly. */
135
- OBJ_INFECT(intermediate, value);
136
202
  return intermediate;
137
203
  }
138
204
 
139
205
  res = rb_str_new(NULL, len);
140
- len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate);
206
+ PG_ENCODING_SET_NOCHECK(res, enc_idx);
207
+ len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate, enc_idx );
141
208
  if( len < len2 ){
142
209
  rb_bug("%s: result length of first encoder run (%i) is less than second run (%i)",
143
210
  rb_obj_classname( self ), len, len2 );
144
211
  }
145
212
  rb_str_set_len( res, len2 );
146
- OBJ_INFECT(res, value);
147
213
 
148
214
  RB_GC_GUARD(intermediate);
149
215
 
@@ -165,10 +231,10 @@ static VALUE
165
231
  pg_coder_decode(int argc, VALUE *argv, VALUE self)
166
232
  {
167
233
  char *val;
168
- VALUE tuple = -1;
169
- VALUE field = -1;
234
+ int tuple = -1;
235
+ int field = -1;
170
236
  VALUE res;
171
- t_pg_coder *this = DATA_PTR(self);
237
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
172
238
 
173
239
  if(argc < 1 || argc > 3){
174
240
  rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..3)", argc);
@@ -180,13 +246,16 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
180
246
  if( NIL_P(argv[0]) )
181
247
  return Qnil;
182
248
 
183
- val = StringValuePtr(argv[0]);
249
+ if( this->format == 0 ){
250
+ val = StringValueCStr(argv[0]);
251
+ }else{
252
+ val = StringValuePtr(argv[0]);
253
+ }
184
254
  if( !this->dec_func ){
185
255
  rb_raise(rb_eRuntimeError, "no decoder function defined");
186
256
  }
187
257
 
188
- res = this->dec_func(this, val, RSTRING_LEN(argv[0]), tuple, field, ENCODING_GET(argv[0]));
189
- OBJ_INFECT(res, argv[0]);
258
+ res = this->dec_func(this, val, RSTRING_LENINT(argv[0]), tuple, field, ENCODING_GET(argv[0]));
190
259
 
191
260
  return res;
192
261
  }
@@ -203,7 +272,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
203
272
  static VALUE
204
273
  pg_coder_oid_set(VALUE self, VALUE oid)
205
274
  {
206
- t_pg_coder *this = DATA_PTR(self);
275
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
207
276
  this->oid = NUM2UINT(oid);
208
277
  return oid;
209
278
  }
@@ -218,7 +287,7 @@ pg_coder_oid_set(VALUE self, VALUE oid)
218
287
  static VALUE
219
288
  pg_coder_oid_get(VALUE self)
220
289
  {
221
- t_pg_coder *this = DATA_PTR(self);
290
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
222
291
  return UINT2NUM(this->oid);
223
292
  }
224
293
 
@@ -234,7 +303,7 @@ pg_coder_oid_get(VALUE self)
234
303
  static VALUE
235
304
  pg_coder_format_set(VALUE self, VALUE format)
236
305
  {
237
- t_pg_coder *this = DATA_PTR(self);
306
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
238
307
  this->format = NUM2INT(format);
239
308
  return format;
240
309
  }
@@ -249,10 +318,40 @@ pg_coder_format_set(VALUE self, VALUE format)
249
318
  static VALUE
250
319
  pg_coder_format_get(VALUE self)
251
320
  {
252
- t_pg_coder *this = DATA_PTR(self);
321
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
253
322
  return INT2NUM(this->format);
254
323
  }
255
324
 
325
+ /*
326
+ * call-seq:
327
+ * coder.flags = Integer
328
+ *
329
+ * Set coder specific bitwise OR-ed flags.
330
+ * See the particular en- or decoder description for available flags.
331
+ *
332
+ * The default is +0+.
333
+ */
334
+ static VALUE
335
+ pg_coder_flags_set(VALUE self, VALUE flags)
336
+ {
337
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
338
+ this->flags = NUM2INT(flags);
339
+ return flags;
340
+ }
341
+
342
+ /*
343
+ * call-seq:
344
+ * coder.flags -> Integer
345
+ *
346
+ * Get current bitwise OR-ed coder flags.
347
+ */
348
+ static VALUE
349
+ pg_coder_flags_get(VALUE self)
350
+ {
351
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
352
+ return INT2NUM(this->flags);
353
+ }
354
+
256
355
  /*
257
356
  * call-seq:
258
357
  * coder.needs_quotation = Boolean
@@ -266,7 +365,7 @@ pg_coder_format_get(VALUE self)
266
365
  static VALUE
267
366
  pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
268
367
  {
269
- t_pg_composite_coder *this = DATA_PTR(self);
368
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
270
369
  this->needs_quotation = RTEST(needs_quotation);
271
370
  return needs_quotation;
272
371
  }
@@ -281,7 +380,7 @@ pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
281
380
  static VALUE
282
381
  pg_coder_needs_quotation_get(VALUE self)
283
382
  {
284
- t_pg_composite_coder *this = DATA_PTR(self);
383
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
285
384
  return this->needs_quotation ? Qtrue : Qfalse;
286
385
  }
287
386
 
@@ -296,7 +395,7 @@ pg_coder_needs_quotation_get(VALUE self)
296
395
  static VALUE
297
396
  pg_coder_delimiter_set(VALUE self, VALUE delimiter)
298
397
  {
299
- t_pg_composite_coder *this = DATA_PTR(self);
398
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
300
399
  StringValue(delimiter);
301
400
  if(RSTRING_LEN(delimiter) != 1)
302
401
  rb_raise( rb_eArgError, "delimiter size must be one byte");
@@ -313,7 +412,7 @@ pg_coder_delimiter_set(VALUE self, VALUE delimiter)
313
412
  static VALUE
314
413
  pg_coder_delimiter_get(VALUE self)
315
414
  {
316
- t_pg_composite_coder *this = DATA_PTR(self);
415
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
317
416
  return rb_str_new(&this->delimiter, 1);
318
417
  }
319
418
 
@@ -329,12 +428,12 @@ pg_coder_delimiter_get(VALUE self)
329
428
  static VALUE
330
429
  pg_coder_elements_type_set(VALUE self, VALUE elem_type)
331
430
  {
332
- t_pg_composite_coder *this = DATA_PTR( self );
431
+ t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
333
432
 
334
433
  if ( NIL_P(elem_type) ){
335
434
  this->elem = NULL;
336
435
  } else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
337
- this->elem = DATA_PTR( elem_type );
436
+ this->elem = RTYPEDDATA_DATA( elem_type );
338
437
  } else {
339
438
  rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::Coder)",
340
439
  rb_obj_classname( elem_type ) );
@@ -344,14 +443,31 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
344
443
  return elem_type;
345
444
  }
346
445
 
446
+ static const rb_data_type_t pg_coder_cfunc_type = {
447
+ "PG::Coder::CFUNC",
448
+ {
449
+ (RUBY_DATA_FUNC)NULL,
450
+ (RUBY_DATA_FUNC)NULL,
451
+ (size_t (*)(const void *))NULL,
452
+ },
453
+ 0,
454
+ 0,
455
+ RUBY_TYPED_FREE_IMMEDIATELY,
456
+ };
457
+
347
458
  void
348
459
  pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
349
460
  {
350
- VALUE cfunc_obj = Data_Wrap_Struct( rb_cObject, NULL, NULL, func );
461
+ VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
351
462
  VALUE coder_klass = rb_define_class_under( nsp, name, base_klass );
352
463
  if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
353
464
  rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
354
465
 
466
+ if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_TextEncoder )
467
+ rb_define_method( coder_klass, "encode", pg_coder_encode, -1 );
468
+ if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
469
+ rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
470
+
355
471
  rb_define_const( coder_klass, "CFUNC", cfunc_obj );
356
472
 
357
473
  RB_GC_GUARD(cfunc_obj);
@@ -359,10 +475,19 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
359
475
 
360
476
 
361
477
  static int
362
- pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
478
+ pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
363
479
  {
364
- *intermediate = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
365
- StringValue( *intermediate );
480
+ int arity = rb_obj_method_arity(conv->coder_obj, s_id_encode);
481
+ if( arity == 1 ){
482
+ VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
483
+ StringValue( out_str );
484
+ *intermediate = rb_str_export_to_enc(out_str, rb_enc_from_index(enc_idx));
485
+ }else{
486
+ VALUE enc = rb_enc_from_encoding(rb_enc_from_index(enc_idx));
487
+ VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 2, value, enc );
488
+ StringValue( out_str );
489
+ *intermediate = out_str;
490
+ }
366
491
  return -1;
367
492
  }
368
493
 
@@ -382,14 +507,14 @@ pg_coder_enc_func(t_pg_coder *this)
382
507
  }
383
508
 
384
509
  static VALUE
385
- pg_text_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
510
+ pg_text_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
386
511
  {
387
512
  VALUE string = pg_text_dec_string(this, val, len, tuple, field, enc_idx);
388
513
  return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
389
514
  }
390
515
 
391
516
  static VALUE
392
- pg_bin_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
517
+ pg_bin_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
393
518
  {
394
519
  VALUE string = pg_bin_dec_bytea(this, val, len, tuple, field, enc_idx);
395
520
  return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
@@ -412,7 +537,7 @@ pg_coder_dec_func(t_pg_coder *this, int binary)
412
537
 
413
538
 
414
539
  void
415
- init_pg_coder()
540
+ init_pg_coder(void)
416
541
  {
417
542
  s_id_encode = rb_intern("encode");
418
543
  s_id_decode = rb_intern("decode");
@@ -436,14 +561,25 @@ init_pg_coder()
436
561
  rb_define_method( rb_cPG_Coder, "oid", pg_coder_oid_get, 0 );
437
562
  rb_define_method( rb_cPG_Coder, "format=", pg_coder_format_set, 1 );
438
563
  rb_define_method( rb_cPG_Coder, "format", pg_coder_format_get, 0 );
564
+ rb_define_method( rb_cPG_Coder, "flags=", pg_coder_flags_set, 1 );
565
+ rb_define_method( rb_cPG_Coder, "flags", pg_coder_flags_get, 0 );
566
+
567
+ /* define flags to be used with PG::Coder#flags= */
568
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_UTC", INT2NUM(PG_CODER_TIMESTAMP_DB_UTC));
569
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_DB_LOCAL));
570
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_UTC", INT2NUM(PG_CODER_TIMESTAMP_APP_UTC));
571
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_APP_LOCAL));
572
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_MASK", INT2NUM(PG_CODER_FORMAT_ERROR_MASK));
573
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_RAISE", INT2NUM(PG_CODER_FORMAT_ERROR_TO_RAISE));
574
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_STRING", INT2NUM(PG_CODER_FORMAT_ERROR_TO_STRING));
575
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_PARTIAL", INT2NUM(PG_CODER_FORMAT_ERROR_TO_PARTIAL));
576
+
439
577
  /*
440
578
  * Name of the coder or the corresponding data type.
441
579
  *
442
580
  * This accessor is only used in PG::Coder#inspect .
443
581
  */
444
582
  rb_define_attr( rb_cPG_Coder, "name", 1, 1 );
445
- rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, 1 );
446
- rb_define_method( rb_cPG_Coder, "decode", pg_coder_decode, -1 );
447
583
 
448
584
  /* Document-class: PG::SimpleCoder < PG::Coder */
449
585
  rb_cPG_SimpleCoder = rb_define_class_under( rb_mPG, "SimpleCoder", rb_cPG_Coder );