pg 1.2.3 → 1.4.6
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +42 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +117 -0
- data/.github/workflows/source-gem.yml +137 -0
- data/.gitignore +19 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.md +804 -0
- data/Manifest.txt +0 -1
- data/README.ja.md +266 -0
- data/README.md +272 -0
- data/Rakefile +33 -135
- data/Rakefile.cross +12 -13
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +12 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +4 -1
- data/ext/extconf.rb +100 -25
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +62 -29
- data/ext/pg.h +20 -1
- data/ext/pg_binary_decoder.c +1 -1
- data/ext/pg_binary_encoder.c +1 -1
- data/ext/pg_coder.c +83 -29
- data/ext/pg_connection.c +953 -670
- data/ext/pg_copy_coder.c +46 -17
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +46 -16
- data/ext/pg_result.c +88 -49
- data/ext/pg_text_decoder.c +2 -2
- data/ext/pg_text_encoder.c +7 -7
- data/ext/pg_tuple.c +50 -30
- data/ext/pg_type_map.c +42 -9
- data/ext/pg_type_map_all_strings.c +16 -2
- data/ext/pg_type_map_by_class.c +50 -25
- data/ext/pg_type_map_by_column.c +68 -30
- data/ext/pg_type_map_by_mri_type.c +48 -19
- data/ext/pg_type_map_by_oid.c +53 -24
- data/ext/pg_type_map_in_ruby.c +51 -20
- data/ext/pg_util.c +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +47 -0
- data/lib/pg/basic_type_map_for_queries.rb +193 -0
- data/lib/pg/basic_type_map_for_results.rb +81 -0
- data/lib/pg/basic_type_registry.rb +301 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +669 -81
- data/lib/pg/exceptions.rb +14 -1
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +45 -36
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +34 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +102 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data/translation/.po4a-version +7 -0
- data/translation/po/all.pot +875 -0
- data/translation/po/ja.po +868 -0
- data/translation/po4a.cfg +9 -0
- data.tar.gz.sig +0 -0
- metadata +120 -206
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/History.rdoc +0 -578
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -213
- data/lib/pg/basic_type_mapping.rb +0 -522
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -380
- data/spec/pg/basic_type_mapping_spec.rb +0 -630
- data/spec/pg/connection_spec.rb +0 -1949
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -681
- data/spec/pg/tuple_spec.rb +0 -333
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -226
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -1123
- data/spec/pg_spec.rb +0 -50
data/ext/pg_connection.c
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
VALUE rb_cPGconn;
|
|
14
14
|
static ID s_id_encode;
|
|
15
|
+
static ID s_id_autoclose_set;
|
|
15
16
|
static VALUE sym_type, sym_format, sym_value;
|
|
16
17
|
static VALUE sym_symbol, sym_string, sym_static_symbol;
|
|
17
18
|
|
|
@@ -20,12 +21,35 @@ static PQnoticeProcessor default_notice_processor = NULL;
|
|
|
20
21
|
|
|
21
22
|
static VALUE pgconn_finish( VALUE );
|
|
22
23
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
|
24
|
+
static VALUE pgconn_wait_for_flush( VALUE self );
|
|
23
25
|
static void pgconn_set_internal_encoding_index( VALUE );
|
|
26
|
+
static const rb_data_type_t pg_connection_type;
|
|
27
|
+
static VALUE pgconn_async_flush(VALUE self);
|
|
24
28
|
|
|
25
29
|
/*
|
|
26
30
|
* Global functions
|
|
27
31
|
*/
|
|
28
32
|
|
|
33
|
+
/*
|
|
34
|
+
* Convenience function to raise connection errors
|
|
35
|
+
*/
|
|
36
|
+
#ifdef __GNUC__
|
|
37
|
+
__attribute__((format(printf, 3, 4)))
|
|
38
|
+
#endif
|
|
39
|
+
static void
|
|
40
|
+
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
|
41
|
+
{
|
|
42
|
+
VALUE msg, error;
|
|
43
|
+
va_list ap;
|
|
44
|
+
|
|
45
|
+
va_start(ap, format);
|
|
46
|
+
msg = rb_vsprintf(format, ap);
|
|
47
|
+
va_end(ap);
|
|
48
|
+
error = rb_exc_new_str(klass, msg);
|
|
49
|
+
rb_iv_set(error, "@connection", self);
|
|
50
|
+
rb_exc_raise(error);
|
|
51
|
+
}
|
|
52
|
+
|
|
29
53
|
/*
|
|
30
54
|
* Fetch the PG::Connection object data pointer.
|
|
31
55
|
*/
|
|
@@ -33,7 +57,7 @@ t_pg_connection *
|
|
|
33
57
|
pg_get_connection( VALUE self )
|
|
34
58
|
{
|
|
35
59
|
t_pg_connection *this;
|
|
36
|
-
|
|
60
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
37
61
|
|
|
38
62
|
return this;
|
|
39
63
|
}
|
|
@@ -46,10 +70,10 @@ static t_pg_connection *
|
|
|
46
70
|
pg_get_connection_safe( VALUE self )
|
|
47
71
|
{
|
|
48
72
|
t_pg_connection *this;
|
|
49
|
-
|
|
73
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
50
74
|
|
|
51
75
|
if ( !this->pgconn )
|
|
52
|
-
|
|
76
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
|
53
77
|
|
|
54
78
|
return this;
|
|
55
79
|
}
|
|
@@ -65,10 +89,11 @@ PGconn *
|
|
|
65
89
|
pg_get_pgconn( VALUE self )
|
|
66
90
|
{
|
|
67
91
|
t_pg_connection *this;
|
|
68
|
-
|
|
92
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
69
93
|
|
|
70
|
-
if ( !this->pgconn )
|
|
71
|
-
|
|
94
|
+
if ( !this->pgconn ){
|
|
95
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
|
96
|
+
}
|
|
72
97
|
|
|
73
98
|
return this->pgconn;
|
|
74
99
|
}
|
|
@@ -86,9 +111,8 @@ pgconn_close_socket_io( VALUE self )
|
|
|
86
111
|
|
|
87
112
|
if ( RTEST(socket_io) ) {
|
|
88
113
|
#if defined(_WIN32)
|
|
89
|
-
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
|
90
|
-
|
|
91
|
-
}
|
|
114
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
|
115
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
|
92
116
|
#endif
|
|
93
117
|
rb_funcall( socket_io, rb_intern("close"), 0 );
|
|
94
118
|
}
|
|
@@ -145,16 +169,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
|
|
|
145
169
|
* GC Mark function
|
|
146
170
|
*/
|
|
147
171
|
static void
|
|
148
|
-
pgconn_gc_mark(
|
|
172
|
+
pgconn_gc_mark( void *_this )
|
|
173
|
+
{
|
|
174
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
|
175
|
+
rb_gc_mark_movable( this->socket_io );
|
|
176
|
+
rb_gc_mark_movable( this->notice_receiver );
|
|
177
|
+
rb_gc_mark_movable( this->notice_processor );
|
|
178
|
+
rb_gc_mark_movable( this->type_map_for_queries );
|
|
179
|
+
rb_gc_mark_movable( this->type_map_for_results );
|
|
180
|
+
rb_gc_mark_movable( this->trace_stream );
|
|
181
|
+
rb_gc_mark_movable( this->encoder_for_put_copy_data );
|
|
182
|
+
rb_gc_mark_movable( this->decoder_for_get_copy_data );
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
static void
|
|
186
|
+
pgconn_gc_compact( void *_this )
|
|
149
187
|
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
188
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
|
189
|
+
pg_gc_location( this->socket_io );
|
|
190
|
+
pg_gc_location( this->notice_receiver );
|
|
191
|
+
pg_gc_location( this->notice_processor );
|
|
192
|
+
pg_gc_location( this->type_map_for_queries );
|
|
193
|
+
pg_gc_location( this->type_map_for_results );
|
|
194
|
+
pg_gc_location( this->trace_stream );
|
|
195
|
+
pg_gc_location( this->encoder_for_put_copy_data );
|
|
196
|
+
pg_gc_location( this->decoder_for_get_copy_data );
|
|
158
197
|
}
|
|
159
198
|
|
|
160
199
|
|
|
@@ -162,11 +201,15 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
|
162
201
|
* GC Free function
|
|
163
202
|
*/
|
|
164
203
|
static void
|
|
165
|
-
pgconn_gc_free(
|
|
204
|
+
pgconn_gc_free( void *_this )
|
|
166
205
|
{
|
|
206
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
|
167
207
|
#if defined(_WIN32)
|
|
168
|
-
if ( RTEST(this->socket_io) )
|
|
169
|
-
rb_w32_unwrap_io_handle(
|
|
208
|
+
if ( RTEST(this->socket_io) ) {
|
|
209
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
|
210
|
+
rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
170
213
|
#endif
|
|
171
214
|
if (this->pgconn != NULL)
|
|
172
215
|
PQfinish( this->pgconn );
|
|
@@ -174,6 +217,29 @@ pgconn_gc_free( t_pg_connection *this )
|
|
|
174
217
|
xfree(this);
|
|
175
218
|
}
|
|
176
219
|
|
|
220
|
+
/*
|
|
221
|
+
* Object Size function
|
|
222
|
+
*/
|
|
223
|
+
static size_t
|
|
224
|
+
pgconn_memsize( const void *_this )
|
|
225
|
+
{
|
|
226
|
+
const t_pg_connection *this = (const t_pg_connection *)_this;
|
|
227
|
+
return sizeof(*this);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
static const rb_data_type_t pg_connection_type = {
|
|
231
|
+
"PG::Connection",
|
|
232
|
+
{
|
|
233
|
+
pgconn_gc_mark,
|
|
234
|
+
pgconn_gc_free,
|
|
235
|
+
pgconn_memsize,
|
|
236
|
+
pg_compact_callback(pgconn_gc_compact),
|
|
237
|
+
},
|
|
238
|
+
0,
|
|
239
|
+
0,
|
|
240
|
+
0,
|
|
241
|
+
};
|
|
242
|
+
|
|
177
243
|
|
|
178
244
|
/**************************************************************************
|
|
179
245
|
* Class Methods
|
|
@@ -189,7 +255,7 @@ static VALUE
|
|
|
189
255
|
pgconn_s_allocate( VALUE klass )
|
|
190
256
|
{
|
|
191
257
|
t_pg_connection *this;
|
|
192
|
-
VALUE self =
|
|
258
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
|
|
193
259
|
|
|
194
260
|
this->pgconn = NULL;
|
|
195
261
|
this->socket_io = Qnil;
|
|
@@ -200,82 +266,27 @@ pgconn_s_allocate( VALUE klass )
|
|
|
200
266
|
this->encoder_for_put_copy_data = Qnil;
|
|
201
267
|
this->decoder_for_get_copy_data = Qnil;
|
|
202
268
|
this->trace_stream = Qnil;
|
|
269
|
+
rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
|
|
203
270
|
|
|
204
271
|
return self;
|
|
205
272
|
}
|
|
206
273
|
|
|
207
|
-
|
|
208
|
-
/*
|
|
209
|
-
* Document-method: new
|
|
210
|
-
*
|
|
211
|
-
* call-seq:
|
|
212
|
-
* PG::Connection.new -> conn
|
|
213
|
-
* PG::Connection.new(connection_hash) -> conn
|
|
214
|
-
* PG::Connection.new(connection_string) -> conn
|
|
215
|
-
* PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
|
|
216
|
-
*
|
|
217
|
-
* Create a connection to the specified server.
|
|
218
|
-
*
|
|
219
|
-
* +connection_hash+ must be a ruby Hash with connection parameters.
|
|
220
|
-
* See the {list of valid parameters}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS] in the PostgreSQL documentation.
|
|
221
|
-
*
|
|
222
|
-
* There are two accepted formats for +connection_string+: plain <code>keyword = value</code> strings and URIs.
|
|
223
|
-
* See the documentation of {connection strings}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING].
|
|
224
|
-
*
|
|
225
|
-
* The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
|
|
226
|
-
* [+host+]
|
|
227
|
-
* server hostname
|
|
228
|
-
* [+port+]
|
|
229
|
-
* server port number
|
|
230
|
-
* [+options+]
|
|
231
|
-
* backend options
|
|
232
|
-
* [+tty+]
|
|
233
|
-
* (ignored in newer versions of PostgreSQL)
|
|
234
|
-
* [+dbname+]
|
|
235
|
-
* connecting database name
|
|
236
|
-
* [+user+]
|
|
237
|
-
* login user name
|
|
238
|
-
* [+password+]
|
|
239
|
-
* login password
|
|
240
|
-
*
|
|
241
|
-
* Examples:
|
|
242
|
-
*
|
|
243
|
-
* # Connect using all defaults
|
|
244
|
-
* PG::Connection.new
|
|
245
|
-
*
|
|
246
|
-
* # As a Hash
|
|
247
|
-
* PG::Connection.new( :dbname => 'test', :port => 5432 )
|
|
248
|
-
*
|
|
249
|
-
* # As a String
|
|
250
|
-
* PG::Connection.new( "dbname=test port=5432" )
|
|
251
|
-
*
|
|
252
|
-
* # As an Array
|
|
253
|
-
* PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
|
|
254
|
-
*
|
|
255
|
-
* If the Ruby default internal encoding is set (i.e., <code>Encoding.default_internal != nil</code>), the
|
|
256
|
-
* connection will have its +client_encoding+ set accordingly.
|
|
257
|
-
*
|
|
258
|
-
* Raises a PG::Error if the connection fails.
|
|
259
|
-
*/
|
|
260
274
|
static VALUE
|
|
261
|
-
|
|
275
|
+
pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
262
276
|
{
|
|
263
277
|
t_pg_connection *this;
|
|
264
278
|
VALUE conninfo;
|
|
265
|
-
VALUE
|
|
279
|
+
VALUE self = pgconn_s_allocate( klass );
|
|
266
280
|
|
|
267
281
|
this = pg_get_connection( self );
|
|
268
282
|
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
|
269
283
|
this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
|
|
270
284
|
|
|
271
285
|
if(this->pgconn == NULL)
|
|
272
|
-
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
|
|
286
|
+
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
|
|
273
287
|
|
|
274
|
-
if (PQstatus(this->pgconn) == CONNECTION_BAD)
|
|
275
|
-
|
|
276
|
-
rb_iv_set(error, "@connection", self);
|
|
277
|
-
rb_exc_raise(error);
|
|
278
|
-
}
|
|
288
|
+
if (PQstatus(this->pgconn) == CONNECTION_BAD)
|
|
289
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
|
|
279
290
|
|
|
280
291
|
pgconn_set_default_encoding( self );
|
|
281
292
|
|
|
@@ -308,7 +319,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
308
319
|
{
|
|
309
320
|
VALUE rb_conn;
|
|
310
321
|
VALUE conninfo;
|
|
311
|
-
VALUE error;
|
|
312
322
|
t_pg_connection *this;
|
|
313
323
|
|
|
314
324
|
/*
|
|
@@ -321,13 +331,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
321
331
|
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
|
322
332
|
|
|
323
333
|
if( this->pgconn == NULL )
|
|
324
|
-
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
|
|
334
|
+
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
|
325
335
|
|
|
326
|
-
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
|
327
|
-
|
|
328
|
-
rb_iv_set(error, "@connection", rb_conn);
|
|
329
|
-
rb_exc_raise(error);
|
|
330
|
-
}
|
|
336
|
+
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
|
337
|
+
pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
|
|
331
338
|
|
|
332
339
|
if ( rb_block_given_p() ) {
|
|
333
340
|
return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
|
|
@@ -335,34 +342,14 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
335
342
|
return rb_conn;
|
|
336
343
|
}
|
|
337
344
|
|
|
338
|
-
/*
|
|
339
|
-
* call-seq:
|
|
340
|
-
* PG::Connection.ping(connection_hash) -> Integer
|
|
341
|
-
* PG::Connection.ping(connection_string) -> Integer
|
|
342
|
-
* PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
|
|
343
|
-
*
|
|
344
|
-
* Check server status.
|
|
345
|
-
*
|
|
346
|
-
* See PG::Connection.new for a description of the parameters.
|
|
347
|
-
*
|
|
348
|
-
* Returns one of:
|
|
349
|
-
* [+PQPING_OK+]
|
|
350
|
-
* server is accepting connections
|
|
351
|
-
* [+PQPING_REJECT+]
|
|
352
|
-
* server is alive but rejecting connections
|
|
353
|
-
* [+PQPING_NO_RESPONSE+]
|
|
354
|
-
* could not establish connection
|
|
355
|
-
* [+PQPING_NO_ATTEMPT+]
|
|
356
|
-
* connection not attempted (bad params)
|
|
357
|
-
*/
|
|
358
345
|
static VALUE
|
|
359
|
-
|
|
346
|
+
pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
|
|
360
347
|
{
|
|
361
348
|
PGPing ping;
|
|
362
349
|
VALUE conninfo;
|
|
363
350
|
|
|
364
351
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
|
365
|
-
ping =
|
|
352
|
+
ping = gvl_PQping( StringValueCStr(conninfo) );
|
|
366
353
|
|
|
367
354
|
return INT2FIX((int)ping);
|
|
368
355
|
}
|
|
@@ -403,32 +390,40 @@ pgconn_s_conndefaults(VALUE self)
|
|
|
403
390
|
return array;
|
|
404
391
|
}
|
|
405
392
|
|
|
406
|
-
|
|
407
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
408
393
|
/*
|
|
409
|
-
*
|
|
410
|
-
* conn.encrypt_password( password, username, algorithm=nil ) -> String
|
|
411
|
-
*
|
|
412
|
-
* This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
|
|
413
|
-
* It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on.
|
|
414
|
-
* Instead, use this function to convert the password to encrypted form before it is sent.
|
|
394
|
+
* Document-method: PG::Connection.conninfo_parse
|
|
415
395
|
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
* Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions).
|
|
419
|
-
* Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
|
|
420
|
-
* If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
|
|
421
|
-
* That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
|
|
422
|
-
* If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm.
|
|
423
|
-
*
|
|
424
|
-
* Return value is the encrypted password.
|
|
425
|
-
* The caller can assume the string doesn't contain any special characters that would require escaping.
|
|
396
|
+
* call-seq:
|
|
397
|
+
* PG::Connection.conninfo_parse(conninfo_string) -> Array
|
|
426
398
|
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
399
|
+
* Returns parsed connection options from the provided connection string as an array of hashes.
|
|
400
|
+
* Each hash has the same keys as PG::Connection.conndefaults() .
|
|
401
|
+
* The values from the +conninfo_string+ are stored in the +:val+ key.
|
|
429
402
|
*/
|
|
430
403
|
static VALUE
|
|
431
|
-
|
|
404
|
+
pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
|
|
405
|
+
{
|
|
406
|
+
VALUE array;
|
|
407
|
+
char *errmsg = NULL;
|
|
408
|
+
PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
|
|
409
|
+
if(errmsg){
|
|
410
|
+
VALUE error = rb_str_new_cstr(errmsg);
|
|
411
|
+
PQfreemem(errmsg);
|
|
412
|
+
rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
|
|
413
|
+
}
|
|
414
|
+
array = pgconn_make_conninfo_array( options );
|
|
415
|
+
|
|
416
|
+
PQconninfoFree(options);
|
|
417
|
+
|
|
418
|
+
UNUSED( self );
|
|
419
|
+
|
|
420
|
+
return array;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
425
|
+
static VALUE
|
|
426
|
+
pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
432
427
|
{
|
|
433
428
|
char *encrypted = NULL;
|
|
434
429
|
VALUE rval = Qnil;
|
|
@@ -445,7 +440,7 @@ pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
|
445
440
|
rval = rb_str_new2( encrypted );
|
|
446
441
|
PQfreemem( encrypted );
|
|
447
442
|
} else {
|
|
448
|
-
|
|
443
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
449
444
|
}
|
|
450
445
|
|
|
451
446
|
return rval;
|
|
@@ -499,17 +494,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
|
499
494
|
* the asynchronous connection is ready
|
|
500
495
|
*
|
|
501
496
|
* Example:
|
|
502
|
-
*
|
|
503
|
-
*
|
|
497
|
+
* require "io/wait"
|
|
498
|
+
*
|
|
499
|
+
* conn = PG::Connection.connect_start(dbname: 'mydatabase')
|
|
504
500
|
* status = conn.connect_poll
|
|
505
501
|
* while(status != PG::PGRES_POLLING_OK) do
|
|
506
502
|
* # do some work while waiting for the connection to complete
|
|
507
503
|
* if(status == PG::PGRES_POLLING_READING)
|
|
508
|
-
*
|
|
504
|
+
* unless conn.socket_io.wait_readable(10.0)
|
|
509
505
|
* raise "Asynchronous connection timed out!"
|
|
510
506
|
* end
|
|
511
507
|
* elsif(status == PG::PGRES_POLLING_WRITING)
|
|
512
|
-
*
|
|
508
|
+
* unless conn.socket_io.wait_writable(10.0)
|
|
513
509
|
* raise "Asynchronous connection timed out!"
|
|
514
510
|
* end
|
|
515
511
|
* end
|
|
@@ -523,6 +519,9 @@ pgconn_connect_poll(VALUE self)
|
|
|
523
519
|
{
|
|
524
520
|
PostgresPollingStatusType status;
|
|
525
521
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
|
522
|
+
|
|
523
|
+
pgconn_close_socket_io(self);
|
|
524
|
+
|
|
526
525
|
return INT2FIX((int)status);
|
|
527
526
|
}
|
|
528
527
|
|
|
@@ -559,15 +558,8 @@ pgconn_finished_p( VALUE self )
|
|
|
559
558
|
}
|
|
560
559
|
|
|
561
560
|
|
|
562
|
-
/*
|
|
563
|
-
* call-seq:
|
|
564
|
-
* conn.reset()
|
|
565
|
-
*
|
|
566
|
-
* Resets the backend connection. This method closes the
|
|
567
|
-
* backend connection and tries to re-connect.
|
|
568
|
-
*/
|
|
569
561
|
static VALUE
|
|
570
|
-
|
|
562
|
+
pgconn_sync_reset( VALUE self )
|
|
571
563
|
{
|
|
572
564
|
pgconn_close_socket_io( self );
|
|
573
565
|
gvl_PQreset( pg_get_pgconn(self) );
|
|
@@ -589,7 +581,7 @@ pgconn_reset_start(VALUE self)
|
|
|
589
581
|
{
|
|
590
582
|
pgconn_close_socket_io( self );
|
|
591
583
|
if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
|
|
592
|
-
|
|
584
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
|
|
593
585
|
return Qnil;
|
|
594
586
|
}
|
|
595
587
|
|
|
@@ -606,6 +598,9 @@ pgconn_reset_poll(VALUE self)
|
|
|
606
598
|
{
|
|
607
599
|
PostgresPollingStatusType status;
|
|
608
600
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
|
601
|
+
|
|
602
|
+
pgconn_close_socket_io(self);
|
|
603
|
+
|
|
609
604
|
return INT2FIX((int)status);
|
|
610
605
|
}
|
|
611
606
|
|
|
@@ -656,7 +651,18 @@ pgconn_pass(VALUE self)
|
|
|
656
651
|
* call-seq:
|
|
657
652
|
* conn.host()
|
|
658
653
|
*
|
|
659
|
-
* Returns the
|
|
654
|
+
* Returns the server host name of the active connection.
|
|
655
|
+
* This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
|
|
656
|
+
* (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
|
|
657
|
+
*
|
|
658
|
+
* If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
|
|
659
|
+
* If only hostaddr was specified, then that is returned.
|
|
660
|
+
* If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
|
|
661
|
+
*
|
|
662
|
+
* If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
|
|
663
|
+
*
|
|
664
|
+
* If multiple hosts were specified in the connection parameters, it is not possible to rely on the result of +host+ until the connection is established.
|
|
665
|
+
* The status of the connection can be checked using the function Connection#status .
|
|
660
666
|
*/
|
|
661
667
|
static VALUE
|
|
662
668
|
pgconn_host(VALUE self)
|
|
@@ -666,6 +672,26 @@ pgconn_host(VALUE self)
|
|
|
666
672
|
return rb_str_new2(host);
|
|
667
673
|
}
|
|
668
674
|
|
|
675
|
+
/* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
|
|
676
|
+
#if defined(HAVE_PQRESULTMEMORYSIZE)
|
|
677
|
+
/*
|
|
678
|
+
* call-seq:
|
|
679
|
+
* conn.hostaddr()
|
|
680
|
+
*
|
|
681
|
+
* Returns the server IP address of the active connection.
|
|
682
|
+
* This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
|
|
683
|
+
* If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
|
|
684
|
+
*
|
|
685
|
+
*/
|
|
686
|
+
static VALUE
|
|
687
|
+
pgconn_hostaddr(VALUE self)
|
|
688
|
+
{
|
|
689
|
+
char *host = PQhostaddr(pg_get_pgconn(self));
|
|
690
|
+
if (!host) return Qnil;
|
|
691
|
+
return rb_str_new2(host);
|
|
692
|
+
}
|
|
693
|
+
#endif
|
|
694
|
+
|
|
669
695
|
/*
|
|
670
696
|
* call-seq:
|
|
671
697
|
* conn.port()
|
|
@@ -676,21 +702,22 @@ static VALUE
|
|
|
676
702
|
pgconn_port(VALUE self)
|
|
677
703
|
{
|
|
678
704
|
char* port = PQport(pg_get_pgconn(self));
|
|
679
|
-
|
|
705
|
+
if (!port || port[0] == '\0')
|
|
706
|
+
return INT2NUM(DEF_PGPORT);
|
|
707
|
+
else
|
|
708
|
+
return INT2NUM(atoi(port));
|
|
680
709
|
}
|
|
681
710
|
|
|
682
711
|
/*
|
|
683
712
|
* call-seq:
|
|
684
713
|
* conn.tty()
|
|
685
714
|
*
|
|
686
|
-
*
|
|
715
|
+
* Obsolete function.
|
|
687
716
|
*/
|
|
688
717
|
static VALUE
|
|
689
718
|
pgconn_tty(VALUE self)
|
|
690
719
|
{
|
|
691
|
-
|
|
692
|
-
if (!tty) return Qnil;
|
|
693
|
-
return rb_str_new2(tty);
|
|
720
|
+
return rb_str_new2("");
|
|
694
721
|
}
|
|
695
722
|
|
|
696
723
|
/*
|
|
@@ -708,7 +735,6 @@ pgconn_options(VALUE self)
|
|
|
708
735
|
}
|
|
709
736
|
|
|
710
737
|
|
|
711
|
-
#ifdef HAVE_PQCONNINFO
|
|
712
738
|
/*
|
|
713
739
|
* call-seq:
|
|
714
740
|
* conn.conninfo -> hash
|
|
@@ -728,14 +754,20 @@ pgconn_conninfo( VALUE self )
|
|
|
728
754
|
|
|
729
755
|
return array;
|
|
730
756
|
}
|
|
731
|
-
#endif
|
|
732
757
|
|
|
733
758
|
|
|
734
759
|
/*
|
|
735
760
|
* call-seq:
|
|
736
761
|
* conn.status()
|
|
737
762
|
*
|
|
738
|
-
* Returns status of connection
|
|
763
|
+
* Returns the status of the connection, which is one:
|
|
764
|
+
* PG::Constants::CONNECTION_OK
|
|
765
|
+
* PG::Constants::CONNECTION_BAD
|
|
766
|
+
*
|
|
767
|
+
* ... and other constants of kind PG::Constants::CONNECTION_*
|
|
768
|
+
*
|
|
769
|
+
* Example:
|
|
770
|
+
* PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
|
|
739
771
|
*/
|
|
740
772
|
static VALUE
|
|
741
773
|
pgconn_status(VALUE self)
|
|
@@ -823,7 +855,10 @@ pgconn_server_version(VALUE self)
|
|
|
823
855
|
* call-seq:
|
|
824
856
|
* conn.error_message -> String
|
|
825
857
|
*
|
|
826
|
-
* Returns the error message
|
|
858
|
+
* Returns the error message most recently generated by an operation on the connection.
|
|
859
|
+
*
|
|
860
|
+
* Nearly all libpq functions will set a message for conn.error_message if they fail.
|
|
861
|
+
* Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
|
|
827
862
|
*/
|
|
828
863
|
static VALUE
|
|
829
864
|
pgconn_error_message(VALUE self)
|
|
@@ -857,7 +892,8 @@ pgconn_socket(VALUE self)
|
|
|
857
892
|
pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
|
|
858
893
|
|
|
859
894
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
|
860
|
-
|
|
895
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
|
896
|
+
|
|
861
897
|
return INT2NUM(sd);
|
|
862
898
|
}
|
|
863
899
|
|
|
@@ -865,38 +901,45 @@ pgconn_socket(VALUE self)
|
|
|
865
901
|
* call-seq:
|
|
866
902
|
* conn.socket_io() -> IO
|
|
867
903
|
*
|
|
868
|
-
* Fetch
|
|
869
|
-
* This object can be used for IO.select to wait for events while running
|
|
870
|
-
*
|
|
904
|
+
* Fetch an IO object created from the Connection's underlying socket.
|
|
905
|
+
* This object can be used per <tt>socket_io.wait_readable</tt>, <tt>socket_io.wait_writable</tt> or for <tt>IO.select</tt> to wait for events while running asynchronous API calls.
|
|
906
|
+
* <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
|
|
907
|
+
*
|
|
908
|
+
* The IO object can change while the connection is established, but is memorized afterwards.
|
|
909
|
+
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
|
871
910
|
*
|
|
872
|
-
* Using this
|
|
873
|
-
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
|
874
|
-
* goes out of scope. In contrast to #socket, it also works on Windows.
|
|
911
|
+
* Using this method also works on Windows in contrast to using #socket .
|
|
912
|
+
* It also avoids the problem of the underlying connection being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt> goes out of scope.
|
|
875
913
|
*/
|
|
876
914
|
static VALUE
|
|
877
915
|
pgconn_socket_io(VALUE self)
|
|
878
916
|
{
|
|
879
917
|
int sd;
|
|
880
918
|
int ruby_sd;
|
|
881
|
-
ID id_autoclose = rb_intern("autoclose=");
|
|
882
919
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
920
|
+
VALUE cSocket;
|
|
883
921
|
VALUE socket_io = this->socket_io;
|
|
884
922
|
|
|
885
923
|
if ( !RTEST(socket_io) ) {
|
|
886
|
-
if( (sd = PQsocket(this->pgconn)) < 0)
|
|
887
|
-
|
|
924
|
+
if( (sd = PQsocket(this->pgconn)) < 0){
|
|
925
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
|
926
|
+
}
|
|
888
927
|
|
|
889
928
|
#ifdef _WIN32
|
|
890
929
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
|
930
|
+
if( ruby_sd == -1 )
|
|
931
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
|
932
|
+
|
|
891
933
|
this->ruby_sd = ruby_sd;
|
|
892
934
|
#else
|
|
893
935
|
ruby_sd = sd;
|
|
894
936
|
#endif
|
|
895
937
|
|
|
896
|
-
|
|
938
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
|
939
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
|
897
940
|
|
|
898
941
|
/* Disable autoclose feature */
|
|
899
|
-
rb_funcall( socket_io,
|
|
942
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
|
900
943
|
|
|
901
944
|
this->socket_io = socket_io;
|
|
902
945
|
}
|
|
@@ -918,6 +961,51 @@ pgconn_backend_pid(VALUE self)
|
|
|
918
961
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
|
919
962
|
}
|
|
920
963
|
|
|
964
|
+
typedef struct
|
|
965
|
+
{
|
|
966
|
+
struct sockaddr_storage addr;
|
|
967
|
+
socklen_t salen;
|
|
968
|
+
} SockAddr;
|
|
969
|
+
|
|
970
|
+
/* Copy of struct pg_cancel from libpq-int.h
|
|
971
|
+
*
|
|
972
|
+
* See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
|
|
973
|
+
*/
|
|
974
|
+
struct pg_cancel
|
|
975
|
+
{
|
|
976
|
+
SockAddr raddr; /* Remote address */
|
|
977
|
+
int be_pid; /* PID of backend --- needed for cancels */
|
|
978
|
+
int be_key; /* key of backend --- needed for cancels */
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
/*
|
|
982
|
+
* call-seq:
|
|
983
|
+
* conn.backend_key() -> Integer
|
|
984
|
+
*
|
|
985
|
+
* Returns the key of the backend server process for this connection.
|
|
986
|
+
* This key can be used to cancel queries on the server.
|
|
987
|
+
*/
|
|
988
|
+
static VALUE
|
|
989
|
+
pgconn_backend_key(VALUE self)
|
|
990
|
+
{
|
|
991
|
+
int be_key;
|
|
992
|
+
struct pg_cancel *cancel;
|
|
993
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
994
|
+
|
|
995
|
+
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
|
996
|
+
if(cancel == NULL)
|
|
997
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
|
998
|
+
|
|
999
|
+
if( cancel->be_pid != PQbackendPID(conn) )
|
|
1000
|
+
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
|
1001
|
+
|
|
1002
|
+
be_key = cancel->be_key;
|
|
1003
|
+
|
|
1004
|
+
PQfreeCancel(cancel);
|
|
1005
|
+
|
|
1006
|
+
return INT2NUM(be_key);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
921
1009
|
/*
|
|
922
1010
|
* call-seq:
|
|
923
1011
|
* conn.connection_needs_password() -> Boolean
|
|
@@ -948,7 +1036,7 @@ pgconn_connection_used_password(VALUE self)
|
|
|
948
1036
|
/* :TODO: get_ssl */
|
|
949
1037
|
|
|
950
1038
|
|
|
951
|
-
static VALUE
|
|
1039
|
+
static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
|
952
1040
|
|
|
953
1041
|
/*
|
|
954
1042
|
* call-seq:
|
|
@@ -962,11 +1050,11 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
|
962
1050
|
* However #async_exec has two advantages:
|
|
963
1051
|
*
|
|
964
1052
|
* 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
|
|
965
|
-
* 2. Ruby VM gets notified about IO blocked operations.
|
|
966
|
-
*
|
|
1053
|
+
* 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
|
|
1054
|
+
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
|
967
1055
|
*/
|
|
968
1056
|
static VALUE
|
|
969
|
-
|
|
1057
|
+
pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
|
970
1058
|
{
|
|
971
1059
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
972
1060
|
PGresult *result = NULL;
|
|
@@ -987,7 +1075,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
|
987
1075
|
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
|
988
1076
|
|
|
989
1077
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
|
990
|
-
return
|
|
1078
|
+
return pgconn_sync_exec_params( argc, argv, self );
|
|
991
1079
|
|
|
992
1080
|
}
|
|
993
1081
|
|
|
@@ -1019,7 +1107,7 @@ struct query_params_data {
|
|
|
1019
1107
|
* Filled by alloc_query_params()
|
|
1020
1108
|
*/
|
|
1021
1109
|
|
|
1022
|
-
/* Wraps the pointer of allocated memory, if function parameters
|
|
1110
|
+
/* Wraps the pointer of allocated memory, if function parameters don't
|
|
1023
1111
|
* fit in the memory_pool below.
|
|
1024
1112
|
*/
|
|
1025
1113
|
VALUE heap_pool;
|
|
@@ -1037,7 +1125,7 @@ struct query_params_data {
|
|
|
1037
1125
|
Oid *types;
|
|
1038
1126
|
|
|
1039
1127
|
/* This array takes the string values for the timeframe of the query,
|
|
1040
|
-
* if param value
|
|
1128
|
+
* if param value conversion is required
|
|
1041
1129
|
*/
|
|
1042
1130
|
VALUE gc_array;
|
|
1043
1131
|
|
|
@@ -1051,8 +1139,9 @@ struct query_params_data {
|
|
|
1051
1139
|
};
|
|
1052
1140
|
|
|
1053
1141
|
static void
|
|
1054
|
-
free_typecast_heap_chain(
|
|
1142
|
+
free_typecast_heap_chain(void *_chain_entry)
|
|
1055
1143
|
{
|
|
1144
|
+
struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
|
|
1056
1145
|
while(chain_entry){
|
|
1057
1146
|
struct linked_typecast_data *next = chain_entry->next;
|
|
1058
1147
|
xfree(chain_entry);
|
|
@@ -1060,6 +1149,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
|
|
|
1060
1149
|
}
|
|
1061
1150
|
}
|
|
1062
1151
|
|
|
1152
|
+
static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1153
|
+
"PG::Connection typecast buffer chain",
|
|
1154
|
+
{
|
|
1155
|
+
(RUBY_DATA_FUNC) NULL,
|
|
1156
|
+
free_typecast_heap_chain,
|
|
1157
|
+
(size_t (*)(const void *))NULL,
|
|
1158
|
+
},
|
|
1159
|
+
0,
|
|
1160
|
+
0,
|
|
1161
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1063
1164
|
static char *
|
|
1064
1165
|
alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
1065
1166
|
{
|
|
@@ -1070,17 +1171,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
|
1070
1171
|
/* Did we already wrap a memory chain per T_DATA object? */
|
|
1071
1172
|
if( NIL_P( *typecast_heap_chain ) ){
|
|
1072
1173
|
/* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
|
|
1073
|
-
*typecast_heap_chain =
|
|
1174
|
+
*typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
|
|
1074
1175
|
allocated->next = NULL;
|
|
1075
1176
|
} else {
|
|
1076
1177
|
/* Append to the chain */
|
|
1077
|
-
allocated->next =
|
|
1078
|
-
|
|
1178
|
+
allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
|
|
1179
|
+
RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
|
|
1079
1180
|
}
|
|
1080
1181
|
|
|
1081
1182
|
return &allocated->data[0];
|
|
1082
1183
|
}
|
|
1083
1184
|
|
|
1185
|
+
static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1186
|
+
"PG::Connection query heap pool",
|
|
1187
|
+
{
|
|
1188
|
+
(RUBY_DATA_FUNC) NULL,
|
|
1189
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
1190
|
+
(size_t (*)(const void *))NULL,
|
|
1191
|
+
},
|
|
1192
|
+
0,
|
|
1193
|
+
0,
|
|
1194
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
1195
|
+
};
|
|
1084
1196
|
|
|
1085
1197
|
static int
|
|
1086
1198
|
alloc_query_params(struct query_params_data *paramsData)
|
|
@@ -1095,7 +1207,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1095
1207
|
|
|
1096
1208
|
Check_Type(paramsData->params, T_ARRAY);
|
|
1097
1209
|
|
|
1098
|
-
p_typemap =
|
|
1210
|
+
p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
|
|
1099
1211
|
p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
|
|
1100
1212
|
|
|
1101
1213
|
paramsData->heap_pool = Qnil;
|
|
@@ -1114,7 +1226,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1114
1226
|
/* Allocate one combined memory pool for all possible function parameters */
|
|
1115
1227
|
memory_pool = (char*)xmalloc( required_pool_size );
|
|
1116
1228
|
/* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
|
|
1117
|
-
paramsData->heap_pool =
|
|
1229
|
+
paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
|
|
1118
1230
|
required_pool_size = 0;
|
|
1119
1231
|
}else{
|
|
1120
1232
|
/* Use stack memory for function parameters */
|
|
@@ -1227,12 +1339,11 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
|
1227
1339
|
/* Use default typemap for queries. It's type is checked when assigned. */
|
|
1228
1340
|
paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
|
|
1229
1341
|
}else{
|
|
1342
|
+
t_typemap *tm;
|
|
1343
|
+
UNUSED(tm);
|
|
1344
|
+
|
|
1230
1345
|
/* Check type of method param */
|
|
1231
|
-
|
|
1232
|
-
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
|
|
1233
|
-
rb_obj_classname( paramsData->typemap ) );
|
|
1234
|
-
}
|
|
1235
|
-
Check_Type( paramsData->typemap, T_DATA );
|
|
1346
|
+
TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
|
|
1236
1347
|
}
|
|
1237
1348
|
}
|
|
1238
1349
|
|
|
@@ -1246,7 +1357,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
|
1246
1357
|
* It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
|
|
1247
1358
|
*/
|
|
1248
1359
|
static VALUE
|
|
1249
|
-
|
|
1360
|
+
pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1250
1361
|
{
|
|
1251
1362
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1252
1363
|
PGresult *result = NULL;
|
|
@@ -1266,7 +1377,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1266
1377
|
*/
|
|
1267
1378
|
if ( NIL_P(paramsData.params) ) {
|
|
1268
1379
|
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
|
1269
|
-
return
|
|
1380
|
+
return pgconn_sync_exec( 1, argv, self );
|
|
1270
1381
|
}
|
|
1271
1382
|
pgconn_query_assign_typemap( self, ¶msData );
|
|
1272
1383
|
|
|
@@ -1297,7 +1408,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1297
1408
|
* It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
|
|
1298
1409
|
*/
|
|
1299
1410
|
static VALUE
|
|
1300
|
-
|
|
1411
|
+
pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
1301
1412
|
{
|
|
1302
1413
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1303
1414
|
PGresult *result = NULL;
|
|
@@ -1346,7 +1457,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1346
1457
|
* It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
|
|
1347
1458
|
*/
|
|
1348
1459
|
static VALUE
|
|
1349
|
-
|
|
1460
|
+
pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1350
1461
|
{
|
|
1351
1462
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1352
1463
|
PGresult *result = NULL;
|
|
@@ -1391,7 +1502,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1391
1502
|
* It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
|
|
1392
1503
|
*/
|
|
1393
1504
|
static VALUE
|
|
1394
|
-
|
|
1505
|
+
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1395
1506
|
{
|
|
1396
1507
|
PGresult *result;
|
|
1397
1508
|
VALUE rb_pgresult;
|
|
@@ -1419,8 +1530,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
1419
1530
|
* It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
|
|
1420
1531
|
*/
|
|
1421
1532
|
static VALUE
|
|
1422
|
-
|
|
1423
|
-
VALUE self, stmt_name;
|
|
1533
|
+
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
1424
1534
|
{
|
|
1425
1535
|
PGresult *result;
|
|
1426
1536
|
VALUE rb_pgresult;
|
|
@@ -1454,6 +1564,9 @@ pgconn_describe_portal(self, stmt_name)
|
|
|
1454
1564
|
* * +PGRES_NONFATAL_ERROR+
|
|
1455
1565
|
* * +PGRES_FATAL_ERROR+
|
|
1456
1566
|
* * +PGRES_COPY_BOTH+
|
|
1567
|
+
* * +PGRES_SINGLE_TUPLE+
|
|
1568
|
+
* * +PGRES_PIPELINE_SYNC+
|
|
1569
|
+
* * +PGRES_PIPELINE_ABORTED+
|
|
1457
1570
|
*/
|
|
1458
1571
|
static VALUE
|
|
1459
1572
|
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
@@ -1509,9 +1622,9 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
|
1509
1622
|
if( !singleton ) {
|
|
1510
1623
|
size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
|
|
1511
1624
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
|
1512
|
-
if(error)
|
|
1513
|
-
|
|
1514
|
-
|
|
1625
|
+
if(error)
|
|
1626
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
|
|
1627
|
+
|
|
1515
1628
|
} else {
|
|
1516
1629
|
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
|
1517
1630
|
}
|
|
@@ -1607,7 +1720,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
|
1607
1720
|
{
|
|
1608
1721
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1609
1722
|
char *escaped = NULL;
|
|
1610
|
-
VALUE error;
|
|
1611
1723
|
VALUE result = Qnil;
|
|
1612
1724
|
int enc_idx = this->enc_idx;
|
|
1613
1725
|
|
|
@@ -1618,12 +1730,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
|
1618
1730
|
|
|
1619
1731
|
escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
|
1620
1732
|
if (escaped == NULL)
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
rb_iv_set(error, "@connection", self);
|
|
1624
|
-
rb_exc_raise(error);
|
|
1625
|
-
return Qnil;
|
|
1626
|
-
}
|
|
1733
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
1734
|
+
|
|
1627
1735
|
result = rb_str_new2(escaped);
|
|
1628
1736
|
PQfreemem(escaped);
|
|
1629
1737
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
|
@@ -1646,7 +1754,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
|
1646
1754
|
{
|
|
1647
1755
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1648
1756
|
char *escaped = NULL;
|
|
1649
|
-
VALUE error;
|
|
1650
1757
|
VALUE result = Qnil;
|
|
1651
1758
|
int enc_idx = this->enc_idx;
|
|
1652
1759
|
|
|
@@ -1657,12 +1764,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
|
1657
1764
|
|
|
1658
1765
|
escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
|
1659
1766
|
if (escaped == NULL)
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
rb_iv_set(error, "@connection", self);
|
|
1663
|
-
rb_exc_raise(error);
|
|
1664
|
-
return Qnil;
|
|
1665
|
-
}
|
|
1767
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
1768
|
+
|
|
1666
1769
|
result = rb_str_new2(escaped);
|
|
1667
1770
|
PQfreemem(escaped);
|
|
1668
1771
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
|
@@ -1710,14 +1813,9 @@ static VALUE
|
|
|
1710
1813
|
pgconn_set_single_row_mode(VALUE self)
|
|
1711
1814
|
{
|
|
1712
1815
|
PGconn *conn = pg_get_pgconn(self);
|
|
1713
|
-
VALUE error;
|
|
1714
1816
|
|
|
1715
1817
|
if( PQsetSingleRowMode(conn) == 0 )
|
|
1716
|
-
|
|
1717
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
|
1718
|
-
rb_iv_set(error, "@connection", self);
|
|
1719
|
-
rb_exc_raise(error);
|
|
1720
|
-
}
|
|
1818
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
1721
1819
|
|
|
1722
1820
|
return self;
|
|
1723
1821
|
}
|
|
@@ -1741,15 +1839,13 @@ static VALUE
|
|
|
1741
1839
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1742
1840
|
{
|
|
1743
1841
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1744
|
-
VALUE error;
|
|
1745
1842
|
|
|
1746
1843
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
|
1747
1844
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
|
1748
|
-
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
}
|
|
1845
|
+
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
|
1846
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
1847
|
+
|
|
1848
|
+
pgconn_wait_for_flush( self );
|
|
1753
1849
|
return Qnil;
|
|
1754
1850
|
}
|
|
1755
1851
|
|
|
@@ -1779,7 +1875,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
|
1779
1875
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
1780
1876
|
* { :value => <string value>, :type => 0, :format => 0 }
|
|
1781
1877
|
*
|
|
1782
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
1878
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
1783
1879
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
1784
1880
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
1785
1881
|
*
|
|
@@ -1805,7 +1901,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1805
1901
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1806
1902
|
int result;
|
|
1807
1903
|
VALUE command, in_res_fmt;
|
|
1808
|
-
VALUE error;
|
|
1809
1904
|
int nParams;
|
|
1810
1905
|
int resultFormat;
|
|
1811
1906
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1822,11 +1917,10 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1822
1917
|
|
|
1823
1918
|
free_query_params( ¶msData );
|
|
1824
1919
|
|
|
1825
|
-
if(result == 0)
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
}
|
|
1920
|
+
if(result == 0)
|
|
1921
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
1922
|
+
|
|
1923
|
+
pgconn_wait_for_flush( self );
|
|
1830
1924
|
return Qnil;
|
|
1831
1925
|
}
|
|
1832
1926
|
|
|
@@ -1847,7 +1941,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1847
1941
|
*
|
|
1848
1942
|
* For example: "SELECT $1::int"
|
|
1849
1943
|
*
|
|
1850
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
1944
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
1851
1945
|
* inside the SQL query.
|
|
1852
1946
|
*/
|
|
1853
1947
|
static VALUE
|
|
@@ -1857,7 +1951,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1857
1951
|
int result;
|
|
1858
1952
|
VALUE name, command, in_paramtypes;
|
|
1859
1953
|
VALUE param;
|
|
1860
|
-
VALUE error;
|
|
1861
1954
|
int i = 0;
|
|
1862
1955
|
int nParams = 0;
|
|
1863
1956
|
Oid *paramTypes = NULL;
|
|
@@ -1886,10 +1979,9 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1886
1979
|
xfree(paramTypes);
|
|
1887
1980
|
|
|
1888
1981
|
if(result == 0) {
|
|
1889
|
-
|
|
1890
|
-
rb_iv_set(error, "@connection", self);
|
|
1891
|
-
rb_exc_raise(error);
|
|
1982
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
1892
1983
|
}
|
|
1984
|
+
pgconn_wait_for_flush( self );
|
|
1893
1985
|
return Qnil;
|
|
1894
1986
|
}
|
|
1895
1987
|
|
|
@@ -1911,7 +2003,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1911
2003
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
1912
2004
|
* { :value => <string value>, :format => 0 }
|
|
1913
2005
|
*
|
|
1914
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
2006
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
1915
2007
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
1916
2008
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
1917
2009
|
*
|
|
@@ -1931,7 +2023,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1931
2023
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1932
2024
|
int result;
|
|
1933
2025
|
VALUE name, in_res_fmt;
|
|
1934
|
-
VALUE error;
|
|
1935
2026
|
int nParams;
|
|
1936
2027
|
int resultFormat;
|
|
1937
2028
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1941,7 +2032,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1941
2032
|
|
|
1942
2033
|
if(NIL_P(paramsData.params)) {
|
|
1943
2034
|
paramsData.params = rb_ary_new2(0);
|
|
1944
|
-
resultFormat = 0;
|
|
1945
2035
|
}
|
|
1946
2036
|
pgconn_query_assign_typemap( self, ¶msData );
|
|
1947
2037
|
|
|
@@ -1954,11 +2044,10 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1954
2044
|
|
|
1955
2045
|
free_query_params( ¶msData );
|
|
1956
2046
|
|
|
1957
|
-
if(result == 0)
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
}
|
|
2047
|
+
if(result == 0)
|
|
2048
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2049
|
+
|
|
2050
|
+
pgconn_wait_for_flush( self );
|
|
1962
2051
|
return Qnil;
|
|
1963
2052
|
}
|
|
1964
2053
|
|
|
@@ -1972,14 +2061,12 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1972
2061
|
static VALUE
|
|
1973
2062
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1974
2063
|
{
|
|
1975
|
-
VALUE error;
|
|
1976
2064
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1977
2065
|
/* returns 0 on failure */
|
|
1978
|
-
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
}
|
|
2066
|
+
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
|
2067
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2068
|
+
|
|
2069
|
+
pgconn_wait_for_flush( self );
|
|
1983
2070
|
return Qnil;
|
|
1984
2071
|
}
|
|
1985
2072
|
|
|
@@ -1994,36 +2081,18 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
1994
2081
|
static VALUE
|
|
1995
2082
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
1996
2083
|
{
|
|
1997
|
-
VALUE error;
|
|
1998
2084
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1999
2085
|
/* returns 0 on failure */
|
|
2000
|
-
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
}
|
|
2086
|
+
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
|
2087
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2088
|
+
|
|
2089
|
+
pgconn_wait_for_flush( self );
|
|
2005
2090
|
return Qnil;
|
|
2006
2091
|
}
|
|
2007
2092
|
|
|
2008
2093
|
|
|
2009
|
-
/*
|
|
2010
|
-
* call-seq:
|
|
2011
|
-
* conn.get_result() -> PG::Result
|
|
2012
|
-
* conn.get_result() {|pg_result| block }
|
|
2013
|
-
*
|
|
2014
|
-
* Blocks waiting for the next result from a call to
|
|
2015
|
-
* #send_query (or another asynchronous command), and returns
|
|
2016
|
-
* it. Returns +nil+ if no more results are available.
|
|
2017
|
-
*
|
|
2018
|
-
* Note: call this function repeatedly until it returns +nil+, or else
|
|
2019
|
-
* you will not be able to issue further commands.
|
|
2020
|
-
*
|
|
2021
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
|
2022
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
|
2023
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
|
2024
|
-
*/
|
|
2025
2094
|
static VALUE
|
|
2026
|
-
|
|
2095
|
+
pgconn_sync_get_result(VALUE self)
|
|
2027
2096
|
{
|
|
2028
2097
|
PGconn *conn = pg_get_pgconn(self);
|
|
2029
2098
|
PGresult *result;
|
|
@@ -2049,17 +2118,15 @@ pgconn_get_result(VALUE self)
|
|
|
2049
2118
|
* or *notifies* to see if the state has changed.
|
|
2050
2119
|
*/
|
|
2051
2120
|
static VALUE
|
|
2052
|
-
pgconn_consume_input(self)
|
|
2053
|
-
VALUE self;
|
|
2121
|
+
pgconn_consume_input(VALUE self)
|
|
2054
2122
|
{
|
|
2055
|
-
VALUE error;
|
|
2056
2123
|
PGconn *conn = pg_get_pgconn(self);
|
|
2057
2124
|
/* returns 0 on error */
|
|
2058
2125
|
if(PQconsumeInput(conn) == 0) {
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
rb_exc_raise(error);
|
|
2126
|
+
pgconn_close_socket_io(self);
|
|
2127
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
|
|
2062
2128
|
}
|
|
2129
|
+
|
|
2063
2130
|
return Qnil;
|
|
2064
2131
|
}
|
|
2065
2132
|
|
|
@@ -2068,37 +2135,18 @@ pgconn_consume_input(self)
|
|
|
2068
2135
|
* conn.is_busy() -> Boolean
|
|
2069
2136
|
*
|
|
2070
2137
|
* Returns +true+ if a command is busy, that is, if
|
|
2071
|
-
*
|
|
2138
|
+
* #get_result would block. Otherwise returns +false+.
|
|
2072
2139
|
*/
|
|
2073
2140
|
static VALUE
|
|
2074
|
-
pgconn_is_busy(self)
|
|
2075
|
-
VALUE self;
|
|
2141
|
+
pgconn_is_busy(VALUE self)
|
|
2076
2142
|
{
|
|
2077
2143
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2078
2144
|
}
|
|
2079
2145
|
|
|
2080
|
-
/*
|
|
2081
|
-
* call-seq:
|
|
2082
|
-
* conn.setnonblocking(Boolean) -> nil
|
|
2083
|
-
*
|
|
2084
|
-
* Sets the nonblocking status of the connection.
|
|
2085
|
-
* In the blocking state, calls to #send_query
|
|
2086
|
-
* will block until the message is sent to the server,
|
|
2087
|
-
* but will not wait for the query results.
|
|
2088
|
-
* In the nonblocking state, calls to #send_query
|
|
2089
|
-
* will return an error if the socket is not ready for
|
|
2090
|
-
* writing.
|
|
2091
|
-
* Note: This function does not affect #exec, because
|
|
2092
|
-
* that function doesn't return until the server has
|
|
2093
|
-
* processed the query and returned the results.
|
|
2094
|
-
* Returns +nil+.
|
|
2095
|
-
*/
|
|
2096
2146
|
static VALUE
|
|
2097
|
-
|
|
2098
|
-
VALUE self, state;
|
|
2147
|
+
pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
|
2099
2148
|
{
|
|
2100
2149
|
int arg;
|
|
2101
|
-
VALUE error;
|
|
2102
2150
|
PGconn *conn = pg_get_pgconn(self);
|
|
2103
2151
|
if(state == Qtrue)
|
|
2104
2152
|
arg = 1;
|
|
@@ -2107,67 +2155,32 @@ pgconn_setnonblocking(self, state)
|
|
|
2107
2155
|
else
|
|
2108
2156
|
rb_raise(rb_eArgError, "Boolean value expected");
|
|
2109
2157
|
|
|
2110
|
-
if(PQsetnonblocking(conn, arg) == -1)
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
rb_exc_raise(error);
|
|
2114
|
-
}
|
|
2158
|
+
if(PQsetnonblocking(conn, arg) == -1)
|
|
2159
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2160
|
+
|
|
2115
2161
|
return Qnil;
|
|
2116
2162
|
}
|
|
2117
2163
|
|
|
2118
2164
|
|
|
2119
|
-
/*
|
|
2120
|
-
* call-seq:
|
|
2121
|
-
* conn.isnonblocking() -> Boolean
|
|
2122
|
-
*
|
|
2123
|
-
* Returns +true+ if a command is busy, that is, if
|
|
2124
|
-
* PQgetResult would block. Otherwise returns +false+.
|
|
2125
|
-
*/
|
|
2126
2165
|
static VALUE
|
|
2127
|
-
|
|
2128
|
-
VALUE self;
|
|
2166
|
+
pgconn_sync_isnonblocking(VALUE self)
|
|
2129
2167
|
{
|
|
2130
2168
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2131
2169
|
}
|
|
2132
2170
|
|
|
2133
|
-
/*
|
|
2134
|
-
* call-seq:
|
|
2135
|
-
* conn.flush() -> Boolean
|
|
2136
|
-
*
|
|
2137
|
-
* Attempts to flush any queued output data to the server.
|
|
2138
|
-
* Returns +true+ if data is successfully flushed, +false+
|
|
2139
|
-
* if not (can only return +false+ if connection is
|
|
2140
|
-
* nonblocking.
|
|
2141
|
-
* Raises PG::Error if some other failure occurred.
|
|
2142
|
-
*/
|
|
2143
2171
|
static VALUE
|
|
2144
|
-
|
|
2145
|
-
VALUE self;
|
|
2172
|
+
pgconn_sync_flush(VALUE self)
|
|
2146
2173
|
{
|
|
2147
2174
|
PGconn *conn = pg_get_pgconn(self);
|
|
2148
|
-
int ret;
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
|
2153
|
-
rb_iv_set(error, "@connection", self);
|
|
2154
|
-
rb_exc_raise(error);
|
|
2155
|
-
}
|
|
2175
|
+
int ret = PQflush(conn);
|
|
2176
|
+
if(ret == -1)
|
|
2177
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2178
|
+
|
|
2156
2179
|
return (ret) ? Qfalse : Qtrue;
|
|
2157
2180
|
}
|
|
2158
2181
|
|
|
2159
|
-
/*
|
|
2160
|
-
* call-seq:
|
|
2161
|
-
* conn.cancel() -> String
|
|
2162
|
-
*
|
|
2163
|
-
* Requests cancellation of the command currently being
|
|
2164
|
-
* processed. (Only implemented in PostgreSQL >= 8.0)
|
|
2165
|
-
*
|
|
2166
|
-
* Returns +nil+ on success, or a string containing the
|
|
2167
|
-
* error message if a failure occurs.
|
|
2168
|
-
*/
|
|
2169
2182
|
static VALUE
|
|
2170
|
-
|
|
2183
|
+
pgconn_sync_cancel(VALUE self)
|
|
2171
2184
|
{
|
|
2172
2185
|
char errbuf[256];
|
|
2173
2186
|
PGcancel *cancel;
|
|
@@ -2176,9 +2189,9 @@ pgconn_cancel(VALUE self)
|
|
|
2176
2189
|
|
|
2177
2190
|
cancel = PQgetCancel(pg_get_pgconn(self));
|
|
2178
2191
|
if(cancel == NULL)
|
|
2179
|
-
|
|
2192
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
|
2180
2193
|
|
|
2181
|
-
ret = gvl_PQcancel(cancel, errbuf,
|
|
2194
|
+
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
|
2182
2195
|
if(ret == 1)
|
|
2183
2196
|
retval = Qnil;
|
|
2184
2197
|
else
|
|
@@ -2229,55 +2242,63 @@ pgconn_notifies(VALUE self)
|
|
|
2229
2242
|
return hash;
|
|
2230
2243
|
}
|
|
2231
2244
|
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
/*
|
|
2235
|
-
*
|
|
2236
|
-
* instead of rb_wait_for_single_fd().
|
|
2245
|
+
#if defined(_WIN32)
|
|
2246
|
+
|
|
2247
|
+
/* We use a specialized implementation of rb_io_wait() on Windows.
|
|
2248
|
+
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
|
2237
2249
|
*/
|
|
2238
2250
|
|
|
2251
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
|
2252
|
+
#include <ruby/fiber/scheduler.h>
|
|
2253
|
+
#endif
|
|
2254
|
+
|
|
2255
|
+
typedef enum {
|
|
2256
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2257
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2258
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2259
|
+
} pg_rb_io_event_t;
|
|
2260
|
+
|
|
2239
2261
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2240
2262
|
|
|
2241
|
-
static
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2263
|
+
static VALUE
|
|
2264
|
+
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2265
|
+
rb_io_t *fptr;
|
|
2266
|
+
struct timeval ptimeout;
|
|
2267
|
+
|
|
2246
2268
|
struct timeval aborttime={0,0}, currtime, waittime;
|
|
2247
2269
|
DWORD timeout_milisec = INFINITE;
|
|
2248
|
-
|
|
2249
|
-
WSAEVENT hEvent;
|
|
2250
|
-
|
|
2251
|
-
if ( sd < 0 )
|
|
2252
|
-
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
|
2270
|
+
HANDLE hEvent = WSACreateEvent();
|
|
2253
2271
|
|
|
2254
|
-
|
|
2272
|
+
long rb_events = NUM2UINT(events);
|
|
2273
|
+
long w32_events = 0;
|
|
2274
|
+
DWORD wait_ret;
|
|
2255
2275
|
|
|
2256
|
-
|
|
2257
|
-
if(
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
}
|
|
2276
|
+
GetOpenFile((io), fptr);
|
|
2277
|
+
if( !NIL_P(timeout) ){
|
|
2278
|
+
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2279
|
+
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
|
2261
2280
|
|
|
2262
|
-
if ( ptimeout ) {
|
|
2263
2281
|
gettimeofday(&currtime, NULL);
|
|
2264
|
-
timeradd(&currtime, ptimeout, &aborttime);
|
|
2282
|
+
timeradd(&currtime, &ptimeout, &aborttime);
|
|
2265
2283
|
}
|
|
2266
2284
|
|
|
2267
|
-
|
|
2268
|
-
|
|
2285
|
+
if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
|
2286
|
+
if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
|
|
2287
|
+
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
|
2288
|
+
|
|
2289
|
+
for(;;) {
|
|
2290
|
+
if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
|
|
2269
2291
|
WSACloseEvent( hEvent );
|
|
2270
2292
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
|
2271
2293
|
}
|
|
2272
2294
|
|
|
2273
|
-
if (
|
|
2295
|
+
if ( !NIL_P(timeout) ) {
|
|
2274
2296
|
gettimeofday(&currtime, NULL);
|
|
2275
2297
|
timersub(&aborttime, &currtime, &waittime);
|
|
2276
2298
|
timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
|
|
2277
2299
|
}
|
|
2278
2300
|
|
|
2279
|
-
|
|
2280
|
-
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2301
|
+
if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2281
2302
|
/* Wait for the socket to become readable before checking again */
|
|
2282
2303
|
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
|
2283
2304
|
} else {
|
|
@@ -2286,9 +2307,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2286
2307
|
|
|
2287
2308
|
if ( wait_ret == WAIT_TIMEOUT ) {
|
|
2288
2309
|
WSACloseEvent( hEvent );
|
|
2289
|
-
return
|
|
2310
|
+
return UINT2NUM(0);
|
|
2290
2311
|
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
|
2312
|
+
WSACloseEvent( hEvent );
|
|
2291
2313
|
/* The event we were waiting for. */
|
|
2314
|
+
return UINT2NUM(rb_events);
|
|
2292
2315
|
} else if ( wait_ret == WAIT_OBJECT_0 + 1) {
|
|
2293
2316
|
/* This indicates interruption from timer thread, GC, exception
|
|
2294
2317
|
* from other threads etc... */
|
|
@@ -2300,36 +2323,66 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2300
2323
|
WSACloseEvent( hEvent );
|
|
2301
2324
|
rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
|
2302
2325
|
}
|
|
2303
|
-
|
|
2304
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
|
2305
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
|
2306
|
-
WSACloseEvent( hEvent );
|
|
2307
|
-
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
|
2308
|
-
}
|
|
2309
2326
|
}
|
|
2327
|
+
}
|
|
2310
2328
|
|
|
2311
|
-
|
|
2312
|
-
|
|
2329
|
+
static VALUE
|
|
2330
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2331
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
|
2332
|
+
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
|
2333
|
+
* Fortunatelly ruby-3.1 offers a C-API for it.
|
|
2334
|
+
*/
|
|
2335
|
+
VALUE scheduler = rb_fiber_scheduler_current();
|
|
2336
|
+
|
|
2337
|
+
if (!NIL_P(scheduler)) {
|
|
2338
|
+
return rb_io_wait(io, events, timeout);
|
|
2339
|
+
}
|
|
2340
|
+
#endif
|
|
2341
|
+
return pg_rb_thread_io_wait(io, events, timeout);
|
|
2313
2342
|
}
|
|
2314
2343
|
|
|
2344
|
+
#elif defined(HAVE_RB_IO_WAIT)
|
|
2345
|
+
|
|
2346
|
+
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
|
2347
|
+
#define pg_rb_io_wait rb_io_wait
|
|
2348
|
+
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
|
2349
|
+
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
|
2350
|
+
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
|
2351
|
+
|
|
2315
2352
|
#else
|
|
2353
|
+
/* For compat with ruby < 3.0 */
|
|
2354
|
+
|
|
2355
|
+
typedef enum {
|
|
2356
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2357
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2358
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2359
|
+
} pg_rb_io_event_t;
|
|
2316
2360
|
|
|
2317
|
-
|
|
2361
|
+
static VALUE
|
|
2362
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2363
|
+
rb_io_t *fptr;
|
|
2364
|
+
struct timeval waittime;
|
|
2365
|
+
int res;
|
|
2366
|
+
|
|
2367
|
+
GetOpenFile((io), fptr);
|
|
2368
|
+
if( !NIL_P(timeout) ){
|
|
2369
|
+
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2370
|
+
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
|
2371
|
+
}
|
|
2372
|
+
res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
|
2373
|
+
|
|
2374
|
+
return UINT2NUM(res);
|
|
2375
|
+
}
|
|
2376
|
+
#endif
|
|
2318
2377
|
|
|
2319
2378
|
static void *
|
|
2320
|
-
wait_socket_readable(
|
|
2379
|
+
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
|
2321
2380
|
{
|
|
2322
|
-
|
|
2323
|
-
int ret;
|
|
2381
|
+
VALUE ret;
|
|
2324
2382
|
void *retval;
|
|
2325
2383
|
struct timeval aborttime={0,0}, currtime, waittime;
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
|
2329
|
-
|
|
2330
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
|
2331
|
-
if ( PQconsumeInput(conn) == 0 )
|
|
2332
|
-
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
|
2384
|
+
VALUE wait_timeout = Qnil;
|
|
2385
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
2333
2386
|
|
|
2334
2387
|
if ( ptimeout ) {
|
|
2335
2388
|
gettimeofday(&currtime, NULL);
|
|
@@ -2340,36 +2393,80 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2340
2393
|
if ( ptimeout ) {
|
|
2341
2394
|
gettimeofday(&currtime, NULL);
|
|
2342
2395
|
timersub(&aborttime, &currtime, &waittime);
|
|
2396
|
+
wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
|
|
2343
2397
|
}
|
|
2344
2398
|
|
|
2345
2399
|
/* Is the given timeout valid? */
|
|
2346
2400
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2401
|
+
VALUE socket_io;
|
|
2402
|
+
|
|
2403
|
+
/* before we wait for data, make sure everything has been sent */
|
|
2404
|
+
pgconn_async_flush(self);
|
|
2405
|
+
if ((retval=is_readable(conn)))
|
|
2406
|
+
return retval;
|
|
2407
|
+
|
|
2408
|
+
socket_io = pgconn_socket_io(self);
|
|
2347
2409
|
/* Wait for the socket to become readable before checking again */
|
|
2348
|
-
ret =
|
|
2410
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
|
2349
2411
|
} else {
|
|
2350
|
-
ret =
|
|
2351
|
-
}
|
|
2352
|
-
|
|
2353
|
-
if ( ret < 0 ){
|
|
2354
|
-
rb_sys_fail( "rb_wait_for_single_fd()" );
|
|
2412
|
+
ret = Qfalse;
|
|
2355
2413
|
}
|
|
2356
2414
|
|
|
2357
2415
|
/* Return false if the select() timed out */
|
|
2358
|
-
if ( ret ==
|
|
2416
|
+
if ( ret == Qfalse ){
|
|
2359
2417
|
return NULL;
|
|
2360
2418
|
}
|
|
2361
2419
|
|
|
2362
2420
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
|
2363
2421
|
if ( PQconsumeInput(conn) == 0 ){
|
|
2364
|
-
|
|
2422
|
+
pgconn_close_socket_io(self);
|
|
2423
|
+
pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
|
|
2365
2424
|
}
|
|
2366
2425
|
}
|
|
2367
2426
|
|
|
2368
2427
|
return retval;
|
|
2369
2428
|
}
|
|
2370
2429
|
|
|
2430
|
+
/*
|
|
2431
|
+
* call-seq:
|
|
2432
|
+
* conn.flush() -> Boolean
|
|
2433
|
+
*
|
|
2434
|
+
* Attempts to flush any queued output data to the server.
|
|
2435
|
+
* Returns +true+ if data is successfully flushed, +false+
|
|
2436
|
+
* if not. It can only return +false+ if connection is
|
|
2437
|
+
* in nonblocking mode.
|
|
2438
|
+
* Raises PG::Error if some other failure occurred.
|
|
2439
|
+
*/
|
|
2440
|
+
static VALUE
|
|
2441
|
+
pgconn_async_flush(VALUE self)
|
|
2442
|
+
{
|
|
2443
|
+
while( pgconn_sync_flush(self) == Qfalse ){
|
|
2444
|
+
/* wait for the socket to become read- or write-ready */
|
|
2445
|
+
int events;
|
|
2446
|
+
VALUE socket_io = pgconn_socket_io(self);
|
|
2447
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
|
2371
2448
|
|
|
2372
|
-
|
|
2449
|
+
if (events & PG_RUBY_IO_READABLE){
|
|
2450
|
+
pgconn_consume_input(self);
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
return Qtrue;
|
|
2454
|
+
}
|
|
2455
|
+
|
|
2456
|
+
static VALUE
|
|
2457
|
+
pgconn_wait_for_flush( VALUE self ){
|
|
2458
|
+
if( !pg_get_connection_safe(self)->flush_data )
|
|
2459
|
+
return Qnil;
|
|
2460
|
+
|
|
2461
|
+
return pgconn_async_flush(self);
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
static VALUE
|
|
2465
|
+
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
|
2466
|
+
t_pg_connection *conn = pg_get_connection(self);
|
|
2467
|
+
conn->flush_data = RTEST(enabled);
|
|
2468
|
+
return enabled;
|
|
2469
|
+
}
|
|
2373
2470
|
|
|
2374
2471
|
static void *
|
|
2375
2472
|
notify_readable(PGconn *conn)
|
|
@@ -2408,7 +2505,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
|
2408
2505
|
ptimeout = &timeout;
|
|
2409
2506
|
}
|
|
2410
2507
|
|
|
2411
|
-
pnotification = (PGnotify*) wait_socket_readable(
|
|
2508
|
+
pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
|
|
2412
2509
|
|
|
2413
2510
|
/* Return nil if the select timed out */
|
|
2414
2511
|
if ( !pnotification ) return Qnil;
|
|
@@ -2429,28 +2526,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
|
2429
2526
|
}
|
|
2430
2527
|
|
|
2431
2528
|
|
|
2432
|
-
/*
|
|
2433
|
-
* call-seq:
|
|
2434
|
-
* conn.put_copy_data( buffer [, encoder] ) -> Boolean
|
|
2435
|
-
*
|
|
2436
|
-
* Transmits _buffer_ as copy data to the server.
|
|
2437
|
-
* Returns true if the data was sent, false if it was
|
|
2438
|
-
* not sent (false is only possible if the connection
|
|
2439
|
-
* is in nonblocking mode, and this command would block).
|
|
2440
|
-
*
|
|
2441
|
-
* _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
|
|
2442
|
-
* This encodes the data fields given as _buffer_ from an Array of Strings to
|
|
2443
|
-
* PostgreSQL's COPY text format inclusive proper escaping. Optionally
|
|
2444
|
-
* the encoder can type cast the fields from various Ruby types in one step,
|
|
2445
|
-
* if PG::TextEncoder::CopyRow#type_map is set accordingly.
|
|
2446
|
-
*
|
|
2447
|
-
* Raises an exception if an error occurs.
|
|
2448
|
-
*
|
|
2449
|
-
* See also #copy_data.
|
|
2450
|
-
*
|
|
2451
|
-
*/
|
|
2452
2529
|
static VALUE
|
|
2453
|
-
|
|
2530
|
+
pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2454
2531
|
{
|
|
2455
2532
|
int ret;
|
|
2456
2533
|
int len;
|
|
@@ -2467,13 +2544,11 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2467
2544
|
if( NIL_P(this->encoder_for_put_copy_data) ){
|
|
2468
2545
|
buffer = value;
|
|
2469
2546
|
} else {
|
|
2470
|
-
p_coder =
|
|
2547
|
+
p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
|
|
2471
2548
|
}
|
|
2472
|
-
} else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
|
|
2473
|
-
Data_Get_Struct( encoder, t_pg_coder, p_coder );
|
|
2474
2549
|
} else {
|
|
2475
|
-
|
|
2476
|
-
|
|
2550
|
+
/* Check argument type and use argument encoder */
|
|
2551
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
|
|
2477
2552
|
}
|
|
2478
2553
|
|
|
2479
2554
|
if( p_coder ){
|
|
@@ -2496,36 +2571,19 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2496
2571
|
Check_Type(buffer, T_STRING);
|
|
2497
2572
|
|
|
2498
2573
|
ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
|
|
2499
|
-
if(ret == -1)
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
rb_exc_raise(error);
|
|
2503
|
-
}
|
|
2574
|
+
if(ret == -1)
|
|
2575
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2576
|
+
|
|
2504
2577
|
RB_GC_GUARD(intermediate);
|
|
2505
2578
|
RB_GC_GUARD(buffer);
|
|
2506
2579
|
|
|
2507
2580
|
return (ret) ? Qtrue : Qfalse;
|
|
2508
2581
|
}
|
|
2509
2582
|
|
|
2510
|
-
/*
|
|
2511
|
-
* call-seq:
|
|
2512
|
-
* conn.put_copy_end( [ error_message ] ) -> Boolean
|
|
2513
|
-
*
|
|
2514
|
-
* Sends end-of-data indication to the server.
|
|
2515
|
-
*
|
|
2516
|
-
* _error_message_ is an optional parameter, and if set,
|
|
2517
|
-
* forces the COPY command to fail with the string
|
|
2518
|
-
* _error_message_.
|
|
2519
|
-
*
|
|
2520
|
-
* Returns true if the end-of-data was sent, false if it was
|
|
2521
|
-
* not sent (false is only possible if the connection
|
|
2522
|
-
* is in nonblocking mode, and this command would block).
|
|
2523
|
-
*/
|
|
2524
2583
|
static VALUE
|
|
2525
|
-
|
|
2584
|
+
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2526
2585
|
{
|
|
2527
2586
|
VALUE str;
|
|
2528
|
-
VALUE error;
|
|
2529
2587
|
int ret;
|
|
2530
2588
|
const char *error_message = NULL;
|
|
2531
2589
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
@@ -2536,38 +2594,16 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
|
2536
2594
|
error_message = pg_cstr_enc(str, this->enc_idx);
|
|
2537
2595
|
|
|
2538
2596
|
ret = gvl_PQputCopyEnd(this->pgconn, error_message);
|
|
2539
|
-
if(ret == -1)
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
rb_exc_raise(error);
|
|
2543
|
-
}
|
|
2597
|
+
if(ret == -1)
|
|
2598
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2599
|
+
|
|
2544
2600
|
return (ret) ? Qtrue : Qfalse;
|
|
2545
2601
|
}
|
|
2546
2602
|
|
|
2547
|
-
/*
|
|
2548
|
-
* call-seq:
|
|
2549
|
-
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
|
|
2550
|
-
*
|
|
2551
|
-
* Return one row of data, +nil+
|
|
2552
|
-
* if the copy is done, or +false+ if the call would
|
|
2553
|
-
* block (only possible if _async_ is true).
|
|
2554
|
-
*
|
|
2555
|
-
* If _decoder_ is not set or +nil+, data is returned as binary string.
|
|
2556
|
-
*
|
|
2557
|
-
* If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
|
|
2558
|
-
* PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
|
|
2559
|
-
* COPY text format to an Array of Strings.
|
|
2560
|
-
* Optionally the decoder can type cast the single fields to various Ruby types in one step,
|
|
2561
|
-
* if PG::TextDecoder::CopyRow#type_map is set accordingly.
|
|
2562
|
-
*
|
|
2563
|
-
* See also #copy_data.
|
|
2564
|
-
*
|
|
2565
|
-
*/
|
|
2566
2603
|
static VALUE
|
|
2567
|
-
|
|
2604
|
+
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2568
2605
|
{
|
|
2569
2606
|
VALUE async_in;
|
|
2570
|
-
VALUE error;
|
|
2571
2607
|
VALUE result;
|
|
2572
2608
|
int ret;
|
|
2573
2609
|
char *buffer;
|
|
@@ -2579,20 +2615,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2579
2615
|
|
|
2580
2616
|
if( NIL_P(decoder) ){
|
|
2581
2617
|
if( !NIL_P(this->decoder_for_get_copy_data) ){
|
|
2582
|
-
p_coder =
|
|
2618
|
+
p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
|
|
2583
2619
|
}
|
|
2584
|
-
} else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
|
|
2585
|
-
Data_Get_Struct( decoder, t_pg_coder, p_coder );
|
|
2586
2620
|
} else {
|
|
2587
|
-
|
|
2588
|
-
|
|
2621
|
+
/* Check argument type and use argument decoder */
|
|
2622
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
|
2589
2623
|
}
|
|
2590
2624
|
|
|
2591
2625
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
|
2592
|
-
if(ret == -2)
|
|
2593
|
-
|
|
2594
|
-
rb_iv_set(error, "@connection", self);
|
|
2595
|
-
rb_exc_raise(error);
|
|
2626
|
+
if(ret == -2){ /* error */
|
|
2627
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2596
2628
|
}
|
|
2597
2629
|
if(ret == -1) { /* No data left */
|
|
2598
2630
|
return Qnil;
|
|
@@ -2830,7 +2862,7 @@ notice_processor_proxy(void *arg, const char *message)
|
|
|
2830
2862
|
* call-seq:
|
|
2831
2863
|
* conn.set_notice_processor {|message| ... } -> Proc
|
|
2832
2864
|
*
|
|
2833
|
-
* See #set_notice_receiver for the
|
|
2865
|
+
* See #set_notice_receiver for the description of what this and the
|
|
2834
2866
|
* notice_processor methods do.
|
|
2835
2867
|
*
|
|
2836
2868
|
* This function takes a new block to act as the notice processor and returns
|
|
@@ -2884,68 +2916,27 @@ pgconn_get_client_encoding(VALUE self)
|
|
|
2884
2916
|
|
|
2885
2917
|
/*
|
|
2886
2918
|
* call-seq:
|
|
2887
|
-
* conn.
|
|
2919
|
+
* conn.sync_set_client_encoding( encoding )
|
|
2888
2920
|
*
|
|
2889
|
-
*
|
|
2921
|
+
* This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
|
|
2922
|
+
* See #async_exec for the differences between the two API variants.
|
|
2923
|
+
* It's not recommended to use explicit sync or async variants but #set_client_encoding instead, unless you have a good reason to do so.
|
|
2890
2924
|
*/
|
|
2891
2925
|
static VALUE
|
|
2892
|
-
|
|
2926
|
+
pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2893
2927
|
{
|
|
2894
2928
|
PGconn *conn = pg_get_pgconn( self );
|
|
2895
2929
|
|
|
2896
2930
|
Check_Type(str, T_STRING);
|
|
2897
2931
|
|
|
2898
|
-
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
2899
|
-
|
|
2900
|
-
|
|
2932
|
+
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
2933
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2934
|
+
|
|
2901
2935
|
pgconn_set_internal_encoding_index( self );
|
|
2902
2936
|
|
|
2903
2937
|
return Qnil;
|
|
2904
2938
|
}
|
|
2905
2939
|
|
|
2906
|
-
/*
|
|
2907
|
-
* call-seq:
|
|
2908
|
-
* conn.transaction { |conn| ... } -> result of the block
|
|
2909
|
-
*
|
|
2910
|
-
* Executes a +BEGIN+ at the start of the block,
|
|
2911
|
-
* and a +COMMIT+ at the end of the block, or
|
|
2912
|
-
* +ROLLBACK+ if any exception occurs.
|
|
2913
|
-
*/
|
|
2914
|
-
static VALUE
|
|
2915
|
-
pgconn_transaction(VALUE self)
|
|
2916
|
-
{
|
|
2917
|
-
PGconn *conn = pg_get_pgconn(self);
|
|
2918
|
-
PGresult *result;
|
|
2919
|
-
VALUE rb_pgresult;
|
|
2920
|
-
VALUE block_result = Qnil;
|
|
2921
|
-
int status;
|
|
2922
|
-
|
|
2923
|
-
if (rb_block_given_p()) {
|
|
2924
|
-
result = gvl_PQexec(conn, "BEGIN");
|
|
2925
|
-
rb_pgresult = pg_new_result(result, self);
|
|
2926
|
-
pg_result_check(rb_pgresult);
|
|
2927
|
-
block_result = rb_protect(rb_yield, self, &status);
|
|
2928
|
-
if(status == 0) {
|
|
2929
|
-
result = gvl_PQexec(conn, "COMMIT");
|
|
2930
|
-
rb_pgresult = pg_new_result(result, self);
|
|
2931
|
-
pg_result_check(rb_pgresult);
|
|
2932
|
-
}
|
|
2933
|
-
else {
|
|
2934
|
-
/* exception occurred, ROLLBACK and re-raise */
|
|
2935
|
-
result = gvl_PQexec(conn, "ROLLBACK");
|
|
2936
|
-
rb_pgresult = pg_new_result(result, self);
|
|
2937
|
-
pg_result_check(rb_pgresult);
|
|
2938
|
-
rb_jump_tag(status);
|
|
2939
|
-
}
|
|
2940
|
-
|
|
2941
|
-
}
|
|
2942
|
-
else {
|
|
2943
|
-
/* no block supplied? */
|
|
2944
|
-
rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
|
|
2945
|
-
}
|
|
2946
|
-
return block_result;
|
|
2947
|
-
}
|
|
2948
|
-
|
|
2949
2940
|
|
|
2950
2941
|
/*
|
|
2951
2942
|
* call-seq:
|
|
@@ -3020,10 +3011,8 @@ get_result_readable(PGconn *conn)
|
|
|
3020
3011
|
* If +true+ is returned, +conn.is_busy+ will return +false+
|
|
3021
3012
|
* and +conn.get_result+ will not block.
|
|
3022
3013
|
*/
|
|
3023
|
-
|
|
3014
|
+
VALUE
|
|
3024
3015
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3025
|
-
PGconn *conn = pg_get_pgconn( self );
|
|
3026
|
-
|
|
3027
3016
|
struct timeval timeout;
|
|
3028
3017
|
struct timeval *ptimeout = NULL;
|
|
3029
3018
|
VALUE timeout_in;
|
|
@@ -3037,7 +3026,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
|
3037
3026
|
ptimeout = &timeout;
|
|
3038
3027
|
}
|
|
3039
3028
|
|
|
3040
|
-
ret = wait_socket_readable(
|
|
3029
|
+
ret = wait_socket_readable( self, ptimeout, get_result_readable);
|
|
3041
3030
|
|
|
3042
3031
|
if( !ret )
|
|
3043
3032
|
return Qfalse;
|
|
@@ -3046,6 +3035,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
|
3046
3035
|
}
|
|
3047
3036
|
|
|
3048
3037
|
|
|
3038
|
+
/*
|
|
3039
|
+
* call-seq:
|
|
3040
|
+
* conn.sync_get_last_result( ) -> PG::Result
|
|
3041
|
+
*
|
|
3042
|
+
* This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
|
|
3043
|
+
* See #async_exec for the differences between the two API variants.
|
|
3044
|
+
* It's not recommended to use explicit sync or async variants but #get_last_result instead, unless you have a good reason to do so.
|
|
3045
|
+
*/
|
|
3046
|
+
static VALUE
|
|
3047
|
+
pgconn_sync_get_last_result(VALUE self)
|
|
3048
|
+
{
|
|
3049
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3050
|
+
VALUE rb_pgresult = Qnil;
|
|
3051
|
+
PGresult *cur, *prev;
|
|
3052
|
+
|
|
3053
|
+
|
|
3054
|
+
cur = prev = NULL;
|
|
3055
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
|
3056
|
+
int status;
|
|
3057
|
+
|
|
3058
|
+
if (prev) PQclear(prev);
|
|
3059
|
+
prev = cur;
|
|
3060
|
+
|
|
3061
|
+
status = PQresultStatus(cur);
|
|
3062
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
|
3063
|
+
break;
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
if (prev) {
|
|
3067
|
+
rb_pgresult = pg_new_result( prev, self );
|
|
3068
|
+
pg_result_check(rb_pgresult);
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
return rb_pgresult;
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3049
3074
|
/*
|
|
3050
3075
|
* call-seq:
|
|
3051
3076
|
* conn.get_last_result( ) -> PG::Result
|
|
@@ -3056,27 +3081,36 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
|
3056
3081
|
* returns the last non-NULL result, or +nil+ if no
|
|
3057
3082
|
* results are available.
|
|
3058
3083
|
*
|
|
3084
|
+
* If the last result contains a bad result_status, an
|
|
3085
|
+
* appropriate exception is raised.
|
|
3086
|
+
*
|
|
3059
3087
|
* This function is similar to #get_result
|
|
3060
3088
|
* except that it is designed to get one and only
|
|
3061
|
-
* one result.
|
|
3089
|
+
* one result and that it checks the result state.
|
|
3062
3090
|
*/
|
|
3063
3091
|
static VALUE
|
|
3064
|
-
|
|
3092
|
+
pgconn_async_get_last_result(VALUE self)
|
|
3065
3093
|
{
|
|
3066
3094
|
PGconn *conn = pg_get_pgconn(self);
|
|
3067
3095
|
VALUE rb_pgresult = Qnil;
|
|
3068
3096
|
PGresult *cur, *prev;
|
|
3069
3097
|
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
|
3098
|
+
cur = prev = NULL;
|
|
3099
|
+
for(;;) {
|
|
3073
3100
|
int status;
|
|
3074
3101
|
|
|
3102
|
+
/* wait for input (without blocking) before reading each result */
|
|
3103
|
+
wait_socket_readable(self, NULL, get_result_readable);
|
|
3104
|
+
|
|
3105
|
+
cur = gvl_PQgetResult(conn);
|
|
3106
|
+
if (cur == NULL)
|
|
3107
|
+
break;
|
|
3108
|
+
|
|
3075
3109
|
if (prev) PQclear(prev);
|
|
3076
3110
|
prev = cur;
|
|
3077
3111
|
|
|
3078
3112
|
status = PQresultStatus(cur);
|
|
3079
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
|
3113
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
|
3080
3114
|
break;
|
|
3081
3115
|
}
|
|
3082
3116
|
|
|
@@ -3093,29 +3127,91 @@ pgconn_get_last_result(VALUE self)
|
|
|
3093
3127
|
* conn.discard_results()
|
|
3094
3128
|
*
|
|
3095
3129
|
* Silently discard any prior query result that application didn't eat.
|
|
3096
|
-
* This is
|
|
3097
|
-
*
|
|
3130
|
+
* This is internally used prior to Connection#exec and sibling methods.
|
|
3131
|
+
* It doesn't raise an exception on connection errors, but returns +false+ instead.
|
|
3132
|
+
*
|
|
3133
|
+
* Returns:
|
|
3134
|
+
* * +nil+ when the connection is already idle
|
|
3135
|
+
* * +true+ when some results have been discarded
|
|
3136
|
+
* * +false+ when a failure occured and the connection was closed
|
|
3137
|
+
*
|
|
3098
3138
|
*/
|
|
3099
3139
|
static VALUE
|
|
3100
3140
|
pgconn_discard_results(VALUE self)
|
|
3101
3141
|
{
|
|
3102
3142
|
PGconn *conn = pg_get_pgconn(self);
|
|
3143
|
+
VALUE socket_io;
|
|
3144
|
+
|
|
3145
|
+
switch( PQtransactionStatus(conn) ) {
|
|
3146
|
+
case PQTRANS_IDLE:
|
|
3147
|
+
case PQTRANS_INTRANS:
|
|
3148
|
+
case PQTRANS_INERROR:
|
|
3149
|
+
return Qnil;
|
|
3150
|
+
default:;
|
|
3151
|
+
}
|
|
3103
3152
|
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3153
|
+
socket_io = pgconn_socket_io(self);
|
|
3154
|
+
|
|
3155
|
+
for(;;) {
|
|
3156
|
+
PGresult *cur;
|
|
3157
|
+
int status;
|
|
3158
|
+
|
|
3159
|
+
/* pgconn_block() raises an exception in case of errors.
|
|
3160
|
+
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
|
3161
|
+
*/
|
|
3162
|
+
while( gvl_PQisBusy(conn) ){
|
|
3163
|
+
int events;
|
|
3164
|
+
|
|
3165
|
+
switch( PQflush(conn) ) {
|
|
3166
|
+
case 1:
|
|
3167
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
|
3168
|
+
if (events & PG_RUBY_IO_READABLE){
|
|
3169
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3170
|
+
}
|
|
3171
|
+
break;
|
|
3172
|
+
case 0:
|
|
3173
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
|
3174
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3175
|
+
break;
|
|
3176
|
+
default:
|
|
3177
|
+
goto error;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
|
|
3181
|
+
cur = gvl_PQgetResult(conn);
|
|
3182
|
+
if( cur == NULL) break;
|
|
3183
|
+
|
|
3184
|
+
status = PQresultStatus(cur);
|
|
3107
3185
|
PQclear(cur);
|
|
3108
3186
|
if (status == PGRES_COPY_IN){
|
|
3109
|
-
gvl_PQputCopyEnd(conn, "COPY terminated by new
|
|
3187
|
+
while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
|
|
3188
|
+
pgconn_async_flush(self);
|
|
3189
|
+
}
|
|
3110
3190
|
}
|
|
3111
3191
|
if (status == PGRES_COPY_OUT){
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3192
|
+
for(;;) {
|
|
3193
|
+
char *buffer = NULL;
|
|
3194
|
+
int st = gvl_PQgetCopyData(conn, &buffer, 1);
|
|
3195
|
+
if( st == 0 ) {
|
|
3196
|
+
/* would block -> wait for readable data */
|
|
3197
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
|
3198
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3199
|
+
} else if( st > 0 ) {
|
|
3200
|
+
/* some data retrieved -> discard it */
|
|
3201
|
+
PQfreemem(buffer);
|
|
3202
|
+
} else {
|
|
3203
|
+
/* no more data */
|
|
3204
|
+
break;
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3115
3207
|
}
|
|
3116
3208
|
}
|
|
3117
3209
|
|
|
3118
|
-
return
|
|
3210
|
+
return Qtrue;
|
|
3211
|
+
|
|
3212
|
+
error:
|
|
3213
|
+
pgconn_close_socket_io(self);
|
|
3214
|
+
return Qfalse;
|
|
3119
3215
|
}
|
|
3120
3216
|
|
|
3121
3217
|
/*
|
|
@@ -3138,6 +3234,7 @@ pgconn_discard_results(VALUE self)
|
|
|
3138
3234
|
* #exec is an alias for #async_exec which is almost identical to #sync_exec .
|
|
3139
3235
|
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
|
3140
3236
|
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
|
3237
|
+
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
|
3141
3238
|
* Both methods ensure that other threads can process while waiting for the server to
|
|
3142
3239
|
* complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
|
|
3143
3240
|
* This is most notably visible by a delayed reaction to Control+C.
|
|
@@ -3152,8 +3249,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
|
3152
3249
|
|
|
3153
3250
|
pgconn_discard_results( self );
|
|
3154
3251
|
pgconn_send_query( argc, argv, self );
|
|
3155
|
-
|
|
3156
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3252
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3157
3253
|
|
|
3158
3254
|
if ( rb_block_given_p() ) {
|
|
3159
3255
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3182,7 +3278,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
|
3182
3278
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
3183
3279
|
* { :value => <string value>, :type => 0, :format => 0 }
|
|
3184
3280
|
*
|
|
3185
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
3281
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3186
3282
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
3187
3283
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
3188
3284
|
*
|
|
@@ -3225,8 +3321,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
|
3225
3321
|
} else {
|
|
3226
3322
|
pgconn_send_query_params( argc, argv, self );
|
|
3227
3323
|
}
|
|
3228
|
-
|
|
3229
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3324
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3230
3325
|
|
|
3231
3326
|
if ( rb_block_given_p() ) {
|
|
3232
3327
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3252,7 +3347,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
|
3252
3347
|
*
|
|
3253
3348
|
* For example: "SELECT $1::int"
|
|
3254
3349
|
*
|
|
3255
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
3350
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3256
3351
|
* inside the SQL query.
|
|
3257
3352
|
*
|
|
3258
3353
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
|
|
@@ -3264,8 +3359,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
3264
3359
|
|
|
3265
3360
|
pgconn_discard_results( self );
|
|
3266
3361
|
pgconn_send_prepare( argc, argv, self );
|
|
3267
|
-
|
|
3268
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3362
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3269
3363
|
|
|
3270
3364
|
if ( rb_block_given_p() ) {
|
|
3271
3365
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3292,7 +3386,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
3292
3386
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
3293
3387
|
* { :value => <string value>, :format => 0 }
|
|
3294
3388
|
*
|
|
3295
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
3389
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3296
3390
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
3297
3391
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
3298
3392
|
*
|
|
@@ -3318,8 +3412,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
3318
3412
|
|
|
3319
3413
|
pgconn_discard_results( self );
|
|
3320
3414
|
pgconn_send_query_prepared( argc, argv, self );
|
|
3321
|
-
|
|
3322
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3415
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3323
3416
|
|
|
3324
3417
|
if ( rb_block_given_p() ) {
|
|
3325
3418
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3343,8 +3436,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
|
3343
3436
|
|
|
3344
3437
|
pgconn_discard_results( self );
|
|
3345
3438
|
pgconn_send_describe_portal( self, portal );
|
|
3346
|
-
|
|
3347
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3439
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3348
3440
|
|
|
3349
3441
|
if ( rb_block_given_p() ) {
|
|
3350
3442
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3368,8 +3460,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
3368
3460
|
|
|
3369
3461
|
pgconn_discard_results( self );
|
|
3370
3462
|
pgconn_send_describe_prepared( self, stmt_name );
|
|
3371
|
-
|
|
3372
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3463
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3373
3464
|
|
|
3374
3465
|
if ( rb_block_given_p() ) {
|
|
3375
3466
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3457,10 +3548,134 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
|
3457
3548
|
#endif
|
|
3458
3549
|
|
|
3459
3550
|
|
|
3551
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
|
3552
|
+
/*
|
|
3553
|
+
* call-seq:
|
|
3554
|
+
* conn.pipeline_status -> Integer
|
|
3555
|
+
*
|
|
3556
|
+
* Returns the current pipeline mode status of the libpq connection.
|
|
3557
|
+
*
|
|
3558
|
+
* PQpipelineStatus can return one of the following values:
|
|
3559
|
+
*
|
|
3560
|
+
* * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
|
|
3561
|
+
* * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
|
|
3562
|
+
* * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
|
3563
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
|
3564
|
+
*
|
|
3565
|
+
* Available since PostgreSQL-14
|
|
3566
|
+
*/
|
|
3567
|
+
static VALUE
|
|
3568
|
+
pgconn_pipeline_status(VALUE self)
|
|
3569
|
+
{
|
|
3570
|
+
int res = PQpipelineStatus(pg_get_pgconn(self));
|
|
3571
|
+
return INT2FIX(res);
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3574
|
+
|
|
3575
|
+
/*
|
|
3576
|
+
* call-seq:
|
|
3577
|
+
* conn.enter_pipeline_mode -> nil
|
|
3578
|
+
*
|
|
3579
|
+
* Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
|
|
3580
|
+
*
|
|
3581
|
+
* Raises PG::Error and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc.
|
|
3582
|
+
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
|
3583
|
+
*
|
|
3584
|
+
* Available since PostgreSQL-14
|
|
3585
|
+
*/
|
|
3586
|
+
static VALUE
|
|
3587
|
+
pgconn_enter_pipeline_mode(VALUE self)
|
|
3588
|
+
{
|
|
3589
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3590
|
+
int res = PQenterPipelineMode(conn);
|
|
3591
|
+
if( res != 1 )
|
|
3592
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3593
|
+
|
|
3594
|
+
return Qnil;
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
/*
|
|
3598
|
+
* call-seq:
|
|
3599
|
+
* conn.exit_pipeline_mode -> nil
|
|
3600
|
+
*
|
|
3601
|
+
* Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
|
|
3602
|
+
*
|
|
3603
|
+
* Takes no action if not in pipeline mode.
|
|
3604
|
+
* Raises PG::Error if the current statement isn't finished processing, or PQgetResult has not been called to collect results from all previously sent query.
|
|
3605
|
+
*
|
|
3606
|
+
* Available since PostgreSQL-14
|
|
3607
|
+
*/
|
|
3608
|
+
static VALUE
|
|
3609
|
+
pgconn_exit_pipeline_mode(VALUE self)
|
|
3610
|
+
{
|
|
3611
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3612
|
+
int res = PQexitPipelineMode(conn);
|
|
3613
|
+
if( res != 1 )
|
|
3614
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3615
|
+
|
|
3616
|
+
return Qnil;
|
|
3617
|
+
}
|
|
3618
|
+
|
|
3619
|
+
|
|
3620
|
+
/*
|
|
3621
|
+
* call-seq:
|
|
3622
|
+
* conn.pipeline_sync -> nil
|
|
3623
|
+
*
|
|
3624
|
+
* Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
|
|
3625
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
|
|
3626
|
+
*
|
|
3627
|
+
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
|
3628
|
+
*
|
|
3629
|
+
* Available since PostgreSQL-14
|
|
3630
|
+
*/
|
|
3631
|
+
static VALUE
|
|
3632
|
+
pgconn_pipeline_sync(VALUE self)
|
|
3633
|
+
{
|
|
3634
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3635
|
+
int res = PQpipelineSync(conn);
|
|
3636
|
+
if( res != 1 )
|
|
3637
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3638
|
+
|
|
3639
|
+
return Qnil;
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3642
|
+
/*
|
|
3643
|
+
* call-seq:
|
|
3644
|
+
* conn.pipeline_sync -> nil
|
|
3645
|
+
*
|
|
3646
|
+
* Sends a request for the server to flush its output buffer.
|
|
3647
|
+
*
|
|
3648
|
+
* The server flushes its output buffer automatically as a result of Connection#pipeline_sync being called, or on any request when not in pipeline mode.
|
|
3649
|
+
* This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
|
|
3650
|
+
* Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
|
|
3651
|
+
*
|
|
3652
|
+
* Available since PostgreSQL-14
|
|
3653
|
+
*/
|
|
3654
|
+
static VALUE
|
|
3655
|
+
pgconn_send_flush_request(VALUE self)
|
|
3656
|
+
{
|
|
3657
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3658
|
+
int res = PQsendFlushRequest(conn);
|
|
3659
|
+
if( res != 1 )
|
|
3660
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3661
|
+
|
|
3662
|
+
return Qnil;
|
|
3663
|
+
}
|
|
3664
|
+
|
|
3665
|
+
#endif
|
|
3666
|
+
|
|
3460
3667
|
/**************************************************************************
|
|
3461
3668
|
* LARGE OBJECT SUPPORT
|
|
3462
3669
|
**************************************************************************/
|
|
3463
3670
|
|
|
3671
|
+
#define BLOCKING_BEGIN(conn) do { \
|
|
3672
|
+
int old_nonblocking = PQisnonblocking(conn); \
|
|
3673
|
+
PQsetnonblocking(conn, 0);
|
|
3674
|
+
|
|
3675
|
+
#define BLOCKING_END(th) \
|
|
3676
|
+
PQsetnonblocking(conn, old_nonblocking); \
|
|
3677
|
+
} while(0);
|
|
3678
|
+
|
|
3464
3679
|
/*
|
|
3465
3680
|
* call-seq:
|
|
3466
3681
|
* conn.lo_creat( [mode] ) -> Integer
|
|
@@ -3481,9 +3696,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
|
3481
3696
|
else
|
|
3482
3697
|
mode = NUM2INT(nmode);
|
|
3483
3698
|
|
|
3484
|
-
|
|
3699
|
+
BLOCKING_BEGIN(conn)
|
|
3700
|
+
lo_oid = lo_creat(conn, mode);
|
|
3701
|
+
BLOCKING_END(conn)
|
|
3702
|
+
|
|
3485
3703
|
if (lo_oid == 0)
|
|
3486
|
-
|
|
3704
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
|
|
3487
3705
|
|
|
3488
3706
|
return UINT2NUM(lo_oid);
|
|
3489
3707
|
}
|
|
@@ -3504,7 +3722,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
|
|
3504
3722
|
|
|
3505
3723
|
ret = lo_create(conn, lo_oid);
|
|
3506
3724
|
if (ret == InvalidOid)
|
|
3507
|
-
|
|
3725
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
|
|
3508
3726
|
|
|
3509
3727
|
return UINT2NUM(ret);
|
|
3510
3728
|
}
|
|
@@ -3526,9 +3744,12 @@ pgconn_loimport(VALUE self, VALUE filename)
|
|
|
3526
3744
|
|
|
3527
3745
|
Check_Type(filename, T_STRING);
|
|
3528
3746
|
|
|
3529
|
-
|
|
3747
|
+
BLOCKING_BEGIN(conn)
|
|
3748
|
+
lo_oid = lo_import(conn, StringValueCStr(filename));
|
|
3749
|
+
BLOCKING_END(conn)
|
|
3750
|
+
|
|
3530
3751
|
if (lo_oid == 0) {
|
|
3531
|
-
|
|
3752
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3532
3753
|
}
|
|
3533
3754
|
return UINT2NUM(lo_oid);
|
|
3534
3755
|
}
|
|
@@ -3544,12 +3765,17 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
|
3544
3765
|
{
|
|
3545
3766
|
PGconn *conn = pg_get_pgconn(self);
|
|
3546
3767
|
Oid oid;
|
|
3768
|
+
int ret;
|
|
3547
3769
|
Check_Type(filename, T_STRING);
|
|
3548
3770
|
|
|
3549
3771
|
oid = NUM2UINT(lo_oid);
|
|
3550
3772
|
|
|
3551
|
-
|
|
3552
|
-
|
|
3773
|
+
BLOCKING_BEGIN(conn)
|
|
3774
|
+
ret = lo_export(conn, oid, StringValueCStr(filename));
|
|
3775
|
+
BLOCKING_END(conn)
|
|
3776
|
+
|
|
3777
|
+
if (ret < 0) {
|
|
3778
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3553
3779
|
}
|
|
3554
3780
|
return Qnil;
|
|
3555
3781
|
}
|
|
@@ -3579,8 +3805,12 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
|
3579
3805
|
else
|
|
3580
3806
|
mode = NUM2INT(nmode);
|
|
3581
3807
|
|
|
3582
|
-
|
|
3583
|
-
|
|
3808
|
+
BLOCKING_BEGIN(conn)
|
|
3809
|
+
fd = lo_open(conn, lo_oid, mode);
|
|
3810
|
+
BLOCKING_END(conn)
|
|
3811
|
+
|
|
3812
|
+
if(fd < 0) {
|
|
3813
|
+
pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
|
|
3584
3814
|
}
|
|
3585
3815
|
return INT2FIX(fd);
|
|
3586
3816
|
}
|
|
@@ -3602,11 +3832,15 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
|
3602
3832
|
Check_Type(buffer, T_STRING);
|
|
3603
3833
|
|
|
3604
3834
|
if( RSTRING_LEN(buffer) < 0) {
|
|
3605
|
-
|
|
3835
|
+
pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
|
|
3606
3836
|
}
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3837
|
+
BLOCKING_BEGIN(conn)
|
|
3838
|
+
n = lo_write(conn, fd, StringValuePtr(buffer),
|
|
3839
|
+
RSTRING_LEN(buffer));
|
|
3840
|
+
BLOCKING_END(conn)
|
|
3841
|
+
|
|
3842
|
+
if(n < 0) {
|
|
3843
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
|
|
3610
3844
|
}
|
|
3611
3845
|
|
|
3612
3846
|
return INT2FIX(n);
|
|
@@ -3629,16 +3863,17 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
|
3629
3863
|
VALUE str;
|
|
3630
3864
|
char *buffer;
|
|
3631
3865
|
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
rb_raise(rb_eNoMemError, "ALLOC failed!");
|
|
3866
|
+
if (len < 0)
|
|
3867
|
+
pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
|
|
3635
3868
|
|
|
3636
|
-
|
|
3637
|
-
rb_raise(rb_ePGerror,"nagative length %d given", len);
|
|
3638
|
-
}
|
|
3869
|
+
buffer = ALLOC_N(char, len);
|
|
3639
3870
|
|
|
3640
|
-
|
|
3641
|
-
|
|
3871
|
+
BLOCKING_BEGIN(conn)
|
|
3872
|
+
ret = lo_read(conn, lo_desc, buffer, len);
|
|
3873
|
+
BLOCKING_END(conn)
|
|
3874
|
+
|
|
3875
|
+
if(ret < 0)
|
|
3876
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
|
|
3642
3877
|
|
|
3643
3878
|
if(ret == 0) {
|
|
3644
3879
|
xfree(buffer);
|
|
@@ -3667,8 +3902,12 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
|
3667
3902
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3668
3903
|
int ret;
|
|
3669
3904
|
|
|
3670
|
-
|
|
3671
|
-
|
|
3905
|
+
BLOCKING_BEGIN(conn)
|
|
3906
|
+
ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
|
|
3907
|
+
BLOCKING_END(conn)
|
|
3908
|
+
|
|
3909
|
+
if(ret < 0) {
|
|
3910
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
|
|
3672
3911
|
}
|
|
3673
3912
|
|
|
3674
3913
|
return INT2FIX(ret);
|
|
@@ -3687,8 +3926,12 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
|
|
3687
3926
|
PGconn *conn = pg_get_pgconn(self);
|
|
3688
3927
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3689
3928
|
|
|
3690
|
-
|
|
3691
|
-
|
|
3929
|
+
BLOCKING_BEGIN(conn)
|
|
3930
|
+
position = lo_tell(conn, lo_desc);
|
|
3931
|
+
BLOCKING_END(conn)
|
|
3932
|
+
|
|
3933
|
+
if(position < 0)
|
|
3934
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
|
|
3692
3935
|
|
|
3693
3936
|
return INT2FIX(position);
|
|
3694
3937
|
}
|
|
@@ -3705,9 +3948,14 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
|
3705
3948
|
PGconn *conn = pg_get_pgconn(self);
|
|
3706
3949
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3707
3950
|
size_t len = NUM2INT(in_len);
|
|
3951
|
+
int ret;
|
|
3708
3952
|
|
|
3709
|
-
|
|
3710
|
-
|
|
3953
|
+
BLOCKING_BEGIN(conn)
|
|
3954
|
+
ret = lo_truncate(conn,lo_desc,len);
|
|
3955
|
+
BLOCKING_END(conn)
|
|
3956
|
+
|
|
3957
|
+
if(ret < 0)
|
|
3958
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
|
|
3711
3959
|
|
|
3712
3960
|
return Qnil;
|
|
3713
3961
|
}
|
|
@@ -3723,9 +3971,14 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
|
|
3723
3971
|
{
|
|
3724
3972
|
PGconn *conn = pg_get_pgconn(self);
|
|
3725
3973
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3974
|
+
int ret;
|
|
3975
|
+
|
|
3976
|
+
BLOCKING_BEGIN(conn)
|
|
3977
|
+
ret = lo_close(conn,lo_desc);
|
|
3978
|
+
BLOCKING_END(conn)
|
|
3726
3979
|
|
|
3727
|
-
if(
|
|
3728
|
-
|
|
3980
|
+
if(ret < 0)
|
|
3981
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
|
|
3729
3982
|
|
|
3730
3983
|
return Qnil;
|
|
3731
3984
|
}
|
|
@@ -3741,9 +3994,14 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
|
3741
3994
|
{
|
|
3742
3995
|
PGconn *conn = pg_get_pgconn(self);
|
|
3743
3996
|
Oid oid = NUM2UINT(in_oid);
|
|
3997
|
+
int ret;
|
|
3998
|
+
|
|
3999
|
+
BLOCKING_BEGIN(conn)
|
|
4000
|
+
ret = lo_unlink(conn,oid);
|
|
4001
|
+
BLOCKING_END(conn)
|
|
3744
4002
|
|
|
3745
|
-
if(
|
|
3746
|
-
|
|
4003
|
+
if(ret < 0)
|
|
4004
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
|
|
3747
4005
|
|
|
3748
4006
|
return Qnil;
|
|
3749
4007
|
}
|
|
@@ -3801,11 +4059,11 @@ static VALUE
|
|
|
3801
4059
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3802
4060
|
{
|
|
3803
4061
|
if (NIL_P(enc)) {
|
|
3804
|
-
|
|
4062
|
+
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
|
3805
4063
|
return enc;
|
|
3806
4064
|
}
|
|
3807
4065
|
else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
|
|
3808
|
-
|
|
4066
|
+
pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
|
3809
4067
|
return enc;
|
|
3810
4068
|
}
|
|
3811
4069
|
else {
|
|
@@ -3843,16 +4101,33 @@ pgconn_external_encoding(VALUE self)
|
|
|
3843
4101
|
return rb_enc_from_encoding( enc );
|
|
3844
4102
|
}
|
|
3845
4103
|
|
|
4104
|
+
/*
|
|
4105
|
+
* call-seq:
|
|
4106
|
+
* conn.set_client_encoding( encoding )
|
|
4107
|
+
*
|
|
4108
|
+
* Sets the client encoding to the _encoding_ String.
|
|
4109
|
+
*/
|
|
4110
|
+
static VALUE
|
|
4111
|
+
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4112
|
+
{
|
|
4113
|
+
VALUE query_format, query;
|
|
4114
|
+
|
|
4115
|
+
Check_Type(encname, T_STRING);
|
|
4116
|
+
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
|
4117
|
+
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
|
4118
|
+
|
|
4119
|
+
pgconn_async_exec(1, &query, self);
|
|
4120
|
+
pgconn_set_internal_encoding_index( self );
|
|
4121
|
+
|
|
4122
|
+
return Qnil;
|
|
4123
|
+
}
|
|
3846
4124
|
|
|
3847
4125
|
static VALUE
|
|
3848
4126
|
pgconn_set_client_encoding_async1( VALUE args )
|
|
3849
4127
|
{
|
|
3850
4128
|
VALUE self = ((VALUE*)args)[0];
|
|
3851
4129
|
VALUE encname = ((VALUE*)args)[1];
|
|
3852
|
-
|
|
3853
|
-
VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
|
3854
|
-
|
|
3855
|
-
pgconn_async_exec(1, &query, self);
|
|
4130
|
+
pgconn_async_set_client_encoding(self, encname);
|
|
3856
4131
|
return 0;
|
|
3857
4132
|
}
|
|
3858
4133
|
|
|
@@ -3867,9 +4142,9 @@ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
|
|
|
3867
4142
|
|
|
3868
4143
|
|
|
3869
4144
|
static VALUE
|
|
3870
|
-
pgconn_set_client_encoding_async( VALUE self,
|
|
4145
|
+
pgconn_set_client_encoding_async( VALUE self, VALUE encname )
|
|
3871
4146
|
{
|
|
3872
|
-
VALUE args[] = { self,
|
|
4147
|
+
VALUE args[] = { self, encname };
|
|
3873
4148
|
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
|
3874
4149
|
}
|
|
3875
4150
|
|
|
@@ -3891,10 +4166,9 @@ pgconn_set_default_encoding( VALUE self )
|
|
|
3891
4166
|
|
|
3892
4167
|
if (( enc = rb_default_internal_encoding() )) {
|
|
3893
4168
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
|
3894
|
-
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
|
4169
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
|
3895
4170
|
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
|
3896
4171
|
encname, PQerrorMessage(conn) );
|
|
3897
|
-
pgconn_set_internal_encoding_index( self );
|
|
3898
4172
|
return rb_enc_from_encoding( enc );
|
|
3899
4173
|
} else {
|
|
3900
4174
|
pgconn_set_internal_encoding_index( self );
|
|
@@ -3916,12 +4190,12 @@ static VALUE
|
|
|
3916
4190
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
3917
4191
|
{
|
|
3918
4192
|
t_pg_connection *this = pg_get_connection( self );
|
|
4193
|
+
t_typemap *tm;
|
|
4194
|
+
UNUSED(tm);
|
|
4195
|
+
|
|
4196
|
+
/* Check type of method param */
|
|
4197
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
|
3919
4198
|
|
|
3920
|
-
if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
|
|
3921
|
-
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
|
|
3922
|
-
rb_obj_classname( typemap ) );
|
|
3923
|
-
}
|
|
3924
|
-
Check_Type(typemap, T_DATA);
|
|
3925
4199
|
this->type_map_for_queries = typemap;
|
|
3926
4200
|
|
|
3927
4201
|
return typemap;
|
|
@@ -3956,12 +4230,10 @@ static VALUE
|
|
|
3956
4230
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
3957
4231
|
{
|
|
3958
4232
|
t_pg_connection *this = pg_get_connection( self );
|
|
4233
|
+
t_typemap *tm;
|
|
4234
|
+
UNUSED(tm);
|
|
3959
4235
|
|
|
3960
|
-
|
|
3961
|
-
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
|
|
3962
|
-
rb_obj_classname( typemap ) );
|
|
3963
|
-
}
|
|
3964
|
-
Check_Type(typemap, T_DATA);
|
|
4236
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
|
3965
4237
|
this->type_map_for_results = typemap;
|
|
3966
4238
|
|
|
3967
4239
|
return typemap;
|
|
@@ -3996,20 +4268,19 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
|
3996
4268
|
*
|
|
3997
4269
|
*/
|
|
3998
4270
|
static VALUE
|
|
3999
|
-
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE
|
|
4271
|
+
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4000
4272
|
{
|
|
4001
4273
|
t_pg_connection *this = pg_get_connection( self );
|
|
4002
4274
|
|
|
4003
|
-
if(
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
Check_Type(typemap, T_DATA);
|
|
4275
|
+
if( encoder != Qnil ){
|
|
4276
|
+
t_pg_coder *co;
|
|
4277
|
+
UNUSED(co);
|
|
4278
|
+
/* Check argument type */
|
|
4279
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
|
4009
4280
|
}
|
|
4010
|
-
this->encoder_for_put_copy_data =
|
|
4281
|
+
this->encoder_for_put_copy_data = encoder;
|
|
4011
4282
|
|
|
4012
|
-
return
|
|
4283
|
+
return encoder;
|
|
4013
4284
|
}
|
|
4014
4285
|
|
|
4015
4286
|
/*
|
|
@@ -4045,20 +4316,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
|
4045
4316
|
*
|
|
4046
4317
|
*/
|
|
4047
4318
|
static VALUE
|
|
4048
|
-
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE
|
|
4319
|
+
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4049
4320
|
{
|
|
4050
4321
|
t_pg_connection *this = pg_get_connection( self );
|
|
4051
4322
|
|
|
4052
|
-
if(
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
Check_Type(typemap, T_DATA);
|
|
4323
|
+
if( decoder != Qnil ){
|
|
4324
|
+
t_pg_coder *co;
|
|
4325
|
+
UNUSED(co);
|
|
4326
|
+
/* Check argument type */
|
|
4327
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
|
4058
4328
|
}
|
|
4059
|
-
this->decoder_for_get_copy_data =
|
|
4329
|
+
this->decoder_for_get_copy_data = decoder;
|
|
4060
4330
|
|
|
4061
|
-
return
|
|
4331
|
+
return decoder;
|
|
4062
4332
|
}
|
|
4063
4333
|
|
|
4064
4334
|
/*
|
|
@@ -4138,9 +4408,10 @@ pgconn_field_name_type_get(VALUE self)
|
|
|
4138
4408
|
* Document-class: PG::Connection
|
|
4139
4409
|
*/
|
|
4140
4410
|
void
|
|
4141
|
-
init_pg_connection()
|
|
4411
|
+
init_pg_connection(void)
|
|
4142
4412
|
{
|
|
4143
4413
|
s_id_encode = rb_intern("encode");
|
|
4414
|
+
s_id_autoclose_set = rb_intern("autoclose=");
|
|
4144
4415
|
sym_type = ID2SYM(rb_intern("type"));
|
|
4145
4416
|
sym_format = ID2SYM(rb_intern("format"));
|
|
4146
4417
|
sym_value = ID2SYM(rb_intern("value"));
|
|
@@ -4156,10 +4427,6 @@ init_pg_connection()
|
|
|
4156
4427
|
/****** PG::Connection CLASS METHODS ******/
|
|
4157
4428
|
rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
|
|
4158
4429
|
|
|
4159
|
-
SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
|
|
4160
|
-
SINGLETON_ALIAS(rb_cPGconn, "open", "new");
|
|
4161
|
-
SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
|
|
4162
|
-
SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
|
|
4163
4430
|
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
|
4164
4431
|
SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
|
|
4165
4432
|
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
|
@@ -4168,14 +4435,15 @@ init_pg_connection()
|
|
|
4168
4435
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
|
4169
4436
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
|
4170
4437
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
|
4171
|
-
rb_define_singleton_method(rb_cPGconn, "
|
|
4438
|
+
rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
|
|
4439
|
+
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
|
4440
|
+
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
|
4172
4441
|
|
|
4173
4442
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
|
4174
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
|
4175
4443
|
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
|
4176
4444
|
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
|
4177
4445
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
|
4178
|
-
rb_define_method(rb_cPGconn, "
|
|
4446
|
+
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
|
4179
4447
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
|
4180
4448
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
|
4181
4449
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
|
@@ -4185,11 +4453,12 @@ init_pg_connection()
|
|
|
4185
4453
|
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
|
4186
4454
|
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
|
4187
4455
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
|
4456
|
+
#if defined(HAVE_PQRESULTMEMORYSIZE)
|
|
4457
|
+
rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
|
|
4458
|
+
#endif
|
|
4188
4459
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
|
4189
4460
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
|
4190
|
-
#ifdef HAVE_PQCONNINFO
|
|
4191
4461
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|
|
4192
|
-
#endif
|
|
4193
4462
|
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
|
4194
4463
|
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
|
4195
4464
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
|
@@ -4200,17 +4469,18 @@ init_pg_connection()
|
|
|
4200
4469
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
|
4201
4470
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
|
4202
4471
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
|
4472
|
+
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
|
4203
4473
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
|
4204
4474
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
|
4205
4475
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
|
4206
4476
|
|
|
4207
4477
|
/****** PG::Connection INSTANCE METHODS: Command Execution ******/
|
|
4208
|
-
rb_define_method(rb_cPGconn, "sync_exec",
|
|
4209
|
-
rb_define_method(rb_cPGconn, "sync_exec_params",
|
|
4210
|
-
rb_define_method(rb_cPGconn, "sync_prepare",
|
|
4211
|
-
rb_define_method(rb_cPGconn, "sync_exec_prepared",
|
|
4212
|
-
rb_define_method(rb_cPGconn, "sync_describe_prepared",
|
|
4213
|
-
rb_define_method(rb_cPGconn, "sync_describe_portal",
|
|
4478
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
|
|
4479
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
|
|
4480
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
|
|
4481
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
|
4482
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
|
4483
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
|
4214
4484
|
|
|
4215
4485
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
|
4216
4486
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
|
@@ -4243,25 +4513,26 @@ init_pg_connection()
|
|
|
4243
4513
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
|
4244
4514
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
|
4245
4515
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
|
4246
|
-
rb_define_method(rb_cPGconn, "
|
|
4516
|
+
rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
|
|
4247
4517
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
|
4248
4518
|
rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
|
|
4249
|
-
rb_define_method(rb_cPGconn, "
|
|
4250
|
-
rb_define_method(rb_cPGconn, "
|
|
4251
|
-
|
|
4252
|
-
rb_define_method(rb_cPGconn, "flush",
|
|
4519
|
+
rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
|
|
4520
|
+
rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
|
|
4521
|
+
rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
|
|
4522
|
+
rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
|
|
4523
|
+
rb_define_alias(rb_cPGconn, "async_flush", "flush");
|
|
4253
4524
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
|
4254
4525
|
|
|
4255
4526
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
|
4256
|
-
rb_define_method(rb_cPGconn, "
|
|
4527
|
+
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
|
4257
4528
|
|
|
4258
4529
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
|
4259
4530
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
|
4260
4531
|
|
|
4261
4532
|
/****** PG::Connection INSTANCE METHODS: COPY ******/
|
|
4262
|
-
rb_define_method(rb_cPGconn, "
|
|
4263
|
-
rb_define_method(rb_cPGconn, "
|
|
4264
|
-
rb_define_method(rb_cPGconn, "
|
|
4533
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
|
|
4534
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
|
|
4535
|
+
rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
|
|
4265
4536
|
|
|
4266
4537
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
|
4267
4538
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
|
@@ -4277,16 +4548,20 @@ init_pg_connection()
|
|
|
4277
4548
|
|
|
4278
4549
|
/****** PG::Connection INSTANCE METHODS: Other ******/
|
|
4279
4550
|
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
|
4280
|
-
rb_define_method(rb_cPGconn, "
|
|
4551
|
+
rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
|
|
4552
|
+
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
|
|
4553
|
+
rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
|
|
4281
4554
|
rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
|
|
4282
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
|
4283
4555
|
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
|
4556
|
+
rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
|
|
4284
4557
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
|
4285
4558
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
|
4286
4559
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
|
4287
|
-
rb_define_method(rb_cPGconn, "
|
|
4560
|
+
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
|
4561
|
+
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
|
4562
|
+
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
|
4288
4563
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
4289
|
-
rb_define_method(rb_cPGconn, "
|
|
4564
|
+
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
|
4290
4565
|
#endif
|
|
4291
4566
|
|
|
4292
4567
|
#ifdef HAVE_PQSSLATTRIBUTE
|
|
@@ -4295,6 +4570,14 @@ init_pg_connection()
|
|
|
4295
4570
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
|
4296
4571
|
#endif
|
|
4297
4572
|
|
|
4573
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
|
4574
|
+
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
|
4575
|
+
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
|
4576
|
+
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
|
4577
|
+
rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
|
|
4578
|
+
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
|
4579
|
+
#endif
|
|
4580
|
+
|
|
4298
4581
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
|
4299
4582
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
|
4300
4583
|
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|