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.
- data/.gemtest +0 -0
- data/ChangeLog +1647 -462
- data/Contributors.rdoc +39 -0
- data/History.rdoc +61 -0
- data/Manifest.txt +43 -0
- data/README.OS_X.rdoc +68 -0
- data/README.ja.rdoc +7 -0
- data/{README → README.rdoc} +38 -18
- data/{README.windows → README.windows.rdoc} +23 -31
- data/Rakefile +104 -318
- data/Rakefile.cross +234 -0
- data/ext/compat.c +2 -2
- data/ext/extconf.rb +10 -2
- data/ext/pg.c +223 -43
- data/ext/vc/pg.sln +26 -0
- data/ext/vc/pg_18/pg.vcproj +216 -0
- data/ext/vc/pg_19/pg_19.vcproj +209 -0
- data/lib/1.8/pg_ext.so +0 -0
- data/lib/1.9/pg_ext.so +0 -0
- data/lib/pg.rb +5 -7
- data/misc/openssl-pg-segfault.rb +31 -0
- data/sample/async_api.rb +109 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/losample.rb +69 -0
- data/sample/notify_wait.rb +43 -0
- data/sample/psql.rb +1181 -0
- data/sample/psqlHelp.rb +158 -0
- data/sample/test1.rb +60 -0
- data/sample/test2.rb +44 -0
- data/sample/test4.rb +71 -0
- data/sample/test_binary_values.rb +35 -0
- data/spec/lib/helpers.rb +6 -4
- data/spec/m17n_spec.rb +2 -2
- data/spec/pgconn_spec.rb +51 -6
- data/spec/pgresult_spec.rb +30 -4
- metadata +147 -86
- data.tar.gz.sig +0 -3
- data/Contributors +0 -32
- data/README.OS_X +0 -19
- data/README.ja +0 -183
- data/Rakefile.local +0 -312
- data/rake/191_compat.rb +0 -26
- data/rake/dependencies.rb +0 -76
- data/rake/documentation.rb +0 -123
- data/rake/helpers.rb +0 -502
- data/rake/hg.rb +0 -318
- data/rake/manual.rb +0 -787
- data/rake/packaging.rb +0 -129
- data/rake/publishing.rb +0 -341
- data/rake/style.rb +0 -62
- data/rake/svn.rb +0 -668
- data/rake/testing.rb +0 -152
- data/rake/verifytask.rb +0 -64
- metadata.gz.sig +0 -3
data/Rakefile.cross
ADDED
@@ -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
|
data/ext/compat.c
CHANGED
data/ext/extconf.rb
CHANGED
@@ -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" % [
|
25
|
-
$LDFLAGS << " -L%s" % [
|
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
|
12
|
-
$Date
|
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.
|
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
|
-
*
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
2698
|
+
VALUE timeout_in;
|
2699
|
+
double timeout_sec;
|
2561
2700
|
|
2562
|
-
/* Always set a timeout
|
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
|
-
|
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
|
-
|
2586
|
-
|
2587
|
-
|
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
|
-
|
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.
|
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
|
-
|
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.
|
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
|
-
|
3234
|
+
pgresult_error_field(VALUE self, VALUE field)
|
3070
3235
|
{
|
3071
|
-
PGresult *result = get_pgresult(self);
|
3072
|
-
int fieldcode = NUM2INT(field);
|
3073
|
-
|
3074
|
-
|
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
|
-
|
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, "
|
4290
|
-
|
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");
|