pg 0.18.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/BSDL +2 -2
  4. data/ChangeLog +689 -5
  5. data/History.rdoc +84 -0
  6. data/Manifest.txt +0 -18
  7. data/README.rdoc +13 -10
  8. data/Rakefile +16 -19
  9. data/Rakefile.cross +21 -24
  10. data/ext/errorcodes.def +33 -0
  11. data/ext/errorcodes.txt +15 -1
  12. data/ext/extconf.rb +21 -33
  13. data/ext/gvl_wrappers.c +4 -0
  14. data/ext/gvl_wrappers.h +27 -39
  15. data/ext/pg.c +18 -50
  16. data/ext/pg.h +13 -80
  17. data/ext/pg_binary_encoder.c +8 -8
  18. data/ext/pg_coder.c +31 -10
  19. data/ext/pg_connection.c +340 -225
  20. data/ext/pg_copy_coder.c +34 -4
  21. data/ext/pg_result.c +24 -22
  22. data/ext/pg_text_encoder.c +62 -42
  23. data/ext/pg_type_map.c +14 -7
  24. data/lib/pg/basic_type_mapping.rb +35 -8
  25. data/lib/pg/connection.rb +53 -12
  26. data/lib/pg/result.rb +10 -5
  27. data/lib/pg/text_decoder.rb +7 -0
  28. data/lib/pg/text_encoder.rb +8 -0
  29. data/lib/pg.rb +18 -10
  30. data/spec/helpers.rb +8 -15
  31. data/spec/pg/basic_type_mapping_spec.rb +54 -0
  32. data/spec/pg/connection_spec.rb +384 -209
  33. data/spec/pg/result_spec.rb +14 -7
  34. data/spec/pg/type_map_by_class_spec.rb +2 -2
  35. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  36. data/spec/pg/type_spec.rb +83 -3
  37. data/spec/pg_spec.rb +1 -1
  38. data.tar.gz.sig +0 -0
  39. metadata +55 -64
  40. metadata.gz.sig +0 -0
  41. data/sample/array_insert.rb +0 -20
  42. data/sample/async_api.rb +0 -106
  43. data/sample/async_copyto.rb +0 -39
  44. data/sample/async_mixed.rb +0 -56
  45. data/sample/check_conn.rb +0 -21
  46. data/sample/copyfrom.rb +0 -81
  47. data/sample/copyto.rb +0 -19
  48. data/sample/cursor.rb +0 -21
  49. data/sample/disk_usage_report.rb +0 -186
  50. data/sample/issue-119.rb +0 -94
  51. data/sample/losample.rb +0 -69
  52. data/sample/minimal-testcase.rb +0 -17
  53. data/sample/notify_wait.rb +0 -72
  54. data/sample/pg_statistics.rb +0 -294
  55. data/sample/replication_monitor.rb +0 -231
  56. data/sample/test_binary_values.rb +0 -33
  57. data/sample/wal_shipper.rb +0 -434
  58. data/sample/warehouse_partitions.rb +0 -320
data/ext/gvl_wrappers.h CHANGED
@@ -15,14 +15,7 @@
15
15
  #ifndef __gvl_wrappers_h
16
16
  #define __gvl_wrappers_h
17
17
 
18
- #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
19
- extern void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
20
- #endif
21
-
22
- #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
23
- extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
24
- rb_unblock_function_t *ubf, void *data2);
25
- #endif
18
+ #include <ruby/thread.h>
26
19
 
27
20
  #define DEFINE_PARAM_LIST1(type, name) \
28
21
  name,
@@ -53,21 +46,14 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
53
46
  return NULL; \
54
47
  }
55
48
 
56
- #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
57
- #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
58
- rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
59
- struct gvl_wrapper_##name##_params params = { \
60
- {FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
61
- }; \
62
- rb_thread_call_without_gvl(gvl_##name##_skeleton, &params, RUBY_UBF_IO, 0); \
63
- when_non_void( return params.retval; ) \
64
- }
65
- #else
66
- #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
67
- rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
68
- return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
69
- }
70
- #endif
49
+ #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
50
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
51
+ struct gvl_wrapper_##name##_params params = { \
52
+ {FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
53
+ }; \
54
+ rb_thread_call_without_gvl(gvl_##name##_skeleton, &params, RUBY_UBF_IO, 0); \
55
+ when_non_void( return params.retval; ) \
56
+ }
71
57
 
72
58
  #define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
73
59
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
@@ -80,21 +66,14 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
80
66
  return NULL; \
81
67
  }
82
68
 
83
- #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
84
- #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
85
- rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
86
- struct gvl_wrapper_##name##_params params = { \
87
- {FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
88
- }; \
89
- rb_thread_call_with_gvl(gvl_##name##_skeleton, &params); \
90
- when_non_void( return params.retval; ) \
91
- }
92
- #else
93
- #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
94
- rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
95
- return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
96
- }
97
- #endif
69
+ #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
70
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
71
+ struct gvl_wrapper_##name##_params params = { \
72
+ {FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
73
+ }; \
74
+ rb_thread_call_with_gvl(gvl_##name##_skeleton, &params); \
75
+ when_non_void( return params.retval; ) \
76
+ }
98
77
 
99
78
  #define GVL_TYPE_VOID(string)
100
79
  #define GVL_TYPE_NONVOID(string) string
@@ -195,8 +174,16 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
195
174
  #define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
196
175
  param(PGconn *, conn)
197
176
 
177
+ #define FOR_EACH_PARAM_OF_PQsetClientEncoding(param) \
178
+ param(PGconn *, conn)
179
+
198
180
  #define FOR_EACH_PARAM_OF_PQisBusy(param)
199
181
 
182
+ #define FOR_EACH_PARAM_OF_PQencryptPasswordConn(param) \
183
+ param(PGconn *, conn) \
184
+ param(const char *, passwd) \
185
+ param(const char *, user)
186
+
200
187
  #define FOR_EACH_PARAM_OF_PQcancel(param) \
201
188
  param(PGcancel *, cancel) \
202
189
  param(char *, errbuf)
@@ -226,10 +213,11 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
226
213
  function(PQsendQueryPrepared, GVL_TYPE_NONVOID, int, int, resultFormat) \
227
214
  function(PQsendDescribePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
228
215
  function(PQsendDescribePortal, GVL_TYPE_NONVOID, int, const char *, portal) \
216
+ function(PQsetClientEncoding, GVL_TYPE_NONVOID, int, const char *, encoding) \
229
217
  function(PQisBusy, GVL_TYPE_NONVOID, int, PGconn *, conn) \
218
+ function(PQencryptPasswordConn, GVL_TYPE_NONVOID, char *, const char *, algorithm) \
230
219
  function(PQcancel, GVL_TYPE_NONVOID, int, int, errbufsize);
231
220
 
232
-
233
221
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
234
222
 
235
223
 
data/ext/pg.c CHANGED
@@ -1,12 +1,13 @@
1
1
  /*
2
2
  * pg.c - Toplevel extension
3
- * $Id: pg.c,v b60c89ee93c8 2015/02/11 20:59:36 lars $
3
+ * $Id: pg.c,v 1f0926bfa9a5 2018/01/04 18:14:32 lars $
4
4
  *
5
5
  * Author/s:
6
6
  *
7
7
  * - Jeff Davis <ruby-pg@j-davis.com>
8
8
  * - Guy Decoux (ts) <decoux@moulon.inra.fr>
9
9
  * - Michael Granger <ged@FaerieMUD.org>
10
+ * - Lars Kanis <lars@greiz-reinsdorf.de>
10
11
  * - Dave Lee
11
12
  * - Eiji Matsumoto <usagi@ruby.club.or.jp>
12
13
  * - Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -15,10 +16,10 @@
15
16
  * See Contributors.rdoc for the many additional fine people that have contributed
16
17
  * to this library over the years.
17
18
  *
18
- * Copyright (c) 1997-2015 by the authors.
19
+ * Copyright (c) 1997-2016 by the authors.
19
20
  *
20
21
  * You may redistribute this software under the same terms as Ruby itself; see
21
- * http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
22
+ * https://www.ruby-lang.org/en/about/license.txt or the BSDL file in the source
22
23
  * for details.
23
24
  *
24
25
  * Portions of the code are from the PostgreSQL project, and are distributed
@@ -68,7 +69,6 @@ VALUE rb_mPGconstants;
68
69
  * M17n functions
69
70
  */
70
71
 
71
- #ifdef M17N_SUPPORTED
72
72
  /**
73
73
  * The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
74
74
  */
@@ -143,7 +143,7 @@ pg_find_or_create_johab(void)
143
143
 
144
144
  enc_index = rb_define_dummy_encoding(aliases[0]);
145
145
  for (i = 1; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
146
- ENC_ALIAS(aliases[i], aliases[0]);
146
+ rb_encdb_alias(aliases[i], aliases[0]);
147
147
  }
148
148
  return rb_enc_from_index(enc_index);
149
149
  }
@@ -228,8 +228,6 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
228
228
  return encname;
229
229
  }
230
230
 
231
- #endif /* M17N_SUPPORTED */
232
-
233
231
 
234
232
  /*
235
233
  * Ensures that the given string has enough capacity to take expand_len
@@ -259,45 +257,26 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
259
257
  * rb_str_set_len( string, current_out - RSTRING_PTR(string) );
260
258
  *
261
259
  */
262
- #ifdef HAVE_RB_STR_MODIFY_EXPAND
263
- /* Use somewhat faster version with access to string capacity on MRI */
264
- char *
265
- pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
266
- {
267
- long curr_len = curr_ptr - RSTRING_PTR(str);
268
- long curr_capa = rb_str_capacity( str );
269
- if( curr_capa < curr_len + expand_len ){
270
- rb_str_set_len( str, curr_len );
271
- rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa );
272
- curr_ptr = RSTRING_PTR(str) + curr_len;
273
- }
274
- if( end_ptr )
275
- *end_ptr = RSTRING_PTR(str) + rb_str_capacity( str );
276
- return curr_ptr;
277
- }
278
- #else
279
- /* Use the more portable version */
280
- char *
281
- pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
282
- {
283
- long curr_len = curr_ptr - RSTRING_PTR(str);
284
- long curr_capa = RSTRING_LEN( str );
285
- if( curr_capa < curr_len + expand_len ){
286
- rb_str_resize( str, (curr_len + expand_len) * 2 - curr_capa );
287
- curr_ptr = RSTRING_PTR(str) + curr_len;
288
- }
289
- if( end_ptr )
290
- *end_ptr = RSTRING_PTR(str) + RSTRING_LEN(str);
291
- return curr_ptr;
260
+ char *
261
+ pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
262
+ {
263
+ long curr_len = curr_ptr - RSTRING_PTR(str);
264
+ long curr_capa = rb_str_capacity( str );
265
+ if( curr_capa < curr_len + expand_len ){
266
+ rb_str_set_len( str, curr_len );
267
+ rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa );
268
+ curr_ptr = RSTRING_PTR(str) + curr_len;
292
269
  }
293
- #endif
270
+ if( end_ptr )
271
+ *end_ptr = RSTRING_PTR(str) + rb_str_capacity( str );
272
+ return curr_ptr;
273
+ }
294
274
 
295
275
 
296
276
  /**************************************************************************
297
277
  * Module Methods
298
278
  **************************************************************************/
299
279
 
300
- #ifdef HAVE_PQLIBVERSION
301
280
  /*
302
281
  * call-seq:
303
282
  * PG.library_version -> Integer
@@ -315,7 +294,6 @@ pg_s_library_version(VALUE self)
315
294
  UNUSED( self );
316
295
  return INT2NUM(PQlibVersion());
317
296
  }
318
- #endif
319
297
 
320
298
 
321
299
  /*
@@ -409,9 +387,7 @@ Init_pg_ext()
409
387
  /*************************
410
388
  * PG module methods
411
389
  *************************/
412
- #ifdef HAVE_PQLIBVERSION
413
390
  rb_define_singleton_method( rb_mPG, "library_version", pg_s_library_version, 0 );
414
- #endif
415
391
  rb_define_singleton_method( rb_mPG, "isthreadsafe", pg_s_threadsafe_p, 0 );
416
392
  SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
417
393
  SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
@@ -477,7 +453,6 @@ Init_pg_ext()
477
453
  /* Verbose error verbosity level (#set_error_verbosity) */
478
454
  rb_define_const(rb_mPGconstants, "PQERRORS_VERBOSE", INT2FIX(PQERRORS_VERBOSE));
479
455
 
480
- #ifdef HAVE_PQPING
481
456
  /****** PG::Connection CLASS CONSTANTS: Check Server Status ******/
482
457
 
483
458
  /* Server is accepting connections. */
@@ -488,7 +463,6 @@ Init_pg_ext()
488
463
  rb_define_const(rb_mPGconstants, "PQPING_NO_RESPONSE", INT2FIX(PQPING_NO_RESPONSE));
489
464
  /* Connection not attempted (bad params). */
490
465
  rb_define_const(rb_mPGconstants, "PQPING_NO_ATTEMPT", INT2FIX(PQPING_NO_ATTEMPT));
491
- #endif
492
466
 
493
467
  /****** PG::Connection CLASS CONSTANTS: Large Objects ******/
494
468
 
@@ -523,13 +497,9 @@ Init_pg_ext()
523
497
  /* #result_status constant: A fatal error occurred. */
524
498
  rb_define_const(rb_mPGconstants, "PGRES_FATAL_ERROR", INT2FIX(PGRES_FATAL_ERROR));
525
499
  /* #result_status constant: Copy In/Out data transfer in progress. */
526
- #ifdef HAVE_CONST_PGRES_COPY_BOTH
527
500
  rb_define_const(rb_mPGconstants, "PGRES_COPY_BOTH", INT2FIX(PGRES_COPY_BOTH));
528
- #endif
529
501
  /* #result_status constant: Single tuple from larger resultset. */
530
- #ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
531
502
  rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
532
- #endif
533
503
 
534
504
  /****** Result CONSTANTS: result error field codes ******/
535
505
 
@@ -641,9 +611,7 @@ Init_pg_ext()
641
611
  /* Add the constants to the toplevel namespace */
642
612
  rb_include_module( rb_mPG, rb_mPGconstants );
643
613
 
644
- #ifdef M17N_SUPPORTED
645
614
  enc_pg2ruby = st_init_numtable();
646
- #endif
647
615
 
648
616
  /* Initialize the main extension classes */
649
617
  init_pg_connection();
data/ext/pg.h CHANGED
@@ -9,95 +9,30 @@
9
9
  #include <stdio.h>
10
10
  #include <stdlib.h>
11
11
  #include <sys/types.h>
12
+ #if !defined(_WIN32)
13
+ # include <sys/time.h>
14
+ #endif
12
15
  #if defined(HAVE_UNISTD_H) && !defined(_WIN32)
13
16
  # include <unistd.h>
14
17
  #endif /* HAVE_UNISTD_H */
15
18
 
16
19
  /* Ruby headers */
17
20
  #include "ruby.h"
18
- #ifdef HAVE_RUBY_ST_H
19
- # include "ruby/st.h"
20
- #elif HAVE_ST_H
21
- # include "st.h"
22
- #endif
21
+ #include "ruby/st.h"
22
+ #include "ruby/encoding.h"
23
23
 
24
- #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
25
- # include "ruby/encoding.h"
26
- # define M17N_SUPPORTED
27
- # ifdef HAVE_RB_ENCDB_ALIAS
28
- extern int rb_encdb_alias(const char *, const char *);
29
- # define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
30
- # elif HAVE_RB_ENC_ALIAS
31
- extern int rb_enc_alias(const char *, const char *);
32
- # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
33
- # else
34
- extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
35
- # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
36
- # endif
37
-
38
-
39
- # if !defined(ENCODING_SET_INLINED)
40
- /* Rubinius doesn't define ENCODING_SET_INLINED, so we fall back to the more
41
- * portable version.
42
- */
43
- # define PG_ENCODING_SET_NOCHECK(obj,i) \
44
- do { \
45
- rb_enc_set_index((obj), (i)); \
46
- } while(0)
47
- # else
48
- # define PG_ENCODING_SET_NOCHECK(obj,i) \
24
+ /* exported by ruby-1.9.3+ but not declared */
25
+ extern int rb_encdb_alias(const char *, const char *);
26
+
27
+ #define PG_ENCODING_SET_NOCHECK(obj,i) \
49
28
  do { \
50
29
  if ((i) < ENCODING_INLINE_MAX) \
51
30
  ENCODING_SET_INLINED((obj), (i)); \
52
31
  else \
53
32
  rb_enc_set_index((obj), (i)); \
54
33
  } while(0)
55
- # endif
56
-
57
- #else
58
- # define PG_ENCODING_SET_NOCHECK(obj,i) /* nothing */
59
- #endif
60
-
61
- #if RUBY_VM != 1
62
- # define RUBY_18_COMPAT
63
- #endif
64
-
65
- #ifndef RARRAY_LEN
66
- # define RARRAY_LEN(x) RARRAY((x))->len
67
- #endif /* RARRAY_LEN */
68
34
 
69
- #ifndef RSTRING_LEN
70
- # define RSTRING_LEN(x) RSTRING((x))->len
71
- #endif /* RSTRING_LEN */
72
-
73
- #ifndef RSTRING_PTR
74
- # define RSTRING_PTR(x) RSTRING((x))->ptr
75
- #endif /* RSTRING_PTR */
76
-
77
- #ifndef StringValuePtr
78
- # define StringValuePtr(x) STR2CSTR(x)
79
- #endif /* StringValuePtr */
80
-
81
- #ifdef RUBY_18_COMPAT
82
- # define rb_io_stdio_file GetWriteFile
83
- # include "rubyio.h"
84
- #else
85
- # include "ruby/io.h"
86
- #endif
87
-
88
- #ifdef RUBINIUS
89
- /* Workaround for wrong FIXNUM_MAX definition */
90
- typedef intptr_t native_int;
91
- #endif
92
-
93
- #ifndef RETURN_SIZED_ENUMERATOR
94
- #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) RETURN_ENUMERATOR((obj), (argc), (argv))
95
- #endif
96
-
97
- #ifndef HAVE_RB_HASH_DUP
98
- /* Rubinius doesn't define rb_hash_dup() */
99
- #define rb_hash_dup(tuple) rb_funcall((tuple), rb_intern("dup"), 0)
100
- #endif
35
+ #include "ruby/io.h"
101
36
 
102
37
  #ifndef timeradd
103
38
  #define timeradd(a, b, result) \
@@ -205,7 +140,7 @@ typedef struct {
205
140
  } t_pg_result;
206
141
 
207
142
 
208
- typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
143
+ typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *, int);
209
144
  typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
210
145
  typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
211
146
  typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
@@ -321,8 +256,8 @@ void init_pg_binary_decoder _(( void ));
321
256
  VALUE lookup_error_class _(( const char * ));
322
257
  VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
323
258
  VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
324
- int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *));
325
- int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *));
259
+ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *, int));
260
+ int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
326
261
  t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
327
262
  t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
328
263
  void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
@@ -379,12 +314,10 @@ pgresult_get_this( VALUE self )
379
314
  }
380
315
 
381
316
 
382
- #ifdef M17N_SUPPORTED
383
317
  rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
384
318
  rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
385
319
  const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
386
320
  rb_encoding *pg_conn_enc_get _(( PGconn * ));
387
- #endif /* M17N_SUPPORTED */
388
321
 
389
322
  void notice_receiver_proxy(void *arg, const PGresult *result);
390
323
  void notice_processor_proxy(void *arg, const char *message);
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_encoder.c,v 72168db5fb7b 2015/11/04 16:13:42 lars $
3
+ * $Id: pg_binary_encoder.c,v e61a06f1f5ed 2015/12/25 21:14:21 lars $
4
4
  *
5
5
  */
6
6
 
@@ -22,7 +22,7 @@ VALUE rb_mPG_BinaryEncoder;
22
22
  *
23
23
  */
24
24
  static int
25
- pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
25
+ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
26
26
  {
27
27
  char mybool;
28
28
  switch(value){
@@ -44,7 +44,7 @@ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
44
44
  *
45
45
  */
46
46
  static int
47
- pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
47
+ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
48
48
  {
49
49
  if(out){
50
50
  write_nbo16(NUM2INT(*intermediate), out);
@@ -63,7 +63,7 @@ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
63
63
  *
64
64
  */
65
65
  static int
66
- pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
66
+ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
67
67
  {
68
68
  if(out){
69
69
  write_nbo32(NUM2LONG(*intermediate), out);
@@ -82,7 +82,7 @@ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
82
82
  *
83
83
  */
84
84
  static int
85
- pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
85
+ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
86
86
  {
87
87
  if(out){
88
88
  write_nbo64(NUM2LL(*intermediate), out);
@@ -100,7 +100,7 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
100
100
  *
101
101
  */
102
102
  static int
103
- pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
103
+ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
104
104
  {
105
105
  int strlen;
106
106
  VALUE subint;
@@ -109,13 +109,13 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
109
109
 
110
110
  if(out){
111
111
  /* Second encoder pass, if required */
112
- strlen = enc_func(this->elem, value, out, intermediate);
112
+ strlen = enc_func(this->elem, value, out, intermediate, enc_idx);
113
113
  strlen = base64_decode( out, out, strlen );
114
114
 
115
115
  return strlen;
116
116
  } else {
117
117
  /* First encoder pass */
118
- strlen = enc_func(this->elem, value, NULL, &subint);
118
+ strlen = enc_func(this->elem, value, NULL, &subint, enc_idx);
119
119
 
120
120
  if( strlen == -1 ){
121
121
  /* Encoded string is returned in subint */
data/ext/pg_coder.c CHANGED
@@ -105,7 +105,7 @@ pg_composite_decoder_allocate( VALUE klass )
105
105
 
106
106
  /*
107
107
  * call-seq:
108
- * coder.encode( value )
108
+ * coder.encode( value [, encoding] )
109
109
  *
110
110
  * Encodes the given Ruby object into string representation, without
111
111
  * sending data to/from the database server.
@@ -114,13 +114,24 @@ pg_composite_decoder_allocate( VALUE klass )
114
114
  *
115
115
  */
116
116
  static VALUE
117
- pg_coder_encode(VALUE self, VALUE value)
117
+ pg_coder_encode(int argc, VALUE *argv, VALUE self)
118
118
  {
119
119
  VALUE res;
120
120
  VALUE intermediate;
121
+ VALUE value;
121
122
  int len, len2;
123
+ int enc_idx;
122
124
  t_pg_coder *this = DATA_PTR(self);
123
125
 
126
+ if(argc < 1 || argc > 2){
127
+ rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
128
+ }else if(argc == 1){
129
+ enc_idx = rb_ascii8bit_encindex();
130
+ }else{
131
+ enc_idx = rb_to_encoding_index(argv[1]);
132
+ }
133
+ value = argv[0];
134
+
124
135
  if( NIL_P(value) )
125
136
  return Qnil;
126
137
 
@@ -128,7 +139,7 @@ pg_coder_encode(VALUE self, VALUE value)
128
139
  rb_raise(rb_eRuntimeError, "no encoder function defined");
129
140
  }
130
141
 
131
- len = this->enc_func( this, value, NULL, &intermediate );
142
+ len = this->enc_func( this, value, NULL, &intermediate, enc_idx );
132
143
 
133
144
  if( len == -1 ){
134
145
  /* The intermediate value is a String that can be used directly. */
@@ -137,7 +148,8 @@ pg_coder_encode(VALUE self, VALUE value)
137
148
  }
138
149
 
139
150
  res = rb_str_new(NULL, len);
140
- len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate);
151
+ PG_ENCODING_SET_NOCHECK(res, enc_idx);
152
+ len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate, enc_idx );
141
153
  if( len < len2 ){
142
154
  rb_bug("%s: result length of first encoder run (%i) is less than second run (%i)",
143
155
  rb_obj_classname( self ), len, len2 );
@@ -165,8 +177,8 @@ static VALUE
165
177
  pg_coder_decode(int argc, VALUE *argv, VALUE self)
166
178
  {
167
179
  char *val;
168
- VALUE tuple = -1;
169
- VALUE field = -1;
180
+ int tuple = -1;
181
+ int field = -1;
170
182
  VALUE res;
171
183
  t_pg_coder *this = DATA_PTR(self);
172
184
 
@@ -359,10 +371,19 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
359
371
 
360
372
 
361
373
  static int
362
- pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
374
+ pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
363
375
  {
364
- *intermediate = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
365
- StringValue( *intermediate );
376
+ int arity = rb_obj_method_arity(conv->coder_obj, s_id_encode);
377
+ if( arity == 1 ){
378
+ VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
379
+ StringValue( out_str );
380
+ *intermediate = rb_str_export_to_enc(out_str, rb_enc_from_index(enc_idx));
381
+ }else{
382
+ VALUE enc = rb_enc_from_encoding(rb_enc_from_index(enc_idx));
383
+ VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 2, value, enc );
384
+ StringValue( out_str );
385
+ *intermediate = out_str;
386
+ }
366
387
  return -1;
367
388
  }
368
389
 
@@ -442,7 +463,7 @@ init_pg_coder()
442
463
  * This accessor is only used in PG::Coder#inspect .
443
464
  */
444
465
  rb_define_attr( rb_cPG_Coder, "name", 1, 1 );
445
- rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, 1 );
466
+ rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, -1 );
446
467
  rb_define_method( rb_cPG_Coder, "decode", pg_coder_decode, -1 );
447
468
 
448
469
  /* Document-class: PG::SimpleCoder < PG::Coder */