pg 1.2.3 → 1.3.4
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 +36 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +86 -0
- data/.github/workflows/source-gem.yml +129 -0
- data/.gitignore +13 -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.rdoc +134 -7
- data/Manifest.txt +0 -1
- data/README.rdoc +7 -6
- data/Rakefile +27 -138
- data/Rakefile.cross +8 -5
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/ext/errorcodes.def +8 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +3 -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 +59 -4
- data/ext/pg.h +19 -1
- data/ext/pg_coder.c +82 -28
- data/ext/pg_connection.c +667 -498
- data/ext/pg_copy_coder.c +45 -16
- data/ext/pg_record_coder.c +39 -11
- data/ext/pg_result.c +76 -40
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +6 -6
- data/ext/pg_tuple.c +49 -29
- data/ext/pg_type_map.c +41 -8
- data/ext/pg_type_map_all_strings.c +15 -1
- data/ext/pg_type_map_by_class.c +49 -24
- data/ext/pg_type_map_by_column.c +66 -28
- data/ext/pg_type_map_by_mri_type.c +47 -18
- data/ext/pg_type_map_by_oid.c +52 -23
- data/ext/pg_type_map_in_ruby.c +50 -19
- 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 +296 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +589 -58
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +47 -32
- 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 +32 -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.tar.gz.sig +0 -0
- metadata +87 -224
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- 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,7 +21,9 @@ 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;
|
|
24
27
|
|
|
25
28
|
/*
|
|
26
29
|
* Global functions
|
|
@@ -33,7 +36,7 @@ t_pg_connection *
|
|
|
33
36
|
pg_get_connection( VALUE self )
|
|
34
37
|
{
|
|
35
38
|
t_pg_connection *this;
|
|
36
|
-
|
|
39
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
37
40
|
|
|
38
41
|
return this;
|
|
39
42
|
}
|
|
@@ -46,7 +49,7 @@ static t_pg_connection *
|
|
|
46
49
|
pg_get_connection_safe( VALUE self )
|
|
47
50
|
{
|
|
48
51
|
t_pg_connection *this;
|
|
49
|
-
|
|
52
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
50
53
|
|
|
51
54
|
if ( !this->pgconn )
|
|
52
55
|
rb_raise( rb_eConnectionBad, "connection is closed" );
|
|
@@ -65,7 +68,7 @@ PGconn *
|
|
|
65
68
|
pg_get_pgconn( VALUE self )
|
|
66
69
|
{
|
|
67
70
|
t_pg_connection *this;
|
|
68
|
-
|
|
71
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
69
72
|
|
|
70
73
|
if ( !this->pgconn )
|
|
71
74
|
rb_raise( rb_eConnectionBad, "connection is closed" );
|
|
@@ -145,16 +148,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
|
|
|
145
148
|
* GC Mark function
|
|
146
149
|
*/
|
|
147
150
|
static void
|
|
148
|
-
pgconn_gc_mark(
|
|
151
|
+
pgconn_gc_mark( void *_this )
|
|
149
152
|
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
|
154
|
+
rb_gc_mark_movable( this->socket_io );
|
|
155
|
+
rb_gc_mark_movable( this->notice_receiver );
|
|
156
|
+
rb_gc_mark_movable( this->notice_processor );
|
|
157
|
+
rb_gc_mark_movable( this->type_map_for_queries );
|
|
158
|
+
rb_gc_mark_movable( this->type_map_for_results );
|
|
159
|
+
rb_gc_mark_movable( this->trace_stream );
|
|
160
|
+
rb_gc_mark_movable( this->encoder_for_put_copy_data );
|
|
161
|
+
rb_gc_mark_movable( this->decoder_for_get_copy_data );
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static void
|
|
165
|
+
pgconn_gc_compact( void *_this )
|
|
166
|
+
{
|
|
167
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
|
168
|
+
pg_gc_location( this->socket_io );
|
|
169
|
+
pg_gc_location( this->notice_receiver );
|
|
170
|
+
pg_gc_location( this->notice_processor );
|
|
171
|
+
pg_gc_location( this->type_map_for_queries );
|
|
172
|
+
pg_gc_location( this->type_map_for_results );
|
|
173
|
+
pg_gc_location( this->trace_stream );
|
|
174
|
+
pg_gc_location( this->encoder_for_put_copy_data );
|
|
175
|
+
pg_gc_location( this->decoder_for_get_copy_data );
|
|
158
176
|
}
|
|
159
177
|
|
|
160
178
|
|
|
@@ -162,11 +180,15 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
|
162
180
|
* GC Free function
|
|
163
181
|
*/
|
|
164
182
|
static void
|
|
165
|
-
pgconn_gc_free(
|
|
183
|
+
pgconn_gc_free( void *_this )
|
|
166
184
|
{
|
|
185
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
|
167
186
|
#if defined(_WIN32)
|
|
168
|
-
if ( RTEST(this->socket_io) )
|
|
169
|
-
rb_w32_unwrap_io_handle(
|
|
187
|
+
if ( RTEST(this->socket_io) ) {
|
|
188
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
|
189
|
+
rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
170
192
|
#endif
|
|
171
193
|
if (this->pgconn != NULL)
|
|
172
194
|
PQfinish( this->pgconn );
|
|
@@ -174,6 +196,29 @@ pgconn_gc_free( t_pg_connection *this )
|
|
|
174
196
|
xfree(this);
|
|
175
197
|
}
|
|
176
198
|
|
|
199
|
+
/*
|
|
200
|
+
* Object Size function
|
|
201
|
+
*/
|
|
202
|
+
static size_t
|
|
203
|
+
pgconn_memsize( const void *_this )
|
|
204
|
+
{
|
|
205
|
+
const t_pg_connection *this = (const t_pg_connection *)_this;
|
|
206
|
+
return sizeof(*this);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static const rb_data_type_t pg_connection_type = {
|
|
210
|
+
"PG::Connection",
|
|
211
|
+
{
|
|
212
|
+
pgconn_gc_mark,
|
|
213
|
+
pgconn_gc_free,
|
|
214
|
+
pgconn_memsize,
|
|
215
|
+
pg_compact_callback(pgconn_gc_compact),
|
|
216
|
+
},
|
|
217
|
+
0,
|
|
218
|
+
0,
|
|
219
|
+
0,
|
|
220
|
+
};
|
|
221
|
+
|
|
177
222
|
|
|
178
223
|
/**************************************************************************
|
|
179
224
|
* Class Methods
|
|
@@ -189,7 +234,7 @@ static VALUE
|
|
|
189
234
|
pgconn_s_allocate( VALUE klass )
|
|
190
235
|
{
|
|
191
236
|
t_pg_connection *this;
|
|
192
|
-
VALUE self =
|
|
237
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
|
|
193
238
|
|
|
194
239
|
this->pgconn = NULL;
|
|
195
240
|
this->socket_io = Qnil;
|
|
@@ -204,65 +249,13 @@ pgconn_s_allocate( VALUE klass )
|
|
|
204
249
|
return self;
|
|
205
250
|
}
|
|
206
251
|
|
|
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
252
|
static VALUE
|
|
261
|
-
|
|
253
|
+
pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
262
254
|
{
|
|
263
255
|
t_pg_connection *this;
|
|
264
256
|
VALUE conninfo;
|
|
265
257
|
VALUE error;
|
|
258
|
+
VALUE self = pgconn_s_allocate( klass );
|
|
266
259
|
|
|
267
260
|
this = pg_get_connection( self );
|
|
268
261
|
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
|
@@ -335,34 +328,14 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
335
328
|
return rb_conn;
|
|
336
329
|
}
|
|
337
330
|
|
|
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
331
|
static VALUE
|
|
359
|
-
|
|
332
|
+
pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
|
|
360
333
|
{
|
|
361
334
|
PGPing ping;
|
|
362
335
|
VALUE conninfo;
|
|
363
336
|
|
|
364
337
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
|
365
|
-
ping =
|
|
338
|
+
ping = gvl_PQping( StringValueCStr(conninfo) );
|
|
366
339
|
|
|
367
340
|
return INT2FIX((int)ping);
|
|
368
341
|
}
|
|
@@ -405,30 +378,8 @@ pgconn_s_conndefaults(VALUE self)
|
|
|
405
378
|
|
|
406
379
|
|
|
407
380
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
408
|
-
/*
|
|
409
|
-
* call-seq:
|
|
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.
|
|
415
|
-
*
|
|
416
|
-
* The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
|
|
417
|
-
* +algorithm+ specifies the encryption algorithm to use to encrypt the password.
|
|
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.
|
|
426
|
-
*
|
|
427
|
-
* Available since PostgreSQL-10.
|
|
428
|
-
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN].
|
|
429
|
-
*/
|
|
430
381
|
static VALUE
|
|
431
|
-
|
|
382
|
+
pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
432
383
|
{
|
|
433
384
|
char *encrypted = NULL;
|
|
434
385
|
VALUE rval = Qnil;
|
|
@@ -523,6 +474,9 @@ pgconn_connect_poll(VALUE self)
|
|
|
523
474
|
{
|
|
524
475
|
PostgresPollingStatusType status;
|
|
525
476
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
|
477
|
+
|
|
478
|
+
pgconn_close_socket_io(self);
|
|
479
|
+
|
|
526
480
|
return INT2FIX((int)status);
|
|
527
481
|
}
|
|
528
482
|
|
|
@@ -559,15 +513,8 @@ pgconn_finished_p( VALUE self )
|
|
|
559
513
|
}
|
|
560
514
|
|
|
561
515
|
|
|
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
516
|
static VALUE
|
|
570
|
-
|
|
517
|
+
pgconn_sync_reset( VALUE self )
|
|
571
518
|
{
|
|
572
519
|
pgconn_close_socket_io( self );
|
|
573
520
|
gvl_PQreset( pg_get_pgconn(self) );
|
|
@@ -606,6 +553,9 @@ pgconn_reset_poll(VALUE self)
|
|
|
606
553
|
{
|
|
607
554
|
PostgresPollingStatusType status;
|
|
608
555
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
|
556
|
+
|
|
557
|
+
pgconn_close_socket_io(self);
|
|
558
|
+
|
|
609
559
|
return INT2FIX((int)status);
|
|
610
560
|
}
|
|
611
561
|
|
|
@@ -676,21 +626,19 @@ static VALUE
|
|
|
676
626
|
pgconn_port(VALUE self)
|
|
677
627
|
{
|
|
678
628
|
char* port = PQport(pg_get_pgconn(self));
|
|
679
|
-
return INT2NUM(
|
|
629
|
+
return INT2NUM(atoi(port));
|
|
680
630
|
}
|
|
681
631
|
|
|
682
632
|
/*
|
|
683
633
|
* call-seq:
|
|
684
634
|
* conn.tty()
|
|
685
635
|
*
|
|
686
|
-
*
|
|
636
|
+
* Obsolete function.
|
|
687
637
|
*/
|
|
688
638
|
static VALUE
|
|
689
639
|
pgconn_tty(VALUE self)
|
|
690
640
|
{
|
|
691
|
-
|
|
692
|
-
if (!tty) return Qnil;
|
|
693
|
-
return rb_str_new2(tty);
|
|
641
|
+
return rb_str_new2("");
|
|
694
642
|
}
|
|
695
643
|
|
|
696
644
|
/*
|
|
@@ -708,7 +656,6 @@ pgconn_options(VALUE self)
|
|
|
708
656
|
}
|
|
709
657
|
|
|
710
658
|
|
|
711
|
-
#ifdef HAVE_PQCONNINFO
|
|
712
659
|
/*
|
|
713
660
|
* call-seq:
|
|
714
661
|
* conn.conninfo -> hash
|
|
@@ -728,14 +675,17 @@ pgconn_conninfo( VALUE self )
|
|
|
728
675
|
|
|
729
676
|
return array;
|
|
730
677
|
}
|
|
731
|
-
#endif
|
|
732
678
|
|
|
733
679
|
|
|
734
680
|
/*
|
|
735
681
|
* call-seq:
|
|
736
682
|
* conn.status()
|
|
737
683
|
*
|
|
738
|
-
* Returns status of connection
|
|
684
|
+
* Returns the status of the connection, which is one:
|
|
685
|
+
* PG::Constants::CONNECTION_OK
|
|
686
|
+
* PG::Constants::CONNECTION_BAD
|
|
687
|
+
*
|
|
688
|
+
* ... and other constants of kind PG::Constants::CONNECTION_*
|
|
739
689
|
*/
|
|
740
690
|
static VALUE
|
|
741
691
|
pgconn_status(VALUE self)
|
|
@@ -823,7 +773,10 @@ pgconn_server_version(VALUE self)
|
|
|
823
773
|
* call-seq:
|
|
824
774
|
* conn.error_message -> String
|
|
825
775
|
*
|
|
826
|
-
* Returns the error message
|
|
776
|
+
* Returns the error message most recently generated by an operation on the connection.
|
|
777
|
+
*
|
|
778
|
+
* Nearly all libpq functions will set a message for conn.error_message if they fail.
|
|
779
|
+
* Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
|
|
827
780
|
*/
|
|
828
781
|
static VALUE
|
|
829
782
|
pgconn_error_message(VALUE self)
|
|
@@ -878,8 +831,8 @@ pgconn_socket_io(VALUE self)
|
|
|
878
831
|
{
|
|
879
832
|
int sd;
|
|
880
833
|
int ruby_sd;
|
|
881
|
-
ID id_autoclose = rb_intern("autoclose=");
|
|
882
834
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
835
|
+
VALUE cSocket;
|
|
883
836
|
VALUE socket_io = this->socket_io;
|
|
884
837
|
|
|
885
838
|
if ( !RTEST(socket_io) ) {
|
|
@@ -888,15 +841,19 @@ pgconn_socket_io(VALUE self)
|
|
|
888
841
|
|
|
889
842
|
#ifdef _WIN32
|
|
890
843
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
|
844
|
+
if( ruby_sd == -1 ){
|
|
845
|
+
rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
|
|
846
|
+
}
|
|
891
847
|
this->ruby_sd = ruby_sd;
|
|
892
848
|
#else
|
|
893
849
|
ruby_sd = sd;
|
|
894
850
|
#endif
|
|
895
851
|
|
|
896
|
-
|
|
852
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
|
853
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
|
897
854
|
|
|
898
855
|
/* Disable autoclose feature */
|
|
899
|
-
rb_funcall( socket_io,
|
|
856
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
|
900
857
|
|
|
901
858
|
this->socket_io = socket_io;
|
|
902
859
|
}
|
|
@@ -918,6 +875,51 @@ pgconn_backend_pid(VALUE self)
|
|
|
918
875
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
|
919
876
|
}
|
|
920
877
|
|
|
878
|
+
typedef struct
|
|
879
|
+
{
|
|
880
|
+
struct sockaddr_storage addr;
|
|
881
|
+
socklen_t salen;
|
|
882
|
+
} SockAddr;
|
|
883
|
+
|
|
884
|
+
/* Copy of struct pg_cancel from libpq-int.h
|
|
885
|
+
*
|
|
886
|
+
* See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
|
|
887
|
+
*/
|
|
888
|
+
struct pg_cancel
|
|
889
|
+
{
|
|
890
|
+
SockAddr raddr; /* Remote address */
|
|
891
|
+
int be_pid; /* PID of backend --- needed for cancels */
|
|
892
|
+
int be_key; /* key of backend --- needed for cancels */
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
/*
|
|
896
|
+
* call-seq:
|
|
897
|
+
* conn.backend_key() -> Integer
|
|
898
|
+
*
|
|
899
|
+
* Returns the key of the backend server process for this connection.
|
|
900
|
+
* This key can be used to cancel queries on the server.
|
|
901
|
+
*/
|
|
902
|
+
static VALUE
|
|
903
|
+
pgconn_backend_key(VALUE self)
|
|
904
|
+
{
|
|
905
|
+
int be_key;
|
|
906
|
+
struct pg_cancel *cancel;
|
|
907
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
908
|
+
|
|
909
|
+
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
|
910
|
+
if(cancel == NULL)
|
|
911
|
+
rb_raise(rb_ePGerror,"Invalid connection!");
|
|
912
|
+
|
|
913
|
+
if( cancel->be_pid != PQbackendPID(conn) )
|
|
914
|
+
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
|
915
|
+
|
|
916
|
+
be_key = cancel->be_key;
|
|
917
|
+
|
|
918
|
+
PQfreeCancel(cancel);
|
|
919
|
+
|
|
920
|
+
return INT2NUM(be_key);
|
|
921
|
+
}
|
|
922
|
+
|
|
921
923
|
/*
|
|
922
924
|
* call-seq:
|
|
923
925
|
* conn.connection_needs_password() -> Boolean
|
|
@@ -948,7 +950,7 @@ pgconn_connection_used_password(VALUE self)
|
|
|
948
950
|
/* :TODO: get_ssl */
|
|
949
951
|
|
|
950
952
|
|
|
951
|
-
static VALUE
|
|
953
|
+
static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
|
952
954
|
|
|
953
955
|
/*
|
|
954
956
|
* call-seq:
|
|
@@ -962,11 +964,11 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
|
962
964
|
* However #async_exec has two advantages:
|
|
963
965
|
*
|
|
964
966
|
* 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
|
-
*
|
|
967
|
+
* 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
|
|
968
|
+
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
|
967
969
|
*/
|
|
968
970
|
static VALUE
|
|
969
|
-
|
|
971
|
+
pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
|
970
972
|
{
|
|
971
973
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
972
974
|
PGresult *result = NULL;
|
|
@@ -987,7 +989,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
|
987
989
|
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
|
988
990
|
|
|
989
991
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
|
990
|
-
return
|
|
992
|
+
return pgconn_sync_exec_params( argc, argv, self );
|
|
991
993
|
|
|
992
994
|
}
|
|
993
995
|
|
|
@@ -1019,7 +1021,7 @@ struct query_params_data {
|
|
|
1019
1021
|
* Filled by alloc_query_params()
|
|
1020
1022
|
*/
|
|
1021
1023
|
|
|
1022
|
-
/* Wraps the pointer of allocated memory, if function parameters
|
|
1024
|
+
/* Wraps the pointer of allocated memory, if function parameters don't
|
|
1023
1025
|
* fit in the memory_pool below.
|
|
1024
1026
|
*/
|
|
1025
1027
|
VALUE heap_pool;
|
|
@@ -1037,7 +1039,7 @@ struct query_params_data {
|
|
|
1037
1039
|
Oid *types;
|
|
1038
1040
|
|
|
1039
1041
|
/* This array takes the string values for the timeframe of the query,
|
|
1040
|
-
* if param value
|
|
1042
|
+
* if param value conversion is required
|
|
1041
1043
|
*/
|
|
1042
1044
|
VALUE gc_array;
|
|
1043
1045
|
|
|
@@ -1051,8 +1053,9 @@ struct query_params_data {
|
|
|
1051
1053
|
};
|
|
1052
1054
|
|
|
1053
1055
|
static void
|
|
1054
|
-
free_typecast_heap_chain(
|
|
1056
|
+
free_typecast_heap_chain(void *_chain_entry)
|
|
1055
1057
|
{
|
|
1058
|
+
struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
|
|
1056
1059
|
while(chain_entry){
|
|
1057
1060
|
struct linked_typecast_data *next = chain_entry->next;
|
|
1058
1061
|
xfree(chain_entry);
|
|
@@ -1060,6 +1063,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
|
|
|
1060
1063
|
}
|
|
1061
1064
|
}
|
|
1062
1065
|
|
|
1066
|
+
static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1067
|
+
"PG::Connection typecast buffer chain",
|
|
1068
|
+
{
|
|
1069
|
+
(RUBY_DATA_FUNC) NULL,
|
|
1070
|
+
free_typecast_heap_chain,
|
|
1071
|
+
(size_t (*)(const void *))NULL,
|
|
1072
|
+
},
|
|
1073
|
+
0,
|
|
1074
|
+
0,
|
|
1075
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1063
1078
|
static char *
|
|
1064
1079
|
alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
1065
1080
|
{
|
|
@@ -1070,17 +1085,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
|
1070
1085
|
/* Did we already wrap a memory chain per T_DATA object? */
|
|
1071
1086
|
if( NIL_P( *typecast_heap_chain ) ){
|
|
1072
1087
|
/* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
|
|
1073
|
-
*typecast_heap_chain =
|
|
1088
|
+
*typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
|
|
1074
1089
|
allocated->next = NULL;
|
|
1075
1090
|
} else {
|
|
1076
1091
|
/* Append to the chain */
|
|
1077
|
-
allocated->next =
|
|
1078
|
-
|
|
1092
|
+
allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
|
|
1093
|
+
RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
|
|
1079
1094
|
}
|
|
1080
1095
|
|
|
1081
1096
|
return &allocated->data[0];
|
|
1082
1097
|
}
|
|
1083
1098
|
|
|
1099
|
+
static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1100
|
+
"PG::Connection query heap pool",
|
|
1101
|
+
{
|
|
1102
|
+
(RUBY_DATA_FUNC) NULL,
|
|
1103
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
1104
|
+
(size_t (*)(const void *))NULL,
|
|
1105
|
+
},
|
|
1106
|
+
0,
|
|
1107
|
+
0,
|
|
1108
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
1109
|
+
};
|
|
1084
1110
|
|
|
1085
1111
|
static int
|
|
1086
1112
|
alloc_query_params(struct query_params_data *paramsData)
|
|
@@ -1095,7 +1121,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1095
1121
|
|
|
1096
1122
|
Check_Type(paramsData->params, T_ARRAY);
|
|
1097
1123
|
|
|
1098
|
-
p_typemap =
|
|
1124
|
+
p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
|
|
1099
1125
|
p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
|
|
1100
1126
|
|
|
1101
1127
|
paramsData->heap_pool = Qnil;
|
|
@@ -1114,7 +1140,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1114
1140
|
/* Allocate one combined memory pool for all possible function parameters */
|
|
1115
1141
|
memory_pool = (char*)xmalloc( required_pool_size );
|
|
1116
1142
|
/* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
|
|
1117
|
-
paramsData->heap_pool =
|
|
1143
|
+
paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
|
|
1118
1144
|
required_pool_size = 0;
|
|
1119
1145
|
}else{
|
|
1120
1146
|
/* Use stack memory for function parameters */
|
|
@@ -1227,12 +1253,11 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
|
1227
1253
|
/* Use default typemap for queries. It's type is checked when assigned. */
|
|
1228
1254
|
paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
|
|
1229
1255
|
}else{
|
|
1256
|
+
t_typemap *tm;
|
|
1257
|
+
UNUSED(tm);
|
|
1258
|
+
|
|
1230
1259
|
/* 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 );
|
|
1260
|
+
TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
|
|
1236
1261
|
}
|
|
1237
1262
|
}
|
|
1238
1263
|
|
|
@@ -1246,7 +1271,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
|
1246
1271
|
* 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
1272
|
*/
|
|
1248
1273
|
static VALUE
|
|
1249
|
-
|
|
1274
|
+
pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1250
1275
|
{
|
|
1251
1276
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1252
1277
|
PGresult *result = NULL;
|
|
@@ -1266,7 +1291,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1266
1291
|
*/
|
|
1267
1292
|
if ( NIL_P(paramsData.params) ) {
|
|
1268
1293
|
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
|
1269
|
-
return
|
|
1294
|
+
return pgconn_sync_exec( 1, argv, self );
|
|
1270
1295
|
}
|
|
1271
1296
|
pgconn_query_assign_typemap( self, ¶msData );
|
|
1272
1297
|
|
|
@@ -1297,7 +1322,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1297
1322
|
* It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
|
|
1298
1323
|
*/
|
|
1299
1324
|
static VALUE
|
|
1300
|
-
|
|
1325
|
+
pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
1301
1326
|
{
|
|
1302
1327
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1303
1328
|
PGresult *result = NULL;
|
|
@@ -1346,7 +1371,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1346
1371
|
* 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
1372
|
*/
|
|
1348
1373
|
static VALUE
|
|
1349
|
-
|
|
1374
|
+
pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1350
1375
|
{
|
|
1351
1376
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1352
1377
|
PGresult *result = NULL;
|
|
@@ -1391,7 +1416,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1391
1416
|
* 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
1417
|
*/
|
|
1393
1418
|
static VALUE
|
|
1394
|
-
|
|
1419
|
+
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1395
1420
|
{
|
|
1396
1421
|
PGresult *result;
|
|
1397
1422
|
VALUE rb_pgresult;
|
|
@@ -1419,7 +1444,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
1419
1444
|
* 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
1445
|
*/
|
|
1421
1446
|
static VALUE
|
|
1422
|
-
|
|
1447
|
+
pgconn_sync_describe_portal(self, stmt_name)
|
|
1423
1448
|
VALUE self, stmt_name;
|
|
1424
1449
|
{
|
|
1425
1450
|
PGresult *result;
|
|
@@ -1454,6 +1479,9 @@ pgconn_describe_portal(self, stmt_name)
|
|
|
1454
1479
|
* * +PGRES_NONFATAL_ERROR+
|
|
1455
1480
|
* * +PGRES_FATAL_ERROR+
|
|
1456
1481
|
* * +PGRES_COPY_BOTH+
|
|
1482
|
+
* * +PGRES_SINGLE_TUPLE+
|
|
1483
|
+
* * +PGRES_PIPELINE_SYNC+
|
|
1484
|
+
* * +PGRES_PIPELINE_ABORTED+
|
|
1457
1485
|
*/
|
|
1458
1486
|
static VALUE
|
|
1459
1487
|
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
@@ -1750,6 +1778,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
|
1750
1778
|
rb_iv_set(error, "@connection", self);
|
|
1751
1779
|
rb_exc_raise(error);
|
|
1752
1780
|
}
|
|
1781
|
+
pgconn_wait_for_flush( self );
|
|
1753
1782
|
return Qnil;
|
|
1754
1783
|
}
|
|
1755
1784
|
|
|
@@ -1779,7 +1808,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
|
1779
1808
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
1780
1809
|
* { :value => <string value>, :type => 0, :format => 0 }
|
|
1781
1810
|
*
|
|
1782
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
1811
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
1783
1812
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
1784
1813
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
1785
1814
|
*
|
|
@@ -1827,6 +1856,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1827
1856
|
rb_iv_set(error, "@connection", self);
|
|
1828
1857
|
rb_exc_raise(error);
|
|
1829
1858
|
}
|
|
1859
|
+
pgconn_wait_for_flush( self );
|
|
1830
1860
|
return Qnil;
|
|
1831
1861
|
}
|
|
1832
1862
|
|
|
@@ -1847,7 +1877,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1847
1877
|
*
|
|
1848
1878
|
* For example: "SELECT $1::int"
|
|
1849
1879
|
*
|
|
1850
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
1880
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
1851
1881
|
* inside the SQL query.
|
|
1852
1882
|
*/
|
|
1853
1883
|
static VALUE
|
|
@@ -1890,6 +1920,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1890
1920
|
rb_iv_set(error, "@connection", self);
|
|
1891
1921
|
rb_exc_raise(error);
|
|
1892
1922
|
}
|
|
1923
|
+
pgconn_wait_for_flush( self );
|
|
1893
1924
|
return Qnil;
|
|
1894
1925
|
}
|
|
1895
1926
|
|
|
@@ -1911,7 +1942,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1911
1942
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
1912
1943
|
* { :value => <string value>, :format => 0 }
|
|
1913
1944
|
*
|
|
1914
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
1945
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
1915
1946
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
1916
1947
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
1917
1948
|
*
|
|
@@ -1941,7 +1972,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1941
1972
|
|
|
1942
1973
|
if(NIL_P(paramsData.params)) {
|
|
1943
1974
|
paramsData.params = rb_ary_new2(0);
|
|
1944
|
-
resultFormat = 0;
|
|
1945
1975
|
}
|
|
1946
1976
|
pgconn_query_assign_typemap( self, ¶msData );
|
|
1947
1977
|
|
|
@@ -1959,6 +1989,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1959
1989
|
rb_iv_set(error, "@connection", self);
|
|
1960
1990
|
rb_exc_raise(error);
|
|
1961
1991
|
}
|
|
1992
|
+
pgconn_wait_for_flush( self );
|
|
1962
1993
|
return Qnil;
|
|
1963
1994
|
}
|
|
1964
1995
|
|
|
@@ -1980,6 +2011,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
1980
2011
|
rb_iv_set(error, "@connection", self);
|
|
1981
2012
|
rb_exc_raise(error);
|
|
1982
2013
|
}
|
|
2014
|
+
pgconn_wait_for_flush( self );
|
|
1983
2015
|
return Qnil;
|
|
1984
2016
|
}
|
|
1985
2017
|
|
|
@@ -2002,28 +2034,13 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
|
2002
2034
|
rb_iv_set(error, "@connection", self);
|
|
2003
2035
|
rb_exc_raise(error);
|
|
2004
2036
|
}
|
|
2037
|
+
pgconn_wait_for_flush( self );
|
|
2005
2038
|
return Qnil;
|
|
2006
2039
|
}
|
|
2007
2040
|
|
|
2008
2041
|
|
|
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
2042
|
static VALUE
|
|
2026
|
-
|
|
2043
|
+
pgconn_sync_get_result(VALUE self)
|
|
2027
2044
|
{
|
|
2028
2045
|
PGconn *conn = pg_get_pgconn(self);
|
|
2029
2046
|
PGresult *result;
|
|
@@ -2056,6 +2073,7 @@ pgconn_consume_input(self)
|
|
|
2056
2073
|
PGconn *conn = pg_get_pgconn(self);
|
|
2057
2074
|
/* returns 0 on error */
|
|
2058
2075
|
if(PQconsumeInput(conn) == 0) {
|
|
2076
|
+
pgconn_close_socket_io(self);
|
|
2059
2077
|
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
|
2060
2078
|
rb_iv_set(error, "@connection", self);
|
|
2061
2079
|
rb_exc_raise(error);
|
|
@@ -2068,7 +2086,7 @@ pgconn_consume_input(self)
|
|
|
2068
2086
|
* conn.is_busy() -> Boolean
|
|
2069
2087
|
*
|
|
2070
2088
|
* Returns +true+ if a command is busy, that is, if
|
|
2071
|
-
*
|
|
2089
|
+
* #get_result would block. Otherwise returns +false+.
|
|
2072
2090
|
*/
|
|
2073
2091
|
static VALUE
|
|
2074
2092
|
pgconn_is_busy(self)
|
|
@@ -2077,24 +2095,8 @@ pgconn_is_busy(self)
|
|
|
2077
2095
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2078
2096
|
}
|
|
2079
2097
|
|
|
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
2098
|
static VALUE
|
|
2097
|
-
|
|
2099
|
+
pgconn_sync_setnonblocking(self, state)
|
|
2098
2100
|
VALUE self, state;
|
|
2099
2101
|
{
|
|
2100
2102
|
int arg;
|
|
@@ -2116,33 +2118,15 @@ pgconn_setnonblocking(self, state)
|
|
|
2116
2118
|
}
|
|
2117
2119
|
|
|
2118
2120
|
|
|
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
2121
|
static VALUE
|
|
2127
|
-
|
|
2122
|
+
pgconn_sync_isnonblocking(self)
|
|
2128
2123
|
VALUE self;
|
|
2129
2124
|
{
|
|
2130
2125
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2131
2126
|
}
|
|
2132
2127
|
|
|
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
2128
|
static VALUE
|
|
2144
|
-
|
|
2145
|
-
VALUE self;
|
|
2129
|
+
pgconn_sync_flush(VALUE self)
|
|
2146
2130
|
{
|
|
2147
2131
|
PGconn *conn = pg_get_pgconn(self);
|
|
2148
2132
|
int ret;
|
|
@@ -2156,18 +2140,8 @@ pgconn_flush(self)
|
|
|
2156
2140
|
return (ret) ? Qfalse : Qtrue;
|
|
2157
2141
|
}
|
|
2158
2142
|
|
|
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
2143
|
static VALUE
|
|
2170
|
-
|
|
2144
|
+
pgconn_sync_cancel(VALUE self)
|
|
2171
2145
|
{
|
|
2172
2146
|
char errbuf[256];
|
|
2173
2147
|
PGcancel *cancel;
|
|
@@ -2178,7 +2152,7 @@ pgconn_cancel(VALUE self)
|
|
|
2178
2152
|
if(cancel == NULL)
|
|
2179
2153
|
rb_raise(rb_ePGerror,"Invalid connection!");
|
|
2180
2154
|
|
|
2181
|
-
ret = gvl_PQcancel(cancel, errbuf,
|
|
2155
|
+
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
|
2182
2156
|
if(ret == 1)
|
|
2183
2157
|
retval = Qnil;
|
|
2184
2158
|
else
|
|
@@ -2229,55 +2203,63 @@ pgconn_notifies(VALUE self)
|
|
|
2229
2203
|
return hash;
|
|
2230
2204
|
}
|
|
2231
2205
|
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
/*
|
|
2235
|
-
*
|
|
2236
|
-
* instead of rb_wait_for_single_fd().
|
|
2206
|
+
#if defined(_WIN32)
|
|
2207
|
+
|
|
2208
|
+
/* We use a specialized implementation of rb_io_wait() on Windows.
|
|
2209
|
+
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
|
2237
2210
|
*/
|
|
2238
2211
|
|
|
2212
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
|
2213
|
+
#include <ruby/fiber/scheduler.h>
|
|
2214
|
+
#endif
|
|
2215
|
+
|
|
2216
|
+
typedef enum {
|
|
2217
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2218
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2219
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2220
|
+
} pg_rb_io_event_t;
|
|
2221
|
+
|
|
2239
2222
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2240
2223
|
|
|
2241
|
-
static
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2224
|
+
static VALUE
|
|
2225
|
+
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2226
|
+
rb_io_t *fptr;
|
|
2227
|
+
struct timeval ptimeout;
|
|
2228
|
+
|
|
2246
2229
|
struct timeval aborttime={0,0}, currtime, waittime;
|
|
2247
2230
|
DWORD timeout_milisec = INFINITE;
|
|
2248
|
-
|
|
2249
|
-
WSAEVENT hEvent;
|
|
2250
|
-
|
|
2251
|
-
if ( sd < 0 )
|
|
2252
|
-
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
|
2231
|
+
HANDLE hEvent = WSACreateEvent();
|
|
2253
2232
|
|
|
2254
|
-
|
|
2233
|
+
long rb_events = NUM2UINT(events);
|
|
2234
|
+
long w32_events = 0;
|
|
2235
|
+
DWORD wait_ret;
|
|
2255
2236
|
|
|
2256
|
-
|
|
2257
|
-
if(
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
}
|
|
2237
|
+
GetOpenFile((io), fptr);
|
|
2238
|
+
if( !NIL_P(timeout) ){
|
|
2239
|
+
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2240
|
+
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
|
2261
2241
|
|
|
2262
|
-
if ( ptimeout ) {
|
|
2263
2242
|
gettimeofday(&currtime, NULL);
|
|
2264
|
-
timeradd(&currtime, ptimeout, &aborttime);
|
|
2243
|
+
timeradd(&currtime, &ptimeout, &aborttime);
|
|
2265
2244
|
}
|
|
2266
2245
|
|
|
2267
|
-
|
|
2268
|
-
|
|
2246
|
+
if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
|
2247
|
+
if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
|
|
2248
|
+
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
|
2249
|
+
|
|
2250
|
+
for(;;) {
|
|
2251
|
+
if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
|
|
2269
2252
|
WSACloseEvent( hEvent );
|
|
2270
2253
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
|
2271
2254
|
}
|
|
2272
2255
|
|
|
2273
|
-
if (
|
|
2256
|
+
if ( !NIL_P(timeout) ) {
|
|
2274
2257
|
gettimeofday(&currtime, NULL);
|
|
2275
2258
|
timersub(&aborttime, &currtime, &waittime);
|
|
2276
2259
|
timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
|
|
2277
2260
|
}
|
|
2278
2261
|
|
|
2279
|
-
|
|
2280
|
-
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2262
|
+
if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2281
2263
|
/* Wait for the socket to become readable before checking again */
|
|
2282
2264
|
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
|
2283
2265
|
} else {
|
|
@@ -2286,9 +2268,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2286
2268
|
|
|
2287
2269
|
if ( wait_ret == WAIT_TIMEOUT ) {
|
|
2288
2270
|
WSACloseEvent( hEvent );
|
|
2289
|
-
return
|
|
2271
|
+
return UINT2NUM(0);
|
|
2290
2272
|
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
|
2273
|
+
WSACloseEvent( hEvent );
|
|
2291
2274
|
/* The event we were waiting for. */
|
|
2275
|
+
return UINT2NUM(rb_events);
|
|
2292
2276
|
} else if ( wait_ret == WAIT_OBJECT_0 + 1) {
|
|
2293
2277
|
/* This indicates interruption from timer thread, GC, exception
|
|
2294
2278
|
* from other threads etc... */
|
|
@@ -2300,36 +2284,66 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2300
2284
|
WSACloseEvent( hEvent );
|
|
2301
2285
|
rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
|
2302
2286
|
}
|
|
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
2287
|
}
|
|
2288
|
+
}
|
|
2310
2289
|
|
|
2311
|
-
|
|
2312
|
-
|
|
2290
|
+
static VALUE
|
|
2291
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2292
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
|
2293
|
+
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
|
2294
|
+
* Fortunatelly ruby-3.1 offers a C-API for it.
|
|
2295
|
+
*/
|
|
2296
|
+
VALUE scheduler = rb_fiber_scheduler_current();
|
|
2297
|
+
|
|
2298
|
+
if (!NIL_P(scheduler)) {
|
|
2299
|
+
return rb_io_wait(io, events, timeout);
|
|
2300
|
+
}
|
|
2301
|
+
#endif
|
|
2302
|
+
return pg_rb_thread_io_wait(io, events, timeout);
|
|
2313
2303
|
}
|
|
2314
2304
|
|
|
2305
|
+
#elif defined(HAVE_RB_IO_WAIT)
|
|
2306
|
+
|
|
2307
|
+
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
|
2308
|
+
#define pg_rb_io_wait rb_io_wait
|
|
2309
|
+
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
|
2310
|
+
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
|
2311
|
+
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
|
2312
|
+
|
|
2315
2313
|
#else
|
|
2314
|
+
/* For compat with ruby < 3.0 */
|
|
2316
2315
|
|
|
2317
|
-
|
|
2316
|
+
typedef enum {
|
|
2317
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2318
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2319
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2320
|
+
} pg_rb_io_event_t;
|
|
2321
|
+
|
|
2322
|
+
static VALUE
|
|
2323
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2324
|
+
rb_io_t *fptr;
|
|
2325
|
+
struct timeval waittime;
|
|
2326
|
+
int res;
|
|
2327
|
+
|
|
2328
|
+
GetOpenFile((io), fptr);
|
|
2329
|
+
if( !NIL_P(timeout) ){
|
|
2330
|
+
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2331
|
+
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
|
2332
|
+
}
|
|
2333
|
+
res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
|
2334
|
+
|
|
2335
|
+
return UINT2NUM(res);
|
|
2336
|
+
}
|
|
2337
|
+
#endif
|
|
2318
2338
|
|
|
2319
2339
|
static void *
|
|
2320
|
-
wait_socket_readable(
|
|
2340
|
+
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
|
2321
2341
|
{
|
|
2322
|
-
|
|
2323
|
-
int ret;
|
|
2342
|
+
VALUE ret;
|
|
2324
2343
|
void *retval;
|
|
2325
2344
|
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) );
|
|
2345
|
+
VALUE wait_timeout = Qnil;
|
|
2346
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
2333
2347
|
|
|
2334
2348
|
if ( ptimeout ) {
|
|
2335
2349
|
gettimeofday(&currtime, NULL);
|
|
@@ -2340,27 +2354,26 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2340
2354
|
if ( ptimeout ) {
|
|
2341
2355
|
gettimeofday(&currtime, NULL);
|
|
2342
2356
|
timersub(&aborttime, &currtime, &waittime);
|
|
2357
|
+
wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
|
|
2343
2358
|
}
|
|
2344
2359
|
|
|
2345
2360
|
/* Is the given timeout valid? */
|
|
2346
2361
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2362
|
+
VALUE socket_io = pgconn_socket_io(self);
|
|
2347
2363
|
/* Wait for the socket to become readable before checking again */
|
|
2348
|
-
ret =
|
|
2364
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
|
2349
2365
|
} else {
|
|
2350
|
-
ret =
|
|
2351
|
-
}
|
|
2352
|
-
|
|
2353
|
-
if ( ret < 0 ){
|
|
2354
|
-
rb_sys_fail( "rb_wait_for_single_fd()" );
|
|
2366
|
+
ret = Qfalse;
|
|
2355
2367
|
}
|
|
2356
2368
|
|
|
2357
2369
|
/* Return false if the select() timed out */
|
|
2358
|
-
if ( ret ==
|
|
2370
|
+
if ( ret == Qfalse ){
|
|
2359
2371
|
return NULL;
|
|
2360
2372
|
}
|
|
2361
2373
|
|
|
2362
2374
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
|
2363
2375
|
if ( PQconsumeInput(conn) == 0 ){
|
|
2376
|
+
pgconn_close_socket_io(self);
|
|
2364
2377
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
|
2365
2378
|
}
|
|
2366
2379
|
}
|
|
@@ -2368,8 +2381,45 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
|
2368
2381
|
return retval;
|
|
2369
2382
|
}
|
|
2370
2383
|
|
|
2384
|
+
/*
|
|
2385
|
+
* call-seq:
|
|
2386
|
+
* conn.flush() -> Boolean
|
|
2387
|
+
*
|
|
2388
|
+
* Attempts to flush any queued output data to the server.
|
|
2389
|
+
* Returns +true+ if data is successfully flushed, +false+
|
|
2390
|
+
* if not (can only return +false+ if connection is
|
|
2391
|
+
* nonblocking.
|
|
2392
|
+
* Raises PG::Error if some other failure occurred.
|
|
2393
|
+
*/
|
|
2394
|
+
static VALUE
|
|
2395
|
+
pgconn_async_flush(VALUE self)
|
|
2396
|
+
{
|
|
2397
|
+
while( pgconn_sync_flush(self) == Qfalse ){
|
|
2398
|
+
/* wait for the socket to become read- or write-ready */
|
|
2399
|
+
int events;
|
|
2400
|
+
VALUE socket_io = pgconn_socket_io(self);
|
|
2401
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
|
2402
|
+
|
|
2403
|
+
if (events & PG_RUBY_IO_READABLE)
|
|
2404
|
+
pgconn_consume_input(self);
|
|
2405
|
+
}
|
|
2406
|
+
return Qtrue;
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
static VALUE
|
|
2410
|
+
pgconn_wait_for_flush( VALUE self ){
|
|
2411
|
+
if( !pg_get_connection_safe(self)->flush_data )
|
|
2412
|
+
return Qnil;
|
|
2371
2413
|
|
|
2372
|
-
|
|
2414
|
+
return pgconn_async_flush(self);
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
static VALUE
|
|
2418
|
+
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
|
2419
|
+
t_pg_connection *conn = pg_get_connection(self);
|
|
2420
|
+
conn->flush_data = RTEST(enabled);
|
|
2421
|
+
return enabled;
|
|
2422
|
+
}
|
|
2373
2423
|
|
|
2374
2424
|
static void *
|
|
2375
2425
|
notify_readable(PGconn *conn)
|
|
@@ -2408,7 +2458,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
|
2408
2458
|
ptimeout = &timeout;
|
|
2409
2459
|
}
|
|
2410
2460
|
|
|
2411
|
-
pnotification = (PGnotify*) wait_socket_readable(
|
|
2461
|
+
pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
|
|
2412
2462
|
|
|
2413
2463
|
/* Return nil if the select timed out */
|
|
2414
2464
|
if ( !pnotification ) return Qnil;
|
|
@@ -2429,28 +2479,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
|
2429
2479
|
}
|
|
2430
2480
|
|
|
2431
2481
|
|
|
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
2482
|
static VALUE
|
|
2453
|
-
|
|
2483
|
+
pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2454
2484
|
{
|
|
2455
2485
|
int ret;
|
|
2456
2486
|
int len;
|
|
@@ -2467,13 +2497,11 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2467
2497
|
if( NIL_P(this->encoder_for_put_copy_data) ){
|
|
2468
2498
|
buffer = value;
|
|
2469
2499
|
} else {
|
|
2470
|
-
p_coder =
|
|
2500
|
+
p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
|
|
2471
2501
|
}
|
|
2472
|
-
} else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
|
|
2473
|
-
Data_Get_Struct( encoder, t_pg_coder, p_coder );
|
|
2474
2502
|
} else {
|
|
2475
|
-
|
|
2476
|
-
|
|
2503
|
+
/* Check argument type and use argument encoder */
|
|
2504
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
|
|
2477
2505
|
}
|
|
2478
2506
|
|
|
2479
2507
|
if( p_coder ){
|
|
@@ -2507,22 +2535,8 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2507
2535
|
return (ret) ? Qtrue : Qfalse;
|
|
2508
2536
|
}
|
|
2509
2537
|
|
|
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
2538
|
static VALUE
|
|
2525
|
-
|
|
2539
|
+
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2526
2540
|
{
|
|
2527
2541
|
VALUE str;
|
|
2528
2542
|
VALUE error;
|
|
@@ -2544,27 +2558,8 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
|
2544
2558
|
return (ret) ? Qtrue : Qfalse;
|
|
2545
2559
|
}
|
|
2546
2560
|
|
|
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
2561
|
static VALUE
|
|
2567
|
-
|
|
2562
|
+
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2568
2563
|
{
|
|
2569
2564
|
VALUE async_in;
|
|
2570
2565
|
VALUE error;
|
|
@@ -2579,13 +2574,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2579
2574
|
|
|
2580
2575
|
if( NIL_P(decoder) ){
|
|
2581
2576
|
if( !NIL_P(this->decoder_for_get_copy_data) ){
|
|
2582
|
-
p_coder =
|
|
2577
|
+
p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
|
|
2583
2578
|
}
|
|
2584
|
-
} else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
|
|
2585
|
-
Data_Get_Struct( decoder, t_pg_coder, p_coder );
|
|
2586
2579
|
} else {
|
|
2587
|
-
|
|
2588
|
-
|
|
2580
|
+
/* Check argument type and use argument decoder */
|
|
2581
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
|
2589
2582
|
}
|
|
2590
2583
|
|
|
2591
2584
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
|
@@ -2830,7 +2823,7 @@ notice_processor_proxy(void *arg, const char *message)
|
|
|
2830
2823
|
* call-seq:
|
|
2831
2824
|
* conn.set_notice_processor {|message| ... } -> Proc
|
|
2832
2825
|
*
|
|
2833
|
-
* See #set_notice_receiver for the
|
|
2826
|
+
* See #set_notice_receiver for the description of what this and the
|
|
2834
2827
|
* notice_processor methods do.
|
|
2835
2828
|
*
|
|
2836
2829
|
* This function takes a new block to act as the notice processor and returns
|
|
@@ -2884,12 +2877,14 @@ pgconn_get_client_encoding(VALUE self)
|
|
|
2884
2877
|
|
|
2885
2878
|
/*
|
|
2886
2879
|
* call-seq:
|
|
2887
|
-
* conn.
|
|
2880
|
+
* conn.sync_set_client_encoding( encoding )
|
|
2888
2881
|
*
|
|
2889
|
-
*
|
|
2882
|
+
* This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
|
|
2883
|
+
* See #async_exec for the differences between the two API variants.
|
|
2884
|
+
* 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
2885
|
*/
|
|
2891
2886
|
static VALUE
|
|
2892
|
-
|
|
2887
|
+
pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2893
2888
|
{
|
|
2894
2889
|
PGconn *conn = pg_get_pgconn( self );
|
|
2895
2890
|
|
|
@@ -2903,49 +2898,6 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
|
2903
2898
|
return Qnil;
|
|
2904
2899
|
}
|
|
2905
2900
|
|
|
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
2901
|
|
|
2950
2902
|
/*
|
|
2951
2903
|
* call-seq:
|
|
@@ -3020,10 +2972,8 @@ get_result_readable(PGconn *conn)
|
|
|
3020
2972
|
* If +true+ is returned, +conn.is_busy+ will return +false+
|
|
3021
2973
|
* and +conn.get_result+ will not block.
|
|
3022
2974
|
*/
|
|
3023
|
-
|
|
2975
|
+
VALUE
|
|
3024
2976
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3025
|
-
PGconn *conn = pg_get_pgconn( self );
|
|
3026
|
-
|
|
3027
2977
|
struct timeval timeout;
|
|
3028
2978
|
struct timeval *ptimeout = NULL;
|
|
3029
2979
|
VALUE timeout_in;
|
|
@@ -3037,7 +2987,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
|
3037
2987
|
ptimeout = &timeout;
|
|
3038
2988
|
}
|
|
3039
2989
|
|
|
3040
|
-
ret = wait_socket_readable(
|
|
2990
|
+
ret = wait_socket_readable( self, ptimeout, get_result_readable);
|
|
3041
2991
|
|
|
3042
2992
|
if( !ret )
|
|
3043
2993
|
return Qfalse;
|
|
@@ -3046,6 +2996,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
|
3046
2996
|
}
|
|
3047
2997
|
|
|
3048
2998
|
|
|
2999
|
+
/*
|
|
3000
|
+
* call-seq:
|
|
3001
|
+
* conn.sync_get_last_result( ) -> PG::Result
|
|
3002
|
+
*
|
|
3003
|
+
* This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
|
|
3004
|
+
* See #async_exec for the differences between the two API variants.
|
|
3005
|
+
* 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.
|
|
3006
|
+
*/
|
|
3007
|
+
static VALUE
|
|
3008
|
+
pgconn_sync_get_last_result(VALUE self)
|
|
3009
|
+
{
|
|
3010
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3011
|
+
VALUE rb_pgresult = Qnil;
|
|
3012
|
+
PGresult *cur, *prev;
|
|
3013
|
+
|
|
3014
|
+
|
|
3015
|
+
cur = prev = NULL;
|
|
3016
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
|
3017
|
+
int status;
|
|
3018
|
+
|
|
3019
|
+
if (prev) PQclear(prev);
|
|
3020
|
+
prev = cur;
|
|
3021
|
+
|
|
3022
|
+
status = PQresultStatus(cur);
|
|
3023
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
|
3024
|
+
break;
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
if (prev) {
|
|
3028
|
+
rb_pgresult = pg_new_result( prev, self );
|
|
3029
|
+
pg_result_check(rb_pgresult);
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
return rb_pgresult;
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3049
3035
|
/*
|
|
3050
3036
|
* call-seq:
|
|
3051
3037
|
* conn.get_last_result( ) -> PG::Result
|
|
@@ -3056,27 +3042,36 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
|
3056
3042
|
* returns the last non-NULL result, or +nil+ if no
|
|
3057
3043
|
* results are available.
|
|
3058
3044
|
*
|
|
3045
|
+
* If the last result contains a bad result_status, an
|
|
3046
|
+
* appropriate exception is raised.
|
|
3047
|
+
*
|
|
3059
3048
|
* This function is similar to #get_result
|
|
3060
3049
|
* except that it is designed to get one and only
|
|
3061
|
-
* one result.
|
|
3050
|
+
* one result and that it checks the result state.
|
|
3062
3051
|
*/
|
|
3063
3052
|
static VALUE
|
|
3064
|
-
|
|
3053
|
+
pgconn_async_get_last_result(VALUE self)
|
|
3065
3054
|
{
|
|
3066
3055
|
PGconn *conn = pg_get_pgconn(self);
|
|
3067
3056
|
VALUE rb_pgresult = Qnil;
|
|
3068
3057
|
PGresult *cur, *prev;
|
|
3069
3058
|
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
|
3059
|
+
cur = prev = NULL;
|
|
3060
|
+
for(;;) {
|
|
3073
3061
|
int status;
|
|
3074
3062
|
|
|
3063
|
+
/* wait for input (without blocking) before reading each result */
|
|
3064
|
+
wait_socket_readable(self, NULL, get_result_readable);
|
|
3065
|
+
|
|
3066
|
+
cur = gvl_PQgetResult(conn);
|
|
3067
|
+
if (cur == NULL)
|
|
3068
|
+
break;
|
|
3069
|
+
|
|
3075
3070
|
if (prev) PQclear(prev);
|
|
3076
3071
|
prev = cur;
|
|
3077
3072
|
|
|
3078
3073
|
status = PQresultStatus(cur);
|
|
3079
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
|
3074
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
|
3080
3075
|
break;
|
|
3081
3076
|
}
|
|
3082
3077
|
|
|
@@ -3100,22 +3095,60 @@ static VALUE
|
|
|
3100
3095
|
pgconn_discard_results(VALUE self)
|
|
3101
3096
|
{
|
|
3102
3097
|
PGconn *conn = pg_get_pgconn(self);
|
|
3098
|
+
VALUE socket_io;
|
|
3103
3099
|
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3100
|
+
if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
|
|
3101
|
+
return Qnil;
|
|
3102
|
+
}
|
|
3103
|
+
|
|
3104
|
+
socket_io = pgconn_socket_io(self);
|
|
3105
|
+
|
|
3106
|
+
for(;;) {
|
|
3107
|
+
PGresult *cur;
|
|
3108
|
+
int status;
|
|
3109
|
+
|
|
3110
|
+
/* pgconn_block() raises an exception in case of errors.
|
|
3111
|
+
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
|
3112
|
+
*/
|
|
3113
|
+
while( gvl_PQisBusy(conn) ){
|
|
3114
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
|
3115
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
|
3116
|
+
pgconn_close_socket_io(self);
|
|
3117
|
+
return Qfalse;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
cur = gvl_PQgetResult(conn);
|
|
3122
|
+
if( cur == NULL) break;
|
|
3123
|
+
|
|
3124
|
+
status = PQresultStatus(cur);
|
|
3107
3125
|
PQclear(cur);
|
|
3108
3126
|
if (status == PGRES_COPY_IN){
|
|
3109
3127
|
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
|
3110
3128
|
}
|
|
3111
3129
|
if (status == PGRES_COPY_OUT){
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3130
|
+
for(;;) {
|
|
3131
|
+
char *buffer = NULL;
|
|
3132
|
+
int st = gvl_PQgetCopyData(conn, &buffer, 1);
|
|
3133
|
+
if( st == 0 ) {
|
|
3134
|
+
/* would block -> wait for readable data */
|
|
3135
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
|
3136
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
|
3137
|
+
pgconn_close_socket_io(self);
|
|
3138
|
+
return Qfalse;
|
|
3139
|
+
}
|
|
3140
|
+
} else if( st > 0 ) {
|
|
3141
|
+
/* some data retrieved -> discard it */
|
|
3142
|
+
PQfreemem(buffer);
|
|
3143
|
+
} else {
|
|
3144
|
+
/* no more data */
|
|
3145
|
+
break;
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3115
3148
|
}
|
|
3116
3149
|
}
|
|
3117
3150
|
|
|
3118
|
-
return
|
|
3151
|
+
return Qtrue;
|
|
3119
3152
|
}
|
|
3120
3153
|
|
|
3121
3154
|
/*
|
|
@@ -3138,6 +3171,7 @@ pgconn_discard_results(VALUE self)
|
|
|
3138
3171
|
* #exec is an alias for #async_exec which is almost identical to #sync_exec .
|
|
3139
3172
|
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
|
3140
3173
|
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
|
3174
|
+
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
|
3141
3175
|
* Both methods ensure that other threads can process while waiting for the server to
|
|
3142
3176
|
* complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
|
|
3143
3177
|
* This is most notably visible by a delayed reaction to Control+C.
|
|
@@ -3152,8 +3186,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
|
3152
3186
|
|
|
3153
3187
|
pgconn_discard_results( self );
|
|
3154
3188
|
pgconn_send_query( argc, argv, self );
|
|
3155
|
-
|
|
3156
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3189
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3157
3190
|
|
|
3158
3191
|
if ( rb_block_given_p() ) {
|
|
3159
3192
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3182,7 +3215,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
|
3182
3215
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
3183
3216
|
* { :value => <string value>, :type => 0, :format => 0 }
|
|
3184
3217
|
*
|
|
3185
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
3218
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3186
3219
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
3187
3220
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
3188
3221
|
*
|
|
@@ -3225,8 +3258,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
|
3225
3258
|
} else {
|
|
3226
3259
|
pgconn_send_query_params( argc, argv, self );
|
|
3227
3260
|
}
|
|
3228
|
-
|
|
3229
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3261
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3230
3262
|
|
|
3231
3263
|
if ( rb_block_given_p() ) {
|
|
3232
3264
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3252,7 +3284,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
|
3252
3284
|
*
|
|
3253
3285
|
* For example: "SELECT $1::int"
|
|
3254
3286
|
*
|
|
3255
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
3287
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3256
3288
|
* inside the SQL query.
|
|
3257
3289
|
*
|
|
3258
3290
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
|
|
@@ -3264,8 +3296,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
3264
3296
|
|
|
3265
3297
|
pgconn_discard_results( self );
|
|
3266
3298
|
pgconn_send_prepare( argc, argv, self );
|
|
3267
|
-
|
|
3268
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3299
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3269
3300
|
|
|
3270
3301
|
if ( rb_block_given_p() ) {
|
|
3271
3302
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3292,7 +3323,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
3292
3323
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
3293
3324
|
* { :value => <string value>, :format => 0 }
|
|
3294
3325
|
*
|
|
3295
|
-
* PostgreSQL bind parameters are represented as $1, $
|
|
3326
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3296
3327
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
3297
3328
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
|
3298
3329
|
*
|
|
@@ -3318,8 +3349,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
3318
3349
|
|
|
3319
3350
|
pgconn_discard_results( self );
|
|
3320
3351
|
pgconn_send_query_prepared( argc, argv, self );
|
|
3321
|
-
|
|
3322
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3352
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3323
3353
|
|
|
3324
3354
|
if ( rb_block_given_p() ) {
|
|
3325
3355
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3343,8 +3373,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
|
3343
3373
|
|
|
3344
3374
|
pgconn_discard_results( self );
|
|
3345
3375
|
pgconn_send_describe_portal( self, portal );
|
|
3346
|
-
|
|
3347
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3376
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3348
3377
|
|
|
3349
3378
|
if ( rb_block_given_p() ) {
|
|
3350
3379
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3368,8 +3397,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
3368
3397
|
|
|
3369
3398
|
pgconn_discard_results( self );
|
|
3370
3399
|
pgconn_send_describe_prepared( self, stmt_name );
|
|
3371
|
-
|
|
3372
|
-
rb_pgresult = pgconn_get_last_result( self );
|
|
3400
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3373
3401
|
|
|
3374
3402
|
if ( rb_block_given_p() ) {
|
|
3375
3403
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
@@ -3457,6 +3485,126 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
|
3457
3485
|
#endif
|
|
3458
3486
|
|
|
3459
3487
|
|
|
3488
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
|
3489
|
+
/*
|
|
3490
|
+
* call-seq:
|
|
3491
|
+
* conn.pipeline_status -> Integer
|
|
3492
|
+
*
|
|
3493
|
+
* Returns the current pipeline mode status of the libpq connection.
|
|
3494
|
+
*
|
|
3495
|
+
* PQpipelineStatus can return one of the following values:
|
|
3496
|
+
*
|
|
3497
|
+
* * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
|
|
3498
|
+
* * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
|
|
3499
|
+
* * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
|
3500
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
|
3501
|
+
*
|
|
3502
|
+
* Available since PostgreSQL-14
|
|
3503
|
+
*/
|
|
3504
|
+
static VALUE
|
|
3505
|
+
pgconn_pipeline_status(VALUE self)
|
|
3506
|
+
{
|
|
3507
|
+
int res = PQpipelineStatus(pg_get_pgconn(self));
|
|
3508
|
+
return INT2FIX(res);
|
|
3509
|
+
}
|
|
3510
|
+
|
|
3511
|
+
|
|
3512
|
+
/*
|
|
3513
|
+
* call-seq:
|
|
3514
|
+
* conn.enter_pipeline_mode -> nil
|
|
3515
|
+
*
|
|
3516
|
+
* Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
|
|
3517
|
+
*
|
|
3518
|
+
* 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.
|
|
3519
|
+
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
|
3520
|
+
*
|
|
3521
|
+
* Available since PostgreSQL-14
|
|
3522
|
+
*/
|
|
3523
|
+
static VALUE
|
|
3524
|
+
pgconn_enter_pipeline_mode(VALUE self)
|
|
3525
|
+
{
|
|
3526
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3527
|
+
int res = PQenterPipelineMode(conn);
|
|
3528
|
+
if( res == 1 ) {
|
|
3529
|
+
return Qnil;
|
|
3530
|
+
} else {
|
|
3531
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
/*
|
|
3536
|
+
* call-seq:
|
|
3537
|
+
* conn.exit_pipeline_mode -> nil
|
|
3538
|
+
*
|
|
3539
|
+
* Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
|
|
3540
|
+
*
|
|
3541
|
+
* Takes no action if not in pipeline mode.
|
|
3542
|
+
* 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.
|
|
3543
|
+
*
|
|
3544
|
+
* Available since PostgreSQL-14
|
|
3545
|
+
*/
|
|
3546
|
+
static VALUE
|
|
3547
|
+
pgconn_exit_pipeline_mode(VALUE self)
|
|
3548
|
+
{
|
|
3549
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3550
|
+
int res = PQexitPipelineMode(conn);
|
|
3551
|
+
if( res == 1 ) {
|
|
3552
|
+
return Qnil;
|
|
3553
|
+
} else {
|
|
3554
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
|
3555
|
+
}
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
|
|
3559
|
+
/*
|
|
3560
|
+
* call-seq:
|
|
3561
|
+
* conn.pipeline_sync -> nil
|
|
3562
|
+
*
|
|
3563
|
+
* Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
|
|
3564
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
|
|
3565
|
+
*
|
|
3566
|
+
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
|
3567
|
+
*
|
|
3568
|
+
* Available since PostgreSQL-14
|
|
3569
|
+
*/
|
|
3570
|
+
static VALUE
|
|
3571
|
+
pgconn_pipeline_sync(VALUE self)
|
|
3572
|
+
{
|
|
3573
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3574
|
+
int res = PQpipelineSync(conn);
|
|
3575
|
+
if( res == 1 ) {
|
|
3576
|
+
return Qnil;
|
|
3577
|
+
} else {
|
|
3578
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
|
|
3582
|
+
/*
|
|
3583
|
+
* call-seq:
|
|
3584
|
+
* conn.pipeline_sync -> nil
|
|
3585
|
+
*
|
|
3586
|
+
* Sends a request for the server to flush its output buffer.
|
|
3587
|
+
*
|
|
3588
|
+
* 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.
|
|
3589
|
+
* This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
|
|
3590
|
+
* Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
|
|
3591
|
+
*
|
|
3592
|
+
* Available since PostgreSQL-14
|
|
3593
|
+
*/
|
|
3594
|
+
static VALUE
|
|
3595
|
+
pgconn_send_flush_request(VALUE self)
|
|
3596
|
+
{
|
|
3597
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3598
|
+
int res = PQsendFlushRequest(conn);
|
|
3599
|
+
if( res == 1 ) {
|
|
3600
|
+
return Qnil;
|
|
3601
|
+
} else {
|
|
3602
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3606
|
+
#endif
|
|
3607
|
+
|
|
3460
3608
|
/**************************************************************************
|
|
3461
3609
|
* LARGE OBJECT SUPPORT
|
|
3462
3610
|
**************************************************************************/
|
|
@@ -3801,11 +3949,11 @@ static VALUE
|
|
|
3801
3949
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3802
3950
|
{
|
|
3803
3951
|
if (NIL_P(enc)) {
|
|
3804
|
-
|
|
3952
|
+
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
|
3805
3953
|
return enc;
|
|
3806
3954
|
}
|
|
3807
3955
|
else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
|
|
3808
|
-
|
|
3956
|
+
pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
|
3809
3957
|
return enc;
|
|
3810
3958
|
}
|
|
3811
3959
|
else {
|
|
@@ -3843,16 +3991,33 @@ pgconn_external_encoding(VALUE self)
|
|
|
3843
3991
|
return rb_enc_from_encoding( enc );
|
|
3844
3992
|
}
|
|
3845
3993
|
|
|
3994
|
+
/*
|
|
3995
|
+
* call-seq:
|
|
3996
|
+
* conn.set_client_encoding( encoding )
|
|
3997
|
+
*
|
|
3998
|
+
* Sets the client encoding to the _encoding_ String.
|
|
3999
|
+
*/
|
|
4000
|
+
static VALUE
|
|
4001
|
+
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4002
|
+
{
|
|
4003
|
+
VALUE query_format, query;
|
|
4004
|
+
|
|
4005
|
+
Check_Type(encname, T_STRING);
|
|
4006
|
+
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
|
4007
|
+
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
|
4008
|
+
|
|
4009
|
+
pgconn_async_exec(1, &query, self);
|
|
4010
|
+
pgconn_set_internal_encoding_index( self );
|
|
4011
|
+
|
|
4012
|
+
return Qnil;
|
|
4013
|
+
}
|
|
3846
4014
|
|
|
3847
4015
|
static VALUE
|
|
3848
4016
|
pgconn_set_client_encoding_async1( VALUE args )
|
|
3849
4017
|
{
|
|
3850
4018
|
VALUE self = ((VALUE*)args)[0];
|
|
3851
4019
|
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);
|
|
4020
|
+
pgconn_async_set_client_encoding(self, encname);
|
|
3856
4021
|
return 0;
|
|
3857
4022
|
}
|
|
3858
4023
|
|
|
@@ -3867,9 +4032,9 @@ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
|
|
|
3867
4032
|
|
|
3868
4033
|
|
|
3869
4034
|
static VALUE
|
|
3870
|
-
pgconn_set_client_encoding_async( VALUE self,
|
|
4035
|
+
pgconn_set_client_encoding_async( VALUE self, VALUE encname )
|
|
3871
4036
|
{
|
|
3872
|
-
VALUE args[] = { self,
|
|
4037
|
+
VALUE args[] = { self, encname };
|
|
3873
4038
|
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
|
3874
4039
|
}
|
|
3875
4040
|
|
|
@@ -3891,10 +4056,9 @@ pgconn_set_default_encoding( VALUE self )
|
|
|
3891
4056
|
|
|
3892
4057
|
if (( enc = rb_default_internal_encoding() )) {
|
|
3893
4058
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
|
3894
|
-
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
|
4059
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
|
3895
4060
|
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
|
3896
4061
|
encname, PQerrorMessage(conn) );
|
|
3897
|
-
pgconn_set_internal_encoding_index( self );
|
|
3898
4062
|
return rb_enc_from_encoding( enc );
|
|
3899
4063
|
} else {
|
|
3900
4064
|
pgconn_set_internal_encoding_index( self );
|
|
@@ -3916,12 +4080,12 @@ static VALUE
|
|
|
3916
4080
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
3917
4081
|
{
|
|
3918
4082
|
t_pg_connection *this = pg_get_connection( self );
|
|
4083
|
+
t_typemap *tm;
|
|
4084
|
+
UNUSED(tm);
|
|
4085
|
+
|
|
4086
|
+
/* Check type of method param */
|
|
4087
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
|
3919
4088
|
|
|
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
4089
|
this->type_map_for_queries = typemap;
|
|
3926
4090
|
|
|
3927
4091
|
return typemap;
|
|
@@ -3956,12 +4120,10 @@ static VALUE
|
|
|
3956
4120
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
3957
4121
|
{
|
|
3958
4122
|
t_pg_connection *this = pg_get_connection( self );
|
|
4123
|
+
t_typemap *tm;
|
|
4124
|
+
UNUSED(tm);
|
|
3959
4125
|
|
|
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);
|
|
4126
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
|
3965
4127
|
this->type_map_for_results = typemap;
|
|
3966
4128
|
|
|
3967
4129
|
return typemap;
|
|
@@ -3996,20 +4158,19 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
|
3996
4158
|
*
|
|
3997
4159
|
*/
|
|
3998
4160
|
static VALUE
|
|
3999
|
-
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE
|
|
4161
|
+
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4000
4162
|
{
|
|
4001
4163
|
t_pg_connection *this = pg_get_connection( self );
|
|
4002
4164
|
|
|
4003
|
-
if(
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
Check_Type(typemap, T_DATA);
|
|
4165
|
+
if( encoder != Qnil ){
|
|
4166
|
+
t_pg_coder *co;
|
|
4167
|
+
UNUSED(co);
|
|
4168
|
+
/* Check argument type */
|
|
4169
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
|
4009
4170
|
}
|
|
4010
|
-
this->encoder_for_put_copy_data =
|
|
4171
|
+
this->encoder_for_put_copy_data = encoder;
|
|
4011
4172
|
|
|
4012
|
-
return
|
|
4173
|
+
return encoder;
|
|
4013
4174
|
}
|
|
4014
4175
|
|
|
4015
4176
|
/*
|
|
@@ -4045,20 +4206,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
|
4045
4206
|
*
|
|
4046
4207
|
*/
|
|
4047
4208
|
static VALUE
|
|
4048
|
-
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE
|
|
4209
|
+
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4049
4210
|
{
|
|
4050
4211
|
t_pg_connection *this = pg_get_connection( self );
|
|
4051
4212
|
|
|
4052
|
-
if(
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
Check_Type(typemap, T_DATA);
|
|
4213
|
+
if( decoder != Qnil ){
|
|
4214
|
+
t_pg_coder *co;
|
|
4215
|
+
UNUSED(co);
|
|
4216
|
+
/* Check argument type */
|
|
4217
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
|
4058
4218
|
}
|
|
4059
|
-
this->decoder_for_get_copy_data =
|
|
4219
|
+
this->decoder_for_get_copy_data = decoder;
|
|
4060
4220
|
|
|
4061
|
-
return
|
|
4221
|
+
return decoder;
|
|
4062
4222
|
}
|
|
4063
4223
|
|
|
4064
4224
|
/*
|
|
@@ -4141,6 +4301,7 @@ void
|
|
|
4141
4301
|
init_pg_connection()
|
|
4142
4302
|
{
|
|
4143
4303
|
s_id_encode = rb_intern("encode");
|
|
4304
|
+
s_id_autoclose_set = rb_intern("autoclose=");
|
|
4144
4305
|
sym_type = ID2SYM(rb_intern("type"));
|
|
4145
4306
|
sym_format = ID2SYM(rb_intern("format"));
|
|
4146
4307
|
sym_value = ID2SYM(rb_intern("value"));
|
|
@@ -4156,10 +4317,6 @@ init_pg_connection()
|
|
|
4156
4317
|
/****** PG::Connection CLASS METHODS ******/
|
|
4157
4318
|
rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
|
|
4158
4319
|
|
|
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
4320
|
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
|
4164
4321
|
SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
|
|
4165
4322
|
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
|
@@ -4168,14 +4325,14 @@ init_pg_connection()
|
|
|
4168
4325
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
|
4169
4326
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
|
4170
4327
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
|
4171
|
-
rb_define_singleton_method(rb_cPGconn, "
|
|
4328
|
+
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
|
4329
|
+
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
|
4172
4330
|
|
|
4173
4331
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
|
4174
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
|
4175
4332
|
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
|
4176
4333
|
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
|
4177
4334
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
|
4178
|
-
rb_define_method(rb_cPGconn, "
|
|
4335
|
+
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
|
4179
4336
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
|
4180
4337
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
|
4181
4338
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
|
@@ -4187,9 +4344,7 @@ init_pg_connection()
|
|
|
4187
4344
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
|
4188
4345
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
|
4189
4346
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
|
4190
|
-
#ifdef HAVE_PQCONNINFO
|
|
4191
4347
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|
|
4192
|
-
#endif
|
|
4193
4348
|
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
|
4194
4349
|
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
|
4195
4350
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
|
@@ -4200,17 +4355,18 @@ init_pg_connection()
|
|
|
4200
4355
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
|
4201
4356
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
|
4202
4357
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
|
4358
|
+
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
|
4203
4359
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
|
4204
4360
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
|
4205
4361
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
|
4206
4362
|
|
|
4207
4363
|
/****** 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",
|
|
4364
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
|
|
4365
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
|
|
4366
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
|
|
4367
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
|
4368
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
|
4369
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
|
4214
4370
|
|
|
4215
4371
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
|
4216
4372
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
|
@@ -4243,25 +4399,26 @@ init_pg_connection()
|
|
|
4243
4399
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
|
4244
4400
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
|
4245
4401
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
|
4246
|
-
rb_define_method(rb_cPGconn, "
|
|
4402
|
+
rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
|
|
4247
4403
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
|
4248
4404
|
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",
|
|
4405
|
+
rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
|
|
4406
|
+
rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
|
|
4407
|
+
rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
|
|
4408
|
+
rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
|
|
4409
|
+
rb_define_alias(rb_cPGconn, "async_flush", "flush");
|
|
4253
4410
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
|
4254
4411
|
|
|
4255
4412
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
|
4256
|
-
rb_define_method(rb_cPGconn, "
|
|
4413
|
+
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
|
4257
4414
|
|
|
4258
4415
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
|
4259
4416
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
|
4260
4417
|
|
|
4261
4418
|
/****** PG::Connection INSTANCE METHODS: COPY ******/
|
|
4262
|
-
rb_define_method(rb_cPGconn, "
|
|
4263
|
-
rb_define_method(rb_cPGconn, "
|
|
4264
|
-
rb_define_method(rb_cPGconn, "
|
|
4419
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
|
|
4420
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
|
|
4421
|
+
rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
|
|
4265
4422
|
|
|
4266
4423
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
|
4267
4424
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
|
@@ -4277,16 +4434,20 @@ init_pg_connection()
|
|
|
4277
4434
|
|
|
4278
4435
|
/****** PG::Connection INSTANCE METHODS: Other ******/
|
|
4279
4436
|
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
|
4280
|
-
rb_define_method(rb_cPGconn, "
|
|
4437
|
+
rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
|
|
4438
|
+
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
|
|
4439
|
+
rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
|
|
4281
4440
|
rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
|
|
4282
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
|
4283
4441
|
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
|
4442
|
+
rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
|
|
4284
4443
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
|
4285
4444
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
|
4286
4445
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
|
4287
|
-
rb_define_method(rb_cPGconn, "
|
|
4446
|
+
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
|
4447
|
+
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
|
4448
|
+
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
|
4288
4449
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
4289
|
-
rb_define_method(rb_cPGconn, "
|
|
4450
|
+
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
|
4290
4451
|
#endif
|
|
4291
4452
|
|
|
4292
4453
|
#ifdef HAVE_PQSSLATTRIBUTE
|
|
@@ -4295,6 +4456,14 @@ init_pg_connection()
|
|
|
4295
4456
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
|
4296
4457
|
#endif
|
|
4297
4458
|
|
|
4459
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
|
4460
|
+
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
|
4461
|
+
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
|
4462
|
+
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
|
4463
|
+
rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
|
|
4464
|
+
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
|
4465
|
+
#endif
|
|
4466
|
+
|
|
4298
4467
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
|
4299
4468
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
|
4300
4469
|
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|