pg 1.4.6 → 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} +185 -3
- data/Gemfile +12 -3
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +75 -41
- data/README.md +86 -31
- 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 +165 -14
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +33 -0
- data/ext/pg.c +28 -35
- data/ext/pg.h +18 -14
- data/ext/pg_binary_decoder.c +231 -0
- data/ext/pg_binary_encoder.c +427 -0
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +70 -12
- data/ext/pg_connection.c +473 -208
- data/ext/pg_copy_coder.c +316 -23
- data/ext/pg_record_coder.c +12 -11
- data/ext/pg_result.c +102 -30
- data/ext/pg_text_decoder.c +31 -10
- data/ext/pg_text_encoder.c +58 -26
- data/ext/pg_tuple.c +36 -33
- data/ext/pg_type_map.c +4 -3
- data/ext/pg_type_map_all_strings.c +3 -3
- data/ext/pg_type_map_by_class.c +6 -4
- data/ext/pg_type_map_by_column.c +9 -4
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +10 -5
- data/ext/pg_type_map_in_ruby.c +6 -3
- data/lib/pg/basic_type_map_based_on_result.rb +21 -1
- data/lib/pg/basic_type_map_for_queries.rb +23 -10
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +46 -36
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +18 -14
- data/lib/pg/connection.rb +387 -172
- data/lib/pg/exceptions.rb +6 -0
- data/lib/pg/text_decoder/date.rb +21 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +17 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +13 -0
- data/lib/pg/text_encoder/inet.rb +31 -0
- data/lib/pg/text_encoder/json.rb +17 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +78 -17
- 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 +9 -5
- 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 +61 -49
- 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 -137
- data/.gitignore +0 -19
- 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/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
- data/translation/.po4a-version +0 -7
- data/translation/po/all.pot +0 -875
- data/translation/po/ja.po +0 -868
- data/translation/po4a.cfg +0 -9
data/ext/pg_connection.c
CHANGED
@@ -16,9 +16,6 @@ static ID s_id_autoclose_set;
|
|
16
16
|
static VALUE sym_type, sym_format, sym_value;
|
17
17
|
static VALUE sym_symbol, sym_string, sym_static_symbol;
|
18
18
|
|
19
|
-
static PQnoticeReceiver default_notice_receiver = NULL;
|
20
|
-
static PQnoticeProcessor default_notice_processor = NULL;
|
21
|
-
|
22
19
|
static VALUE pgconn_finish( VALUE );
|
23
20
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
24
21
|
static VALUE pgconn_wait_for_flush( VALUE self );
|
@@ -33,10 +30,7 @@ static VALUE pgconn_async_flush(VALUE self);
|
|
33
30
|
/*
|
34
31
|
* Convenience function to raise connection errors
|
35
32
|
*/
|
36
|
-
|
37
|
-
__attribute__((format(printf, 3, 4)))
|
38
|
-
#endif
|
39
|
-
static void
|
33
|
+
void
|
40
34
|
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
41
35
|
{
|
42
36
|
VALUE msg, error;
|
@@ -99,6 +93,20 @@ pg_get_pgconn( VALUE self )
|
|
99
93
|
}
|
100
94
|
|
101
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
|
+
|
102
110
|
|
103
111
|
/*
|
104
112
|
* Close the associated socket IO object if there is one.
|
@@ -107,17 +115,7 @@ static void
|
|
107
115
|
pgconn_close_socket_io( VALUE self )
|
108
116
|
{
|
109
117
|
t_pg_connection *this = pg_get_connection( self );
|
110
|
-
|
111
|
-
|
112
|
-
if ( RTEST(socket_io) ) {
|
113
|
-
#if defined(_WIN32)
|
114
|
-
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
115
|
-
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
116
|
-
#endif
|
117
|
-
rb_funcall( socket_io, rb_intern("close"), 0 );
|
118
|
-
}
|
119
|
-
|
120
|
-
this->socket_io = Qnil;
|
118
|
+
pg_unwrap_socket_io( self, &this->socket_io, this->ruby_sd);
|
121
119
|
}
|
122
120
|
|
123
121
|
|
@@ -233,11 +231,11 @@ static const rb_data_type_t pg_connection_type = {
|
|
233
231
|
pgconn_gc_mark,
|
234
232
|
pgconn_gc_free,
|
235
233
|
pgconn_memsize,
|
236
|
-
|
234
|
+
pgconn_gc_compact,
|
237
235
|
},
|
238
236
|
0,
|
239
237
|
0,
|
240
|
-
|
238
|
+
RUBY_TYPED_WB_PROTECTED,
|
241
239
|
};
|
242
240
|
|
243
241
|
|
@@ -258,15 +256,16 @@ pgconn_s_allocate( VALUE klass )
|
|
258
256
|
VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
|
259
257
|
|
260
258
|
this->pgconn = NULL;
|
261
|
-
this->socket_io
|
262
|
-
this->notice_receiver
|
263
|
-
this->notice_processor
|
264
|
-
this->type_map_for_queries
|
265
|
-
this->type_map_for_results
|
266
|
-
this->encoder_for_put_copy_data
|
267
|
-
this->decoder_for_get_copy_data
|
268
|
-
this->trace_stream
|
259
|
+
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
260
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
|
261
|
+
RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
|
262
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
|
263
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
|
264
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
|
265
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, Qnil);
|
266
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
269
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);
|
270
269
|
|
271
270
|
return self;
|
272
271
|
}
|
@@ -421,7 +420,6 @@ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
|
|
421
420
|
}
|
422
421
|
|
423
422
|
|
424
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
425
423
|
static VALUE
|
426
424
|
pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
427
425
|
{
|
@@ -445,7 +443,6 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
445
443
|
|
446
444
|
return rval;
|
447
445
|
}
|
448
|
-
#endif
|
449
446
|
|
450
447
|
|
451
448
|
/*
|
@@ -518,9 +515,9 @@ static VALUE
|
|
518
515
|
pgconn_connect_poll(VALUE self)
|
519
516
|
{
|
520
517
|
PostgresPollingStatusType status;
|
521
|
-
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
522
518
|
|
523
519
|
pgconn_close_socket_io(self);
|
520
|
+
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
524
521
|
|
525
522
|
return INT2FIX((int)status);
|
526
523
|
}
|
@@ -566,6 +563,27 @@ pgconn_sync_reset( VALUE self )
|
|
566
563
|
return self;
|
567
564
|
}
|
568
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
|
+
|
569
587
|
/*
|
570
588
|
* call-seq:
|
571
589
|
* conn.reset_start() -> nil
|
@@ -590,16 +608,16 @@ pgconn_reset_start(VALUE self)
|
|
590
608
|
* conn.reset_poll -> Integer
|
591
609
|
*
|
592
610
|
* Checks the status of a connection reset operation.
|
593
|
-
* See
|
611
|
+
* See Connection.connect_start and #connect_poll for
|
594
612
|
* usage information and return values.
|
595
613
|
*/
|
596
614
|
static VALUE
|
597
615
|
pgconn_reset_poll(VALUE self)
|
598
616
|
{
|
599
617
|
PostgresPollingStatusType status;
|
600
|
-
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
601
618
|
|
602
619
|
pgconn_close_socket_io(self);
|
620
|
+
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
603
621
|
|
604
622
|
return INT2FIX((int)status);
|
605
623
|
}
|
@@ -741,7 +759,6 @@ pgconn_options(VALUE self)
|
|
741
759
|
*
|
742
760
|
* Returns the connection options used by a live connection.
|
743
761
|
*
|
744
|
-
* Available since PostgreSQL-9.3
|
745
762
|
*/
|
746
763
|
static VALUE
|
747
764
|
pgconn_conninfo( VALUE self )
|
@@ -766,6 +783,10 @@ pgconn_conninfo( VALUE self )
|
|
766
783
|
*
|
767
784
|
* ... and other constants of kind PG::Constants::CONNECTION_*
|
768
785
|
*
|
786
|
+
* This method returns the status of the last command from memory.
|
787
|
+
* It doesn't do any socket access hence is not suitable to test the connectivity.
|
788
|
+
* See check_socket for a way to verify the socket state.
|
789
|
+
*
|
769
790
|
* Example:
|
770
791
|
* PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
|
771
792
|
*/
|
@@ -824,31 +845,52 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
824
845
|
* call-seq:
|
825
846
|
* conn.protocol_version -> Integer
|
826
847
|
*
|
827
|
-
*
|
828
|
-
*
|
829
|
-
*
|
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.
|
830
856
|
*/
|
831
857
|
static VALUE
|
832
858
|
pgconn_protocol_version(VALUE self)
|
833
859
|
{
|
834
|
-
|
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);
|
835
865
|
}
|
836
866
|
|
837
867
|
/*
|
838
868
|
* call-seq:
|
839
869
|
* conn.server_version -> Integer
|
840
870
|
*
|
841
|
-
*
|
842
|
-
*
|
843
|
-
*
|
844
|
-
*
|
845
|
-
*
|
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).
|
846
884
|
*
|
847
885
|
*/
|
848
886
|
static VALUE
|
849
887
|
pgconn_server_version(VALUE self)
|
850
888
|
{
|
851
|
-
|
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);
|
852
894
|
}
|
853
895
|
|
854
896
|
/*
|
@@ -897,13 +939,42 @@ pgconn_socket(VALUE self)
|
|
897
939
|
return INT2NUM(sd);
|
898
940
|
}
|
899
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
|
+
|
900
971
|
/*
|
901
972
|
* call-seq:
|
902
973
|
* conn.socket_io() -> IO
|
903
974
|
*
|
904
975
|
* Fetch an IO object created from the Connection's underlying socket.
|
905
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.
|
906
|
-
* <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>.
|
907
978
|
*
|
908
979
|
* The IO object can change while the connection is established, but is memorized afterwards.
|
909
980
|
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
@@ -914,37 +985,17 @@ pgconn_socket(VALUE self)
|
|
914
985
|
static VALUE
|
915
986
|
pgconn_socket_io(VALUE self)
|
916
987
|
{
|
917
|
-
int sd;
|
918
|
-
int ruby_sd;
|
919
988
|
t_pg_connection *this = pg_get_connection_safe( self );
|
920
|
-
VALUE cSocket;
|
921
|
-
VALUE socket_io = this->socket_io;
|
922
989
|
|
923
|
-
if ( !RTEST(socket_io) ) {
|
990
|
+
if ( !RTEST(this->socket_io) ) {
|
991
|
+
int sd;
|
924
992
|
if( (sd = PQsocket(this->pgconn)) < 0){
|
925
993
|
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
926
994
|
}
|
927
|
-
|
928
|
-
#ifdef _WIN32
|
929
|
-
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
930
|
-
if( ruby_sd == -1 )
|
931
|
-
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
932
|
-
|
933
|
-
this->ruby_sd = ruby_sd;
|
934
|
-
#else
|
935
|
-
ruby_sd = sd;
|
936
|
-
#endif
|
937
|
-
|
938
|
-
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
939
|
-
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
940
|
-
|
941
|
-
/* Disable autoclose feature */
|
942
|
-
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
943
|
-
|
944
|
-
this->socket_io = socket_io;
|
995
|
+
return pg_wrap_socket_io( sd, self, &this->socket_io, &this->ruby_sd);
|
945
996
|
}
|
946
997
|
|
947
|
-
return socket_io;
|
998
|
+
return this->socket_io;
|
948
999
|
}
|
949
1000
|
|
950
1001
|
/*
|
@@ -961,6 +1012,7 @@ pgconn_backend_pid(VALUE self)
|
|
961
1012
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
962
1013
|
}
|
963
1014
|
|
1015
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
964
1016
|
typedef struct
|
965
1017
|
{
|
966
1018
|
struct sockaddr_storage addr;
|
@@ -1005,6 +1057,7 @@ pgconn_backend_key(VALUE self)
|
|
1005
1057
|
|
1006
1058
|
return INT2NUM(be_key);
|
1007
1059
|
}
|
1060
|
+
#endif
|
1008
1061
|
|
1009
1062
|
/*
|
1010
1063
|
* call-seq:
|
@@ -1158,7 +1211,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1158
1211
|
},
|
1159
1212
|
0,
|
1160
1213
|
0,
|
1161
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1214
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1162
1215
|
};
|
1163
1216
|
|
1164
1217
|
static char *
|
@@ -1191,7 +1244,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1191
1244
|
},
|
1192
1245
|
0,
|
1193
1246
|
0,
|
1194
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1247
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1195
1248
|
};
|
1196
1249
|
|
1197
1250
|
static int
|
@@ -1277,7 +1330,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1277
1330
|
paramsData->lengths[i] = 0;
|
1278
1331
|
} else {
|
1279
1332
|
t_pg_coder_enc_func enc_func = pg_coder_enc_func( conv );
|
1280
|
-
VALUE intermediate;
|
1333
|
+
VALUE intermediate = Qnil;
|
1281
1334
|
|
1282
1335
|
/* 1st pass for retiving the required memory space */
|
1283
1336
|
int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
|
@@ -1317,8 +1370,6 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1317
1370
|
required_pool_size += len;
|
1318
1371
|
}
|
1319
1372
|
}
|
1320
|
-
|
1321
|
-
RB_GC_GUARD(intermediate);
|
1322
1373
|
}
|
1323
1374
|
}
|
1324
1375
|
}
|
@@ -1493,6 +1544,19 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1493
1544
|
return rb_pgresult;
|
1494
1545
|
}
|
1495
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
|
+
|
1496
1560
|
/*
|
1497
1561
|
* call-seq:
|
1498
1562
|
* conn.sync_describe_prepared( statement_name ) -> PG::Result
|
@@ -1504,20 +1568,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1504
1568
|
static VALUE
|
1505
1569
|
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
1506
1570
|
{
|
1507
|
-
|
1508
|
-
VALUE rb_pgresult;
|
1509
|
-
t_pg_connection *this = pg_get_connection_safe( self );
|
1510
|
-
const char *stmt;
|
1511
|
-
if(NIL_P(stmt_name)) {
|
1512
|
-
stmt = NULL;
|
1513
|
-
}
|
1514
|
-
else {
|
1515
|
-
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1516
|
-
}
|
1517
|
-
result = gvl_PQdescribePrepared(this->pgconn, stmt);
|
1518
|
-
rb_pgresult = pg_new_result(result, self);
|
1519
|
-
pg_result_check(rb_pgresult);
|
1520
|
-
return rb_pgresult;
|
1571
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePrepared);
|
1521
1572
|
}
|
1522
1573
|
|
1523
1574
|
|
@@ -1532,23 +1583,44 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1532
1583
|
static VALUE
|
1533
1584
|
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
1534
1585
|
{
|
1535
|
-
|
1536
|
-
VALUE rb_pgresult;
|
1537
|
-
t_pg_connection *this = pg_get_connection_safe( self );
|
1538
|
-
const char *stmt;
|
1539
|
-
if(NIL_P(stmt_name)) {
|
1540
|
-
stmt = NULL;
|
1541
|
-
}
|
1542
|
-
else {
|
1543
|
-
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1544
|
-
}
|
1545
|
-
result = gvl_PQdescribePortal(this->pgconn, stmt);
|
1546
|
-
rb_pgresult = pg_new_result(result, self);
|
1547
|
-
pg_result_check(rb_pgresult);
|
1548
|
-
return rb_pgresult;
|
1586
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePortal);
|
1549
1587
|
}
|
1550
1588
|
|
1551
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
|
+
|
1552
1624
|
/*
|
1553
1625
|
* call-seq:
|
1554
1626
|
* conn.make_empty_pgresult( status ) -> PG::Result
|
@@ -1565,6 +1637,7 @@ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
1565
1637
|
* * +PGRES_FATAL_ERROR+
|
1566
1638
|
* * +PGRES_COPY_BOTH+
|
1567
1639
|
* * +PGRES_SINGLE_TUPLE+
|
1640
|
+
* * +PGRES_TUPLES_CHUNK+
|
1568
1641
|
* * +PGRES_PIPELINE_SYNC+
|
1569
1642
|
* * +PGRES_PIPELINE_ABORTED+
|
1570
1643
|
*/
|
@@ -1789,14 +1862,11 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1789
1862
|
* (column names, types, etc) that an ordinary Result object for the query
|
1790
1863
|
* would have.
|
1791
1864
|
*
|
1792
|
-
* *Caution:* While processing a query, the server may return some rows and
|
1793
|
-
*
|
1794
|
-
*
|
1795
|
-
*
|
1796
|
-
* application
|
1797
|
-
* For proper transactional behavior, the application must be designed to discard
|
1798
|
-
* or undo whatever has been done with the previously-processed rows, if the query
|
1799
|
-
* 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.
|
1800
1870
|
*
|
1801
1871
|
* Example:
|
1802
1872
|
* conn.send_query( "your SQL command" )
|
@@ -1814,11 +1884,51 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1814
1884
|
{
|
1815
1885
|
PGconn *conn = pg_get_pgconn(self);
|
1816
1886
|
|
1887
|
+
rb_check_frozen(self);
|
1817
1888
|
if( PQsetSingleRowMode(conn) == 0 )
|
1818
|
-
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));
|
1819
1928
|
|
1820
1929
|
return self;
|
1821
1930
|
}
|
1931
|
+
#endif
|
1822
1932
|
|
1823
1933
|
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
1824
1934
|
|
@@ -1843,7 +1953,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1843
1953
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
1844
1954
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1845
1955
|
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
1846
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1956
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));
|
1847
1957
|
|
1848
1958
|
pgconn_wait_for_flush( self );
|
1849
1959
|
return Qnil;
|
@@ -1918,7 +2028,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1918
2028
|
free_query_params( ¶msData );
|
1919
2029
|
|
1920
2030
|
if(result == 0)
|
1921
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2031
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryParams %s", PQerrorMessage(this->pgconn));
|
1922
2032
|
|
1923
2033
|
pgconn_wait_for_flush( self );
|
1924
2034
|
return Qnil;
|
@@ -1979,7 +2089,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1979
2089
|
xfree(paramTypes);
|
1980
2090
|
|
1981
2091
|
if(result == 0) {
|
1982
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2092
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendPrepare %s", PQerrorMessage(this->pgconn));
|
1983
2093
|
}
|
1984
2094
|
pgconn_wait_for_flush( self );
|
1985
2095
|
return Qnil;
|
@@ -2045,7 +2155,21 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
2045
2155
|
free_query_params( ¶msData );
|
2046
2156
|
|
2047
2157
|
if(result == 0)
|
2048
|
-
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));
|
2049
2173
|
|
2050
2174
|
pgconn_wait_for_flush( self );
|
2051
2175
|
return Qnil;
|
@@ -2061,13 +2185,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
2061
2185
|
static VALUE
|
2062
2186
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
2063
2187
|
{
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2068
|
-
|
2069
|
-
pgconn_wait_for_flush( self );
|
2070
|
-
return Qnil;
|
2188
|
+
return pgconn_send_describe_close_prepared_portal(
|
2189
|
+
self, stmt_name, gvl_PQsendDescribePrepared,
|
2190
|
+
"PQsendDescribePrepared");
|
2071
2191
|
}
|
2072
2192
|
|
2073
2193
|
|
@@ -2081,16 +2201,48 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2081
2201
|
static VALUE
|
2082
2202
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
2083
2203
|
{
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2204
|
+
return pgconn_send_describe_close_prepared_portal(
|
2205
|
+
self, portal, gvl_PQsendDescribePortal,
|
2206
|
+
"PQsendDescribePortal");
|
2207
|
+
}
|
2088
2208
|
|
2089
|
-
|
2090
|
-
|
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");
|
2091
2225
|
}
|
2092
2226
|
|
2093
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
|
+
|
2094
2246
|
static VALUE
|
2095
2247
|
pgconn_sync_get_result(VALUE self)
|
2096
2248
|
{
|
@@ -2148,6 +2300,7 @@ pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
|
2148
2300
|
{
|
2149
2301
|
int arg;
|
2150
2302
|
PGconn *conn = pg_get_pgconn(self);
|
2303
|
+
rb_check_frozen(self);
|
2151
2304
|
if(state == Qtrue)
|
2152
2305
|
arg = 1;
|
2153
2306
|
else if (state == Qfalse)
|
@@ -2179,6 +2332,7 @@ pgconn_sync_flush(VALUE self)
|
|
2179
2332
|
return (ret) ? Qfalse : Qtrue;
|
2180
2333
|
}
|
2181
2334
|
|
2335
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
2182
2336
|
static VALUE
|
2183
2337
|
pgconn_sync_cancel(VALUE self)
|
2184
2338
|
{
|
@@ -2200,6 +2354,7 @@ pgconn_sync_cancel(VALUE self)
|
|
2200
2354
|
PQfreeCancel(cancel);
|
2201
2355
|
return retval;
|
2202
2356
|
}
|
2357
|
+
#endif
|
2203
2358
|
|
2204
2359
|
|
2205
2360
|
/*
|
@@ -2242,6 +2397,18 @@ pgconn_notifies(VALUE self)
|
|
2242
2397
|
return hash;
|
2243
2398
|
}
|
2244
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
|
+
|
2245
2412
|
#if defined(_WIN32)
|
2246
2413
|
|
2247
2414
|
/* We use a specialized implementation of rb_io_wait() on Windows.
|
@@ -2262,7 +2429,6 @@ int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2262
2429
|
|
2263
2430
|
static VALUE
|
2264
2431
|
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2265
|
-
rb_io_t *fptr;
|
2266
2432
|
struct timeval ptimeout;
|
2267
2433
|
|
2268
2434
|
struct timeval aborttime={0,0}, currtime, waittime;
|
@@ -2273,7 +2439,6 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2273
2439
|
long w32_events = 0;
|
2274
2440
|
DWORD wait_ret;
|
2275
2441
|
|
2276
|
-
GetOpenFile((io), fptr);
|
2277
2442
|
if( !NIL_P(timeout) ){
|
2278
2443
|
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
2279
2444
|
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
@@ -2287,7 +2452,7 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2287
2452
|
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
2288
2453
|
|
2289
2454
|
for(;;) {
|
2290
|
-
if ( WSAEventSelect(_get_osfhandle(
|
2455
|
+
if ( WSAEventSelect(_get_osfhandle(rb_io_descriptor(io)), hEvent, w32_events) == SOCKET_ERROR ) {
|
2291
2456
|
WSACloseEvent( hEvent );
|
2292
2457
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2293
2458
|
}
|
@@ -2330,7 +2495,7 @@ static VALUE
|
|
2330
2495
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2331
2496
|
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2332
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.
|
2333
|
-
*
|
2498
|
+
* Fortunately ruby-3.1 offers a C-API for it.
|
2334
2499
|
*/
|
2335
2500
|
VALUE scheduler = rb_fiber_scheduler_current();
|
2336
2501
|
|
@@ -2360,16 +2525,14 @@ typedef enum {
|
|
2360
2525
|
|
2361
2526
|
static VALUE
|
2362
2527
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2363
|
-
rb_io_t *fptr;
|
2364
2528
|
struct timeval waittime;
|
2365
2529
|
int res;
|
2366
2530
|
|
2367
|
-
GetOpenFile((io), fptr);
|
2368
2531
|
if( !NIL_P(timeout) ){
|
2369
2532
|
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
2370
2533
|
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
2371
2534
|
}
|
2372
|
-
res = rb_wait_for_single_fd(
|
2535
|
+
res = rb_wait_for_single_fd(rb_io_descriptor(io), NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
2373
2536
|
|
2374
2537
|
return UINT2NUM(res);
|
2375
2538
|
}
|
@@ -2464,6 +2627,7 @@ pgconn_wait_for_flush( VALUE self ){
|
|
2464
2627
|
static VALUE
|
2465
2628
|
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2466
2629
|
t_pg_connection *conn = pg_get_connection(self);
|
2630
|
+
rb_check_frozen(self);
|
2467
2631
|
conn->flush_data = RTEST(enabled);
|
2468
2632
|
return enabled;
|
2469
2633
|
}
|
@@ -2535,7 +2699,7 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2535
2699
|
VALUE value;
|
2536
2700
|
VALUE buffer = Qnil;
|
2537
2701
|
VALUE encoder;
|
2538
|
-
VALUE intermediate;
|
2702
|
+
VALUE intermediate = Qnil;
|
2539
2703
|
t_pg_coder *p_coder = NULL;
|
2540
2704
|
|
2541
2705
|
rb_scan_args( argc, argv, "11", &value, &encoder );
|
@@ -2574,7 +2738,6 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2574
2738
|
if(ret == -1)
|
2575
2739
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2576
2740
|
|
2577
|
-
RB_GC_GUARD(intermediate);
|
2578
2741
|
RB_GC_GUARD(buffer);
|
2579
2742
|
|
2580
2743
|
return (ret) ? Qtrue : Qfalse;
|
@@ -2669,7 +2832,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2669
2832
|
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
2670
2833
|
}
|
2671
2834
|
|
2672
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
2673
2835
|
/*
|
2674
2836
|
* call-seq:
|
2675
2837
|
* conn.set_error_context_visibility( context_visibility ) -> Integer
|
@@ -2689,7 +2851,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2689
2851
|
*
|
2690
2852
|
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
|
2691
2853
|
*
|
2692
|
-
* Available since PostgreSQL-9.6
|
2693
2854
|
*/
|
2694
2855
|
static VALUE
|
2695
2856
|
pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
@@ -2698,7 +2859,6 @@ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
|
2698
2859
|
PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
|
2699
2860
|
return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
|
2700
2861
|
}
|
2701
|
-
#endif
|
2702
2862
|
|
2703
2863
|
/*
|
2704
2864
|
* call-seq:
|
@@ -2718,6 +2878,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2718
2878
|
VALUE new_file;
|
2719
2879
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2720
2880
|
|
2881
|
+
rb_check_frozen(self);
|
2721
2882
|
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2722
2883
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2723
2884
|
|
@@ -2739,7 +2900,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2739
2900
|
rb_raise(rb_eArgError, "stream is not writable");
|
2740
2901
|
|
2741
2902
|
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2742
|
-
this->trace_stream
|
2903
|
+
RB_OBJ_WRITE(self, &this->trace_stream, new_file);
|
2743
2904
|
|
2744
2905
|
PQtrace(this->pgconn, new_fp);
|
2745
2906
|
return Qnil;
|
@@ -2758,7 +2919,7 @@ pgconn_untrace(VALUE self)
|
|
2758
2919
|
|
2759
2920
|
PQuntrace(this->pgconn);
|
2760
2921
|
rb_funcall(this->trace_stream, rb_intern("close"), 0);
|
2761
|
-
this->trace_stream
|
2922
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
2762
2923
|
return Qnil;
|
2763
2924
|
}
|
2764
2925
|
|
@@ -2817,13 +2978,14 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2817
2978
|
VALUE proc, old_proc;
|
2818
2979
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2819
2980
|
|
2981
|
+
rb_check_frozen(self);
|
2820
2982
|
/* If default_notice_receiver is unset, assume that the current
|
2821
2983
|
* notice receiver is the default, and save it to a global variable.
|
2822
2984
|
* This should not be a problem because the default receiver is
|
2823
2985
|
* always the same, so won't vary among connections.
|
2824
2986
|
*/
|
2825
|
-
if(default_notice_receiver == NULL)
|
2826
|
-
default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
|
2987
|
+
if(this->default_notice_receiver == NULL)
|
2988
|
+
this->default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
|
2827
2989
|
|
2828
2990
|
old_proc = this->notice_receiver;
|
2829
2991
|
if( rb_block_given_p() ) {
|
@@ -2832,10 +2994,10 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2832
2994
|
} else {
|
2833
2995
|
/* if no block is given, set back to default */
|
2834
2996
|
proc = Qnil;
|
2835
|
-
PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
|
2997
|
+
PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
|
2836
2998
|
}
|
2837
2999
|
|
2838
|
-
this->notice_receiver
|
3000
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, proc);
|
2839
3001
|
return old_proc;
|
2840
3002
|
}
|
2841
3003
|
|
@@ -2850,10 +3012,10 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2850
3012
|
VALUE self = (VALUE)arg;
|
2851
3013
|
t_pg_connection *this = pg_get_connection( self );
|
2852
3014
|
|
2853
|
-
if (this->
|
3015
|
+
if (this->notice_processor != Qnil) {
|
2854
3016
|
VALUE message_str = rb_str_new2(message);
|
2855
3017
|
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2856
|
-
rb_funcall(this->
|
3018
|
+
rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
|
2857
3019
|
}
|
2858
3020
|
return;
|
2859
3021
|
}
|
@@ -2877,25 +3039,26 @@ pgconn_set_notice_processor(VALUE self)
|
|
2877
3039
|
VALUE proc, old_proc;
|
2878
3040
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2879
3041
|
|
3042
|
+
rb_check_frozen(self);
|
2880
3043
|
/* If default_notice_processor is unset, assume that the current
|
2881
3044
|
* notice processor is the default, and save it to a global variable.
|
2882
3045
|
* This should not be a problem because the default processor is
|
2883
3046
|
* always the same, so won't vary among connections.
|
2884
3047
|
*/
|
2885
|
-
if(default_notice_processor == NULL)
|
2886
|
-
default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
|
3048
|
+
if(this->default_notice_processor == NULL)
|
3049
|
+
this->default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
|
2887
3050
|
|
2888
|
-
old_proc = this->
|
3051
|
+
old_proc = this->notice_processor;
|
2889
3052
|
if( rb_block_given_p() ) {
|
2890
3053
|
proc = rb_block_proc();
|
2891
3054
|
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
|
2892
3055
|
} else {
|
2893
3056
|
/* if no block is given, set back to default */
|
2894
3057
|
proc = Qnil;
|
2895
|
-
PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
|
3058
|
+
PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
|
2896
3059
|
}
|
2897
3060
|
|
2898
|
-
this->
|
3061
|
+
RB_OBJ_WRITE(self, &this->notice_processor, proc);
|
2899
3062
|
return old_proc;
|
2900
3063
|
}
|
2901
3064
|
|
@@ -2927,6 +3090,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2927
3090
|
{
|
2928
3091
|
PGconn *conn = pg_get_pgconn( self );
|
2929
3092
|
|
3093
|
+
rb_check_frozen(self);
|
2930
3094
|
Check_Type(str, T_STRING);
|
2931
3095
|
|
2932
3096
|
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
@@ -3095,11 +3259,13 @@ pgconn_async_get_last_result(VALUE self)
|
|
3095
3259
|
VALUE rb_pgresult = Qnil;
|
3096
3260
|
PGresult *cur, *prev;
|
3097
3261
|
|
3098
|
-
|
3262
|
+
cur = prev = NULL;
|
3099
3263
|
for(;;) {
|
3100
3264
|
int status;
|
3101
3265
|
|
3102
|
-
/*
|
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
|
+
*/
|
3103
3269
|
wait_socket_readable(self, NULL, get_result_readable);
|
3104
3270
|
|
3105
3271
|
cur = gvl_PQgetResult(conn);
|
@@ -3133,7 +3299,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
3133
3299
|
* Returns:
|
3134
3300
|
* * +nil+ when the connection is already idle
|
3135
3301
|
* * +true+ when some results have been discarded
|
3136
|
-
* * +false+ when a failure
|
3302
|
+
* * +false+ when a failure occurred and the connection was closed
|
3137
3303
|
*
|
3138
3304
|
*/
|
3139
3305
|
static VALUE
|
@@ -3420,6 +3586,21 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
3420
3586
|
return rb_pgresult;
|
3421
3587
|
}
|
3422
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
|
+
}
|
3423
3604
|
|
3424
3605
|
/*
|
3425
3606
|
* call-seq:
|
@@ -3432,16 +3613,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
3432
3613
|
static VALUE
|
3433
3614
|
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
3434
3615
|
{
|
3435
|
-
|
3436
|
-
|
3437
|
-
pgconn_discard_results( self );
|
3438
|
-
pgconn_send_describe_portal( self, portal );
|
3439
|
-
rb_pgresult = pgconn_async_get_last_result( self );
|
3440
|
-
|
3441
|
-
if ( rb_block_given_p() ) {
|
3442
|
-
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3443
|
-
}
|
3444
|
-
return rb_pgresult;
|
3616
|
+
return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_describe_portal);
|
3445
3617
|
}
|
3446
3618
|
|
3447
3619
|
|
@@ -3456,27 +3628,64 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
|
|
3456
3628
|
static VALUE
|
3457
3629
|
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
3458
3630
|
{
|
3459
|
-
|
3460
|
-
|
3461
|
-
pgconn_discard_results( self );
|
3462
|
-
pgconn_send_describe_prepared( self, stmt_name );
|
3463
|
-
rb_pgresult = pgconn_async_get_last_result( self );
|
3631
|
+
return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_describe_prepared);
|
3632
|
+
}
|
3464
3633
|
|
3465
|
-
|
3466
|
-
|
3467
|
-
|
3468
|
-
|
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);
|
3469
3656
|
}
|
3470
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
|
3471
3682
|
|
3472
|
-
#ifdef HAVE_PQSSLATTRIBUTE
|
3473
3683
|
/*
|
3474
3684
|
* call-seq:
|
3475
3685
|
* conn.ssl_in_use? -> Boolean
|
3476
3686
|
*
|
3477
3687
|
* Returns +true+ if the connection uses SSL/TLS, +false+ if not.
|
3478
3688
|
*
|
3479
|
-
* Available since PostgreSQL-9.5
|
3480
3689
|
*/
|
3481
3690
|
static VALUE
|
3482
3691
|
pgconn_ssl_in_use(VALUE self)
|
@@ -3510,7 +3719,6 @@ pgconn_ssl_in_use(VALUE self)
|
|
3510
3719
|
*
|
3511
3720
|
* See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
|
3512
3721
|
*
|
3513
|
-
* Available since PostgreSQL-9.5
|
3514
3722
|
*/
|
3515
3723
|
static VALUE
|
3516
3724
|
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
@@ -3529,7 +3737,6 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
|
3529
3737
|
*
|
3530
3738
|
* See also #ssl_attribute
|
3531
3739
|
*
|
3532
|
-
* Available since PostgreSQL-9.5
|
3533
3740
|
*/
|
3534
3741
|
static VALUE
|
3535
3742
|
pgconn_ssl_attribute_names(VALUE self)
|
@@ -3545,8 +3752,6 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
3545
3752
|
}
|
3546
3753
|
|
3547
3754
|
|
3548
|
-
#endif
|
3549
|
-
|
3550
3755
|
|
3551
3756
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
3552
3757
|
/*
|
@@ -3581,6 +3786,8 @@ pgconn_pipeline_status(VALUE self)
|
|
3581
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.
|
3582
3787
|
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
3583
3788
|
*
|
3789
|
+
* See the {PostgreSQL documentation}[https://www.postgresql.org/docs/17/libpq-pipeline-mode.html#LIBPQ-PIPELINE-MODE].
|
3790
|
+
*
|
3584
3791
|
* Available since PostgreSQL-14
|
3585
3792
|
*/
|
3586
3793
|
static VALUE
|
@@ -3619,29 +3826,55 @@ pgconn_exit_pipeline_mode(VALUE self)
|
|
3619
3826
|
|
3620
3827
|
/*
|
3621
3828
|
* call-seq:
|
3622
|
-
* conn.
|
3829
|
+
* conn.sync_pipeline_sync -> nil
|
3830
|
+
*
|
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.
|
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
|
3623
3853
|
*
|
3624
|
-
* Marks a synchronization point in a pipeline by sending a sync message
|
3625
|
-
* This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
|
3854
|
+
* Marks a synchronization point in a pipeline by sending a sync message without flushing the send buffer.
|
3626
3855
|
*
|
3856
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point.
|
3627
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.
|
3628
3859
|
*
|
3629
|
-
* Available since PostgreSQL-
|
3860
|
+
* Available since PostgreSQL-17
|
3630
3861
|
*/
|
3631
3862
|
static VALUE
|
3632
|
-
|
3863
|
+
pgconn_send_pipeline_sync(VALUE self)
|
3633
3864
|
{
|
3634
3865
|
PGconn *conn = pg_get_pgconn(self);
|
3635
|
-
int res =
|
3866
|
+
int res = gvl_PQsendPipelineSync(conn);
|
3636
3867
|
if( res != 1 )
|
3637
3868
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3638
3869
|
|
3639
3870
|
return Qnil;
|
3640
3871
|
}
|
3872
|
+
#endif
|
3873
|
+
|
3641
3874
|
|
3642
3875
|
/*
|
3643
3876
|
* call-seq:
|
3644
|
-
* conn.
|
3877
|
+
* conn.send_flush_request -> nil
|
3645
3878
|
*
|
3646
3879
|
* Sends a request for the server to flush its output buffer.
|
3647
3880
|
*
|
@@ -4058,6 +4291,7 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
4058
4291
|
static VALUE
|
4059
4292
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
4060
4293
|
{
|
4294
|
+
rb_check_frozen(self);
|
4061
4295
|
if (NIL_P(enc)) {
|
4062
4296
|
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
4063
4297
|
return enc;
|
@@ -4112,6 +4346,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4112
4346
|
{
|
4113
4347
|
VALUE query_format, query;
|
4114
4348
|
|
4349
|
+
rb_check_frozen(self);
|
4115
4350
|
Check_Type(encname, T_STRING);
|
4116
4351
|
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4117
4352
|
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
@@ -4161,15 +4396,23 @@ static VALUE
|
|
4161
4396
|
pgconn_set_default_encoding( VALUE self )
|
4162
4397
|
{
|
4163
4398
|
PGconn *conn = pg_get_pgconn( self );
|
4164
|
-
rb_encoding *
|
4165
|
-
|
4166
|
-
|
4167
|
-
if ((
|
4168
|
-
|
4169
|
-
|
4170
|
-
|
4171
|
-
|
4172
|
-
|
4399
|
+
rb_encoding *rb_enc;
|
4400
|
+
|
4401
|
+
rb_check_frozen(self);
|
4402
|
+
if (( rb_enc = rb_default_internal_encoding() )) {
|
4403
|
+
rb_encoding * conn_encoding = pg_conn_enc_get( conn );
|
4404
|
+
|
4405
|
+
/* Don't set the server encoding, if it's unnecessary.
|
4406
|
+
* This is important for connection proxies, who disallow configuration settings.
|
4407
|
+
*/
|
4408
|
+
if ( conn_encoding != rb_enc ) {
|
4409
|
+
const char *encname = pg_get_rb_encoding_as_pg_encoding( rb_enc );
|
4410
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
4411
|
+
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
4412
|
+
encname, PQerrorMessage(conn) );
|
4413
|
+
}
|
4414
|
+
pgconn_set_internal_encoding_index( self );
|
4415
|
+
return rb_enc_from_encoding( rb_enc );
|
4173
4416
|
} else {
|
4174
4417
|
pgconn_set_internal_encoding_index( self );
|
4175
4418
|
return Qnil;
|
@@ -4193,10 +4436,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
4193
4436
|
t_typemap *tm;
|
4194
4437
|
UNUSED(tm);
|
4195
4438
|
|
4439
|
+
rb_check_frozen(self);
|
4196
4440
|
/* Check type of method param */
|
4197
4441
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4198
4442
|
|
4199
|
-
this->type_map_for_queries
|
4443
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
|
4200
4444
|
|
4201
4445
|
return typemap;
|
4202
4446
|
}
|
@@ -4233,8 +4477,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
4233
4477
|
t_typemap *tm;
|
4234
4478
|
UNUSED(tm);
|
4235
4479
|
|
4480
|
+
rb_check_frozen(self);
|
4236
4481
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4237
|
-
this->type_map_for_results
|
4482
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
|
4238
4483
|
|
4239
4484
|
return typemap;
|
4240
4485
|
}
|
@@ -4272,13 +4517,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4272
4517
|
{
|
4273
4518
|
t_pg_connection *this = pg_get_connection( self );
|
4274
4519
|
|
4520
|
+
rb_check_frozen(self);
|
4275
4521
|
if( encoder != Qnil ){
|
4276
4522
|
t_pg_coder *co;
|
4277
4523
|
UNUSED(co);
|
4278
4524
|
/* Check argument type */
|
4279
4525
|
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4280
4526
|
}
|
4281
|
-
this->encoder_for_put_copy_data
|
4527
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
|
4282
4528
|
|
4283
4529
|
return encoder;
|
4284
4530
|
}
|
@@ -4320,13 +4566,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4320
4566
|
{
|
4321
4567
|
t_pg_connection *this = pg_get_connection( self );
|
4322
4568
|
|
4569
|
+
rb_check_frozen(self);
|
4323
4570
|
if( decoder != Qnil ){
|
4324
4571
|
t_pg_coder *co;
|
4325
4572
|
UNUSED(co);
|
4326
4573
|
/* Check argument type */
|
4327
4574
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4328
4575
|
}
|
4329
|
-
this->decoder_for_get_copy_data
|
4576
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
|
4330
4577
|
|
4331
4578
|
return decoder;
|
4332
4579
|
}
|
@@ -4372,6 +4619,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
4372
4619
|
{
|
4373
4620
|
t_pg_connection *this = pg_get_connection( self );
|
4374
4621
|
|
4622
|
+
rb_check_frozen(self);
|
4375
4623
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4376
4624
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4377
4625
|
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
@@ -4445,6 +4693,7 @@ init_pg_connection(void)
|
|
4445
4693
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
4446
4694
|
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
4447
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);
|
4448
4697
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4449
4698
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
4450
4699
|
|
@@ -4469,7 +4718,9 @@ init_pg_connection(void)
|
|
4469
4718
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
4470
4719
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
4471
4720
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4721
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
4472
4722
|
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
4723
|
+
#endif
|
4473
4724
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
4474
4725
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
4475
4726
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
@@ -4481,6 +4732,10 @@ init_pg_connection(void)
|
|
4481
4732
|
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
4482
4733
|
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
4483
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
|
4484
4739
|
|
4485
4740
|
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
4486
4741
|
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
@@ -4488,6 +4743,10 @@ init_pg_connection(void)
|
|
4488
4743
|
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
|
4489
4744
|
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
|
4490
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
|
4491
4750
|
|
4492
4751
|
rb_define_alias(rb_cPGconn, "async_exec", "exec");
|
4493
4752
|
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
@@ -4496,6 +4755,10 @@ init_pg_connection(void)
|
|
4496
4755
|
rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
|
4497
4756
|
rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
|
4498
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
|
4499
4762
|
|
4500
4763
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
4501
4764
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
@@ -4505,6 +4768,9 @@ init_pg_connection(void)
|
|
4505
4768
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4506
4769
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4507
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
|
4508
4774
|
|
4509
4775
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
4510
4776
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
@@ -4524,7 +4790,9 @@ init_pg_connection(void)
|
|
4524
4790
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
4525
4791
|
|
4526
4792
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4793
|
+
#ifndef HAVE_PQSETCHUNKEDROWSMODE
|
4527
4794
|
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
4795
|
+
#endif
|
4528
4796
|
|
4529
4797
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
4530
4798
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
@@ -4536,9 +4804,7 @@ init_pg_connection(void)
|
|
4536
4804
|
|
4537
4805
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
4538
4806
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4539
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
4540
4807
|
rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
|
4541
|
-
#endif
|
4542
4808
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
4543
4809
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4544
4810
|
|
@@ -4560,22 +4826,21 @@ init_pg_connection(void)
|
|
4560
4826
|
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
4561
4827
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
4562
4828
|
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
4563
|
-
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4564
4829
|
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
4565
|
-
#endif
|
4566
4830
|
|
4567
|
-
#ifdef HAVE_PQSSLATTRIBUTE
|
4568
4831
|
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
4569
4832
|
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
4570
4833
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4571
|
-
#endif
|
4572
4834
|
|
4573
4835
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
4574
4836
|
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
4575
4837
|
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
4576
4838
|
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
4577
|
-
rb_define_method(rb_cPGconn, "
|
4839
|
+
rb_define_method(rb_cPGconn, "sync_pipeline_sync", pgconn_sync_pipeline_sync, 0);
|
4578
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
|
4579
4844
|
#endif
|
4580
4845
|
|
4581
4846
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|