pg 0.14.1-x86-mingw32 → 0.15.0.pre.432-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.tar.gz.sig +2 -0
- data/ChangeLog +424 -28
- data/Contributors.rdoc +1 -1
- data/History.rdoc +35 -0
- data/Manifest.txt +3 -0
- data/README.rdoc +5 -3
- data/Rakefile +0 -1
- data/Rakefile.cross +2 -2
- data/ext/extconf.rb +4 -0
- data/ext/gvl_wrappers.c +13 -0
- data/ext/gvl_wrappers.h +185 -0
- data/ext/pg.c +8 -4
- data/ext/pg.h +3 -0
- data/ext/pg_connection.c +451 -350
- data/ext/pg_result.c +8 -11
- data/lib/1.8/pg_ext.so +0 -0
- data/lib/1.9/pg_ext.so +0 -0
- 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 +54 -30
- metadata.gz.sig +0 -0
data/Contributors.rdoc
CHANGED
@@ -37,7 +37,7 @@ list.
|
|
37
37
|
* Lars Kanis <kanis@comcard.de>
|
38
38
|
* Jason Yanowitz <me-bitbucket@jasonyanowitz.com>
|
39
39
|
* Charlie Savage <cfis@rubyforge.org>
|
40
|
-
* Rafał Bigaj <rafal@
|
40
|
+
* Rafał Bigaj <rafal.bigaj@gmail.com>
|
41
41
|
* Jason Yanowitz <me-bitbucket@jasonyanowitz.com>
|
42
42
|
* Greg Hazel <ghazel@gmail.com>
|
43
43
|
* Chris White <cwprogram@live.com>
|
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
CHANGED
@@ -132,7 +132,6 @@ file 'ChangeLog' => '.hg/branch' do |task|
|
|
132
132
|
$stderr.puts "Updating the changelog..."
|
133
133
|
begin
|
134
134
|
include Hoe::MercurialHelpers
|
135
|
-
|
136
135
|
content = make_changelog()
|
137
136
|
rescue NameError
|
138
137
|
abort "Packaging tasks require the hoe-mercurial plugin (gem install hoe-mercurial)"
|
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
@@ -65,9 +65,13 @@ have_func 'pg_char_to_encoding'
|
|
65
65
|
have_func 'PQsetClientEncoding'
|
66
66
|
have_func 'PQlibVersion'
|
67
67
|
have_func 'PQping'
|
68
|
+
have_func 'PQsetSingleRowMode'
|
68
69
|
|
69
70
|
have_func 'rb_encdb_alias'
|
70
71
|
have_func 'rb_enc_alias'
|
72
|
+
have_func 'rb_thread_call_without_gvl'
|
73
|
+
have_func 'rb_thread_call_with_gvl'
|
74
|
+
have_func 'rb_thread_fd_select'
|
71
75
|
|
72
76
|
have_const 'PGRES_COPY_BOTH', 'libpq-fe.h'
|
73
77
|
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
@@ -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
@@ -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): %lu", 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 );
|
2308
|
+
pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
|
2058
2309
|
|
2059
|
-
|
2060
|
-
|
2061
|
-
#endif
|
2310
|
+
/* Return nil if the select timed out */
|
2311
|
+
if ( !pnotification ) return Qnil;
|
2062
2312
|
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
#ifdef _WIN32
|
2067
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
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,36 +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
2825
|
VALUE timeout_in;
|
2577
2826
|
double timeout_sec;
|
2827
|
+
void *ret;
|
2578
2828
|
|
2579
2829
|
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2580
2830
|
timeout_sec = NUM2DBL( timeout_in );
|
@@ -2583,166 +2833,14 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
2583
2833
|
ptimeout = &timeout;
|
2584
2834
|
}
|
2585
2835
|
|
2586
|
-
|
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 */
|
2836
|
+
ret = wait_socket_readable( conn, ptimeout, get_result_readable);
|
2596
2837
|
|
2597
|
-
|
2598
|
-
|
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
|
-
VALUE timeout_in;
|
2702
|
-
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;
|
2711
|
-
|
2712
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2713
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2714
|
-
timeout.tv_sec = (time_t)timeout_sec;
|
2715
|
-
timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
|
2716
|
-
ptimeout = &timeout;
|
2717
|
-
}
|
2718
|
-
|
2719
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2720
|
-
if( PQconsumeInput(conn) == 0 )
|
2721
|
-
rb_raise( rb_ePGerror, PQerrorMessage(conn) );
|
2722
|
-
|
2723
|
-
while ( PQisBusy(conn) ) {
|
2724
|
-
FD_ZERO( &sd_rset );
|
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
|
-
|