pg 0.14.1 → 0.15.0.pre.432
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/ChangeLog +425 -2
- data/Contributors.rdoc +1 -1
- data/History.rdoc +35 -0
- data/Manifest.txt +3 -0
- data/README.rdoc +5 -3
- data/Rakefile.cross +2 -2
- data/ext/extconf.rb +7 -1
- data/ext/gvl_wrappers.c +13 -0
- data/ext/gvl_wrappers.h +185 -0
- data/ext/pg.c +9 -5
- data/ext/pg.h +3 -0
- data/ext/pg_connection.c +452 -351
- data/ext/pg_result.c +9 -12
- data/lib/pg.rb +1 -1
- data/lib/pg/connection.rb +22 -2
- data/lib/pg/result.rb +6 -1
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +1 -1
- data/sample/async_copyto.rb +1 -1
- data/sample/async_mixed.rb +1 -1
- data/spec/lib/helpers.rb +16 -10
- data/spec/pg/connection_spec.rb +212 -108
- data/spec/pg/result_spec.rb +23 -8
- metadata +11 -7
- metadata.gz.sig +0 -0
data/History.rdoc
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
== v0.15.0 [YYYY-MM-DD] Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
Bugfixes:
|
4
|
+
|
5
|
+
- Fix segfault in PG::Result#field_values when called with non String value.
|
6
|
+
- Fix encoding of messages delivered by notice callbacks.
|
7
|
+
- Fix text encoding for Connection#wait_for_notify and Connection#notifies.
|
8
|
+
- Fix 'Bad file descriptor' problems under Windows: wrong behaviour of
|
9
|
+
#wait_for_notify() and timeout handling of #block on Ruby 1.9.
|
10
|
+
|
11
|
+
Documentation fixes:
|
12
|
+
|
13
|
+
- conn#socket() can not be used with IO.for_fd() on Windows.
|
14
|
+
|
15
|
+
Enhancements:
|
16
|
+
|
17
|
+
- Add single row mode of PostgreSQL 9.2.
|
18
|
+
- Set fallback_application_name to programm name $0. Thanks to Will Leinweber
|
19
|
+
for the patch.
|
20
|
+
- Release Ruby's GVL while calls to blocking libpq functions to allow better
|
21
|
+
concurrency in threaded applications.
|
22
|
+
- Refactor different variants of waiting for the connection socket.
|
23
|
+
- Make use of rb_thread_fd_select() on Ruby 1.9 and avoid deprecated
|
24
|
+
rb_thread_select().
|
25
|
+
- Add an example of how to insert array data using a prepared statement (#145).
|
26
|
+
- Add continous integration tests on travis-ci.org.
|
27
|
+
- Add PG::Result#each_value for looping over result sets by row. Thanks to
|
28
|
+
Aaron Patterson for the patch.
|
29
|
+
|
30
|
+
Specs:
|
31
|
+
|
32
|
+
- Fix various specs to run on older PostgreSQL and Ruby versions.
|
33
|
+
- Avoid fork() in specs to allow usage on Windows and JRuby.
|
34
|
+
|
35
|
+
|
1
36
|
== v0.14.1 [2012-09-02] Michael Granger <ged@FaerieMUD.org>
|
2
37
|
|
3
38
|
Important bugfix:
|
data/Manifest.txt
CHANGED
@@ -13,6 +13,8 @@ README.rdoc
|
|
13
13
|
Rakefile
|
14
14
|
Rakefile.cross
|
15
15
|
ext/extconf.rb
|
16
|
+
ext/gvl_wrappers.c
|
17
|
+
ext/gvl_wrappers.h
|
16
18
|
ext/pg.c
|
17
19
|
ext/pg.h
|
18
20
|
ext/pg_connection.c
|
@@ -25,6 +27,7 @@ lib/pg/connection.rb
|
|
25
27
|
lib/pg/constants.rb
|
26
28
|
lib/pg/exceptions.rb
|
27
29
|
lib/pg/result.rb
|
30
|
+
sample/array_insert.rb
|
28
31
|
sample/async_api.rb
|
29
32
|
sample/async_copyto.rb
|
30
33
|
sample/async_mixed.rb
|
data/README.rdoc
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
{<img src="https://travis-ci.org/ged/ruby-pg.png?branch=master" alt="Build Status" />}[https://travis-ci.org/ged/ruby-pg]
|
2
|
+
|
1
3
|
= pg
|
2
4
|
|
3
5
|
* https://bitbucket.org/ged/ruby-pg
|
@@ -11,14 +13,14 @@ It works with {PostgreSQL 8.3 and later}[http://bit.ly/6AfPhm].
|
|
11
13
|
A small example usage:
|
12
14
|
|
13
15
|
#!/usr/bin/env ruby
|
14
|
-
|
16
|
+
|
15
17
|
require 'pg'
|
16
|
-
|
18
|
+
|
17
19
|
# Output a table of current connections to the DB
|
18
20
|
conn = PG.connect( dbname: 'sales' )
|
19
21
|
conn.exec( "SELECT * FROM pg_stat_activity" ) do |result|
|
20
22
|
puts " PID | User | Query"
|
21
|
-
|
23
|
+
result.each do |row|
|
22
24
|
puts " %7d | %-16s | %s " %
|
23
25
|
row.values_at('procpid', 'usename', 'current_query')
|
24
26
|
end
|
data/Rakefile.cross
CHANGED
@@ -19,7 +19,7 @@ end
|
|
19
19
|
|
20
20
|
# Cross-compilation constants
|
21
21
|
OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '1.0.1c'
|
22
|
-
POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '9.
|
22
|
+
POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '9.2.2'
|
23
23
|
|
24
24
|
COMPILE_HOME = Pathname( "./build" ).expand_path
|
25
25
|
STATIC_SOURCESDIR = COMPILE_HOME + 'sources'
|
@@ -172,7 +172,7 @@ file STATIC_POSTGRESQL_BUILDDIR => POSTGRESQL_TARBALL do |t|
|
|
172
172
|
STATIC_POSTGRESQL_BUILDDIR.mkpath
|
173
173
|
run 'tar', '-xjf', POSTGRESQL_TARBALL.to_s, '-C', STATIC_POSTGRESQL_BUILDDIR.parent.to_s
|
174
174
|
mv POSTGRESQL_SHLIB_MAKEFILE, POSTGRESQL_SHLIB_MF_ORIG
|
175
|
-
|
175
|
+
|
176
176
|
POSTGRESQL_PATCHES.each do |patchfile|
|
177
177
|
puts " applying patch #{patchfile}..."
|
178
178
|
run 'patch', '-Np1', '-d', STATIC_POSTGRESQL_BUILDDIR.to_s,
|
data/ext/extconf.rb
CHANGED
@@ -32,7 +32,9 @@ dir_config 'pg'
|
|
32
32
|
if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
|
33
33
|
$stderr.puts "Using config values from %s" % [ pgconfig ]
|
34
34
|
$CPPFLAGS << " -I%s" % [ `"#{pgconfig}" --includedir`.chomp ]
|
35
|
-
|
35
|
+
|
36
|
+
libdir = `"#{pgconfig}" --libdir`.chomp
|
37
|
+
$LDFLAGS << " -L%s -Wl,-rpath,%s" % [ libdir, libdir ]
|
36
38
|
else
|
37
39
|
$stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
|
38
40
|
" --with-pg-config=/path/to/pg_config"
|
@@ -65,9 +67,13 @@ have_func 'pg_char_to_encoding'
|
|
65
67
|
have_func 'PQsetClientEncoding'
|
66
68
|
have_func 'PQlibVersion'
|
67
69
|
have_func 'PQping'
|
70
|
+
have_func 'PQsetSingleRowMode'
|
68
71
|
|
69
72
|
have_func 'rb_encdb_alias'
|
70
73
|
have_func 'rb_enc_alias'
|
74
|
+
have_func 'rb_thread_call_without_gvl'
|
75
|
+
have_func 'rb_thread_call_with_gvl'
|
76
|
+
have_func 'rb_thread_fd_select'
|
71
77
|
|
72
78
|
have_const 'PGRES_COPY_BOTH', 'libpq-fe.h'
|
73
79
|
have_const 'PGRES_SINGLE_TUPLE', 'libpq-fe.h'
|
data/ext/gvl_wrappers.c
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* gvl_wrappers.c - Wrapper functions for locking/unlocking the Ruby GVL
|
3
|
+
*
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "pg.h"
|
7
|
+
|
8
|
+
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
|
9
|
+
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_SKELETON );
|
10
|
+
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
|
11
|
+
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
|
12
|
+
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
|
13
|
+
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
|
data/ext/gvl_wrappers.h
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
/*
|
2
|
+
* gvl_wrappers.h - Wrapper functions for locking/unlocking the Ruby GVL
|
3
|
+
*
|
4
|
+
* These are some obscure preprocessor directives that allow to generate
|
5
|
+
* drop-in replacement wrapper functions in a declarative manner.
|
6
|
+
* These wrapper functions ensure that ruby's GVL is released on each
|
7
|
+
* function call and reacquired at the end of the call or in callbacks.
|
8
|
+
* This way blocking functions calls don't block concurrent ruby threads.
|
9
|
+
*
|
10
|
+
* The wrapper of each function is prefixed by "gvl_".
|
11
|
+
*
|
12
|
+
* Use "gcc -E" to retrieve the generated code.
|
13
|
+
*/
|
14
|
+
|
15
|
+
#ifndef __gvl_wrappers_h
|
16
|
+
#define __gvl_wrappers_h
|
17
|
+
|
18
|
+
#if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
|
19
|
+
extern void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
23
|
+
extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
24
|
+
rb_unblock_function_t *ubf, void *data2);
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#define DEFINE_PARAM_LIST1(type, name) \
|
28
|
+
name,
|
29
|
+
|
30
|
+
#define DEFINE_PARAM_LIST2(type, name) \
|
31
|
+
p->params.name,
|
32
|
+
|
33
|
+
#define DEFINE_PARAM_LIST3(type, name) \
|
34
|
+
type name,
|
35
|
+
|
36
|
+
#define DEFINE_PARAM_DECL(type, name) \
|
37
|
+
type name;
|
38
|
+
|
39
|
+
#define DEFINE_GVL_WRAPPER_STRUCT(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
40
|
+
struct gvl_wrapper_##name##_params { \
|
41
|
+
struct { \
|
42
|
+
FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_DECL) \
|
43
|
+
lastparamtype lastparamname; \
|
44
|
+
} params; \
|
45
|
+
when_non_void( rettype retval; ) \
|
46
|
+
};
|
47
|
+
|
48
|
+
#define DEFINE_GVL_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
49
|
+
static void * gvl_##name##_skeleton( void *data ){ \
|
50
|
+
struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
|
51
|
+
when_non_void( p->retval = ) \
|
52
|
+
name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST2) p->params.lastparamname ); \
|
53
|
+
return NULL; \
|
54
|
+
}
|
55
|
+
|
56
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
57
|
+
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
58
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
59
|
+
struct gvl_wrapper_##name##_params params = { \
|
60
|
+
{FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
|
61
|
+
}; \
|
62
|
+
rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms, RUBY_UBF_IO, 0); \
|
63
|
+
when_non_void( return params.retval; ) \
|
64
|
+
}
|
65
|
+
#else
|
66
|
+
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
67
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
68
|
+
return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
69
|
+
}
|
70
|
+
#endif
|
71
|
+
|
72
|
+
#define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
73
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
|
74
|
+
|
75
|
+
#define DEFINE_GVLCB_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
76
|
+
static void * gvl_##name##_skeleton( void *data ){ \
|
77
|
+
struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
|
78
|
+
when_non_void( p->retval = ) \
|
79
|
+
name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST2) p->params.lastparamname ); \
|
80
|
+
return NULL; \
|
81
|
+
}
|
82
|
+
|
83
|
+
#if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
|
84
|
+
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
85
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
86
|
+
struct gvl_wrapper_##name##_params params = { \
|
87
|
+
{FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
|
88
|
+
}; \
|
89
|
+
rb_thread_call_with_gvl(gvl_##name##_skeleton, ¶ms); \
|
90
|
+
when_non_void( return params.retval; ) \
|
91
|
+
}
|
92
|
+
#else
|
93
|
+
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
94
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
95
|
+
return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
96
|
+
}
|
97
|
+
#endif
|
98
|
+
|
99
|
+
#define GVL_TYPE_VOID(string)
|
100
|
+
#define GVL_TYPE_NONVOID(string) string
|
101
|
+
|
102
|
+
|
103
|
+
/*
|
104
|
+
* Definitions of blocking functions and their parameters
|
105
|
+
*/
|
106
|
+
|
107
|
+
#define FOR_EACH_PARAM_OF_PQexec(param) \
|
108
|
+
param(PGconn *, conn)
|
109
|
+
|
110
|
+
#define FOR_EACH_PARAM_OF_PQexecParams(param) \
|
111
|
+
param(PGconn *, conn) \
|
112
|
+
param(const char *, command) \
|
113
|
+
param(int, nParams) \
|
114
|
+
param(const Oid *, paramTypes) \
|
115
|
+
param(const char * const *, paramValues) \
|
116
|
+
param(const int *, paramLengths) \
|
117
|
+
param(const int *, paramFormats)
|
118
|
+
|
119
|
+
#define FOR_EACH_PARAM_OF_PQexecPrepared(param) \
|
120
|
+
param(PGconn *, conn) \
|
121
|
+
param(const char *, stmtName) \
|
122
|
+
param(int, nParams) \
|
123
|
+
param(const char * const *, paramValues) \
|
124
|
+
param(const int *, paramLengths) \
|
125
|
+
param(const int *, paramFormats)
|
126
|
+
|
127
|
+
#define FOR_EACH_PARAM_OF_PQprepare(param) \
|
128
|
+
param(PGconn *, conn) \
|
129
|
+
param(const char *, stmtName) \
|
130
|
+
param(const char *, query) \
|
131
|
+
param(int, nParams)
|
132
|
+
|
133
|
+
#define FOR_EACH_PARAM_OF_PQdescribePrepared(param) \
|
134
|
+
param(PGconn *, conn)
|
135
|
+
|
136
|
+
#define FOR_EACH_PARAM_OF_PQdescribePortal(param) \
|
137
|
+
param(PGconn *, conn)
|
138
|
+
|
139
|
+
#define FOR_EACH_PARAM_OF_PQgetResult(param)
|
140
|
+
|
141
|
+
#define FOR_EACH_PARAM_OF_PQputCopyData(param) \
|
142
|
+
param(PGconn *, conn) \
|
143
|
+
param(const char *, buffer)
|
144
|
+
|
145
|
+
#define FOR_EACH_PARAM_OF_PQputCopyEnd(param) \
|
146
|
+
param(PGconn *, conn)
|
147
|
+
|
148
|
+
#define FOR_EACH_PARAM_OF_PQgetCopyData(param) \
|
149
|
+
param(PGconn *, conn) \
|
150
|
+
param(char **, buffer)
|
151
|
+
|
152
|
+
/* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
153
|
+
#define FOR_EACH_BLOCKING_FUNCTION(function) \
|
154
|
+
function(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
|
155
|
+
function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
156
|
+
function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
157
|
+
function(PQprepare, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
|
158
|
+
function(PQdescribePrepared, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
|
159
|
+
function(PQdescribePortal, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
|
160
|
+
function(PQgetResult, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
|
161
|
+
function(PQputCopyData, GVL_TYPE_NONVOID, int, int, nbytes) \
|
162
|
+
function(PQputCopyEnd, GVL_TYPE_NONVOID, int, const char *, errormsg) \
|
163
|
+
function(PQgetCopyData, GVL_TYPE_NONVOID, int, int, async) \
|
164
|
+
|
165
|
+
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
|
166
|
+
|
167
|
+
|
168
|
+
/*
|
169
|
+
* Definitions of callback functions and their parameters
|
170
|
+
*/
|
171
|
+
|
172
|
+
#define FOR_EACH_PARAM_OF_notice_processor_proxy(param) \
|
173
|
+
param(void *, arg)
|
174
|
+
|
175
|
+
#define FOR_EACH_PARAM_OF_notice_receiver_proxy(param) \
|
176
|
+
param(void *, arg)
|
177
|
+
|
178
|
+
/* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
179
|
+
#define FOR_EACH_CALLBACK_FUNCTION(function) \
|
180
|
+
function(notice_processor_proxy, GVL_TYPE_VOID, void, const char *, message) \
|
181
|
+
function(notice_receiver_proxy, GVL_TYPE_VOID, void, const PGresult *, result) \
|
182
|
+
|
183
|
+
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_STUB_DECL );
|
184
|
+
|
185
|
+
#endif /* end __gvl_wrappers_h */
|
data/ext/pg.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg.c - Toplevel extension
|
3
|
-
* $Id: pg.c,v
|
3
|
+
* $Id: pg.c,v d0c5d5f7f1e8 2012/12/26 21:09:28 kanis $
|
4
4
|
*
|
5
5
|
* Author/s:
|
6
6
|
*
|
@@ -129,7 +129,7 @@ static ID s_id_index;
|
|
129
129
|
|
130
130
|
/*
|
131
131
|
* Get the index of encoding +val+.
|
132
|
-
* :FIXME: Look into replacing this with rb_enc_get_index() since 1.9.1 isn't really
|
132
|
+
* :FIXME: Look into replacing this with rb_enc_get_index() since 1.9.1 isn't really
|
133
133
|
* used anymore.
|
134
134
|
*/
|
135
135
|
int
|
@@ -174,7 +174,7 @@ pg_find_or_create_johab(void)
|
|
174
174
|
* - returns ASCII-8BIT if the client encoding is unknown.
|
175
175
|
*/
|
176
176
|
rb_encoding *
|
177
|
-
pg_get_pg_encoding_as_rb_encoding( int enc_id )
|
177
|
+
pg_get_pg_encoding_as_rb_encoding( int enc_id )
|
178
178
|
{
|
179
179
|
rb_encoding *enc;
|
180
180
|
|
@@ -409,7 +409,7 @@ Init_pg_ext()
|
|
409
409
|
rb_define_const(rb_mPGconstants, "PGRES_EMPTY_QUERY", INT2FIX(PGRES_EMPTY_QUERY));
|
410
410
|
/* #result_status constant: Successful completion of a command returning no data. */
|
411
411
|
rb_define_const(rb_mPGconstants, "PGRES_COMMAND_OK", INT2FIX(PGRES_COMMAND_OK));
|
412
|
-
/* #result_status constant: Successful completion of a command returning data
|
412
|
+
/* #result_status constant: Successful completion of a command returning data
|
413
413
|
(such as a SELECT or SHOW). */
|
414
414
|
rb_define_const(rb_mPGconstants, "PGRES_TUPLES_OK", INT2FIX(PGRES_TUPLES_OK));
|
415
415
|
/* #result_status constant: Copy Out (from server) data transfer started. */
|
@@ -426,6 +426,10 @@ Init_pg_ext()
|
|
426
426
|
#ifdef HAVE_CONST_PGRES_COPY_BOTH
|
427
427
|
rb_define_const(rb_mPGconstants, "PGRES_COPY_BOTH", INT2FIX(PGRES_COPY_BOTH));
|
428
428
|
#endif
|
429
|
+
/* #result_status constant: Single tuple from larger resultset. */
|
430
|
+
#ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
|
431
|
+
rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
|
432
|
+
#endif
|
429
433
|
|
430
434
|
/****** Result CONSTANTS: result error field codes ******/
|
431
435
|
|
@@ -509,7 +513,7 @@ Init_pg_ext()
|
|
509
513
|
/* Add the constants to the toplevel namespace */
|
510
514
|
rb_include_module( rb_mPG, rb_mPGconstants );
|
511
515
|
|
512
|
-
#ifdef M17N_SUPPORTED
|
516
|
+
#ifdef M17N_SUPPORTED
|
513
517
|
enc_pg2ruby = st_init_numtable();
|
514
518
|
s_id_index = rb_intern("@encoding");
|
515
519
|
#endif
|
data/ext/pg.h
CHANGED
@@ -77,6 +77,7 @@ __declspec(dllexport)
|
|
77
77
|
typedef long suseconds_t;
|
78
78
|
#endif
|
79
79
|
|
80
|
+
#include "gvl_wrappers.h"
|
80
81
|
|
81
82
|
/***************************************************************************
|
82
83
|
* Globals
|
@@ -119,5 +120,7 @@ int pg_enc_get_index _(( VALUE ));
|
|
119
120
|
rb_encoding *pg_conn_enc_get _(( PGconn * ));
|
120
121
|
#endif /* M17N_SUPPORTED */
|
121
122
|
|
123
|
+
void notice_receiver_proxy(void *arg, const PGresult *result);
|
124
|
+
void notice_processor_proxy(void *arg, const char *message);
|
122
125
|
|
123
126
|
#endif /* end __pg_h */
|
data/ext/pg_connection.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_connection.c - PG::Connection class extension
|
3
|
-
* $Id: pg_connection.c,v
|
3
|
+
* $Id: pg_connection.c,v 7c313c2355b7 2013/02/03 18:37:06 ged $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -8,10 +8,10 @@
|
|
8
8
|
|
9
9
|
|
10
10
|
/********************************************************************
|
11
|
-
*
|
11
|
+
*
|
12
12
|
* Document-class: PG::Connection
|
13
13
|
*
|
14
|
-
* The class to access PostgreSQL RDBMS, based on the libpq interface,
|
14
|
+
* The class to access PostgreSQL RDBMS, based on the libpq interface,
|
15
15
|
* provides convenient OO methods to interact with PostgreSQL.
|
16
16
|
*
|
17
17
|
* For example, to send query to the database on the localhost:
|
@@ -35,6 +35,15 @@ static VALUE pgconn_finish( VALUE );
|
|
35
35
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
36
36
|
#endif
|
37
37
|
|
38
|
+
#ifndef HAVE_RB_THREAD_FD_SELECT
|
39
|
+
#define rb_fdset_t fd_set
|
40
|
+
#define rb_fd_init(f)
|
41
|
+
#define rb_fd_zero(f) FD_ZERO(f)
|
42
|
+
#define rb_fd_set(n, f) FD_SET(n, f)
|
43
|
+
#define rb_fd_term(f)
|
44
|
+
#define rb_thread_fd_select rb_thread_select
|
45
|
+
#endif
|
46
|
+
|
38
47
|
/*
|
39
48
|
* Global functions
|
40
49
|
*/
|
@@ -92,7 +101,7 @@ pgconn_gc_free( PGconn *conn )
|
|
92
101
|
|
93
102
|
/*
|
94
103
|
* Document-method: allocate
|
95
|
-
*
|
104
|
+
*
|
96
105
|
* call-seq:
|
97
106
|
* PG::Connection.allocate -> conn
|
98
107
|
*/
|
@@ -111,9 +120,9 @@ pgconn_s_allocate( VALUE klass )
|
|
111
120
|
* PG::Connection.new(connection_hash) -> conn
|
112
121
|
* PG::Connection.new(connection_string) -> conn
|
113
122
|
* PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
|
114
|
-
*
|
123
|
+
*
|
115
124
|
* Create a connection to the specified server.
|
116
|
-
*
|
125
|
+
*
|
117
126
|
* [+host+]
|
118
127
|
* server hostname
|
119
128
|
* [+hostaddr+]
|
@@ -140,24 +149,24 @@ pgconn_s_allocate( VALUE klass )
|
|
140
149
|
* GSS library to use for GSSAPI authentication
|
141
150
|
* [+service+]
|
142
151
|
* service name to use for additional parameters
|
143
|
-
*
|
152
|
+
*
|
144
153
|
* Examples:
|
145
|
-
*
|
154
|
+
*
|
146
155
|
* # Connect using all defaults
|
147
156
|
* PG::Connection.new
|
148
157
|
*
|
149
158
|
* # As a Hash
|
150
159
|
* PG::Connection.new( :dbname => 'test', :port => 5432 )
|
151
|
-
*
|
160
|
+
*
|
152
161
|
* # As a String
|
153
162
|
* PG::Connection.new( "dbname=test port=5432" )
|
154
|
-
*
|
163
|
+
*
|
155
164
|
* # As an Array
|
156
165
|
* PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
|
157
|
-
*
|
166
|
+
*
|
158
167
|
* If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
|
159
168
|
* connection will have its +client_encoding+ set accordingly.
|
160
|
-
*
|
169
|
+
*
|
161
170
|
* Raises a PG::Error if the connection fails.
|
162
171
|
*/
|
163
172
|
static VALUE
|
@@ -202,11 +211,11 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
202
211
|
*
|
203
212
|
* Use #connect_poll to poll the status of the connection.
|
204
213
|
*
|
205
|
-
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
206
|
-
* Encoding.default_internal is set. To set it after the connection is established,
|
207
|
-
* call #internal_encoding=. You can also set it automatically by setting
|
214
|
+
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
215
|
+
* Encoding.default_internal is set. To set it after the connection is established,
|
216
|
+
* call #internal_encoding=. You can also set it automatically by setting
|
208
217
|
* ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
|
209
|
-
*
|
218
|
+
*
|
210
219
|
*/
|
211
220
|
static VALUE
|
212
221
|
pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
@@ -266,7 +275,6 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
|
|
266
275
|
{
|
267
276
|
PGPing ping;
|
268
277
|
VALUE conninfo;
|
269
|
-
VALUE error;
|
270
278
|
|
271
279
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
272
280
|
ping = PQping( StringValuePtr(conninfo) );
|
@@ -333,7 +341,7 @@ pgconn_s_conndefaults(VALUE self)
|
|
333
341
|
*
|
334
342
|
* This function is intended to be used by client applications that
|
335
343
|
* send commands like: +ALTER USER joe PASSWORD 'pwd'+.
|
336
|
-
* The arguments are the cleartext password, and the SQL name
|
344
|
+
* The arguments are the cleartext password, and the SQL name
|
337
345
|
* of the user it is for.
|
338
346
|
*
|
339
347
|
* Return value is the encrypted password.
|
@@ -439,7 +447,7 @@ pgconn_finished_p( VALUE self )
|
|
439
447
|
* call-seq:
|
440
448
|
* conn.reset()
|
441
449
|
*
|
442
|
-
* Resets the backend connection. This method closes the
|
450
|
+
* Resets the backend connection. This method closes the
|
443
451
|
* backend connection and tries to re-connect.
|
444
452
|
*/
|
445
453
|
static VALUE
|
@@ -456,7 +464,7 @@ pgconn_reset(VALUE self)
|
|
456
464
|
* Initiate a connection reset in a nonblocking manner.
|
457
465
|
* This will close the current connection and attempt to
|
458
466
|
* reconnect using the same connection parameters.
|
459
|
-
* Use #reset_poll to check the status of the
|
467
|
+
* Use #reset_poll to check the status of the
|
460
468
|
* connection reset.
|
461
469
|
*/
|
462
470
|
static VALUE
|
@@ -617,14 +625,14 @@ pgconn_transaction_status(VALUE self)
|
|
617
625
|
* _param_name_ is one of
|
618
626
|
* * +server_version+
|
619
627
|
* * +server_encoding+
|
620
|
-
* * +client_encoding+
|
628
|
+
* * +client_encoding+
|
621
629
|
* * +is_superuser+
|
622
630
|
* * +session_authorization+
|
623
631
|
* * +DateStyle+
|
624
632
|
* * +TimeZone+
|
625
633
|
* * +integer_datetimes+
|
626
634
|
* * +standard_conforming_strings+
|
627
|
-
*
|
635
|
+
*
|
628
636
|
* Returns nil if the value of the parameter is not known.
|
629
637
|
*/
|
630
638
|
static VALUE
|
@@ -641,8 +649,8 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
641
649
|
* call-seq:
|
642
650
|
* conn.protocol_version -> Integer
|
643
651
|
*
|
644
|
-
* The 3.0 protocol will normally be used when communicating with PostgreSQL 7.4
|
645
|
-
* or later servers; pre-7.4 servers support only protocol 2.0. (Protocol 1.0 is
|
652
|
+
* The 3.0 protocol will normally be used when communicating with PostgreSQL 7.4
|
653
|
+
* or later servers; pre-7.4 servers support only protocol 2.0. (Protocol 1.0 is
|
646
654
|
* obsolete and not supported by libpq.)
|
647
655
|
*/
|
648
656
|
static VALUE
|
@@ -651,16 +659,16 @@ pgconn_protocol_version(VALUE self)
|
|
651
659
|
return INT2NUM(PQprotocolVersion(pg_get_pgconn(self)));
|
652
660
|
}
|
653
661
|
|
654
|
-
/*
|
655
|
-
* call-seq:
|
662
|
+
/*
|
663
|
+
* call-seq:
|
656
664
|
* conn.server_version -> Integer
|
657
|
-
*
|
665
|
+
*
|
658
666
|
* The number is formed by converting the major, minor, and revision
|
659
667
|
* numbers into two-decimal-digit numbers and appending them together.
|
660
668
|
* For example, version 7.4.2 will be returned as 70402, and version
|
661
669
|
* 8.1 will be returned as 80100 (leading zeroes are not shown). Zero
|
662
670
|
* is returned if the connection is bad.
|
663
|
-
*
|
671
|
+
*
|
664
672
|
*/
|
665
673
|
static VALUE
|
666
674
|
pgconn_server_version(VALUE self)
|
@@ -687,6 +695,15 @@ pgconn_error_message(VALUE self)
|
|
687
695
|
* conn.socket() -> Fixnum
|
688
696
|
*
|
689
697
|
* Returns the socket's file descriptor for this connection.
|
698
|
+
* <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
|
699
|
+
* If you do so, you will likely also want to set <tt>autoclose=false</tt>
|
700
|
+
* on it to prevent Ruby from closing the socket to PostgreSQL if it
|
701
|
+
* goes out of scope. Alternatively, you can use #socket_io, which
|
702
|
+
* creates an IO that's associated with the connection object itself,
|
703
|
+
* and so won't go out of scope until the connection does.
|
704
|
+
*
|
705
|
+
* *Note:* On Windows the file descriptor is not really usable,
|
706
|
+
* since it can not be used to build a Ruby IO object.
|
690
707
|
*/
|
691
708
|
static VALUE
|
692
709
|
pgconn_socket(VALUE self)
|
@@ -742,16 +759,64 @@ pgconn_connection_used_password(VALUE self)
|
|
742
759
|
/* :TODO: get_ssl */
|
743
760
|
|
744
761
|
|
762
|
+
static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
763
|
+
|
745
764
|
/*
|
746
765
|
* call-seq:
|
747
|
-
* conn.exec(sql
|
748
|
-
* conn.exec(sql
|
766
|
+
* conn.exec(sql) -> PG::Result
|
767
|
+
* conn.exec(sql) {|pg_result| block }
|
749
768
|
*
|
750
769
|
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
751
770
|
* Returns a PG::Result instance on success.
|
752
771
|
* On failure, it raises a PG::Error.
|
753
772
|
*
|
754
|
-
*
|
773
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
774
|
+
* it will call #exec_params for you. New code should explicitly use #exec_params if
|
775
|
+
* argument placeholders are used.
|
776
|
+
*
|
777
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
778
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
779
|
+
* In this instance, <code>conn.exec</code> returns the value of the block.
|
780
|
+
*/
|
781
|
+
static VALUE
|
782
|
+
pgconn_exec(int argc, VALUE *argv, VALUE self)
|
783
|
+
{
|
784
|
+
PGconn *conn = pg_get_pgconn(self);
|
785
|
+
PGresult *result = NULL;
|
786
|
+
VALUE rb_pgresult;
|
787
|
+
|
788
|
+
/* If called with no parameters, use PQexec */
|
789
|
+
if ( argc == 1 ) {
|
790
|
+
Check_Type(argv[0], T_STRING);
|
791
|
+
|
792
|
+
result = gvl_PQexec(conn, StringValuePtr(argv[0]));
|
793
|
+
rb_pgresult = pg_new_result(result, self);
|
794
|
+
pg_result_check(rb_pgresult);
|
795
|
+
if (rb_block_given_p()) {
|
796
|
+
return rb_ensure(rb_yield, rb_pgresult, pg_result_clear, rb_pgresult);
|
797
|
+
}
|
798
|
+
return rb_pgresult;
|
799
|
+
}
|
800
|
+
|
801
|
+
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
802
|
+
else {
|
803
|
+
return pgconn_exec_params( argc, argv, self );
|
804
|
+
}
|
805
|
+
|
806
|
+
}
|
807
|
+
|
808
|
+
|
809
|
+
/*
|
810
|
+
* call-seq:
|
811
|
+
* conn.exec_params(sql, params[, result_format ] ) -> PG::Result
|
812
|
+
* conn.exec_params(sql, params[, result_format ] ) {|pg_result| block }
|
813
|
+
*
|
814
|
+
* Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
|
815
|
+
* for parameters.
|
816
|
+
*
|
817
|
+
* Returns a PG::Result instance on success. On failure, it raises a PG::Error.
|
818
|
+
*
|
819
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
755
820
|
* Each element of the +params+ array may be either:
|
756
821
|
* a hash of the form:
|
757
822
|
* {:value => String (value of bind parameter)
|
@@ -760,11 +825,11 @@ pgconn_connection_used_password(VALUE self)
|
|
760
825
|
* }
|
761
826
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
762
827
|
* { :value => <string value>, :type => 0, :format => 0 }
|
763
|
-
*
|
828
|
+
*
|
764
829
|
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
765
830
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
766
831
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
767
|
-
*
|
832
|
+
*
|
768
833
|
* If the types are not specified, they will be inferred by PostgreSQL.
|
769
834
|
* Instead of specifying type oids, it's recommended to simply add
|
770
835
|
* explicit casts in the query to ensure that the right type is used.
|
@@ -774,12 +839,12 @@ pgconn_connection_used_password(VALUE self)
|
|
774
839
|
* The optional +result_format+ should be 0 for text results, 1
|
775
840
|
* for binary.
|
776
841
|
*
|
777
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
778
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
842
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
843
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
779
844
|
* In this instance, <code>conn.exec</code> returns the value of the block.
|
780
845
|
*/
|
781
846
|
static VALUE
|
782
|
-
|
847
|
+
pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
783
848
|
{
|
784
849
|
PGconn *conn = pg_get_pgconn(self);
|
785
850
|
PGresult *result = NULL;
|
@@ -799,25 +864,17 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
799
864
|
|
800
865
|
rb_scan_args(argc, argv, "12", &command, ¶ms, &in_res_fmt);
|
801
866
|
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
pg_result_check(rb_pgresult);
|
809
|
-
if (rb_block_given_p()) {
|
810
|
-
return rb_ensure(rb_yield, rb_pgresult, pg_result_clear, rb_pgresult);
|
867
|
+
/*
|
868
|
+
* Handle the edge-case where the caller is coming from #exec, but passed an explict +nil+
|
869
|
+
* for the second parameter.
|
870
|
+
*/
|
871
|
+
if ( NIL_P(params) ) {
|
872
|
+
return pgconn_exec( 1, argv, self );
|
811
873
|
}
|
812
|
-
return rb_pgresult;
|
813
|
-
}
|
814
874
|
|
815
|
-
/* If called with parameters, and optionally result_format,
|
816
|
-
* use PQexecParams
|
817
|
-
*/
|
818
875
|
Check_Type(params, T_ARRAY);
|
819
876
|
|
820
|
-
if(NIL_P(in_res_fmt)) {
|
877
|
+
if ( NIL_P(in_res_fmt) ) {
|
821
878
|
resultFormat = 0;
|
822
879
|
}
|
823
880
|
else {
|
@@ -826,15 +883,17 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
826
883
|
|
827
884
|
gc_array = rb_ary_new();
|
828
885
|
rb_gc_register_address(&gc_array);
|
886
|
+
|
829
887
|
sym_type = ID2SYM(rb_intern("type"));
|
830
888
|
sym_value = ID2SYM(rb_intern("value"));
|
831
889
|
sym_format = ID2SYM(rb_intern("format"));
|
832
890
|
nParams = (int)RARRAY_LEN(params);
|
833
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
891
|
+
paramTypes = ALLOC_N(Oid, nParams);
|
834
892
|
paramValues = ALLOC_N(char *, nParams);
|
835
893
|
paramLengths = ALLOC_N(int, nParams);
|
836
894
|
paramFormats = ALLOC_N(int, nParams);
|
837
|
-
|
895
|
+
|
896
|
+
for ( i = 0; i < nParams; i++ ) {
|
838
897
|
param = rb_ary_entry(params, i);
|
839
898
|
if (TYPE(param) == T_HASH) {
|
840
899
|
param_type = rb_hash_aref(param, sym_type);
|
@@ -877,7 +936,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
877
936
|
paramFormats[i] = NUM2INT(param_format);
|
878
937
|
}
|
879
938
|
|
880
|
-
result =
|
939
|
+
result = gvl_PQexecParams(conn, StringValuePtr(command), nParams, paramTypes,
|
881
940
|
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
882
941
|
|
883
942
|
rb_gc_unregister_address(&gc_array);
|
@@ -889,10 +948,11 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
889
948
|
|
890
949
|
rb_pgresult = pg_new_result(result, self);
|
891
950
|
pg_result_check(rb_pgresult);
|
951
|
+
|
892
952
|
if (rb_block_given_p()) {
|
893
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
894
|
-
pg_result_clear, rb_pgresult);
|
953
|
+
return rb_ensure(rb_yield, rb_pgresult, pg_result_clear, rb_pgresult);
|
895
954
|
}
|
955
|
+
|
896
956
|
return rb_pgresult;
|
897
957
|
}
|
898
958
|
|
@@ -904,7 +964,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
904
964
|
* Returns a PG::Result instance on success.
|
905
965
|
* On failure, it raises a PG::Error.
|
906
966
|
*
|
907
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
967
|
+
* +param_types+ is an optional parameter to specify the Oids of the
|
908
968
|
* types of the parameters.
|
909
969
|
*
|
910
970
|
* If the types are not specified, they will be inferred by PostgreSQL.
|
@@ -912,7 +972,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
912
972
|
* explicit casts in the query to ensure that the right type is used.
|
913
973
|
*
|
914
974
|
* For example: "SELECT $1::int"
|
915
|
-
*
|
975
|
+
*
|
916
976
|
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
917
977
|
* inside the SQL query.
|
918
978
|
*/
|
@@ -935,7 +995,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
935
995
|
if(! NIL_P(in_paramtypes)) {
|
936
996
|
Check_Type(in_paramtypes, T_ARRAY);
|
937
997
|
nParams = (int)RARRAY_LEN(in_paramtypes);
|
938
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
998
|
+
paramTypes = ALLOC_N(Oid, nParams);
|
939
999
|
for(i = 0; i < nParams; i++) {
|
940
1000
|
param = rb_ary_entry(in_paramtypes, i);
|
941
1001
|
Check_Type(param, T_FIXNUM);
|
@@ -945,7 +1005,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
945
1005
|
paramTypes[i] = NUM2INT(param);
|
946
1006
|
}
|
947
1007
|
}
|
948
|
-
result =
|
1008
|
+
result = gvl_PQprepare(conn, StringValuePtr(name), StringValuePtr(command),
|
949
1009
|
nParams, paramTypes);
|
950
1010
|
|
951
1011
|
xfree(paramTypes);
|
@@ -964,7 +1024,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
964
1024
|
* Returns a PG::Result instance on success.
|
965
1025
|
* On failure, it raises a PG::Error.
|
966
1026
|
*
|
967
|
-
* +params+ is an array of the optional bind parameters for the
|
1027
|
+
* +params+ is an array of the optional bind parameters for the
|
968
1028
|
* SQL query. Each element of the +params+ array may be either:
|
969
1029
|
* a hash of the form:
|
970
1030
|
* {:value => String (value of bind parameter)
|
@@ -972,7 +1032,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
972
1032
|
* }
|
973
1033
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
974
1034
|
* { :value => <string value>, :format => 0 }
|
975
|
-
*
|
1035
|
+
*
|
976
1036
|
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
977
1037
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
978
1038
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
@@ -980,8 +1040,8 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
980
1040
|
* The optional +result_format+ should be 0 for text results, 1
|
981
1041
|
* for binary.
|
982
1042
|
*
|
983
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
984
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
1043
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1044
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
985
1045
|
* In this instance, <code>conn.exec_prepared</code> returns the value of the block.
|
986
1046
|
*/
|
987
1047
|
static VALUE
|
@@ -1064,8 +1124,8 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1064
1124
|
paramFormats[i] = NUM2INT(param_format);
|
1065
1125
|
}
|
1066
1126
|
|
1067
|
-
result =
|
1068
|
-
(const char * const *)paramValues, paramLengths, paramFormats,
|
1127
|
+
result = gvl_PQexecPrepared(conn, StringValuePtr(name), nParams,
|
1128
|
+
(const char * const *)paramValues, paramLengths, paramFormats,
|
1069
1129
|
resultFormat);
|
1070
1130
|
|
1071
1131
|
rb_gc_unregister_address(&gc_array);
|
@@ -1077,7 +1137,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1077
1137
|
rb_pgresult = pg_new_result(result, self);
|
1078
1138
|
pg_result_check(rb_pgresult);
|
1079
1139
|
if (rb_block_given_p()) {
|
1080
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1140
|
+
return rb_ensure(rb_yield, rb_pgresult,
|
1081
1141
|
pg_result_clear, rb_pgresult);
|
1082
1142
|
}
|
1083
1143
|
return rb_pgresult;
|
@@ -1104,7 +1164,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1104
1164
|
Check_Type(stmt_name, T_STRING);
|
1105
1165
|
stmt = StringValuePtr(stmt_name);
|
1106
1166
|
}
|
1107
|
-
result =
|
1167
|
+
result = gvl_PQdescribePrepared(conn, stmt);
|
1108
1168
|
rb_pgresult = pg_new_result(result, self);
|
1109
1169
|
pg_result_check(rb_pgresult);
|
1110
1170
|
return rb_pgresult;
|
@@ -1132,7 +1192,7 @@ pgconn_describe_portal(self, stmt_name)
|
|
1132
1192
|
Check_Type(stmt_name, T_STRING);
|
1133
1193
|
stmt = StringValuePtr(stmt_name);
|
1134
1194
|
}
|
1135
|
-
result =
|
1195
|
+
result = gvl_PQdescribePortal(conn, stmt);
|
1136
1196
|
rb_pgresult = pg_new_result(result, self);
|
1137
1197
|
pg_result_check(rb_pgresult);
|
1138
1198
|
return rb_pgresult;
|
@@ -1175,12 +1235,12 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
1175
1235
|
* Connection instance method for versions of 8.1 and higher of libpq
|
1176
1236
|
* uses PQescapeStringConn, which is safer. Avoid calling as a class method,
|
1177
1237
|
* the class method uses the deprecated PQescapeString() API function.
|
1178
|
-
*
|
1238
|
+
*
|
1179
1239
|
* Returns a SQL-safe version of the String _str_.
|
1180
|
-
* This is the preferred way to make strings safe for inclusion in
|
1240
|
+
* This is the preferred way to make strings safe for inclusion in
|
1181
1241
|
* SQL queries.
|
1182
|
-
*
|
1183
|
-
* Consider using exec_params, which avoids the need for passing values
|
1242
|
+
*
|
1243
|
+
* Consider using exec_params, which avoids the need for passing values
|
1184
1244
|
* inside of SQL commands.
|
1185
1245
|
*
|
1186
1246
|
* Encoding of escaped string will be equal to client encoding of connection.
|
@@ -1192,7 +1252,7 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1192
1252
|
size_t size;
|
1193
1253
|
int error;
|
1194
1254
|
VALUE result;
|
1195
|
-
#ifdef M17N_SUPPORTED
|
1255
|
+
#ifdef M17N_SUPPORTED
|
1196
1256
|
rb_encoding* enc;
|
1197
1257
|
#endif
|
1198
1258
|
|
@@ -1200,7 +1260,7 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1200
1260
|
|
1201
1261
|
escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
|
1202
1262
|
if(rb_obj_class(self) == rb_cPGconn) {
|
1203
|
-
size = PQescapeStringConn(pg_get_pgconn(self), escaped,
|
1263
|
+
size = PQescapeStringConn(pg_get_pgconn(self), escaped,
|
1204
1264
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1205
1265
|
if(error) {
|
1206
1266
|
xfree(escaped);
|
@@ -1227,7 +1287,7 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1227
1287
|
|
1228
1288
|
/*
|
1229
1289
|
* call-seq:
|
1230
|
-
* conn.escape_bytea( string ) -> String
|
1290
|
+
* conn.escape_bytea( string ) -> String
|
1231
1291
|
*
|
1232
1292
|
* Connection instance method for versions of 8.1 and higher of libpq
|
1233
1293
|
* uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
|
@@ -1237,16 +1297,16 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1237
1297
|
* class method.
|
1238
1298
|
*
|
1239
1299
|
* Escapes binary data for use within an SQL command with the type +bytea+.
|
1240
|
-
*
|
1300
|
+
*
|
1241
1301
|
* Certain byte values must be escaped (but all byte values may be escaped)
|
1242
1302
|
* when used as part of a +bytea+ literal in an SQL statement. In general, to
|
1243
1303
|
* escape a byte, it is converted into the three digit octal number equal to
|
1244
1304
|
* the octet value, and preceded by two backslashes. The single quote (') and
|
1245
1305
|
* backslash (\) characters have special alternative escape sequences.
|
1246
|
-
* #escape_bytea performs this operation, escaping only the minimally required
|
1306
|
+
* #escape_bytea performs this operation, escaping only the minimally required
|
1247
1307
|
* bytes.
|
1248
|
-
*
|
1249
|
-
* Consider using exec_params, which avoids the need for passing values inside of
|
1308
|
+
*
|
1309
|
+
* Consider using exec_params, which avoids the need for passing values inside of
|
1250
1310
|
* SQL commands.
|
1251
1311
|
*/
|
1252
1312
|
static VALUE
|
@@ -1368,6 +1428,61 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1368
1428
|
}
|
1369
1429
|
#endif
|
1370
1430
|
|
1431
|
+
#ifdef HAVE_PQSETSINGLEROWMODE
|
1432
|
+
/*
|
1433
|
+
* call-seq:
|
1434
|
+
* conn.set_single_row_mode -> self
|
1435
|
+
*
|
1436
|
+
* To enter single-row mode, call this method immediately after a successful
|
1437
|
+
* call of send_query (or a sibling function). This mode selection is effective
|
1438
|
+
* only for the currently executing query.
|
1439
|
+
* Then call Connection#get_result repeatedly, until it returns nil.
|
1440
|
+
*
|
1441
|
+
* Each (but the last) received Result has exactly one row and a
|
1442
|
+
* Result#result_status of PGRES_SINGLE_TUPLE. The last row has
|
1443
|
+
* zero rows and is used to indicate a successful execution of the query.
|
1444
|
+
* All of these Result objects will contain the same row description data
|
1445
|
+
* (column names, types, etc) that an ordinary Result object for the query
|
1446
|
+
* would have.
|
1447
|
+
*
|
1448
|
+
* *Caution:* While processing a query, the server may return some rows and
|
1449
|
+
* then encounter an error, causing the query to be aborted. Ordinarily, pg
|
1450
|
+
* discards any such rows and reports only the error. But in single-row mode,
|
1451
|
+
* those rows will have already been returned to the application. Hence, the
|
1452
|
+
* application will see some Result objects followed by an Error raised in get_result.
|
1453
|
+
* For proper transactional behavior, the application must be designed to discard
|
1454
|
+
* or undo whatever has been done with the previously-processed rows, if the query
|
1455
|
+
* ultimately fails.
|
1456
|
+
*
|
1457
|
+
* Example:
|
1458
|
+
* conn.send_query( "your SQL command" )
|
1459
|
+
* conn.set_single_row_mode
|
1460
|
+
* loop do
|
1461
|
+
* res = conn.get_result or break
|
1462
|
+
* res.check
|
1463
|
+
* res.each do |row|
|
1464
|
+
* # do something with the received row
|
1465
|
+
* end
|
1466
|
+
* end
|
1467
|
+
*
|
1468
|
+
*/
|
1469
|
+
static VALUE
|
1470
|
+
pgconn_set_single_row_mode(VALUE self)
|
1471
|
+
{
|
1472
|
+
PGconn *conn = pg_get_pgconn(self);
|
1473
|
+
VALUE error;
|
1474
|
+
|
1475
|
+
if( PQsetSingleRowMode(conn) == 0 )
|
1476
|
+
{
|
1477
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
1478
|
+
rb_iv_set(error, "@connection", self);
|
1479
|
+
rb_exc_raise(error);
|
1480
|
+
}
|
1481
|
+
|
1482
|
+
return self;
|
1483
|
+
}
|
1484
|
+
#endif
|
1485
|
+
|
1371
1486
|
/*
|
1372
1487
|
* call-seq:
|
1373
1488
|
* conn.send_query(sql [, params, result_format ] ) -> nil
|
@@ -1385,11 +1500,11 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1385
1500
|
* }
|
1386
1501
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1387
1502
|
* { :value => <string value>, :type => 0, :format => 0 }
|
1388
|
-
*
|
1503
|
+
*
|
1389
1504
|
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1390
1505
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1391
1506
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1392
|
-
*
|
1507
|
+
*
|
1393
1508
|
* If the types are not specified, they will be inferred by PostgreSQL.
|
1394
1509
|
* Instead of specifying type oids, it's recommended to simply add
|
1395
1510
|
* explicit casts in the query to ensure that the right type is used.
|
@@ -1449,7 +1564,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1449
1564
|
sym_value = ID2SYM(rb_intern("value"));
|
1450
1565
|
sym_format = ID2SYM(rb_intern("format"));
|
1451
1566
|
nParams = (int)RARRAY_LEN(params);
|
1452
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1567
|
+
paramTypes = ALLOC_N(Oid, nParams);
|
1453
1568
|
paramValues = ALLOC_N(char *, nParams);
|
1454
1569
|
paramLengths = ALLOC_N(int, nParams);
|
1455
1570
|
paramFormats = ALLOC_N(int, nParams);
|
@@ -1496,10 +1611,10 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1496
1611
|
paramFormats[i] = NUM2INT(param_format);
|
1497
1612
|
}
|
1498
1613
|
|
1499
|
-
result = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1614
|
+
result = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1500
1615
|
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1501
1616
|
|
1502
|
-
rb_gc_unregister_address(&gc_array);
|
1617
|
+
rb_gc_unregister_address(&gc_array);
|
1503
1618
|
|
1504
1619
|
xfree(paramTypes);
|
1505
1620
|
xfree(paramValues);
|
@@ -1522,7 +1637,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1522
1637
|
* Sends prepare command asynchronously, and returns immediately.
|
1523
1638
|
* On failure, it raises a PG::Error.
|
1524
1639
|
*
|
1525
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1640
|
+
* +param_types+ is an optional parameter to specify the Oids of the
|
1526
1641
|
* types of the parameters.
|
1527
1642
|
*
|
1528
1643
|
* If the types are not specified, they will be inferred by PostgreSQL.
|
@@ -1530,7 +1645,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1530
1645
|
* explicit casts in the query to ensure that the right type is used.
|
1531
1646
|
*
|
1532
1647
|
* For example: "SELECT $1::int"
|
1533
|
-
*
|
1648
|
+
*
|
1534
1649
|
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1535
1650
|
* inside the SQL query.
|
1536
1651
|
*/
|
@@ -1553,7 +1668,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1553
1668
|
if(! NIL_P(in_paramtypes)) {
|
1554
1669
|
Check_Type(in_paramtypes, T_ARRAY);
|
1555
1670
|
nParams = (int)RARRAY_LEN(in_paramtypes);
|
1556
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1671
|
+
paramTypes = ALLOC_N(Oid, nParams);
|
1557
1672
|
for(i = 0; i < nParams; i++) {
|
1558
1673
|
param = rb_ary_entry(in_paramtypes, i);
|
1559
1674
|
Check_Type(param, T_FIXNUM);
|
@@ -1585,7 +1700,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1585
1700
|
* asynchronously, and returns immediately.
|
1586
1701
|
* On failure, it raises a PG::Error.
|
1587
1702
|
*
|
1588
|
-
* +params+ is an array of the optional bind parameters for the
|
1703
|
+
* +params+ is an array of the optional bind parameters for the
|
1589
1704
|
* SQL query. Each element of the +params+ array may be either:
|
1590
1705
|
* a hash of the form:
|
1591
1706
|
* {:value => String (value of bind parameter)
|
@@ -1593,7 +1708,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1593
1708
|
* }
|
1594
1709
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1595
1710
|
* { :value => <string value>, :format => 0 }
|
1596
|
-
*
|
1711
|
+
*
|
1597
1712
|
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1598
1713
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1599
1714
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
@@ -1681,8 +1796,8 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1681
1796
|
paramFormats[i] = NUM2INT(param_format);
|
1682
1797
|
}
|
1683
1798
|
|
1684
|
-
result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
|
1685
|
-
(const char * const *)paramValues, paramLengths, paramFormats,
|
1799
|
+
result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
|
1800
|
+
(const char * const *)paramValues, paramLengths, paramFormats,
|
1686
1801
|
resultFormat);
|
1687
1802
|
|
1688
1803
|
rb_gc_unregister_address(&gc_array);
|
@@ -1703,7 +1818,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1703
1818
|
* call-seq:
|
1704
1819
|
* conn.send_describe_prepared( statement_name ) -> nil
|
1705
1820
|
*
|
1706
|
-
* Asynchronously send _command_ to the server. Does not block.
|
1821
|
+
* Asynchronously send _command_ to the server. Does not block.
|
1707
1822
|
* Use in combination with +conn.get_result+.
|
1708
1823
|
*/
|
1709
1824
|
static VALUE
|
@@ -1725,7 +1840,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1725
1840
|
* call-seq:
|
1726
1841
|
* conn.send_describe_portal( portal_name ) -> nil
|
1727
1842
|
*
|
1728
|
-
* Asynchronously send _command_ to the server. Does not block.
|
1843
|
+
* Asynchronously send _command_ to the server. Does not block.
|
1729
1844
|
* Use in combination with +conn.get_result+.
|
1730
1845
|
*/
|
1731
1846
|
static VALUE
|
@@ -1755,8 +1870,8 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
1755
1870
|
* Note: call this function repeatedly until it returns +nil+, or else
|
1756
1871
|
* you will not be able to issue further commands.
|
1757
1872
|
*
|
1758
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1759
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
1873
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1874
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
1760
1875
|
* In this instance, <code>conn.exec</code> returns the value of the block.
|
1761
1876
|
*/
|
1762
1877
|
static VALUE
|
@@ -1766,7 +1881,7 @@ pgconn_get_result(VALUE self)
|
|
1766
1881
|
PGresult *result;
|
1767
1882
|
VALUE rb_pgresult;
|
1768
1883
|
|
1769
|
-
result =
|
1884
|
+
result = gvl_PQgetResult(conn);
|
1770
1885
|
if(result == NULL)
|
1771
1886
|
return Qnil;
|
1772
1887
|
rb_pgresult = pg_new_result(result, self);
|
@@ -1818,7 +1933,7 @@ pgconn_is_busy(self)
|
|
1818
1933
|
* call-seq:
|
1819
1934
|
* conn.setnonblocking(Boolean) -> nil
|
1820
1935
|
*
|
1821
|
-
* Sets the nonblocking status of the connection.
|
1936
|
+
* Sets the nonblocking status of the connection.
|
1822
1937
|
* In the blocking state, calls to #send_query
|
1823
1938
|
* will block until the message is sent to the server,
|
1824
1939
|
* but will not wait for the query results.
|
@@ -1826,7 +1941,7 @@ pgconn_is_busy(self)
|
|
1826
1941
|
* will return an error if the socket is not ready for
|
1827
1942
|
* writing.
|
1828
1943
|
* Note: This function does not affect #exec, because
|
1829
|
-
* that function doesn't return until the server has
|
1944
|
+
* that function doesn't return until the server has
|
1830
1945
|
* processed the query and returned the results.
|
1831
1946
|
* Returns +nil+.
|
1832
1947
|
*/
|
@@ -1959,6 +2074,10 @@ pgconn_notifies(VALUE self)
|
|
1959
2074
|
relname = rb_tainted_str_new2(notification->relname);
|
1960
2075
|
be_pid = INT2NUM(notification->be_pid);
|
1961
2076
|
extra = rb_tainted_str_new2(notification->extra);
|
2077
|
+
#ifdef M17N_SUPPORTED
|
2078
|
+
ENCODING_SET( relname, rb_enc_to_index(pg_conn_enc_get( conn )) );
|
2079
|
+
ENCODING_SET( extra, rb_enc_to_index(pg_conn_enc_get( conn )) );
|
2080
|
+
#endif
|
1962
2081
|
|
1963
2082
|
rb_hash_aset(hash, sym_relname, relname);
|
1964
2083
|
rb_hash_aset(hash, sym_be_pid, be_pid);
|
@@ -1968,9 +2087,10 @@ pgconn_notifies(VALUE self)
|
|
1968
2087
|
return hash;
|
1969
2088
|
}
|
1970
2089
|
|
2090
|
+
/* Win32 + Ruby 1.8 */
|
2091
|
+
#if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
|
1971
2092
|
|
1972
|
-
|
1973
|
-
/*
|
2093
|
+
/*
|
1974
2094
|
* Duplicate the sockets from libpq and create temporary CRT FDs
|
1975
2095
|
*/
|
1976
2096
|
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
@@ -2004,6 +2124,149 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
|
2004
2124
|
}
|
2005
2125
|
#endif
|
2006
2126
|
|
2127
|
+
/* Win32 + Ruby 1.9+ */
|
2128
|
+
#if defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
|
2129
|
+
/*
|
2130
|
+
* On Windows, use platform-specific strategies to wait for the socket
|
2131
|
+
* instead of rb_thread_select().
|
2132
|
+
*/
|
2133
|
+
|
2134
|
+
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2135
|
+
|
2136
|
+
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2137
|
+
* and does not wait (nor sleep) any time even if timeout is given.
|
2138
|
+
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2139
|
+
|
2140
|
+
static void *
|
2141
|
+
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
|
2142
|
+
{
|
2143
|
+
int sd = PQsocket( conn );
|
2144
|
+
void *retval;
|
2145
|
+
DWORD timeout_milisec = INFINITE;
|
2146
|
+
DWORD wait_ret;
|
2147
|
+
WSAEVENT hEvent;
|
2148
|
+
|
2149
|
+
if ( sd < 0 )
|
2150
|
+
rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
|
2151
|
+
|
2152
|
+
hEvent = WSACreateEvent();
|
2153
|
+
|
2154
|
+
if ( ptimeout ) {
|
2155
|
+
timeout_milisec = (DWORD)( ptimeout->tv_sec * 1e3 + ptimeout->tv_usec / 1e3 );
|
2156
|
+
}
|
2157
|
+
|
2158
|
+
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2159
|
+
if( PQconsumeInput(conn) == 0 ) {
|
2160
|
+
WSACloseEvent( hEvent );
|
2161
|
+
rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
|
2162
|
+
}
|
2163
|
+
|
2164
|
+
while ( !(retval=is_readable(conn)) ) {
|
2165
|
+
if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
|
2166
|
+
WSACloseEvent( hEvent );
|
2167
|
+
rb_raise( rb_ePGerror, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
2171
|
+
|
2172
|
+
if ( wait_ret == WAIT_TIMEOUT ) {
|
2173
|
+
WSACloseEvent( hEvent );
|
2174
|
+
return NULL;
|
2175
|
+
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2176
|
+
/* The event we were waiting for. */
|
2177
|
+
} else if ( wait_ret == WAIT_FAILED ) {
|
2178
|
+
WSACloseEvent( hEvent );
|
2179
|
+
rb_raise( rb_ePGerror, "Wait on socket error (WaitForMultipleObjects): %d", GetLastError() );
|
2180
|
+
} else {
|
2181
|
+
WSACloseEvent( hEvent );
|
2182
|
+
rb_raise( rb_ePGerror, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2183
|
+
}
|
2184
|
+
|
2185
|
+
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2186
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
2187
|
+
WSACloseEvent( hEvent );
|
2188
|
+
rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
|
2189
|
+
}
|
2190
|
+
}
|
2191
|
+
|
2192
|
+
WSACloseEvent( hEvent );
|
2193
|
+
return retval;
|
2194
|
+
}
|
2195
|
+
|
2196
|
+
#else
|
2197
|
+
|
2198
|
+
/* non Win32 or Win32+Ruby-1.8 */
|
2199
|
+
|
2200
|
+
static void *
|
2201
|
+
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
2202
|
+
{
|
2203
|
+
int sd = PQsocket( conn );
|
2204
|
+
int ret;
|
2205
|
+
void *retval;
|
2206
|
+
rb_fdset_t sd_rset;
|
2207
|
+
#ifdef _WIN32
|
2208
|
+
rb_fdset_t crt_sd_rset;
|
2209
|
+
#endif
|
2210
|
+
|
2211
|
+
if ( sd < 0 )
|
2212
|
+
rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
|
2213
|
+
|
2214
|
+
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2215
|
+
if ( PQconsumeInput(conn) == 0 )
|
2216
|
+
rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
|
2217
|
+
|
2218
|
+
rb_fd_init( &sd_rset );
|
2219
|
+
|
2220
|
+
while ( !(retval=is_readable(conn)) ) {
|
2221
|
+
rb_fd_zero( &sd_rset );
|
2222
|
+
rb_fd_set( sd, &sd_rset );
|
2223
|
+
|
2224
|
+
#ifdef _WIN32
|
2225
|
+
/* Ruby's FD_SET is modified on win32 to convert a file descriptor
|
2226
|
+
* to osfhandle, but we already get a osfhandle from PQsocket().
|
2227
|
+
* Therefore it's overwritten here. */
|
2228
|
+
sd_rset.fd_array[0] = sd;
|
2229
|
+
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2230
|
+
#endif
|
2231
|
+
|
2232
|
+
/* Wait for the socket to become readable before checking again */
|
2233
|
+
ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2234
|
+
|
2235
|
+
#ifdef _WIN32
|
2236
|
+
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2237
|
+
#endif
|
2238
|
+
|
2239
|
+
if ( ret < 0 ){
|
2240
|
+
rb_fd_term( &sd_rset );
|
2241
|
+
rb_sys_fail( "rb_thread_select()" );
|
2242
|
+
}
|
2243
|
+
|
2244
|
+
/* Return false if the select() timed out */
|
2245
|
+
if ( ret == 0 ){
|
2246
|
+
rb_fd_term( &sd_rset );
|
2247
|
+
return NULL;
|
2248
|
+
}
|
2249
|
+
|
2250
|
+
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2251
|
+
if ( PQconsumeInput(conn) == 0 ){
|
2252
|
+
rb_fd_term( &sd_rset );
|
2253
|
+
rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
|
2254
|
+
}
|
2255
|
+
}
|
2256
|
+
|
2257
|
+
rb_fd_term( &sd_rset );
|
2258
|
+
return retval;
|
2259
|
+
}
|
2260
|
+
|
2261
|
+
|
2262
|
+
#endif
|
2263
|
+
|
2264
|
+
static void *
|
2265
|
+
notify_readable(PGconn *conn)
|
2266
|
+
{
|
2267
|
+
return (void*)PQnotifies(conn);
|
2268
|
+
}
|
2269
|
+
|
2007
2270
|
/*
|
2008
2271
|
* call-seq:
|
2009
2272
|
* conn.wait_for_notify( [ timeout ] ) -> String
|
@@ -2017,30 +2280,21 @@ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
|
2017
2280
|
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2018
2281
|
* event otherwise. If used in block form, passes the name of the
|
2019
2282
|
* NOTIFY +event+ and the generating +pid+ into the block.
|
2020
|
-
*
|
2283
|
+
*
|
2021
2284
|
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2022
2285
|
* the optional +payload+ string, it will be given to the block as the
|
2023
2286
|
* third argument.
|
2024
|
-
*
|
2287
|
+
*
|
2025
2288
|
*/
|
2026
2289
|
static VALUE
|
2027
2290
|
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
2028
2291
|
{
|
2029
2292
|
PGconn *conn = pg_get_pgconn( self );
|
2030
|
-
PGnotify *
|
2031
|
-
int sd = PQsocket( conn );
|
2032
|
-
int ret;
|
2293
|
+
PGnotify *pnotification;
|
2033
2294
|
struct timeval timeout;
|
2034
2295
|
struct timeval *ptimeout = NULL;
|
2035
2296
|
VALUE timeout_in = Qnil, relname = Qnil, be_pid = Qnil, extra = Qnil;
|
2036
2297
|
double timeout_sec;
|
2037
|
-
fd_set sd_rset;
|
2038
|
-
#ifdef _WIN32
|
2039
|
-
fd_set crt_sd_rset;
|
2040
|
-
#endif
|
2041
|
-
|
2042
|
-
if ( sd < 0 )
|
2043
|
-
rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
|
2044
2298
|
|
2045
2299
|
rb_scan_args( argc, argv, "01", &timeout_in );
|
2046
2300
|
|
@@ -2051,43 +2305,25 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2051
2305
|
ptimeout = &timeout;
|
2052
2306
|
}
|
2053
2307
|
|
2054
|
-
|
2055
|
-
while ( (notification = PQnotifies(conn)) == NULL ) {
|
2056
|
-
FD_ZERO( &sd_rset );
|
2057
|
-
FD_SET( sd, &sd_rset );
|
2058
|
-
|
2059
|
-
#ifdef _WIN32
|
2060
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2061
|
-
#endif
|
2308
|
+
pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
|
2062
2309
|
|
2063
|
-
|
2064
|
-
|
2310
|
+
/* Return nil if the select timed out */
|
2311
|
+
if ( !pnotification ) return Qnil;
|
2065
2312
|
|
2066
|
-
|
2067
|
-
|
2313
|
+
relname = rb_tainted_str_new2( pnotification->relname );
|
2314
|
+
#ifdef M17N_SUPPORTED
|
2315
|
+
ENCODING_SET( relname, rb_enc_to_index(pg_conn_enc_get( conn )) );
|
2068
2316
|
#endif
|
2069
|
-
|
2070
|
-
if ( ret < 0 )
|
2071
|
-
rb_sys_fail( 0 );
|
2072
|
-
|
2073
|
-
/* Return nil if the select timed out */
|
2074
|
-
if ( ret == 0 ) return Qnil;
|
2075
|
-
|
2076
|
-
/* Read the socket */
|
2077
|
-
if ( (ret = PQconsumeInput(conn)) != 1 )
|
2078
|
-
rb_raise( rb_ePGerror, "PQconsumeInput == %d: %s", ret, PQerrorMessage(conn) );
|
2079
|
-
}
|
2080
|
-
|
2081
|
-
relname = rb_tainted_str_new2( notification->relname );
|
2082
|
-
ASSOCIATE_INDEX( relname, self );
|
2083
|
-
be_pid = INT2NUM( notification->be_pid );
|
2317
|
+
be_pid = INT2NUM( pnotification->be_pid );
|
2084
2318
|
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2085
|
-
if ( *
|
2086
|
-
extra = rb_tainted_str_new2(
|
2087
|
-
|
2319
|
+
if ( *pnotification->extra ) {
|
2320
|
+
extra = rb_tainted_str_new2( pnotification->extra );
|
2321
|
+
#ifdef M17N_SUPPORTED
|
2322
|
+
ENCODING_SET( extra, rb_enc_to_index(pg_conn_enc_get( conn )) );
|
2323
|
+
#endif
|
2088
2324
|
}
|
2089
2325
|
#endif
|
2090
|
-
PQfreemem(
|
2326
|
+
PQfreemem( pnotification );
|
2091
2327
|
|
2092
2328
|
if ( rb_block_given_p() )
|
2093
2329
|
rb_yield_values( 3, relname, be_pid, extra );
|
@@ -2116,7 +2352,7 @@ pgconn_put_copy_data(self, buffer)
|
|
2116
2352
|
PGconn *conn = pg_get_pgconn(self);
|
2117
2353
|
Check_Type(buffer, T_STRING);
|
2118
2354
|
|
2119
|
-
ret =
|
2355
|
+
ret = gvl_PQputCopyData(conn, RSTRING_PTR(buffer), (int)RSTRING_LEN(buffer));
|
2120
2356
|
if(ret == -1) {
|
2121
2357
|
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
2122
2358
|
rb_iv_set(error, "@connection", self);
|
@@ -2138,7 +2374,7 @@ pgconn_put_copy_data(self, buffer)
|
|
2138
2374
|
* Returns true if the end-of-data was sent, false if it was
|
2139
2375
|
* not sent (false is only possible if the connection
|
2140
2376
|
* is in nonblocking mode, and this command would block).
|
2141
|
-
*/
|
2377
|
+
*/
|
2142
2378
|
static VALUE
|
2143
2379
|
pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2144
2380
|
{
|
@@ -2153,7 +2389,7 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2153
2389
|
else
|
2154
2390
|
error_message = StringValuePtr(str);
|
2155
2391
|
|
2156
|
-
ret =
|
2392
|
+
ret = gvl_PQputCopyEnd(conn, error_message);
|
2157
2393
|
if(ret == -1) {
|
2158
2394
|
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
2159
2395
|
rb_iv_set(error, "@connection", self);
|
@@ -2167,7 +2403,7 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2167
2403
|
* conn.get_copy_data( [ async = false ] ) -> String
|
2168
2404
|
*
|
2169
2405
|
* Return a string containing one row of data, +nil+
|
2170
|
-
* if the copy is done, or +false+ if the call would
|
2406
|
+
* if the copy is done, or +false+ if the call would
|
2171
2407
|
* block (only possible if _async_ is true).
|
2172
2408
|
*
|
2173
2409
|
*/
|
@@ -2187,7 +2423,7 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2187
2423
|
else
|
2188
2424
|
async = (async_in == Qfalse || async_in == Qnil) ? 0 : 1;
|
2189
2425
|
|
2190
|
-
ret =
|
2426
|
+
ret = gvl_PQgetCopyData(conn, &buffer, async);
|
2191
2427
|
if(ret == -2) { /* error */
|
2192
2428
|
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
2193
2429
|
rb_iv_set(error, "@connection", self);
|
@@ -2225,8 +2461,8 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2225
2461
|
/*
|
2226
2462
|
* call-seq:
|
2227
2463
|
* conn.trace( stream ) -> nil
|
2228
|
-
*
|
2229
|
-
* Enables tracing message passing between backend. The
|
2464
|
+
*
|
2465
|
+
* Enables tracing message passing between backend. The
|
2230
2466
|
* trace message will be written to the stream _stream_,
|
2231
2467
|
* which must implement a method +fileno+ that returns
|
2232
2468
|
* a writable file descriptor.
|
@@ -2269,7 +2505,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2269
2505
|
/*
|
2270
2506
|
* call-seq:
|
2271
2507
|
* conn.untrace() -> nil
|
2272
|
-
*
|
2508
|
+
*
|
2273
2509
|
* Disables the message tracing.
|
2274
2510
|
*/
|
2275
2511
|
static VALUE
|
@@ -2288,15 +2524,20 @@ pgconn_untrace(VALUE self)
|
|
2288
2524
|
* Notice callback proxy function -- delegate the callback to the
|
2289
2525
|
* currently-registered Ruby notice_receiver object.
|
2290
2526
|
*/
|
2291
|
-
|
2527
|
+
void
|
2292
2528
|
notice_receiver_proxy(void *arg, const PGresult *result)
|
2293
2529
|
{
|
2294
2530
|
VALUE proc;
|
2295
2531
|
VALUE self = (VALUE)arg;
|
2296
2532
|
|
2297
2533
|
if ((proc = rb_iv_get(self, "@notice_receiver")) != Qnil) {
|
2298
|
-
|
2299
|
-
|
2534
|
+
VALUE val = Data_Wrap_Struct(rb_cPGresult, NULL, NULL, (PGresult*)result);
|
2535
|
+
#ifdef M17N_SUPPORTED
|
2536
|
+
PGconn *conn = pg_get_pgconn( self );
|
2537
|
+
rb_encoding *enc = pg_conn_enc_get( conn );
|
2538
|
+
ENCODING_SET( val, rb_enc_to_index(enc) );
|
2539
|
+
#endif
|
2540
|
+
rb_funcall(proc, rb_intern("call"), 1, val);
|
2300
2541
|
}
|
2301
2542
|
return;
|
2302
2543
|
}
|
@@ -2313,15 +2554,15 @@ notice_receiver_proxy(void *arg, const PGresult *result)
|
|
2313
2554
|
* application can override this behavior by supplying its own handling
|
2314
2555
|
* function.
|
2315
2556
|
*
|
2316
|
-
* For historical reasons, there are two levels of notice handling, called the
|
2317
|
-
* notice receiver and notice processor. The default behavior is for the notice
|
2318
|
-
* receiver to format the notice and pass a string to the notice processor for
|
2319
|
-
* printing. However, an application that chooses to provide its own notice
|
2320
|
-
* receiver will typically ignore the notice processor layer and just do all
|
2557
|
+
* For historical reasons, there are two levels of notice handling, called the
|
2558
|
+
* notice receiver and notice processor. The default behavior is for the notice
|
2559
|
+
* receiver to format the notice and pass a string to the notice processor for
|
2560
|
+
* printing. However, an application that chooses to provide its own notice
|
2561
|
+
* receiver will typically ignore the notice processor layer and just do all
|
2321
2562
|
* the work in the notice receiver.
|
2322
2563
|
*
|
2323
2564
|
* This function takes a new block to act as the handler, which should
|
2324
|
-
* accept a single parameter that will be a PG::Result object, and returns
|
2565
|
+
* accept a single parameter that will be a PG::Result object, and returns
|
2325
2566
|
* the Proc object previously set, or +nil+ if it was previously the default.
|
2326
2567
|
*
|
2327
2568
|
* If you pass no arguments, it will reset the handler to the default.
|
@@ -2336,8 +2577,8 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2336
2577
|
VALUE proc, old_proc;
|
2337
2578
|
PGconn *conn = pg_get_pgconn(self);
|
2338
2579
|
|
2339
|
-
/* If default_notice_receiver is unset, assume that the current
|
2340
|
-
* notice receiver is the default, and save it to a global variable.
|
2580
|
+
/* If default_notice_receiver is unset, assume that the current
|
2581
|
+
* notice receiver is the default, and save it to a global variable.
|
2341
2582
|
* This should not be a problem because the default receiver is
|
2342
2583
|
* always the same, so won't vary among connections.
|
2343
2584
|
*/
|
@@ -2347,7 +2588,7 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2347
2588
|
old_proc = rb_iv_get(self, "@notice_receiver");
|
2348
2589
|
if( rb_block_given_p() ) {
|
2349
2590
|
proc = rb_block_proc();
|
2350
|
-
PQsetNoticeReceiver(conn,
|
2591
|
+
PQsetNoticeReceiver(conn, gvl_notice_receiver_proxy, (void *)self);
|
2351
2592
|
} else {
|
2352
2593
|
/* if no block is given, set back to default */
|
2353
2594
|
proc = Qnil;
|
@@ -2363,14 +2604,20 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2363
2604
|
* Notice callback proxy function -- delegate the callback to the
|
2364
2605
|
* currently-registered Ruby notice_processor object.
|
2365
2606
|
*/
|
2366
|
-
|
2607
|
+
void
|
2367
2608
|
notice_processor_proxy(void *arg, const char *message)
|
2368
2609
|
{
|
2369
2610
|
VALUE proc;
|
2370
2611
|
VALUE self = (VALUE)arg;
|
2371
2612
|
|
2372
2613
|
if ((proc = rb_iv_get(self, "@notice_processor")) != Qnil) {
|
2373
|
-
|
2614
|
+
VALUE message_str = rb_tainted_str_new2(message);
|
2615
|
+
#ifdef M17N_SUPPORTED
|
2616
|
+
PGconn *conn = pg_get_pgconn( self );
|
2617
|
+
rb_encoding *enc = pg_conn_enc_get( conn );
|
2618
|
+
ENCODING_SET( message_str, rb_enc_to_index(enc) );
|
2619
|
+
#endif
|
2620
|
+
rb_funcall(proc, rb_intern("call"), 1, message_str);
|
2374
2621
|
}
|
2375
2622
|
return;
|
2376
2623
|
}
|
@@ -2382,9 +2629,9 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2382
2629
|
* See #set_notice_receiver for the desription of what this and the
|
2383
2630
|
* notice_processor methods do.
|
2384
2631
|
*
|
2385
|
-
* This function takes a new block to act as the notice processor and returns
|
2632
|
+
* This function takes a new block to act as the notice processor and returns
|
2386
2633
|
* the Proc object previously set, or +nil+ if it was previously the default.
|
2387
|
-
* The block should accept a single
|
2634
|
+
* The block should accept a single String object.
|
2388
2635
|
*
|
2389
2636
|
* If you pass no arguments, it will reset the handler to the default.
|
2390
2637
|
*/
|
@@ -2394,8 +2641,8 @@ pgconn_set_notice_processor(VALUE self)
|
|
2394
2641
|
VALUE proc, old_proc;
|
2395
2642
|
PGconn *conn = pg_get_pgconn(self);
|
2396
2643
|
|
2397
|
-
/* If default_notice_processor is unset, assume that the current
|
2398
|
-
* notice processor is the default, and save it to a global variable.
|
2644
|
+
/* If default_notice_processor is unset, assume that the current
|
2645
|
+
* notice processor is the default, and save it to a global variable.
|
2399
2646
|
* This should not be a problem because the default processor is
|
2400
2647
|
* always the same, so won't vary among connections.
|
2401
2648
|
*/
|
@@ -2405,7 +2652,7 @@ pgconn_set_notice_processor(VALUE self)
|
|
2405
2652
|
old_proc = rb_iv_get(self, "@notice_processor");
|
2406
2653
|
if( rb_block_given_p() ) {
|
2407
2654
|
proc = rb_block_proc();
|
2408
|
-
PQsetNoticeProcessor(conn,
|
2655
|
+
PQsetNoticeProcessor(conn, gvl_notice_processor_proxy, (void *)self);
|
2409
2656
|
} else {
|
2410
2657
|
/* if no block is given, set back to default */
|
2411
2658
|
proc = Qnil;
|
@@ -2420,7 +2667,7 @@ pgconn_set_notice_processor(VALUE self)
|
|
2420
2667
|
/*
|
2421
2668
|
* call-seq:
|
2422
2669
|
* conn.get_client_encoding() -> String
|
2423
|
-
*
|
2670
|
+
*
|
2424
2671
|
* Returns the client encoding as a String.
|
2425
2672
|
*/
|
2426
2673
|
static VALUE
|
@@ -2434,7 +2681,7 @@ pgconn_get_client_encoding(VALUE self)
|
|
2434
2681
|
/*
|
2435
2682
|
* call-seq:
|
2436
2683
|
* conn.set_client_encoding( encoding )
|
2437
|
-
*
|
2684
|
+
*
|
2438
2685
|
* Sets the client encoding to the _encoding_ String.
|
2439
2686
|
*/
|
2440
2687
|
static VALUE
|
@@ -2456,7 +2703,7 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2456
2703
|
* conn.transaction { |conn| ... } -> nil
|
2457
2704
|
*
|
2458
2705
|
* Executes a +BEGIN+ at the start of the block,
|
2459
|
-
* and a +COMMIT+ at the end of the block, or
|
2706
|
+
* and a +COMMIT+ at the end of the block, or
|
2460
2707
|
* +ROLLBACK+ if any exception occurs.
|
2461
2708
|
*/
|
2462
2709
|
static VALUE
|
@@ -2468,18 +2715,18 @@ pgconn_transaction(VALUE self)
|
|
2468
2715
|
int status;
|
2469
2716
|
|
2470
2717
|
if (rb_block_given_p()) {
|
2471
|
-
result =
|
2718
|
+
result = gvl_PQexec(conn, "BEGIN");
|
2472
2719
|
rb_pgresult = pg_new_result(result, self);
|
2473
2720
|
pg_result_check(rb_pgresult);
|
2474
2721
|
rb_protect(rb_yield, self, &status);
|
2475
2722
|
if(status == 0) {
|
2476
|
-
result =
|
2723
|
+
result = gvl_PQexec(conn, "COMMIT");
|
2477
2724
|
rb_pgresult = pg_new_result(result, self);
|
2478
2725
|
pg_result_check(rb_pgresult);
|
2479
2726
|
}
|
2480
2727
|
else {
|
2481
2728
|
/* exception occurred, ROLLBACK and re-raise */
|
2482
|
-
result =
|
2729
|
+
result = gvl_PQexec(conn, "ROLLBACK");
|
2483
2730
|
rb_pgresult = pg_new_result(result, self);
|
2484
2731
|
pg_result_check(rb_pgresult);
|
2485
2732
|
rb_jump_tag(status);
|
@@ -2502,7 +2749,7 @@ pgconn_transaction(VALUE self)
|
|
2502
2749
|
* Returns a string that is safe for inclusion in a SQL query as an
|
2503
2750
|
* identifier. Note: this is not a quote function for values, but for
|
2504
2751
|
* identifiers.
|
2505
|
-
*
|
2752
|
+
*
|
2506
2753
|
* For example, in a typical SQL query: <tt>SELECT FOO FROM MYTABLE</tt>
|
2507
2754
|
* The identifier <tt>FOO</tt> is folded to lower case, so it actually
|
2508
2755
|
* means <tt>foo</tt>. If you really want to access the case-sensitive
|
@@ -2510,7 +2757,7 @@ pgconn_transaction(VALUE self)
|
|
2510
2757
|
* <tt>PG::Connection.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
|
2511
2758
|
* (with double-quotes). PostgreSQL will see the double-quotes, and
|
2512
2759
|
* it will not fold to lower case.
|
2513
|
-
*
|
2760
|
+
*
|
2514
2761
|
* Similarly, this function also protects against special characters,
|
2515
2762
|
* and other things that might allow SQL injection if the identifier
|
2516
2763
|
* comes from an untrusted source.
|
@@ -2528,13 +2775,13 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
|
2528
2775
|
UNUSED( self );
|
2529
2776
|
|
2530
2777
|
if(strlen(str) >= NAMEDATALEN) {
|
2531
|
-
rb_raise(rb_eArgError,
|
2778
|
+
rb_raise(rb_eArgError,
|
2532
2779
|
"Input string is longer than NAMEDATALEN-1 (%d)",
|
2533
2780
|
NAMEDATALEN-1);
|
2534
2781
|
}
|
2535
2782
|
buffer[j++] = '"';
|
2536
2783
|
for(i = 0; i < strlen(str) && str[i]; i++) {
|
2537
|
-
if(str[i] == '"')
|
2784
|
+
if(str[i] == '"')
|
2538
2785
|
buffer[j++] = '"';
|
2539
2786
|
buffer[j++] = str[i];
|
2540
2787
|
}
|
@@ -2545,169 +2792,39 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
|
2545
2792
|
}
|
2546
2793
|
|
2547
2794
|
|
2548
|
-
|
2795
|
+
static void *
|
2796
|
+
get_result_readable(PGconn *conn)
|
2797
|
+
{
|
2798
|
+
return PQisBusy(conn) ? NULL : (void*)1;
|
2799
|
+
}
|
2800
|
+
|
2549
2801
|
|
2550
2802
|
/*
|
2551
2803
|
* call-seq:
|
2552
2804
|
* conn.block( [ timeout ] ) -> Boolean
|
2553
2805
|
*
|
2554
|
-
* Blocks until the server is no longer busy, or until the
|
2806
|
+
* Blocks until the server is no longer busy, or until the
|
2555
2807
|
* optional _timeout_ is reached, whichever comes first.
|
2556
2808
|
* _timeout_ is measured in seconds and can be fractional.
|
2557
|
-
*
|
2809
|
+
*
|
2558
2810
|
* Returns +false+ if _timeout_ is reached, +true+ otherwise.
|
2559
|
-
*
|
2811
|
+
*
|
2560
2812
|
* If +true+ is returned, +conn.is_busy+ will return +false+
|
2561
2813
|
* and +conn.get_result+ will not block.
|
2562
2814
|
*/
|
2563
2815
|
static VALUE
|
2564
2816
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2565
2817
|
PGconn *conn = pg_get_pgconn( self );
|
2566
|
-
int sd = PQsocket( conn );
|
2567
|
-
int ret;
|
2568
2818
|
|
2569
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2819
|
+
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2570
2820
|
* and does not wait (nor sleep) any time even if timeout is given.
|
2571
2821
|
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2572
2822
|
|
2573
2823
|
struct timeval timeout;
|
2574
2824
|
struct timeval *ptimeout = NULL;
|
2575
|
-
fd_set sd_rset;
|
2576
|
-
VALUE timeout_in;
|
2577
|
-
double timeout_sec;
|
2578
|
-
|
2579
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2580
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2581
|
-
timeout.tv_sec = (time_t)timeout_sec;
|
2582
|
-
timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
|
2583
|
-
ptimeout = &timeout;
|
2584
|
-
}
|
2585
|
-
|
2586
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2587
|
-
if ( PQconsumeInput(conn) == 0 )
|
2588
|
-
rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
|
2589
|
-
|
2590
|
-
while ( PQisBusy(conn) ) {
|
2591
|
-
FD_ZERO( &sd_rset );
|
2592
|
-
FD_SET( sd, &sd_rset );
|
2593
|
-
|
2594
|
-
if ( (ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout )) < 0 )
|
2595
|
-
rb_sys_fail( "rb_thread_select()" ); /* Raises */
|
2596
|
-
|
2597
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2598
|
-
if ( ret == 0 && argc )
|
2599
|
-
return Qfalse;
|
2600
|
-
|
2601
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2602
|
-
if ( PQconsumeInput(conn) == 0 )
|
2603
|
-
rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
|
2604
|
-
}
|
2605
|
-
|
2606
|
-
return Qtrue;
|
2607
|
-
}
|
2608
|
-
|
2609
|
-
|
2610
|
-
#else /* _WIN32 */
|
2611
|
-
|
2612
|
-
/*
|
2613
|
-
* Win32 PG::Connection#block -- on Windows, use platform-specific strategies to wait for the socket
|
2614
|
-
* instead of rb_thread_select().
|
2615
|
-
*/
|
2616
|
-
|
2617
|
-
/* Win32 + Ruby 1.9+ */
|
2618
|
-
#ifdef HAVE_RUBY_VM_H
|
2619
|
-
|
2620
|
-
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2621
|
-
|
2622
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2623
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2624
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2625
|
-
|
2626
|
-
static VALUE
|
2627
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2628
|
-
PGconn *conn = pg_get_pgconn( self );
|
2629
|
-
int sd = PQsocket( conn );
|
2630
|
-
int ret;
|
2631
|
-
|
2632
|
-
DWORD timeout_milisec = INFINITY;
|
2633
|
-
DWORD wait_ret;
|
2634
|
-
WSAEVENT hEvent;
|
2635
|
-
VALUE timeout_in;
|
2636
|
-
double timeout_sec;
|
2637
|
-
|
2638
|
-
hEvent = WSACreateEvent();
|
2639
|
-
|
2640
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2641
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2642
|
-
timeout_milisec = (DWORD)( (timeout_sec - (DWORD)timeout_sec) * 1e3 );
|
2643
|
-
}
|
2644
|
-
|
2645
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2646
|
-
if( PQconsumeInput(conn) == 0 ) {
|
2647
|
-
WSACloseEvent( hEvent );
|
2648
|
-
rb_raise( rb_ePGerror, PQerrorMessage(conn) );
|
2649
|
-
}
|
2650
|
-
|
2651
|
-
while ( PQisBusy(conn) ) {
|
2652
|
-
if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
|
2653
|
-
WSACloseEvent( hEvent );
|
2654
|
-
rb_raise( rb_ePGerror, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2655
|
-
}
|
2656
|
-
|
2657
|
-
wait_ret = rb_w32_wait_events( &hEvent, 1, 100 );
|
2658
|
-
|
2659
|
-
if ( wait_ret == WAIT_TIMEOUT ) {
|
2660
|
-
ret = 0;
|
2661
|
-
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2662
|
-
ret = 1;
|
2663
|
-
} else if ( wait_ret == WAIT_FAILED ) {
|
2664
|
-
WSACloseEvent( hEvent );
|
2665
|
-
rb_raise( rb_ePGerror, "Wait on socket error (WaitForMultipleObjects): %d", GetLastError() );
|
2666
|
-
} else {
|
2667
|
-
WSACloseEvent( hEvent );
|
2668
|
-
rb_raise( rb_ePGerror, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2669
|
-
}
|
2670
|
-
|
2671
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2672
|
-
if ( ret == 0 && argc ) {
|
2673
|
-
WSACloseEvent( hEvent );
|
2674
|
-
return Qfalse;
|
2675
|
-
}
|
2676
|
-
|
2677
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2678
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
2679
|
-
WSACloseEvent( hEvent );
|
2680
|
-
rb_raise( rb_ePGerror, PQerrorMessage(conn) );
|
2681
|
-
}
|
2682
|
-
}
|
2683
|
-
|
2684
|
-
WSACloseEvent( hEvent );
|
2685
|
-
|
2686
|
-
return Qtrue;
|
2687
|
-
}
|
2688
|
-
|
2689
|
-
#else /* Win32 + Ruby < 1.9 */
|
2690
|
-
|
2691
|
-
static VALUE
|
2692
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2693
|
-
PGconn *conn = pg_get_pgconn( self );
|
2694
|
-
int sd = PQsocket( conn );
|
2695
|
-
int ret;
|
2696
|
-
|
2697
|
-
struct timeval timeout;
|
2698
|
-
struct timeval *ptimeout = NULL;
|
2699
|
-
fd_set sd_rset;
|
2700
|
-
fd_set crt_sd_rset;
|
2701
2825
|
VALUE timeout_in;
|
2702
2826
|
double timeout_sec;
|
2703
|
-
|
2704
|
-
/* Always set a timeout, as rb_thread_select() sometimes
|
2705
|
-
* doesn't return when a second ruby thread is running although data
|
2706
|
-
* could be read. So we use timeout-based polling instead.
|
2707
|
-
*/
|
2708
|
-
timeout.tv_sec = 0;
|
2709
|
-
timeout.tv_usec = 10000; /* 10ms */
|
2710
|
-
ptimeout = &timeout;
|
2827
|
+
void *ret;
|
2711
2828
|
|
2712
2829
|
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2713
2830
|
timeout_sec = NUM2DBL( timeout_in );
|
@@ -2716,33 +2833,14 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
2716
2833
|
ptimeout = &timeout;
|
2717
2834
|
}
|
2718
2835
|
|
2719
|
-
|
2720
|
-
if( PQconsumeInput(conn) == 0 )
|
2721
|
-
rb_raise( rb_ePGerror, PQerrorMessage(conn) );
|
2836
|
+
ret = wait_socket_readable( conn, ptimeout, get_result_readable);
|
2722
2837
|
|
2723
|
-
|
2724
|
-
|
2725
|
-
FD_SET( sd, &sd_rset );
|
2726
|
-
|
2727
|
-
create_crt_fd( &sd_rset, &crt_sd_rset );
|
2728
|
-
ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2729
|
-
cleanup_crt_fd( &sd_rset, &crt_sd_rset );
|
2730
|
-
|
2731
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2732
|
-
if ( ret == 0 && argc )
|
2733
|
-
return Qfalse;
|
2734
|
-
|
2735
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2736
|
-
if ( PQconsumeInput(conn) == 0 )
|
2737
|
-
rb_raise( rb_ePGerror, PQerrorMessage(conn) );
|
2738
|
-
}
|
2838
|
+
if( !ret )
|
2839
|
+
return Qfalse;
|
2739
2840
|
|
2740
2841
|
return Qtrue;
|
2741
2842
|
}
|
2742
2843
|
|
2743
|
-
#endif /* Ruby 1.9 */
|
2744
|
-
#endif /* Win32 */
|
2745
|
-
|
2746
2844
|
|
2747
2845
|
/*
|
2748
2846
|
* call-seq:
|
@@ -2767,7 +2865,7 @@ pgconn_get_last_result(VALUE self)
|
|
2767
2865
|
|
2768
2866
|
|
2769
2867
|
cur = prev = NULL;
|
2770
|
-
while ((cur =
|
2868
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
2771
2869
|
int status;
|
2772
2870
|
|
2773
2871
|
if (prev) PQclear(prev);
|
@@ -2793,8 +2891,8 @@ pgconn_get_last_result(VALUE self)
|
|
2793
2891
|
* conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
|
2794
2892
|
*
|
2795
2893
|
* This function has the same behavior as #exec,
|
2796
|
-
* except that it's implemented using asynchronous command
|
2797
|
-
* processing and ruby's +rb_thread_select+ in order to
|
2894
|
+
* except that it's implemented using asynchronous command
|
2895
|
+
* processing and ruby's +rb_thread_select+ in order to
|
2798
2896
|
* allow other threads to process while waiting for the
|
2799
2897
|
* server to complete the request.
|
2800
2898
|
*/
|
@@ -2922,7 +3020,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
2922
3020
|
* call-seq:
|
2923
3021
|
* conn.lo_open( oid, [mode] ) -> Fixnum
|
2924
3022
|
*
|
2925
|
-
* Open a large object of _oid_. Returns a large object descriptor
|
3023
|
+
* Open a large object of _oid_. Returns a large object descriptor
|
2926
3024
|
* instance on success. The _mode_ argument specifies the mode for
|
2927
3025
|
* the opened large object,which is either +INV_READ+, or +INV_WRITE+.
|
2928
3026
|
*
|
@@ -2968,7 +3066,7 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
2968
3066
|
if( RSTRING_LEN(buffer) < 0) {
|
2969
3067
|
rb_raise(rb_ePGerror, "write buffer zero string");
|
2970
3068
|
}
|
2971
|
-
if((n = lo_write(conn, fd, StringValuePtr(buffer),
|
3069
|
+
if((n = lo_write(conn, fd, StringValuePtr(buffer),
|
2972
3070
|
RSTRING_LEN(buffer))) < 0) {
|
2973
3071
|
rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
|
2974
3072
|
}
|
@@ -3250,7 +3348,7 @@ init_pg_connection()
|
|
3250
3348
|
{
|
3251
3349
|
rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
|
3252
3350
|
rb_include_module(rb_cPGconn, rb_mPGconstants);
|
3253
|
-
|
3351
|
+
|
3254
3352
|
/****** PG::Connection CLASS METHODS ******/
|
3255
3353
|
rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
|
3256
3354
|
|
@@ -3304,6 +3402,7 @@ init_pg_connection()
|
|
3304
3402
|
/****** PG::Connection INSTANCE METHODS: Command Execution ******/
|
3305
3403
|
rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
|
3306
3404
|
rb_define_alias(rb_cPGconn, "query", "exec");
|
3405
|
+
rb_define_method(rb_cPGconn, "exec_params", pgconn_exec_params, -1);
|
3307
3406
|
rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
|
3308
3407
|
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
|
3309
3408
|
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
|
@@ -3319,6 +3418,9 @@ init_pg_connection()
|
|
3319
3418
|
#endif
|
3320
3419
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
3321
3420
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
3421
|
+
#ifdef HAVE_PQSETSINGLEROWMODE
|
3422
|
+
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
3423
|
+
#endif
|
3322
3424
|
|
3323
3425
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
3324
3426
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
@@ -3404,4 +3506,3 @@ init_pg_connection()
|
|
3404
3506
|
|
3405
3507
|
}
|
3406
3508
|
|
3407
|
-
|