pg 0.18.4-x86-mingw32 → 0.19.0.pre20160817083826-x86-mingw32

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 (54) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +686 -167
  5. data/History.rdoc +23 -0
  6. data/README.rdoc +6 -6
  7. data/Rakefile +10 -12
  8. data/Rakefile.cross +6 -6
  9. data/ext/errorcodes.def +16 -0
  10. data/ext/errorcodes.txt +5 -1
  11. data/ext/extconf.rb +9 -1
  12. data/ext/gvl_wrappers.h +4 -0
  13. data/ext/pg.c +1 -1
  14. data/ext/pg.h +6 -3
  15. data/ext/pg_binary_decoder.c +1 -1
  16. data/ext/pg_binary_encoder.c +8 -8
  17. data/ext/pg_coder.c +30 -9
  18. data/ext/pg_connection.c +203 -77
  19. data/ext/pg_copy_coder.c +34 -4
  20. data/ext/pg_result.c +2 -2
  21. data/ext/pg_text_decoder.c +1 -1
  22. data/ext/pg_text_encoder.c +62 -42
  23. data/ext/pg_type_map.c +1 -1
  24. data/ext/pg_type_map_all_strings.c +1 -1
  25. data/ext/pg_type_map_by_class.c +1 -1
  26. data/ext/pg_type_map_by_column.c +1 -1
  27. data/ext/pg_type_map_by_mri_type.c +1 -1
  28. data/ext/pg_type_map_by_oid.c +1 -1
  29. data/ext/pg_type_map_in_ruby.c +1 -1
  30. data/ext/util.c +1 -1
  31. data/lib/1.9/pg_ext.so +0 -0
  32. data/lib/2.0/pg_ext.so +0 -0
  33. data/lib/2.1/pg_ext.so +0 -0
  34. data/lib/2.2/pg_ext.so +0 -0
  35. data/lib/2.3/pg_ext.so +0 -0
  36. data/lib/libpq.dll +0 -0
  37. data/lib/pg.rb +3 -3
  38. data/lib/pg/basic_type_mapping.rb +35 -8
  39. data/lib/pg/connection.rb +46 -6
  40. data/lib/pg/result.rb +6 -2
  41. data/lib/pg/text_decoder.rb +7 -0
  42. data/lib/pg/text_encoder.rb +8 -0
  43. data/sample/disk_usage_report.rb +1 -1
  44. data/sample/pg_statistics.rb +1 -1
  45. data/sample/replication_monitor.rb +1 -1
  46. data/spec/helpers.rb +6 -9
  47. data/spec/pg/basic_type_mapping_spec.rb +54 -0
  48. data/spec/pg/connection_spec.rb +130 -23
  49. data/spec/pg/type_map_by_class_spec.rb +1 -1
  50. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  51. data/spec/pg/type_spec.rb +82 -2
  52. metadata +33 -35
  53. metadata.gz.sig +0 -0
  54. data/lib/i386-mingw32/libpq.dll +0 -0
@@ -1,3 +1,26 @@
1
+ == v0.19.0 [YYYY-MM-DD] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ - Deprecate Ruby 1.9
4
+
5
+ Enhancements:
6
+ - Respect and convert character encoding of all strings sent
7
+ to the server. #231
8
+ - Add PostgreSQL-9.5 functions PQsslInUse(), PQsslAttribute()
9
+ and PQsslAttributeNames().
10
+ - Various documentation fixes and improvements.
11
+ - Add mechanism to build without pg_config:
12
+ gem install pg -- --with-pg-config=ignore
13
+ - Update Windows binary gems to Ruby-2.3, PostgreSQL 9.5.4 and
14
+ OpenSSL 1.0.2f.
15
+ - Add JSON coders and add them to BasicTypeMapForResults and
16
+ BasicTypeMapBasedOnResult
17
+ - Allow build from git per bundler.
18
+
19
+ Bugfixes:
20
+ - Release GVL while calling PQsetClientEncoding(). #245
21
+ - Add __EXTENSIONS__ to Solaris/SmartOS for Ruby >= 2.3.x. #236
22
+
23
+
1
24
  == v0.18.4 [2015-11-13] Michael Granger <ged@FaerieMUD.org>
2
25
 
3
26
  Enhancements:
@@ -11,7 +11,7 @@ docs :: http://deveiate.org/code/pg
11
11
 
12
12
  Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
13
13
 
14
- It works with {PostgreSQL 8.4 and later}[http://www.postgresql.org/support/versioning/].
14
+ It works with {PostgreSQL 9.1 and later}[http://www.postgresql.org/support/versioning/].
15
15
 
16
16
  A small example usage:
17
17
 
@@ -23,7 +23,7 @@ A small example usage:
23
23
  conn = PG.connect( dbname: 'sales' )
24
24
  conn.exec( "SELECT * FROM pg_stat_activity" ) do |result|
25
25
  puts " PID | User | Query"
26
- result.each do |row|
26
+ result.each do |row|
27
27
  puts " %7d | %-16s | %s " %
28
28
  row.values_at('procpid', 'usename', 'current_query')
29
29
  end
@@ -37,10 +37,10 @@ A small example usage:
37
37
 
38
38
  == Requirements
39
39
 
40
- * Ruby 1.9.3-p392, or 2.0.0-p0.
41
- * PostgreSQL 8.4.x or later (with headers, -dev packages, etc).
40
+ * Ruby 2.2
41
+ * PostgreSQL 9.1.x or later (with headers, -dev packages, etc).
42
42
 
43
- It may work with earlier versions of Ruby/PostgreSQL as well, but those are
43
+ It usually work with earlier versions of Ruby/PostgreSQL as well, but those are
44
44
  not regularly tested.
45
45
 
46
46
 
@@ -112,7 +112,7 @@ needs for type casting. The default type map is PG::TypeMapAllStrings.
112
112
 
113
113
  A type map can be assigned per connection or per query respectively per
114
114
  result set. Type maps can also be used for COPY in and out data streaming.
115
-
115
+ See PG::Connection#copy_data .
116
116
 
117
117
  == Contributing
118
118
 
data/Rakefile CHANGED
@@ -55,22 +55,21 @@ $hoespec = Hoe.spec 'pg' do
55
55
  self.extra_rdoc_files = Rake::FileList[ '*.rdoc' ]
56
56
  self.extra_rdoc_files.include( 'POSTGRES', 'LICENSE' )
57
57
  self.extra_rdoc_files.include( 'ext/*.c' )
58
- self.license :BSD
58
+ self.license 'BSD-3-Clause'
59
59
 
60
60
  self.developer 'Michael Granger', 'ged@FaerieMUD.org'
61
61
  self.developer 'Lars Kanis', 'lars@greiz-reinsdorf.de'
62
62
 
63
63
  self.dependency 'rake-compiler', '~> 0.9', :developer
64
- self.dependency 'rake-compiler-dock', '~> 0.3', :developer
64
+ self.dependency 'rake-compiler-dock', '~> 0.5', :developer
65
65
  self.dependency 'hoe', '~> 3.12', :developer
66
66
  self.dependency 'hoe-deveiate', '~> 0.6', :developer
67
67
  self.dependency 'hoe-bundler', '~> 1.0', :developer
68
68
  self.dependency 'rspec', '~> 3.0', :developer
69
69
 
70
- self.spec_extras[:licenses] = ['BSD', 'Ruby', 'GPL']
71
70
  self.spec_extras[:extensions] = [ 'ext/extconf.rb' ]
72
71
 
73
- self.require_ruby_version( '>= 1.9.3' )
72
+ self.require_ruby_version( '>= 2.0.0' )
74
73
 
75
74
  self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
76
75
  self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
@@ -81,7 +80,7 @@ end
81
80
  ENV['VERSION'] ||= $hoespec.spec.version.to_s
82
81
 
83
82
  # Tests should pass before checking in
84
- task 'hg:precheckin' => [ :check_history, :check_manifest, :spec ]
83
+ task 'hg:precheckin' => [ :check_history, :check_manifest, :spec, :gemspec ]
85
84
 
86
85
  # Support for 'rvm specs'
87
86
  task :specs => :spec
@@ -97,7 +96,7 @@ task :test do
97
96
  # the installed gem dir. So we clear the task rake-compiler set up
98
97
  # to break the dependency between :spec and :compile when running under
99
98
  # rubygems-test, and then run :spec.
100
- Rake::Task[ EXT.to_s ].clear
99
+ Rake::Task[ EXT.to_s ].clear if File.exist?(EXT.to_s)
101
100
  Rake::Task[ :spec ].execute
102
101
  end
103
102
 
@@ -132,8 +131,7 @@ Rake::ExtensionTask.new do |ext|
132
131
 
133
132
  # Add libpq.dll to windows binary gemspec
134
133
  ext.cross_compiling do |spec|
135
- # mingw32-platform strings differ (RUBY_PLATFORM=i386-mingw32 vs. x86-mingw32 for rubygems)
136
- spec.files << "lib/#{spec.platform.to_s.gsub(/^x86-/, "i386-")}/libpq.dll"
134
+ spec.files << "lib/libpq.dll"
137
135
  end
138
136
  end
139
137
 
@@ -191,9 +189,7 @@ task :update_error_codes do
191
189
 
192
190
  ERRORCODES_TXT = "ext/errorcodes.txt"
193
191
  sh "wget #{URL_ERRORCODES_TXT.inspect} -O #{ERRORCODES_TXT.inspect} || curl #{URL_ERRORCODES_TXT.inspect} -o #{ERRORCODES_TXT.inspect}"
194
- end
195
192
 
196
- file 'ext/errorcodes.def' => ['ext/errorcodes.rb', 'ext/errorcodes.txt'] do
197
193
  ruby 'ext/errorcodes.rb', 'ext/errorcodes.txt', 'ext/errorcodes.def'
198
194
  end
199
195
 
@@ -207,12 +203,14 @@ file GEMSPEC => __FILE__
207
203
  task GEMSPEC do |task|
208
204
  spec = $hoespec.spec
209
205
  spec.files.delete( '.gemtest' )
210
- spec.version = "#{spec.version}.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
206
+ spec.signing_key = nil
207
+ spec.version = "#{spec.version.bump}.0.pre#{Time.now.strftime("%Y%m%d%H%M%S")}"
208
+ spec.cert_chain = [ 'certs/ged.pem' ]
211
209
  File.open( task.name, 'w' ) do |fh|
212
210
  fh.write( spec.to_ruby )
213
211
  end
214
212
  end
215
213
 
216
- CLOBBER.include( GEMSPEC.to_s )
214
+ CLOBBER.include( '*.gemspec' )
217
215
  task :default => :gemspec
218
216
 
@@ -29,8 +29,8 @@ class CrossLibrary < OpenStruct
29
29
  self.host_platform = toolchain
30
30
 
31
31
  # Cross-compilation constants
32
- self.openssl_version = ENV['OPENSSL_VERSION'] || '1.0.2d'
33
- self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '9.4.4'
32
+ self.openssl_version = ENV['OPENSSL_VERSION'] || '1.0.2h'
33
+ self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '9.5.4'
34
34
 
35
35
  # Check if symlinks work in the current working directory.
36
36
  # This fails, if rake-compiler-dock is running on a Windows box.
@@ -235,7 +235,7 @@ class CrossLibrary < OpenStruct
235
235
  task :libpq => postgresql_lib
236
236
 
237
237
  # copy libpq.dll to lib dir
238
- dest_libpq = "lib/#{for_platform}/#{postgresql_lib.basename}"
238
+ dest_libpq = "lib/#{postgresql_lib.basename}"
239
239
  directory File.dirname(dest_libpq)
240
240
  file dest_libpq => [postgresql_lib, File.dirname(dest_libpq)] do
241
241
  cp postgresql_lib, dest_libpq
@@ -290,12 +290,12 @@ task 'gem:windows' => ['ChangeLog'] do
290
290
 
291
291
  # Copy gem signing key and certs to be accessable from the docker container
292
292
  mkdir_p 'build/gem'
293
- sh "cp ~/.gem/gem-*.pem build/gem/"
293
+ sh "cp ~/.gem/gem-*.pem build/gem/ || true"
294
294
 
295
295
  RakeCompilerDock.sh <<-EOT
296
296
  mkdir ~/.gem &&
297
- cp build/gem/gem-*.pem ~/.gem/ &&
297
+ (cp build/gem/gem-*.pem ~/.gem/ || true) &&
298
298
  bundle install &&
299
- rake cross native gem RUBYOPT=--disable-rubygems RUBY_CC_VERSION=1.9.3:2.0.0:2.1.6:2.2.2
299
+ rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.6:2.0.0:1.9.3
300
300
  EOT
301
301
  end
@@ -198,6 +198,14 @@
198
198
  VALUE klass = define_error_class( "InvalidRowCountInResultOffsetClause", "22" );
199
199
  register_error_class( "2201X", klass );
200
200
  }
201
+ {
202
+ VALUE klass = define_error_class( "InvalidTablesampleArgument", "22" );
203
+ register_error_class( "2202H", klass );
204
+ }
205
+ {
206
+ VALUE klass = define_error_class( "InvalidTablesampleRepeat", "22" );
207
+ register_error_class( "2202G", klass );
208
+ }
201
209
  {
202
210
  VALUE klass = define_error_class( "InvalidTimeZoneDisplacementValue", "22" );
203
211
  register_error_class( "22009", klass );
@@ -466,6 +474,10 @@
466
474
  VALUE klass = define_error_class( "ERIESrfProtocolViolated", "39" );
467
475
  register_error_class( "39P02", klass );
468
476
  }
477
+ {
478
+ VALUE klass = define_error_class( "ERIEEventTriggerProtocolViolated", "39" );
479
+ register_error_class( "39P03", klass );
480
+ }
469
481
  {
470
482
  VALUE klass = define_error_class( "SavepointException", NULL );
471
483
  register_error_class( "3B000", klass );
@@ -916,6 +928,10 @@
916
928
  VALUE klass = define_error_class( "TooManyRows", "P0" );
917
929
  register_error_class( "P0003", klass );
918
930
  }
931
+ {
932
+ VALUE klass = define_error_class( "AssertFailure", "P0" );
933
+ register_error_class( "P0004", klass );
934
+ }
919
935
  {
920
936
  VALUE klass = define_error_class( "InternalError", NULL );
921
937
  register_error_class( "XX000", klass );
@@ -2,7 +2,7 @@
2
2
  # errcodes.txt
3
3
  # PostgreSQL error codes
4
4
  #
5
- # Copyright (c) 2003-2013, PostgreSQL Global Development Group
5
+ # Copyright (c) 2003-2016, PostgreSQL Global Development Group
6
6
  #
7
7
  # This list serves as the basis for generating source files containing error
8
8
  # codes. It is kept in a common format to make sure all these source files have
@@ -177,6 +177,8 @@ Section: Class 22 - Data Exception
177
177
  2201B E ERRCODE_INVALID_REGULAR_EXPRESSION invalid_regular_expression
178
178
  2201W E ERRCODE_INVALID_ROW_COUNT_IN_LIMIT_CLAUSE invalid_row_count_in_limit_clause
179
179
  2201X E ERRCODE_INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE invalid_row_count_in_result_offset_clause
180
+ 2202H E ERRCODE_INVALID_TABLESAMPLE_ARGUMENT invalid_tablesample_argument
181
+ 2202G E ERRCODE_INVALID_TABLESAMPLE_REPEAT invalid_tablesample_repeat
180
182
  22009 E ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE invalid_time_zone_displacement_value
181
183
  2200C E ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER invalid_use_of_escape_character
182
184
  2200G E ERRCODE_MOST_SPECIFIC_TYPE_MISMATCH most_specific_type_mismatch
@@ -278,6 +280,7 @@ Section: Class 39 - External Routine Invocation Exception
278
280
  39004 E ERRCODE_E_R_I_E_NULL_VALUE_NOT_ALLOWED null_value_not_allowed
279
281
  39P01 E ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED trigger_protocol_violated
280
282
  39P02 E ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED srf_protocol_violated
283
+ 39P03 E ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED event_trigger_protocol_violated
281
284
 
282
285
  Section: Class 3B - Savepoint Exception
283
286
 
@@ -454,6 +457,7 @@ P0000 E ERRCODE_PLPGSQL_ERROR plp
454
457
  P0001 E ERRCODE_RAISE_EXCEPTION raise_exception
455
458
  P0002 E ERRCODE_NO_DATA_FOUND no_data_found
456
459
  P0003 E ERRCODE_TOO_MANY_ROWS too_many_rows
460
+ P0004 E ERRCODE_ASSERT_FAILURE assert_failure
457
461
 
458
462
  Section: Class XX - Internal Error
459
463
 
@@ -24,7 +24,11 @@ if enable_config("windows-cross")
24
24
  else
25
25
  # Native build
26
26
 
27
- if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
27
+ pgconfig = with_config('pg-config') ||
28
+ with_config('pg_config') ||
29
+ find_executable('pg_config')
30
+
31
+ if pgconfig && pgconfig != 'ignore'
28
32
  $stderr.puts "Using config values from %s" % [ pgconfig ]
29
33
  incdir = `"#{pgconfig}" --includedir`.chomp
30
34
  libdir = `"#{pgconfig}" --libdir`.chomp
@@ -43,6 +47,9 @@ else
43
47
  end
44
48
  end
45
49
 
50
+ if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
51
+ append_cppflags( '-D__EXTENSIONS__' )
52
+ end
46
53
 
47
54
  find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
48
55
  find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
@@ -73,6 +80,7 @@ have_func 'PQlibVersion'
73
80
  have_func 'PQping'
74
81
  have_func 'PQsetSingleRowMode'
75
82
  have_func 'PQconninfo'
83
+ have_func 'PQsslAttribute'
76
84
 
77
85
  have_func 'rb_encdb_alias'
78
86
  have_func 'rb_enc_alias'
@@ -195,6 +195,9 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
195
195
  #define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
196
196
  param(PGconn *, conn)
197
197
 
198
+ #define FOR_EACH_PARAM_OF_PQsetClientEncoding(param) \
199
+ param(PGconn *, conn)
200
+
198
201
  #define FOR_EACH_PARAM_OF_PQisBusy(param)
199
202
 
200
203
  #define FOR_EACH_PARAM_OF_PQcancel(param) \
@@ -226,6 +229,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
226
229
  function(PQsendQueryPrepared, GVL_TYPE_NONVOID, int, int, resultFormat) \
227
230
  function(PQsendDescribePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
228
231
  function(PQsendDescribePortal, GVL_TYPE_NONVOID, int, const char *, portal) \
232
+ function(PQsetClientEncoding, GVL_TYPE_NONVOID, int, const char *, encoding) \
229
233
  function(PQisBusy, GVL_TYPE_NONVOID, int, PGconn *, conn) \
230
234
  function(PQcancel, GVL_TYPE_NONVOID, int, int, errbufsize);
231
235
 
data/ext/pg.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg.c - Toplevel extension
3
- * $Id: pg.c,v b60c89ee93c8 2015/02/11 20:59:36 lars $
3
+ * $Id$
4
4
  *
5
5
  * Author/s:
6
6
  *
data/ext/pg.h CHANGED
@@ -9,6 +9,9 @@
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 */
@@ -205,7 +208,7 @@ typedef struct {
205
208
  } t_pg_result;
206
209
 
207
210
 
208
- typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
211
+ typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *, int);
209
212
  typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
210
213
  typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
211
214
  typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
@@ -321,8 +324,8 @@ void init_pg_binary_decoder _(( void ));
321
324
  VALUE lookup_error_class _(( const char * ));
322
325
  VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
323
326
  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 *));
327
+ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *, int));
328
+ int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
326
329
  t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
327
330
  t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
328
331
  void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_decoder.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -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$
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 */
@@ -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 */