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.
- 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");
|