pg 1.5.9 → 1.7.0
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/{History.md → CHANGELOG.md} +126 -0
- data/Gemfile +11 -7
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +83 -32
- data/README.md +79 -29
- data/Rakefile +84 -19
- data/certs/larskanis-2026.pem +24 -0
- data/ext/errorcodes.def +9 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +8 -1
- data/ext/extconf.rb +194 -30
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +47 -134
- data/ext/pg.c +23 -16
- data/ext/pg.h +23 -24
- data/ext/pg_binary_decoder.c +157 -3
- data/ext/pg_binary_encoder.c +219 -9
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +58 -9
- data/ext/pg_connection.c +558 -291
- data/ext/pg_copy_coder.c +36 -23
- data/ext/pg_record_coder.c +11 -7
- data/ext/pg_result.c +144 -76
- data/ext/pg_text_decoder.c +7 -7
- data/ext/pg_text_encoder.c +29 -11
- data/ext/pg_tuple.c +9 -9
- data/ext/pg_type_map.c +45 -3
- data/ext/pg_type_map_all_strings.c +3 -3
- data/ext/pg_type_map_by_class.c +2 -2
- data/ext/pg_type_map_by_column.c +4 -3
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +4 -2
- data/ext/pg_type_map_in_ruby.c +2 -2
- data/ext/pg_util.c +2 -2
- data/ext/pg_util.h +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +5 -0
- data/lib/pg/basic_type_map_for_queries.rb +16 -5
- data/lib/pg/basic_type_map_for_results.rb +5 -0
- data/lib/pg/basic_type_registry.rb +2 -2
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +4 -2
- data/lib/pg/connection.rb +393 -180
- data/lib/pg/text_decoder/date.rb +1 -1
- data/lib/pg/text_decoder/json.rb +1 -1
- data/lib/pg/text_encoder/date.rb +7 -1
- data/lib/pg/text_encoder/json.rb +1 -1
- data/lib/pg/version.rb +2 -1
- data/lib/pg.rb +156 -130
- data/misc/glibc/Dockerfile +20 -0
- data/misc/glibc/docker-compose.yml +9 -0
- data/misc/glibc/glibc_spec.rb +5 -0
- data/misc/yugabyte/Dockerfile +9 -0
- data/misc/yugabyte/docker-compose.yml +28 -0
- data/misc/yugabyte/pg-test.rb +45 -0
- data/pg.gemspec +5 -3
- data/ports/patches/krb5/1.22.2/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/krb5/1.22.2/0002-unknown-command-line-option-on-clang.patch +12 -0
- data/ports/patches/postgresql/18.6/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data/sample/async_mixed.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +36 -22
- metadata.gz.sig +0 -0
- data/Manifest.txt +0 -72
- data/Rakefile.cross +0 -303
data/ext/pg_connection.c
CHANGED
|
@@ -14,7 +14,7 @@ VALUE rb_cPGconn;
|
|
|
14
14
|
static ID s_id_encode;
|
|
15
15
|
static ID s_id_autoclose_set;
|
|
16
16
|
static VALUE sym_type, sym_format, sym_value;
|
|
17
|
-
static VALUE sym_symbol, sym_string
|
|
17
|
+
static VALUE sym_symbol, sym_string;
|
|
18
18
|
|
|
19
19
|
static VALUE pgconn_finish( VALUE );
|
|
20
20
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
|
@@ -30,11 +30,8 @@ static VALUE pgconn_async_flush(VALUE self);
|
|
|
30
30
|
/*
|
|
31
31
|
* Convenience function to raise connection errors
|
|
32
32
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
#endif
|
|
36
|
-
NORETURN( static void
|
|
37
|
-
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...))
|
|
33
|
+
void
|
|
34
|
+
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
|
38
35
|
{
|
|
39
36
|
VALUE msg, error;
|
|
40
37
|
va_list ap;
|
|
@@ -69,6 +66,7 @@ pg_get_connection_safe( VALUE self )
|
|
|
69
66
|
t_pg_connection *this;
|
|
70
67
|
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
71
68
|
|
|
69
|
+
rb_check_frozen(self);
|
|
72
70
|
if ( !this->pgconn )
|
|
73
71
|
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
|
74
72
|
|
|
@@ -96,6 +94,20 @@ pg_get_pgconn( VALUE self )
|
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
|
|
97
|
+
void
|
|
98
|
+
pg_unwrap_socket_io( VALUE self, VALUE *p_socket_io, int ruby_sd )
|
|
99
|
+
{
|
|
100
|
+
if ( RTEST(*p_socket_io) ) {
|
|
101
|
+
#if defined(_WIN32)
|
|
102
|
+
if( rb_w32_unwrap_io_handle(ruby_sd) )
|
|
103
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
|
104
|
+
#endif
|
|
105
|
+
rb_funcall( *p_socket_io, rb_intern("close"), 0 );
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
RB_OBJ_WRITE(self, p_socket_io, Qnil);
|
|
109
|
+
}
|
|
110
|
+
|
|
99
111
|
|
|
100
112
|
/*
|
|
101
113
|
* Close the associated socket IO object if there is one.
|
|
@@ -104,17 +116,7 @@ static void
|
|
|
104
116
|
pgconn_close_socket_io( VALUE self )
|
|
105
117
|
{
|
|
106
118
|
t_pg_connection *this = pg_get_connection( self );
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if ( RTEST(socket_io) ) {
|
|
110
|
-
#if defined(_WIN32)
|
|
111
|
-
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
|
112
|
-
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
|
113
|
-
#endif
|
|
114
|
-
rb_funcall( socket_io, rb_intern("close"), 0 );
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
|
119
|
+
pg_unwrap_socket_io( self, &this->socket_io, this->ruby_sd);
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
|
|
@@ -151,13 +153,13 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
|
|
|
151
153
|
return ary;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
static const char *pg_cstr_enc(VALUE str, int enc_idx){
|
|
156
|
+
static const char *pg_cstr_enc(VALUE str, int enc_idx, VALUE *transcoded_str){
|
|
155
157
|
const char *ptr = StringValueCStr(str);
|
|
156
158
|
if( ENCODING_GET(str) == enc_idx ){
|
|
157
159
|
return ptr;
|
|
158
160
|
} else {
|
|
159
|
-
|
|
160
|
-
return StringValueCStr(
|
|
161
|
+
*transcoded_str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
|
|
162
|
+
return StringValueCStr(*transcoded_str);
|
|
161
163
|
}
|
|
162
164
|
}
|
|
163
165
|
|
|
@@ -186,6 +188,7 @@ pgconn_gc_compact( void *_this )
|
|
|
186
188
|
pg_gc_location( this->socket_io );
|
|
187
189
|
pg_gc_location( this->notice_receiver );
|
|
188
190
|
pg_gc_location( this->notice_processor );
|
|
191
|
+
pg_gc_location( this->self );
|
|
189
192
|
pg_gc_location( this->type_map_for_queries );
|
|
190
193
|
pg_gc_location( this->type_map_for_results );
|
|
191
194
|
pg_gc_location( this->trace_stream );
|
|
@@ -230,7 +233,7 @@ static const rb_data_type_t pg_connection_type = {
|
|
|
230
233
|
pgconn_gc_mark,
|
|
231
234
|
pgconn_gc_free,
|
|
232
235
|
pgconn_memsize,
|
|
233
|
-
|
|
236
|
+
pgconn_gc_compact,
|
|
234
237
|
},
|
|
235
238
|
0,
|
|
236
239
|
0,
|
|
@@ -258,6 +261,7 @@ pgconn_s_allocate( VALUE klass )
|
|
|
258
261
|
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
|
259
262
|
RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
|
|
260
263
|
RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
|
|
264
|
+
RB_OBJ_WRITE(self, &this->self, self);
|
|
261
265
|
RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
|
|
262
266
|
RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
|
|
263
267
|
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
|
|
@@ -278,7 +282,8 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
|
278
282
|
|
|
279
283
|
this = pg_get_connection( self );
|
|
280
284
|
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
|
281
|
-
this->pgconn =
|
|
285
|
+
this->pgconn = PQconnectdb(StringValueCStr(conninfo));
|
|
286
|
+
RB_GC_GUARD(conninfo);
|
|
282
287
|
|
|
283
288
|
if(this->pgconn == NULL)
|
|
284
289
|
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
|
|
@@ -327,6 +332,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
327
332
|
this = pg_get_connection( rb_conn );
|
|
328
333
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
|
329
334
|
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
|
335
|
+
RB_GC_GUARD(conninfo);
|
|
330
336
|
|
|
331
337
|
if( this->pgconn == NULL )
|
|
332
338
|
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
|
@@ -348,6 +354,7 @@ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
|
|
|
348
354
|
|
|
349
355
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
|
350
356
|
ping = gvl_PQping( StringValueCStr(conninfo) );
|
|
357
|
+
RB_GC_GUARD(conninfo);
|
|
351
358
|
|
|
352
359
|
return INT2FIX((int)ping);
|
|
353
360
|
}
|
|
@@ -419,7 +426,6 @@ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
|
|
|
419
426
|
}
|
|
420
427
|
|
|
421
428
|
|
|
422
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
423
429
|
static VALUE
|
|
424
430
|
pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
425
431
|
{
|
|
@@ -433,7 +439,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
|
433
439
|
Check_Type(password, T_STRING);
|
|
434
440
|
Check_Type(username, T_STRING);
|
|
435
441
|
|
|
436
|
-
encrypted =
|
|
442
|
+
encrypted = PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
|
|
437
443
|
if ( encrypted ) {
|
|
438
444
|
rval = rb_str_new2( encrypted );
|
|
439
445
|
PQfreemem( encrypted );
|
|
@@ -443,7 +449,6 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
|
443
449
|
|
|
444
450
|
return rval;
|
|
445
451
|
}
|
|
446
|
-
#endif
|
|
447
452
|
|
|
448
453
|
|
|
449
454
|
/*
|
|
@@ -560,7 +565,7 @@ static VALUE
|
|
|
560
565
|
pgconn_sync_reset( VALUE self )
|
|
561
566
|
{
|
|
562
567
|
pgconn_close_socket_io( self );
|
|
563
|
-
|
|
568
|
+
PQreset( pg_get_pgconn(self) );
|
|
564
569
|
return self;
|
|
565
570
|
}
|
|
566
571
|
|
|
@@ -568,13 +573,17 @@ static VALUE
|
|
|
568
573
|
pgconn_reset_start2( VALUE self, VALUE conninfo )
|
|
569
574
|
{
|
|
570
575
|
t_pg_connection *this = pg_get_connection( self );
|
|
576
|
+
/* Ensure conninfo is a valid C string before closing the connection. */
|
|
577
|
+
char *p_conninfo = StringValueCStr(conninfo);
|
|
571
578
|
|
|
572
579
|
/* Close old connection */
|
|
573
580
|
pgconn_close_socket_io( self );
|
|
574
581
|
PQfinish( this->pgconn );
|
|
582
|
+
this->pgconn = NULL; /* Ensure no double free can happen. */
|
|
575
583
|
|
|
576
584
|
/* Start new connection */
|
|
577
|
-
this->pgconn = gvl_PQconnectStart(
|
|
585
|
+
this->pgconn = gvl_PQconnectStart( p_conninfo );
|
|
586
|
+
RB_GC_GUARD(conninfo);
|
|
578
587
|
|
|
579
588
|
if( this->pgconn == NULL )
|
|
580
589
|
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
|
@@ -609,7 +618,7 @@ pgconn_reset_start(VALUE self)
|
|
|
609
618
|
* conn.reset_poll -> Integer
|
|
610
619
|
*
|
|
611
620
|
* Checks the status of a connection reset operation.
|
|
612
|
-
* See
|
|
621
|
+
* See Connection.connect_start and #connect_poll for
|
|
613
622
|
* usage information and return values.
|
|
614
623
|
*/
|
|
615
624
|
static VALUE
|
|
@@ -760,7 +769,6 @@ pgconn_options(VALUE self)
|
|
|
760
769
|
*
|
|
761
770
|
* Returns the connection options used by a live connection.
|
|
762
771
|
*
|
|
763
|
-
* Available since PostgreSQL-9.3
|
|
764
772
|
*/
|
|
765
773
|
static VALUE
|
|
766
774
|
pgconn_conninfo( VALUE self )
|
|
@@ -847,31 +855,79 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
|
847
855
|
* call-seq:
|
|
848
856
|
* conn.protocol_version -> Integer
|
|
849
857
|
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
858
|
+
* Interrogates the frontend/backend protocol being used.
|
|
859
|
+
*
|
|
860
|
+
* Applications might wish to use this function to determine whether certain features are supported.
|
|
861
|
+
* Currently, the only value is 3 (3.0 protocol).
|
|
862
|
+
* The protocol version will not change after connection startup is complete, but it could theoretically change during a connection reset.
|
|
863
|
+
* The 3.0 protocol is supported by PostgreSQL server versions 7.4 and above.
|
|
864
|
+
*
|
|
865
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
|
853
866
|
*/
|
|
854
867
|
static VALUE
|
|
855
868
|
pgconn_protocol_version(VALUE self)
|
|
856
869
|
{
|
|
857
|
-
|
|
870
|
+
int protocol_version = PQprotocolVersion(pg_get_pgconn(self));
|
|
871
|
+
if (protocol_version == 0) {
|
|
872
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQprotocolVersion() can't get protocol version");
|
|
873
|
+
}
|
|
874
|
+
return INT2NUM(protocol_version);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
#ifdef LIBPQ_HAS_FULL_PROTOCOL_VERSION
|
|
878
|
+
/*
|
|
879
|
+
* call-seq:
|
|
880
|
+
* conn.full_protocol_version -> Integer
|
|
881
|
+
*
|
|
882
|
+
* Interrogates the frontend/backend protocol being used, including minor version.
|
|
883
|
+
*
|
|
884
|
+
* Applications might wish to use this function to determine whether certain features are supported.
|
|
885
|
+
* The result is the major version multiplied by 10000 added to the minor version, e.g. 30002 for version 3.2.
|
|
886
|
+
* The protocol version will not change after connection startup is complete, but it could theoretically change during a connection reset.
|
|
887
|
+
* The 3.0 protocol is supported by PostgreSQL server versions 7.4 and above.
|
|
888
|
+
*
|
|
889
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
|
890
|
+
*
|
|
891
|
+
* Available since PostgreSQL-18.
|
|
892
|
+
*/
|
|
893
|
+
static VALUE
|
|
894
|
+
pgconn_full_protocol_version(VALUE self)
|
|
895
|
+
{
|
|
896
|
+
int protocol_version = PQfullProtocolVersion(pg_get_pgconn(self));
|
|
897
|
+
if (protocol_version == 0) {
|
|
898
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQfullProtocolVersion() can't get protocol version");
|
|
899
|
+
}
|
|
900
|
+
return INT2NUM(protocol_version);
|
|
858
901
|
}
|
|
902
|
+
#endif
|
|
859
903
|
|
|
860
904
|
/*
|
|
861
905
|
* call-seq:
|
|
862
906
|
* conn.server_version -> Integer
|
|
863
907
|
*
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
*
|
|
868
|
-
*
|
|
908
|
+
* Returns an integer representing the server version.
|
|
909
|
+
*
|
|
910
|
+
* Applications might use this function to determine the version of the database server they are connected to.
|
|
911
|
+
* The result is formed by multiplying the server's major version number by 10000 and adding the minor version number.
|
|
912
|
+
* For example, version 10.1 will be returned as 100001, and version 11.0 will be returned as 110000.
|
|
913
|
+
*
|
|
914
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
|
915
|
+
*
|
|
916
|
+
* Prior to major version 10, PostgreSQL used three-part version numbers in which the first two parts together represented the major version.
|
|
917
|
+
* For those versions, PQserverVersion uses two digits for each part; for example version 9.1.5 will be returned as 90105, and version 9.2.0 will be returned as 90200.
|
|
918
|
+
*
|
|
919
|
+
* Therefore, for purposes of determining feature compatibility, applications should divide the result of PQserverVersion by 100 not 10000 to determine a logical major version number.
|
|
920
|
+
* In all release series, only the last two digits differ between minor releases (bug-fix releases).
|
|
869
921
|
*
|
|
870
922
|
*/
|
|
871
923
|
static VALUE
|
|
872
924
|
pgconn_server_version(VALUE self)
|
|
873
925
|
{
|
|
874
|
-
|
|
926
|
+
int server_version = PQserverVersion(pg_get_pgconn(self));
|
|
927
|
+
if (server_version == 0) {
|
|
928
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQserverVersion() can't get server version");
|
|
929
|
+
}
|
|
930
|
+
return INT2NUM(server_version);
|
|
875
931
|
}
|
|
876
932
|
|
|
877
933
|
/*
|
|
@@ -920,13 +976,42 @@ pgconn_socket(VALUE self)
|
|
|
920
976
|
return INT2NUM(sd);
|
|
921
977
|
}
|
|
922
978
|
|
|
979
|
+
|
|
980
|
+
VALUE
|
|
981
|
+
pg_wrap_socket_io(int sd, VALUE self, VALUE *p_socket_io, int *p_ruby_sd)
|
|
982
|
+
{
|
|
983
|
+
int ruby_sd;
|
|
984
|
+
VALUE cSocket;
|
|
985
|
+
VALUE socket_io = *p_socket_io;
|
|
986
|
+
|
|
987
|
+
#ifdef _WIN32
|
|
988
|
+
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
|
989
|
+
if( ruby_sd == -1 )
|
|
990
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
|
991
|
+
|
|
992
|
+
*p_ruby_sd = ruby_sd;
|
|
993
|
+
#else
|
|
994
|
+
*p_ruby_sd = ruby_sd = sd;
|
|
995
|
+
#endif
|
|
996
|
+
|
|
997
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
|
998
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
|
999
|
+
|
|
1000
|
+
/* Disable autoclose feature */
|
|
1001
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
|
1002
|
+
|
|
1003
|
+
RB_OBJ_WRITE(self, p_socket_io, socket_io);
|
|
1004
|
+
|
|
1005
|
+
return socket_io;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
923
1008
|
/*
|
|
924
1009
|
* call-seq:
|
|
925
1010
|
* conn.socket_io() -> IO
|
|
926
1011
|
*
|
|
927
1012
|
* Fetch an IO object created from the Connection's underlying socket.
|
|
928
1013
|
* 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.
|
|
929
|
-
* <tt>IO#wait_*able</tt> is
|
|
1014
|
+
* <tt>IO#wait_*able</tt> is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
|
|
930
1015
|
*
|
|
931
1016
|
* The IO object can change while the connection is established, but is memorized afterwards.
|
|
932
1017
|
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
|
@@ -937,37 +1022,17 @@ pgconn_socket(VALUE self)
|
|
|
937
1022
|
static VALUE
|
|
938
1023
|
pgconn_socket_io(VALUE self)
|
|
939
1024
|
{
|
|
940
|
-
int sd;
|
|
941
|
-
int ruby_sd;
|
|
942
1025
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
943
|
-
VALUE cSocket;
|
|
944
|
-
VALUE socket_io = this->socket_io;
|
|
945
1026
|
|
|
946
|
-
if ( !RTEST(socket_io) ) {
|
|
1027
|
+
if ( !RTEST(this->socket_io) ) {
|
|
1028
|
+
int sd;
|
|
947
1029
|
if( (sd = PQsocket(this->pgconn)) < 0){
|
|
948
1030
|
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
|
949
1031
|
}
|
|
950
|
-
|
|
951
|
-
#ifdef _WIN32
|
|
952
|
-
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
|
953
|
-
if( ruby_sd == -1 )
|
|
954
|
-
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
|
955
|
-
|
|
956
|
-
this->ruby_sd = ruby_sd;
|
|
957
|
-
#else
|
|
958
|
-
ruby_sd = sd;
|
|
959
|
-
#endif
|
|
960
|
-
|
|
961
|
-
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
|
962
|
-
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
|
963
|
-
|
|
964
|
-
/* Disable autoclose feature */
|
|
965
|
-
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
|
966
|
-
|
|
967
|
-
RB_OBJ_WRITE(self, &this->socket_io, socket_io);
|
|
1032
|
+
return pg_wrap_socket_io( sd, self, &this->socket_io, &this->ruby_sd);
|
|
968
1033
|
}
|
|
969
1034
|
|
|
970
|
-
return socket_io;
|
|
1035
|
+
return this->socket_io;
|
|
971
1036
|
}
|
|
972
1037
|
|
|
973
1038
|
/*
|
|
@@ -984,6 +1049,7 @@ pgconn_backend_pid(VALUE self)
|
|
|
984
1049
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
|
985
1050
|
}
|
|
986
1051
|
|
|
1052
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
987
1053
|
typedef struct
|
|
988
1054
|
{
|
|
989
1055
|
struct sockaddr_storage addr;
|
|
@@ -1028,6 +1094,7 @@ pgconn_backend_key(VALUE self)
|
|
|
1028
1094
|
|
|
1029
1095
|
return INT2NUM(be_key);
|
|
1030
1096
|
}
|
|
1097
|
+
#endif
|
|
1031
1098
|
|
|
1032
1099
|
/*
|
|
1033
1100
|
* call-seq:
|
|
@@ -1069,11 +1136,11 @@ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
|
|
1069
1136
|
* This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
|
|
1070
1137
|
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
|
1071
1138
|
*
|
|
1072
|
-
*
|
|
1073
|
-
* However #async_exec has two advantages:
|
|
1139
|
+
* However #async_exec has some advantages:
|
|
1074
1140
|
*
|
|
1075
|
-
* 1. #async_exec
|
|
1076
|
-
* 2.
|
|
1141
|
+
* 1. Only #async_exec allows concurrent threads to run, while waiting for a server response.
|
|
1142
|
+
* 2. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
|
|
1143
|
+
* 3. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
|
|
1077
1144
|
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
|
1078
1145
|
*/
|
|
1079
1146
|
static VALUE
|
|
@@ -1086,8 +1153,10 @@ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
|
|
1086
1153
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
|
1087
1154
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
|
1088
1155
|
VALUE query_str = argv[0];
|
|
1156
|
+
VALUE transcoded_str;
|
|
1089
1157
|
|
|
1090
|
-
result =
|
|
1158
|
+
result = PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx, &transcoded_str));
|
|
1159
|
+
RB_GC_GUARD(transcoded_str);
|
|
1091
1160
|
rb_pgresult = pg_new_result(result, self);
|
|
1092
1161
|
pg_result_check(rb_pgresult);
|
|
1093
1162
|
if (rb_block_given_p()) {
|
|
@@ -1225,7 +1294,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1225
1294
|
int nParams;
|
|
1226
1295
|
int i=0;
|
|
1227
1296
|
t_pg_coder *conv;
|
|
1228
|
-
|
|
1297
|
+
size_t required_pool_size;
|
|
1229
1298
|
char *memory_pool;
|
|
1230
1299
|
|
|
1231
1300
|
Check_Type(paramsData->params, T_ARRAY);
|
|
@@ -1237,7 +1306,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1237
1306
|
paramsData->typecast_heap_chain = Qnil;
|
|
1238
1307
|
paramsData->gc_array = Qnil;
|
|
1239
1308
|
|
|
1240
|
-
nParams = (
|
|
1309
|
+
nParams = RARRAY_LENINT(paramsData->params);
|
|
1241
1310
|
|
|
1242
1311
|
required_pool_size = nParams * (
|
|
1243
1312
|
sizeof(char *) +
|
|
@@ -1300,7 +1369,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1300
1369
|
paramsData->lengths[i] = 0;
|
|
1301
1370
|
} else {
|
|
1302
1371
|
t_pg_coder_enc_func enc_func = pg_coder_enc_func( conv );
|
|
1303
|
-
VALUE intermediate;
|
|
1372
|
+
VALUE intermediate = Qnil;
|
|
1304
1373
|
|
|
1305
1374
|
/* 1st pass for retiving the required memory space */
|
|
1306
1375
|
int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
|
|
@@ -1340,8 +1409,6 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1340
1409
|
required_pool_size += len;
|
|
1341
1410
|
}
|
|
1342
1411
|
}
|
|
1343
|
-
|
|
1344
|
-
RB_GC_GUARD(intermediate);
|
|
1345
1412
|
}
|
|
1346
1413
|
}
|
|
1347
1414
|
}
|
|
@@ -1386,6 +1453,7 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1386
1453
|
PGresult *result = NULL;
|
|
1387
1454
|
VALUE rb_pgresult;
|
|
1388
1455
|
VALUE command, in_res_fmt;
|
|
1456
|
+
VALUE transcoded_str;
|
|
1389
1457
|
int nParams;
|
|
1390
1458
|
int resultFormat;
|
|
1391
1459
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1407,9 +1475,10 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1407
1475
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
1408
1476
|
nParams = alloc_query_params( ¶msData );
|
|
1409
1477
|
|
|
1410
|
-
result =
|
|
1478
|
+
result = PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
|
|
1411
1479
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
|
1412
1480
|
|
|
1481
|
+
RB_GC_GUARD(transcoded_str);
|
|
1413
1482
|
free_query_params( ¶msData );
|
|
1414
1483
|
|
|
1415
1484
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -1438,6 +1507,7 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1438
1507
|
VALUE rb_pgresult;
|
|
1439
1508
|
VALUE name, command, in_paramtypes;
|
|
1440
1509
|
VALUE param;
|
|
1510
|
+
VALUE transcoded_str1, transcoded_str2;
|
|
1441
1511
|
int i = 0;
|
|
1442
1512
|
int nParams = 0;
|
|
1443
1513
|
Oid *paramTypes = NULL;
|
|
@@ -1446,12 +1516,12 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1446
1516
|
int enc_idx = this->enc_idx;
|
|
1447
1517
|
|
|
1448
1518
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
|
1449
|
-
name_cstr = pg_cstr_enc(name, enc_idx);
|
|
1450
|
-
command_cstr = pg_cstr_enc(command, enc_idx);
|
|
1519
|
+
name_cstr = pg_cstr_enc(name, enc_idx, &transcoded_str1);
|
|
1520
|
+
command_cstr = pg_cstr_enc(command, enc_idx, &transcoded_str2);
|
|
1451
1521
|
|
|
1452
1522
|
if(! NIL_P(in_paramtypes)) {
|
|
1453
1523
|
Check_Type(in_paramtypes, T_ARRAY);
|
|
1454
|
-
nParams = (
|
|
1524
|
+
nParams = RARRAY_LENINT(in_paramtypes);
|
|
1455
1525
|
paramTypes = ALLOC_N(Oid, nParams);
|
|
1456
1526
|
for(i = 0; i < nParams; i++) {
|
|
1457
1527
|
param = rb_ary_entry(in_paramtypes, i);
|
|
@@ -1461,8 +1531,10 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1461
1531
|
paramTypes[i] = NUM2UINT(param);
|
|
1462
1532
|
}
|
|
1463
1533
|
}
|
|
1464
|
-
result =
|
|
1534
|
+
result = PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
|
1465
1535
|
|
|
1536
|
+
RB_GC_GUARD(transcoded_str1);
|
|
1537
|
+
RB_GC_GUARD(transcoded_str2);
|
|
1466
1538
|
xfree(paramTypes);
|
|
1467
1539
|
|
|
1468
1540
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -1486,6 +1558,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1486
1558
|
PGresult *result = NULL;
|
|
1487
1559
|
VALUE rb_pgresult;
|
|
1488
1560
|
VALUE name, in_res_fmt;
|
|
1561
|
+
VALUE transcoded_str;
|
|
1489
1562
|
int nParams;
|
|
1490
1563
|
int resultFormat;
|
|
1491
1564
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1501,10 +1574,11 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1501
1574
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
1502
1575
|
nParams = alloc_query_params( ¶msData );
|
|
1503
1576
|
|
|
1504
|
-
result =
|
|
1577
|
+
result = PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
|
|
1505
1578
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
|
1506
1579
|
resultFormat);
|
|
1507
1580
|
|
|
1581
|
+
RB_GC_GUARD(transcoded_str);
|
|
1508
1582
|
free_query_params( ¶msData );
|
|
1509
1583
|
|
|
1510
1584
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -1516,6 +1590,23 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1516
1590
|
return rb_pgresult;
|
|
1517
1591
|
}
|
|
1518
1592
|
|
|
1593
|
+
static VALUE
|
|
1594
|
+
pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*func)(PGconn *, const char *))
|
|
1595
|
+
{
|
|
1596
|
+
PGresult *result;
|
|
1597
|
+
VALUE rb_pgresult;
|
|
1598
|
+
VALUE transcoded_str;
|
|
1599
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1600
|
+
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx, &transcoded_str);
|
|
1601
|
+
|
|
1602
|
+
result = func(this->pgconn, stmt);
|
|
1603
|
+
|
|
1604
|
+
RB_GC_GUARD(transcoded_str);
|
|
1605
|
+
rb_pgresult = pg_new_result(result, self);
|
|
1606
|
+
pg_result_check(rb_pgresult);
|
|
1607
|
+
return rb_pgresult;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1519
1610
|
/*
|
|
1520
1611
|
* call-seq:
|
|
1521
1612
|
* conn.sync_describe_prepared( statement_name ) -> PG::Result
|
|
@@ -1527,20 +1618,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1527
1618
|
static VALUE
|
|
1528
1619
|
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1529
1620
|
{
|
|
1530
|
-
|
|
1531
|
-
VALUE rb_pgresult;
|
|
1532
|
-
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1533
|
-
const char *stmt;
|
|
1534
|
-
if(NIL_P(stmt_name)) {
|
|
1535
|
-
stmt = NULL;
|
|
1536
|
-
}
|
|
1537
|
-
else {
|
|
1538
|
-
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
|
1539
|
-
}
|
|
1540
|
-
result = gvl_PQdescribePrepared(this->pgconn, stmt);
|
|
1541
|
-
rb_pgresult = pg_new_result(result, self);
|
|
1542
|
-
pg_result_check(rb_pgresult);
|
|
1543
|
-
return rb_pgresult;
|
|
1621
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQdescribePrepared);
|
|
1544
1622
|
}
|
|
1545
1623
|
|
|
1546
1624
|
|
|
@@ -1555,22 +1633,43 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
1555
1633
|
static VALUE
|
|
1556
1634
|
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
1557
1635
|
{
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1636
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQdescribePortal);
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
|
|
1640
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
1641
|
+
/*
|
|
1642
|
+
* call-seq:
|
|
1643
|
+
* conn.sync_close_prepared( stmt_name ) -> PG::Result
|
|
1644
|
+
*
|
|
1645
|
+
* This function has the same behavior as #async_close_prepared, but is implemented using the synchronous command processing API of libpq.
|
|
1646
|
+
* See #async_exec for the differences between the two API variants.
|
|
1647
|
+
* It's not recommended to use explicit sync or async variants but #close_prepared instead, unless you have a good reason to do so.
|
|
1648
|
+
*
|
|
1649
|
+
* Available since PostgreSQL-17.
|
|
1650
|
+
*/
|
|
1651
|
+
static VALUE
|
|
1652
|
+
pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
|
|
1653
|
+
{
|
|
1654
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQclosePrepared);
|
|
1572
1655
|
}
|
|
1573
1656
|
|
|
1657
|
+
/*
|
|
1658
|
+
* call-seq:
|
|
1659
|
+
* conn.sync_close_portal( portal_name ) -> PG::Result
|
|
1660
|
+
*
|
|
1661
|
+
* This function has the same behavior as #async_close_portal, but is implemented using the synchronous command processing API of libpq.
|
|
1662
|
+
* See #async_exec for the differences between the two API variants.
|
|
1663
|
+
* It's not recommended to use explicit sync or async variants but #close_portal instead, unless you have a good reason to do so.
|
|
1664
|
+
*
|
|
1665
|
+
* Available since PostgreSQL-17.
|
|
1666
|
+
*/
|
|
1667
|
+
static VALUE
|
|
1668
|
+
pgconn_sync_close_portal(VALUE self, VALUE stmt_name)
|
|
1669
|
+
{
|
|
1670
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQclosePortal);
|
|
1671
|
+
}
|
|
1672
|
+
#endif
|
|
1574
1673
|
|
|
1575
1674
|
/*
|
|
1576
1675
|
* call-seq:
|
|
@@ -1588,6 +1687,7 @@ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
|
1588
1687
|
* * +PGRES_FATAL_ERROR+
|
|
1589
1688
|
* * +PGRES_COPY_BOTH+
|
|
1590
1689
|
* * +PGRES_SINGLE_TUPLE+
|
|
1690
|
+
* * +PGRES_TUPLES_CHUNK+
|
|
1591
1691
|
* * +PGRES_PIPELINE_SYNC+
|
|
1592
1692
|
* * +PGRES_PIPELINE_ABORTED+
|
|
1593
1693
|
*/
|
|
@@ -1812,14 +1912,11 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
|
1812
1912
|
* (column names, types, etc) that an ordinary Result object for the query
|
|
1813
1913
|
* would have.
|
|
1814
1914
|
*
|
|
1815
|
-
* *Caution:* While processing a query, the server may return some rows and
|
|
1816
|
-
*
|
|
1817
|
-
*
|
|
1818
|
-
*
|
|
1819
|
-
* application
|
|
1820
|
-
* For proper transactional behavior, the application must be designed to discard
|
|
1821
|
-
* or undo whatever has been done with the previously-processed rows, if the query
|
|
1822
|
-
* ultimately fails.
|
|
1915
|
+
* *Caution:* While processing a query, the server may return some rows and then encounter an error, causing the query to be aborted.
|
|
1916
|
+
* Ordinarily, pg discards any such rows and reports only the error.
|
|
1917
|
+
* But in single-row or chunked mode, some rows may have already been returned to the application.
|
|
1918
|
+
* Hence, the application will see some PGRES_SINGLE_TUPLE or PGRES_TUPLES_CHUNK PG::Result objects followed by a PG::Error raised in get_result.
|
|
1919
|
+
* For proper transactional behavior, the application must be designed to discard or undo whatever has been done with the previously-processed rows, if the query ultimately fails.
|
|
1823
1920
|
*
|
|
1824
1921
|
* Example:
|
|
1825
1922
|
* conn.send_query( "your SQL command" )
|
|
@@ -1839,10 +1936,49 @@ pgconn_set_single_row_mode(VALUE self)
|
|
|
1839
1936
|
|
|
1840
1937
|
rb_check_frozen(self);
|
|
1841
1938
|
if( PQsetSingleRowMode(conn) == 0 )
|
|
1842
|
-
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
1939
|
+
pg_raise_conn_error( rb_ePGerror, self, "PQsetSingleRowMode %s", PQerrorMessage(conn));
|
|
1940
|
+
|
|
1941
|
+
return self;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
1945
|
+
/*
|
|
1946
|
+
* call-seq:
|
|
1947
|
+
* conn.set_chunked_rows_mode -> self
|
|
1948
|
+
*
|
|
1949
|
+
* Select chunked mode for the currently-executing query.
|
|
1950
|
+
*
|
|
1951
|
+
* This function is similar to set_single_row_mode, except that it specifies retrieval of up to +chunk_size+ rows per PGresult, not necessarily just one row.
|
|
1952
|
+
* This function can only be called immediately after send_query or one of its sibling functions, before any other operation on the connection such as consume_input or get_result.
|
|
1953
|
+
* If called at the correct time, the function activates chunked mode for the current query.
|
|
1954
|
+
* Otherwise the mode stays unchanged and the function raises an error.
|
|
1955
|
+
* In any case, the mode reverts to normal after completion of the current query.
|
|
1956
|
+
*
|
|
1957
|
+
* Example:
|
|
1958
|
+
* conn.send_query( "your SQL command" )
|
|
1959
|
+
* conn.set_chunked_rows_mode(10)
|
|
1960
|
+
* loop do
|
|
1961
|
+
* res = conn.get_result or break
|
|
1962
|
+
* res.check
|
|
1963
|
+
* res.each do |row|
|
|
1964
|
+
* # do something with the received max. 10 rows
|
|
1965
|
+
* end
|
|
1966
|
+
* end
|
|
1967
|
+
*
|
|
1968
|
+
* Available since PostgreSQL-17
|
|
1969
|
+
*/
|
|
1970
|
+
static VALUE
|
|
1971
|
+
pgconn_set_chunked_rows_mode(VALUE self, VALUE chunk_size)
|
|
1972
|
+
{
|
|
1973
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
1974
|
+
|
|
1975
|
+
rb_check_frozen(self);
|
|
1976
|
+
if( PQsetChunkedRowsMode(conn, NUM2INT(chunk_size)) == 0 )
|
|
1977
|
+
pg_raise_conn_error( rb_ePGerror, self, "PQsetChunkedRowsMode %s", PQerrorMessage(conn));
|
|
1843
1978
|
|
|
1844
1979
|
return self;
|
|
1845
1980
|
}
|
|
1981
|
+
#endif
|
|
1846
1982
|
|
|
1847
1983
|
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
|
1848
1984
|
|
|
@@ -1862,13 +1998,15 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
|
|
1862
1998
|
static VALUE
|
|
1863
1999
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1864
2000
|
{
|
|
2001
|
+
VALUE transcoded_str;
|
|
1865
2002
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1866
2003
|
|
|
1867
2004
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
|
1868
2005
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
|
1869
|
-
if(
|
|
1870
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2006
|
+
if(PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx, &transcoded_str)) == 0)
|
|
2007
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));
|
|
1871
2008
|
|
|
2009
|
+
RB_GC_GUARD(transcoded_str);
|
|
1872
2010
|
pgconn_wait_for_flush( self );
|
|
1873
2011
|
return Qnil;
|
|
1874
2012
|
}
|
|
@@ -1925,6 +2063,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1925
2063
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1926
2064
|
int result;
|
|
1927
2065
|
VALUE command, in_res_fmt;
|
|
2066
|
+
VALUE transcoded_str;
|
|
1928
2067
|
int nParams;
|
|
1929
2068
|
int resultFormat;
|
|
1930
2069
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1936,13 +2075,14 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1936
2075
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
1937
2076
|
nParams = alloc_query_params( ¶msData );
|
|
1938
2077
|
|
|
1939
|
-
result =
|
|
2078
|
+
result = PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
|
|
1940
2079
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
|
1941
2080
|
|
|
2081
|
+
RB_GC_GUARD(transcoded_str);
|
|
1942
2082
|
free_query_params( ¶msData );
|
|
1943
2083
|
|
|
1944
2084
|
if(result == 0)
|
|
1945
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2085
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryParams %s", PQerrorMessage(this->pgconn));
|
|
1946
2086
|
|
|
1947
2087
|
pgconn_wait_for_flush( self );
|
|
1948
2088
|
return Qnil;
|
|
@@ -1975,6 +2115,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1975
2115
|
int result;
|
|
1976
2116
|
VALUE name, command, in_paramtypes;
|
|
1977
2117
|
VALUE param;
|
|
2118
|
+
VALUE transcoded_str1, transcoded_str2;
|
|
1978
2119
|
int i = 0;
|
|
1979
2120
|
int nParams = 0;
|
|
1980
2121
|
Oid *paramTypes = NULL;
|
|
@@ -1983,12 +2124,12 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1983
2124
|
int enc_idx = this->enc_idx;
|
|
1984
2125
|
|
|
1985
2126
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
|
1986
|
-
name_cstr = pg_cstr_enc(name, enc_idx);
|
|
1987
|
-
command_cstr = pg_cstr_enc(command, enc_idx);
|
|
2127
|
+
name_cstr = pg_cstr_enc(name, enc_idx, &transcoded_str1);
|
|
2128
|
+
command_cstr = pg_cstr_enc(command, enc_idx, &transcoded_str2);
|
|
1988
2129
|
|
|
1989
2130
|
if(! NIL_P(in_paramtypes)) {
|
|
1990
2131
|
Check_Type(in_paramtypes, T_ARRAY);
|
|
1991
|
-
nParams = (
|
|
2132
|
+
nParams = RARRAY_LENINT(in_paramtypes);
|
|
1992
2133
|
paramTypes = ALLOC_N(Oid, nParams);
|
|
1993
2134
|
for(i = 0; i < nParams; i++) {
|
|
1994
2135
|
param = rb_ary_entry(in_paramtypes, i);
|
|
@@ -1998,12 +2139,14 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1998
2139
|
paramTypes[i] = NUM2UINT(param);
|
|
1999
2140
|
}
|
|
2000
2141
|
}
|
|
2001
|
-
result =
|
|
2142
|
+
result = PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
|
2002
2143
|
|
|
2144
|
+
RB_GC_GUARD(transcoded_str1);
|
|
2145
|
+
RB_GC_GUARD(transcoded_str2);
|
|
2003
2146
|
xfree(paramTypes);
|
|
2004
2147
|
|
|
2005
2148
|
if(result == 0) {
|
|
2006
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2149
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendPrepare %s", PQerrorMessage(this->pgconn));
|
|
2007
2150
|
}
|
|
2008
2151
|
pgconn_wait_for_flush( self );
|
|
2009
2152
|
return Qnil;
|
|
@@ -2047,6 +2190,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2047
2190
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2048
2191
|
int result;
|
|
2049
2192
|
VALUE name, in_res_fmt;
|
|
2193
|
+
VALUE transcoded_str;
|
|
2050
2194
|
int nParams;
|
|
2051
2195
|
int resultFormat;
|
|
2052
2196
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -2062,15 +2206,32 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2062
2206
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
2063
2207
|
nParams = alloc_query_params( ¶msData );
|
|
2064
2208
|
|
|
2065
|
-
result =
|
|
2209
|
+
result = PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
|
|
2066
2210
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
|
2067
2211
|
resultFormat);
|
|
2068
2212
|
|
|
2213
|
+
RB_GC_GUARD(transcoded_str);
|
|
2069
2214
|
free_query_params( ¶msData );
|
|
2070
2215
|
|
|
2071
2216
|
if(result == 0)
|
|
2072
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2217
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryPrepared %s", PQerrorMessage(this->pgconn));
|
|
2218
|
+
|
|
2219
|
+
pgconn_wait_for_flush( self );
|
|
2220
|
+
return Qnil;
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
|
|
2224
|
+
static VALUE
|
|
2225
|
+
pgconn_send_describe_close_prepared_portal(VALUE self, VALUE name, int (*func)(PGconn *, const char *), const char *funame)
|
|
2226
|
+
{
|
|
2227
|
+
VALUE transcoded_str;
|
|
2228
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2229
|
+
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx, &transcoded_str);
|
|
2230
|
+
/* returns 0 on failure */
|
|
2231
|
+
if(func(this->pgconn, stmt) == 0)
|
|
2232
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s %s", funame, PQerrorMessage(this->pgconn));
|
|
2073
2233
|
|
|
2234
|
+
RB_GC_GUARD(transcoded_str);
|
|
2074
2235
|
pgconn_wait_for_flush( self );
|
|
2075
2236
|
return Qnil;
|
|
2076
2237
|
}
|
|
@@ -2085,13 +2246,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2085
2246
|
static VALUE
|
|
2086
2247
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2087
2248
|
{
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2092
|
-
|
|
2093
|
-
pgconn_wait_for_flush( self );
|
|
2094
|
-
return Qnil;
|
|
2249
|
+
return pgconn_send_describe_close_prepared_portal(
|
|
2250
|
+
self, stmt_name, PQsendDescribePrepared,
|
|
2251
|
+
"PQsendDescribePrepared");
|
|
2095
2252
|
}
|
|
2096
2253
|
|
|
2097
2254
|
|
|
@@ -2105,16 +2262,48 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
2105
2262
|
static VALUE
|
|
2106
2263
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
2107
2264
|
{
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2265
|
+
return pgconn_send_describe_close_prepared_portal(
|
|
2266
|
+
self, portal, PQsendDescribePortal,
|
|
2267
|
+
"PQsendDescribePortal");
|
|
2268
|
+
}
|
|
2112
2269
|
|
|
2113
|
-
|
|
2114
|
-
|
|
2270
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
2271
|
+
/*
|
|
2272
|
+
* call-seq:
|
|
2273
|
+
* conn.send_close_prepared( statement_name ) -> nil
|
|
2274
|
+
*
|
|
2275
|
+
* Asynchronously send _command_ to the server. Does not block.
|
|
2276
|
+
* Use in combination with +conn.get_result+.
|
|
2277
|
+
*
|
|
2278
|
+
* Available since PostgreSQL-17.
|
|
2279
|
+
*/
|
|
2280
|
+
static VALUE
|
|
2281
|
+
pgconn_send_close_prepared(VALUE self, VALUE stmt_name)
|
|
2282
|
+
{
|
|
2283
|
+
return pgconn_send_describe_close_prepared_portal(
|
|
2284
|
+
self, stmt_name, PQsendClosePrepared,
|
|
2285
|
+
"PQsendClosePrepared");
|
|
2115
2286
|
}
|
|
2116
2287
|
|
|
2117
2288
|
|
|
2289
|
+
/*
|
|
2290
|
+
* call-seq:
|
|
2291
|
+
* conn.send_close_portal( portal_name ) -> nil
|
|
2292
|
+
*
|
|
2293
|
+
* Asynchronously send _command_ to the server. Does not block.
|
|
2294
|
+
* Use in combination with +conn.get_result+.
|
|
2295
|
+
*
|
|
2296
|
+
* Available since PostgreSQL-17.
|
|
2297
|
+
*/
|
|
2298
|
+
static VALUE
|
|
2299
|
+
pgconn_send_close_portal(VALUE self, VALUE portal)
|
|
2300
|
+
{
|
|
2301
|
+
return pgconn_send_describe_close_prepared_portal(
|
|
2302
|
+
self, portal, PQsendClosePortal,
|
|
2303
|
+
"PQsendClosePortal");
|
|
2304
|
+
}
|
|
2305
|
+
#endif
|
|
2306
|
+
|
|
2118
2307
|
static VALUE
|
|
2119
2308
|
pgconn_sync_get_result(VALUE self)
|
|
2120
2309
|
{
|
|
@@ -2122,7 +2311,7 @@ pgconn_sync_get_result(VALUE self)
|
|
|
2122
2311
|
PGresult *result;
|
|
2123
2312
|
VALUE rb_pgresult;
|
|
2124
2313
|
|
|
2125
|
-
result =
|
|
2314
|
+
result = PQgetResult(conn);
|
|
2126
2315
|
if(result == NULL)
|
|
2127
2316
|
return Qnil;
|
|
2128
2317
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -2164,7 +2353,7 @@ pgconn_consume_input(VALUE self)
|
|
|
2164
2353
|
static VALUE
|
|
2165
2354
|
pgconn_is_busy(VALUE self)
|
|
2166
2355
|
{
|
|
2167
|
-
return
|
|
2356
|
+
return PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2168
2357
|
}
|
|
2169
2358
|
|
|
2170
2359
|
static VALUE
|
|
@@ -2204,6 +2393,7 @@ pgconn_sync_flush(VALUE self)
|
|
|
2204
2393
|
return (ret) ? Qfalse : Qtrue;
|
|
2205
2394
|
}
|
|
2206
2395
|
|
|
2396
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
2207
2397
|
static VALUE
|
|
2208
2398
|
pgconn_sync_cancel(VALUE self)
|
|
2209
2399
|
{
|
|
@@ -2216,7 +2406,7 @@ pgconn_sync_cancel(VALUE self)
|
|
|
2216
2406
|
if(cancel == NULL)
|
|
2217
2407
|
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
|
2218
2408
|
|
|
2219
|
-
ret =
|
|
2409
|
+
ret = PQcancel(cancel, errbuf, sizeof(errbuf));
|
|
2220
2410
|
if(ret == 1)
|
|
2221
2411
|
retval = Qnil;
|
|
2222
2412
|
else
|
|
@@ -2225,6 +2415,7 @@ pgconn_sync_cancel(VALUE self)
|
|
|
2225
2415
|
PQfreeCancel(cancel);
|
|
2226
2416
|
return retval;
|
|
2227
2417
|
}
|
|
2418
|
+
#endif
|
|
2228
2419
|
|
|
2229
2420
|
|
|
2230
2421
|
/*
|
|
@@ -2247,12 +2438,12 @@ pgconn_notifies(VALUE self)
|
|
|
2247
2438
|
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
|
2248
2439
|
sym_extra = ID2SYM(rb_intern("extra"));
|
|
2249
2440
|
|
|
2250
|
-
notification =
|
|
2441
|
+
notification = PQnotifies(this->pgconn);
|
|
2251
2442
|
if (notification == NULL) {
|
|
2252
2443
|
return Qnil;
|
|
2253
2444
|
}
|
|
2254
2445
|
|
|
2255
|
-
hash =
|
|
2446
|
+
hash = rb_hash_new_capa(3);
|
|
2256
2447
|
relname = rb_str_new2(notification->relname);
|
|
2257
2448
|
be_pid = INT2NUM(notification->be_pid);
|
|
2258
2449
|
extra = rb_str_new2(notification->extra);
|
|
@@ -2267,32 +2458,13 @@ pgconn_notifies(VALUE self)
|
|
|
2267
2458
|
return hash;
|
|
2268
2459
|
}
|
|
2269
2460
|
|
|
2270
|
-
#ifndef HAVE_RB_IO_DESCRIPTOR
|
|
2271
|
-
static int
|
|
2272
|
-
rb_io_descriptor(VALUE io)
|
|
2273
|
-
{
|
|
2274
|
-
Check_Type(io, T_FILE);
|
|
2275
|
-
rb_io_t *fptr = RFILE(io)->fptr;
|
|
2276
|
-
rb_io_check_closed(fptr);
|
|
2277
|
-
return fptr->fd;
|
|
2278
|
-
}
|
|
2279
|
-
#endif
|
|
2280
|
-
|
|
2281
2461
|
#if defined(_WIN32)
|
|
2282
2462
|
|
|
2283
2463
|
/* We use a specialized implementation of rb_io_wait() on Windows.
|
|
2284
2464
|
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
|
2285
2465
|
*/
|
|
2286
2466
|
|
|
2287
|
-
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
|
2288
2467
|
#include <ruby/fiber/scheduler.h>
|
|
2289
|
-
#endif
|
|
2290
|
-
|
|
2291
|
-
typedef enum {
|
|
2292
|
-
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2293
|
-
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2294
|
-
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2295
|
-
} pg_rb_io_event_t;
|
|
2296
2468
|
|
|
2297
2469
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2298
2470
|
|
|
@@ -2316,9 +2488,9 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2316
2488
|
timeradd(&currtime, &ptimeout, &aborttime);
|
|
2317
2489
|
}
|
|
2318
2490
|
|
|
2319
|
-
if(rb_events &
|
|
2320
|
-
if(rb_events &
|
|
2321
|
-
if(rb_events &
|
|
2491
|
+
if(rb_events & RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
|
2492
|
+
if(rb_events & RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
|
|
2493
|
+
if(rb_events & RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
|
2322
2494
|
|
|
2323
2495
|
for(;;) {
|
|
2324
2496
|
if ( WSAEventSelect(_get_osfhandle(rb_io_descriptor(io)), hEvent, w32_events) == SOCKET_ERROR ) {
|
|
@@ -2362,49 +2534,20 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2362
2534
|
|
|
2363
2535
|
static VALUE
|
|
2364
2536
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2365
|
-
|
|
2366
|
-
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
|
2367
|
-
* Fortunately ruby-3.1 offers a C-API for it.
|
|
2368
|
-
*/
|
|
2537
|
+
/* Avoid slow rb_io_wait() on Windows, if no scheduler is active. */
|
|
2369
2538
|
VALUE scheduler = rb_fiber_scheduler_current();
|
|
2370
2539
|
|
|
2371
2540
|
if (!NIL_P(scheduler)) {
|
|
2372
2541
|
return rb_io_wait(io, events, timeout);
|
|
2373
2542
|
}
|
|
2374
|
-
#endif
|
|
2375
2543
|
return pg_rb_thread_io_wait(io, events, timeout);
|
|
2376
2544
|
}
|
|
2377
2545
|
|
|
2378
|
-
#elif defined(HAVE_RB_IO_WAIT)
|
|
2379
|
-
|
|
2380
|
-
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
|
2381
|
-
#define pg_rb_io_wait rb_io_wait
|
|
2382
|
-
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
|
2383
|
-
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
|
2384
|
-
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
|
2385
|
-
|
|
2386
2546
|
#else
|
|
2387
|
-
/* For compat with ruby < 3.0 */
|
|
2388
|
-
|
|
2389
|
-
typedef enum {
|
|
2390
|
-
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2391
|
-
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2392
|
-
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2393
|
-
} pg_rb_io_event_t;
|
|
2394
|
-
|
|
2395
|
-
static VALUE
|
|
2396
|
-
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2397
|
-
struct timeval waittime;
|
|
2398
|
-
int res;
|
|
2399
2547
|
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
|
2403
|
-
}
|
|
2404
|
-
res = rb_wait_for_single_fd(rb_io_descriptor(io), NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
|
2548
|
+
/* Use rb_io_wait on non-Windows systems */
|
|
2549
|
+
#define pg_rb_io_wait rb_io_wait
|
|
2405
2550
|
|
|
2406
|
-
return UINT2NUM(res);
|
|
2407
|
-
}
|
|
2408
2551
|
#endif
|
|
2409
2552
|
|
|
2410
2553
|
static void *
|
|
@@ -2439,7 +2582,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
|
2439
2582
|
|
|
2440
2583
|
socket_io = pgconn_socket_io(self);
|
|
2441
2584
|
/* Wait for the socket to become readable before checking again */
|
|
2442
|
-
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
2585
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), wait_timeout);
|
|
2443
2586
|
} else {
|
|
2444
2587
|
ret = Qfalse;
|
|
2445
2588
|
}
|
|
@@ -2476,9 +2619,9 @@ pgconn_async_flush(VALUE self)
|
|
|
2476
2619
|
/* wait for the socket to become read- or write-ready */
|
|
2477
2620
|
int events;
|
|
2478
2621
|
VALUE socket_io = pgconn_socket_io(self);
|
|
2479
|
-
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
2622
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
|
|
2480
2623
|
|
|
2481
|
-
if (events &
|
|
2624
|
+
if (events & RUBY_IO_READABLE){
|
|
2482
2625
|
pgconn_consume_input(self);
|
|
2483
2626
|
}
|
|
2484
2627
|
}
|
|
@@ -2504,7 +2647,7 @@ pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
|
|
2504
2647
|
static void *
|
|
2505
2648
|
notify_readable(PGconn *conn)
|
|
2506
2649
|
{
|
|
2507
|
-
return (void*)
|
|
2650
|
+
return (void*)PQnotifies(conn);
|
|
2508
2651
|
}
|
|
2509
2652
|
|
|
2510
2653
|
/*
|
|
@@ -2568,7 +2711,7 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2568
2711
|
VALUE value;
|
|
2569
2712
|
VALUE buffer = Qnil;
|
|
2570
2713
|
VALUE encoder;
|
|
2571
|
-
VALUE intermediate;
|
|
2714
|
+
VALUE intermediate = Qnil;
|
|
2572
2715
|
t_pg_coder *p_coder = NULL;
|
|
2573
2716
|
|
|
2574
2717
|
rb_scan_args( argc, argv, "11", &value, &encoder );
|
|
@@ -2603,11 +2746,10 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2603
2746
|
|
|
2604
2747
|
Check_Type(buffer, T_STRING);
|
|
2605
2748
|
|
|
2606
|
-
ret =
|
|
2749
|
+
ret = PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
|
|
2607
2750
|
if(ret == -1)
|
|
2608
2751
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2609
2752
|
|
|
2610
|
-
RB_GC_GUARD(intermediate);
|
|
2611
2753
|
RB_GC_GUARD(buffer);
|
|
2612
2754
|
|
|
2613
2755
|
return (ret) ? Qtrue : Qfalse;
|
|
@@ -2617,6 +2759,7 @@ static VALUE
|
|
|
2617
2759
|
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2618
2760
|
{
|
|
2619
2761
|
VALUE str;
|
|
2762
|
+
VALUE transcoded_str;
|
|
2620
2763
|
int ret;
|
|
2621
2764
|
const char *error_message = NULL;
|
|
2622
2765
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
@@ -2624,15 +2767,41 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
|
2624
2767
|
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
|
2625
2768
|
error_message = NULL;
|
|
2626
2769
|
else
|
|
2627
|
-
error_message = pg_cstr_enc(str, this->enc_idx);
|
|
2770
|
+
error_message = pg_cstr_enc(str, this->enc_idx, &transcoded_str);
|
|
2628
2771
|
|
|
2629
|
-
ret =
|
|
2772
|
+
ret = PQputCopyEnd(this->pgconn, error_message);
|
|
2630
2773
|
if(ret == -1)
|
|
2631
2774
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2632
2775
|
|
|
2776
|
+
RB_GC_GUARD(transcoded_str);
|
|
2633
2777
|
return (ret) ? Qtrue : Qfalse;
|
|
2634
2778
|
}
|
|
2635
2779
|
|
|
2780
|
+
struct pgconn_copy_data {
|
|
2781
|
+
t_pg_coder *coder;
|
|
2782
|
+
char *buffer;
|
|
2783
|
+
int length;
|
|
2784
|
+
int enc_idx;
|
|
2785
|
+
};
|
|
2786
|
+
|
|
2787
|
+
static VALUE
|
|
2788
|
+
pgconn_decode_copy_data(VALUE data_ptr)
|
|
2789
|
+
{
|
|
2790
|
+
struct pgconn_copy_data *data = (struct pgconn_copy_data *)data_ptr;
|
|
2791
|
+
t_pg_coder_dec_func dec_func = pg_coder_dec_func(data->coder, data->coder->format);
|
|
2792
|
+
|
|
2793
|
+
return dec_func(data->coder, data->buffer, data->length, 0, 0, data->enc_idx);
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2796
|
+
static VALUE
|
|
2797
|
+
pgconn_free_copy_data(VALUE data_ptr)
|
|
2798
|
+
{
|
|
2799
|
+
struct pgconn_copy_data *data = (struct pgconn_copy_data *)data_ptr;
|
|
2800
|
+
|
|
2801
|
+
PQfreemem(data->buffer);
|
|
2802
|
+
return Qnil;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2636
2805
|
static VALUE
|
|
2637
2806
|
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2638
2807
|
{
|
|
@@ -2655,7 +2824,7 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2655
2824
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
|
2656
2825
|
}
|
|
2657
2826
|
|
|
2658
|
-
ret =
|
|
2827
|
+
ret = PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
|
2659
2828
|
if(ret == -2){ /* error */
|
|
2660
2829
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2661
2830
|
}
|
|
@@ -2667,8 +2836,9 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2667
2836
|
}
|
|
2668
2837
|
|
|
2669
2838
|
if( p_coder ){
|
|
2670
|
-
|
|
2671
|
-
|
|
2839
|
+
struct pgconn_copy_data data = { p_coder, buffer, ret, this->enc_idx };
|
|
2840
|
+
|
|
2841
|
+
return rb_ensure(pgconn_decode_copy_data, (VALUE)&data, pgconn_free_copy_data, (VALUE)&data);
|
|
2672
2842
|
} else {
|
|
2673
2843
|
result = rb_str_new(buffer, ret);
|
|
2674
2844
|
}
|
|
@@ -2702,7 +2872,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
|
2702
2872
|
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
|
2703
2873
|
}
|
|
2704
2874
|
|
|
2705
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
|
2706
2875
|
/*
|
|
2707
2876
|
* call-seq:
|
|
2708
2877
|
* conn.set_error_context_visibility( context_visibility ) -> Integer
|
|
@@ -2722,7 +2891,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
|
2722
2891
|
*
|
|
2723
2892
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
|
|
2724
2893
|
*
|
|
2725
|
-
* Available since PostgreSQL-9.6
|
|
2726
2894
|
*/
|
|
2727
2895
|
static VALUE
|
|
2728
2896
|
pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
|
@@ -2731,7 +2899,6 @@ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
|
|
2731
2899
|
PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
|
|
2732
2900
|
return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
|
|
2733
2901
|
}
|
|
2734
|
-
#endif
|
|
2735
2902
|
|
|
2736
2903
|
/*
|
|
2737
2904
|
* call-seq:
|
|
@@ -2804,11 +2971,10 @@ pgconn_untrace(VALUE self)
|
|
|
2804
2971
|
void
|
|
2805
2972
|
notice_receiver_proxy(void *arg, const PGresult *pgresult)
|
|
2806
2973
|
{
|
|
2807
|
-
|
|
2808
|
-
t_pg_connection *this = pg_get_connection( self );
|
|
2974
|
+
t_pg_connection *this = (t_pg_connection*)arg;
|
|
2809
2975
|
|
|
2810
2976
|
if (this->notice_receiver != Qnil) {
|
|
2811
|
-
VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, self );
|
|
2977
|
+
VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, this->self );
|
|
2812
2978
|
|
|
2813
2979
|
rb_funcall(this->notice_receiver, rb_intern("call"), 1, result);
|
|
2814
2980
|
pg_result_clear( result );
|
|
@@ -2863,7 +3029,7 @@ pgconn_set_notice_receiver(VALUE self)
|
|
|
2863
3029
|
old_proc = this->notice_receiver;
|
|
2864
3030
|
if( rb_block_given_p() ) {
|
|
2865
3031
|
proc = rb_block_proc();
|
|
2866
|
-
PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)
|
|
3032
|
+
PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)this);
|
|
2867
3033
|
} else {
|
|
2868
3034
|
/* if no block is given, set back to default */
|
|
2869
3035
|
proc = Qnil;
|
|
@@ -2882,8 +3048,7 @@ pgconn_set_notice_receiver(VALUE self)
|
|
|
2882
3048
|
void
|
|
2883
3049
|
notice_processor_proxy(void *arg, const char *message)
|
|
2884
3050
|
{
|
|
2885
|
-
|
|
2886
|
-
t_pg_connection *this = pg_get_connection( self );
|
|
3051
|
+
t_pg_connection *this = (t_pg_connection*)arg;
|
|
2887
3052
|
|
|
2888
3053
|
if (this->notice_processor != Qnil) {
|
|
2889
3054
|
VALUE message_str = rb_str_new2(message);
|
|
@@ -2924,7 +3089,7 @@ pgconn_set_notice_processor(VALUE self)
|
|
|
2924
3089
|
old_proc = this->notice_processor;
|
|
2925
3090
|
if( rb_block_given_p() ) {
|
|
2926
3091
|
proc = rb_block_proc();
|
|
2927
|
-
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)
|
|
3092
|
+
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)this);
|
|
2928
3093
|
} else {
|
|
2929
3094
|
/* if no block is given, set back to default */
|
|
2930
3095
|
proc = Qnil;
|
|
@@ -2966,7 +3131,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
|
2966
3131
|
rb_check_frozen(self);
|
|
2967
3132
|
Check_Type(str, T_STRING);
|
|
2968
3133
|
|
|
2969
|
-
if ( (
|
|
3134
|
+
if ( (PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
2970
3135
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2971
3136
|
|
|
2972
3137
|
pgconn_set_internal_encoding_index( self );
|
|
@@ -3031,7 +3196,7 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
|
|
|
3031
3196
|
static void *
|
|
3032
3197
|
get_result_readable(PGconn *conn)
|
|
3033
3198
|
{
|
|
3034
|
-
return
|
|
3199
|
+
return PQisBusy(conn) ? NULL : (void*)1;
|
|
3035
3200
|
}
|
|
3036
3201
|
|
|
3037
3202
|
|
|
@@ -3089,7 +3254,7 @@ pgconn_sync_get_last_result(VALUE self)
|
|
|
3089
3254
|
|
|
3090
3255
|
|
|
3091
3256
|
cur = prev = NULL;
|
|
3092
|
-
while ((cur =
|
|
3257
|
+
while ((cur = PQgetResult(conn)) != NULL) {
|
|
3093
3258
|
int status;
|
|
3094
3259
|
|
|
3095
3260
|
if (prev) PQclear(prev);
|
|
@@ -3141,7 +3306,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
|
3141
3306
|
*/
|
|
3142
3307
|
wait_socket_readable(self, NULL, get_result_readable);
|
|
3143
3308
|
|
|
3144
|
-
cur =
|
|
3309
|
+
cur = PQgetResult(conn);
|
|
3145
3310
|
if (cur == NULL)
|
|
3146
3311
|
break;
|
|
3147
3312
|
|
|
@@ -3198,18 +3363,18 @@ pgconn_discard_results(VALUE self)
|
|
|
3198
3363
|
/* pgconn_block() raises an exception in case of errors.
|
|
3199
3364
|
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
|
3200
3365
|
*/
|
|
3201
|
-
while(
|
|
3366
|
+
while( PQisBusy(conn) ){
|
|
3202
3367
|
int events;
|
|
3203
3368
|
|
|
3204
3369
|
switch( PQflush(conn) ) {
|
|
3205
3370
|
case 1:
|
|
3206
|
-
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
3207
|
-
if (events &
|
|
3371
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
|
|
3372
|
+
if (events & RUBY_IO_READABLE){
|
|
3208
3373
|
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3209
3374
|
}
|
|
3210
3375
|
break;
|
|
3211
3376
|
case 0:
|
|
3212
|
-
pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
3377
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
|
|
3213
3378
|
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3214
3379
|
break;
|
|
3215
3380
|
default:
|
|
@@ -3217,23 +3382,23 @@ pgconn_discard_results(VALUE self)
|
|
|
3217
3382
|
}
|
|
3218
3383
|
}
|
|
3219
3384
|
|
|
3220
|
-
cur =
|
|
3385
|
+
cur = PQgetResult(conn);
|
|
3221
3386
|
if( cur == NULL) break;
|
|
3222
3387
|
|
|
3223
3388
|
status = PQresultStatus(cur);
|
|
3224
3389
|
PQclear(cur);
|
|
3225
3390
|
if (status == PGRES_COPY_IN){
|
|
3226
|
-
while(
|
|
3391
|
+
while( PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
|
|
3227
3392
|
pgconn_async_flush(self);
|
|
3228
3393
|
}
|
|
3229
3394
|
}
|
|
3230
3395
|
if (status == PGRES_COPY_OUT){
|
|
3231
3396
|
for(;;) {
|
|
3232
3397
|
char *buffer = NULL;
|
|
3233
|
-
int st =
|
|
3398
|
+
int st = PQgetCopyData(conn, &buffer, 1);
|
|
3234
3399
|
if( st == 0 ) {
|
|
3235
3400
|
/* would block -> wait for readable data */
|
|
3236
|
-
pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
3401
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
|
|
3237
3402
|
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3238
3403
|
} else if( st > 0 ) {
|
|
3239
3404
|
/* some data retrieved -> discard it */
|
|
@@ -3270,12 +3435,12 @@ error:
|
|
|
3270
3435
|
* and the PG::Result object will automatically be cleared when the block terminates.
|
|
3271
3436
|
* In this instance, <code>conn.exec</code> returns the value of the block.
|
|
3272
3437
|
*
|
|
3273
|
-
* #exec is an alias for #async_exec which is
|
|
3438
|
+
* #exec is an alias for #async_exec which is functional identical to #sync_exec .
|
|
3274
3439
|
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
|
3275
3440
|
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
|
3276
3441
|
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
|
3277
|
-
*
|
|
3278
|
-
*
|
|
3442
|
+
* Only #async_exec ensures that other threads can process while waiting for the server to complete the request.
|
|
3443
|
+
* In contrast #sync_exec blocks all threads and signals to be processed until the query is finished.
|
|
3279
3444
|
* This is most notably visible by a delayed reaction to Control+C.
|
|
3280
3445
|
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
|
3281
3446
|
*
|
|
@@ -3310,12 +3475,13 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
|
3310
3475
|
* +params+ is an array of the bind parameters for the SQL query.
|
|
3311
3476
|
* Each element of the +params+ array may be either:
|
|
3312
3477
|
* a hash of the form:
|
|
3313
|
-
* {:value
|
|
3314
|
-
* :type
|
|
3315
|
-
* :
|
|
3478
|
+
* {:value => String (value of bind parameter)
|
|
3479
|
+
* :type => Integer (oid of type of bind parameter)
|
|
3480
|
+
* :typename => String (name of type of bind parameter, only used for conn.embed_params )
|
|
3481
|
+
* :format => Integer (0 for text, 1 for binary)
|
|
3316
3482
|
* }
|
|
3317
3483
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
3318
|
-
* { :value
|
|
3484
|
+
* { :value => <string value>, :type => 0, :format => 0 }
|
|
3319
3485
|
*
|
|
3320
3486
|
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3321
3487
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
@@ -3459,6 +3625,21 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
3459
3625
|
return rb_pgresult;
|
|
3460
3626
|
}
|
|
3461
3627
|
|
|
3628
|
+
static VALUE
|
|
3629
|
+
pgconn_async_describe_close_prepared_potral(VALUE self, VALUE name, VALUE
|
|
3630
|
+
(*func)(VALUE, VALUE))
|
|
3631
|
+
{
|
|
3632
|
+
VALUE rb_pgresult = Qnil;
|
|
3633
|
+
|
|
3634
|
+
pgconn_discard_results( self );
|
|
3635
|
+
func( self, name );
|
|
3636
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3637
|
+
|
|
3638
|
+
if ( rb_block_given_p() ) {
|
|
3639
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
3640
|
+
}
|
|
3641
|
+
return rb_pgresult;
|
|
3642
|
+
}
|
|
3462
3643
|
|
|
3463
3644
|
/*
|
|
3464
3645
|
* call-seq:
|
|
@@ -3471,16 +3652,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
3471
3652
|
static VALUE
|
|
3472
3653
|
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
3473
3654
|
{
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
pgconn_discard_results( self );
|
|
3477
|
-
pgconn_send_describe_portal( self, portal );
|
|
3478
|
-
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3479
|
-
|
|
3480
|
-
if ( rb_block_given_p() ) {
|
|
3481
|
-
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
|
3482
|
-
}
|
|
3483
|
-
return rb_pgresult;
|
|
3655
|
+
return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_describe_portal);
|
|
3484
3656
|
}
|
|
3485
3657
|
|
|
3486
3658
|
|
|
@@ -3495,27 +3667,64 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
|
3495
3667
|
static VALUE
|
|
3496
3668
|
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
|
3497
3669
|
{
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
pgconn_discard_results( self );
|
|
3501
|
-
pgconn_send_describe_prepared( self, stmt_name );
|
|
3502
|
-
rb_pgresult = pgconn_async_get_last_result( self );
|
|
3670
|
+
return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_describe_prepared);
|
|
3671
|
+
}
|
|
3503
3672
|
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3673
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
3674
|
+
/*
|
|
3675
|
+
* call-seq:
|
|
3676
|
+
* conn.close_prepared( statement_name ) -> PG::Result
|
|
3677
|
+
*
|
|
3678
|
+
* Submits a request to close the specified prepared statement, and waits for completion.
|
|
3679
|
+
* close_prepared allows an application to close a previously prepared statement.
|
|
3680
|
+
* Closing a statement releases all of its associated resources on the server and allows its name to be reused.
|
|
3681
|
+
* It's the same as using the +DEALLOCATE+ SQL statement, but on a lower protocol level.
|
|
3682
|
+
*
|
|
3683
|
+
* +statement_name+ can be "" or +nil+ to reference the unnamed statement.
|
|
3684
|
+
* It is fine if no statement exists with this name, in that case the operation is a no-op.
|
|
3685
|
+
* On success, a PG::Result with status PGRES_COMMAND_OK is returned.
|
|
3686
|
+
*
|
|
3687
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLOSEPREPARED].
|
|
3688
|
+
*
|
|
3689
|
+
* Available since PostgreSQL-17.
|
|
3690
|
+
*/
|
|
3691
|
+
static VALUE
|
|
3692
|
+
pgconn_async_close_prepared(VALUE self, VALUE stmt_name)
|
|
3693
|
+
{
|
|
3694
|
+
return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_close_prepared);
|
|
3508
3695
|
}
|
|
3509
3696
|
|
|
3697
|
+
/*
|
|
3698
|
+
* call-seq:
|
|
3699
|
+
* conn.close_portal( portal_name ) -> PG::Result
|
|
3700
|
+
*
|
|
3701
|
+
* Submits a request to close the specified portal, and waits for completion.
|
|
3702
|
+
*
|
|
3703
|
+
* close_portal allows an application to trigger a close of a previously created portal.
|
|
3704
|
+
* Closing a portal releases all of its associated resources on the server and allows its name to be reused.
|
|
3705
|
+
* (pg does not provide any direct access to portals, but you can use this function to close a cursor created with a DECLARE CURSOR SQL command.)
|
|
3706
|
+
*
|
|
3707
|
+
* +portal_name+ can be "" or +nil+ to reference the unnamed portal.
|
|
3708
|
+
* It is fine if no portal exists with this name, in that case the operation is a no-op.
|
|
3709
|
+
* On success, a PG::Result with status PGRES_COMMAND_OK is returned.
|
|
3710
|
+
*
|
|
3711
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLOSEPORTAL].
|
|
3712
|
+
*
|
|
3713
|
+
* Available since PostgreSQL-17.
|
|
3714
|
+
*/
|
|
3715
|
+
static VALUE
|
|
3716
|
+
pgconn_async_close_portal(VALUE self, VALUE portal)
|
|
3717
|
+
{
|
|
3718
|
+
return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_close_portal);
|
|
3719
|
+
}
|
|
3720
|
+
#endif
|
|
3510
3721
|
|
|
3511
|
-
#ifdef HAVE_PQSSLATTRIBUTE
|
|
3512
3722
|
/*
|
|
3513
3723
|
* call-seq:
|
|
3514
3724
|
* conn.ssl_in_use? -> Boolean
|
|
3515
3725
|
*
|
|
3516
3726
|
* Returns +true+ if the connection uses SSL/TLS, +false+ if not.
|
|
3517
3727
|
*
|
|
3518
|
-
* Available since PostgreSQL-9.5
|
|
3519
3728
|
*/
|
|
3520
3729
|
static VALUE
|
|
3521
3730
|
pgconn_ssl_in_use(VALUE self)
|
|
@@ -3549,7 +3758,6 @@ pgconn_ssl_in_use(VALUE self)
|
|
|
3549
3758
|
*
|
|
3550
3759
|
* See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
|
|
3551
3760
|
*
|
|
3552
|
-
* Available since PostgreSQL-9.5
|
|
3553
3761
|
*/
|
|
3554
3762
|
static VALUE
|
|
3555
3763
|
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
|
@@ -3568,7 +3776,6 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
|
|
3568
3776
|
*
|
|
3569
3777
|
* See also #ssl_attribute
|
|
3570
3778
|
*
|
|
3571
|
-
* Available since PostgreSQL-9.5
|
|
3572
3779
|
*/
|
|
3573
3780
|
static VALUE
|
|
3574
3781
|
pgconn_ssl_attribute_names(VALUE self)
|
|
@@ -3584,10 +3791,8 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
|
3584
3791
|
}
|
|
3585
3792
|
|
|
3586
3793
|
|
|
3587
|
-
#endif
|
|
3588
|
-
|
|
3589
3794
|
|
|
3590
|
-
#ifdef
|
|
3795
|
+
#ifdef LIBPQ_HAS_PIPELINING
|
|
3591
3796
|
/*
|
|
3592
3797
|
* call-seq:
|
|
3593
3798
|
* conn.pipeline_status -> Integer
|
|
@@ -3620,6 +3825,8 @@ pgconn_pipeline_status(VALUE self)
|
|
|
3620
3825
|
* 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.
|
|
3621
3826
|
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
|
3622
3827
|
*
|
|
3828
|
+
* See the {PostgreSQL documentation}[https://www.postgresql.org/docs/17/libpq-pipeline-mode.html#LIBPQ-PIPELINE-MODE].
|
|
3829
|
+
*
|
|
3623
3830
|
* Available since PostgreSQL-14
|
|
3624
3831
|
*/
|
|
3625
3832
|
static VALUE
|
|
@@ -3658,17 +3865,16 @@ pgconn_exit_pipeline_mode(VALUE self)
|
|
|
3658
3865
|
|
|
3659
3866
|
/*
|
|
3660
3867
|
* call-seq:
|
|
3661
|
-
* conn.
|
|
3868
|
+
* conn.sync_pipeline_sync -> nil
|
|
3662
3869
|
*
|
|
3663
|
-
*
|
|
3664
|
-
*
|
|
3665
|
-
*
|
|
3666
|
-
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
|
3870
|
+
* This function has the same behavior as #async_pipeline_sync, but is implemented using the synchronous command processing API of libpq.
|
|
3871
|
+
* See #async_exec for the differences between the two API variants.
|
|
3872
|
+
* It's not recommended to use explicit sync or async variants but #pipeline_sync instead, unless you have a good reason to do so.
|
|
3667
3873
|
*
|
|
3668
3874
|
* Available since PostgreSQL-14
|
|
3669
3875
|
*/
|
|
3670
3876
|
static VALUE
|
|
3671
|
-
|
|
3877
|
+
pgconn_sync_pipeline_sync(VALUE self)
|
|
3672
3878
|
{
|
|
3673
3879
|
PGconn *conn = pg_get_pgconn(self);
|
|
3674
3880
|
int res = PQpipelineSync(conn);
|
|
@@ -3678,9 +3884,36 @@ pgconn_pipeline_sync(VALUE self)
|
|
|
3678
3884
|
return Qnil;
|
|
3679
3885
|
}
|
|
3680
3886
|
|
|
3887
|
+
|
|
3888
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
3681
3889
|
/*
|
|
3682
3890
|
* call-seq:
|
|
3683
|
-
* conn.
|
|
3891
|
+
* conn.send_pipeline_sync -> nil
|
|
3892
|
+
*
|
|
3893
|
+
* Marks a synchronization point in a pipeline by sending a sync message without flushing the send buffer.
|
|
3894
|
+
*
|
|
3895
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point.
|
|
3896
|
+
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
|
3897
|
+
* Note that the message is not itself flushed to the server automatically; use flush if necessary.
|
|
3898
|
+
*
|
|
3899
|
+
* Available since PostgreSQL-17
|
|
3900
|
+
*/
|
|
3901
|
+
static VALUE
|
|
3902
|
+
pgconn_send_pipeline_sync(VALUE self)
|
|
3903
|
+
{
|
|
3904
|
+
PGconn *conn = pg_get_pgconn(self);
|
|
3905
|
+
int res = PQsendPipelineSync(conn);
|
|
3906
|
+
if( res != 1 )
|
|
3907
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3908
|
+
|
|
3909
|
+
return Qnil;
|
|
3910
|
+
}
|
|
3911
|
+
#endif
|
|
3912
|
+
|
|
3913
|
+
|
|
3914
|
+
/*
|
|
3915
|
+
* call-seq:
|
|
3916
|
+
* conn.send_flush_request -> nil
|
|
3684
3917
|
*
|
|
3685
3918
|
* Sends a request for the server to flush its output buffer.
|
|
3686
3919
|
*
|
|
@@ -4110,7 +4343,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
|
4110
4343
|
rb_encoding *rbenc = rb_to_encoding( enc );
|
|
4111
4344
|
const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
|
|
4112
4345
|
|
|
4113
|
-
if (
|
|
4346
|
+
if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
|
|
4114
4347
|
VALUE server_encoding = pgconn_external_encoding( self );
|
|
4115
4348
|
rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
|
|
4116
4349
|
rb_enc_name(rb_to_encoding(server_encoding)), name );
|
|
@@ -4150,12 +4383,12 @@ pgconn_external_encoding(VALUE self)
|
|
|
4150
4383
|
static VALUE
|
|
4151
4384
|
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4152
4385
|
{
|
|
4153
|
-
VALUE
|
|
4386
|
+
VALUE query;
|
|
4154
4387
|
|
|
4155
4388
|
rb_check_frozen(self);
|
|
4156
4389
|
Check_Type(encname, T_STRING);
|
|
4157
|
-
|
|
4158
|
-
query
|
|
4390
|
+
query = rb_str_new_cstr("set client_encoding to ");
|
|
4391
|
+
rb_str_concat(query, pgconn_escape_literal(self, encname));
|
|
4159
4392
|
|
|
4160
4393
|
pgconn_async_exec(1, &query, self);
|
|
4161
4394
|
pgconn_set_internal_encoding_index( self );
|
|
@@ -4231,9 +4464,11 @@ pgconn_set_default_encoding( VALUE self )
|
|
|
4231
4464
|
* res.type_map_for_queries = typemap
|
|
4232
4465
|
*
|
|
4233
4466
|
* Set the default TypeMap that is used for type casts of query bind parameters.
|
|
4467
|
+
* It can be overwritten per +type_map+ parameter of #exec_params and siblings.
|
|
4234
4468
|
*
|
|
4235
4469
|
* +typemap+ must be a kind of PG::TypeMap .
|
|
4236
4470
|
*
|
|
4471
|
+
* See also #type_map_for_queries
|
|
4237
4472
|
*/
|
|
4238
4473
|
static VALUE
|
|
4239
4474
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
@@ -4258,6 +4493,9 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
|
4258
4493
|
* Returns the default TypeMap that is currently set for type casts of query
|
|
4259
4494
|
* bind parameters.
|
|
4260
4495
|
*
|
|
4496
|
+
* Default is PG::TypeMapAllStrings .
|
|
4497
|
+
*
|
|
4498
|
+
* See also #type_map_for_queries=
|
|
4261
4499
|
*/
|
|
4262
4500
|
static VALUE
|
|
4263
4501
|
pgconn_type_map_for_queries_get(VALUE self)
|
|
@@ -4272,9 +4510,11 @@ pgconn_type_map_for_queries_get(VALUE self)
|
|
|
4272
4510
|
* res.type_map_for_results = typemap
|
|
4273
4511
|
*
|
|
4274
4512
|
* Set the default TypeMap that is used for type casts of result values.
|
|
4513
|
+
* It can be overwritten per PG::Result#type_map= .
|
|
4275
4514
|
*
|
|
4276
4515
|
* +typemap+ must be a kind of PG::TypeMap .
|
|
4277
4516
|
*
|
|
4517
|
+
* See also #type_map_for_results
|
|
4278
4518
|
*/
|
|
4279
4519
|
static VALUE
|
|
4280
4520
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
@@ -4296,6 +4536,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
|
4296
4536
|
*
|
|
4297
4537
|
* Returns the default TypeMap that is currently set for type casts of result values.
|
|
4298
4538
|
*
|
|
4539
|
+
* Default is PG::TypeMapAllStrings .
|
|
4540
|
+
*
|
|
4541
|
+
* See also #type_map_for_results=
|
|
4299
4542
|
*/
|
|
4300
4543
|
static VALUE
|
|
4301
4544
|
pgconn_type_map_for_results_get(VALUE self)
|
|
@@ -4312,11 +4555,13 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
|
4312
4555
|
*
|
|
4313
4556
|
* Set the default coder that is used for type casting of parameters
|
|
4314
4557
|
* to #put_copy_data .
|
|
4558
|
+
* It can be overwritten per +encoder+ parameter of #put_copy_data and +coder+ parameter of #copy_data.
|
|
4315
4559
|
*
|
|
4316
4560
|
* +encoder+ can be:
|
|
4317
4561
|
* * a kind of PG::Coder
|
|
4318
4562
|
* * +nil+ - disable type encoding, data must be a String.
|
|
4319
4563
|
*
|
|
4564
|
+
* See also #encoder_for_put_copy_data
|
|
4320
4565
|
*/
|
|
4321
4566
|
static VALUE
|
|
4322
4567
|
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
@@ -4346,6 +4591,8 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
|
4346
4591
|
* * a kind of PG::Coder
|
|
4347
4592
|
* * +nil+ - type encoding is disabled, data must be a String.
|
|
4348
4593
|
*
|
|
4594
|
+
* Default is +nil+ .
|
|
4595
|
+
* See also #encoder_for_put_copy_data=
|
|
4349
4596
|
*/
|
|
4350
4597
|
static VALUE
|
|
4351
4598
|
pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
@@ -4361,11 +4608,13 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
|
4361
4608
|
*
|
|
4362
4609
|
* Set the default coder that is used for type casting of received data
|
|
4363
4610
|
* by #get_copy_data .
|
|
4611
|
+
* It can be overwritten per +decoder+ parameter of #get_copy_data and +coder+ parameter of #copy_data.
|
|
4364
4612
|
*
|
|
4365
4613
|
* +decoder+ can be:
|
|
4366
4614
|
* * a kind of PG::Coder
|
|
4367
4615
|
* * +nil+ - disable type decoding, returned data will be a String.
|
|
4368
4616
|
*
|
|
4617
|
+
* See also #decoder_for_get_copy_data
|
|
4369
4618
|
*/
|
|
4370
4619
|
static VALUE
|
|
4371
4620
|
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
@@ -4395,6 +4644,9 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
|
4395
4644
|
* * a kind of PG::Coder
|
|
4396
4645
|
* * +nil+ - type encoding is disabled, returned data will be a String.
|
|
4397
4646
|
*
|
|
4647
|
+
* Default is +nil+ .
|
|
4648
|
+
*
|
|
4649
|
+
* See also #decoder_for_get_copy_data=
|
|
4398
4650
|
*/
|
|
4399
4651
|
static VALUE
|
|
4400
4652
|
pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
@@ -4417,7 +4669,7 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
|
4417
4669
|
*
|
|
4418
4670
|
* Settings the type of field names affects only future results.
|
|
4419
4671
|
*
|
|
4420
|
-
* See further description at PG::Result#field_name_type=
|
|
4672
|
+
* See further description at PG::Result#field_name_type= and #field_name_type .
|
|
4421
4673
|
*
|
|
4422
4674
|
*/
|
|
4423
4675
|
static VALUE
|
|
@@ -4428,7 +4680,6 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
|
4428
4680
|
rb_check_frozen(self);
|
|
4429
4681
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
|
4430
4682
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
|
4431
|
-
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
|
4432
4683
|
else if ( sym == sym_string );
|
|
4433
4684
|
else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
|
|
4434
4685
|
|
|
@@ -4450,8 +4701,6 @@ pgconn_field_name_type_get(VALUE self)
|
|
|
4450
4701
|
|
|
4451
4702
|
if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
|
|
4452
4703
|
return sym_symbol;
|
|
4453
|
-
} else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
|
|
4454
|
-
return sym_static_symbol;
|
|
4455
4704
|
} else {
|
|
4456
4705
|
return sym_string;
|
|
4457
4706
|
}
|
|
@@ -4471,7 +4720,6 @@ init_pg_connection(void)
|
|
|
4471
4720
|
sym_value = ID2SYM(rb_intern("value"));
|
|
4472
4721
|
sym_string = ID2SYM(rb_intern("string"));
|
|
4473
4722
|
sym_symbol = ID2SYM(rb_intern("symbol"));
|
|
4474
|
-
sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
|
|
4475
4723
|
|
|
4476
4724
|
rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
|
|
4477
4725
|
/* Help rdoc to known the Constants module */
|
|
@@ -4519,12 +4767,17 @@ init_pg_connection(void)
|
|
|
4519
4767
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
|
4520
4768
|
rb_define_method(rb_cPGconn, "parameter_status", pgconn_parameter_status, 1);
|
|
4521
4769
|
rb_define_method(rb_cPGconn, "protocol_version", pgconn_protocol_version, 0);
|
|
4770
|
+
#ifdef LIBPQ_HAS_FULL_PROTOCOL_VERSION
|
|
4771
|
+
rb_define_method(rb_cPGconn, "full_protocol_version", pgconn_full_protocol_version, 0);
|
|
4772
|
+
#endif
|
|
4522
4773
|
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
|
4523
4774
|
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
|
4524
4775
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
|
4525
4776
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
|
4526
4777
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
|
4778
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
4527
4779
|
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
|
4780
|
+
#endif
|
|
4528
4781
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
|
4529
4782
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
|
4530
4783
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
|
@@ -4536,6 +4789,10 @@ init_pg_connection(void)
|
|
|
4536
4789
|
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
|
4537
4790
|
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
|
4538
4791
|
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
|
4792
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4793
|
+
rb_define_method(rb_cPGconn, "sync_close_prepared", pgconn_sync_close_prepared, 1);
|
|
4794
|
+
rb_define_method(rb_cPGconn, "sync_close_portal", pgconn_sync_close_portal, 1);
|
|
4795
|
+
#endif
|
|
4539
4796
|
|
|
4540
4797
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
|
4541
4798
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
|
@@ -4543,6 +4800,10 @@ init_pg_connection(void)
|
|
|
4543
4800
|
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
|
|
4544
4801
|
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
|
|
4545
4802
|
rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
|
|
4803
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4804
|
+
rb_define_method(rb_cPGconn, "close_prepared", pgconn_async_close_prepared, 1);
|
|
4805
|
+
rb_define_method(rb_cPGconn, "close_portal", pgconn_async_close_portal, 1);
|
|
4806
|
+
#endif
|
|
4546
4807
|
|
|
4547
4808
|
rb_define_alias(rb_cPGconn, "async_exec", "exec");
|
|
4548
4809
|
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
|
@@ -4551,6 +4812,10 @@ init_pg_connection(void)
|
|
|
4551
4812
|
rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
|
|
4552
4813
|
rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
|
|
4553
4814
|
rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
|
|
4815
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4816
|
+
rb_define_alias(rb_cPGconn, "async_close_prepared", "close_prepared");
|
|
4817
|
+
rb_define_alias(rb_cPGconn, "async_close_portal", "close_portal");
|
|
4818
|
+
#endif
|
|
4554
4819
|
|
|
4555
4820
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
|
4556
4821
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
|
@@ -4560,6 +4825,9 @@ init_pg_connection(void)
|
|
|
4560
4825
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
|
4561
4826
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
|
4562
4827
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
|
4828
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4829
|
+
rb_define_method(rb_cPGconn, "set_chunked_rows_mode", pgconn_set_chunked_rows_mode, 1);
|
|
4830
|
+
#endif
|
|
4563
4831
|
|
|
4564
4832
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
|
4565
4833
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
|
@@ -4579,7 +4847,9 @@ init_pg_connection(void)
|
|
|
4579
4847
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
|
4580
4848
|
|
|
4581
4849
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
|
4850
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
4582
4851
|
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
|
4852
|
+
#endif
|
|
4583
4853
|
|
|
4584
4854
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
|
4585
4855
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
|
@@ -4591,9 +4861,7 @@ init_pg_connection(void)
|
|
|
4591
4861
|
|
|
4592
4862
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
|
4593
4863
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
|
4594
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
|
4595
4864
|
rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
|
|
4596
|
-
#endif
|
|
4597
4865
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
|
4598
4866
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
|
4599
4867
|
|
|
@@ -4615,22 +4883,21 @@ init_pg_connection(void)
|
|
|
4615
4883
|
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
|
4616
4884
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
|
4617
4885
|
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
|
4618
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
4619
4886
|
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
|
4620
|
-
#endif
|
|
4621
4887
|
|
|
4622
|
-
#ifdef HAVE_PQSSLATTRIBUTE
|
|
4623
4888
|
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
|
4624
4889
|
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
|
4625
4890
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
|
4626
|
-
#endif
|
|
4627
4891
|
|
|
4628
|
-
#ifdef
|
|
4892
|
+
#ifdef LIBPQ_HAS_PIPELINING
|
|
4629
4893
|
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
|
4630
4894
|
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
|
4631
4895
|
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
|
4632
|
-
rb_define_method(rb_cPGconn, "
|
|
4896
|
+
rb_define_method(rb_cPGconn, "sync_pipeline_sync", pgconn_sync_pipeline_sync, 0);
|
|
4633
4897
|
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
|
4898
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4899
|
+
rb_define_method(rb_cPGconn, "send_pipeline_sync", pgconn_send_pipeline_sync, 0);
|
|
4900
|
+
#endif
|
|
4634
4901
|
#endif
|
|
4635
4902
|
|
|
4636
4903
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|