pg 0.18.4 → 1.0.0

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 (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 */