pg 1.5.4 → 1.6.1
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} +106 -4
- data/Gemfile +12 -3
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +4 -4
- data/README.md +58 -17
- data/Rakefile +95 -14
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +4 -5
- data/ext/errorcodes.txt +2 -5
- data/ext/extconf.rb +161 -14
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +33 -0
- data/ext/pg.c +17 -6
- data/ext/pg.h +9 -9
- data/ext/pg_binary_decoder.c +152 -0
- data/ext/pg_binary_encoder.c +211 -8
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +54 -5
- data/ext/pg_connection.c +409 -167
- data/ext/pg_copy_coder.c +19 -15
- data/ext/pg_record_coder.c +7 -7
- data/ext/pg_result.c +11 -13
- data/ext/pg_text_decoder.c +4 -1
- data/ext/pg_text_encoder.c +37 -18
- data/ext/pg_tuple.c +2 -2
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +1 -1
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +2 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/lib/pg/basic_type_map_for_queries.rb +15 -7
- data/lib/pg/basic_type_registry.rb +16 -4
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +4 -2
- data/lib/pg/connection.rb +310 -167
- data/lib/pg/exceptions.rb +6 -0
- data/lib/pg/text_decoder/date.rb +3 -0
- data/lib/pg/text_decoder/json.rb +3 -0
- data/lib/pg/text_encoder/date.rb +1 -0
- data/lib/pg/text_encoder/inet.rb +3 -0
- data/lib/pg/text_encoder/json.rb +3 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +23 -8
- 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 +8 -4
- data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
- data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data.tar.gz.sig +0 -0
- metadata +45 -47
- metadata.gz.sig +0 -0
- data/.appveyor.yml +0 -42
- data/.gems +0 -6
- data/.gemtest +0 -0
- data/.github/workflows/binary-gems.yml +0 -117
- data/.github/workflows/source-gem.yml +0 -141
- data/.gitignore +0 -22
- data/.hgsigs +0 -34
- data/.hgtags +0 -41
- data/.irbrc +0 -23
- data/.pryrc +0 -23
- data/.tm_properties +0 -21
- data/.travis.yml +0 -49
- data/Manifest.txt +0 -72
- data/Rakefile.cross +0 -298
- data/translation/.po4a-version +0 -7
- data/translation/po/all.pot +0 -936
- data/translation/po/ja.po +0 -1036
- data/translation/po4a.cfg +0 -12
data/ext/pg_connection.c
CHANGED
@@ -30,10 +30,7 @@ static VALUE pgconn_async_flush(VALUE self);
|
|
30
30
|
/*
|
31
31
|
* Convenience function to raise connection errors
|
32
32
|
*/
|
33
|
-
|
34
|
-
__attribute__((format(printf, 3, 4)))
|
35
|
-
#endif
|
36
|
-
static void
|
33
|
+
void
|
37
34
|
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
38
35
|
{
|
39
36
|
VALUE msg, error;
|
@@ -96,6 +93,20 @@ pg_get_pgconn( VALUE self )
|
|
96
93
|
}
|
97
94
|
|
98
95
|
|
96
|
+
void
|
97
|
+
pg_unwrap_socket_io( VALUE self, VALUE *p_socket_io, int ruby_sd )
|
98
|
+
{
|
99
|
+
if ( RTEST(*p_socket_io) ) {
|
100
|
+
#if defined(_WIN32)
|
101
|
+
if( rb_w32_unwrap_io_handle(ruby_sd) )
|
102
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
103
|
+
#endif
|
104
|
+
rb_funcall( *p_socket_io, rb_intern("close"), 0 );
|
105
|
+
}
|
106
|
+
|
107
|
+
RB_OBJ_WRITE(self, p_socket_io, Qnil);
|
108
|
+
}
|
109
|
+
|
99
110
|
|
100
111
|
/*
|
101
112
|
* Close the associated socket IO object if there is one.
|
@@ -104,17 +115,7 @@ static void
|
|
104
115
|
pgconn_close_socket_io( VALUE self )
|
105
116
|
{
|
106
117
|
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);
|
118
|
+
pg_unwrap_socket_io( self, &this->socket_io, this->ruby_sd);
|
118
119
|
}
|
119
120
|
|
120
121
|
|
@@ -230,7 +231,7 @@ static const rb_data_type_t pg_connection_type = {
|
|
230
231
|
pgconn_gc_mark,
|
231
232
|
pgconn_gc_free,
|
232
233
|
pgconn_memsize,
|
233
|
-
|
234
|
+
pgconn_gc_compact,
|
234
235
|
},
|
235
236
|
0,
|
236
237
|
0,
|
@@ -264,6 +265,7 @@ pgconn_s_allocate( VALUE klass )
|
|
264
265
|
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, Qnil);
|
265
266
|
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
266
267
|
rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
|
268
|
+
rb_ivar_set(self, rb_intern("@iopts_for_reset"), Qnil);
|
267
269
|
|
268
270
|
return self;
|
269
271
|
}
|
@@ -418,7 +420,6 @@ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
|
|
418
420
|
}
|
419
421
|
|
420
422
|
|
421
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
422
423
|
static VALUE
|
423
424
|
pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
424
425
|
{
|
@@ -442,7 +443,6 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
442
443
|
|
443
444
|
return rval;
|
444
445
|
}
|
445
|
-
#endif
|
446
446
|
|
447
447
|
|
448
448
|
/*
|
@@ -515,9 +515,9 @@ static VALUE
|
|
515
515
|
pgconn_connect_poll(VALUE self)
|
516
516
|
{
|
517
517
|
PostgresPollingStatusType status;
|
518
|
-
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
519
518
|
|
520
519
|
pgconn_close_socket_io(self);
|
520
|
+
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
521
521
|
|
522
522
|
return INT2FIX((int)status);
|
523
523
|
}
|
@@ -563,6 +563,27 @@ pgconn_sync_reset( VALUE self )
|
|
563
563
|
return self;
|
564
564
|
}
|
565
565
|
|
566
|
+
static VALUE
|
567
|
+
pgconn_reset_start2( VALUE self, VALUE conninfo )
|
568
|
+
{
|
569
|
+
t_pg_connection *this = pg_get_connection( self );
|
570
|
+
|
571
|
+
/* Close old connection */
|
572
|
+
pgconn_close_socket_io( self );
|
573
|
+
PQfinish( this->pgconn );
|
574
|
+
|
575
|
+
/* Start new connection */
|
576
|
+
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
577
|
+
|
578
|
+
if( this->pgconn == NULL )
|
579
|
+
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
580
|
+
|
581
|
+
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
582
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
|
583
|
+
|
584
|
+
return Qnil;
|
585
|
+
}
|
586
|
+
|
566
587
|
/*
|
567
588
|
* call-seq:
|
568
589
|
* conn.reset_start() -> nil
|
@@ -587,16 +608,16 @@ pgconn_reset_start(VALUE self)
|
|
587
608
|
* conn.reset_poll -> Integer
|
588
609
|
*
|
589
610
|
* Checks the status of a connection reset operation.
|
590
|
-
* See
|
611
|
+
* See Connection.connect_start and #connect_poll for
|
591
612
|
* usage information and return values.
|
592
613
|
*/
|
593
614
|
static VALUE
|
594
615
|
pgconn_reset_poll(VALUE self)
|
595
616
|
{
|
596
617
|
PostgresPollingStatusType status;
|
597
|
-
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
598
618
|
|
599
619
|
pgconn_close_socket_io(self);
|
620
|
+
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
600
621
|
|
601
622
|
return INT2FIX((int)status);
|
602
623
|
}
|
@@ -738,7 +759,6 @@ pgconn_options(VALUE self)
|
|
738
759
|
*
|
739
760
|
* Returns the connection options used by a live connection.
|
740
761
|
*
|
741
|
-
* Available since PostgreSQL-9.3
|
742
762
|
*/
|
743
763
|
static VALUE
|
744
764
|
pgconn_conninfo( VALUE self )
|
@@ -825,31 +845,52 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
825
845
|
* call-seq:
|
826
846
|
* conn.protocol_version -> Integer
|
827
847
|
*
|
828
|
-
*
|
829
|
-
*
|
830
|
-
*
|
848
|
+
* Interrogates the frontend/backend protocol being used.
|
849
|
+
*
|
850
|
+
* Applications might wish to use this function to determine whether certain features are supported.
|
851
|
+
* Currently, the only value is 3 (3.0 protocol).
|
852
|
+
* The protocol version will not change after connection startup is complete, but it could theoretically change during a connection reset.
|
853
|
+
* The 3.0 protocol is supported by PostgreSQL server versions 7.4 and above.
|
854
|
+
*
|
855
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
831
856
|
*/
|
832
857
|
static VALUE
|
833
858
|
pgconn_protocol_version(VALUE self)
|
834
859
|
{
|
835
|
-
|
860
|
+
int protocol_version = PQprotocolVersion(pg_get_pgconn(self));
|
861
|
+
if (protocol_version == 0) {
|
862
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQprotocolVersion() can't get protocol version");
|
863
|
+
}
|
864
|
+
return INT2NUM(protocol_version);
|
836
865
|
}
|
837
866
|
|
838
867
|
/*
|
839
868
|
* call-seq:
|
840
869
|
* conn.server_version -> Integer
|
841
870
|
*
|
842
|
-
*
|
843
|
-
*
|
844
|
-
*
|
845
|
-
*
|
846
|
-
*
|
871
|
+
* Returns an integer representing the server version.
|
872
|
+
*
|
873
|
+
* Applications might use this function to determine the version of the database server they are connected to.
|
874
|
+
* The result is formed by multiplying the server's major version number by 10000 and adding the minor version number.
|
875
|
+
* For example, version 10.1 will be returned as 100001, and version 11.0 will be returned as 110000.
|
876
|
+
*
|
877
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
878
|
+
*
|
879
|
+
* Prior to major version 10, PostgreSQL used three-part version numbers in which the first two parts together represented the major version.
|
880
|
+
* 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.
|
881
|
+
*
|
882
|
+
* 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.
|
883
|
+
* In all release series, only the last two digits differ between minor releases (bug-fix releases).
|
847
884
|
*
|
848
885
|
*/
|
849
886
|
static VALUE
|
850
887
|
pgconn_server_version(VALUE self)
|
851
888
|
{
|
852
|
-
|
889
|
+
int server_version = PQserverVersion(pg_get_pgconn(self));
|
890
|
+
if (server_version == 0) {
|
891
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQserverVersion() can't get server version");
|
892
|
+
}
|
893
|
+
return INT2NUM(server_version);
|
853
894
|
}
|
854
895
|
|
855
896
|
/*
|
@@ -898,13 +939,42 @@ pgconn_socket(VALUE self)
|
|
898
939
|
return INT2NUM(sd);
|
899
940
|
}
|
900
941
|
|
942
|
+
|
943
|
+
VALUE
|
944
|
+
pg_wrap_socket_io(int sd, VALUE self, VALUE *p_socket_io, int *p_ruby_sd)
|
945
|
+
{
|
946
|
+
int ruby_sd;
|
947
|
+
VALUE cSocket;
|
948
|
+
VALUE socket_io = *p_socket_io;
|
949
|
+
|
950
|
+
#ifdef _WIN32
|
951
|
+
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
952
|
+
if( ruby_sd == -1 )
|
953
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
954
|
+
|
955
|
+
*p_ruby_sd = ruby_sd;
|
956
|
+
#else
|
957
|
+
*p_ruby_sd = ruby_sd = sd;
|
958
|
+
#endif
|
959
|
+
|
960
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
961
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
962
|
+
|
963
|
+
/* Disable autoclose feature */
|
964
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
965
|
+
|
966
|
+
RB_OBJ_WRITE(self, p_socket_io, socket_io);
|
967
|
+
|
968
|
+
return socket_io;
|
969
|
+
}
|
970
|
+
|
901
971
|
/*
|
902
972
|
* call-seq:
|
903
973
|
* conn.socket_io() -> IO
|
904
974
|
*
|
905
975
|
* Fetch an IO object created from the Connection's underlying socket.
|
906
976
|
* 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.
|
907
|
-
* <tt>IO#wait_*able</tt> is
|
977
|
+
* <tt>IO#wait_*able</tt> is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
|
908
978
|
*
|
909
979
|
* The IO object can change while the connection is established, but is memorized afterwards.
|
910
980
|
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
@@ -915,37 +985,17 @@ pgconn_socket(VALUE self)
|
|
915
985
|
static VALUE
|
916
986
|
pgconn_socket_io(VALUE self)
|
917
987
|
{
|
918
|
-
int sd;
|
919
|
-
int ruby_sd;
|
920
988
|
t_pg_connection *this = pg_get_connection_safe( self );
|
921
|
-
VALUE cSocket;
|
922
|
-
VALUE socket_io = this->socket_io;
|
923
989
|
|
924
|
-
if ( !RTEST(socket_io) ) {
|
990
|
+
if ( !RTEST(this->socket_io) ) {
|
991
|
+
int sd;
|
925
992
|
if( (sd = PQsocket(this->pgconn)) < 0){
|
926
993
|
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
927
994
|
}
|
928
|
-
|
929
|
-
#ifdef _WIN32
|
930
|
-
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
931
|
-
if( ruby_sd == -1 )
|
932
|
-
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
933
|
-
|
934
|
-
this->ruby_sd = ruby_sd;
|
935
|
-
#else
|
936
|
-
ruby_sd = sd;
|
937
|
-
#endif
|
938
|
-
|
939
|
-
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
940
|
-
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
941
|
-
|
942
|
-
/* Disable autoclose feature */
|
943
|
-
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
944
|
-
|
945
|
-
RB_OBJ_WRITE(self, &this->socket_io, socket_io);
|
995
|
+
return pg_wrap_socket_io( sd, self, &this->socket_io, &this->ruby_sd);
|
946
996
|
}
|
947
997
|
|
948
|
-
return socket_io;
|
998
|
+
return this->socket_io;
|
949
999
|
}
|
950
1000
|
|
951
1001
|
/*
|
@@ -962,6 +1012,7 @@ pgconn_backend_pid(VALUE self)
|
|
962
1012
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
963
1013
|
}
|
964
1014
|
|
1015
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
965
1016
|
typedef struct
|
966
1017
|
{
|
967
1018
|
struct sockaddr_storage addr;
|
@@ -1006,6 +1057,7 @@ pgconn_backend_key(VALUE self)
|
|
1006
1057
|
|
1007
1058
|
return INT2NUM(be_key);
|
1008
1059
|
}
|
1060
|
+
#endif
|
1009
1061
|
|
1010
1062
|
/*
|
1011
1063
|
* call-seq:
|
@@ -1278,7 +1330,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1278
1330
|
paramsData->lengths[i] = 0;
|
1279
1331
|
} else {
|
1280
1332
|
t_pg_coder_enc_func enc_func = pg_coder_enc_func( conv );
|
1281
|
-
VALUE intermediate;
|
1333
|
+
VALUE intermediate = Qnil;
|
1282
1334
|
|
1283
1335
|
/* 1st pass for retiving the required memory space */
|
1284
1336
|
int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
|
@@ -1318,8 +1370,6 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1318
1370
|
required_pool_size += len;
|
1319
1371
|
}
|
1320
1372
|
}
|
1321
|
-
|
1322
|
-
RB_GC_GUARD(intermediate);
|
1323
1373
|
}
|
1324
1374
|
}
|
1325
1375
|
}
|
@@ -1494,6 +1544,19 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1494
1544
|
return rb_pgresult;
|
1495
1545
|
}
|
1496
1546
|
|
1547
|
+
static VALUE
|
1548
|
+
pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*func)(PGconn *, const char *))
|
1549
|
+
{
|
1550
|
+
PGresult *result;
|
1551
|
+
VALUE rb_pgresult;
|
1552
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1553
|
+
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
|
1554
|
+
result = func(this->pgconn, stmt);
|
1555
|
+
rb_pgresult = pg_new_result(result, self);
|
1556
|
+
pg_result_check(rb_pgresult);
|
1557
|
+
return rb_pgresult;
|
1558
|
+
}
|
1559
|
+
|
1497
1560
|
/*
|
1498
1561
|
* call-seq:
|
1499
1562
|
* conn.sync_describe_prepared( statement_name ) -> PG::Result
|
@@ -1505,20 +1568,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1505
1568
|
static VALUE
|
1506
1569
|
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
1507
1570
|
{
|
1508
|
-
|
1509
|
-
VALUE rb_pgresult;
|
1510
|
-
t_pg_connection *this = pg_get_connection_safe( self );
|
1511
|
-
const char *stmt;
|
1512
|
-
if(NIL_P(stmt_name)) {
|
1513
|
-
stmt = NULL;
|
1514
|
-
}
|
1515
|
-
else {
|
1516
|
-
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1517
|
-
}
|
1518
|
-
result = gvl_PQdescribePrepared(this->pgconn, stmt);
|
1519
|
-
rb_pgresult = pg_new_result(result, self);
|
1520
|
-
pg_result_check(rb_pgresult);
|
1521
|
-
return rb_pgresult;
|
1571
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePrepared);
|
1522
1572
|
}
|
1523
1573
|
|
1524
1574
|
|
@@ -1533,23 +1583,44 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1533
1583
|
static VALUE
|
1534
1584
|
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
1535
1585
|
{
|
1536
|
-
|
1537
|
-
VALUE rb_pgresult;
|
1538
|
-
t_pg_connection *this = pg_get_connection_safe( self );
|
1539
|
-
const char *stmt;
|
1540
|
-
if(NIL_P(stmt_name)) {
|
1541
|
-
stmt = NULL;
|
1542
|
-
}
|
1543
|
-
else {
|
1544
|
-
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1545
|
-
}
|
1546
|
-
result = gvl_PQdescribePortal(this->pgconn, stmt);
|
1547
|
-
rb_pgresult = pg_new_result(result, self);
|
1548
|
-
pg_result_check(rb_pgresult);
|
1549
|
-
return rb_pgresult;
|
1586
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePortal);
|
1550
1587
|
}
|
1551
1588
|
|
1552
1589
|
|
1590
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
1591
|
+
/*
|
1592
|
+
* call-seq:
|
1593
|
+
* conn.sync_close_prepared( stmt_name ) -> PG::Result
|
1594
|
+
*
|
1595
|
+
* This function has the same behavior as #async_close_prepared, but is implemented using the synchronous command processing API of libpq.
|
1596
|
+
* See #async_exec for the differences between the two API variants.
|
1597
|
+
* It's not recommended to use explicit sync or async variants but #close_prepared instead, unless you have a good reason to do so.
|
1598
|
+
*
|
1599
|
+
* Available since PostgreSQL-17.
|
1600
|
+
*/
|
1601
|
+
static VALUE
|
1602
|
+
pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
|
1603
|
+
{
|
1604
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQclosePrepared);
|
1605
|
+
}
|
1606
|
+
|
1607
|
+
/*
|
1608
|
+
* call-seq:
|
1609
|
+
* conn.sync_close_portal( portal_name ) -> PG::Result
|
1610
|
+
*
|
1611
|
+
* This function has the same behavior as #async_close_portal, but is implemented using the synchronous command processing API of libpq.
|
1612
|
+
* See #async_exec for the differences between the two API variants.
|
1613
|
+
* It's not recommended to use explicit sync or async variants but #close_portal instead, unless you have a good reason to do so.
|
1614
|
+
*
|
1615
|
+
* Available since PostgreSQL-17.
|
1616
|
+
*/
|
1617
|
+
static VALUE
|
1618
|
+
pgconn_sync_close_portal(VALUE self, VALUE stmt_name)
|
1619
|
+
{
|
1620
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQclosePortal);
|
1621
|
+
}
|
1622
|
+
#endif
|
1623
|
+
|
1553
1624
|
/*
|
1554
1625
|
* call-seq:
|
1555
1626
|
* conn.make_empty_pgresult( status ) -> PG::Result
|
@@ -1566,6 +1637,7 @@ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
1566
1637
|
* * +PGRES_FATAL_ERROR+
|
1567
1638
|
* * +PGRES_COPY_BOTH+
|
1568
1639
|
* * +PGRES_SINGLE_TUPLE+
|
1640
|
+
* * +PGRES_TUPLES_CHUNK+
|
1569
1641
|
* * +PGRES_PIPELINE_SYNC+
|
1570
1642
|
* * +PGRES_PIPELINE_ABORTED+
|
1571
1643
|
*/
|
@@ -1790,14 +1862,11 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1790
1862
|
* (column names, types, etc) that an ordinary Result object for the query
|
1791
1863
|
* would have.
|
1792
1864
|
*
|
1793
|
-
* *Caution:* While processing a query, the server may return some rows and
|
1794
|
-
*
|
1795
|
-
*
|
1796
|
-
*
|
1797
|
-
* application
|
1798
|
-
* For proper transactional behavior, the application must be designed to discard
|
1799
|
-
* or undo whatever has been done with the previously-processed rows, if the query
|
1800
|
-
* ultimately fails.
|
1865
|
+
* *Caution:* While processing a query, the server may return some rows and then encounter an error, causing the query to be aborted.
|
1866
|
+
* Ordinarily, pg discards any such rows and reports only the error.
|
1867
|
+
* But in single-row or chunked mode, some rows may have already been returned to the application.
|
1868
|
+
* 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.
|
1869
|
+
* 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.
|
1801
1870
|
*
|
1802
1871
|
* Example:
|
1803
1872
|
* conn.send_query( "your SQL command" )
|
@@ -1817,10 +1886,49 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1817
1886
|
|
1818
1887
|
rb_check_frozen(self);
|
1819
1888
|
if( PQsetSingleRowMode(conn) == 0 )
|
1820
|
-
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
1889
|
+
pg_raise_conn_error( rb_ePGerror, self, "PQsetSingleRowMode %s", PQerrorMessage(conn));
|
1890
|
+
|
1891
|
+
return self;
|
1892
|
+
}
|
1893
|
+
|
1894
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
1895
|
+
/*
|
1896
|
+
* call-seq:
|
1897
|
+
* conn.set_chunked_rows_mode -> self
|
1898
|
+
*
|
1899
|
+
* Select chunked mode for the currently-executing query.
|
1900
|
+
*
|
1901
|
+
* 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.
|
1902
|
+
* 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.
|
1903
|
+
* If called at the correct time, the function activates chunked mode for the current query.
|
1904
|
+
* Otherwise the mode stays unchanged and the function raises an error.
|
1905
|
+
* In any case, the mode reverts to normal after completion of the current query.
|
1906
|
+
*
|
1907
|
+
* Example:
|
1908
|
+
* conn.send_query( "your SQL command" )
|
1909
|
+
* conn.set_chunked_rows_mode(10)
|
1910
|
+
* loop do
|
1911
|
+
* res = conn.get_result or break
|
1912
|
+
* res.check
|
1913
|
+
* res.each do |row|
|
1914
|
+
* # do something with the received max. 10 rows
|
1915
|
+
* end
|
1916
|
+
* end
|
1917
|
+
*
|
1918
|
+
* Available since PostgreSQL-17
|
1919
|
+
*/
|
1920
|
+
static VALUE
|
1921
|
+
pgconn_set_chunked_rows_mode(VALUE self, VALUE chunk_size)
|
1922
|
+
{
|
1923
|
+
PGconn *conn = pg_get_pgconn(self);
|
1924
|
+
|
1925
|
+
rb_check_frozen(self);
|
1926
|
+
if( PQsetChunkedRowsMode(conn, NUM2INT(chunk_size)) == 0 )
|
1927
|
+
pg_raise_conn_error( rb_ePGerror, self, "PQsetChunkedRowsMode %s", PQerrorMessage(conn));
|
1821
1928
|
|
1822
1929
|
return self;
|
1823
1930
|
}
|
1931
|
+
#endif
|
1824
1932
|
|
1825
1933
|
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
1826
1934
|
|
@@ -1845,7 +1953,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1845
1953
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
1846
1954
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1847
1955
|
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
1848
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1956
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));
|
1849
1957
|
|
1850
1958
|
pgconn_wait_for_flush( self );
|
1851
1959
|
return Qnil;
|
@@ -1920,7 +2028,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1920
2028
|
free_query_params( ¶msData );
|
1921
2029
|
|
1922
2030
|
if(result == 0)
|
1923
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2031
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryParams %s", PQerrorMessage(this->pgconn));
|
1924
2032
|
|
1925
2033
|
pgconn_wait_for_flush( self );
|
1926
2034
|
return Qnil;
|
@@ -1981,7 +2089,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1981
2089
|
xfree(paramTypes);
|
1982
2090
|
|
1983
2091
|
if(result == 0) {
|
1984
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2092
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendPrepare %s", PQerrorMessage(this->pgconn));
|
1985
2093
|
}
|
1986
2094
|
pgconn_wait_for_flush( self );
|
1987
2095
|
return Qnil;
|
@@ -2047,7 +2155,21 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
2047
2155
|
free_query_params( ¶msData );
|
2048
2156
|
|
2049
2157
|
if(result == 0)
|
2050
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2158
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryPrepared %s", PQerrorMessage(this->pgconn));
|
2159
|
+
|
2160
|
+
pgconn_wait_for_flush( self );
|
2161
|
+
return Qnil;
|
2162
|
+
}
|
2163
|
+
|
2164
|
+
|
2165
|
+
static VALUE
|
2166
|
+
pgconn_send_describe_close_prepared_portal(VALUE self, VALUE name, int (*func)(PGconn *, const char *), const char *funame)
|
2167
|
+
{
|
2168
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2169
|
+
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
|
2170
|
+
/* returns 0 on failure */
|
2171
|
+
if(func(this->pgconn, stmt) == 0)
|
2172
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s %s", funame, PQerrorMessage(this->pgconn));
|
2051
2173
|
|
2052
2174
|
pgconn_wait_for_flush( self );
|
2053
2175
|
return Qnil;
|
@@ -2063,13 +2185,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
2063
2185
|
static VALUE
|
2064
2186
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
2065
2187
|
{
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2070
|
-
|
2071
|
-
pgconn_wait_for_flush( self );
|
2072
|
-
return Qnil;
|
2188
|
+
return pgconn_send_describe_close_prepared_portal(
|
2189
|
+
self, stmt_name, gvl_PQsendDescribePrepared,
|
2190
|
+
"PQsendDescribePrepared");
|
2073
2191
|
}
|
2074
2192
|
|
2075
2193
|
|
@@ -2083,16 +2201,48 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2083
2201
|
static VALUE
|
2084
2202
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
2085
2203
|
{
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2204
|
+
return pgconn_send_describe_close_prepared_portal(
|
2205
|
+
self, portal, gvl_PQsendDescribePortal,
|
2206
|
+
"PQsendDescribePortal");
|
2207
|
+
}
|
2090
2208
|
|
2091
|
-
|
2092
|
-
|
2209
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
2210
|
+
/*
|
2211
|
+
* call-seq:
|
2212
|
+
* conn.send_close_prepared( statement_name ) -> nil
|
2213
|
+
*
|
2214
|
+
* Asynchronously send _command_ to the server. Does not block.
|
2215
|
+
* Use in combination with +conn.get_result+.
|
2216
|
+
*
|
2217
|
+
* Available since PostgreSQL-17.
|
2218
|
+
*/
|
2219
|
+
static VALUE
|
2220
|
+
pgconn_send_close_prepared(VALUE self, VALUE stmt_name)
|
2221
|
+
{
|
2222
|
+
return pgconn_send_describe_close_prepared_portal(
|
2223
|
+
self, stmt_name, gvl_PQsendClosePrepared,
|
2224
|
+
"PQsendClosePrepared");
|
2093
2225
|
}
|
2094
2226
|
|
2095
2227
|
|
2228
|
+
/*
|
2229
|
+
* call-seq:
|
2230
|
+
* conn.send_close_portal( portal_name ) -> nil
|
2231
|
+
*
|
2232
|
+
* Asynchronously send _command_ to the server. Does not block.
|
2233
|
+
* Use in combination with +conn.get_result+.
|
2234
|
+
*
|
2235
|
+
* Available since PostgreSQL-17.
|
2236
|
+
*/
|
2237
|
+
static VALUE
|
2238
|
+
pgconn_send_close_portal(VALUE self, VALUE portal)
|
2239
|
+
{
|
2240
|
+
return pgconn_send_describe_close_prepared_portal(
|
2241
|
+
self, portal, gvl_PQsendClosePortal,
|
2242
|
+
"PQsendClosePortal");
|
2243
|
+
}
|
2244
|
+
#endif
|
2245
|
+
|
2096
2246
|
static VALUE
|
2097
2247
|
pgconn_sync_get_result(VALUE self)
|
2098
2248
|
{
|
@@ -2182,6 +2332,7 @@ pgconn_sync_flush(VALUE self)
|
|
2182
2332
|
return (ret) ? Qfalse : Qtrue;
|
2183
2333
|
}
|
2184
2334
|
|
2335
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
2185
2336
|
static VALUE
|
2186
2337
|
pgconn_sync_cancel(VALUE self)
|
2187
2338
|
{
|
@@ -2203,6 +2354,7 @@ pgconn_sync_cancel(VALUE self)
|
|
2203
2354
|
PQfreeCancel(cancel);
|
2204
2355
|
return retval;
|
2205
2356
|
}
|
2357
|
+
#endif
|
2206
2358
|
|
2207
2359
|
|
2208
2360
|
/*
|
@@ -2245,6 +2397,18 @@ pgconn_notifies(VALUE self)
|
|
2245
2397
|
return hash;
|
2246
2398
|
}
|
2247
2399
|
|
2400
|
+
#ifndef HAVE_RB_IO_DESCRIPTOR
|
2401
|
+
static int
|
2402
|
+
rb_io_descriptor(VALUE io)
|
2403
|
+
{
|
2404
|
+
rb_io_t *fptr;
|
2405
|
+
Check_Type(io, T_FILE);
|
2406
|
+
fptr = RFILE(io)->fptr;
|
2407
|
+
rb_io_check_closed(fptr);
|
2408
|
+
return fptr->fd;
|
2409
|
+
}
|
2410
|
+
#endif
|
2411
|
+
|
2248
2412
|
#if defined(_WIN32)
|
2249
2413
|
|
2250
2414
|
/* We use a specialized implementation of rb_io_wait() on Windows.
|
@@ -2265,7 +2429,6 @@ int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2265
2429
|
|
2266
2430
|
static VALUE
|
2267
2431
|
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2268
|
-
rb_io_t *fptr;
|
2269
2432
|
struct timeval ptimeout;
|
2270
2433
|
|
2271
2434
|
struct timeval aborttime={0,0}, currtime, waittime;
|
@@ -2276,7 +2439,6 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2276
2439
|
long w32_events = 0;
|
2277
2440
|
DWORD wait_ret;
|
2278
2441
|
|
2279
|
-
GetOpenFile((io), fptr);
|
2280
2442
|
if( !NIL_P(timeout) ){
|
2281
2443
|
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
2282
2444
|
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
@@ -2290,7 +2452,7 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2290
2452
|
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
2291
2453
|
|
2292
2454
|
for(;;) {
|
2293
|
-
if ( WSAEventSelect(_get_osfhandle(
|
2455
|
+
if ( WSAEventSelect(_get_osfhandle(rb_io_descriptor(io)), hEvent, w32_events) == SOCKET_ERROR ) {
|
2294
2456
|
WSACloseEvent( hEvent );
|
2295
2457
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2296
2458
|
}
|
@@ -2333,7 +2495,7 @@ static VALUE
|
|
2333
2495
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2334
2496
|
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2335
2497
|
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
2336
|
-
*
|
2498
|
+
* Fortunately ruby-3.1 offers a C-API for it.
|
2337
2499
|
*/
|
2338
2500
|
VALUE scheduler = rb_fiber_scheduler_current();
|
2339
2501
|
|
@@ -2363,16 +2525,14 @@ typedef enum {
|
|
2363
2525
|
|
2364
2526
|
static VALUE
|
2365
2527
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2366
|
-
rb_io_t *fptr;
|
2367
2528
|
struct timeval waittime;
|
2368
2529
|
int res;
|
2369
2530
|
|
2370
|
-
GetOpenFile((io), fptr);
|
2371
2531
|
if( !NIL_P(timeout) ){
|
2372
2532
|
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
2373
2533
|
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
2374
2534
|
}
|
2375
|
-
res = rb_wait_for_single_fd(
|
2535
|
+
res = rb_wait_for_single_fd(rb_io_descriptor(io), NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
2376
2536
|
|
2377
2537
|
return UINT2NUM(res);
|
2378
2538
|
}
|
@@ -2539,7 +2699,7 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2539
2699
|
VALUE value;
|
2540
2700
|
VALUE buffer = Qnil;
|
2541
2701
|
VALUE encoder;
|
2542
|
-
VALUE intermediate;
|
2702
|
+
VALUE intermediate = Qnil;
|
2543
2703
|
t_pg_coder *p_coder = NULL;
|
2544
2704
|
|
2545
2705
|
rb_scan_args( argc, argv, "11", &value, &encoder );
|
@@ -2578,7 +2738,6 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2578
2738
|
if(ret == -1)
|
2579
2739
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2580
2740
|
|
2581
|
-
RB_GC_GUARD(intermediate);
|
2582
2741
|
RB_GC_GUARD(buffer);
|
2583
2742
|
|
2584
2743
|
return (ret) ? Qtrue : Qfalse;
|
@@ -2673,7 +2832,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2673
2832
|
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
2674
2833
|
}
|
2675
2834
|
|
2676
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
2677
2835
|
/*
|
2678
2836
|
* call-seq:
|
2679
2837
|
* conn.set_error_context_visibility( context_visibility ) -> Integer
|
@@ -2693,7 +2851,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2693
2851
|
*
|
2694
2852
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
|
2695
2853
|
*
|
2696
|
-
* Available since PostgreSQL-9.6
|
2697
2854
|
*/
|
2698
2855
|
static VALUE
|
2699
2856
|
pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
@@ -2702,7 +2859,6 @@ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
|
2702
2859
|
PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
|
2703
2860
|
return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
|
2704
2861
|
}
|
2705
|
-
#endif
|
2706
2862
|
|
2707
2863
|
/*
|
2708
2864
|
* call-seq:
|
@@ -3107,7 +3263,9 @@ pgconn_async_get_last_result(VALUE self)
|
|
3107
3263
|
for(;;) {
|
3108
3264
|
int status;
|
3109
3265
|
|
3110
|
-
/*
|
3266
|
+
/* Wait for input before reading each result.
|
3267
|
+
* That way we support the ruby-3.x IO scheduler and don't block other ruby threads.
|
3268
|
+
*/
|
3111
3269
|
wait_socket_readable(self, NULL, get_result_readable);
|
3112
3270
|
|
3113
3271
|
cur = gvl_PQgetResult(conn);
|
@@ -3141,7 +3299,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
3141
3299
|
* Returns:
|
3142
3300
|
* * +nil+ when the connection is already idle
|
3143
3301
|
* * +true+ when some results have been discarded
|
3144
|
-
* * +false+ when a failure
|
3302
|
+
* * +false+ when a failure occurred and the connection was closed
|
3145
3303
|
*
|
3146
3304
|
*/
|
3147
3305
|
static VALUE
|
@@ -3428,6 +3586,21 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
3428
3586
|
return rb_pgresult;
|
3429
3587
|
}
|
3430
3588
|
|
3589
|
+
static VALUE
|
3590
|
+
pgconn_async_describe_close_prepared_potral(VALUE self, VALUE name, VALUE
|
3591
|
+
(*func)(VALUE, VALUE))
|
3592
|
+
{
|
3593
|
+
VALUE rb_pgresult = Qnil;
|
3594
|
+
|
3595
|
+
pgconn_discard_results( self );
|
3596
|
+
func( self, name );
|
3597
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3598
|
+
|
3599
|
+
if ( rb_block_given_p() ) {
|
3600
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3601
|
+
}
|
3602
|
+
return rb_pgresult;
|
3603
|
+
}
|
3431
3604
|
|
3432
3605
|
/*
|
3433
3606
|
* call-seq:
|
@@ -3440,16 +3613,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
3440
3613
|
static VALUE
|
3441
3614
|
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
3442
3615
|
{
|
3443
|
-
|
3444
|
-
|
3445
|
-
pgconn_discard_results( self );
|
3446
|
-
pgconn_send_describe_portal( self, portal );
|
3447
|
-
rb_pgresult = pgconn_async_get_last_result( self );
|
3448
|
-
|
3449
|
-
if ( rb_block_given_p() ) {
|
3450
|
-
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3451
|
-
}
|
3452
|
-
return rb_pgresult;
|
3616
|
+
return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_describe_portal);
|
3453
3617
|
}
|
3454
3618
|
|
3455
3619
|
|
@@ -3464,27 +3628,64 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
3464
3628
|
static VALUE
|
3465
3629
|
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
3466
3630
|
{
|
3467
|
-
|
3468
|
-
|
3469
|
-
pgconn_discard_results( self );
|
3470
|
-
pgconn_send_describe_prepared( self, stmt_name );
|
3471
|
-
rb_pgresult = pgconn_async_get_last_result( self );
|
3631
|
+
return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_describe_prepared);
|
3632
|
+
}
|
3472
3633
|
|
3473
|
-
|
3474
|
-
|
3475
|
-
|
3476
|
-
|
3634
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
3635
|
+
/*
|
3636
|
+
* call-seq:
|
3637
|
+
* conn.close_prepared( statement_name ) -> PG::Result
|
3638
|
+
*
|
3639
|
+
* Submits a request to close the specified prepared statement, and waits for completion.
|
3640
|
+
* close_prepared allows an application to close a previously prepared statement.
|
3641
|
+
* Closing a statement releases all of its associated resources on the server and allows its name to be reused.
|
3642
|
+
* It's the same as using the +DEALLOCATE+ SQL statement, but on a lower protocol level.
|
3643
|
+
*
|
3644
|
+
* +statement_name+ can be "" or +nil+ to reference the unnamed statement.
|
3645
|
+
* It is fine if no statement exists with this name, in that case the operation is a no-op.
|
3646
|
+
* On success, a PG::Result with status PGRES_COMMAND_OK is returned.
|
3647
|
+
*
|
3648
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLOSEPREPARED].
|
3649
|
+
*
|
3650
|
+
* Available since PostgreSQL-17.
|
3651
|
+
*/
|
3652
|
+
static VALUE
|
3653
|
+
pgconn_async_close_prepared(VALUE self, VALUE stmt_name)
|
3654
|
+
{
|
3655
|
+
return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_close_prepared);
|
3477
3656
|
}
|
3478
3657
|
|
3658
|
+
/*
|
3659
|
+
* call-seq:
|
3660
|
+
* conn.close_portal( portal_name ) -> PG::Result
|
3661
|
+
*
|
3662
|
+
* Submits a request to close the specified portal, and waits for completion.
|
3663
|
+
*
|
3664
|
+
* close_portal allows an application to trigger a close of a previously created portal.
|
3665
|
+
* Closing a portal releases all of its associated resources on the server and allows its name to be reused.
|
3666
|
+
* (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.)
|
3667
|
+
*
|
3668
|
+
* +portal_name+ can be "" or +nil+ to reference the unnamed portal.
|
3669
|
+
* It is fine if no portal exists with this name, in that case the operation is a no-op.
|
3670
|
+
* On success, a PG::Result with status PGRES_COMMAND_OK is returned.
|
3671
|
+
*
|
3672
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLOSEPORTAL].
|
3673
|
+
*
|
3674
|
+
* Available since PostgreSQL-17.
|
3675
|
+
*/
|
3676
|
+
static VALUE
|
3677
|
+
pgconn_async_close_portal(VALUE self, VALUE portal)
|
3678
|
+
{
|
3679
|
+
return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_close_portal);
|
3680
|
+
}
|
3681
|
+
#endif
|
3479
3682
|
|
3480
|
-
#ifdef HAVE_PQSSLATTRIBUTE
|
3481
3683
|
/*
|
3482
3684
|
* call-seq:
|
3483
3685
|
* conn.ssl_in_use? -> Boolean
|
3484
3686
|
*
|
3485
3687
|
* Returns +true+ if the connection uses SSL/TLS, +false+ if not.
|
3486
3688
|
*
|
3487
|
-
* Available since PostgreSQL-9.5
|
3488
3689
|
*/
|
3489
3690
|
static VALUE
|
3490
3691
|
pgconn_ssl_in_use(VALUE self)
|
@@ -3518,7 +3719,6 @@ pgconn_ssl_in_use(VALUE self)
|
|
3518
3719
|
*
|
3519
3720
|
* See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
|
3520
3721
|
*
|
3521
|
-
* Available since PostgreSQL-9.5
|
3522
3722
|
*/
|
3523
3723
|
static VALUE
|
3524
3724
|
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
@@ -3537,7 +3737,6 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
|
3537
3737
|
*
|
3538
3738
|
* See also #ssl_attribute
|
3539
3739
|
*
|
3540
|
-
* Available since PostgreSQL-9.5
|
3541
3740
|
*/
|
3542
3741
|
static VALUE
|
3543
3742
|
pgconn_ssl_attribute_names(VALUE self)
|
@@ -3553,8 +3752,6 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
3553
3752
|
}
|
3554
3753
|
|
3555
3754
|
|
3556
|
-
#endif
|
3557
|
-
|
3558
3755
|
|
3559
3756
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
3560
3757
|
/*
|
@@ -3589,6 +3786,8 @@ pgconn_pipeline_status(VALUE self)
|
|
3589
3786
|
* 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.
|
3590
3787
|
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
3591
3788
|
*
|
3789
|
+
* See the {PostgreSQL documentation}[https://www.postgresql.org/docs/17/libpq-pipeline-mode.html#LIBPQ-PIPELINE-MODE].
|
3790
|
+
*
|
3592
3791
|
* Available since PostgreSQL-14
|
3593
3792
|
*/
|
3594
3793
|
static VALUE
|
@@ -3627,29 +3826,55 @@ pgconn_exit_pipeline_mode(VALUE self)
|
|
3627
3826
|
|
3628
3827
|
/*
|
3629
3828
|
* call-seq:
|
3630
|
-
* conn.
|
3829
|
+
* conn.sync_pipeline_sync -> nil
|
3631
3830
|
*
|
3632
|
-
*
|
3633
|
-
*
|
3831
|
+
* This function has the same behavior as #async_pipeline_sync, but is implemented using the synchronous command processing API of libpq.
|
3832
|
+
* See #async_exec for the differences between the two API variants.
|
3833
|
+
* It's not recommended to use explicit sync or async variants but #pipeline_sync instead, unless you have a good reason to do so.
|
3634
3834
|
*
|
3835
|
+
* Available since PostgreSQL-14
|
3836
|
+
*/
|
3837
|
+
static VALUE
|
3838
|
+
pgconn_sync_pipeline_sync(VALUE self)
|
3839
|
+
{
|
3840
|
+
PGconn *conn = pg_get_pgconn(self);
|
3841
|
+
int res = gvl_PQpipelineSync(conn);
|
3842
|
+
if( res != 1 )
|
3843
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3844
|
+
|
3845
|
+
return Qnil;
|
3846
|
+
}
|
3847
|
+
|
3848
|
+
|
3849
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
3850
|
+
/*
|
3851
|
+
* call-seq:
|
3852
|
+
* conn.send_pipeline_sync -> nil
|
3853
|
+
*
|
3854
|
+
* Marks a synchronization point in a pipeline by sending a sync message without flushing the send buffer.
|
3855
|
+
*
|
3856
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point.
|
3635
3857
|
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
3858
|
+
* Note that the message is not itself flushed to the server automatically; use flush if necessary.
|
3636
3859
|
*
|
3637
|
-
* Available since PostgreSQL-
|
3860
|
+
* Available since PostgreSQL-17
|
3638
3861
|
*/
|
3639
3862
|
static VALUE
|
3640
|
-
|
3863
|
+
pgconn_send_pipeline_sync(VALUE self)
|
3641
3864
|
{
|
3642
3865
|
PGconn *conn = pg_get_pgconn(self);
|
3643
|
-
int res =
|
3866
|
+
int res = gvl_PQsendPipelineSync(conn);
|
3644
3867
|
if( res != 1 )
|
3645
3868
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3646
3869
|
|
3647
3870
|
return Qnil;
|
3648
3871
|
}
|
3872
|
+
#endif
|
3873
|
+
|
3649
3874
|
|
3650
3875
|
/*
|
3651
3876
|
* call-seq:
|
3652
|
-
* conn.
|
3877
|
+
* conn.send_flush_request -> nil
|
3653
3878
|
*
|
3654
3879
|
* Sends a request for the server to flush its output buffer.
|
3655
3880
|
*
|
@@ -4468,6 +4693,7 @@ init_pg_connection(void)
|
|
4468
4693
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
4469
4694
|
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
4470
4695
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
4696
|
+
rb_define_private_method(rb_cPGconn, "reset_start2", pgconn_reset_start2, 1);
|
4471
4697
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4472
4698
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
4473
4699
|
|
@@ -4492,7 +4718,9 @@ init_pg_connection(void)
|
|
4492
4718
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
4493
4719
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
4494
4720
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4721
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
4495
4722
|
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
4723
|
+
#endif
|
4496
4724
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
4497
4725
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
4498
4726
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
@@ -4504,6 +4732,10 @@ init_pg_connection(void)
|
|
4504
4732
|
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
4505
4733
|
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
4506
4734
|
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
4735
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
4736
|
+
rb_define_method(rb_cPGconn, "sync_close_prepared", pgconn_sync_close_prepared, 1);
|
4737
|
+
rb_define_method(rb_cPGconn, "sync_close_portal", pgconn_sync_close_portal, 1);
|
4738
|
+
#endif
|
4507
4739
|
|
4508
4740
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
4509
4741
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
@@ -4511,6 +4743,10 @@ init_pg_connection(void)
|
|
4511
4743
|
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
|
4512
4744
|
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
|
4513
4745
|
rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
|
4746
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
4747
|
+
rb_define_method(rb_cPGconn, "close_prepared", pgconn_async_close_prepared, 1);
|
4748
|
+
rb_define_method(rb_cPGconn, "close_portal", pgconn_async_close_portal, 1);
|
4749
|
+
#endif
|
4514
4750
|
|
4515
4751
|
rb_define_alias(rb_cPGconn, "async_exec", "exec");
|
4516
4752
|
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
@@ -4519,6 +4755,10 @@ init_pg_connection(void)
|
|
4519
4755
|
rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
|
4520
4756
|
rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
|
4521
4757
|
rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
|
4758
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
4759
|
+
rb_define_alias(rb_cPGconn, "async_close_prepared", "close_prepared");
|
4760
|
+
rb_define_alias(rb_cPGconn, "async_close_portal", "close_portal");
|
4761
|
+
#endif
|
4522
4762
|
|
4523
4763
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
4524
4764
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
@@ -4528,6 +4768,9 @@ init_pg_connection(void)
|
|
4528
4768
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4529
4769
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4530
4770
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
4771
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
4772
|
+
rb_define_method(rb_cPGconn, "set_chunked_rows_mode", pgconn_set_chunked_rows_mode, 1);
|
4773
|
+
#endif
|
4531
4774
|
|
4532
4775
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
4533
4776
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
@@ -4547,7 +4790,9 @@ init_pg_connection(void)
|
|
4547
4790
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
4548
4791
|
|
4549
4792
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4793
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
4550
4794
|
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
4795
|
+
#endif
|
4551
4796
|
|
4552
4797
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
4553
4798
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
@@ -4559,9 +4804,7 @@ init_pg_connection(void)
|
|
4559
4804
|
|
4560
4805
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
4561
4806
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4562
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
4563
4807
|
rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
|
4564
|
-
#endif
|
4565
4808
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
4566
4809
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4567
4810
|
|
@@ -4583,22 +4826,21 @@ init_pg_connection(void)
|
|
4583
4826
|
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
4584
4827
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
4585
4828
|
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
4586
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4587
4829
|
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
4588
|
-
#endif
|
4589
4830
|
|
4590
|
-
#ifdef HAVE_PQSSLATTRIBUTE
|
4591
4831
|
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
4592
4832
|
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
4593
4833
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4594
|
-
#endif
|
4595
4834
|
|
4596
4835
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
4597
4836
|
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
4598
4837
|
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
4599
4838
|
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
4600
|
-
rb_define_method(rb_cPGconn, "
|
4839
|
+
rb_define_method(rb_cPGconn, "sync_pipeline_sync", pgconn_sync_pipeline_sync, 0);
|
4601
4840
|
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
4841
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
4842
|
+
rb_define_method(rb_cPGconn, "send_pipeline_sync", pgconn_send_pipeline_sync, 0);
|
4843
|
+
#endif
|
4602
4844
|
#endif
|
4603
4845
|
|
4604
4846
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|