pg 0.11.0-x86-mingw32 → 0.12.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/.gemtest +0 -0
  2. data/ChangeLog +1647 -462
  3. data/Contributors.rdoc +39 -0
  4. data/History.rdoc +61 -0
  5. data/Manifest.txt +43 -0
  6. data/README.OS_X.rdoc +68 -0
  7. data/README.ja.rdoc +7 -0
  8. data/{README → README.rdoc} +38 -18
  9. data/{README.windows → README.windows.rdoc} +23 -31
  10. data/Rakefile +104 -318
  11. data/Rakefile.cross +234 -0
  12. data/ext/compat.c +2 -2
  13. data/ext/extconf.rb +10 -2
  14. data/ext/pg.c +223 -43
  15. data/ext/vc/pg.sln +26 -0
  16. data/ext/vc/pg_18/pg.vcproj +216 -0
  17. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  18. data/lib/1.8/pg_ext.so +0 -0
  19. data/lib/1.9/pg_ext.so +0 -0
  20. data/lib/pg.rb +5 -7
  21. data/misc/openssl-pg-segfault.rb +31 -0
  22. data/sample/async_api.rb +109 -0
  23. data/sample/async_copyto.rb +39 -0
  24. data/sample/copyfrom.rb +81 -0
  25. data/sample/copyto.rb +19 -0
  26. data/sample/cursor.rb +21 -0
  27. data/sample/losample.rb +69 -0
  28. data/sample/notify_wait.rb +43 -0
  29. data/sample/psql.rb +1181 -0
  30. data/sample/psqlHelp.rb +158 -0
  31. data/sample/test1.rb +60 -0
  32. data/sample/test2.rb +44 -0
  33. data/sample/test4.rb +71 -0
  34. data/sample/test_binary_values.rb +35 -0
  35. data/spec/lib/helpers.rb +6 -4
  36. data/spec/m17n_spec.rb +2 -2
  37. data/spec/pgconn_spec.rb +51 -6
  38. data/spec/pgresult_spec.rb +30 -4
  39. metadata +147 -86
  40. data.tar.gz.sig +0 -3
  41. data/Contributors +0 -32
  42. data/README.OS_X +0 -19
  43. data/README.ja +0 -183
  44. data/Rakefile.local +0 -312
  45. data/rake/191_compat.rb +0 -26
  46. data/rake/dependencies.rb +0 -76
  47. data/rake/documentation.rb +0 -123
  48. data/rake/helpers.rb +0 -502
  49. data/rake/hg.rb +0 -318
  50. data/rake/manual.rb +0 -787
  51. data/rake/packaging.rb +0 -129
  52. data/rake/publishing.rb +0 -341
  53. data/rake/style.rb +0 -62
  54. data/rake/svn.rb +0 -668
  55. data/rake/testing.rb +0 -152
  56. data/rake/verifytask.rb +0 -64
  57. metadata.gz.sig +0 -3
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'uri'
4
+ require 'tempfile'
5
+ require 'rbconfig'
6
+ require 'rake/clean'
7
+ require 'rake/extensiontask'
8
+ require 'rake/extensioncompiler'
9
+
10
+ MISCDIR = BASEDIR + 'misc'
11
+
12
+ NUM_CPUS = if File.exist?('/proc/cpuinfo')
13
+ File.read('/proc/cpuinfo').scan('processor').length
14
+ elsif RUBY_PLATFORM.include?( 'darwin' )
15
+ `system_profiler SPHardwareDataType | grep 'Cores' | awk '{print $5}'`.chomp
16
+ else
17
+ 1
18
+ end
19
+
20
+ # Cross-compilation constants
21
+ OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '1.0.0e'
22
+ POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '9.1.1'
23
+
24
+ COMPILE_HOME = Pathname( "./build" ).expand_path
25
+ STATIC_SOURCESDIR = COMPILE_HOME + 'sources'
26
+ STATIC_BUILDDIR = COMPILE_HOME + 'builds'
27
+
28
+ # Static OpenSSL build vars
29
+ STATIC_OPENSSL_BUILDDIR = STATIC_BUILDDIR + "openssl-#{OPENSSL_VERSION}"
30
+
31
+ OPENSSL_SOURCE_URI =
32
+ URI( "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz" )
33
+ OPENSSL_TARBALL = STATIC_SOURCESDIR + File.basename( OPENSSL_SOURCE_URI.path )
34
+ OPENSSL_MAKEFILE = STATIC_OPENSSL_BUILDDIR + 'Makefile'
35
+
36
+ LIBSSLEAY32 = STATIC_OPENSSL_BUILDDIR + 'libssleay32.a'
37
+ LIBEAY32 = STATIC_OPENSSL_BUILDDIR + 'libeay32.a'
38
+
39
+ OPENSSL_PATCHES = Rake::FileList[ MISCDIR + "openssl-#{OPENSSL_VERSION}.*.patch" ]
40
+
41
+ # Static PostgreSQL build vars
42
+ STATIC_POSTGRESQL_BUILDDIR = STATIC_BUILDDIR + "postgresql-#{POSTGRESQL_VERSION}"
43
+ POSTGRESQL_SOURCE_URI = begin
44
+ uristring = "http://ftp9.us.postgresql.org/pub/mirrors/postgresql/source/" +
45
+ "v%s/postgresql-%s.tar.bz2" % [ POSTGRESQL_VERSION, POSTGRESQL_VERSION ]
46
+ URI( uristring )
47
+ end
48
+ POSTGRESQL_TARBALL = STATIC_SOURCESDIR + File.basename( POSTGRESQL_SOURCE_URI.path )
49
+
50
+ STATIC_POSTGRESQL_SRCDIR = STATIC_POSTGRESQL_BUILDDIR + 'src'
51
+ STATIC_POSTGRESQL_LIBDIR = STATIC_POSTGRESQL_SRCDIR + 'interfaces/libpq'
52
+ STATIC_POSTGRESQL_INCDIR = STATIC_POSTGRESQL_SRCDIR + 'include'
53
+
54
+ POSTGRESQL_GLOBAL_MAKEFILE = STATIC_POSTGRESQL_SRCDIR + 'Makefile.global'
55
+ POSTGRESQL_SHLIB_MAKEFILE = STATIC_POSTGRESQL_SRCDIR + 'Makefile.shlib'
56
+ POSTGRESQL_SHLIB_MF_ORIG = STATIC_POSTGRESQL_SRCDIR + 'Makefile.shlib.orig'
57
+ POSTGRESQL_LIB = STATIC_POSTGRESQL_LIBDIR + 'libpq.a'
58
+
59
+ CROSS_PREFIX = Rake::ExtensionCompiler.mingw_host
60
+
61
+
62
+ # clean intermediate files and folders
63
+ CLEAN.include( STATIC_BUILDDIR.to_s )
64
+
65
+
66
+ ENV['RUBY_CC_VERSION'] ||= '1.8.7:1.9.3'
67
+
68
+ def download(url, save_to)
69
+ part = save_to+".part"
70
+ sh "wget #{url.to_s.inspect} -O #{part.inspect} || curl #{url.to_s.inspect} -o #{part.inspect}"
71
+ FileUtils.mv part, save_to
72
+ end
73
+
74
+ def run(*args)
75
+ sh *args
76
+ end
77
+
78
+ #####################################################################
79
+ ### C R O S S - C O M P I L A T I O N - T A S K S
80
+ #####################################################################
81
+
82
+
83
+ directory STATIC_SOURCESDIR.to_s
84
+
85
+ #
86
+ # Static OpenSSL build tasks
87
+ #
88
+ directory STATIC_OPENSSL_BUILDDIR.to_s
89
+
90
+ # openssl source file should be stored there
91
+ file OPENSSL_TARBALL => STATIC_SOURCESDIR do |t|
92
+ download( OPENSSL_SOURCE_URI, t.name )
93
+ end
94
+
95
+ # Extract the openssl builds
96
+ file STATIC_OPENSSL_BUILDDIR => OPENSSL_TARBALL do |t|
97
+ puts "extracting %s to %s" % [ OPENSSL_TARBALL, STATIC_OPENSSL_BUILDDIR.parent ]
98
+ STATIC_OPENSSL_BUILDDIR.mkpath
99
+ run 'tar', '-xzf', OPENSSL_TARBALL.to_s, '-C', STATIC_OPENSSL_BUILDDIR.parent.to_s
100
+ OPENSSL_MAKEFILE.unlink if OPENSSL_MAKEFILE.exist?
101
+
102
+ OPENSSL_PATCHES.each do |patchfile|
103
+ puts " applying patch #{patchfile}..."
104
+ run 'patch', '-Np1', '-d', STATIC_OPENSSL_BUILDDIR.to_s,
105
+ '-i', File.expand_path( patchfile, BASEDIR )
106
+ end
107
+ end
108
+
109
+ CMD_PRELUDE = [
110
+ 'env',
111
+ "CC=#{CROSS_PREFIX}-gcc",
112
+ "CFLAGS=-DDSO_WIN32",
113
+ "AR=#{CROSS_PREFIX}-ar",
114
+ "RANLIB=#{CROSS_PREFIX}-ranlib"
115
+ ]
116
+
117
+
118
+ # generate the makefile in a clean build location
119
+ file OPENSSL_MAKEFILE => STATIC_OPENSSL_BUILDDIR do |t|
120
+ Dir.chdir( STATIC_OPENSSL_BUILDDIR ) do
121
+ cmd = CMD_PRELUDE.dup
122
+ cmd << "./Configure" << 'mingw'
123
+
124
+ run( *cmd )
125
+ end
126
+ end
127
+
128
+ desc "compile static openssl libraries"
129
+ task :openssl_libs => [ LIBSSLEAY32, LIBEAY32 ]
130
+
131
+ task :compile_static_openssl => OPENSSL_MAKEFILE do |t|
132
+ Dir.chdir( STATIC_OPENSSL_BUILDDIR ) do
133
+ cmd = CMD_PRELUDE.dup
134
+ cmd << 'make' << "-j#{NUM_CPUS}" << 'build_libs'
135
+
136
+ run( *cmd )
137
+ end
138
+ end
139
+
140
+ desc "compile static #{LIBEAY32}"
141
+ file LIBEAY32 => :compile_static_openssl do |t|
142
+ FileUtils.cp( STATIC_OPENSSL_BUILDDIR + 'libcrypto.a', LIBEAY32.to_s )
143
+ end
144
+
145
+ desc "compile static #{LIBSSLEAY32}"
146
+ file LIBSSLEAY32 => :compile_static_openssl do |t|
147
+ FileUtils.cp( STATIC_OPENSSL_BUILDDIR + 'libssl.a', LIBSSLEAY32.to_s )
148
+ end
149
+
150
+
151
+
152
+ #
153
+ # Static PostgreSQL build tasks
154
+ #
155
+ directory STATIC_POSTGRESQL_BUILDDIR.to_s
156
+
157
+
158
+ # postgresql source file should be stored there
159
+ file POSTGRESQL_TARBALL => STATIC_SOURCESDIR do |t|
160
+ download( POSTGRESQL_SOURCE_URI, t.name )
161
+ end
162
+
163
+ # Extract the postgresql sources
164
+ file STATIC_POSTGRESQL_BUILDDIR => POSTGRESQL_TARBALL do |t|
165
+ puts "extracting %s to %s" % [ POSTGRESQL_TARBALL, STATIC_POSTGRESQL_BUILDDIR.parent ]
166
+ STATIC_POSTGRESQL_BUILDDIR.mkpath
167
+ run 'tar', '-xjf', POSTGRESQL_TARBALL.to_s, '-C', STATIC_POSTGRESQL_BUILDDIR.parent.to_s
168
+ mv POSTGRESQL_SHLIB_MAKEFILE, POSTGRESQL_SHLIB_MF_ORIG
169
+ end
170
+
171
+ # generate the makefile in a clean build location
172
+ file POSTGRESQL_GLOBAL_MAKEFILE => [ STATIC_POSTGRESQL_BUILDDIR, :openssl_libs ] do |t|
173
+ options = [
174
+ '--target=i386-mingw32',
175
+ "--host=#{Rake::ExtensionCompiler.mingw_host}",
176
+ '--with-openssl',
177
+ '--without-zlib',
178
+ '--disable-shared',
179
+ ]
180
+
181
+ Dir.chdir( STATIC_POSTGRESQL_BUILDDIR ) do
182
+ configure_path = STATIC_POSTGRESQL_BUILDDIR + 'configure'
183
+ cmd = [ configure_path.to_s, *options ]
184
+ cmd << "CFLAGS=-L#{STATIC_OPENSSL_BUILDDIR}"
185
+ cmd << "LDFLAGS=-L#{STATIC_OPENSSL_BUILDDIR}"
186
+ cmd << "LDFLAGS_SL=-L#{STATIC_OPENSSL_BUILDDIR}"
187
+ cmd << "LIBS=-lwsock32 -lws2_32 -lgdi32"
188
+ cmd << "CPPFLAGS=-I#{STATIC_OPENSSL_BUILDDIR}/include"
189
+
190
+ run( *cmd )
191
+ end
192
+ end
193
+
194
+
195
+ # patch the Makefile.shlib -- depend on the build dir so it's only
196
+ # rewritten if the tarball is re-extracted.
197
+ file POSTGRESQL_SHLIB_MAKEFILE => POSTGRESQL_SHLIB_MF_ORIG do |t|
198
+ tf = Tempfile.new( POSTGRESQL_SHLIB_MAKEFILE.basename )
199
+ POSTGRESQL_SHLIB_MF_ORIG.open( File::RDONLY ) do |ifh|
200
+ ifh.each_line do |line|
201
+ tf.print( line.sub(/^(\s*haslibarule\s*=\s*yes)/, "# \\1 ") )
202
+ end
203
+ end
204
+ tf.close
205
+
206
+ FileUtils.mv( tf.path, t.name, :verbose => $puts )
207
+ end
208
+
209
+
210
+ # make libpq.a
211
+ task POSTGRESQL_LIB => [ POSTGRESQL_GLOBAL_MAKEFILE, POSTGRESQL_SHLIB_MAKEFILE ] do |t|
212
+ Dir.chdir( POSTGRESQL_LIB.dirname ) do
213
+ sh 'make', "-j#{NUM_CPUS}", POSTGRESQL_LIB.basename.to_s, 'PORTNAME=win32'
214
+ end
215
+ end
216
+
217
+
218
+ #desc 'compile static libpg.a'
219
+ task :static_libpq => POSTGRESQL_LIB
220
+
221
+ desc 'cross compile pg for win32'
222
+ task :cross do
223
+ ENV['CROSS_COMPILING'] = 'yes'
224
+ end
225
+ task :cross => [ :mingw32, :static_libpq ]
226
+
227
+ task :mingw32 do
228
+ # Use Rake::ExtensionCompiler helpers to find the proper host
229
+ unless Rake::ExtensionCompiler.mingw_host then
230
+ warn "You need to install mingw32 cross compile functionality to be able to continue."
231
+ warn "Please refer to your distribution/package manager documentation about installation."
232
+ fail
233
+ end
234
+ end
@@ -8,8 +8,8 @@
8
8
  Author: ematsu
9
9
  modified at: Wed Jan 20 16:41:51 1999
10
10
 
11
- $Author: ged $
12
- $Date: 2010/10/31 23:29:59 $
11
+ $Author$
12
+ $Date$
13
13
  ************************************************/
14
14
 
15
15
  #include <ctype.h>
@@ -2,6 +2,11 @@ require 'pp'
2
2
  require 'mkmf'
3
3
 
4
4
 
5
+ if ENV['MAINTAINER_MODE']
6
+ $stderr.puts "Maintainer mode enabled."
7
+ $CFLAGS << ' -Wall' << ' -ggdb' << ' -DDEBUG'
8
+ end
9
+
5
10
  if pgdir = with_config( 'pg' )
6
11
  ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
7
12
  end
@@ -21,8 +26,8 @@ dir_config 'pg'
21
26
 
22
27
  if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
23
28
  $stderr.puts "Using config values from %s" % [ pgconfig ]
24
- $CPPFLAGS << " -I%s" % [ `#{pgconfig} --includedir`.chomp ]
25
- $LDFLAGS << " -L%s" % [ `#{pgconfig} --libdir`.chomp ]
29
+ $CPPFLAGS << " -I%s" % [ `"#{pgconfig}" --includedir`.chomp ]
30
+ $LDFLAGS << " -L%s" % [ `"#{pgconfig}" --libdir`.chomp ]
26
31
  else
27
32
  $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
28
33
  " --with-pg-config=/path/to/pg_config"
@@ -48,6 +53,9 @@ have_func 'lo_create'
48
53
  have_func 'pg_encoding_to_char'
49
54
  have_func 'PQsetClientEncoding'
50
55
 
56
+ have_func 'rb_encdb_alias'
57
+ have_func 'rb_enc_alias'
58
+
51
59
  $defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
52
60
  have_struct_member 'struct pgNotify', 'extra', 'libpq-fe.h'
53
61
 
data/ext/pg.c CHANGED
@@ -8,8 +8,8 @@
8
8
  Author: ematsu
9
9
  modified at: Wed Jan 20 16:41:51 1999
10
10
 
11
- $Author: ged $
12
- $Date: 2011/04/18 23:51:05 $
11
+ $Author$
12
+ $Date$
13
13
  ************************************************/
14
14
 
15
15
  #include "pg.h"
@@ -28,7 +28,7 @@ static VALUE rb_cPGconn;
28
28
  static VALUE rb_cPGresult;
29
29
  static VALUE rb_ePGError;
30
30
 
31
- static const char *VERSION = "0.11.0";
31
+ static const char *VERSION = "0.12.0";
32
32
 
33
33
 
34
34
  /* The following functions are part of libpq, but not
@@ -293,7 +293,7 @@ pgconn_alloc(VALUE klass)
293
293
  * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
294
294
  * connection will have its +client_encoding+ set accordingly.
295
295
  *
296
- * @raises [PGError] if the connection fails.
296
+ * Raises a PGError if the connection fails.
297
297
  */
298
298
  static VALUE
299
299
  pgconn_init(int argc, VALUE *argv, VALUE self)
@@ -784,7 +784,7 @@ pgconn_server_version(VALUE self)
784
784
 
785
785
  /*
786
786
  * call-seq:
787
- * conn.error() -> String
787
+ * conn.error_message -> String
788
788
  *
789
789
  * Returns the error message about connection.
790
790
  */
@@ -1285,7 +1285,6 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1285
1285
  /*
1286
1286
  * call-seq:
1287
1287
  * conn.escape_string( str ) -> String
1288
- * PGconn.escape_string( str ) -> String # DEPRECATED
1289
1288
  *
1290
1289
  * Connection instance method for versions of 8.1 and higher of libpq
1291
1290
  * uses PQescapeStringConn, which is safer. Avoid calling as a class method,
@@ -1343,7 +1342,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1343
1342
  /*
1344
1343
  * call-seq:
1345
1344
  * conn.escape_bytea( string ) -> String
1346
- * PGconn.escape_bytea( string ) -> String # DEPRECATED
1347
1345
  *
1348
1346
  * Connection instance method for versions of 8.1 and higher of libpq
1349
1347
  * uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
@@ -2056,6 +2054,7 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
2056
2054
  * call-seq:
2057
2055
  * conn.wait_for_notify( [ timeout ] ) -> String
2058
2056
  * conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
2057
+ * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
2059
2058
  *
2060
2059
  * Blocks while waiting for notification(s), or until the optional
2061
2060
  * _timeout_ is reached, whichever comes first. _timeout_ is
@@ -2065,6 +2064,10 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
2065
2064
  * event otherwise. If used in block form, passes the name of the
2066
2065
  * NOTIFY +event+ and the generating +pid+ into the block.
2067
2066
  *
2067
+ * Under PostgreSQL 9.0 and later, if the notification is sent with
2068
+ * the optional +payload+ string, it will be given to the block as the
2069
+ * third argument.
2070
+ *
2068
2071
  */
2069
2072
  static VALUE
2070
2073
  pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
@@ -2075,7 +2078,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2075
2078
  int ret;
2076
2079
  struct timeval timeout;
2077
2080
  struct timeval *ptimeout = NULL;
2078
- VALUE timeout_in, relname = Qnil, be_pid = Qnil, extra = Qnil;
2081
+ VALUE timeout_in = Qnil, relname = Qnil, be_pid = Qnil, extra = Qnil;
2079
2082
  double timeout_sec;
2080
2083
  fd_set sd_rset;
2081
2084
  #ifdef _WIN32
@@ -2085,7 +2088,9 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2085
2088
  if ( sd < 0 )
2086
2089
  rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
2087
2090
 
2088
- if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
2091
+ rb_scan_args( argc, argv, "01", &timeout_in );
2092
+
2093
+ if ( RTEST(timeout_in) ) {
2089
2094
  timeout_sec = NUM2DBL( timeout_in );
2090
2095
  timeout.tv_sec = (long)timeout_sec;
2091
2096
  timeout.tv_usec = (long)( (timeout_sec - (long)timeout_sec) * 1e6 );
@@ -2120,9 +2125,13 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2120
2125
  }
2121
2126
 
2122
2127
  relname = rb_tainted_str_new2( notification->relname );
2128
+ ASSOCIATE_INDEX( relname, self );
2123
2129
  be_pid = INT2NUM( notification->be_pid );
2124
2130
  #ifdef HAVE_ST_NOTIFY_EXTRA
2125
- extra = rb_str_new2( notification->extra );
2131
+ if ( *notification->extra ) {
2132
+ extra = rb_tainted_str_new2( notification->extra );
2133
+ ASSOCIATE_INDEX( extra, self );
2134
+ }
2126
2135
  #endif
2127
2136
  PQfreemem( notification );
2128
2137
 
@@ -2483,6 +2492,7 @@ pgconn_transaction(VALUE self)
2483
2492
  return Qnil;
2484
2493
  }
2485
2494
 
2495
+
2486
2496
  /*
2487
2497
  * call-seq:
2488
2498
  * PGconn.quote_ident( str ) -> String
@@ -2532,6 +2542,8 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
2532
2542
  }
2533
2543
 
2534
2544
 
2545
+ #ifndef _WIN32
2546
+
2535
2547
  /*
2536
2548
  * call-seq:
2537
2549
  * conn.block( [ timeout ] ) -> Boolean
@@ -2547,27 +2559,152 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
2547
2559
  */
2548
2560
  static VALUE
2549
2561
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
2550
- PGconn *conn = get_pgconn(self);
2551
- int sd = PQsocket(conn);
2562
+ PGconn *conn = get_pgconn( self );
2563
+ int sd = PQsocket( conn );
2552
2564
  int ret;
2565
+
2566
+ /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2567
+ * and does not wait (nor sleep) any time even if timeout is given.
2568
+ * Instead use the Winsock events and rb_w32_wait_events(). */
2569
+
2553
2570
  struct timeval timeout;
2554
2571
  struct timeval *ptimeout = NULL;
2572
+ fd_set sd_rset;
2573
+ VALUE timeout_in;
2574
+ double timeout_sec;
2575
+
2576
+ if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
2577
+ timeout_sec = NUM2DBL( timeout_in );
2578
+ timeout.tv_sec = (long)timeout_sec;
2579
+ timeout.tv_usec = (long)((timeout_sec - (long)timeout_sec) * 1e6);
2580
+ ptimeout = &timeout;
2581
+ }
2582
+
2583
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2584
+ if ( PQconsumeInput(conn) == 0 )
2585
+ rb_raise( rb_ePGError, PQerrorMessage(conn) );
2586
+
2587
+ while ( PQisBusy(conn) ) {
2588
+ FD_ZERO( &sd_rset );
2589
+ FD_SET( sd, &sd_rset );
2590
+
2591
+ if ( (ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout )) < 0 )
2592
+ rb_sys_fail( "rb_thread_select()" ); /* Raises */
2593
+
2594
+ /* Return false if there was a timeout argument and the select() timed out */
2595
+ if ( ret == 0 && argc )
2596
+ return Qfalse;
2597
+
2598
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2599
+ if ( PQconsumeInput(conn) == 0 )
2600
+ rb_raise( rb_ePGError, PQerrorMessage(conn) );
2601
+ }
2602
+
2603
+ return Qtrue;
2604
+ }
2605
+
2606
+
2607
+ #else /* _WIN32 */
2608
+
2609
+ /*
2610
+ * Win32 PGconn#block -- on Windows, use platform-specific strategies to wait for the socket
2611
+ * instead of rb_thread_select().
2612
+ */
2613
+
2614
+ /* Win32 + Ruby 1.9+ */
2615
+ #ifdef HAVE_RUBY_VM_H
2616
+
2617
+ int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2618
+
2619
+ /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2620
+ * and does not wait (nor sleep) any time even if timeout is given.
2621
+ * Instead use the Winsock events and rb_w32_wait_events(). */
2622
+
2623
+ static VALUE
2624
+ pgconn_block( int argc, VALUE *argv, VALUE self ) {
2625
+ PGconn *conn = get_pgconn( self );
2626
+ int sd = PQsocket( conn );
2627
+ int ret;
2628
+
2629
+ DWORD timeout_milisec = INFINITY;
2630
+ DWORD wait_ret;
2631
+ WSAEVENT hEvent;
2555
2632
  VALUE timeout_in;
2556
2633
  double timeout_sec;
2634
+
2635
+ hEvent = WSACreateEvent();
2636
+
2637
+ if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
2638
+ timeout_sec = NUM2DBL( timeout_in );
2639
+ timeout_milisec = (DWORD)( (timeout_sec - (DWORD)timeout_sec) * 1e3 );
2640
+ }
2641
+
2642
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2643
+ if( PQconsumeInput(conn) == 0 ) {
2644
+ WSACloseEvent( hEvent );
2645
+ rb_raise( rb_ePGError, PQerrorMessage(conn) );
2646
+ }
2647
+
2648
+ while ( PQisBusy(conn) ) {
2649
+ if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2650
+ WSACloseEvent( hEvent );
2651
+ rb_raise( rb_ePGError, "WSAEventSelect socket error: %d", WSAGetLastError() );
2652
+ }
2653
+
2654
+ wait_ret = rb_w32_wait_events( &hEvent, 1, 100 );
2655
+
2656
+ if ( wait_ret == WAIT_TIMEOUT ) {
2657
+ ret = 0;
2658
+ } else if ( wait_ret == WAIT_OBJECT_0 ) {
2659
+ ret = 1;
2660
+ } else if ( wait_ret == WAIT_FAILED ) {
2661
+ WSACloseEvent( hEvent );
2662
+ rb_raise( rb_ePGError, "Wait on socket error (WaitForMultipleObjects): %d", GetLastError() );
2663
+ } else {
2664
+ WSACloseEvent( hEvent );
2665
+ rb_raise( rb_ePGError, "Wait on socket abandoned (WaitForMultipleObjects)" );
2666
+ }
2667
+
2668
+ /* Return false if there was a timeout argument and the select() timed out */
2669
+ if ( ret == 0 && argc ) {
2670
+ WSACloseEvent( hEvent );
2671
+ return Qfalse;
2672
+ }
2673
+
2674
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2675
+ if ( PQconsumeInput(conn) == 0 ) {
2676
+ WSACloseEvent( hEvent );
2677
+ rb_raise( rb_ePGError, PQerrorMessage(conn) );
2678
+ }
2679
+ }
2680
+
2681
+ WSACloseEvent( hEvent );
2682
+
2683
+ return Qtrue;
2684
+ }
2685
+
2686
+ #else /* Win32 + Ruby < 1.9 */
2687
+
2688
+ static VALUE
2689
+ pgconn_block( int argc, VALUE *argv, VALUE self ) {
2690
+ PGconn *conn = get_pgconn( self );
2691
+ int sd = PQsocket( conn );
2692
+ int ret;
2693
+
2694
+ struct timeval timeout;
2695
+ struct timeval *ptimeout = NULL;
2557
2696
  fd_set sd_rset;
2558
- #ifdef _WIN32
2559
2697
  fd_set crt_sd_rset;
2560
- #endif
2698
+ VALUE timeout_in;
2699
+ double timeout_sec;
2561
2700
 
2562
- /* Always set a timeout in WIN32, as rb_thread_select() sometimes
2701
+ /* Always set a timeout, as rb_thread_select() sometimes
2563
2702
  * doesn't return when a second ruby thread is running although data
2564
2703
  * could be read. So we use timeout-based polling instead.
2565
2704
  */
2566
- #if defined(_WIN32)
2567
2705
  timeout.tv_sec = 0;
2568
- timeout.tv_usec = 10000;
2706
+ timeout.tv_usec = 10000; // 10ms
2569
2707
  ptimeout = &timeout;
2570
- #endif
2571
2708
 
2572
2709
  if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
2573
2710
  timeout_sec = NUM2DBL( timeout_in );
@@ -2576,32 +2713,33 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
2576
2713
  ptimeout = &timeout;
2577
2714
  }
2578
2715
 
2579
- PQconsumeInput( conn );
2716
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2717
+ if( PQconsumeInput(conn) == 0 )
2718
+ rb_raise( rb_ePGError, PQerrorMessage(conn) );
2580
2719
 
2581
2720
  while ( PQisBusy(conn) ) {
2582
2721
  FD_ZERO( &sd_rset );
2583
2722
  FD_SET( sd, &sd_rset );
2584
2723
 
2585
- #ifdef _WIN32
2586
- create_crt_fd(&sd_rset, &crt_sd_rset);
2587
- #endif
2588
-
2589
- ret = rb_thread_select (sd+1, &sd_rset, NULL, NULL, ptimeout );
2590
-
2591
- #ifdef _WIN32
2592
- cleanup_crt_fd(&sd_rset, &crt_sd_rset);
2593
- #endif
2724
+ create_crt_fd( &sd_rset, &crt_sd_rset );
2725
+ ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
2726
+ cleanup_crt_fd( &sd_rset, &crt_sd_rset );
2594
2727
 
2595
2728
  /* Return false if there was a timeout argument and the select() timed out */
2596
- if ( ret == 0 && argc )
2729
+ if ( ret == 0 && argc )
2597
2730
  return Qfalse;
2598
2731
 
2599
- PQconsumeInput( conn );
2600
- }
2732
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2733
+ if ( PQconsumeInput(conn) == 0 )
2734
+ rb_raise( rb_ePGError, PQerrorMessage(conn) );
2735
+ }
2601
2736
 
2602
2737
  return Qtrue;
2603
2738
  }
2604
2739
 
2740
+ #endif /* Ruby 1.9 */
2741
+ #endif /* Win32 */
2742
+
2605
2743
 
2606
2744
  /*
2607
2745
  * call-seq:
@@ -2663,6 +2801,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
2663
2801
  VALUE rb_pgresult = Qnil;
2664
2802
 
2665
2803
  /* remove any remaining results from the queue */
2804
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
2666
2805
  pgconn_get_last_result( self );
2667
2806
 
2668
2807
  pgconn_send_query( argc, argv, self );
@@ -3033,12 +3172,12 @@ pgresult_res_status(VALUE self, VALUE status)
3033
3172
 
3034
3173
  /*
3035
3174
  * call-seq:
3036
- * res.result_error_message() -> String
3175
+ * res.error_message() -> String
3037
3176
  *
3038
3177
  * Returns the error message of the command as a string.
3039
3178
  */
3040
3179
  static VALUE
3041
- pgresult_result_error_message(VALUE self)
3180
+ pgresult_error_message(VALUE self)
3042
3181
  {
3043
3182
  VALUE ret = rb_tainted_str_new2(PQresultErrorMessage(get_pgresult(self)));
3044
3183
  ASSOCIATE_INDEX(ret, self);
@@ -3047,7 +3186,7 @@ pgresult_result_error_message(VALUE self)
3047
3186
 
3048
3187
  /*
3049
3188
  * call-seq:
3050
- * res.result_error_field(fieldcode) -> String
3189
+ * res.error_field(fieldcode) -> String
3051
3190
  *
3052
3191
  * Returns the individual field of an error.
3053
3192
  *
@@ -3064,14 +3203,46 @@ pgresult_result_error_message(VALUE self)
3064
3203
  * * +PG_DIAG_SOURCE_FILE+
3065
3204
  * * +PG_DIAG_SOURCE_LINE+
3066
3205
  * * +PG_DIAG_SOURCE_FUNCTION+
3206
+ *
3207
+ * An example:
3208
+ *
3209
+ * begin
3210
+ * conn.exec( "SELECT * FROM nonexistant_table" )
3211
+ * rescue PGError => err
3212
+ * p [
3213
+ * result.error_field( PGresult::PG_DIAG_SEVERITY ),
3214
+ * result.error_field( PGresult::PG_DIAG_SQLSTATE ),
3215
+ * result.error_field( PGresult::PG_DIAG_MESSAGE_PRIMARY ),
3216
+ * result.error_field( PGresult::PG_DIAG_MESSAGE_DETAIL ),
3217
+ * result.error_field( PGresult::PG_DIAG_MESSAGE_HINT ),
3218
+ * result.error_field( PGresult::PG_DIAG_STATEMENT_POSITION ),
3219
+ * result.error_field( PGresult::PG_DIAG_INTERNAL_POSITION ),
3220
+ * result.error_field( PGresult::PG_DIAG_INTERNAL_QUERY ),
3221
+ * result.error_field( PGresult::PG_DIAG_CONTEXT ),
3222
+ * result.error_field( PGresult::PG_DIAG_SOURCE_FILE ),
3223
+ * result.error_field( PGresult::PG_DIAG_SOURCE_LINE ),
3224
+ * result.error_field( PGresult::PG_DIAG_SOURCE_FUNCTION ),
3225
+ * ]
3226
+ * end
3227
+ *
3228
+ * Outputs:
3229
+ *
3230
+ * ["ERROR", "42P01", "relation \"nonexistant_table\" does not exist", nil, nil,
3231
+ * "15", nil, nil, nil, "path/to/parse_relation.c", "857", "parserOpenTable"]
3067
3232
  */
3068
3233
  static VALUE
3069
- pgresult_result_error_field(VALUE self, VALUE field)
3234
+ pgresult_error_field(VALUE self, VALUE field)
3070
3235
  {
3071
- PGresult *result = get_pgresult(self);
3072
- int fieldcode = NUM2INT(field);
3073
- VALUE ret = rb_tainted_str_new2(PQresultErrorField(result,fieldcode));
3074
- ASSOCIATE_INDEX(ret, self);
3236
+ PGresult *result = get_pgresult( self );
3237
+ int fieldcode = NUM2INT( field );
3238
+ char * fieldstr = PQresultErrorField( result, fieldcode );
3239
+ VALUE ret = Qnil;
3240
+
3241
+ if ( fieldstr ) {
3242
+ ret = rb_tainted_str_new2( fieldstr );
3243
+ ASSOCIATE_INDEX( ret, self );
3244
+ }
3245
+
3075
3246
  return ret;
3076
3247
  }
3077
3248
 
@@ -3744,7 +3915,15 @@ static int enc_get_index(VALUE val)
3744
3915
  return i;
3745
3916
  }
3746
3917
 
3918
+ #ifdef HAVE_RB_ENCDB_ALIAS
3919
+ # define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
3920
+ #elif HAVE_RB_ENC_ALIAS
3921
+ # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
3922
+ #else
3747
3923
  extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
3924
+ # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
3925
+ #endif
3926
+
3748
3927
  static rb_encoding *
3749
3928
  find_or_create_johab(void)
3750
3929
  {
@@ -3758,7 +3937,7 @@ find_or_create_johab(void)
3758
3937
 
3759
3938
  enc_index = rb_define_dummy_encoding(aliases[0]);
3760
3939
  for (i = 1; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
3761
- rb_enc_alias(aliases[i], aliases[0]);
3940
+ ENC_ALIAS(aliases[i], aliases[0]);
3762
3941
  }
3763
3942
  return rb_enc_from_index(enc_index);
3764
3943
  }
@@ -4004,7 +4183,6 @@ Init_pg_ext()
4004
4183
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4005
4184
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4006
4185
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4007
-
4008
4186
 
4009
4187
  /****** PGconn CLASS CONSTANTS: Connection Status ******/
4010
4188
 
@@ -4286,8 +4464,10 @@ Init_pg_ext()
4286
4464
  /****** PGresult INSTANCE METHODS: libpq ******/
4287
4465
  rb_define_method(rb_cPGresult, "result_status", pgresult_result_status, 0);
4288
4466
  rb_define_method(rb_cPGresult, "res_status", pgresult_res_status, 1);
4289
- rb_define_method(rb_cPGresult, "result_error_message", pgresult_result_error_message, 0);
4290
- rb_define_method(rb_cPGresult, "result_error_field", pgresult_result_error_field, 1);
4467
+ rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
4468
+ rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
4469
+ rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
4470
+ rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
4291
4471
  rb_define_method(rb_cPGresult, "clear", pgresult_clear, 0);
4292
4472
  rb_define_method(rb_cPGresult, "ntuples", pgresult_ntuples, 0);
4293
4473
  rb_define_alias(rb_cPGresult, "num_tuples", "ntuples");