pg 0.18.4 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) 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 +129 -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 +436 -4
  17. data/Manifest.txt +8 -21
  18. data/README-Windows.rdoc +4 -4
  19. data/README.ja.rdoc +1 -2
  20. data/README.rdoc +67 -17
  21. data/Rakefile +32 -144
  22. data/Rakefile.cross +70 -69
  23. data/certs/ged.pem +24 -0
  24. data/certs/larskanis-2022.pem +26 -0
  25. data/ext/errorcodes.def +109 -0
  26. data/ext/errorcodes.rb +1 -1
  27. data/ext/errorcodes.txt +35 -2
  28. data/ext/extconf.rb +119 -54
  29. data/ext/gvl_wrappers.c +8 -0
  30. data/ext/gvl_wrappers.h +44 -33
  31. data/ext/pg.c +213 -171
  32. data/ext/pg.h +92 -98
  33. data/ext/pg_binary_decoder.c +82 -15
  34. data/ext/pg_binary_encoder.c +20 -19
  35. data/ext/pg_coder.c +175 -39
  36. data/ext/pg_connection.c +1730 -1135
  37. data/ext/pg_copy_coder.c +94 -27
  38. data/ext/pg_record_coder.c +521 -0
  39. data/ext/pg_result.c +640 -221
  40. data/ext/pg_text_decoder.c +606 -40
  41. data/ext/pg_text_encoder.c +250 -99
  42. data/ext/pg_tuple.c +569 -0
  43. data/ext/pg_type_map.c +55 -15
  44. data/ext/pg_type_map_all_strings.c +19 -5
  45. data/ext/pg_type_map_by_class.c +54 -24
  46. data/ext/pg_type_map_by_column.c +73 -34
  47. data/ext/pg_type_map_by_mri_type.c +48 -19
  48. data/ext/pg_type_map_by_oid.c +55 -25
  49. data/ext/pg_type_map_in_ruby.c +51 -20
  50. data/ext/{util.c → pg_util.c} +12 -12
  51. data/ext/{util.h → pg_util.h} +2 -2
  52. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  53. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  54. data/lib/pg/basic_type_map_for_results.rb +81 -0
  55. data/lib/pg/basic_type_registry.rb +301 -0
  56. data/lib/pg/binary_decoder.rb +23 -0
  57. data/lib/pg/coder.rb +24 -3
  58. data/lib/pg/connection.rb +723 -65
  59. data/lib/pg/constants.rb +2 -1
  60. data/lib/pg/exceptions.rb +9 -2
  61. data/lib/pg/result.rb +24 -7
  62. data/lib/pg/text_decoder.rb +24 -22
  63. data/lib/pg/text_encoder.rb +40 -8
  64. data/lib/pg/tuple.rb +30 -0
  65. data/lib/pg/type_map_by_column.rb +3 -2
  66. data/lib/pg/version.rb +4 -0
  67. data/lib/pg.rb +61 -36
  68. data/misc/openssl-pg-segfault.rb +31 -0
  69. data/misc/postgres/History.txt +9 -0
  70. data/misc/postgres/Manifest.txt +5 -0
  71. data/misc/postgres/README.txt +21 -0
  72. data/misc/postgres/Rakefile +21 -0
  73. data/misc/postgres/lib/postgres.rb +16 -0
  74. data/misc/ruby-pg/History.txt +9 -0
  75. data/misc/ruby-pg/Manifest.txt +5 -0
  76. data/misc/ruby-pg/README.txt +21 -0
  77. data/misc/ruby-pg/Rakefile +21 -0
  78. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  79. data/pg.gemspec +32 -0
  80. data/rakelib/task_extension.rb +46 -0
  81. data/sample/array_insert.rb +1 -1
  82. data/sample/async_api.rb +4 -8
  83. data/sample/async_copyto.rb +1 -1
  84. data/sample/async_mixed.rb +1 -1
  85. data/sample/check_conn.rb +1 -1
  86. data/sample/copydata.rb +71 -0
  87. data/sample/copyfrom.rb +1 -1
  88. data/sample/copyto.rb +1 -1
  89. data/sample/cursor.rb +1 -1
  90. data/sample/disk_usage_report.rb +6 -15
  91. data/sample/issue-119.rb +2 -2
  92. data/sample/losample.rb +1 -1
  93. data/sample/minimal-testcase.rb +2 -2
  94. data/sample/notify_wait.rb +1 -1
  95. data/sample/pg_statistics.rb +6 -15
  96. data/sample/replication_monitor.rb +9 -18
  97. data/sample/test_binary_values.rb +1 -1
  98. data/sample/wal_shipper.rb +2 -2
  99. data/sample/warehouse_partitions.rb +8 -17
  100. data.tar.gz.sig +0 -0
  101. metadata +79 -225
  102. metadata.gz.sig +0 -0
  103. data/ChangeLog +0 -5911
  104. data/lib/pg/basic_type_mapping.rb +0 -399
  105. data/spec/data/expected_trace.out +0 -26
  106. data/spec/data/random_binary_data +0 -0
  107. data/spec/helpers.rb +0 -355
  108. data/spec/pg/basic_type_mapping_spec.rb +0 -251
  109. data/spec/pg/connection_spec.rb +0 -1544
  110. data/spec/pg/result_spec.rb +0 -449
  111. data/spec/pg/type_map_by_class_spec.rb +0 -138
  112. data/spec/pg/type_map_by_column_spec.rb +0 -222
  113. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  114. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  115. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  116. data/spec/pg/type_map_spec.rb +0 -22
  117. data/spec/pg/type_spec.rb +0 -697
  118. 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) );
@@ -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 );