pg 0.11.0-x86-mingw32 → 0.12.0-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 (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");