pg 1.2.3-x86-mingw32 → 1.3.0.rc4-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +130 -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 +77 -7
- data/Manifest.txt +0 -1
- data/README.rdoc +7 -6
- data/Rakefile +27 -138
- data/Rakefile.cross +6 -5
- data/certs/ged.pem +24 -0
- data/ext/errorcodes.def +8 -0
- data/ext/errorcodes.txt +3 -1
- data/ext/extconf.rb +91 -19
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +59 -4
- data/ext/pg.h +18 -1
- data/ext/pg_coder.c +82 -28
- data/ext/pg_connection.c +676 -492
- data/ext/pg_copy_coder.c +45 -16
- data/ext/pg_record_coder.c +39 -11
- data/ext/pg_result.c +61 -31
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +6 -6
- data/ext/pg_tuple.c +47 -21
- data/ext/pg_type_map.c +41 -8
- data/ext/pg_type_map_all_strings.c +14 -1
- data/ext/pg_type_map_by_class.c +49 -24
- data/ext/pg_type_map_by_column.c +64 -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/2.5/pg_ext.so +0 -0
- data/lib/2.6/pg_ext.so +0 -0
- data/lib/2.7/pg_ext.so +0 -0
- data/lib/3.0/pg_ext.so +0 -0
- data/lib/3.1/pg_ext.so +0 -0
- 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 +587 -58
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +40 -27
- data/lib/x86-mingw32/libpq.dll +0 -0
- 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/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +106 -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 +93 -233
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/lib/2.2/pg_ext.so +0 -0
- data/lib/2.3/pg_ext.so +0 -0
- data/lib/2.4/pg_ext.so +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,11 @@ pgconn_connect_poll(VALUE self)
|
|
523
474
|
{
|
524
475
|
PostgresPollingStatusType status;
|
525
476
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
477
|
+
|
478
|
+
if ( status == PGRES_POLLING_FAILED ) {
|
479
|
+
pgconn_close_socket_io(self);
|
480
|
+
}
|
481
|
+
|
526
482
|
return INT2FIX((int)status);
|
527
483
|
}
|
528
484
|
|
@@ -559,15 +515,8 @@ pgconn_finished_p( VALUE self )
|
|
559
515
|
}
|
560
516
|
|
561
517
|
|
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
518
|
static VALUE
|
570
|
-
|
519
|
+
pgconn_sync_reset( VALUE self )
|
571
520
|
{
|
572
521
|
pgconn_close_socket_io( self );
|
573
522
|
gvl_PQreset( pg_get_pgconn(self) );
|
@@ -606,6 +555,11 @@ pgconn_reset_poll(VALUE self)
|
|
606
555
|
{
|
607
556
|
PostgresPollingStatusType status;
|
608
557
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
558
|
+
|
559
|
+
if ( status == PGRES_POLLING_FAILED ) {
|
560
|
+
pgconn_close_socket_io(self);
|
561
|
+
}
|
562
|
+
|
609
563
|
return INT2FIX((int)status);
|
610
564
|
}
|
611
565
|
|
@@ -676,21 +630,19 @@ static VALUE
|
|
676
630
|
pgconn_port(VALUE self)
|
677
631
|
{
|
678
632
|
char* port = PQport(pg_get_pgconn(self));
|
679
|
-
return INT2NUM(
|
633
|
+
return INT2NUM(atoi(port));
|
680
634
|
}
|
681
635
|
|
682
636
|
/*
|
683
637
|
* call-seq:
|
684
638
|
* conn.tty()
|
685
639
|
*
|
686
|
-
*
|
640
|
+
* Obsolete function.
|
687
641
|
*/
|
688
642
|
static VALUE
|
689
643
|
pgconn_tty(VALUE self)
|
690
644
|
{
|
691
|
-
|
692
|
-
if (!tty) return Qnil;
|
693
|
-
return rb_str_new2(tty);
|
645
|
+
return rb_str_new2("");
|
694
646
|
}
|
695
647
|
|
696
648
|
/*
|
@@ -708,7 +660,6 @@ pgconn_options(VALUE self)
|
|
708
660
|
}
|
709
661
|
|
710
662
|
|
711
|
-
#ifdef HAVE_PQCONNINFO
|
712
663
|
/*
|
713
664
|
* call-seq:
|
714
665
|
* conn.conninfo -> hash
|
@@ -728,14 +679,17 @@ pgconn_conninfo( VALUE self )
|
|
728
679
|
|
729
680
|
return array;
|
730
681
|
}
|
731
|
-
#endif
|
732
682
|
|
733
683
|
|
734
684
|
/*
|
735
685
|
* call-seq:
|
736
686
|
* conn.status()
|
737
687
|
*
|
738
|
-
* Returns status of connection
|
688
|
+
* Returns the status of the connection, which is one:
|
689
|
+
* PG::Constants::CONNECTION_OK
|
690
|
+
* PG::Constants::CONNECTION_BAD
|
691
|
+
*
|
692
|
+
* ... and other constants of kind PG::Constants::CONNECTION_*
|
739
693
|
*/
|
740
694
|
static VALUE
|
741
695
|
pgconn_status(VALUE self)
|
@@ -823,7 +777,10 @@ pgconn_server_version(VALUE self)
|
|
823
777
|
* call-seq:
|
824
778
|
* conn.error_message -> String
|
825
779
|
*
|
826
|
-
* Returns the error message
|
780
|
+
* Returns the error message most recently generated by an operation on the connection.
|
781
|
+
*
|
782
|
+
* Nearly all libpq functions will set a message for conn.error_message if they fail.
|
783
|
+
* Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
|
827
784
|
*/
|
828
785
|
static VALUE
|
829
786
|
pgconn_error_message(VALUE self)
|
@@ -878,8 +835,8 @@ pgconn_socket_io(VALUE self)
|
|
878
835
|
{
|
879
836
|
int sd;
|
880
837
|
int ruby_sd;
|
881
|
-
ID id_autoclose = rb_intern("autoclose=");
|
882
838
|
t_pg_connection *this = pg_get_connection_safe( self );
|
839
|
+
VALUE cSocket;
|
883
840
|
VALUE socket_io = this->socket_io;
|
884
841
|
|
885
842
|
if ( !RTEST(socket_io) ) {
|
@@ -888,15 +845,19 @@ pgconn_socket_io(VALUE self)
|
|
888
845
|
|
889
846
|
#ifdef _WIN32
|
890
847
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
848
|
+
if( ruby_sd == -1 ){
|
849
|
+
rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
|
850
|
+
}
|
891
851
|
this->ruby_sd = ruby_sd;
|
892
852
|
#else
|
893
853
|
ruby_sd = sd;
|
894
854
|
#endif
|
895
855
|
|
896
|
-
|
856
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
857
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
897
858
|
|
898
859
|
/* Disable autoclose feature */
|
899
|
-
rb_funcall( socket_io,
|
860
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
900
861
|
|
901
862
|
this->socket_io = socket_io;
|
902
863
|
}
|
@@ -918,6 +879,51 @@ pgconn_backend_pid(VALUE self)
|
|
918
879
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
919
880
|
}
|
920
881
|
|
882
|
+
typedef struct
|
883
|
+
{
|
884
|
+
struct sockaddr_storage addr;
|
885
|
+
socklen_t salen;
|
886
|
+
} SockAddr;
|
887
|
+
|
888
|
+
/* Copy of struct pg_cancel from libpq-int.h
|
889
|
+
*
|
890
|
+
* See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
|
891
|
+
*/
|
892
|
+
struct pg_cancel
|
893
|
+
{
|
894
|
+
SockAddr raddr; /* Remote address */
|
895
|
+
int be_pid; /* PID of backend --- needed for cancels */
|
896
|
+
int be_key; /* key of backend --- needed for cancels */
|
897
|
+
};
|
898
|
+
|
899
|
+
/*
|
900
|
+
* call-seq:
|
901
|
+
* conn.backend_key() -> Integer
|
902
|
+
*
|
903
|
+
* Returns the key of the backend server process for this connection.
|
904
|
+
* This key can be used to cancel queries on the server.
|
905
|
+
*/
|
906
|
+
static VALUE
|
907
|
+
pgconn_backend_key(VALUE self)
|
908
|
+
{
|
909
|
+
int be_key;
|
910
|
+
struct pg_cancel *cancel;
|
911
|
+
PGconn *conn = pg_get_pgconn(self);
|
912
|
+
|
913
|
+
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
914
|
+
if(cancel == NULL)
|
915
|
+
rb_raise(rb_ePGerror,"Invalid connection!");
|
916
|
+
|
917
|
+
if( cancel->be_pid != PQbackendPID(conn) )
|
918
|
+
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
919
|
+
|
920
|
+
be_key = cancel->be_key;
|
921
|
+
|
922
|
+
PQfreeCancel(cancel);
|
923
|
+
|
924
|
+
return INT2NUM(be_key);
|
925
|
+
}
|
926
|
+
|
921
927
|
/*
|
922
928
|
* call-seq:
|
923
929
|
* conn.connection_needs_password() -> Boolean
|
@@ -948,7 +954,7 @@ pgconn_connection_used_password(VALUE self)
|
|
948
954
|
/* :TODO: get_ssl */
|
949
955
|
|
950
956
|
|
951
|
-
static VALUE
|
957
|
+
static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
952
958
|
|
953
959
|
/*
|
954
960
|
* call-seq:
|
@@ -962,11 +968,11 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
962
968
|
* However #async_exec has two advantages:
|
963
969
|
*
|
964
970
|
* 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
|
-
*
|
971
|
+
* 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
|
972
|
+
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
967
973
|
*/
|
968
974
|
static VALUE
|
969
|
-
|
975
|
+
pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
970
976
|
{
|
971
977
|
t_pg_connection *this = pg_get_connection_safe( self );
|
972
978
|
PGresult *result = NULL;
|
@@ -987,7 +993,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
987
993
|
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
988
994
|
|
989
995
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
990
|
-
return
|
996
|
+
return pgconn_sync_exec_params( argc, argv, self );
|
991
997
|
|
992
998
|
}
|
993
999
|
|
@@ -1019,7 +1025,7 @@ struct query_params_data {
|
|
1019
1025
|
* Filled by alloc_query_params()
|
1020
1026
|
*/
|
1021
1027
|
|
1022
|
-
/* Wraps the pointer of allocated memory, if function parameters
|
1028
|
+
/* Wraps the pointer of allocated memory, if function parameters don't
|
1023
1029
|
* fit in the memory_pool below.
|
1024
1030
|
*/
|
1025
1031
|
VALUE heap_pool;
|
@@ -1037,7 +1043,7 @@ struct query_params_data {
|
|
1037
1043
|
Oid *types;
|
1038
1044
|
|
1039
1045
|
/* This array takes the string values for the timeframe of the query,
|
1040
|
-
* if param value
|
1046
|
+
* if param value conversion is required
|
1041
1047
|
*/
|
1042
1048
|
VALUE gc_array;
|
1043
1049
|
|
@@ -1051,8 +1057,9 @@ struct query_params_data {
|
|
1051
1057
|
};
|
1052
1058
|
|
1053
1059
|
static void
|
1054
|
-
free_typecast_heap_chain(
|
1060
|
+
free_typecast_heap_chain(void *_chain_entry)
|
1055
1061
|
{
|
1062
|
+
struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
|
1056
1063
|
while(chain_entry){
|
1057
1064
|
struct linked_typecast_data *next = chain_entry->next;
|
1058
1065
|
xfree(chain_entry);
|
@@ -1060,6 +1067,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
|
|
1060
1067
|
}
|
1061
1068
|
}
|
1062
1069
|
|
1070
|
+
static const rb_data_type_t pg_typecast_buffer_type = {
|
1071
|
+
"PG::Connection typecast buffer chain",
|
1072
|
+
{
|
1073
|
+
(RUBY_DATA_FUNC) NULL,
|
1074
|
+
free_typecast_heap_chain,
|
1075
|
+
(size_t (*)(const void *))NULL,
|
1076
|
+
},
|
1077
|
+
0,
|
1078
|
+
0,
|
1079
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1080
|
+
};
|
1081
|
+
|
1063
1082
|
static char *
|
1064
1083
|
alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
1065
1084
|
{
|
@@ -1070,17 +1089,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
1070
1089
|
/* Did we already wrap a memory chain per T_DATA object? */
|
1071
1090
|
if( NIL_P( *typecast_heap_chain ) ){
|
1072
1091
|
/* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
|
1073
|
-
*typecast_heap_chain =
|
1092
|
+
*typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
|
1074
1093
|
allocated->next = NULL;
|
1075
1094
|
} else {
|
1076
1095
|
/* Append to the chain */
|
1077
|
-
allocated->next =
|
1078
|
-
|
1096
|
+
allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
|
1097
|
+
RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
|
1079
1098
|
}
|
1080
1099
|
|
1081
1100
|
return &allocated->data[0];
|
1082
1101
|
}
|
1083
1102
|
|
1103
|
+
static const rb_data_type_t pg_query_heap_pool_type = {
|
1104
|
+
"PG::Connection query heap pool",
|
1105
|
+
{
|
1106
|
+
(RUBY_DATA_FUNC) NULL,
|
1107
|
+
RUBY_TYPED_DEFAULT_FREE,
|
1108
|
+
(size_t (*)(const void *))NULL,
|
1109
|
+
},
|
1110
|
+
0,
|
1111
|
+
0,
|
1112
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1113
|
+
};
|
1084
1114
|
|
1085
1115
|
static int
|
1086
1116
|
alloc_query_params(struct query_params_data *paramsData)
|
@@ -1095,7 +1125,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1095
1125
|
|
1096
1126
|
Check_Type(paramsData->params, T_ARRAY);
|
1097
1127
|
|
1098
|
-
p_typemap =
|
1128
|
+
p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
|
1099
1129
|
p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
|
1100
1130
|
|
1101
1131
|
paramsData->heap_pool = Qnil;
|
@@ -1114,7 +1144,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1114
1144
|
/* Allocate one combined memory pool for all possible function parameters */
|
1115
1145
|
memory_pool = (char*)xmalloc( required_pool_size );
|
1116
1146
|
/* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
|
1117
|
-
paramsData->heap_pool =
|
1147
|
+
paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
|
1118
1148
|
required_pool_size = 0;
|
1119
1149
|
}else{
|
1120
1150
|
/* Use stack memory for function parameters */
|
@@ -1227,12 +1257,11 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1227
1257
|
/* Use default typemap for queries. It's type is checked when assigned. */
|
1228
1258
|
paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
|
1229
1259
|
}else{
|
1260
|
+
t_typemap *tm;
|
1261
|
+
UNUSED(tm);
|
1262
|
+
|
1230
1263
|
/* 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 );
|
1264
|
+
TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
|
1236
1265
|
}
|
1237
1266
|
}
|
1238
1267
|
|
@@ -1246,7 +1275,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1246
1275
|
* 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
1276
|
*/
|
1248
1277
|
static VALUE
|
1249
|
-
|
1278
|
+
pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
1250
1279
|
{
|
1251
1280
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1252
1281
|
PGresult *result = NULL;
|
@@ -1266,7 +1295,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1266
1295
|
*/
|
1267
1296
|
if ( NIL_P(paramsData.params) ) {
|
1268
1297
|
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
1269
|
-
return
|
1298
|
+
return pgconn_sync_exec( 1, argv, self );
|
1270
1299
|
}
|
1271
1300
|
pgconn_query_assign_typemap( self, ¶msData );
|
1272
1301
|
|
@@ -1297,7 +1326,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1297
1326
|
* It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
|
1298
1327
|
*/
|
1299
1328
|
static VALUE
|
1300
|
-
|
1329
|
+
pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
1301
1330
|
{
|
1302
1331
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1303
1332
|
PGresult *result = NULL;
|
@@ -1346,7 +1375,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1346
1375
|
* 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
1376
|
*/
|
1348
1377
|
static VALUE
|
1349
|
-
|
1378
|
+
pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
1350
1379
|
{
|
1351
1380
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1352
1381
|
PGresult *result = NULL;
|
@@ -1391,7 +1420,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1391
1420
|
* 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
1421
|
*/
|
1393
1422
|
static VALUE
|
1394
|
-
|
1423
|
+
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
1395
1424
|
{
|
1396
1425
|
PGresult *result;
|
1397
1426
|
VALUE rb_pgresult;
|
@@ -1419,7 +1448,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1419
1448
|
* 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
1449
|
*/
|
1421
1450
|
static VALUE
|
1422
|
-
|
1451
|
+
pgconn_sync_describe_portal(self, stmt_name)
|
1423
1452
|
VALUE self, stmt_name;
|
1424
1453
|
{
|
1425
1454
|
PGresult *result;
|
@@ -1454,6 +1483,9 @@ pgconn_describe_portal(self, stmt_name)
|
|
1454
1483
|
* * +PGRES_NONFATAL_ERROR+
|
1455
1484
|
* * +PGRES_FATAL_ERROR+
|
1456
1485
|
* * +PGRES_COPY_BOTH+
|
1486
|
+
* * +PGRES_SINGLE_TUPLE+
|
1487
|
+
* * +PGRES_PIPELINE_SYNC+
|
1488
|
+
* * +PGRES_PIPELINE_ABORTED+
|
1457
1489
|
*/
|
1458
1490
|
static VALUE
|
1459
1491
|
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
@@ -1750,6 +1782,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1750
1782
|
rb_iv_set(error, "@connection", self);
|
1751
1783
|
rb_exc_raise(error);
|
1752
1784
|
}
|
1785
|
+
pgconn_wait_for_flush( self );
|
1753
1786
|
return Qnil;
|
1754
1787
|
}
|
1755
1788
|
|
@@ -1779,7 +1812,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1779
1812
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1780
1813
|
* { :value => <string value>, :type => 0, :format => 0 }
|
1781
1814
|
*
|
1782
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1815
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1783
1816
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1784
1817
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1785
1818
|
*
|
@@ -1827,6 +1860,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1827
1860
|
rb_iv_set(error, "@connection", self);
|
1828
1861
|
rb_exc_raise(error);
|
1829
1862
|
}
|
1863
|
+
pgconn_wait_for_flush( self );
|
1830
1864
|
return Qnil;
|
1831
1865
|
}
|
1832
1866
|
|
@@ -1847,7 +1881,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1847
1881
|
*
|
1848
1882
|
* For example: "SELECT $1::int"
|
1849
1883
|
*
|
1850
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1884
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1851
1885
|
* inside the SQL query.
|
1852
1886
|
*/
|
1853
1887
|
static VALUE
|
@@ -1890,6 +1924,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1890
1924
|
rb_iv_set(error, "@connection", self);
|
1891
1925
|
rb_exc_raise(error);
|
1892
1926
|
}
|
1927
|
+
pgconn_wait_for_flush( self );
|
1893
1928
|
return Qnil;
|
1894
1929
|
}
|
1895
1930
|
|
@@ -1911,7 +1946,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1911
1946
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1912
1947
|
* { :value => <string value>, :format => 0 }
|
1913
1948
|
*
|
1914
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1949
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1915
1950
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1916
1951
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1917
1952
|
*
|
@@ -1941,7 +1976,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1941
1976
|
|
1942
1977
|
if(NIL_P(paramsData.params)) {
|
1943
1978
|
paramsData.params = rb_ary_new2(0);
|
1944
|
-
resultFormat = 0;
|
1945
1979
|
}
|
1946
1980
|
pgconn_query_assign_typemap( self, ¶msData );
|
1947
1981
|
|
@@ -1959,6 +1993,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1959
1993
|
rb_iv_set(error, "@connection", self);
|
1960
1994
|
rb_exc_raise(error);
|
1961
1995
|
}
|
1996
|
+
pgconn_wait_for_flush( self );
|
1962
1997
|
return Qnil;
|
1963
1998
|
}
|
1964
1999
|
|
@@ -1980,6 +2015,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1980
2015
|
rb_iv_set(error, "@connection", self);
|
1981
2016
|
rb_exc_raise(error);
|
1982
2017
|
}
|
2018
|
+
pgconn_wait_for_flush( self );
|
1983
2019
|
return Qnil;
|
1984
2020
|
}
|
1985
2021
|
|
@@ -2002,28 +2038,13 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
2002
2038
|
rb_iv_set(error, "@connection", self);
|
2003
2039
|
rb_exc_raise(error);
|
2004
2040
|
}
|
2041
|
+
pgconn_wait_for_flush( self );
|
2005
2042
|
return Qnil;
|
2006
2043
|
}
|
2007
2044
|
|
2008
2045
|
|
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
2046
|
static VALUE
|
2026
|
-
|
2047
|
+
pgconn_sync_get_result(VALUE self)
|
2027
2048
|
{
|
2028
2049
|
PGconn *conn = pg_get_pgconn(self);
|
2029
2050
|
PGresult *result;
|
@@ -2056,6 +2077,7 @@ pgconn_consume_input(self)
|
|
2056
2077
|
PGconn *conn = pg_get_pgconn(self);
|
2057
2078
|
/* returns 0 on error */
|
2058
2079
|
if(PQconsumeInput(conn) == 0) {
|
2080
|
+
pgconn_close_socket_io(self);
|
2059
2081
|
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
2060
2082
|
rb_iv_set(error, "@connection", self);
|
2061
2083
|
rb_exc_raise(error);
|
@@ -2068,7 +2090,7 @@ pgconn_consume_input(self)
|
|
2068
2090
|
* conn.is_busy() -> Boolean
|
2069
2091
|
*
|
2070
2092
|
* Returns +true+ if a command is busy, that is, if
|
2071
|
-
*
|
2093
|
+
* #get_result would block. Otherwise returns +false+.
|
2072
2094
|
*/
|
2073
2095
|
static VALUE
|
2074
2096
|
pgconn_is_busy(self)
|
@@ -2077,24 +2099,8 @@ pgconn_is_busy(self)
|
|
2077
2099
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2078
2100
|
}
|
2079
2101
|
|
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
2102
|
static VALUE
|
2097
|
-
|
2103
|
+
pgconn_sync_setnonblocking(self, state)
|
2098
2104
|
VALUE self, state;
|
2099
2105
|
{
|
2100
2106
|
int arg;
|
@@ -2116,33 +2122,15 @@ pgconn_setnonblocking(self, state)
|
|
2116
2122
|
}
|
2117
2123
|
|
2118
2124
|
|
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
2125
|
static VALUE
|
2127
|
-
|
2126
|
+
pgconn_sync_isnonblocking(self)
|
2128
2127
|
VALUE self;
|
2129
2128
|
{
|
2130
2129
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2131
2130
|
}
|
2132
2131
|
|
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
2132
|
static VALUE
|
2144
|
-
|
2145
|
-
VALUE self;
|
2133
|
+
pgconn_sync_flush(VALUE self)
|
2146
2134
|
{
|
2147
2135
|
PGconn *conn = pg_get_pgconn(self);
|
2148
2136
|
int ret;
|
@@ -2156,18 +2144,8 @@ pgconn_flush(self)
|
|
2156
2144
|
return (ret) ? Qfalse : Qtrue;
|
2157
2145
|
}
|
2158
2146
|
|
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
2147
|
static VALUE
|
2170
|
-
|
2148
|
+
pgconn_sync_cancel(VALUE self)
|
2171
2149
|
{
|
2172
2150
|
char errbuf[256];
|
2173
2151
|
PGcancel *cancel;
|
@@ -2178,7 +2156,7 @@ pgconn_cancel(VALUE self)
|
|
2178
2156
|
if(cancel == NULL)
|
2179
2157
|
rb_raise(rb_ePGerror,"Invalid connection!");
|
2180
2158
|
|
2181
|
-
ret = gvl_PQcancel(cancel, errbuf,
|
2159
|
+
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
2182
2160
|
if(ret == 1)
|
2183
2161
|
retval = Qnil;
|
2184
2162
|
else
|
@@ -2229,55 +2207,67 @@ pgconn_notifies(VALUE self)
|
|
2229
2207
|
return hash;
|
2230
2208
|
}
|
2231
2209
|
|
2232
|
-
|
2233
|
-
|
2234
|
-
/*
|
2235
|
-
*
|
2236
|
-
* instead of rb_wait_for_single_fd().
|
2210
|
+
#if defined(_WIN32)
|
2211
|
+
|
2212
|
+
/* We use a specialized implementation of rb_io_wait() on Windows.
|
2213
|
+
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
2237
2214
|
*/
|
2238
2215
|
|
2216
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2217
|
+
#include <ruby/fiber/scheduler.h>
|
2218
|
+
#endif
|
2219
|
+
|
2220
|
+
typedef enum {
|
2221
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
2222
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
2223
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
2224
|
+
} pg_rb_io_event_t;
|
2225
|
+
|
2239
2226
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2240
2227
|
|
2241
|
-
static
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2228
|
+
static VALUE
|
2229
|
+
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2230
|
+
rb_io_t *fptr;
|
2231
|
+
struct timeval ptimeout;
|
2232
|
+
|
2246
2233
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2247
2234
|
DWORD timeout_milisec = INFINITE;
|
2248
|
-
|
2249
|
-
WSAEVENT hEvent;
|
2235
|
+
HANDLE hEvent = WSACreateEvent();
|
2250
2236
|
|
2251
|
-
|
2252
|
-
|
2237
|
+
long rb_events = NUM2UINT(events);
|
2238
|
+
long w32_events = 0;
|
2239
|
+
DWORD wait_ret;
|
2253
2240
|
|
2254
|
-
|
2241
|
+
GetOpenFile((io), fptr);
|
2242
|
+
if( !NIL_P(timeout) ){
|
2243
|
+
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
2244
|
+
ptimeout.tv_usec = (time_t)(NUM2DBL(timeout) - (double)ptimeout.tv_sec);
|
2255
2245
|
|
2256
|
-
|
2257
|
-
|
2258
|
-
WSACloseEvent( hEvent );
|
2259
|
-
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2246
|
+
gettimeofday(&currtime, NULL);
|
2247
|
+
timeradd(&currtime, &ptimeout, &aborttime);
|
2260
2248
|
}
|
2261
2249
|
|
2262
|
-
if
|
2263
|
-
|
2264
|
-
|
2250
|
+
if(rb_events & PG_RUBY_IO_READABLE) {
|
2251
|
+
w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
2252
|
+
} else if(rb_events & PG_RUBY_IO_WRITABLE) {
|
2253
|
+
w32_events |= FD_WRITE | FD_CONNECT;
|
2254
|
+
} else if(rb_events & PG_RUBY_IO_PRIORITY) {
|
2255
|
+
w32_events |= FD_OOB;
|
2265
2256
|
}
|
2266
2257
|
|
2267
|
-
|
2268
|
-
if ( WSAEventSelect(
|
2258
|
+
for(;;) {
|
2259
|
+
if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
|
2269
2260
|
WSACloseEvent( hEvent );
|
2270
2261
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2271
2262
|
}
|
2272
2263
|
|
2273
|
-
if (
|
2264
|
+
if ( !NIL_P(timeout) ) {
|
2274
2265
|
gettimeofday(&currtime, NULL);
|
2275
2266
|
timersub(&aborttime, &currtime, &waittime);
|
2276
2267
|
timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
|
2277
2268
|
}
|
2278
2269
|
|
2279
|
-
|
2280
|
-
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2270
|
+
if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2281
2271
|
/* Wait for the socket to become readable before checking again */
|
2282
2272
|
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
2283
2273
|
} else {
|
@@ -2286,9 +2276,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2286
2276
|
|
2287
2277
|
if ( wait_ret == WAIT_TIMEOUT ) {
|
2288
2278
|
WSACloseEvent( hEvent );
|
2289
|
-
return
|
2279
|
+
return UINT2NUM(0);
|
2290
2280
|
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2281
|
+
WSACloseEvent( hEvent );
|
2291
2282
|
/* The event we were waiting for. */
|
2283
|
+
return UINT2NUM(rb_events);
|
2292
2284
|
} else if ( wait_ret == WAIT_OBJECT_0 + 1) {
|
2293
2285
|
/* This indicates interruption from timer thread, GC, exception
|
2294
2286
|
* from other threads etc... */
|
@@ -2300,36 +2292,75 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2300
2292
|
WSACloseEvent( hEvent );
|
2301
2293
|
rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2302
2294
|
}
|
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
2295
|
}
|
2296
|
+
}
|
2310
2297
|
|
2311
|
-
|
2312
|
-
|
2298
|
+
static VALUE
|
2299
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2300
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2301
|
+
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
2302
|
+
* Fortunatelly ruby-3.1 offers a C-API for it.
|
2303
|
+
*/
|
2304
|
+
VALUE scheduler = rb_fiber_scheduler_current();
|
2305
|
+
|
2306
|
+
if (!NIL_P(scheduler)) {
|
2307
|
+
return rb_io_wait(io, events, timeout);
|
2308
|
+
}
|
2309
|
+
#endif
|
2310
|
+
return pg_rb_thread_io_wait(io, events, timeout);
|
2313
2311
|
}
|
2314
2312
|
|
2313
|
+
#elif defined(HAVE_RB_IO_WAIT)
|
2314
|
+
|
2315
|
+
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
2316
|
+
#define pg_rb_io_wait rb_io_wait
|
2317
|
+
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
2318
|
+
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
2319
|
+
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
2320
|
+
|
2315
2321
|
#else
|
2322
|
+
/* For compat with ruby < 3.0 */
|
2323
|
+
|
2324
|
+
typedef enum {
|
2325
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
2326
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
2327
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
2328
|
+
} pg_rb_io_event_t;
|
2329
|
+
|
2330
|
+
static VALUE
|
2331
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2332
|
+
rb_io_t *fptr;
|
2333
|
+
struct timeval waittime;
|
2334
|
+
int res;
|
2335
|
+
|
2336
|
+
GetOpenFile((io), fptr);
|
2337
|
+
if( !NIL_P(timeout) ){
|
2338
|
+
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
2339
|
+
waittime.tv_usec = (time_t)(NUM2DBL(timeout) - (double)waittime.tv_sec);
|
2340
|
+
}
|
2341
|
+
res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
2316
2342
|
|
2317
|
-
|
2343
|
+
return UINT2NUM(res);
|
2344
|
+
}
|
2345
|
+
#endif
|
2318
2346
|
|
2319
2347
|
static void *
|
2320
|
-
wait_socket_readable(
|
2348
|
+
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
2321
2349
|
{
|
2322
|
-
|
2323
|
-
|
2350
|
+
VALUE socket_io;
|
2351
|
+
VALUE ret;
|
2324
2352
|
void *retval;
|
2325
2353
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2354
|
+
VALUE wait_timeout = Qnil;
|
2355
|
+
PGconn *conn = pg_get_pgconn(self);
|
2326
2356
|
|
2327
|
-
|
2328
|
-
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
2357
|
+
socket_io = pgconn_socket_io(self);
|
2329
2358
|
|
2330
2359
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2331
|
-
if ( PQconsumeInput(conn) == 0 )
|
2360
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
2361
|
+
pgconn_close_socket_io(self);
|
2332
2362
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2363
|
+
}
|
2333
2364
|
|
2334
2365
|
if ( ptimeout ) {
|
2335
2366
|
gettimeofday(&currtime, NULL);
|
@@ -2340,27 +2371,25 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2340
2371
|
if ( ptimeout ) {
|
2341
2372
|
gettimeofday(&currtime, NULL);
|
2342
2373
|
timersub(&aborttime, &currtime, &waittime);
|
2374
|
+
wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
|
2343
2375
|
}
|
2344
2376
|
|
2345
2377
|
/* Is the given timeout valid? */
|
2346
2378
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2347
2379
|
/* Wait for the socket to become readable before checking again */
|
2348
|
-
ret =
|
2380
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
2349
2381
|
} else {
|
2350
|
-
ret =
|
2351
|
-
}
|
2352
|
-
|
2353
|
-
if ( ret < 0 ){
|
2354
|
-
rb_sys_fail( "rb_wait_for_single_fd()" );
|
2382
|
+
ret = Qfalse;
|
2355
2383
|
}
|
2356
2384
|
|
2357
2385
|
/* Return false if the select() timed out */
|
2358
|
-
if ( ret ==
|
2386
|
+
if ( ret == Qfalse ){
|
2359
2387
|
return NULL;
|
2360
2388
|
}
|
2361
2389
|
|
2362
2390
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2363
2391
|
if ( PQconsumeInput(conn) == 0 ){
|
2392
|
+
pgconn_close_socket_io(self);
|
2364
2393
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2365
2394
|
}
|
2366
2395
|
}
|
@@ -2368,8 +2397,45 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2368
2397
|
return retval;
|
2369
2398
|
}
|
2370
2399
|
|
2400
|
+
/*
|
2401
|
+
* call-seq:
|
2402
|
+
* conn.flush() -> Boolean
|
2403
|
+
*
|
2404
|
+
* Attempts to flush any queued output data to the server.
|
2405
|
+
* Returns +true+ if data is successfully flushed, +false+
|
2406
|
+
* if not (can only return +false+ if connection is
|
2407
|
+
* nonblocking.
|
2408
|
+
* Raises PG::Error if some other failure occurred.
|
2409
|
+
*/
|
2410
|
+
static VALUE
|
2411
|
+
pgconn_async_flush(VALUE self)
|
2412
|
+
{
|
2413
|
+
while( pgconn_sync_flush(self) == Qfalse ){
|
2414
|
+
/* wait for the socket to become read- or write-ready */
|
2415
|
+
int events;
|
2416
|
+
VALUE socket_io = pgconn_socket_io(self);
|
2417
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
2371
2418
|
|
2372
|
-
|
2419
|
+
if (events & PG_RUBY_IO_READABLE)
|
2420
|
+
pgconn_consume_input(self);
|
2421
|
+
}
|
2422
|
+
return Qtrue;
|
2423
|
+
}
|
2424
|
+
|
2425
|
+
static VALUE
|
2426
|
+
pgconn_wait_for_flush( VALUE self ){
|
2427
|
+
if( !pg_get_connection_safe(self)->flush_data )
|
2428
|
+
return Qnil;
|
2429
|
+
|
2430
|
+
return pgconn_async_flush(self);
|
2431
|
+
}
|
2432
|
+
|
2433
|
+
static VALUE
|
2434
|
+
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2435
|
+
t_pg_connection *conn = pg_get_connection(self);
|
2436
|
+
conn->flush_data = RTEST(enabled);
|
2437
|
+
return enabled;
|
2438
|
+
}
|
2373
2439
|
|
2374
2440
|
static void *
|
2375
2441
|
notify_readable(PGconn *conn)
|
@@ -2408,7 +2474,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2408
2474
|
ptimeout = &timeout;
|
2409
2475
|
}
|
2410
2476
|
|
2411
|
-
pnotification = (PGnotify*) wait_socket_readable(
|
2477
|
+
pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
|
2412
2478
|
|
2413
2479
|
/* Return nil if the select timed out */
|
2414
2480
|
if ( !pnotification ) return Qnil;
|
@@ -2429,28 +2495,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2429
2495
|
}
|
2430
2496
|
|
2431
2497
|
|
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
2498
|
static VALUE
|
2453
|
-
|
2499
|
+
pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
2454
2500
|
{
|
2455
2501
|
int ret;
|
2456
2502
|
int len;
|
@@ -2467,13 +2513,11 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2467
2513
|
if( NIL_P(this->encoder_for_put_copy_data) ){
|
2468
2514
|
buffer = value;
|
2469
2515
|
} else {
|
2470
|
-
p_coder =
|
2516
|
+
p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
|
2471
2517
|
}
|
2472
|
-
} else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
|
2473
|
-
Data_Get_Struct( encoder, t_pg_coder, p_coder );
|
2474
2518
|
} else {
|
2475
|
-
|
2476
|
-
|
2519
|
+
/* Check argument type and use argument encoder */
|
2520
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
|
2477
2521
|
}
|
2478
2522
|
|
2479
2523
|
if( p_coder ){
|
@@ -2507,22 +2551,8 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2507
2551
|
return (ret) ? Qtrue : Qfalse;
|
2508
2552
|
}
|
2509
2553
|
|
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
2554
|
static VALUE
|
2525
|
-
|
2555
|
+
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2526
2556
|
{
|
2527
2557
|
VALUE str;
|
2528
2558
|
VALUE error;
|
@@ -2544,27 +2574,8 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2544
2574
|
return (ret) ? Qtrue : Qfalse;
|
2545
2575
|
}
|
2546
2576
|
|
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
2577
|
static VALUE
|
2567
|
-
|
2578
|
+
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2568
2579
|
{
|
2569
2580
|
VALUE async_in;
|
2570
2581
|
VALUE error;
|
@@ -2579,13 +2590,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2579
2590
|
|
2580
2591
|
if( NIL_P(decoder) ){
|
2581
2592
|
if( !NIL_P(this->decoder_for_get_copy_data) ){
|
2582
|
-
p_coder =
|
2593
|
+
p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
|
2583
2594
|
}
|
2584
|
-
} else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
|
2585
|
-
Data_Get_Struct( decoder, t_pg_coder, p_coder );
|
2586
2595
|
} else {
|
2587
|
-
|
2588
|
-
|
2596
|
+
/* Check argument type and use argument decoder */
|
2597
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
2589
2598
|
}
|
2590
2599
|
|
2591
2600
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
@@ -2830,7 +2839,7 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2830
2839
|
* call-seq:
|
2831
2840
|
* conn.set_notice_processor {|message| ... } -> Proc
|
2832
2841
|
*
|
2833
|
-
* See #set_notice_receiver for the
|
2842
|
+
* See #set_notice_receiver for the description of what this and the
|
2834
2843
|
* notice_processor methods do.
|
2835
2844
|
*
|
2836
2845
|
* This function takes a new block to act as the notice processor and returns
|
@@ -2884,12 +2893,14 @@ pgconn_get_client_encoding(VALUE self)
|
|
2884
2893
|
|
2885
2894
|
/*
|
2886
2895
|
* call-seq:
|
2887
|
-
* conn.
|
2896
|
+
* conn.sync_set_client_encoding( encoding )
|
2888
2897
|
*
|
2889
|
-
*
|
2898
|
+
* This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
|
2899
|
+
* See #async_exec for the differences between the two API variants.
|
2900
|
+
* 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
2901
|
*/
|
2891
2902
|
static VALUE
|
2892
|
-
|
2903
|
+
pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
2893
2904
|
{
|
2894
2905
|
PGconn *conn = pg_get_pgconn( self );
|
2895
2906
|
|
@@ -2903,49 +2914,6 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2903
2914
|
return Qnil;
|
2904
2915
|
}
|
2905
2916
|
|
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
2917
|
|
2950
2918
|
/*
|
2951
2919
|
* call-seq:
|
@@ -3022,8 +2990,6 @@ get_result_readable(PGconn *conn)
|
|
3022
2990
|
*/
|
3023
2991
|
static VALUE
|
3024
2992
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
3025
|
-
PGconn *conn = pg_get_pgconn( self );
|
3026
|
-
|
3027
2993
|
struct timeval timeout;
|
3028
2994
|
struct timeval *ptimeout = NULL;
|
3029
2995
|
VALUE timeout_in;
|
@@ -3037,7 +3003,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3037
3003
|
ptimeout = &timeout;
|
3038
3004
|
}
|
3039
3005
|
|
3040
|
-
ret = wait_socket_readable(
|
3006
|
+
ret = wait_socket_readable( self, ptimeout, get_result_readable);
|
3041
3007
|
|
3042
3008
|
if( !ret )
|
3043
3009
|
return Qfalse;
|
@@ -3046,6 +3012,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3046
3012
|
}
|
3047
3013
|
|
3048
3014
|
|
3015
|
+
/*
|
3016
|
+
* call-seq:
|
3017
|
+
* conn.sync_get_last_result( ) -> PG::Result
|
3018
|
+
*
|
3019
|
+
* This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
|
3020
|
+
* See #async_exec for the differences between the two API variants.
|
3021
|
+
* 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.
|
3022
|
+
*/
|
3023
|
+
static VALUE
|
3024
|
+
pgconn_sync_get_last_result(VALUE self)
|
3025
|
+
{
|
3026
|
+
PGconn *conn = pg_get_pgconn(self);
|
3027
|
+
VALUE rb_pgresult = Qnil;
|
3028
|
+
PGresult *cur, *prev;
|
3029
|
+
|
3030
|
+
|
3031
|
+
cur = prev = NULL;
|
3032
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3033
|
+
int status;
|
3034
|
+
|
3035
|
+
if (prev) PQclear(prev);
|
3036
|
+
prev = cur;
|
3037
|
+
|
3038
|
+
status = PQresultStatus(cur);
|
3039
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
3040
|
+
break;
|
3041
|
+
}
|
3042
|
+
|
3043
|
+
if (prev) {
|
3044
|
+
rb_pgresult = pg_new_result( prev, self );
|
3045
|
+
pg_result_check(rb_pgresult);
|
3046
|
+
}
|
3047
|
+
|
3048
|
+
return rb_pgresult;
|
3049
|
+
}
|
3050
|
+
|
3049
3051
|
/*
|
3050
3052
|
* call-seq:
|
3051
3053
|
* conn.get_last_result( ) -> PG::Result
|
@@ -3056,27 +3058,35 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
3056
3058
|
* returns the last non-NULL result, or +nil+ if no
|
3057
3059
|
* results are available.
|
3058
3060
|
*
|
3061
|
+
* If the last result contains a bad result_status, an
|
3062
|
+
* appropriate exception is raised.
|
3063
|
+
*
|
3059
3064
|
* This function is similar to #get_result
|
3060
3065
|
* except that it is designed to get one and only
|
3061
|
-
* one result.
|
3066
|
+
* one result and that it checks the result state.
|
3062
3067
|
*/
|
3063
3068
|
static VALUE
|
3064
|
-
|
3069
|
+
pgconn_async_get_last_result(VALUE self)
|
3065
3070
|
{
|
3066
3071
|
PGconn *conn = pg_get_pgconn(self);
|
3067
3072
|
VALUE rb_pgresult = Qnil;
|
3068
3073
|
PGresult *cur, *prev;
|
3069
3074
|
|
3070
|
-
|
3071
|
-
|
3072
|
-
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3075
|
+
cur = prev = NULL;
|
3076
|
+
for(;;) {
|
3073
3077
|
int status;
|
3074
3078
|
|
3079
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3080
|
+
|
3081
|
+
cur = gvl_PQgetResult(conn);
|
3082
|
+
if (cur == NULL)
|
3083
|
+
break;
|
3084
|
+
|
3075
3085
|
if (prev) PQclear(prev);
|
3076
3086
|
prev = cur;
|
3077
3087
|
|
3078
3088
|
status = PQresultStatus(cur);
|
3079
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
3089
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
3080
3090
|
break;
|
3081
3091
|
}
|
3082
3092
|
|
@@ -3100,22 +3110,60 @@ static VALUE
|
|
3100
3110
|
pgconn_discard_results(VALUE self)
|
3101
3111
|
{
|
3102
3112
|
PGconn *conn = pg_get_pgconn(self);
|
3113
|
+
VALUE socket_io;
|
3103
3114
|
|
3104
|
-
|
3105
|
-
|
3106
|
-
|
3115
|
+
if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
|
3116
|
+
return Qnil;
|
3117
|
+
}
|
3118
|
+
|
3119
|
+
socket_io = pgconn_socket_io(self);
|
3120
|
+
|
3121
|
+
for(;;) {
|
3122
|
+
PGresult *cur;
|
3123
|
+
int status;
|
3124
|
+
|
3125
|
+
/* pgconn_block() raises an exception in case of errors.
|
3126
|
+
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
3127
|
+
*/
|
3128
|
+
while( gvl_PQisBusy(conn) ){
|
3129
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3130
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
3131
|
+
pgconn_close_socket_io(self);
|
3132
|
+
return Qfalse;
|
3133
|
+
}
|
3134
|
+
}
|
3135
|
+
|
3136
|
+
cur = gvl_PQgetResult(conn);
|
3137
|
+
if( cur == NULL) break;
|
3138
|
+
|
3139
|
+
status = PQresultStatus(cur);
|
3107
3140
|
PQclear(cur);
|
3108
3141
|
if (status == PGRES_COPY_IN){
|
3109
3142
|
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
3110
3143
|
}
|
3111
3144
|
if (status == PGRES_COPY_OUT){
|
3112
|
-
|
3113
|
-
|
3114
|
-
|
3145
|
+
for(;;) {
|
3146
|
+
char *buffer = NULL;
|
3147
|
+
int st = gvl_PQgetCopyData(conn, &buffer, 1);
|
3148
|
+
if( st == 0 ) {
|
3149
|
+
/* would block -> wait for readable data */
|
3150
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3151
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
3152
|
+
pgconn_close_socket_io(self);
|
3153
|
+
return Qfalse;
|
3154
|
+
}
|
3155
|
+
} else if( st > 0 ) {
|
3156
|
+
/* some data retrieved -> discard it */
|
3157
|
+
PQfreemem(buffer);
|
3158
|
+
} else {
|
3159
|
+
/* no more data */
|
3160
|
+
break;
|
3161
|
+
}
|
3162
|
+
}
|
3115
3163
|
}
|
3116
3164
|
}
|
3117
3165
|
|
3118
|
-
return
|
3166
|
+
return Qtrue;
|
3119
3167
|
}
|
3120
3168
|
|
3121
3169
|
/*
|
@@ -3138,6 +3186,7 @@ pgconn_discard_results(VALUE self)
|
|
3138
3186
|
* #exec is an alias for #async_exec which is almost identical to #sync_exec .
|
3139
3187
|
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
3140
3188
|
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
3189
|
+
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
3141
3190
|
* Both methods ensure that other threads can process while waiting for the server to
|
3142
3191
|
* complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
|
3143
3192
|
* This is most notably visible by a delayed reaction to Control+C.
|
@@ -3152,8 +3201,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3152
3201
|
|
3153
3202
|
pgconn_discard_results( self );
|
3154
3203
|
pgconn_send_query( argc, argv, self );
|
3155
|
-
|
3156
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3204
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3157
3205
|
|
3158
3206
|
if ( rb_block_given_p() ) {
|
3159
3207
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3182,7 +3230,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3182
3230
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3183
3231
|
* { :value => <string value>, :type => 0, :format => 0 }
|
3184
3232
|
*
|
3185
|
-
* PostgreSQL bind parameters are represented as $1, $
|
3233
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3186
3234
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
3187
3235
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3188
3236
|
*
|
@@ -3225,8 +3273,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
3225
3273
|
} else {
|
3226
3274
|
pgconn_send_query_params( argc, argv, self );
|
3227
3275
|
}
|
3228
|
-
|
3229
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3276
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3230
3277
|
|
3231
3278
|
if ( rb_block_given_p() ) {
|
3232
3279
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3252,7 +3299,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
|
3252
3299
|
*
|
3253
3300
|
* For example: "SELECT $1::int"
|
3254
3301
|
*
|
3255
|
-
* PostgreSQL bind parameters are represented as $1, $
|
3302
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3256
3303
|
* inside the SQL query.
|
3257
3304
|
*
|
3258
3305
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
|
@@ -3264,8 +3311,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
3264
3311
|
|
3265
3312
|
pgconn_discard_results( self );
|
3266
3313
|
pgconn_send_prepare( argc, argv, self );
|
3267
|
-
|
3268
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3314
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3269
3315
|
|
3270
3316
|
if ( rb_block_given_p() ) {
|
3271
3317
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3292,7 +3338,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
|
3292
3338
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3293
3339
|
* { :value => <string value>, :format => 0 }
|
3294
3340
|
*
|
3295
|
-
* PostgreSQL bind parameters are represented as $1, $
|
3341
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3296
3342
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
3297
3343
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3298
3344
|
*
|
@@ -3318,8 +3364,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
3318
3364
|
|
3319
3365
|
pgconn_discard_results( self );
|
3320
3366
|
pgconn_send_query_prepared( argc, argv, self );
|
3321
|
-
|
3322
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3367
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3323
3368
|
|
3324
3369
|
if ( rb_block_given_p() ) {
|
3325
3370
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3343,8 +3388,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
3343
3388
|
|
3344
3389
|
pgconn_discard_results( self );
|
3345
3390
|
pgconn_send_describe_portal( self, portal );
|
3346
|
-
|
3347
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3391
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3348
3392
|
|
3349
3393
|
if ( rb_block_given_p() ) {
|
3350
3394
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3368,8 +3412,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
|
3368
3412
|
|
3369
3413
|
pgconn_discard_results( self );
|
3370
3414
|
pgconn_send_describe_prepared( self, stmt_name );
|
3371
|
-
|
3372
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3415
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3373
3416
|
|
3374
3417
|
if ( rb_block_given_p() ) {
|
3375
3418
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3457,6 +3500,126 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
3457
3500
|
#endif
|
3458
3501
|
|
3459
3502
|
|
3503
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
3504
|
+
/*
|
3505
|
+
* call-seq:
|
3506
|
+
* conn.pipeline_status -> Integer
|
3507
|
+
*
|
3508
|
+
* Returns the current pipeline mode status of the libpq connection.
|
3509
|
+
*
|
3510
|
+
* PQpipelineStatus can return one of the following values:
|
3511
|
+
*
|
3512
|
+
* * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
|
3513
|
+
* * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
|
3514
|
+
* * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
3515
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
3516
|
+
*
|
3517
|
+
* Available since PostgreSQL-14
|
3518
|
+
*/
|
3519
|
+
static VALUE
|
3520
|
+
pgconn_pipeline_status(VALUE self)
|
3521
|
+
{
|
3522
|
+
int res = PQpipelineStatus(pg_get_pgconn(self));
|
3523
|
+
return INT2FIX(res);
|
3524
|
+
}
|
3525
|
+
|
3526
|
+
|
3527
|
+
/*
|
3528
|
+
* call-seq:
|
3529
|
+
* conn.enter_pipeline_mode -> nil
|
3530
|
+
*
|
3531
|
+
* Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
|
3532
|
+
*
|
3533
|
+
* 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.
|
3534
|
+
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
3535
|
+
*
|
3536
|
+
* Available since PostgreSQL-14
|
3537
|
+
*/
|
3538
|
+
static VALUE
|
3539
|
+
pgconn_enter_pipeline_mode(VALUE self)
|
3540
|
+
{
|
3541
|
+
PGconn *conn = pg_get_pgconn(self);
|
3542
|
+
int res = PQenterPipelineMode(conn);
|
3543
|
+
if( res == 1 ) {
|
3544
|
+
return Qnil;
|
3545
|
+
} else {
|
3546
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3547
|
+
}
|
3548
|
+
}
|
3549
|
+
|
3550
|
+
/*
|
3551
|
+
* call-seq:
|
3552
|
+
* conn.exit_pipeline_mode -> nil
|
3553
|
+
*
|
3554
|
+
* Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
|
3555
|
+
*
|
3556
|
+
* Takes no action if not in pipeline mode.
|
3557
|
+
* 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.
|
3558
|
+
*
|
3559
|
+
* Available since PostgreSQL-14
|
3560
|
+
*/
|
3561
|
+
static VALUE
|
3562
|
+
pgconn_exit_pipeline_mode(VALUE self)
|
3563
|
+
{
|
3564
|
+
PGconn *conn = pg_get_pgconn(self);
|
3565
|
+
int res = PQexitPipelineMode(conn);
|
3566
|
+
if( res == 1 ) {
|
3567
|
+
return Qnil;
|
3568
|
+
} else {
|
3569
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3570
|
+
}
|
3571
|
+
}
|
3572
|
+
|
3573
|
+
|
3574
|
+
/*
|
3575
|
+
* call-seq:
|
3576
|
+
* conn.pipeline_sync -> nil
|
3577
|
+
*
|
3578
|
+
* Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
|
3579
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
|
3580
|
+
*
|
3581
|
+
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
3582
|
+
*
|
3583
|
+
* Available since PostgreSQL-14
|
3584
|
+
*/
|
3585
|
+
static VALUE
|
3586
|
+
pgconn_pipeline_sync(VALUE self)
|
3587
|
+
{
|
3588
|
+
PGconn *conn = pg_get_pgconn(self);
|
3589
|
+
int res = PQpipelineSync(conn);
|
3590
|
+
if( res == 1 ) {
|
3591
|
+
return Qnil;
|
3592
|
+
} else {
|
3593
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3594
|
+
}
|
3595
|
+
}
|
3596
|
+
|
3597
|
+
/*
|
3598
|
+
* call-seq:
|
3599
|
+
* conn.pipeline_sync -> nil
|
3600
|
+
*
|
3601
|
+
* Sends a request for the server to flush its output buffer.
|
3602
|
+
*
|
3603
|
+
* 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.
|
3604
|
+
* This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
|
3605
|
+
* Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
|
3606
|
+
*
|
3607
|
+
* Available since PostgreSQL-14
|
3608
|
+
*/
|
3609
|
+
static VALUE
|
3610
|
+
pgconn_send_flush_request(VALUE self)
|
3611
|
+
{
|
3612
|
+
PGconn *conn = pg_get_pgconn(self);
|
3613
|
+
int res = PQsendFlushRequest(conn);
|
3614
|
+
if( res == 1 ) {
|
3615
|
+
return Qnil;
|
3616
|
+
} else {
|
3617
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3618
|
+
}
|
3619
|
+
}
|
3620
|
+
|
3621
|
+
#endif
|
3622
|
+
|
3460
3623
|
/**************************************************************************
|
3461
3624
|
* LARGE OBJECT SUPPORT
|
3462
3625
|
**************************************************************************/
|
@@ -3801,11 +3964,11 @@ static VALUE
|
|
3801
3964
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3802
3965
|
{
|
3803
3966
|
if (NIL_P(enc)) {
|
3804
|
-
|
3967
|
+
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3805
3968
|
return enc;
|
3806
3969
|
}
|
3807
3970
|
else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
|
3808
|
-
|
3971
|
+
pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
3809
3972
|
return enc;
|
3810
3973
|
}
|
3811
3974
|
else {
|
@@ -3843,16 +4006,33 @@ pgconn_external_encoding(VALUE self)
|
|
3843
4006
|
return rb_enc_from_encoding( enc );
|
3844
4007
|
}
|
3845
4008
|
|
4009
|
+
/*
|
4010
|
+
* call-seq:
|
4011
|
+
* conn.set_client_encoding( encoding )
|
4012
|
+
*
|
4013
|
+
* Sets the client encoding to the _encoding_ String.
|
4014
|
+
*/
|
4015
|
+
static VALUE
|
4016
|
+
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
4017
|
+
{
|
4018
|
+
VALUE query_format, query;
|
4019
|
+
|
4020
|
+
Check_Type(encname, T_STRING);
|
4021
|
+
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4022
|
+
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
4023
|
+
|
4024
|
+
pgconn_async_exec(1, &query, self);
|
4025
|
+
pgconn_set_internal_encoding_index( self );
|
4026
|
+
|
4027
|
+
return Qnil;
|
4028
|
+
}
|
3846
4029
|
|
3847
4030
|
static VALUE
|
3848
4031
|
pgconn_set_client_encoding_async1( VALUE args )
|
3849
4032
|
{
|
3850
4033
|
VALUE self = ((VALUE*)args)[0];
|
3851
4034
|
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);
|
4035
|
+
pgconn_async_set_client_encoding(self, encname);
|
3856
4036
|
return 0;
|
3857
4037
|
}
|
3858
4038
|
|
@@ -3867,9 +4047,9 @@ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
|
|
3867
4047
|
|
3868
4048
|
|
3869
4049
|
static VALUE
|
3870
|
-
pgconn_set_client_encoding_async( VALUE self,
|
4050
|
+
pgconn_set_client_encoding_async( VALUE self, VALUE encname )
|
3871
4051
|
{
|
3872
|
-
VALUE args[] = { self,
|
4052
|
+
VALUE args[] = { self, encname };
|
3873
4053
|
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
3874
4054
|
}
|
3875
4055
|
|
@@ -3891,10 +4071,9 @@ pgconn_set_default_encoding( VALUE self )
|
|
3891
4071
|
|
3892
4072
|
if (( enc = rb_default_internal_encoding() )) {
|
3893
4073
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3894
|
-
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
4074
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
3895
4075
|
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
3896
4076
|
encname, PQerrorMessage(conn) );
|
3897
|
-
pgconn_set_internal_encoding_index( self );
|
3898
4077
|
return rb_enc_from_encoding( enc );
|
3899
4078
|
} else {
|
3900
4079
|
pgconn_set_internal_encoding_index( self );
|
@@ -3916,12 +4095,12 @@ static VALUE
|
|
3916
4095
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
3917
4096
|
{
|
3918
4097
|
t_pg_connection *this = pg_get_connection( self );
|
4098
|
+
t_typemap *tm;
|
4099
|
+
UNUSED(tm);
|
4100
|
+
|
4101
|
+
/* Check type of method param */
|
4102
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
3919
4103
|
|
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
4104
|
this->type_map_for_queries = typemap;
|
3926
4105
|
|
3927
4106
|
return typemap;
|
@@ -3956,12 +4135,10 @@ static VALUE
|
|
3956
4135
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
3957
4136
|
{
|
3958
4137
|
t_pg_connection *this = pg_get_connection( self );
|
4138
|
+
t_typemap *tm;
|
4139
|
+
UNUSED(tm);
|
3959
4140
|
|
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);
|
4141
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
3965
4142
|
this->type_map_for_results = typemap;
|
3966
4143
|
|
3967
4144
|
return typemap;
|
@@ -3996,20 +4173,19 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
3996
4173
|
*
|
3997
4174
|
*/
|
3998
4175
|
static VALUE
|
3999
|
-
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE
|
4176
|
+
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
4000
4177
|
{
|
4001
4178
|
t_pg_connection *this = pg_get_connection( self );
|
4002
4179
|
|
4003
|
-
if(
|
4004
|
-
|
4005
|
-
|
4006
|
-
|
4007
|
-
|
4008
|
-
Check_Type(typemap, T_DATA);
|
4180
|
+
if( encoder != Qnil ){
|
4181
|
+
t_pg_coder *co;
|
4182
|
+
UNUSED(co);
|
4183
|
+
/* Check argument type */
|
4184
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4009
4185
|
}
|
4010
|
-
this->encoder_for_put_copy_data =
|
4186
|
+
this->encoder_for_put_copy_data = encoder;
|
4011
4187
|
|
4012
|
-
return
|
4188
|
+
return encoder;
|
4013
4189
|
}
|
4014
4190
|
|
4015
4191
|
/*
|
@@ -4045,20 +4221,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
4045
4221
|
*
|
4046
4222
|
*/
|
4047
4223
|
static VALUE
|
4048
|
-
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE
|
4224
|
+
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
4049
4225
|
{
|
4050
4226
|
t_pg_connection *this = pg_get_connection( self );
|
4051
4227
|
|
4052
|
-
if(
|
4053
|
-
|
4054
|
-
|
4055
|
-
|
4056
|
-
|
4057
|
-
Check_Type(typemap, T_DATA);
|
4228
|
+
if( decoder != Qnil ){
|
4229
|
+
t_pg_coder *co;
|
4230
|
+
UNUSED(co);
|
4231
|
+
/* Check argument type */
|
4232
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4058
4233
|
}
|
4059
|
-
this->decoder_for_get_copy_data =
|
4234
|
+
this->decoder_for_get_copy_data = decoder;
|
4060
4235
|
|
4061
|
-
return
|
4236
|
+
return decoder;
|
4062
4237
|
}
|
4063
4238
|
|
4064
4239
|
/*
|
@@ -4141,6 +4316,7 @@ void
|
|
4141
4316
|
init_pg_connection()
|
4142
4317
|
{
|
4143
4318
|
s_id_encode = rb_intern("encode");
|
4319
|
+
s_id_autoclose_set = rb_intern("autoclose=");
|
4144
4320
|
sym_type = ID2SYM(rb_intern("type"));
|
4145
4321
|
sym_format = ID2SYM(rb_intern("format"));
|
4146
4322
|
sym_value = ID2SYM(rb_intern("value"));
|
@@ -4156,10 +4332,6 @@ init_pg_connection()
|
|
4156
4332
|
/****** PG::Connection CLASS METHODS ******/
|
4157
4333
|
rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
|
4158
4334
|
|
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
4335
|
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
4164
4336
|
SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
|
4165
4337
|
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
@@ -4168,14 +4340,14 @@ init_pg_connection()
|
|
4168
4340
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4169
4341
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4170
4342
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4171
|
-
rb_define_singleton_method(rb_cPGconn, "
|
4343
|
+
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
4344
|
+
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
4172
4345
|
|
4173
4346
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
4174
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
4175
4347
|
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
4176
4348
|
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
4177
4349
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
4178
|
-
rb_define_method(rb_cPGconn, "
|
4350
|
+
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
4179
4351
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
4180
4352
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4181
4353
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
@@ -4187,9 +4359,7 @@ init_pg_connection()
|
|
4187
4359
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
4188
4360
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
4189
4361
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
4190
|
-
#ifdef HAVE_PQCONNINFO
|
4191
4362
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|
4192
|
-
#endif
|
4193
4363
|
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
4194
4364
|
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
4195
4365
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
@@ -4200,17 +4370,18 @@ init_pg_connection()
|
|
4200
4370
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
4201
4371
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
4202
4372
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4373
|
+
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
4203
4374
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
4204
4375
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
4205
4376
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
4206
4377
|
|
4207
4378
|
/****** 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",
|
4379
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
|
4380
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
|
4381
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
|
4382
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
4383
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
4384
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
4214
4385
|
|
4215
4386
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
4216
4387
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
@@ -4243,25 +4414,26 @@ init_pg_connection()
|
|
4243
4414
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4244
4415
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4245
4416
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4246
|
-
rb_define_method(rb_cPGconn, "
|
4417
|
+
rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
|
4247
4418
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
4248
4419
|
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",
|
4420
|
+
rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
|
4421
|
+
rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
|
4422
|
+
rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
|
4423
|
+
rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
|
4424
|
+
rb_define_alias(rb_cPGconn, "async_flush", "flush");
|
4253
4425
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
4254
4426
|
|
4255
4427
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4256
|
-
rb_define_method(rb_cPGconn, "
|
4428
|
+
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
4257
4429
|
|
4258
4430
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
4259
4431
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
4260
4432
|
|
4261
4433
|
/****** PG::Connection INSTANCE METHODS: COPY ******/
|
4262
|
-
rb_define_method(rb_cPGconn, "
|
4263
|
-
rb_define_method(rb_cPGconn, "
|
4264
|
-
rb_define_method(rb_cPGconn, "
|
4434
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
|
4435
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
|
4436
|
+
rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
|
4265
4437
|
|
4266
4438
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
4267
4439
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
@@ -4277,16 +4449,20 @@ init_pg_connection()
|
|
4277
4449
|
|
4278
4450
|
/****** PG::Connection INSTANCE METHODS: Other ******/
|
4279
4451
|
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
4280
|
-
rb_define_method(rb_cPGconn, "
|
4452
|
+
rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
|
4453
|
+
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
|
4454
|
+
rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
|
4281
4455
|
rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
|
4282
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
4283
4456
|
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
4457
|
+
rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
|
4284
4458
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
4285
4459
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
4286
4460
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4287
|
-
rb_define_method(rb_cPGconn, "
|
4461
|
+
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
4462
|
+
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
4463
|
+
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
4288
4464
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4289
|
-
rb_define_method(rb_cPGconn, "
|
4465
|
+
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
4290
4466
|
#endif
|
4291
4467
|
|
4292
4468
|
#ifdef HAVE_PQSSLATTRIBUTE
|
@@ -4295,6 +4471,14 @@ init_pg_connection()
|
|
4295
4471
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4296
4472
|
#endif
|
4297
4473
|
|
4474
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
4475
|
+
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
4476
|
+
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
4477
|
+
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
4478
|
+
rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
|
4479
|
+
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
4480
|
+
#endif
|
4481
|
+
|
4298
4482
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
4299
4483
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
4300
4484
|
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|