pg 0.18.0.pre20140820094244 → 0.18.0.pre20141017155815

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +1573 -2
  5. data/History.rdoc +3 -11
  6. data/Manifest.txt +24 -0
  7. data/README.rdoc +51 -4
  8. data/Rakefile +20 -14
  9. data/Rakefile.cross +39 -32
  10. data/ext/extconf.rb +27 -26
  11. data/ext/pg.c +75 -21
  12. data/ext/pg.h +194 -6
  13. data/ext/pg_binary_decoder.c +160 -0
  14. data/ext/pg_binary_encoder.c +160 -0
  15. data/ext/pg_coder.c +454 -0
  16. data/ext/pg_connection.c +815 -518
  17. data/ext/pg_copy_coder.c +557 -0
  18. data/ext/pg_result.c +258 -103
  19. data/ext/pg_text_decoder.c +424 -0
  20. data/ext/pg_text_encoder.c +608 -0
  21. data/ext/pg_type_map.c +113 -0
  22. data/ext/pg_type_map_all_strings.c +113 -0
  23. data/ext/pg_type_map_by_column.c +254 -0
  24. data/ext/pg_type_map_by_mri_type.c +266 -0
  25. data/ext/pg_type_map_by_oid.c +341 -0
  26. data/ext/util.c +121 -0
  27. data/ext/util.h +63 -0
  28. data/lib/pg.rb +11 -1
  29. data/lib/pg/basic_type_mapping.rb +377 -0
  30. data/lib/pg/coder.rb +74 -0
  31. data/lib/pg/connection.rb +38 -5
  32. data/lib/pg/result.rb +13 -3
  33. data/lib/pg/text_decoder.rb +42 -0
  34. data/lib/pg/text_encoder.rb +27 -0
  35. data/lib/pg/type_map_by_column.rb +15 -0
  36. data/spec/helpers.rb +9 -1
  37. data/spec/pg/basic_type_mapping_spec.rb +251 -0
  38. data/spec/pg/connection_spec.rb +232 -13
  39. data/spec/pg/result_spec.rb +52 -0
  40. data/spec/pg/type_map_by_column_spec.rb +135 -0
  41. data/spec/pg/type_map_by_mri_type_spec.rb +122 -0
  42. data/spec/pg/type_map_by_oid_spec.rb +133 -0
  43. data/spec/pg/type_map_spec.rb +39 -0
  44. data/spec/pg/type_spec.rb +620 -0
  45. metadata +40 -4
  46. metadata.gz.sig +0 -0
data/History.rdoc CHANGED
@@ -1,16 +1,8 @@
1
- == v0.18.0 [2014-08-20] Michael Granger <ged@FaerieMUD.org>
1
+ == v0.18.0 [unreleased]
2
2
 
3
- New:
4
-
5
- - Add PG::Connection#conninfo
6
- - Convert specs to expect syntax for RSpec 3
7
- - Check connection status with a matcher in specs
8
-
9
- Bugfixes:
10
-
11
- - Fix some type mismatches for Oid return values. Thanks to Mina Naguib for the fix.
12
- - Fix typo in documentation.
3
+ Enhancements:
13
4
 
5
+ - Add an extensible type cast system.
14
6
 
15
7
  == v0.17.1 [2013-12-18] Michael Granger <ged@FaerieMUD.org>
16
8
 
data/Manifest.txt CHANGED
@@ -20,17 +20,35 @@ ext/gvl_wrappers.c
20
20
  ext/gvl_wrappers.h
21
21
  ext/pg.c
22
22
  ext/pg.h
23
+ ext/pg_binary_decoder.c
24
+ ext/pg_binary_encoder.c
25
+ ext/pg_coder.c
23
26
  ext/pg_connection.c
27
+ ext/pg_copy_coder.c
24
28
  ext/pg_errors.c
25
29
  ext/pg_result.c
30
+ ext/pg_text_decoder.c
31
+ ext/pg_text_encoder.c
32
+ ext/pg_type_map_all_strings.c
33
+ ext/pg_type_map_by_column.c
34
+ ext/pg_type_map_by_mri_type.c
35
+ ext/pg_type_map_by_oid.c
36
+ ext/pg_type_map.c
37
+ ext/util.c
38
+ ext/util.h
26
39
  ext/vc/pg.sln
27
40
  ext/vc/pg_18/pg.vcproj
28
41
  ext/vc/pg_19/pg_19.vcproj
29
42
  lib/pg.rb
43
+ lib/pg/basic_type_mapping.rb
44
+ lib/pg/coder.rb
30
45
  lib/pg/connection.rb
31
46
  lib/pg/constants.rb
32
47
  lib/pg/exceptions.rb
33
48
  lib/pg/result.rb
49
+ lib/pg/text_decoder.rb
50
+ lib/pg/text_encoder.rb
51
+ lib/pg/type_map_by_column.rb
34
52
  sample/array_insert.rb
35
53
  sample/async_api.rb
36
54
  sample/async_copyto.rb
@@ -52,6 +70,12 @@ sample/warehouse_partitions.rb
52
70
  spec/data/expected_trace.out
53
71
  spec/data/random_binary_data
54
72
  spec/helpers.rb
73
+ spec/pg/basic_type_mapping_spec.rb
55
74
  spec/pg/connection_spec.rb
56
75
  spec/pg/result_spec.rb
76
+ spec/pg/type_map_by_column_spec.rb
77
+ spec/pg/type_map_by_mri_type_spec.rb
78
+ spec/pg/type_map_by_oid_spec.rb
79
+ spec/pg/type_map_spec.rb
80
+ spec/pg/type_spec.rb
57
81
  spec/pg_spec.rb
data/README.rdoc CHANGED
@@ -9,7 +9,7 @@ docs :: http://deveiate.org/code/pg
9
9
 
10
10
  Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
11
11
 
12
- It works with {PostgreSQL 9.0 and later}[http://www.postgresql.org/support/versioning/].
12
+ It works with {PostgreSQL 8.4 and later}[http://www.postgresql.org/support/versioning/].
13
13
 
14
14
  A small example usage:
15
15
 
@@ -34,8 +34,8 @@ A small example usage:
34
34
 
35
35
  == Requirements
36
36
 
37
- * Ruby 1.9.3 or later.
38
- * PostgreSQL 9.0.x or later (with headers, -dev packages, etc).
37
+ * Ruby 1.9.3-p392, or 2.0.0-p0.
38
+ * PostgreSQL 8.4.x or later (with headers, -dev packages, etc).
39
39
 
40
40
  It may work with earlier versions of Ruby/PostgreSQL as well, but those are
41
41
  not regularly tested.
@@ -64,6 +64,53 @@ There's also {a Google+ group}[http://goo.gl/TFy1U] and a
64
64
  want to chat about something.
65
65
 
66
66
 
67
+ == Type Casts
68
+
69
+ Pg can optionally type cast result values and query parameters in Ruby or
70
+ native C code. This can speed up data transfers to and from the database,
71
+ because String allocations are reduced and conversions in (slower) Ruby code
72
+ can be omitted.
73
+
74
+ Very basic type casting can be enabled by:
75
+
76
+ conn.type_map_for_results = PG::BasicTypeMapForResults.new conn
77
+ # ... this works for result value mapping:
78
+ conn.exec("select 1, now(), '{2,3}'::int[]").values
79
+ # => [[1, 2014-09-21 20:51:56 +0200, [2, 3]]]
80
+
81
+ conn.type_map_for_queries = PG::BasicTypeMapForQueries.new conn
82
+ # ... and this for param value mapping:
83
+ conn.exec_params("SELECT $1::text, $2::text, $3::text", [1, 1.23, [2,3]]).values
84
+ # => [["1", "1.2300000000000000E+00", "{2,3}"]]
85
+
86
+ But Pg's type casting is highly customizable. That's why it's divided into
87
+ 2 layers:
88
+
89
+ === Encoders / Decoders (ext/pg_*coder.c, lib/pg/*coder.rb)
90
+
91
+ This is the lower layer, containing encoding classes that convert Ruby
92
+ objects for transmission to the DBMS and decoding classes to convert
93
+ received data back to Ruby objects. The classes are namespaced according
94
+ to their format and direction in PG::TextEncoder, PG::TextDecoder,
95
+ PG::BinaryEncoder and PG::BinaryDecoder.
96
+
97
+ It is possible to assign a type OID, format code (text or binary) and
98
+ optionally a name to an encoder or decoder object. It's also possible
99
+ to build composite types by assigning an element encoder/decoder.
100
+ PG::Coder objects can be used to set up a PG::TypeMap or alternatively
101
+ to convert single values to/from their string representation.
102
+
103
+ === PG::TypeMap and derivations (ext/pg_type_map*.c, lib/pg/type_map*.rb)
104
+
105
+ A TypeMap defines which value will be converted by which encoder/decoder.
106
+ There are different type map strategies, implemented by several derivations
107
+ of this class. They can be chosen and configured according to the particular
108
+ needs for type casting.
109
+
110
+ A type map can be assigned per connection or per query respectively per
111
+ result set. Type maps can also be used for COPY in and out data streaming.
112
+
113
+
67
114
  == Contributing
68
115
 
69
116
  To report bugs, suggest features, or check out the source with Mercurial,
@@ -83,7 +130,7 @@ Lars Kanis <lars@greiz-reinsdorf.de>.
83
130
 
84
131
  == Copying
85
132
 
86
- Copyright (c) 1997-2014 by the authors.
133
+ Copyright (c) 1997-2013 by the authors.
87
134
 
88
135
  * Jeff Davis <ruby-pg@j-davis.com>
89
136
  * Guy Decoux (ts) <decoux@moulon.inra.fr>
data/Rakefile CHANGED
@@ -29,10 +29,10 @@ TMPDIR = BASEDIR + 'tmp'
29
29
  DLEXT = RbConfig::CONFIG['DLEXT']
30
30
  EXT = LIBDIR + "pg_ext.#{DLEXT}"
31
31
 
32
- TEST_DIRECTORY = BASEDIR + "tmp_test_specs"
33
-
34
32
  GEMSPEC = 'pg.gemspec'
35
33
 
34
+ TEST_DIRECTORY = BASEDIR + "tmp_test_specs"
35
+
36
36
  CLOBBER.include( TEST_DIRECTORY.to_s )
37
37
  CLEAN.include( PKGDIR.to_s, TMPDIR.to_s )
38
38
 
@@ -69,7 +69,7 @@ $hoespec = Hoe.spec 'pg' do
69
69
  self.spec_extras[:licenses] = ['BSD', 'Ruby', 'GPL']
70
70
  self.spec_extras[:extensions] = [ 'ext/extconf.rb' ]
71
71
 
72
- self.require_ruby_version( '>= 1.9.3' )
72
+ self.require_ruby_version( '>= 1.8.7' )
73
73
 
74
74
  self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
75
75
  self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
@@ -122,16 +122,23 @@ Rake::ExtensionTask.new do |ext|
122
122
  ext.cross_compile = true
123
123
  ext.cross_platform = CrossLibraries.map &:for_platform
124
124
 
125
- ext.cross_config_options += CrossLibraries.map do |lib|
126
- {
127
- lib.for_platform => [
128
- "--with-pg-include=#{lib.static_postgresql_libdir}",
129
- "--with-opt-include=#{lib.static_postgresql_incdir}",
130
- "--with-pg-lib=#{lib.static_postgresql_libdir}",
131
- "--with-opt-lib=#{lib.static_openssl_builddir}",
132
- ]
133
- }
134
- end
125
+ ext.cross_config_options += CrossLibraries.map do |lib|
126
+ {
127
+ lib.for_platform => [
128
+ "--enable-windows-cross",
129
+ "--with-pg-include=#{lib.static_postgresql_incdir}",
130
+ "--with-pg-lib=#{lib.static_postgresql_libdir}",
131
+ # libpq-fe.h resides in src/interfaces/libpq/ before make install
132
+ "--with-opt-include=#{lib.static_postgresql_libdir}",
133
+ ]
134
+ }
135
+ end
136
+
137
+ # Add libpq.dll to windows binary gemspec
138
+ ext.cross_compiling do |spec|
139
+ # mingw32-platform strings differ (RUBY_PLATFORM=i386-mingw32 vs. x86-mingw32 for rubygems)
140
+ spec.files << "lib/#{spec.platform.to_s.gsub(/^x86-/, "i386-")}/libpq.dll"
141
+ end
135
142
  end
136
143
 
137
144
 
@@ -183,7 +190,6 @@ file 'ext/pg_errors.c' => ['ext/errorcodes.def'] do
183
190
  touch 'ext/pg_errors.c'
184
191
  end
185
192
 
186
-
187
193
  task :gemspec => GEMSPEC
188
194
  file GEMSPEC => __FILE__
189
195
  task GEMSPEC do |task|
data/Rakefile.cross CHANGED
@@ -28,8 +28,8 @@ class CrossLibrary < OpenStruct
28
28
  self.openssl_config = openssl_config
29
29
 
30
30
  # Cross-compilation constants
31
- self.openssl_version = ENV['OPENSSL_VERSION'] || '1.0.1e'
32
- self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '9.2.3'
31
+ self.openssl_version = ENV['OPENSSL_VERSION'] || '1.0.1i'
32
+ self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '9.3.5'
33
33
 
34
34
  self.compile_home = Pathname( "./build" ).expand_path
35
35
  self.static_sourcesdir = compile_home + 'sources'
@@ -64,7 +64,7 @@ class CrossLibrary < OpenStruct
64
64
  self.postgresql_global_makefile = static_postgresql_srcdir + 'Makefile.global'
65
65
  self.postgresql_shlib_makefile = static_postgresql_srcdir + 'Makefile.shlib'
66
66
  self.postgresql_shlib_mf_orig = static_postgresql_srcdir + 'Makefile.shlib.orig'
67
- self.postgresql_lib = static_postgresql_libdir + 'libpq.a'
67
+ self.postgresql_lib = static_postgresql_libdir + 'libpq.dll'
68
68
  self.postgresql_patches = Rake::FileList[ (MISCDIR + "postgresql-#{postgresql_version}.*.patch").to_s ]
69
69
 
70
70
  # Use rake-compilers config.yml to determine the toolchain that was used
@@ -82,7 +82,7 @@ class CrossLibrary < OpenStruct
82
82
  CLEAN.include( static_builddir.to_s )
83
83
 
84
84
 
85
- ENV['RUBY_CC_VERSION'] ||= '1.8.7:1.9.3:2.0.0'
85
+ ENV['RUBY_CC_VERSION'] ||= '1.9.3:2.0.0'
86
86
 
87
87
  def download(url, save_to)
88
88
  part = save_to+".part"
@@ -136,7 +136,7 @@ class CrossLibrary < OpenStruct
136
136
 
137
137
  # generate the makefile in a clean build location
138
138
  file openssl_makefile => static_openssl_builddir do |t|
139
- Dir.chdir( static_openssl_builddir ) do
139
+ chdir( static_openssl_builddir ) do
140
140
  cmd = cmd_prelude.dup
141
141
  cmd << "./Configure" << openssl_config
142
142
 
@@ -148,7 +148,7 @@ class CrossLibrary < OpenStruct
148
148
  task :openssl_libs => [ libssleay32, libeay32 ]
149
149
 
150
150
  task :compile_static_openssl => openssl_makefile do |t|
151
- Dir.chdir( static_openssl_builddir ) do
151
+ chdir( static_openssl_builddir ) do
152
152
  cmd = cmd_prelude.dup
153
153
  cmd << 'make' << "-j#{NUM_CPUS}" << 'build_libs'
154
154
 
@@ -184,7 +184,6 @@ class CrossLibrary < OpenStruct
184
184
  puts "extracting %s to %s" % [ postgresql_tarball, static_postgresql_builddir.parent ]
185
185
  static_postgresql_builddir.mkpath
186
186
  run 'tar', '-xjf', postgresql_tarball.to_s, '-C', static_postgresql_builddir.parent.to_s
187
- mv postgresql_shlib_makefile, postgresql_shlib_mf_orig
188
187
 
189
188
  postgresql_patches.each do |patchfile|
190
189
  puts " applying patch #{patchfile}..."
@@ -200,10 +199,9 @@ class CrossLibrary < OpenStruct
200
199
  "--host=#{host_platform}",
201
200
  '--with-openssl',
202
201
  '--without-zlib',
203
- '--disable-shared',
204
202
  ]
205
203
 
206
- Dir.chdir( static_postgresql_builddir ) do
204
+ chdir( static_postgresql_builddir ) do
207
205
  configure_path = static_postgresql_builddir + 'configure'
208
206
  cmd = [ configure_path.to_s, *options ]
209
207
  cmd << "CFLAGS=-L#{static_openssl_builddir}"
@@ -217,31 +215,32 @@ class CrossLibrary < OpenStruct
217
215
  end
218
216
 
219
217
 
220
- # patch the Makefile.shlib -- depend on the build dir so it's only
221
- # rewritten if the tarball is re-extracted.
222
- file postgresql_shlib_makefile => postgresql_shlib_mf_orig do |t|
223
- tf = Tempfile.new( postgresql_shlib_makefile.basename.to_s )
224
- postgresql_shlib_mf_orig.open( File::RDONLY ) do |ifh|
225
- ifh.each_line do |line|
226
- tf.print( line.sub(/^(\s*haslibarule\s*=\s*yes)/, "# \\1 ") )
227
- end
218
+ # make libpq.dll
219
+ task postgresql_lib => [ postgresql_global_makefile ] do |t|
220
+ chdir( postgresql_lib.dirname ) do
221
+ sh 'make',
222
+ "-j#{NUM_CPUS}",
223
+ postgresql_lib.basename.to_s,
224
+ 'SHLIB_LINK=-lssleay32 -leay32 -lcrypt32 -lgdi32 -lsecur32 -lwsock32 -lws2_32'
228
225
  end
229
- tf.close
230
-
231
- FileUtils.mv( tf.path, t.name, :verbose => $puts )
232
226
  end
233
227
 
234
228
 
235
- # make libpq.a
236
- task postgresql_lib => [ postgresql_global_makefile, postgresql_shlib_makefile ] do |t|
237
- Dir.chdir( postgresql_lib.dirname ) do
238
- sh 'make', "-j#{NUM_CPUS}", postgresql_lib.basename.to_s, 'PORTNAME=win32'
239
- end
240
- end
229
+ #desc 'compile libpg.a'
230
+ task :libpq => postgresql_lib
241
231
 
232
+ # copy libpq.dll to lib dir
233
+ dest_libpq = "lib/#{for_platform}/#{postgresql_lib.basename}"
234
+ directory File.dirname(dest_libpq)
235
+ file dest_libpq => [postgresql_lib, File.dirname(dest_libpq)] do
236
+ cp postgresql_lib, dest_libpq
237
+ end
242
238
 
243
- #desc 'compile static libpg.a'
244
- task :static_libpq => postgresql_lib
239
+ stage_libpq = "tmp/#{for_platform}/stage/#{dest_libpq}"
240
+ directory File.dirname(stage_libpq)
241
+ file stage_libpq => [postgresql_lib, File.dirname(stage_libpq)] do |t|
242
+ cp postgresql_lib, stage_libpq
243
+ end
245
244
  end
246
245
  end
247
246
 
@@ -258,10 +257,7 @@ else
258
257
  end
259
258
 
260
259
  desc 'cross compile pg for win32'
261
- task :cross do
262
- ENV['CROSS_COMPILING'] = 'yes'
263
- end
264
- task :cross => [ :mingw32, :static_libpq ]
260
+ task :cross => [ :mingw32, :libpq ]
265
261
 
266
262
  task :mingw32 do
267
263
  # Use Rake::ExtensionCompiler helpers to find the proper host
@@ -271,3 +267,14 @@ task :mingw32 do
271
267
  fail
272
268
  end
273
269
  end
270
+
271
+ # To reduce the gem file size strip mingw32 dlls before packaging
272
+ ENV['RUBY_CC_VERSION'].to_s.split(':').each do |ruby_version|
273
+ task "tmp/i386-mingw32/stage/lib/#{ruby_version[/^\d+\.\d+/]}/pg_ext.so" do |t|
274
+ sh "i686-w64-mingw32-strip -S tmp/i386-mingw32/stage/lib/#{ruby_version[/^\d+\.\d+/]}/pg_ext.so"
275
+ end
276
+
277
+ task "tmp/x64-mingw32/stage/lib/#{ruby_version[/^\d+\.\d+/]}/pg_ext.so" do |t|
278
+ sh "x86_64-w64-mingw32-strip -S tmp/x64-mingw32/stage/lib/#{ruby_version[/^\d+\.\d+/]}/pg_ext.so"
279
+ end
280
+ end
data/ext/extconf.rb CHANGED
@@ -15,36 +15,35 @@ if pgdir = with_config( 'pg' )
15
15
  ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
16
16
  end
17
17
 
18
- if ENV['CROSS_COMPILING']
19
- $LDFLAGS << " -L#{CONFIG['libdir']}"
20
-
21
- # Link against all required libraries for static build, if they are available
22
- have_library( 'crypt32', 'CertOpenStore' ) && append_library( $libs, 'crypt32' )
23
- have_library( 'gdi32', 'CreateDC' ) && append_library( $libs, 'gdi32' )
24
- have_library( 'secur32' ) && append_library( $libs, 'secur32' )
25
- have_library( 'ws2_32', 'WSASocket') && append_library( $libs, 'ws2_32' )
26
- have_library( 'crypto', 'BIO_new' ) && append_library( $libs, 'crypto' )
27
- have_library( 'ssl', 'SSL_new' ) && append_library( $libs, 'ssl' )
28
- end
18
+ if enable_config("windows-cross")
19
+ # Avoid dependency to external libgcc.dll on x86-mingw32
20
+ $LDFLAGS << " -static-libgcc"
21
+ # Don't use pg_config for cross build, but --with-pg-* path options
22
+ dir_config 'pg'
29
23
 
30
- if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
31
- $stderr.puts "Using config values from %s" % [ pgconfig ]
32
- incdir = `"#{pgconfig}" --includedir`.chomp
33
- libdir = `"#{pgconfig}" --libdir`.chomp
34
- dir_config 'pg', incdir, libdir
35
-
36
- # Try to use runtime path linker option, even if RbConfig doesn't know about it.
37
- # The rpath option is usually set implicit by dir_config(), but so far not
38
- # on MacOS-X.
39
- if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
40
- $LDFLAGS << " -Wl,-rpath,#{libdir}"
41
- end
42
24
  else
43
- $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
44
- " --with-pg-config=/path/to/pg_config"
45
- dir_config 'pg'
25
+ # Native build
26
+
27
+ if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
28
+ $stderr.puts "Using config values from %s" % [ pgconfig ]
29
+ incdir = `"#{pgconfig}" --includedir`.chomp
30
+ libdir = `"#{pgconfig}" --libdir`.chomp
31
+ dir_config 'pg', incdir, libdir
32
+
33
+ # Try to use runtime path linker option, even if RbConfig doesn't know about it.
34
+ # The rpath option is usually set implicit by dir_config(), but so far not
35
+ # on MacOS-X.
36
+ if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
37
+ $LDFLAGS << " -Wl,-rpath,#{libdir}"
38
+ end
39
+ else
40
+ $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
41
+ " --with-pg-config=/path/to/pg_config"
42
+ dir_config 'pg'
43
+ end
46
44
  end
47
45
 
46
+
48
47
  find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
49
48
  find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
50
49
  find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
@@ -73,6 +72,7 @@ have_func 'PQsetClientEncoding'
73
72
  have_func 'PQlibVersion'
74
73
  have_func 'PQping'
75
74
  have_func 'PQsetSingleRowMode'
75
+ have_func 'PQconninfo'
76
76
 
77
77
  have_func 'rb_encdb_alias'
78
78
  have_func 'rb_enc_alias'
@@ -80,6 +80,7 @@ have_func 'rb_thread_call_without_gvl'
80
80
  have_func 'rb_thread_call_with_gvl'
81
81
  have_func 'rb_thread_fd_select'
82
82
  have_func 'rb_w32_wrap_io_handle'
83
+ have_func 'rb_str_modify_expand'
83
84
 
84
85
  have_const 'PGRES_COPY_BOTH', 'libpq-fe.h'
85
86
  have_const 'PGRES_SINGLE_TUPLE', 'libpq-fe.h'
data/ext/pg.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg.c - Toplevel extension
3
- * $Id: pg.c,v 8e95248e80f6 2014/08/20 16:42:14 ged $
3
+ * $Id: pg.c,v c2e817ef9b8c 2014/09/27 16:40:13 lars $
4
4
  *
5
5
  * Author/s:
6
6
  *
@@ -15,7 +15,7 @@
15
15
  * See Contributors.rdoc for the many additional fine people that have contributed
16
16
  * to this library over the years.
17
17
  *
18
- * Copyright (c) 1997-2014 by the authors.
18
+ * Copyright (c) 1997-2012 by the authors.
19
19
  *
20
20
  * You may redistribute this software under the same terms as Ruby itself; see
21
21
  * http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
@@ -123,24 +123,6 @@ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
123
123
  * A cache of mapping from PostgreSQL's encoding indices to Ruby's rb_encoding*s.
124
124
  */
125
125
  static struct st_table *enc_pg2ruby;
126
- static ID s_id_index;
127
-
128
-
129
- /*
130
- * Get the index of encoding +val+.
131
- * :FIXME: Look into replacing this with rb_enc_get_index() since 1.9.1 isn't really
132
- * used anymore.
133
- */
134
- int
135
- pg_enc_get_index(VALUE val)
136
- {
137
- int i = ENCODING_GET_INLINED(val);
138
- if (i == ENCODING_INLINE_MAX) {
139
- VALUE iv = rb_ivar_get(val, s_id_index);
140
- i = NUM2INT(iv);
141
- }
142
- return i;
143
- }
144
126
 
145
127
 
146
128
  /*
@@ -249,6 +231,68 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
249
231
  #endif /* M17N_SUPPORTED */
250
232
 
251
233
 
234
+ /*
235
+ * Ensures that the given string has enough capacity to take expand_len
236
+ * more data bytes. The new data part of the String is not initialized.
237
+ *
238
+ * current_out must be a pointer within the data part of the String object.
239
+ * This pointer is returned and possibly adjusted, because the location of the data
240
+ * part of the String can change through this function.
241
+ *
242
+ * PG_RB_STR_ENSURE_CAPA can be used to do fast inline checks of the remaining capacity.
243
+ * end_capa it is then set to the first byte after the currently reserved memory,
244
+ * if not NULL.
245
+ *
246
+ * Before the String can be used with other string functions or returned to Ruby space,
247
+ * the string length has to be set with rb_str_set_len().
248
+ *
249
+ * Usage example:
250
+ *
251
+ * VALUE string;
252
+ * char *current_out, *end_capa;
253
+ * PG_RB_STR_NEW( string, current_out, end_capa );
254
+ * while( data_is_going_to_be_processed ){
255
+ * PG_RB_STR_ENSURE_CAPA( string, 2 current_out, end_capa );
256
+ * *current_out++ = databyte1;
257
+ * *current_out++ = databyte2;
258
+ * }
259
+ * rb_str_set_len( string, current_out - RSTRING_PTR(string) );
260
+ *
261
+ */
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;
292
+ }
293
+ #endif
294
+
295
+
252
296
  /**************************************************************************
253
297
  * Module Methods
254
298
  **************************************************************************/
@@ -534,12 +578,22 @@ Init_pg_ext()
534
578
 
535
579
  #ifdef M17N_SUPPORTED
536
580
  enc_pg2ruby = st_init_numtable();
537
- s_id_index = rb_intern("@encoding");
538
581
  #endif
539
582
 
540
583
  /* Initialize the main extension classes */
541
584
  init_pg_connection();
542
585
  init_pg_result();
543
586
  init_pg_errors();
587
+ init_pg_type_map();
588
+ init_pg_type_map_all_strings();
589
+ init_pg_type_map_by_column();
590
+ init_pg_type_map_by_mri_type();
591
+ init_pg_type_map_by_oid();
592
+ init_pg_coder();
593
+ init_pg_text_encoder();
594
+ init_pg_text_decoder();
595
+ init_pg_binary_encoder();
596
+ init_pg_binary_decoder();
597
+ init_pg_copycoder();
544
598
  }
545
599