pg 1.2.3 → 1.3.5
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 +153 -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 +131 -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 +680 -508
- data/ext/pg_copy_coder.c +45 -16
- data/ext/pg_record_coder.c +45 -15
- data/ext/pg_result.c +77 -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 +301 -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;
|
@@ -499,17 +450,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
499
450
|
* the asynchronous connection is ready
|
500
451
|
*
|
501
452
|
* Example:
|
502
|
-
*
|
503
|
-
*
|
453
|
+
* require "io/wait"
|
454
|
+
*
|
455
|
+
* conn = PG::Connection.connect_start(dbname: 'mydatabase')
|
504
456
|
* status = conn.connect_poll
|
505
457
|
* while(status != PG::PGRES_POLLING_OK) do
|
506
458
|
* # do some work while waiting for the connection to complete
|
507
459
|
* if(status == PG::PGRES_POLLING_READING)
|
508
|
-
*
|
460
|
+
* unless conn.socket_io.wait_readable(10.0)
|
509
461
|
* raise "Asynchronous connection timed out!"
|
510
462
|
* end
|
511
463
|
* elsif(status == PG::PGRES_POLLING_WRITING)
|
512
|
-
*
|
464
|
+
* unless conn.socket_io.wait_writable(10.0)
|
513
465
|
* raise "Asynchronous connection timed out!"
|
514
466
|
* end
|
515
467
|
* end
|
@@ -523,6 +475,9 @@ pgconn_connect_poll(VALUE self)
|
|
523
475
|
{
|
524
476
|
PostgresPollingStatusType status;
|
525
477
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
478
|
+
|
479
|
+
pgconn_close_socket_io(self);
|
480
|
+
|
526
481
|
return INT2FIX((int)status);
|
527
482
|
}
|
528
483
|
|
@@ -559,15 +514,8 @@ pgconn_finished_p( VALUE self )
|
|
559
514
|
}
|
560
515
|
|
561
516
|
|
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
517
|
static VALUE
|
570
|
-
|
518
|
+
pgconn_sync_reset( VALUE self )
|
571
519
|
{
|
572
520
|
pgconn_close_socket_io( self );
|
573
521
|
gvl_PQreset( pg_get_pgconn(self) );
|
@@ -606,6 +554,9 @@ pgconn_reset_poll(VALUE self)
|
|
606
554
|
{
|
607
555
|
PostgresPollingStatusType status;
|
608
556
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
557
|
+
|
558
|
+
pgconn_close_socket_io(self);
|
559
|
+
|
609
560
|
return INT2FIX((int)status);
|
610
561
|
}
|
611
562
|
|
@@ -676,21 +627,19 @@ static VALUE
|
|
676
627
|
pgconn_port(VALUE self)
|
677
628
|
{
|
678
629
|
char* port = PQport(pg_get_pgconn(self));
|
679
|
-
return INT2NUM(
|
630
|
+
return INT2NUM(atoi(port));
|
680
631
|
}
|
681
632
|
|
682
633
|
/*
|
683
634
|
* call-seq:
|
684
635
|
* conn.tty()
|
685
636
|
*
|
686
|
-
*
|
637
|
+
* Obsolete function.
|
687
638
|
*/
|
688
639
|
static VALUE
|
689
640
|
pgconn_tty(VALUE self)
|
690
641
|
{
|
691
|
-
|
692
|
-
if (!tty) return Qnil;
|
693
|
-
return rb_str_new2(tty);
|
642
|
+
return rb_str_new2("");
|
694
643
|
}
|
695
644
|
|
696
645
|
/*
|
@@ -708,7 +657,6 @@ pgconn_options(VALUE self)
|
|
708
657
|
}
|
709
658
|
|
710
659
|
|
711
|
-
#ifdef HAVE_PQCONNINFO
|
712
660
|
/*
|
713
661
|
* call-seq:
|
714
662
|
* conn.conninfo -> hash
|
@@ -728,14 +676,17 @@ pgconn_conninfo( VALUE self )
|
|
728
676
|
|
729
677
|
return array;
|
730
678
|
}
|
731
|
-
#endif
|
732
679
|
|
733
680
|
|
734
681
|
/*
|
735
682
|
* call-seq:
|
736
683
|
* conn.status()
|
737
684
|
*
|
738
|
-
* Returns status of connection
|
685
|
+
* Returns the status of the connection, which is one:
|
686
|
+
* PG::Constants::CONNECTION_OK
|
687
|
+
* PG::Constants::CONNECTION_BAD
|
688
|
+
*
|
689
|
+
* ... and other constants of kind PG::Constants::CONNECTION_*
|
739
690
|
*/
|
740
691
|
static VALUE
|
741
692
|
pgconn_status(VALUE self)
|
@@ -823,7 +774,10 @@ pgconn_server_version(VALUE self)
|
|
823
774
|
* call-seq:
|
824
775
|
* conn.error_message -> String
|
825
776
|
*
|
826
|
-
* Returns the error message
|
777
|
+
* Returns the error message most recently generated by an operation on the connection.
|
778
|
+
*
|
779
|
+
* Nearly all libpq functions will set a message for conn.error_message if they fail.
|
780
|
+
* Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
|
827
781
|
*/
|
828
782
|
static VALUE
|
829
783
|
pgconn_error_message(VALUE self)
|
@@ -865,21 +819,23 @@ pgconn_socket(VALUE self)
|
|
865
819
|
* call-seq:
|
866
820
|
* conn.socket_io() -> IO
|
867
821
|
*
|
868
|
-
* Fetch
|
869
|
-
* This object can be used for IO.select to wait for events while running
|
870
|
-
*
|
822
|
+
* Fetch an IO object created from the Connection's underlying socket.
|
823
|
+
* This object can be used per <tt>socket_io.wait_readable</tt>, <tt>socket_io.wait_writable</tt> or for <tt>IO.select</tt> to wait for events while running asynchronous API calls.
|
824
|
+
* <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
|
825
|
+
*
|
826
|
+
* The IO object can change while the connection is established, but is memorized afterwards.
|
827
|
+
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
871
828
|
*
|
872
|
-
* Using this
|
873
|
-
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
874
|
-
* goes out of scope. In contrast to #socket, it also works on Windows.
|
829
|
+
* Using this method also works on Windows in contrast to using #socket .
|
830
|
+
* It also avoids the problem of the underlying connection being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt> goes out of scope.
|
875
831
|
*/
|
876
832
|
static VALUE
|
877
833
|
pgconn_socket_io(VALUE self)
|
878
834
|
{
|
879
835
|
int sd;
|
880
836
|
int ruby_sd;
|
881
|
-
ID id_autoclose = rb_intern("autoclose=");
|
882
837
|
t_pg_connection *this = pg_get_connection_safe( self );
|
838
|
+
VALUE cSocket;
|
883
839
|
VALUE socket_io = this->socket_io;
|
884
840
|
|
885
841
|
if ( !RTEST(socket_io) ) {
|
@@ -888,15 +844,19 @@ pgconn_socket_io(VALUE self)
|
|
888
844
|
|
889
845
|
#ifdef _WIN32
|
890
846
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
847
|
+
if( ruby_sd == -1 ){
|
848
|
+
rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
|
849
|
+
}
|
891
850
|
this->ruby_sd = ruby_sd;
|
892
851
|
#else
|
893
852
|
ruby_sd = sd;
|
894
853
|
#endif
|
895
854
|
|
896
|
-
|
855
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
856
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
897
857
|
|
898
858
|
/* Disable autoclose feature */
|
899
|
-
rb_funcall( socket_io,
|
859
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
900
860
|
|
901
861
|
this->socket_io = socket_io;
|
902
862
|
}
|
@@ -918,6 +878,51 @@ pgconn_backend_pid(VALUE self)
|
|
918
878
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
919
879
|
}
|
920
880
|
|
881
|
+
typedef struct
|
882
|
+
{
|
883
|
+
struct sockaddr_storage addr;
|
884
|
+
socklen_t salen;
|
885
|
+
} SockAddr;
|
886
|
+
|
887
|
+
/* Copy of struct pg_cancel from libpq-int.h
|
888
|
+
*
|
889
|
+
* See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
|
890
|
+
*/
|
891
|
+
struct pg_cancel
|
892
|
+
{
|
893
|
+
SockAddr raddr; /* Remote address */
|
894
|
+
int be_pid; /* PID of backend --- needed for cancels */
|
895
|
+
int be_key; /* key of backend --- needed for cancels */
|
896
|
+
};
|
897
|
+
|
898
|
+
/*
|
899
|
+
* call-seq:
|
900
|
+
* conn.backend_key() -> Integer
|
901
|
+
*
|
902
|
+
* Returns the key of the backend server process for this connection.
|
903
|
+
* This key can be used to cancel queries on the server.
|
904
|
+
*/
|
905
|
+
static VALUE
|
906
|
+
pgconn_backend_key(VALUE self)
|
907
|
+
{
|
908
|
+
int be_key;
|
909
|
+
struct pg_cancel *cancel;
|
910
|
+
PGconn *conn = pg_get_pgconn(self);
|
911
|
+
|
912
|
+
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
913
|
+
if(cancel == NULL)
|
914
|
+
rb_raise(rb_ePGerror,"Invalid connection!");
|
915
|
+
|
916
|
+
if( cancel->be_pid != PQbackendPID(conn) )
|
917
|
+
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
918
|
+
|
919
|
+
be_key = cancel->be_key;
|
920
|
+
|
921
|
+
PQfreeCancel(cancel);
|
922
|
+
|
923
|
+
return INT2NUM(be_key);
|
924
|
+
}
|
925
|
+
|
921
926
|
/*
|
922
927
|
* call-seq:
|
923
928
|
* conn.connection_needs_password() -> Boolean
|
@@ -948,7 +953,7 @@ pgconn_connection_used_password(VALUE self)
|
|
948
953
|
/* :TODO: get_ssl */
|
949
954
|
|
950
955
|
|
951
|
-
static VALUE
|
956
|
+
static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
952
957
|
|
953
958
|
/*
|
954
959
|
* call-seq:
|
@@ -962,11 +967,11 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
962
967
|
* However #async_exec has two advantages:
|
963
968
|
*
|
964
969
|
* 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
|
-
*
|
970
|
+
* 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
|
971
|
+
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
967
972
|
*/
|
968
973
|
static VALUE
|
969
|
-
|
974
|
+
pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
970
975
|
{
|
971
976
|
t_pg_connection *this = pg_get_connection_safe( self );
|
972
977
|
PGresult *result = NULL;
|
@@ -987,7 +992,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
987
992
|
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
988
993
|
|
989
994
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
990
|
-
return
|
995
|
+
return pgconn_sync_exec_params( argc, argv, self );
|
991
996
|
|
992
997
|
}
|
993
998
|
|
@@ -1019,7 +1024,7 @@ struct query_params_data {
|
|
1019
1024
|
* Filled by alloc_query_params()
|
1020
1025
|
*/
|
1021
1026
|
|
1022
|
-
/* Wraps the pointer of allocated memory, if function parameters
|
1027
|
+
/* Wraps the pointer of allocated memory, if function parameters don't
|
1023
1028
|
* fit in the memory_pool below.
|
1024
1029
|
*/
|
1025
1030
|
VALUE heap_pool;
|
@@ -1037,7 +1042,7 @@ struct query_params_data {
|
|
1037
1042
|
Oid *types;
|
1038
1043
|
|
1039
1044
|
/* This array takes the string values for the timeframe of the query,
|
1040
|
-
* if param value
|
1045
|
+
* if param value conversion is required
|
1041
1046
|
*/
|
1042
1047
|
VALUE gc_array;
|
1043
1048
|
|
@@ -1051,8 +1056,9 @@ struct query_params_data {
|
|
1051
1056
|
};
|
1052
1057
|
|
1053
1058
|
static void
|
1054
|
-
free_typecast_heap_chain(
|
1059
|
+
free_typecast_heap_chain(void *_chain_entry)
|
1055
1060
|
{
|
1061
|
+
struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
|
1056
1062
|
while(chain_entry){
|
1057
1063
|
struct linked_typecast_data *next = chain_entry->next;
|
1058
1064
|
xfree(chain_entry);
|
@@ -1060,6 +1066,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
|
|
1060
1066
|
}
|
1061
1067
|
}
|
1062
1068
|
|
1069
|
+
static const rb_data_type_t pg_typecast_buffer_type = {
|
1070
|
+
"PG::Connection typecast buffer chain",
|
1071
|
+
{
|
1072
|
+
(RUBY_DATA_FUNC) NULL,
|
1073
|
+
free_typecast_heap_chain,
|
1074
|
+
(size_t (*)(const void *))NULL,
|
1075
|
+
},
|
1076
|
+
0,
|
1077
|
+
0,
|
1078
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1079
|
+
};
|
1080
|
+
|
1063
1081
|
static char *
|
1064
1082
|
alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
1065
1083
|
{
|
@@ -1070,17 +1088,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
1070
1088
|
/* Did we already wrap a memory chain per T_DATA object? */
|
1071
1089
|
if( NIL_P( *typecast_heap_chain ) ){
|
1072
1090
|
/* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
|
1073
|
-
*typecast_heap_chain =
|
1091
|
+
*typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
|
1074
1092
|
allocated->next = NULL;
|
1075
1093
|
} else {
|
1076
1094
|
/* Append to the chain */
|
1077
|
-
allocated->next =
|
1078
|
-
|
1095
|
+
allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
|
1096
|
+
RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
|
1079
1097
|
}
|
1080
1098
|
|
1081
1099
|
return &allocated->data[0];
|
1082
1100
|
}
|
1083
1101
|
|
1102
|
+
static const rb_data_type_t pg_query_heap_pool_type = {
|
1103
|
+
"PG::Connection query heap pool",
|
1104
|
+
{
|
1105
|
+
(RUBY_DATA_FUNC) NULL,
|
1106
|
+
RUBY_TYPED_DEFAULT_FREE,
|
1107
|
+
(size_t (*)(const void *))NULL,
|
1108
|
+
},
|
1109
|
+
0,
|
1110
|
+
0,
|
1111
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1112
|
+
};
|
1084
1113
|
|
1085
1114
|
static int
|
1086
1115
|
alloc_query_params(struct query_params_data *paramsData)
|
@@ -1095,7 +1124,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1095
1124
|
|
1096
1125
|
Check_Type(paramsData->params, T_ARRAY);
|
1097
1126
|
|
1098
|
-
p_typemap =
|
1127
|
+
p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
|
1099
1128
|
p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
|
1100
1129
|
|
1101
1130
|
paramsData->heap_pool = Qnil;
|
@@ -1114,7 +1143,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1114
1143
|
/* Allocate one combined memory pool for all possible function parameters */
|
1115
1144
|
memory_pool = (char*)xmalloc( required_pool_size );
|
1116
1145
|
/* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
|
1117
|
-
paramsData->heap_pool =
|
1146
|
+
paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
|
1118
1147
|
required_pool_size = 0;
|
1119
1148
|
}else{
|
1120
1149
|
/* Use stack memory for function parameters */
|
@@ -1227,12 +1256,11 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1227
1256
|
/* Use default typemap for queries. It's type is checked when assigned. */
|
1228
1257
|
paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
|
1229
1258
|
}else{
|
1259
|
+
t_typemap *tm;
|
1260
|
+
UNUSED(tm);
|
1261
|
+
|
1230
1262
|
/* 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 );
|
1263
|
+
TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
|
1236
1264
|
}
|
1237
1265
|
}
|
1238
1266
|
|
@@ -1246,7 +1274,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1246
1274
|
* 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
1275
|
*/
|
1248
1276
|
static VALUE
|
1249
|
-
|
1277
|
+
pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
1250
1278
|
{
|
1251
1279
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1252
1280
|
PGresult *result = NULL;
|
@@ -1266,7 +1294,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1266
1294
|
*/
|
1267
1295
|
if ( NIL_P(paramsData.params) ) {
|
1268
1296
|
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
1269
|
-
return
|
1297
|
+
return pgconn_sync_exec( 1, argv, self );
|
1270
1298
|
}
|
1271
1299
|
pgconn_query_assign_typemap( self, ¶msData );
|
1272
1300
|
|
@@ -1297,7 +1325,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1297
1325
|
* It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
|
1298
1326
|
*/
|
1299
1327
|
static VALUE
|
1300
|
-
|
1328
|
+
pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
1301
1329
|
{
|
1302
1330
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1303
1331
|
PGresult *result = NULL;
|
@@ -1346,7 +1374,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1346
1374
|
* 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
1375
|
*/
|
1348
1376
|
static VALUE
|
1349
|
-
|
1377
|
+
pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
1350
1378
|
{
|
1351
1379
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1352
1380
|
PGresult *result = NULL;
|
@@ -1391,7 +1419,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1391
1419
|
* 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
1420
|
*/
|
1393
1421
|
static VALUE
|
1394
|
-
|
1422
|
+
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
1395
1423
|
{
|
1396
1424
|
PGresult *result;
|
1397
1425
|
VALUE rb_pgresult;
|
@@ -1419,7 +1447,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1419
1447
|
* 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
1448
|
*/
|
1421
1449
|
static VALUE
|
1422
|
-
|
1450
|
+
pgconn_sync_describe_portal(self, stmt_name)
|
1423
1451
|
VALUE self, stmt_name;
|
1424
1452
|
{
|
1425
1453
|
PGresult *result;
|
@@ -1454,6 +1482,9 @@ pgconn_describe_portal(self, stmt_name)
|
|
1454
1482
|
* * +PGRES_NONFATAL_ERROR+
|
1455
1483
|
* * +PGRES_FATAL_ERROR+
|
1456
1484
|
* * +PGRES_COPY_BOTH+
|
1485
|
+
* * +PGRES_SINGLE_TUPLE+
|
1486
|
+
* * +PGRES_PIPELINE_SYNC+
|
1487
|
+
* * +PGRES_PIPELINE_ABORTED+
|
1457
1488
|
*/
|
1458
1489
|
static VALUE
|
1459
1490
|
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
@@ -1750,6 +1781,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1750
1781
|
rb_iv_set(error, "@connection", self);
|
1751
1782
|
rb_exc_raise(error);
|
1752
1783
|
}
|
1784
|
+
pgconn_wait_for_flush( self );
|
1753
1785
|
return Qnil;
|
1754
1786
|
}
|
1755
1787
|
|
@@ -1779,7 +1811,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1779
1811
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1780
1812
|
* { :value => <string value>, :type => 0, :format => 0 }
|
1781
1813
|
*
|
1782
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1814
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1783
1815
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1784
1816
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1785
1817
|
*
|
@@ -1827,6 +1859,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1827
1859
|
rb_iv_set(error, "@connection", self);
|
1828
1860
|
rb_exc_raise(error);
|
1829
1861
|
}
|
1862
|
+
pgconn_wait_for_flush( self );
|
1830
1863
|
return Qnil;
|
1831
1864
|
}
|
1832
1865
|
|
@@ -1847,7 +1880,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1847
1880
|
*
|
1848
1881
|
* For example: "SELECT $1::int"
|
1849
1882
|
*
|
1850
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1883
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1851
1884
|
* inside the SQL query.
|
1852
1885
|
*/
|
1853
1886
|
static VALUE
|
@@ -1890,6 +1923,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1890
1923
|
rb_iv_set(error, "@connection", self);
|
1891
1924
|
rb_exc_raise(error);
|
1892
1925
|
}
|
1926
|
+
pgconn_wait_for_flush( self );
|
1893
1927
|
return Qnil;
|
1894
1928
|
}
|
1895
1929
|
|
@@ -1911,7 +1945,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1911
1945
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1912
1946
|
* { :value => <string value>, :format => 0 }
|
1913
1947
|
*
|
1914
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1948
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1915
1949
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1916
1950
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1917
1951
|
*
|
@@ -1941,7 +1975,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1941
1975
|
|
1942
1976
|
if(NIL_P(paramsData.params)) {
|
1943
1977
|
paramsData.params = rb_ary_new2(0);
|
1944
|
-
resultFormat = 0;
|
1945
1978
|
}
|
1946
1979
|
pgconn_query_assign_typemap( self, ¶msData );
|
1947
1980
|
|
@@ -1959,6 +1992,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1959
1992
|
rb_iv_set(error, "@connection", self);
|
1960
1993
|
rb_exc_raise(error);
|
1961
1994
|
}
|
1995
|
+
pgconn_wait_for_flush( self );
|
1962
1996
|
return Qnil;
|
1963
1997
|
}
|
1964
1998
|
|
@@ -1980,6 +2014,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1980
2014
|
rb_iv_set(error, "@connection", self);
|
1981
2015
|
rb_exc_raise(error);
|
1982
2016
|
}
|
2017
|
+
pgconn_wait_for_flush( self );
|
1983
2018
|
return Qnil;
|
1984
2019
|
}
|
1985
2020
|
|
@@ -2002,28 +2037,13 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
2002
2037
|
rb_iv_set(error, "@connection", self);
|
2003
2038
|
rb_exc_raise(error);
|
2004
2039
|
}
|
2040
|
+
pgconn_wait_for_flush( self );
|
2005
2041
|
return Qnil;
|
2006
2042
|
}
|
2007
2043
|
|
2008
2044
|
|
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
2045
|
static VALUE
|
2026
|
-
|
2046
|
+
pgconn_sync_get_result(VALUE self)
|
2027
2047
|
{
|
2028
2048
|
PGconn *conn = pg_get_pgconn(self);
|
2029
2049
|
PGresult *result;
|
@@ -2056,6 +2076,7 @@ pgconn_consume_input(self)
|
|
2056
2076
|
PGconn *conn = pg_get_pgconn(self);
|
2057
2077
|
/* returns 0 on error */
|
2058
2078
|
if(PQconsumeInput(conn) == 0) {
|
2079
|
+
pgconn_close_socket_io(self);
|
2059
2080
|
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
2060
2081
|
rb_iv_set(error, "@connection", self);
|
2061
2082
|
rb_exc_raise(error);
|
@@ -2068,7 +2089,7 @@ pgconn_consume_input(self)
|
|
2068
2089
|
* conn.is_busy() -> Boolean
|
2069
2090
|
*
|
2070
2091
|
* Returns +true+ if a command is busy, that is, if
|
2071
|
-
*
|
2092
|
+
* #get_result would block. Otherwise returns +false+.
|
2072
2093
|
*/
|
2073
2094
|
static VALUE
|
2074
2095
|
pgconn_is_busy(self)
|
@@ -2077,24 +2098,8 @@ pgconn_is_busy(self)
|
|
2077
2098
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2078
2099
|
}
|
2079
2100
|
|
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
2101
|
static VALUE
|
2097
|
-
|
2102
|
+
pgconn_sync_setnonblocking(self, state)
|
2098
2103
|
VALUE self, state;
|
2099
2104
|
{
|
2100
2105
|
int arg;
|
@@ -2116,33 +2121,15 @@ pgconn_setnonblocking(self, state)
|
|
2116
2121
|
}
|
2117
2122
|
|
2118
2123
|
|
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
2124
|
static VALUE
|
2127
|
-
|
2125
|
+
pgconn_sync_isnonblocking(self)
|
2128
2126
|
VALUE self;
|
2129
2127
|
{
|
2130
2128
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2131
2129
|
}
|
2132
2130
|
|
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
2131
|
static VALUE
|
2144
|
-
|
2145
|
-
VALUE self;
|
2132
|
+
pgconn_sync_flush(VALUE self)
|
2146
2133
|
{
|
2147
2134
|
PGconn *conn = pg_get_pgconn(self);
|
2148
2135
|
int ret;
|
@@ -2156,18 +2143,8 @@ pgconn_flush(self)
|
|
2156
2143
|
return (ret) ? Qfalse : Qtrue;
|
2157
2144
|
}
|
2158
2145
|
|
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
2146
|
static VALUE
|
2170
|
-
|
2147
|
+
pgconn_sync_cancel(VALUE self)
|
2171
2148
|
{
|
2172
2149
|
char errbuf[256];
|
2173
2150
|
PGcancel *cancel;
|
@@ -2178,7 +2155,7 @@ pgconn_cancel(VALUE self)
|
|
2178
2155
|
if(cancel == NULL)
|
2179
2156
|
rb_raise(rb_ePGerror,"Invalid connection!");
|
2180
2157
|
|
2181
|
-
ret = gvl_PQcancel(cancel, errbuf,
|
2158
|
+
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
2182
2159
|
if(ret == 1)
|
2183
2160
|
retval = Qnil;
|
2184
2161
|
else
|
@@ -2229,55 +2206,63 @@ pgconn_notifies(VALUE self)
|
|
2229
2206
|
return hash;
|
2230
2207
|
}
|
2231
2208
|
|
2232
|
-
|
2233
|
-
|
2234
|
-
/*
|
2235
|
-
*
|
2236
|
-
* instead of rb_wait_for_single_fd().
|
2209
|
+
#if defined(_WIN32)
|
2210
|
+
|
2211
|
+
/* We use a specialized implementation of rb_io_wait() on Windows.
|
2212
|
+
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
2237
2213
|
*/
|
2238
2214
|
|
2215
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2216
|
+
#include <ruby/fiber/scheduler.h>
|
2217
|
+
#endif
|
2218
|
+
|
2219
|
+
typedef enum {
|
2220
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
2221
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
2222
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
2223
|
+
} pg_rb_io_event_t;
|
2224
|
+
|
2239
2225
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2240
2226
|
|
2241
|
-
static
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2227
|
+
static VALUE
|
2228
|
+
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2229
|
+
rb_io_t *fptr;
|
2230
|
+
struct timeval ptimeout;
|
2231
|
+
|
2246
2232
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2247
2233
|
DWORD timeout_milisec = INFINITE;
|
2248
|
-
|
2249
|
-
WSAEVENT hEvent;
|
2234
|
+
HANDLE hEvent = WSACreateEvent();
|
2250
2235
|
|
2251
|
-
|
2252
|
-
|
2253
|
-
|
2254
|
-
hEvent = WSACreateEvent();
|
2236
|
+
long rb_events = NUM2UINT(events);
|
2237
|
+
long w32_events = 0;
|
2238
|
+
DWORD wait_ret;
|
2255
2239
|
|
2256
|
-
|
2257
|
-
if(
|
2258
|
-
|
2259
|
-
|
2260
|
-
}
|
2240
|
+
GetOpenFile((io), fptr);
|
2241
|
+
if( !NIL_P(timeout) ){
|
2242
|
+
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
2243
|
+
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
2261
2244
|
|
2262
|
-
if ( ptimeout ) {
|
2263
2245
|
gettimeofday(&currtime, NULL);
|
2264
|
-
timeradd(&currtime, ptimeout, &aborttime);
|
2246
|
+
timeradd(&currtime, &ptimeout, &aborttime);
|
2265
2247
|
}
|
2266
2248
|
|
2267
|
-
|
2268
|
-
|
2249
|
+
if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
2250
|
+
if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
|
2251
|
+
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
2252
|
+
|
2253
|
+
for(;;) {
|
2254
|
+
if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
|
2269
2255
|
WSACloseEvent( hEvent );
|
2270
2256
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2271
2257
|
}
|
2272
2258
|
|
2273
|
-
if (
|
2259
|
+
if ( !NIL_P(timeout) ) {
|
2274
2260
|
gettimeofday(&currtime, NULL);
|
2275
2261
|
timersub(&aborttime, &currtime, &waittime);
|
2276
2262
|
timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
|
2277
2263
|
}
|
2278
2264
|
|
2279
|
-
|
2280
|
-
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2265
|
+
if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2281
2266
|
/* Wait for the socket to become readable before checking again */
|
2282
2267
|
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
2283
2268
|
} else {
|
@@ -2286,9 +2271,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2286
2271
|
|
2287
2272
|
if ( wait_ret == WAIT_TIMEOUT ) {
|
2288
2273
|
WSACloseEvent( hEvent );
|
2289
|
-
return
|
2274
|
+
return UINT2NUM(0);
|
2290
2275
|
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2276
|
+
WSACloseEvent( hEvent );
|
2291
2277
|
/* The event we were waiting for. */
|
2278
|
+
return UINT2NUM(rb_events);
|
2292
2279
|
} else if ( wait_ret == WAIT_OBJECT_0 + 1) {
|
2293
2280
|
/* This indicates interruption from timer thread, GC, exception
|
2294
2281
|
* from other threads etc... */
|
@@ -2300,36 +2287,66 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2300
2287
|
WSACloseEvent( hEvent );
|
2301
2288
|
rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2302
2289
|
}
|
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
2290
|
}
|
2291
|
+
}
|
2310
2292
|
|
2311
|
-
|
2312
|
-
|
2293
|
+
static VALUE
|
2294
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2295
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2296
|
+
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
2297
|
+
* Fortunatelly ruby-3.1 offers a C-API for it.
|
2298
|
+
*/
|
2299
|
+
VALUE scheduler = rb_fiber_scheduler_current();
|
2300
|
+
|
2301
|
+
if (!NIL_P(scheduler)) {
|
2302
|
+
return rb_io_wait(io, events, timeout);
|
2303
|
+
}
|
2304
|
+
#endif
|
2305
|
+
return pg_rb_thread_io_wait(io, events, timeout);
|
2313
2306
|
}
|
2314
2307
|
|
2308
|
+
#elif defined(HAVE_RB_IO_WAIT)
|
2309
|
+
|
2310
|
+
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
2311
|
+
#define pg_rb_io_wait rb_io_wait
|
2312
|
+
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
2313
|
+
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
2314
|
+
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
2315
|
+
|
2315
2316
|
#else
|
2317
|
+
/* For compat with ruby < 3.0 */
|
2318
|
+
|
2319
|
+
typedef enum {
|
2320
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
2321
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
2322
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
2323
|
+
} pg_rb_io_event_t;
|
2324
|
+
|
2325
|
+
static VALUE
|
2326
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2327
|
+
rb_io_t *fptr;
|
2328
|
+
struct timeval waittime;
|
2329
|
+
int res;
|
2330
|
+
|
2331
|
+
GetOpenFile((io), fptr);
|
2332
|
+
if( !NIL_P(timeout) ){
|
2333
|
+
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
2334
|
+
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
2335
|
+
}
|
2336
|
+
res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
2316
2337
|
|
2317
|
-
|
2338
|
+
return UINT2NUM(res);
|
2339
|
+
}
|
2340
|
+
#endif
|
2318
2341
|
|
2319
2342
|
static void *
|
2320
|
-
wait_socket_readable(
|
2343
|
+
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
2321
2344
|
{
|
2322
|
-
|
2323
|
-
int ret;
|
2345
|
+
VALUE ret;
|
2324
2346
|
void *retval;
|
2325
2347
|
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) );
|
2348
|
+
VALUE wait_timeout = Qnil;
|
2349
|
+
PGconn *conn = pg_get_pgconn(self);
|
2333
2350
|
|
2334
2351
|
if ( ptimeout ) {
|
2335
2352
|
gettimeofday(&currtime, NULL);
|
@@ -2340,27 +2357,26 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2340
2357
|
if ( ptimeout ) {
|
2341
2358
|
gettimeofday(&currtime, NULL);
|
2342
2359
|
timersub(&aborttime, &currtime, &waittime);
|
2360
|
+
wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
|
2343
2361
|
}
|
2344
2362
|
|
2345
2363
|
/* Is the given timeout valid? */
|
2346
2364
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2365
|
+
VALUE socket_io = pgconn_socket_io(self);
|
2347
2366
|
/* Wait for the socket to become readable before checking again */
|
2348
|
-
ret =
|
2367
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
2349
2368
|
} else {
|
2350
|
-
ret =
|
2351
|
-
}
|
2352
|
-
|
2353
|
-
if ( ret < 0 ){
|
2354
|
-
rb_sys_fail( "rb_wait_for_single_fd()" );
|
2369
|
+
ret = Qfalse;
|
2355
2370
|
}
|
2356
2371
|
|
2357
2372
|
/* Return false if the select() timed out */
|
2358
|
-
if ( ret ==
|
2373
|
+
if ( ret == Qfalse ){
|
2359
2374
|
return NULL;
|
2360
2375
|
}
|
2361
2376
|
|
2362
2377
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2363
2378
|
if ( PQconsumeInput(conn) == 0 ){
|
2379
|
+
pgconn_close_socket_io(self);
|
2364
2380
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2365
2381
|
}
|
2366
2382
|
}
|
@@ -2368,8 +2384,45 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2368
2384
|
return retval;
|
2369
2385
|
}
|
2370
2386
|
|
2387
|
+
/*
|
2388
|
+
* call-seq:
|
2389
|
+
* conn.flush() -> Boolean
|
2390
|
+
*
|
2391
|
+
* Attempts to flush any queued output data to the server.
|
2392
|
+
* Returns +true+ if data is successfully flushed, +false+
|
2393
|
+
* if not (can only return +false+ if connection is
|
2394
|
+
* nonblocking.
|
2395
|
+
* Raises PG::Error if some other failure occurred.
|
2396
|
+
*/
|
2397
|
+
static VALUE
|
2398
|
+
pgconn_async_flush(VALUE self)
|
2399
|
+
{
|
2400
|
+
while( pgconn_sync_flush(self) == Qfalse ){
|
2401
|
+
/* wait for the socket to become read- or write-ready */
|
2402
|
+
int events;
|
2403
|
+
VALUE socket_io = pgconn_socket_io(self);
|
2404
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
2371
2405
|
|
2372
|
-
|
2406
|
+
if (events & PG_RUBY_IO_READABLE)
|
2407
|
+
pgconn_consume_input(self);
|
2408
|
+
}
|
2409
|
+
return Qtrue;
|
2410
|
+
}
|
2411
|
+
|
2412
|
+
static VALUE
|
2413
|
+
pgconn_wait_for_flush( VALUE self ){
|
2414
|
+
if( !pg_get_connection_safe(self)->flush_data )
|
2415
|
+
return Qnil;
|
2416
|
+
|
2417
|
+
return pgconn_async_flush(self);
|
2418
|
+
}
|
2419
|
+
|
2420
|
+
static VALUE
|
2421
|
+
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2422
|
+
t_pg_connection *conn = pg_get_connection(self);
|
2423
|
+
conn->flush_data = RTEST(enabled);
|
2424
|
+
return enabled;
|
2425
|
+
}
|
2373
2426
|
|
2374
2427
|
static void *
|
2375
2428
|
notify_readable(PGconn *conn)
|
@@ -2408,7 +2461,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2408
2461
|
ptimeout = &timeout;
|
2409
2462
|
}
|
2410
2463
|
|
2411
|
-
pnotification = (PGnotify*) wait_socket_readable(
|
2464
|
+
pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
|
2412
2465
|
|
2413
2466
|
/* Return nil if the select timed out */
|
2414
2467
|
if ( !pnotification ) return Qnil;
|
@@ -2429,28 +2482,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2429
2482
|
}
|
2430
2483
|
|
2431
2484
|
|
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
2485
|
static VALUE
|
2453
|
-
|
2486
|
+
pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
2454
2487
|
{
|
2455
2488
|
int ret;
|
2456
2489
|
int len;
|
@@ -2467,13 +2500,11 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2467
2500
|
if( NIL_P(this->encoder_for_put_copy_data) ){
|
2468
2501
|
buffer = value;
|
2469
2502
|
} else {
|
2470
|
-
p_coder =
|
2503
|
+
p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
|
2471
2504
|
}
|
2472
|
-
} else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
|
2473
|
-
Data_Get_Struct( encoder, t_pg_coder, p_coder );
|
2474
2505
|
} else {
|
2475
|
-
|
2476
|
-
|
2506
|
+
/* Check argument type and use argument encoder */
|
2507
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
|
2477
2508
|
}
|
2478
2509
|
|
2479
2510
|
if( p_coder ){
|
@@ -2507,22 +2538,8 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2507
2538
|
return (ret) ? Qtrue : Qfalse;
|
2508
2539
|
}
|
2509
2540
|
|
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
2541
|
static VALUE
|
2525
|
-
|
2542
|
+
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2526
2543
|
{
|
2527
2544
|
VALUE str;
|
2528
2545
|
VALUE error;
|
@@ -2544,27 +2561,8 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2544
2561
|
return (ret) ? Qtrue : Qfalse;
|
2545
2562
|
}
|
2546
2563
|
|
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
2564
|
static VALUE
|
2567
|
-
|
2565
|
+
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2568
2566
|
{
|
2569
2567
|
VALUE async_in;
|
2570
2568
|
VALUE error;
|
@@ -2579,13 +2577,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2579
2577
|
|
2580
2578
|
if( NIL_P(decoder) ){
|
2581
2579
|
if( !NIL_P(this->decoder_for_get_copy_data) ){
|
2582
|
-
p_coder =
|
2580
|
+
p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
|
2583
2581
|
}
|
2584
|
-
} else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
|
2585
|
-
Data_Get_Struct( decoder, t_pg_coder, p_coder );
|
2586
2582
|
} else {
|
2587
|
-
|
2588
|
-
|
2583
|
+
/* Check argument type and use argument decoder */
|
2584
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
2589
2585
|
}
|
2590
2586
|
|
2591
2587
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
@@ -2830,7 +2826,7 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2830
2826
|
* call-seq:
|
2831
2827
|
* conn.set_notice_processor {|message| ... } -> Proc
|
2832
2828
|
*
|
2833
|
-
* See #set_notice_receiver for the
|
2829
|
+
* See #set_notice_receiver for the description of what this and the
|
2834
2830
|
* notice_processor methods do.
|
2835
2831
|
*
|
2836
2832
|
* This function takes a new block to act as the notice processor and returns
|
@@ -2884,12 +2880,14 @@ pgconn_get_client_encoding(VALUE self)
|
|
2884
2880
|
|
2885
2881
|
/*
|
2886
2882
|
* call-seq:
|
2887
|
-
* conn.
|
2883
|
+
* conn.sync_set_client_encoding( encoding )
|
2888
2884
|
*
|
2889
|
-
*
|
2885
|
+
* This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
|
2886
|
+
* See #async_exec for the differences between the two API variants.
|
2887
|
+
* 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
2888
|
*/
|
2891
2889
|
static VALUE
|
2892
|
-
|
2890
|
+
pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
2893
2891
|
{
|
2894
2892
|
PGconn *conn = pg_get_pgconn( self );
|
2895
2893
|
|
@@ -2903,49 +2901,6 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2903
2901
|
return Qnil;
|
2904
2902
|
}
|
2905
2903
|
|
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
2904
|
|
2950
2905
|
/*
|
2951
2906
|
* call-seq:
|
@@ -3020,10 +2975,8 @@ get_result_readable(PGconn *conn)
|
|
3020
2975
|
* If +true+ is returned, +conn.is_busy+ will return +false+
|
3021
2976
|
* and +conn.get_result+ will not block.
|
3022
2977
|
*/
|
3023
|
-
|
2978
|
+
VALUE
|
3024
2979
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
3025
|
-
PGconn *conn = pg_get_pgconn( self );
|
3026
|
-
|
3027
2980
|
struct timeval timeout;
|
3028
2981
|
struct timeval *ptimeout = NULL;
|
3029
2982
|
VALUE timeout_in;
|
@@ -3037,7 +2990,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3037
2990
|
ptimeout = &timeout;
|
3038
2991
|
}
|
3039
2992
|
|
3040
|
-
ret = wait_socket_readable(
|
2993
|
+
ret = wait_socket_readable( self, ptimeout, get_result_readable);
|
3041
2994
|
|
3042
2995
|
if( !ret )
|
3043
2996
|
return Qfalse;
|
@@ -3046,6 +2999,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3046
2999
|
}
|
3047
3000
|
|
3048
3001
|
|
3002
|
+
/*
|
3003
|
+
* call-seq:
|
3004
|
+
* conn.sync_get_last_result( ) -> PG::Result
|
3005
|
+
*
|
3006
|
+
* This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
|
3007
|
+
* See #async_exec for the differences between the two API variants.
|
3008
|
+
* 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.
|
3009
|
+
*/
|
3010
|
+
static VALUE
|
3011
|
+
pgconn_sync_get_last_result(VALUE self)
|
3012
|
+
{
|
3013
|
+
PGconn *conn = pg_get_pgconn(self);
|
3014
|
+
VALUE rb_pgresult = Qnil;
|
3015
|
+
PGresult *cur, *prev;
|
3016
|
+
|
3017
|
+
|
3018
|
+
cur = prev = NULL;
|
3019
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3020
|
+
int status;
|
3021
|
+
|
3022
|
+
if (prev) PQclear(prev);
|
3023
|
+
prev = cur;
|
3024
|
+
|
3025
|
+
status = PQresultStatus(cur);
|
3026
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
3027
|
+
break;
|
3028
|
+
}
|
3029
|
+
|
3030
|
+
if (prev) {
|
3031
|
+
rb_pgresult = pg_new_result( prev, self );
|
3032
|
+
pg_result_check(rb_pgresult);
|
3033
|
+
}
|
3034
|
+
|
3035
|
+
return rb_pgresult;
|
3036
|
+
}
|
3037
|
+
|
3049
3038
|
/*
|
3050
3039
|
* call-seq:
|
3051
3040
|
* conn.get_last_result( ) -> PG::Result
|
@@ -3056,27 +3045,36 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3056
3045
|
* returns the last non-NULL result, or +nil+ if no
|
3057
3046
|
* results are available.
|
3058
3047
|
*
|
3048
|
+
* If the last result contains a bad result_status, an
|
3049
|
+
* appropriate exception is raised.
|
3050
|
+
*
|
3059
3051
|
* This function is similar to #get_result
|
3060
3052
|
* except that it is designed to get one and only
|
3061
|
-
* one result.
|
3053
|
+
* one result and that it checks the result state.
|
3062
3054
|
*/
|
3063
3055
|
static VALUE
|
3064
|
-
|
3056
|
+
pgconn_async_get_last_result(VALUE self)
|
3065
3057
|
{
|
3066
3058
|
PGconn *conn = pg_get_pgconn(self);
|
3067
3059
|
VALUE rb_pgresult = Qnil;
|
3068
3060
|
PGresult *cur, *prev;
|
3069
3061
|
|
3070
|
-
|
3071
|
-
|
3072
|
-
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3062
|
+
cur = prev = NULL;
|
3063
|
+
for(;;) {
|
3073
3064
|
int status;
|
3074
3065
|
|
3066
|
+
/* wait for input (without blocking) before reading each result */
|
3067
|
+
wait_socket_readable(self, NULL, get_result_readable);
|
3068
|
+
|
3069
|
+
cur = gvl_PQgetResult(conn);
|
3070
|
+
if (cur == NULL)
|
3071
|
+
break;
|
3072
|
+
|
3075
3073
|
if (prev) PQclear(prev);
|
3076
3074
|
prev = cur;
|
3077
3075
|
|
3078
3076
|
status = PQresultStatus(cur);
|
3079
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
3077
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
3080
3078
|
break;
|
3081
3079
|
}
|
3082
3080
|
|
@@ -3100,22 +3098,60 @@ static VALUE
|
|
3100
3098
|
pgconn_discard_results(VALUE self)
|
3101
3099
|
{
|
3102
3100
|
PGconn *conn = pg_get_pgconn(self);
|
3101
|
+
VALUE socket_io;
|
3103
3102
|
|
3104
|
-
|
3105
|
-
|
3106
|
-
|
3103
|
+
if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
|
3104
|
+
return Qnil;
|
3105
|
+
}
|
3106
|
+
|
3107
|
+
socket_io = pgconn_socket_io(self);
|
3108
|
+
|
3109
|
+
for(;;) {
|
3110
|
+
PGresult *cur;
|
3111
|
+
int status;
|
3112
|
+
|
3113
|
+
/* pgconn_block() raises an exception in case of errors.
|
3114
|
+
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
3115
|
+
*/
|
3116
|
+
while( gvl_PQisBusy(conn) ){
|
3117
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3118
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
3119
|
+
pgconn_close_socket_io(self);
|
3120
|
+
return Qfalse;
|
3121
|
+
}
|
3122
|
+
}
|
3123
|
+
|
3124
|
+
cur = gvl_PQgetResult(conn);
|
3125
|
+
if( cur == NULL) break;
|
3126
|
+
|
3127
|
+
status = PQresultStatus(cur);
|
3107
3128
|
PQclear(cur);
|
3108
3129
|
if (status == PGRES_COPY_IN){
|
3109
3130
|
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
3110
3131
|
}
|
3111
3132
|
if (status == PGRES_COPY_OUT){
|
3112
|
-
|
3113
|
-
|
3114
|
-
|
3133
|
+
for(;;) {
|
3134
|
+
char *buffer = NULL;
|
3135
|
+
int st = gvl_PQgetCopyData(conn, &buffer, 1);
|
3136
|
+
if( st == 0 ) {
|
3137
|
+
/* would block -> wait for readable data */
|
3138
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3139
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
3140
|
+
pgconn_close_socket_io(self);
|
3141
|
+
return Qfalse;
|
3142
|
+
}
|
3143
|
+
} else if( st > 0 ) {
|
3144
|
+
/* some data retrieved -> discard it */
|
3145
|
+
PQfreemem(buffer);
|
3146
|
+
} else {
|
3147
|
+
/* no more data */
|
3148
|
+
break;
|
3149
|
+
}
|
3150
|
+
}
|
3115
3151
|
}
|
3116
3152
|
}
|
3117
3153
|
|
3118
|
-
return
|
3154
|
+
return Qtrue;
|
3119
3155
|
}
|
3120
3156
|
|
3121
3157
|
/*
|
@@ -3138,6 +3174,7 @@ pgconn_discard_results(VALUE self)
|
|
3138
3174
|
* #exec is an alias for #async_exec which is almost identical to #sync_exec .
|
3139
3175
|
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
3140
3176
|
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
3177
|
+
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
3141
3178
|
* Both methods ensure that other threads can process while waiting for the server to
|
3142
3179
|
* complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
|
3143
3180
|
* This is most notably visible by a delayed reaction to Control+C.
|
@@ -3152,8 +3189,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3152
3189
|
|
3153
3190
|
pgconn_discard_results( self );
|
3154
3191
|
pgconn_send_query( argc, argv, self );
|
3155
|
-
|
3156
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3192
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3157
3193
|
|
3158
3194
|
if ( rb_block_given_p() ) {
|
3159
3195
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3182,7 +3218,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3182
3218
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3183
3219
|
* { :value => <string value>, :type => 0, :format => 0 }
|
3184
3220
|
*
|
3185
|
-
* PostgreSQL bind parameters are represented as $1, $
|
3221
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3186
3222
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
3187
3223
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3188
3224
|
*
|
@@ -3225,8 +3261,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
3225
3261
|
} else {
|
3226
3262
|
pgconn_send_query_params( argc, argv, self );
|
3227
3263
|
}
|
3228
|
-
|
3229
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3264
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3230
3265
|
|
3231
3266
|
if ( rb_block_given_p() ) {
|
3232
3267
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3252,7 +3287,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
3252
3287
|
*
|
3253
3288
|
* For example: "SELECT $1::int"
|
3254
3289
|
*
|
3255
|
-
* PostgreSQL bind parameters are represented as $1, $
|
3290
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3256
3291
|
* inside the SQL query.
|
3257
3292
|
*
|
3258
3293
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
|
@@ -3264,8 +3299,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
3264
3299
|
|
3265
3300
|
pgconn_discard_results( self );
|
3266
3301
|
pgconn_send_prepare( argc, argv, self );
|
3267
|
-
|
3268
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3302
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3269
3303
|
|
3270
3304
|
if ( rb_block_given_p() ) {
|
3271
3305
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3292,7 +3326,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
3292
3326
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3293
3327
|
* { :value => <string value>, :format => 0 }
|
3294
3328
|
*
|
3295
|
-
* PostgreSQL bind parameters are represented as $1, $
|
3329
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3296
3330
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
3297
3331
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3298
3332
|
*
|
@@ -3318,8 +3352,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
3318
3352
|
|
3319
3353
|
pgconn_discard_results( self );
|
3320
3354
|
pgconn_send_query_prepared( argc, argv, self );
|
3321
|
-
|
3322
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3355
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3323
3356
|
|
3324
3357
|
if ( rb_block_given_p() ) {
|
3325
3358
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3343,8 +3376,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
3343
3376
|
|
3344
3377
|
pgconn_discard_results( self );
|
3345
3378
|
pgconn_send_describe_portal( self, portal );
|
3346
|
-
|
3347
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3379
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3348
3380
|
|
3349
3381
|
if ( rb_block_given_p() ) {
|
3350
3382
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3368,8 +3400,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
|
3368
3400
|
|
3369
3401
|
pgconn_discard_results( self );
|
3370
3402
|
pgconn_send_describe_prepared( self, stmt_name );
|
3371
|
-
|
3372
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3403
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3373
3404
|
|
3374
3405
|
if ( rb_block_given_p() ) {
|
3375
3406
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3457,6 +3488,126 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
3457
3488
|
#endif
|
3458
3489
|
|
3459
3490
|
|
3491
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
3492
|
+
/*
|
3493
|
+
* call-seq:
|
3494
|
+
* conn.pipeline_status -> Integer
|
3495
|
+
*
|
3496
|
+
* Returns the current pipeline mode status of the libpq connection.
|
3497
|
+
*
|
3498
|
+
* PQpipelineStatus can return one of the following values:
|
3499
|
+
*
|
3500
|
+
* * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
|
3501
|
+
* * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
|
3502
|
+
* * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
3503
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
3504
|
+
*
|
3505
|
+
* Available since PostgreSQL-14
|
3506
|
+
*/
|
3507
|
+
static VALUE
|
3508
|
+
pgconn_pipeline_status(VALUE self)
|
3509
|
+
{
|
3510
|
+
int res = PQpipelineStatus(pg_get_pgconn(self));
|
3511
|
+
return INT2FIX(res);
|
3512
|
+
}
|
3513
|
+
|
3514
|
+
|
3515
|
+
/*
|
3516
|
+
* call-seq:
|
3517
|
+
* conn.enter_pipeline_mode -> nil
|
3518
|
+
*
|
3519
|
+
* Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
|
3520
|
+
*
|
3521
|
+
* 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.
|
3522
|
+
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
3523
|
+
*
|
3524
|
+
* Available since PostgreSQL-14
|
3525
|
+
*/
|
3526
|
+
static VALUE
|
3527
|
+
pgconn_enter_pipeline_mode(VALUE self)
|
3528
|
+
{
|
3529
|
+
PGconn *conn = pg_get_pgconn(self);
|
3530
|
+
int res = PQenterPipelineMode(conn);
|
3531
|
+
if( res == 1 ) {
|
3532
|
+
return Qnil;
|
3533
|
+
} else {
|
3534
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3535
|
+
}
|
3536
|
+
}
|
3537
|
+
|
3538
|
+
/*
|
3539
|
+
* call-seq:
|
3540
|
+
* conn.exit_pipeline_mode -> nil
|
3541
|
+
*
|
3542
|
+
* Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
|
3543
|
+
*
|
3544
|
+
* Takes no action if not in pipeline mode.
|
3545
|
+
* 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.
|
3546
|
+
*
|
3547
|
+
* Available since PostgreSQL-14
|
3548
|
+
*/
|
3549
|
+
static VALUE
|
3550
|
+
pgconn_exit_pipeline_mode(VALUE self)
|
3551
|
+
{
|
3552
|
+
PGconn *conn = pg_get_pgconn(self);
|
3553
|
+
int res = PQexitPipelineMode(conn);
|
3554
|
+
if( res == 1 ) {
|
3555
|
+
return Qnil;
|
3556
|
+
} else {
|
3557
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3558
|
+
}
|
3559
|
+
}
|
3560
|
+
|
3561
|
+
|
3562
|
+
/*
|
3563
|
+
* call-seq:
|
3564
|
+
* conn.pipeline_sync -> nil
|
3565
|
+
*
|
3566
|
+
* Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
|
3567
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
|
3568
|
+
*
|
3569
|
+
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
3570
|
+
*
|
3571
|
+
* Available since PostgreSQL-14
|
3572
|
+
*/
|
3573
|
+
static VALUE
|
3574
|
+
pgconn_pipeline_sync(VALUE self)
|
3575
|
+
{
|
3576
|
+
PGconn *conn = pg_get_pgconn(self);
|
3577
|
+
int res = PQpipelineSync(conn);
|
3578
|
+
if( res == 1 ) {
|
3579
|
+
return Qnil;
|
3580
|
+
} else {
|
3581
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3582
|
+
}
|
3583
|
+
}
|
3584
|
+
|
3585
|
+
/*
|
3586
|
+
* call-seq:
|
3587
|
+
* conn.pipeline_sync -> nil
|
3588
|
+
*
|
3589
|
+
* Sends a request for the server to flush its output buffer.
|
3590
|
+
*
|
3591
|
+
* 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.
|
3592
|
+
* This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
|
3593
|
+
* Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
|
3594
|
+
*
|
3595
|
+
* Available since PostgreSQL-14
|
3596
|
+
*/
|
3597
|
+
static VALUE
|
3598
|
+
pgconn_send_flush_request(VALUE self)
|
3599
|
+
{
|
3600
|
+
PGconn *conn = pg_get_pgconn(self);
|
3601
|
+
int res = PQsendFlushRequest(conn);
|
3602
|
+
if( res == 1 ) {
|
3603
|
+
return Qnil;
|
3604
|
+
} else {
|
3605
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3606
|
+
}
|
3607
|
+
}
|
3608
|
+
|
3609
|
+
#endif
|
3610
|
+
|
3460
3611
|
/**************************************************************************
|
3461
3612
|
* LARGE OBJECT SUPPORT
|
3462
3613
|
**************************************************************************/
|
@@ -3801,11 +3952,11 @@ static VALUE
|
|
3801
3952
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3802
3953
|
{
|
3803
3954
|
if (NIL_P(enc)) {
|
3804
|
-
|
3955
|
+
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3805
3956
|
return enc;
|
3806
3957
|
}
|
3807
3958
|
else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
|
3808
|
-
|
3959
|
+
pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
3809
3960
|
return enc;
|
3810
3961
|
}
|
3811
3962
|
else {
|
@@ -3843,16 +3994,33 @@ pgconn_external_encoding(VALUE self)
|
|
3843
3994
|
return rb_enc_from_encoding( enc );
|
3844
3995
|
}
|
3845
3996
|
|
3997
|
+
/*
|
3998
|
+
* call-seq:
|
3999
|
+
* conn.set_client_encoding( encoding )
|
4000
|
+
*
|
4001
|
+
* Sets the client encoding to the _encoding_ String.
|
4002
|
+
*/
|
4003
|
+
static VALUE
|
4004
|
+
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
4005
|
+
{
|
4006
|
+
VALUE query_format, query;
|
4007
|
+
|
4008
|
+
Check_Type(encname, T_STRING);
|
4009
|
+
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4010
|
+
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
4011
|
+
|
4012
|
+
pgconn_async_exec(1, &query, self);
|
4013
|
+
pgconn_set_internal_encoding_index( self );
|
4014
|
+
|
4015
|
+
return Qnil;
|
4016
|
+
}
|
3846
4017
|
|
3847
4018
|
static VALUE
|
3848
4019
|
pgconn_set_client_encoding_async1( VALUE args )
|
3849
4020
|
{
|
3850
4021
|
VALUE self = ((VALUE*)args)[0];
|
3851
4022
|
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);
|
4023
|
+
pgconn_async_set_client_encoding(self, encname);
|
3856
4024
|
return 0;
|
3857
4025
|
}
|
3858
4026
|
|
@@ -3867,9 +4035,9 @@ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
|
|
3867
4035
|
|
3868
4036
|
|
3869
4037
|
static VALUE
|
3870
|
-
pgconn_set_client_encoding_async( VALUE self,
|
4038
|
+
pgconn_set_client_encoding_async( VALUE self, VALUE encname )
|
3871
4039
|
{
|
3872
|
-
VALUE args[] = { self,
|
4040
|
+
VALUE args[] = { self, encname };
|
3873
4041
|
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
3874
4042
|
}
|
3875
4043
|
|
@@ -3891,10 +4059,9 @@ pgconn_set_default_encoding( VALUE self )
|
|
3891
4059
|
|
3892
4060
|
if (( enc = rb_default_internal_encoding() )) {
|
3893
4061
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3894
|
-
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
4062
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
3895
4063
|
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
3896
4064
|
encname, PQerrorMessage(conn) );
|
3897
|
-
pgconn_set_internal_encoding_index( self );
|
3898
4065
|
return rb_enc_from_encoding( enc );
|
3899
4066
|
} else {
|
3900
4067
|
pgconn_set_internal_encoding_index( self );
|
@@ -3916,12 +4083,12 @@ static VALUE
|
|
3916
4083
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
3917
4084
|
{
|
3918
4085
|
t_pg_connection *this = pg_get_connection( self );
|
4086
|
+
t_typemap *tm;
|
4087
|
+
UNUSED(tm);
|
4088
|
+
|
4089
|
+
/* Check type of method param */
|
4090
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
3919
4091
|
|
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
4092
|
this->type_map_for_queries = typemap;
|
3926
4093
|
|
3927
4094
|
return typemap;
|
@@ -3956,12 +4123,10 @@ static VALUE
|
|
3956
4123
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
3957
4124
|
{
|
3958
4125
|
t_pg_connection *this = pg_get_connection( self );
|
4126
|
+
t_typemap *tm;
|
4127
|
+
UNUSED(tm);
|
3959
4128
|
|
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);
|
4129
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
3965
4130
|
this->type_map_for_results = typemap;
|
3966
4131
|
|
3967
4132
|
return typemap;
|
@@ -3996,20 +4161,19 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
3996
4161
|
*
|
3997
4162
|
*/
|
3998
4163
|
static VALUE
|
3999
|
-
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE
|
4164
|
+
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
4000
4165
|
{
|
4001
4166
|
t_pg_connection *this = pg_get_connection( self );
|
4002
4167
|
|
4003
|
-
if(
|
4004
|
-
|
4005
|
-
|
4006
|
-
|
4007
|
-
|
4008
|
-
Check_Type(typemap, T_DATA);
|
4168
|
+
if( encoder != Qnil ){
|
4169
|
+
t_pg_coder *co;
|
4170
|
+
UNUSED(co);
|
4171
|
+
/* Check argument type */
|
4172
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4009
4173
|
}
|
4010
|
-
this->encoder_for_put_copy_data =
|
4174
|
+
this->encoder_for_put_copy_data = encoder;
|
4011
4175
|
|
4012
|
-
return
|
4176
|
+
return encoder;
|
4013
4177
|
}
|
4014
4178
|
|
4015
4179
|
/*
|
@@ -4045,20 +4209,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
4045
4209
|
*
|
4046
4210
|
*/
|
4047
4211
|
static VALUE
|
4048
|
-
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE
|
4212
|
+
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
4049
4213
|
{
|
4050
4214
|
t_pg_connection *this = pg_get_connection( self );
|
4051
4215
|
|
4052
|
-
if(
|
4053
|
-
|
4054
|
-
|
4055
|
-
|
4056
|
-
|
4057
|
-
Check_Type(typemap, T_DATA);
|
4216
|
+
if( decoder != Qnil ){
|
4217
|
+
t_pg_coder *co;
|
4218
|
+
UNUSED(co);
|
4219
|
+
/* Check argument type */
|
4220
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4058
4221
|
}
|
4059
|
-
this->decoder_for_get_copy_data =
|
4222
|
+
this->decoder_for_get_copy_data = decoder;
|
4060
4223
|
|
4061
|
-
return
|
4224
|
+
return decoder;
|
4062
4225
|
}
|
4063
4226
|
|
4064
4227
|
/*
|
@@ -4141,6 +4304,7 @@ void
|
|
4141
4304
|
init_pg_connection()
|
4142
4305
|
{
|
4143
4306
|
s_id_encode = rb_intern("encode");
|
4307
|
+
s_id_autoclose_set = rb_intern("autoclose=");
|
4144
4308
|
sym_type = ID2SYM(rb_intern("type"));
|
4145
4309
|
sym_format = ID2SYM(rb_intern("format"));
|
4146
4310
|
sym_value = ID2SYM(rb_intern("value"));
|
@@ -4156,10 +4320,6 @@ init_pg_connection()
|
|
4156
4320
|
/****** PG::Connection CLASS METHODS ******/
|
4157
4321
|
rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
|
4158
4322
|
|
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
4323
|
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
4164
4324
|
SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
|
4165
4325
|
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
@@ -4168,14 +4328,14 @@ init_pg_connection()
|
|
4168
4328
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4169
4329
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4170
4330
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4171
|
-
rb_define_singleton_method(rb_cPGconn, "
|
4331
|
+
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
4332
|
+
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
4172
4333
|
|
4173
4334
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
4174
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
4175
4335
|
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
4176
4336
|
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
4177
4337
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
4178
|
-
rb_define_method(rb_cPGconn, "
|
4338
|
+
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
4179
4339
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
4180
4340
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4181
4341
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
@@ -4187,9 +4347,7 @@ init_pg_connection()
|
|
4187
4347
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
4188
4348
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
4189
4349
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
4190
|
-
#ifdef HAVE_PQCONNINFO
|
4191
4350
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|
4192
|
-
#endif
|
4193
4351
|
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
4194
4352
|
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
4195
4353
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
@@ -4200,17 +4358,18 @@ init_pg_connection()
|
|
4200
4358
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
4201
4359
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
4202
4360
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4361
|
+
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
4203
4362
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
4204
4363
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
4205
4364
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
4206
4365
|
|
4207
4366
|
/****** 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",
|
4367
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
|
4368
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
|
4369
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
|
4370
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
4371
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
4372
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
4214
4373
|
|
4215
4374
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
4216
4375
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
@@ -4243,25 +4402,26 @@ init_pg_connection()
|
|
4243
4402
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4244
4403
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4245
4404
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4246
|
-
rb_define_method(rb_cPGconn, "
|
4405
|
+
rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
|
4247
4406
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
4248
4407
|
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",
|
4408
|
+
rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
|
4409
|
+
rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
|
4410
|
+
rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
|
4411
|
+
rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
|
4412
|
+
rb_define_alias(rb_cPGconn, "async_flush", "flush");
|
4253
4413
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
4254
4414
|
|
4255
4415
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4256
|
-
rb_define_method(rb_cPGconn, "
|
4416
|
+
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
4257
4417
|
|
4258
4418
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
4259
4419
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
4260
4420
|
|
4261
4421
|
/****** PG::Connection INSTANCE METHODS: COPY ******/
|
4262
|
-
rb_define_method(rb_cPGconn, "
|
4263
|
-
rb_define_method(rb_cPGconn, "
|
4264
|
-
rb_define_method(rb_cPGconn, "
|
4422
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
|
4423
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
|
4424
|
+
rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
|
4265
4425
|
|
4266
4426
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
4267
4427
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
@@ -4277,16 +4437,20 @@ init_pg_connection()
|
|
4277
4437
|
|
4278
4438
|
/****** PG::Connection INSTANCE METHODS: Other ******/
|
4279
4439
|
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
4280
|
-
rb_define_method(rb_cPGconn, "
|
4440
|
+
rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
|
4441
|
+
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
|
4442
|
+
rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
|
4281
4443
|
rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
|
4282
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
4283
4444
|
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
4445
|
+
rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
|
4284
4446
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
4285
4447
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
4286
4448
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4287
|
-
rb_define_method(rb_cPGconn, "
|
4449
|
+
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
4450
|
+
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
4451
|
+
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
4288
4452
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4289
|
-
rb_define_method(rb_cPGconn, "
|
4453
|
+
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
4290
4454
|
#endif
|
4291
4455
|
|
4292
4456
|
#ifdef HAVE_PQSSLATTRIBUTE
|
@@ -4295,6 +4459,14 @@ init_pg_connection()
|
|
4295
4459
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4296
4460
|
#endif
|
4297
4461
|
|
4462
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
4463
|
+
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
4464
|
+
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
4465
|
+
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
4466
|
+
rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
|
4467
|
+
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
4468
|
+
#endif
|
4469
|
+
|
4298
4470
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
4299
4471
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
4300
4472
|
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|