pg 0.18.0 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/BSDL +2 -2
- data/ChangeLog +1221 -4
- data/History.rdoc +200 -0
- data/Manifest.txt +5 -18
- data/README-Windows.rdoc +15 -26
- data/README.rdoc +27 -10
- data/Rakefile +33 -24
- data/Rakefile.cross +57 -39
- data/ext/errorcodes.def +37 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +16 -1
- data/ext/extconf.rb +29 -35
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +27 -39
- data/ext/pg.c +27 -53
- data/ext/pg.h +66 -83
- data/ext/pg_binary_decoder.c +75 -6
- data/ext/pg_binary_encoder.c +14 -12
- data/ext/pg_coder.c +83 -13
- data/ext/pg_connection.c +627 -351
- data/ext/pg_copy_coder.c +44 -9
- data/ext/pg_result.c +364 -134
- data/ext/pg_text_decoder.c +605 -46
- data/ext/pg_text_encoder.c +95 -76
- data/ext/pg_tuple.c +541 -0
- data/ext/pg_type_map.c +20 -13
- data/ext/pg_type_map_by_column.c +7 -7
- data/ext/pg_type_map_by_mri_type.c +2 -2
- data/ext/pg_type_map_in_ruby.c +4 -7
- data/ext/util.c +7 -7
- data/ext/util.h +3 -3
- data/lib/pg/basic_type_mapping.rb +105 -45
- data/lib/pg/binary_decoder.rb +22 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +109 -39
- data/lib/pg/constants.rb +1 -1
- data/lib/pg/exceptions.rb +1 -1
- data/lib/pg/result.rb +11 -6
- data/lib/pg/text_decoder.rb +25 -20
- data/lib/pg/text_encoder.rb +43 -1
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +1 -1
- data/lib/pg.rb +21 -11
- data/spec/helpers.rb +50 -25
- data/spec/pg/basic_type_mapping_spec.rb +287 -30
- data/spec/pg/connection_spec.rb +695 -282
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +59 -17
- data/spec/pg/tuple_spec.rb +280 -0
- data/spec/pg/type_map_by_class_spec.rb +3 -3
- data/spec/pg/type_map_by_column_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +2 -2
- data/spec/pg/type_map_by_oid_spec.rb +1 -1
- data/spec/pg/type_map_in_ruby_spec.rb +1 -1
- data/spec/pg/type_map_spec.rb +1 -1
- data/spec/pg/type_spec.rb +319 -35
- data/spec/pg_spec.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +68 -68
- metadata.gz.sig +0 -0
- data/sample/array_insert.rb +0 -20
- data/sample/async_api.rb +0 -106
- data/sample/async_copyto.rb +0 -39
- data/sample/async_mixed.rb +0 -56
- data/sample/check_conn.rb +0 -21
- data/sample/copyfrom.rb +0 -81
- data/sample/copyto.rb +0 -19
- data/sample/cursor.rb +0 -21
- data/sample/disk_usage_report.rb +0 -186
- data/sample/issue-119.rb +0 -94
- data/sample/losample.rb +0 -69
- data/sample/minimal-testcase.rb +0 -17
- data/sample/notify_wait.rb +0 -72
- data/sample/pg_statistics.rb +0 -294
- data/sample/replication_monitor.rb +0 -231
- data/sample/test_binary_values.rb +0 -33
- data/sample/wal_shipper.rb +0 -434
- data/sample/warehouse_partitions.rb +0 -320
data/ext/pg_connection.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_connection.c - PG::Connection class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -18,19 +18,8 @@ static PQnoticeReceiver default_notice_receiver = NULL;
|
|
18
18
|
static PQnoticeProcessor default_notice_processor = NULL;
|
19
19
|
|
20
20
|
static VALUE pgconn_finish( VALUE );
|
21
|
-
#ifdef M17N_SUPPORTED
|
22
21
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
23
22
|
void pgconn_set_internal_encoding_index( VALUE );
|
24
|
-
#endif
|
25
|
-
|
26
|
-
#ifndef HAVE_RB_THREAD_FD_SELECT
|
27
|
-
#define rb_fdset_t fd_set
|
28
|
-
#define rb_fd_init(f)
|
29
|
-
#define rb_fd_zero(f) FD_ZERO(f)
|
30
|
-
#define rb_fd_set(n, f) FD_SET(n, f)
|
31
|
-
#define rb_fd_term(f)
|
32
|
-
#define rb_thread_fd_select rb_thread_select
|
33
|
-
#endif
|
34
23
|
|
35
24
|
/*
|
36
25
|
* Global functions
|
@@ -52,7 +41,7 @@ pg_get_connection( VALUE self )
|
|
52
41
|
* Fetch the PG::Connection object data pointer and check it's
|
53
42
|
* PGconn data pointer for sanity.
|
54
43
|
*/
|
55
|
-
t_pg_connection *
|
44
|
+
static t_pg_connection *
|
56
45
|
pg_get_connection_safe( VALUE self )
|
57
46
|
{
|
58
47
|
t_pg_connection *this;
|
@@ -88,16 +77,15 @@ pg_get_pgconn( VALUE self )
|
|
88
77
|
/*
|
89
78
|
* Close the associated socket IO object if there is one.
|
90
79
|
*/
|
91
|
-
void
|
80
|
+
static void
|
92
81
|
pgconn_close_socket_io( VALUE self )
|
93
82
|
{
|
94
83
|
t_pg_connection *this = pg_get_connection( self );
|
95
84
|
VALUE socket_io = this->socket_io;
|
96
85
|
|
97
86
|
if ( RTEST(socket_io) ) {
|
98
|
-
#if defined(_WIN32)
|
99
|
-
|
100
|
-
if( rb_w32_unwrap_io_handle(ruby_sd) ){
|
87
|
+
#if defined(_WIN32)
|
88
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
101
89
|
rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
|
102
90
|
}
|
103
91
|
#endif
|
@@ -141,6 +129,16 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
|
|
141
129
|
return ary;
|
142
130
|
}
|
143
131
|
|
132
|
+
static const char *pg_cstr_enc(VALUE str, int enc_idx){
|
133
|
+
const char *ptr = StringValueCStr(str);
|
134
|
+
if( ENCODING_GET(str) == enc_idx ){
|
135
|
+
return ptr;
|
136
|
+
} else {
|
137
|
+
str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
|
138
|
+
return StringValueCStr(str);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
144
142
|
|
145
143
|
/*
|
146
144
|
* GC Mark function
|
@@ -166,6 +164,10 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
166
164
|
static void
|
167
165
|
pgconn_gc_free( t_pg_connection *this )
|
168
166
|
{
|
167
|
+
#if defined(_WIN32)
|
168
|
+
if ( RTEST(this->socket_io) )
|
169
|
+
rb_w32_unwrap_io_handle( this->ruby_sd );
|
170
|
+
#endif
|
169
171
|
if (this->pgconn != NULL)
|
170
172
|
PQfinish( this->pgconn );
|
171
173
|
|
@@ -199,6 +201,7 @@ pgconn_s_allocate( VALUE klass )
|
|
199
201
|
this->decoder_for_get_copy_data = Qnil;
|
200
202
|
this->trace_stream = Qnil;
|
201
203
|
this->external_encoding = Qnil;
|
204
|
+
this->guess_result_memsize = 1;
|
202
205
|
|
203
206
|
return self;
|
204
207
|
}
|
@@ -281,9 +284,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
281
284
|
rb_exc_raise(error);
|
282
285
|
}
|
283
286
|
|
284
|
-
#ifdef M17N_SUPPORTED
|
285
287
|
pgconn_set_default_encoding( self );
|
286
|
-
#endif
|
287
288
|
|
288
289
|
if (rb_block_given_p()) {
|
289
290
|
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
@@ -339,12 +340,11 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
339
340
|
return rb_conn;
|
340
341
|
}
|
341
342
|
|
342
|
-
#ifdef HAVE_PQPING
|
343
343
|
/*
|
344
344
|
* call-seq:
|
345
|
-
* PG::Connection.ping(connection_hash) ->
|
346
|
-
* PG::Connection.ping(connection_string) ->
|
347
|
-
* PG::Connection.ping(host, port, options, tty, dbname, login, password) ->
|
345
|
+
* PG::Connection.ping(connection_hash) -> Integer
|
346
|
+
* PG::Connection.ping(connection_string) -> Integer
|
347
|
+
* PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
|
348
348
|
*
|
349
349
|
* Check server status.
|
350
350
|
*
|
@@ -357,6 +357,8 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
357
357
|
* could not establish connection
|
358
358
|
* [+PQPING_NO_ATTEMPT+]
|
359
359
|
* connection not attempted (bad params)
|
360
|
+
*
|
361
|
+
* Available since PostgreSQL-9.1
|
360
362
|
*/
|
361
363
|
static VALUE
|
362
364
|
pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
|
@@ -369,11 +371,10 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
|
|
369
371
|
|
370
372
|
return INT2FIX((int)ping);
|
371
373
|
}
|
372
|
-
#endif
|
373
374
|
|
374
375
|
|
375
376
|
/*
|
376
|
-
* Document-method: conndefaults
|
377
|
+
* Document-method: PG::Connection.conndefaults
|
377
378
|
*
|
378
379
|
* call-seq:
|
379
380
|
* PG::Connection.conndefaults() -> Array
|
@@ -408,16 +409,65 @@ pgconn_s_conndefaults(VALUE self)
|
|
408
409
|
}
|
409
410
|
|
410
411
|
|
412
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
411
413
|
/*
|
412
414
|
* call-seq:
|
413
|
-
*
|
415
|
+
* conn.encrypt_password( password, username, algorithm=nil ) -> String
|
414
416
|
*
|
415
|
-
* This function is intended to be used by client applications that
|
416
|
-
* send
|
417
|
-
*
|
418
|
-
*
|
417
|
+
* This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
|
418
|
+
* It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on.
|
419
|
+
* Instead, use this function to convert the password to encrypted form before it is sent.
|
420
|
+
*
|
421
|
+
* The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
|
422
|
+
* +algorithm+ specifies the encryption algorithm to use to encrypt the password.
|
423
|
+
* Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions).
|
424
|
+
* Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
|
425
|
+
* If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
|
426
|
+
* That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
|
427
|
+
* If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm.
|
419
428
|
*
|
420
429
|
* Return value is the encrypted password.
|
430
|
+
* The caller can assume the string doesn't contain any special characters that would require escaping.
|
431
|
+
*
|
432
|
+
* Available since PostgreSQL-10
|
433
|
+
*/
|
434
|
+
static VALUE
|
435
|
+
pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
|
436
|
+
{
|
437
|
+
char *encrypted = NULL;
|
438
|
+
VALUE rval = Qnil;
|
439
|
+
VALUE password, username, algorithm;
|
440
|
+
PGconn *conn = pg_get_pgconn(self);
|
441
|
+
|
442
|
+
rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
|
443
|
+
|
444
|
+
Check_Type(password, T_STRING);
|
445
|
+
Check_Type(username, T_STRING);
|
446
|
+
|
447
|
+
encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
|
448
|
+
if ( encrypted ) {
|
449
|
+
rval = rb_str_new2( encrypted );
|
450
|
+
PQfreemem( encrypted );
|
451
|
+
|
452
|
+
OBJ_INFECT( rval, password );
|
453
|
+
OBJ_INFECT( rval, username );
|
454
|
+
OBJ_INFECT( rval, algorithm );
|
455
|
+
} else {
|
456
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
457
|
+
}
|
458
|
+
|
459
|
+
return rval;
|
460
|
+
}
|
461
|
+
#endif
|
462
|
+
|
463
|
+
|
464
|
+
/*
|
465
|
+
* call-seq:
|
466
|
+
* PG::Connection.encrypt_password( password, username ) -> String
|
467
|
+
*
|
468
|
+
* This is an older, deprecated version of #encrypt_password.
|
469
|
+
* The difference is that this function always uses +md5+ as the encryption algorithm.
|
470
|
+
*
|
421
471
|
*/
|
422
472
|
static VALUE
|
423
473
|
pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
@@ -447,7 +497,7 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
447
497
|
|
448
498
|
/*
|
449
499
|
* call-seq:
|
450
|
-
* conn.connect_poll() ->
|
500
|
+
* conn.connect_poll() -> Integer
|
451
501
|
*
|
452
502
|
* Returns one of:
|
453
503
|
* [+PGRES_POLLING_READING+]
|
@@ -556,7 +606,7 @@ pgconn_reset_start(VALUE self)
|
|
556
606
|
|
557
607
|
/*
|
558
608
|
* call-seq:
|
559
|
-
* conn.reset_poll ->
|
609
|
+
* conn.reset_poll -> Integer
|
560
610
|
*
|
561
611
|
* Checks the status of a connection reset operation.
|
562
612
|
* See #connect_start and #connect_poll for
|
@@ -603,7 +653,7 @@ pgconn_user(VALUE self)
|
|
603
653
|
* call-seq:
|
604
654
|
* conn.pass()
|
605
655
|
*
|
606
|
-
* Returns the authenticated
|
656
|
+
* Returns the authenticated password.
|
607
657
|
*/
|
608
658
|
static VALUE
|
609
659
|
pgconn_pass(VALUE self)
|
@@ -627,22 +677,6 @@ pgconn_host(VALUE self)
|
|
627
677
|
return rb_tainted_str_new2(host);
|
628
678
|
}
|
629
679
|
|
630
|
-
#ifdef HAVE_PQHOSTADDR
|
631
|
-
/*
|
632
|
-
* call-seq:
|
633
|
-
* conn.hostaddr()
|
634
|
-
*
|
635
|
-
* Returns the server numeric IP address of the connection.
|
636
|
-
*/
|
637
|
-
static VALUE
|
638
|
-
pgconn_hostaddr(VALUE self)
|
639
|
-
{
|
640
|
-
char *hostaddr = PQhostaddr(pg_get_pgconn(self));
|
641
|
-
if (!hostaddr) return Qnil;
|
642
|
-
return rb_tainted_str_new2(hostaddr);
|
643
|
-
}
|
644
|
-
#endif
|
645
|
-
|
646
680
|
/*
|
647
681
|
* call-seq:
|
648
682
|
* conn.port()
|
@@ -692,6 +726,7 @@ pgconn_options(VALUE self)
|
|
692
726
|
*
|
693
727
|
* Returns the connection options used by a live connection.
|
694
728
|
*
|
729
|
+
* Available since PostgreSQL-9.3
|
695
730
|
*/
|
696
731
|
static VALUE
|
697
732
|
pgconn_conninfo( VALUE self )
|
@@ -811,7 +846,9 @@ pgconn_error_message(VALUE self)
|
|
811
846
|
|
812
847
|
/*
|
813
848
|
* call-seq:
|
814
|
-
* conn.socket() ->
|
849
|
+
* conn.socket() -> Integer
|
850
|
+
*
|
851
|
+
* This method is deprecated. Please use the more portable method #socket_io .
|
815
852
|
*
|
816
853
|
* Returns the socket's file descriptor for this connection.
|
817
854
|
* <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
|
@@ -821,7 +858,7 @@ pgconn_error_message(VALUE self)
|
|
821
858
|
* creates an IO that's associated with the connection object itself,
|
822
859
|
* and so won't go out of scope until the connection does.
|
823
860
|
*
|
824
|
-
* *Note:* On Windows the file descriptor is not
|
861
|
+
* *Note:* On Windows the file descriptor is not usable,
|
825
862
|
* since it can not be used to build a Ruby IO object.
|
826
863
|
*/
|
827
864
|
static VALUE
|
@@ -833,22 +870,17 @@ pgconn_socket(VALUE self)
|
|
833
870
|
return INT2NUM(sd);
|
834
871
|
}
|
835
872
|
|
836
|
-
|
837
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
838
|
-
|
839
873
|
/*
|
840
874
|
* call-seq:
|
841
875
|
* conn.socket_io() -> IO
|
842
876
|
*
|
843
|
-
* Fetch a
|
877
|
+
* Fetch a memorized IO object created from the Connection's underlying socket.
|
844
878
|
* This object can be used for IO.select to wait for events while running
|
845
879
|
* asynchronous API calls.
|
846
880
|
*
|
847
881
|
* Using this instead of #socket avoids the problem of the underlying connection
|
848
882
|
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
849
|
-
* goes out of scope.
|
850
|
-
*
|
851
|
-
* This method can also be used on Windows but requires Ruby-2.0+.
|
883
|
+
* goes out of scope. In contrast to #socket, it also works on Windows.
|
852
884
|
*/
|
853
885
|
static VALUE
|
854
886
|
pgconn_socket_io(VALUE self)
|
@@ -865,16 +897,15 @@ pgconn_socket_io(VALUE self)
|
|
865
897
|
|
866
898
|
#ifdef _WIN32
|
867
899
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
900
|
+
this->ruby_sd = ruby_sd;
|
868
901
|
#else
|
869
902
|
ruby_sd = sd;
|
870
903
|
#endif
|
871
904
|
|
872
905
|
socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
|
873
906
|
|
874
|
-
/* Disable autoclose feature
|
875
|
-
|
876
|
-
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
877
|
-
}
|
907
|
+
/* Disable autoclose feature */
|
908
|
+
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
878
909
|
|
879
910
|
this->socket_io = socket_io;
|
880
911
|
}
|
@@ -882,11 +913,9 @@ pgconn_socket_io(VALUE self)
|
|
882
913
|
return socket_io;
|
883
914
|
}
|
884
915
|
|
885
|
-
#endif
|
886
|
-
|
887
916
|
/*
|
888
917
|
* call-seq:
|
889
|
-
* conn.backend_pid() ->
|
918
|
+
* conn.backend_pid() -> Integer
|
890
919
|
*
|
891
920
|
* Returns the process ID of the backend server
|
892
921
|
* process for this connection.
|
@@ -936,7 +965,7 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
936
965
|
* conn.exec(sql) {|pg_result| block }
|
937
966
|
*
|
938
967
|
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
939
|
-
*
|
968
|
+
* On success, it returns a PG::Result instance with all result rows and columns.
|
940
969
|
* On failure, it raises a PG::Error.
|
941
970
|
*
|
942
971
|
* For backward compatibility, if you pass more than one parameter to this method,
|
@@ -947,9 +976,9 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
947
976
|
* and the PG::Result object will automatically be cleared when the block terminates.
|
948
977
|
* In this instance, <code>conn.exec</code> returns the value of the block.
|
949
978
|
*
|
950
|
-
* #
|
979
|
+
* #sync_exec is implemented on the synchronous command processing API of libpq, whereas
|
951
980
|
* #async_exec is implemented on the asynchronous API.
|
952
|
-
* #
|
981
|
+
* #sync_exec is somewhat faster that #async_exec, but blocks any signals to be processed until
|
953
982
|
* the query is finished. This is most notably visible by a delayed reaction to Control+C.
|
954
983
|
* Both methods ensure that other threads can process while waiting for the server to
|
955
984
|
* complete the request.
|
@@ -961,11 +990,11 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
961
990
|
PGresult *result = NULL;
|
962
991
|
VALUE rb_pgresult;
|
963
992
|
|
964
|
-
/* If called with no parameters, use PQexec */
|
965
|
-
if ( argc == 1 ) {
|
966
|
-
|
993
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
994
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
995
|
+
VALUE query_str = argv[0];
|
967
996
|
|
968
|
-
result = gvl_PQexec(conn,
|
997
|
+
result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
|
969
998
|
rb_pgresult = pg_new_result(result, self);
|
970
999
|
pg_result_check(rb_pgresult);
|
971
1000
|
if (rb_block_given_p()) {
|
@@ -973,11 +1002,10 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
973
1002
|
}
|
974
1003
|
return rb_pgresult;
|
975
1004
|
}
|
1005
|
+
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
976
1006
|
|
977
1007
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
978
|
-
|
979
|
-
return pgconn_exec_params( argc, argv, self );
|
980
|
-
}
|
1008
|
+
return pgconn_exec_params( argc, argv, self );
|
981
1009
|
|
982
1010
|
}
|
983
1011
|
|
@@ -994,6 +1022,10 @@ struct query_params_data {
|
|
994
1022
|
* Filled by caller
|
995
1023
|
*/
|
996
1024
|
|
1025
|
+
/* The character encoding index of the connection. Any strings
|
1026
|
+
* given as query parameters are converted to this encoding.
|
1027
|
+
*/
|
1028
|
+
int enc_idx;
|
997
1029
|
/* Is the query function to execute one with types array? */
|
998
1030
|
int with_types;
|
999
1031
|
/* Array of query params from user space */
|
@@ -1154,7 +1186,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1154
1186
|
VALUE intermediate;
|
1155
1187
|
|
1156
1188
|
/* 1st pass for retiving the required memory space */
|
1157
|
-
int len = enc_func(conv, param_value, NULL, &intermediate);
|
1189
|
+
int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
|
1158
1190
|
|
1159
1191
|
if( len == -1 ){
|
1160
1192
|
/* The intermediate value is a String that can be used directly. */
|
@@ -1178,7 +1210,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1178
1210
|
}
|
1179
1211
|
|
1180
1212
|
/* 2nd pass for writing the data to prepared buffer */
|
1181
|
-
len = enc_func(conv, param_value, typecast_buf, &intermediate);
|
1213
|
+
len = enc_func(conv, param_value, typecast_buf, &intermediate, paramsData->enc_idx);
|
1182
1214
|
paramsData->values[i] = typecast_buf;
|
1183
1215
|
if( paramsData->formats[i] == 0 ){
|
1184
1216
|
/* text format strings must be zero terminated and lengths are ignored */
|
@@ -1236,8 +1268,8 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1236
1268
|
* Each element of the +params+ array may be either:
|
1237
1269
|
* a hash of the form:
|
1238
1270
|
* {:value => String (value of bind parameter)
|
1239
|
-
* :type =>
|
1240
|
-
* :format =>
|
1271
|
+
* :type => Integer (oid of type of bind parameter)
|
1272
|
+
* :format => Integer (0 for text, 1 for binary)
|
1241
1273
|
* }
|
1242
1274
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1243
1275
|
* { :value => <string value>, :type => 0, :format => 0 }
|
@@ -1256,7 +1288,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1256
1288
|
* for binary.
|
1257
1289
|
*
|
1258
1290
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1259
|
-
* This will type cast the params
|
1291
|
+
* This will type cast the params from various Ruby types before transmission
|
1260
1292
|
* based on the encoders defined by the type map. When a type encoder is used
|
1261
1293
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1262
1294
|
* instead out of the hash form described above.
|
@@ -1274,16 +1306,18 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1274
1306
|
VALUE command, in_res_fmt;
|
1275
1307
|
int nParams;
|
1276
1308
|
int resultFormat;
|
1277
|
-
struct query_params_data paramsData;
|
1309
|
+
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1278
1310
|
|
1311
|
+
/* For compatibility we accept 1 to 4 parameters */
|
1279
1312
|
rb_scan_args(argc, argv, "13", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1280
1313
|
paramsData.with_types = 1;
|
1281
1314
|
|
1282
1315
|
/*
|
1283
|
-
*
|
1284
|
-
*
|
1316
|
+
* For backward compatibility no or +nil+ for the second parameter
|
1317
|
+
* is passed to #exec
|
1285
1318
|
*/
|
1286
1319
|
if ( NIL_P(paramsData.params) ) {
|
1320
|
+
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
1287
1321
|
return pgconn_exec( 1, argv, self );
|
1288
1322
|
}
|
1289
1323
|
pgconn_query_assign_typemap( self, ¶msData );
|
@@ -1291,7 +1325,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1291
1325
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1292
1326
|
nParams = alloc_query_params( ¶msData );
|
1293
1327
|
|
1294
|
-
result = gvl_PQexecParams(conn,
|
1328
|
+
result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
|
1295
1329
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
1296
1330
|
|
1297
1331
|
free_query_params( ¶msData );
|
@@ -1337,10 +1371,13 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1337
1371
|
int i = 0;
|
1338
1372
|
int nParams = 0;
|
1339
1373
|
Oid *paramTypes = NULL;
|
1374
|
+
const char *name_cstr;
|
1375
|
+
const char *command_cstr;
|
1376
|
+
int enc_idx = ENCODING_GET(self);
|
1340
1377
|
|
1341
1378
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1342
|
-
|
1343
|
-
|
1379
|
+
name_cstr = pg_cstr_enc(name, enc_idx);
|
1380
|
+
command_cstr = pg_cstr_enc(command, enc_idx);
|
1344
1381
|
|
1345
1382
|
if(! NIL_P(in_paramtypes)) {
|
1346
1383
|
Check_Type(in_paramtypes, T_ARRAY);
|
@@ -1354,8 +1391,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1354
1391
|
paramTypes[i] = NUM2UINT(param);
|
1355
1392
|
}
|
1356
1393
|
}
|
1357
|
-
result = gvl_PQprepare(conn,
|
1358
|
-
nParams, paramTypes);
|
1394
|
+
result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
|
1359
1395
|
|
1360
1396
|
xfree(paramTypes);
|
1361
1397
|
|
@@ -1377,7 +1413,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1377
1413
|
* SQL query. Each element of the +params+ array may be either:
|
1378
1414
|
* a hash of the form:
|
1379
1415
|
* {:value => String (value of bind parameter)
|
1380
|
-
* :format =>
|
1416
|
+
* :format => Integer (0 for text, 1 for binary)
|
1381
1417
|
* }
|
1382
1418
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1383
1419
|
* { :value => <string value>, :format => 0 }
|
@@ -1390,7 +1426,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1390
1426
|
* for binary.
|
1391
1427
|
*
|
1392
1428
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1393
|
-
* This will type cast the params
|
1429
|
+
* This will type cast the params from various Ruby types before transmission
|
1394
1430
|
* based on the encoders defined by the type map. When a type encoder is used
|
1395
1431
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1396
1432
|
* instead out of the hash form described above.
|
@@ -1408,11 +1444,10 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1408
1444
|
VALUE name, in_res_fmt;
|
1409
1445
|
int nParams;
|
1410
1446
|
int resultFormat;
|
1411
|
-
struct query_params_data paramsData;
|
1447
|
+
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1412
1448
|
|
1413
1449
|
rb_scan_args(argc, argv, "13", &name, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1414
1450
|
paramsData.with_types = 0;
|
1415
|
-
Check_Type(name, T_STRING);
|
1416
1451
|
|
1417
1452
|
if(NIL_P(paramsData.params)) {
|
1418
1453
|
paramsData.params = rb_ary_new2(0);
|
@@ -1422,7 +1457,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1422
1457
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1423
1458
|
nParams = alloc_query_params( ¶msData );
|
1424
1459
|
|
1425
|
-
result = gvl_PQexecPrepared(conn,
|
1460
|
+
result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
|
1426
1461
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
1427
1462
|
resultFormat);
|
1428
1463
|
|
@@ -1450,13 +1485,12 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1450
1485
|
PGresult *result;
|
1451
1486
|
VALUE rb_pgresult;
|
1452
1487
|
PGconn *conn = pg_get_pgconn(self);
|
1453
|
-
char *stmt;
|
1454
|
-
if(stmt_name
|
1488
|
+
const char *stmt;
|
1489
|
+
if(NIL_P(stmt_name)) {
|
1455
1490
|
stmt = NULL;
|
1456
1491
|
}
|
1457
1492
|
else {
|
1458
|
-
|
1459
|
-
stmt = StringValueCStr(stmt_name);
|
1493
|
+
stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
|
1460
1494
|
}
|
1461
1495
|
result = gvl_PQdescribePrepared(conn, stmt);
|
1462
1496
|
rb_pgresult = pg_new_result(result, self);
|
@@ -1478,13 +1512,12 @@ pgconn_describe_portal(self, stmt_name)
|
|
1478
1512
|
PGresult *result;
|
1479
1513
|
VALUE rb_pgresult;
|
1480
1514
|
PGconn *conn = pg_get_pgconn(self);
|
1481
|
-
char *stmt;
|
1482
|
-
if(stmt_name
|
1515
|
+
const char *stmt;
|
1516
|
+
if(NIL_P(stmt_name)) {
|
1483
1517
|
stmt = NULL;
|
1484
1518
|
}
|
1485
1519
|
else {
|
1486
|
-
|
1487
|
-
stmt = StringValueCStr(stmt_name);
|
1520
|
+
stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
|
1488
1521
|
}
|
1489
1522
|
result = gvl_PQdescribePortal(conn, stmt);
|
1490
1523
|
rb_pgresult = pg_new_result(result, self);
|
@@ -1526,10 +1559,6 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
1526
1559
|
* call-seq:
|
1527
1560
|
* conn.escape_string( str ) -> String
|
1528
1561
|
*
|
1529
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1530
|
-
* uses PQescapeStringConn, which is safer. Avoid calling as a class method,
|
1531
|
-
* the class method uses the deprecated PQescapeString() API function.
|
1532
|
-
*
|
1533
1562
|
* Returns a SQL-safe version of the String _str_.
|
1534
1563
|
* This is the preferred way to make strings safe for inclusion in
|
1535
1564
|
* SQL queries.
|
@@ -1538,32 +1567,41 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
1538
1567
|
* inside of SQL commands.
|
1539
1568
|
*
|
1540
1569
|
* Encoding of escaped string will be equal to client encoding of connection.
|
1570
|
+
*
|
1571
|
+
* NOTE: This class version of this method can only be used safely in client
|
1572
|
+
* programs that use a single PostgreSQL connection at a time (in this case it can
|
1573
|
+
* find out what it needs to know "behind the scenes"). It might give the wrong
|
1574
|
+
* results if used in programs that use multiple database connections; use the
|
1575
|
+
* same method on the connection object in such cases.
|
1541
1576
|
*/
|
1542
1577
|
static VALUE
|
1543
1578
|
pgconn_s_escape(VALUE self, VALUE string)
|
1544
1579
|
{
|
1545
|
-
char *escaped;
|
1546
1580
|
size_t size;
|
1547
1581
|
int error;
|
1548
1582
|
VALUE result;
|
1583
|
+
int enc_idx;
|
1584
|
+
int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
|
1549
1585
|
|
1550
|
-
|
1586
|
+
StringValueCStr(string);
|
1587
|
+
enc_idx = ENCODING_GET( singleton ? string : self );
|
1588
|
+
if( ENCODING_GET(string) != enc_idx ){
|
1589
|
+
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1590
|
+
}
|
1551
1591
|
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1592
|
+
result = rb_str_new(NULL, RSTRING_LEN(string) * 2 + 1);
|
1593
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1594
|
+
if( !singleton ) {
|
1595
|
+
size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
|
1555
1596
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1556
1597
|
if(error) {
|
1557
|
-
xfree(escaped);
|
1558
1598
|
rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
|
1559
1599
|
}
|
1560
1600
|
} else {
|
1561
|
-
size = PQescapeString(
|
1601
|
+
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
1562
1602
|
}
|
1563
|
-
result
|
1564
|
-
xfree(escaped);
|
1603
|
+
rb_str_set_len(result, size);
|
1565
1604
|
OBJ_INFECT(result, string);
|
1566
|
-
PG_ENCODING_SET_NOCHECK(result, ENCODING_GET( rb_obj_class(self) == rb_cPGconn ? self : string ));
|
1567
1605
|
|
1568
1606
|
return result;
|
1569
1607
|
}
|
@@ -1572,13 +1610,6 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1572
1610
|
* call-seq:
|
1573
1611
|
* conn.escape_bytea( string ) -> String
|
1574
1612
|
*
|
1575
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1576
|
-
* uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
|
1577
|
-
* the class method uses the deprecated PQescapeBytea() API function.
|
1578
|
-
*
|
1579
|
-
* Use the instance method version of this function, it is safer than the
|
1580
|
-
* class method.
|
1581
|
-
*
|
1582
1613
|
* Escapes binary data for use within an SQL command with the type +bytea+.
|
1583
1614
|
*
|
1584
1615
|
* Certain byte values must be escaped (but all byte values may be escaped)
|
@@ -1591,6 +1622,12 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1591
1622
|
*
|
1592
1623
|
* Consider using exec_params, which avoids the need for passing values inside of
|
1593
1624
|
* SQL commands.
|
1625
|
+
*
|
1626
|
+
* NOTE: This class version of this method can only be used safely in client
|
1627
|
+
* programs that use a single PostgreSQL connection at a time (in this case it can
|
1628
|
+
* find out what it needs to know "behind the scenes"). It might give the wrong
|
1629
|
+
* results if used in programs that use multiple database connections; use the
|
1630
|
+
* same method on the connection object in such cases.
|
1594
1631
|
*/
|
1595
1632
|
static VALUE
|
1596
1633
|
pgconn_s_escape_bytea(VALUE self, VALUE str)
|
@@ -1603,7 +1640,7 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
|
|
1603
1640
|
from = (unsigned char*)RSTRING_PTR(str);
|
1604
1641
|
from_len = RSTRING_LEN(str);
|
1605
1642
|
|
1606
|
-
if(
|
1643
|
+
if ( rb_obj_is_kind_of(self, rb_cPGconn) ) {
|
1607
1644
|
to = PQescapeByteaConn(pg_get_pgconn(self), from, from_len, &to_len);
|
1608
1645
|
} else {
|
1609
1646
|
to = PQescapeBytea( from, from_len, &to_len);
|
@@ -1645,12 +1682,13 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
|
|
1645
1682
|
return ret;
|
1646
1683
|
}
|
1647
1684
|
|
1648
|
-
#ifdef HAVE_PQESCAPELITERAL
|
1649
1685
|
/*
|
1650
1686
|
* call-seq:
|
1651
1687
|
* conn.escape_literal( str ) -> String
|
1652
1688
|
*
|
1653
1689
|
* Escape an arbitrary String +str+ as a literal.
|
1690
|
+
*
|
1691
|
+
* Available since PostgreSQL-9.0
|
1654
1692
|
*/
|
1655
1693
|
static VALUE
|
1656
1694
|
pgconn_escape_literal(VALUE self, VALUE string)
|
@@ -1659,8 +1697,12 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1659
1697
|
char *escaped = NULL;
|
1660
1698
|
VALUE error;
|
1661
1699
|
VALUE result = Qnil;
|
1700
|
+
int enc_idx = ENCODING_GET(self);
|
1662
1701
|
|
1663
|
-
|
1702
|
+
StringValueCStr(string);
|
1703
|
+
if( ENCODING_GET(string) != enc_idx ){
|
1704
|
+
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1705
|
+
}
|
1664
1706
|
|
1665
1707
|
escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1666
1708
|
if (escaped == NULL)
|
@@ -1673,21 +1715,22 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1673
1715
|
result = rb_str_new2(escaped);
|
1674
1716
|
PQfreemem(escaped);
|
1675
1717
|
OBJ_INFECT(result, string);
|
1676
|
-
PG_ENCODING_SET_NOCHECK(result,
|
1718
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1677
1719
|
|
1678
1720
|
return result;
|
1679
1721
|
}
|
1680
|
-
#endif
|
1681
1722
|
|
1682
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
1683
1723
|
/*
|
1684
1724
|
* call-seq:
|
1685
1725
|
* conn.escape_identifier( str ) -> String
|
1686
1726
|
*
|
1687
1727
|
* Escape an arbitrary String +str+ as an identifier.
|
1688
1728
|
*
|
1689
|
-
* This method does the same as #quote_ident
|
1690
|
-
*
|
1729
|
+
* This method does the same as #quote_ident with a String argument,
|
1730
|
+
* but it doesn't support an Array argument and it makes use of libpq
|
1731
|
+
* to process the string.
|
1732
|
+
*
|
1733
|
+
* Available since PostgreSQL-9.0
|
1691
1734
|
*/
|
1692
1735
|
static VALUE
|
1693
1736
|
pgconn_escape_identifier(VALUE self, VALUE string)
|
@@ -1696,8 +1739,12 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1696
1739
|
char *escaped = NULL;
|
1697
1740
|
VALUE error;
|
1698
1741
|
VALUE result = Qnil;
|
1742
|
+
int enc_idx = ENCODING_GET(self);
|
1699
1743
|
|
1700
|
-
|
1744
|
+
StringValueCStr(string);
|
1745
|
+
if( ENCODING_GET(string) != enc_idx ){
|
1746
|
+
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1747
|
+
}
|
1701
1748
|
|
1702
1749
|
escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1703
1750
|
if (escaped == NULL)
|
@@ -1710,13 +1757,11 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1710
1757
|
result = rb_str_new2(escaped);
|
1711
1758
|
PQfreemem(escaped);
|
1712
1759
|
OBJ_INFECT(result, string);
|
1713
|
-
PG_ENCODING_SET_NOCHECK(result,
|
1760
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1714
1761
|
|
1715
1762
|
return result;
|
1716
1763
|
}
|
1717
|
-
#endif
|
1718
1764
|
|
1719
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1720
1765
|
/*
|
1721
1766
|
* call-seq:
|
1722
1767
|
* conn.set_single_row_mode -> self
|
@@ -1753,6 +1798,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1753
1798
|
* end
|
1754
1799
|
* end
|
1755
1800
|
*
|
1801
|
+
* Available since PostgreSQL-9.2
|
1756
1802
|
*/
|
1757
1803
|
static VALUE
|
1758
1804
|
pgconn_set_single_row_mode(VALUE self)
|
@@ -1769,22 +1815,60 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1769
1815
|
|
1770
1816
|
return self;
|
1771
1817
|
}
|
1772
|
-
|
1818
|
+
|
1819
|
+
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
1820
|
+
|
1821
|
+
/*
|
1822
|
+
* call-seq:
|
1823
|
+
* conn.send_query(sql) -> nil
|
1824
|
+
*
|
1825
|
+
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1826
|
+
* asynchronous processing, and immediately returns.
|
1827
|
+
* On failure, it raises a PG::Error.
|
1828
|
+
*
|
1829
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
1830
|
+
* it will call #send_query_params for you. New code should explicitly use #send_query_params if
|
1831
|
+
* argument placeholders are used.
|
1832
|
+
*
|
1833
|
+
*/
|
1834
|
+
static VALUE
|
1835
|
+
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1836
|
+
{
|
1837
|
+
PGconn *conn = pg_get_pgconn(self);
|
1838
|
+
VALUE error;
|
1839
|
+
|
1840
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
1841
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1842
|
+
if(gvl_PQsendQuery(conn, pg_cstr_enc(argv[0], ENCODING_GET(self))) == 0) {
|
1843
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1844
|
+
rb_iv_set(error, "@connection", self);
|
1845
|
+
rb_exc_raise(error);
|
1846
|
+
}
|
1847
|
+
return Qnil;
|
1848
|
+
}
|
1849
|
+
|
1850
|
+
pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
|
1851
|
+
|
1852
|
+
/* If called with parameters, and optionally result_format,
|
1853
|
+
* use PQsendQueryParams
|
1854
|
+
*/
|
1855
|
+
return pgconn_send_query_params( argc, argv, self);
|
1856
|
+
}
|
1773
1857
|
|
1774
1858
|
/*
|
1775
1859
|
* call-seq:
|
1776
|
-
* conn.
|
1860
|
+
* conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
|
1777
1861
|
*
|
1778
1862
|
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1779
1863
|
* asynchronous processing, and immediately returns.
|
1780
1864
|
* On failure, it raises a PG::Error.
|
1781
1865
|
*
|
1782
|
-
* +params+ is an
|
1866
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
1783
1867
|
* Each element of the +params+ array may be either:
|
1784
1868
|
* a hash of the form:
|
1785
1869
|
* {:value => String (value of bind parameter)
|
1786
|
-
* :type =>
|
1787
|
-
* :format =>
|
1870
|
+
* :type => Integer (oid of type of bind parameter)
|
1871
|
+
* :format => Integer (0 for text, 1 for binary)
|
1788
1872
|
* }
|
1789
1873
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1790
1874
|
* { :value => <string value>, :type => 0, :format => 0 }
|
@@ -1803,14 +1887,14 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1803
1887
|
* for binary.
|
1804
1888
|
*
|
1805
1889
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1806
|
-
* This will type cast the params
|
1890
|
+
* This will type cast the params from various Ruby types before transmission
|
1807
1891
|
* based on the encoders defined by the type map. When a type encoder is used
|
1808
1892
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1809
1893
|
* instead out of the hash form described above.
|
1810
1894
|
*
|
1811
1895
|
*/
|
1812
1896
|
static VALUE
|
1813
|
-
|
1897
|
+
pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
1814
1898
|
{
|
1815
1899
|
PGconn *conn = pg_get_pgconn(self);
|
1816
1900
|
int result;
|
@@ -1818,31 +1902,16 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1818
1902
|
VALUE error;
|
1819
1903
|
int nParams;
|
1820
1904
|
int resultFormat;
|
1821
|
-
struct query_params_data paramsData;
|
1905
|
+
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1822
1906
|
|
1823
|
-
rb_scan_args(argc, argv, "
|
1907
|
+
rb_scan_args(argc, argv, "22", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1824
1908
|
paramsData.with_types = 1;
|
1825
|
-
Check_Type(command, T_STRING);
|
1826
|
-
|
1827
|
-
/* If called with no parameters, use PQsendQuery */
|
1828
|
-
if(NIL_P(paramsData.params)) {
|
1829
|
-
if(gvl_PQsendQuery(conn,StringValueCStr(command)) == 0) {
|
1830
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1831
|
-
rb_iv_set(error, "@connection", self);
|
1832
|
-
rb_exc_raise(error);
|
1833
|
-
}
|
1834
|
-
return Qnil;
|
1835
|
-
}
|
1836
|
-
|
1837
|
-
/* If called with parameters, and optionally result_format,
|
1838
|
-
* use PQsendQueryParams
|
1839
|
-
*/
|
1840
1909
|
|
1841
1910
|
pgconn_query_assign_typemap( self, ¶msData );
|
1842
1911
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1843
1912
|
nParams = alloc_query_params( ¶msData );
|
1844
1913
|
|
1845
|
-
result = gvl_PQsendQueryParams(conn,
|
1914
|
+
result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
|
1846
1915
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
1847
1916
|
|
1848
1917
|
free_query_params( ¶msData );
|
@@ -1886,10 +1955,13 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1886
1955
|
int i = 0;
|
1887
1956
|
int nParams = 0;
|
1888
1957
|
Oid *paramTypes = NULL;
|
1958
|
+
const char *name_cstr;
|
1959
|
+
const char *command_cstr;
|
1960
|
+
int enc_idx = ENCODING_GET(self);
|
1889
1961
|
|
1890
1962
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1891
|
-
|
1892
|
-
|
1963
|
+
name_cstr = pg_cstr_enc(name, enc_idx);
|
1964
|
+
command_cstr = pg_cstr_enc(command, enc_idx);
|
1893
1965
|
|
1894
1966
|
if(! NIL_P(in_paramtypes)) {
|
1895
1967
|
Check_Type(in_paramtypes, T_ARRAY);
|
@@ -1903,8 +1975,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1903
1975
|
paramTypes[i] = NUM2UINT(param);
|
1904
1976
|
}
|
1905
1977
|
}
|
1906
|
-
result = gvl_PQsendPrepare(conn,
|
1907
|
-
nParams, paramTypes);
|
1978
|
+
result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
|
1908
1979
|
|
1909
1980
|
xfree(paramTypes);
|
1910
1981
|
|
@@ -1929,7 +2000,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1929
2000
|
* SQL query. Each element of the +params+ array may be either:
|
1930
2001
|
* a hash of the form:
|
1931
2002
|
* {:value => String (value of bind parameter)
|
1932
|
-
* :format =>
|
2003
|
+
* :format => Integer (0 for text, 1 for binary)
|
1933
2004
|
* }
|
1934
2005
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1935
2006
|
* { :value => <string value>, :format => 0 }
|
@@ -1942,7 +2013,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1942
2013
|
* for binary.
|
1943
2014
|
*
|
1944
2015
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1945
|
-
* This will type cast the params
|
2016
|
+
* This will type cast the params from various Ruby types before transmission
|
1946
2017
|
* based on the encoders defined by the type map. When a type encoder is used
|
1947
2018
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1948
2019
|
* instead out of the hash form described above.
|
@@ -1957,11 +2028,10 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1957
2028
|
VALUE error;
|
1958
2029
|
int nParams;
|
1959
2030
|
int resultFormat;
|
1960
|
-
struct query_params_data paramsData;
|
2031
|
+
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1961
2032
|
|
1962
2033
|
rb_scan_args(argc, argv, "13", &name, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1963
2034
|
paramsData.with_types = 0;
|
1964
|
-
Check_Type(name, T_STRING);
|
1965
2035
|
|
1966
2036
|
if(NIL_P(paramsData.params)) {
|
1967
2037
|
paramsData.params = rb_ary_new2(0);
|
@@ -1972,7 +2042,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1972
2042
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1973
2043
|
nParams = alloc_query_params( ¶msData );
|
1974
2044
|
|
1975
|
-
result = gvl_PQsendQueryPrepared(conn,
|
2045
|
+
result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
|
1976
2046
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
1977
2047
|
resultFormat);
|
1978
2048
|
|
@@ -1999,7 +2069,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1999
2069
|
VALUE error;
|
2000
2070
|
PGconn *conn = pg_get_pgconn(self);
|
2001
2071
|
/* returns 0 on failure */
|
2002
|
-
if(gvl_PQsendDescribePrepared(conn,
|
2072
|
+
if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
|
2003
2073
|
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
2004
2074
|
rb_iv_set(error, "@connection", self);
|
2005
2075
|
rb_exc_raise(error);
|
@@ -2021,7 +2091,7 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
2021
2091
|
VALUE error;
|
2022
2092
|
PGconn *conn = pg_get_pgconn(self);
|
2023
2093
|
/* returns 0 on failure */
|
2024
|
-
if(gvl_PQsendDescribePortal(conn,
|
2094
|
+
if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
|
2025
2095
|
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
2026
2096
|
rb_iv_set(error, "@connection", self);
|
2027
2097
|
rb_exc_raise(error);
|
@@ -2193,7 +2263,6 @@ pgconn_flush(self)
|
|
2193
2263
|
static VALUE
|
2194
2264
|
pgconn_cancel(VALUE self)
|
2195
2265
|
{
|
2196
|
-
#ifdef HAVE_PQGETCANCEL
|
2197
2266
|
char errbuf[256];
|
2198
2267
|
PGcancel *cancel;
|
2199
2268
|
VALUE retval;
|
@@ -2211,9 +2280,6 @@ pgconn_cancel(VALUE self)
|
|
2211
2280
|
|
2212
2281
|
PQfreeCancel(cancel);
|
2213
2282
|
return retval;
|
2214
|
-
#else
|
2215
|
-
rb_notimplement();
|
2216
|
-
#endif
|
2217
2283
|
}
|
2218
2284
|
|
2219
2285
|
|
@@ -2257,56 +2323,15 @@ pgconn_notifies(VALUE self)
|
|
2257
2323
|
return hash;
|
2258
2324
|
}
|
2259
2325
|
|
2260
|
-
/* Win32 + Ruby 1.8 */
|
2261
|
-
#if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
|
2262
|
-
|
2263
|
-
/*
|
2264
|
-
* Duplicate the sockets from libpq and create temporary CRT FDs
|
2265
|
-
*/
|
2266
|
-
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2267
|
-
{
|
2268
|
-
int i;
|
2269
|
-
crt_set->fd_count = os_set->fd_count;
|
2270
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2271
|
-
WSAPROTOCOL_INFO wsa_pi;
|
2272
|
-
/* dupicate the SOCKET */
|
2273
|
-
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2274
|
-
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2275
|
-
/* create the CRT fd so ruby can get back to the SOCKET */
|
2276
|
-
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2277
|
-
os_set->fd_array[i] = s;
|
2278
|
-
crt_set->fd_array[i] = fd;
|
2279
|
-
}
|
2280
|
-
}
|
2281
|
-
|
2282
|
-
/*
|
2283
|
-
* Clean up the CRT FDs from create_crt_fd()
|
2284
|
-
*/
|
2285
|
-
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2286
|
-
{
|
2287
|
-
int i;
|
2288
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2289
|
-
/* cleanup the CRT fd */
|
2290
|
-
_close(crt_set->fd_array[i]);
|
2291
|
-
/* cleanup the duplicated SOCKET */
|
2292
|
-
closesocket(os_set->fd_array[i]);
|
2293
|
-
}
|
2294
|
-
}
|
2295
|
-
#endif
|
2296
|
-
|
2297
2326
|
/* Win32 + Ruby 1.9+ */
|
2298
|
-
#if defined(
|
2327
|
+
#if defined( _WIN32 )
|
2299
2328
|
/*
|
2300
2329
|
* On Windows, use platform-specific strategies to wait for the socket
|
2301
|
-
* instead of
|
2330
|
+
* instead of rb_wait_for_single_fd().
|
2302
2331
|
*/
|
2303
2332
|
|
2304
2333
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2305
2334
|
|
2306
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2307
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2308
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2309
|
-
|
2310
2335
|
static void *
|
2311
2336
|
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
|
2312
2337
|
{
|
@@ -2383,7 +2408,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2383
2408
|
|
2384
2409
|
#else
|
2385
2410
|
|
2386
|
-
/* non Win32
|
2411
|
+
/* non Win32 */
|
2387
2412
|
|
2388
2413
|
static void *
|
2389
2414
|
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
@@ -2391,11 +2416,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2391
2416
|
int sd = PQsocket( conn );
|
2392
2417
|
int ret;
|
2393
2418
|
void *retval;
|
2394
|
-
rb_fdset_t sd_rset;
|
2395
2419
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2396
|
-
#ifdef _WIN32
|
2397
|
-
rb_fdset_t crt_sd_rset;
|
2398
|
-
#endif
|
2399
2420
|
|
2400
2421
|
if ( sd < 0 )
|
2401
2422
|
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
@@ -2404,25 +2425,12 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2404
2425
|
if ( PQconsumeInput(conn) == 0 )
|
2405
2426
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2406
2427
|
|
2407
|
-
rb_fd_init( &sd_rset );
|
2408
|
-
|
2409
2428
|
if ( ptimeout ) {
|
2410
2429
|
gettimeofday(&currtime, NULL);
|
2411
2430
|
timeradd(&currtime, ptimeout, &aborttime);
|
2412
2431
|
}
|
2413
2432
|
|
2414
2433
|
while ( !(retval=is_readable(conn)) ) {
|
2415
|
-
rb_fd_zero( &sd_rset );
|
2416
|
-
rb_fd_set( sd, &sd_rset );
|
2417
|
-
|
2418
|
-
#ifdef _WIN32
|
2419
|
-
/* Ruby's FD_SET is modified on win32 to convert a file descriptor
|
2420
|
-
* to osfhandle, but we already get a osfhandle from PQsocket().
|
2421
|
-
* Therefore it's overwritten here. */
|
2422
|
-
sd_rset.fd_array[0] = sd;
|
2423
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2424
|
-
#endif
|
2425
|
-
|
2426
2434
|
if ( ptimeout ) {
|
2427
2435
|
gettimeofday(&currtime, NULL);
|
2428
2436
|
timersub(&aborttime, &currtime, &waittime);
|
@@ -2431,35 +2439,26 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2431
2439
|
/* Is the given timeout valid? */
|
2432
2440
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2433
2441
|
/* Wait for the socket to become readable before checking again */
|
2434
|
-
ret =
|
2442
|
+
ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
|
2435
2443
|
} else {
|
2436
2444
|
ret = 0;
|
2437
2445
|
}
|
2438
2446
|
|
2439
|
-
|
2440
|
-
#ifdef _WIN32
|
2441
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2442
|
-
#endif
|
2443
|
-
|
2444
2447
|
if ( ret < 0 ){
|
2445
|
-
|
2446
|
-
rb_sys_fail( "rb_thread_select()" );
|
2448
|
+
rb_sys_fail( "rb_wait_for_single_fd()" );
|
2447
2449
|
}
|
2448
2450
|
|
2449
2451
|
/* Return false if the select() timed out */
|
2450
2452
|
if ( ret == 0 ){
|
2451
|
-
rb_fd_term( &sd_rset );
|
2452
2453
|
return NULL;
|
2453
2454
|
}
|
2454
2455
|
|
2455
2456
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2456
2457
|
if ( PQconsumeInput(conn) == 0 ){
|
2457
|
-
rb_fd_term( &sd_rset );
|
2458
2458
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2459
2459
|
}
|
2460
2460
|
}
|
2461
2461
|
|
2462
|
-
rb_fd_term( &sd_rset );
|
2463
2462
|
return retval;
|
2464
2463
|
}
|
2465
2464
|
|
@@ -2474,22 +2473,15 @@ notify_readable(PGconn *conn)
|
|
2474
2473
|
|
2475
2474
|
/*
|
2476
2475
|
* call-seq:
|
2477
|
-
* conn.wait_for_notify( [ timeout ] ) -> String
|
2478
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
|
2479
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
|
2476
|
+
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
|
2480
2477
|
*
|
2481
2478
|
* Blocks while waiting for notification(s), or until the optional
|
2482
2479
|
* _timeout_ is reached, whichever comes first. _timeout_ is
|
2483
2480
|
* measured in seconds and can be fractional.
|
2484
2481
|
*
|
2485
|
-
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2486
|
-
*
|
2487
|
-
*
|
2488
|
-
*
|
2489
|
-
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2490
|
-
* the optional +payload+ string, it will be given to the block as the
|
2491
|
-
* third argument.
|
2492
|
-
*
|
2482
|
+
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
|
2483
|
+
* If used in block form, passes the name of the NOTIFY +event+, the generating
|
2484
|
+
* +pid+ and the optional +payload+ string into the block.
|
2493
2485
|
*/
|
2494
2486
|
static VALUE
|
2495
2487
|
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
@@ -2518,12 +2510,10 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2518
2510
|
relname = rb_tainted_str_new2( pnotification->relname );
|
2519
2511
|
PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
|
2520
2512
|
be_pid = INT2NUM( pnotification->be_pid );
|
2521
|
-
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2522
2513
|
if ( *pnotification->extra ) {
|
2523
2514
|
extra = rb_tainted_str_new2( pnotification->extra );
|
2524
2515
|
PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
|
2525
2516
|
}
|
2526
|
-
#endif
|
2527
2517
|
PQfreemem( pnotification );
|
2528
2518
|
|
2529
2519
|
if ( rb_block_given_p() )
|
@@ -2542,9 +2532,10 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2542
2532
|
* not sent (false is only possible if the connection
|
2543
2533
|
* is in nonblocking mode, and this command would block).
|
2544
2534
|
*
|
2545
|
-
*
|
2546
|
-
* This encodes the
|
2547
|
-
*
|
2535
|
+
* _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
|
2536
|
+
* This encodes the data fields given as _buffer_ from an Array of Strings to
|
2537
|
+
* PostgreSQL's COPY text format inclusive proper escaping. Optionally
|
2538
|
+
* the encoder can type cast the fields from various Ruby types in one step,
|
2548
2539
|
* if PG::TextEncoder::CopyRow#type_map is set accordingly.
|
2549
2540
|
*
|
2550
2541
|
* Raises an exception if an error occurs.
|
@@ -2581,16 +2572,17 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2581
2572
|
|
2582
2573
|
if( p_coder ){
|
2583
2574
|
t_pg_coder_enc_func enc_func;
|
2575
|
+
int enc_idx = ENCODING_GET(self);
|
2584
2576
|
|
2585
2577
|
enc_func = pg_coder_enc_func( p_coder );
|
2586
|
-
len = enc_func( p_coder, value, NULL, &intermediate );
|
2578
|
+
len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
|
2587
2579
|
|
2588
2580
|
if( len == -1 ){
|
2589
2581
|
/* The intermediate value is a String that can be used directly. */
|
2590
2582
|
buffer = intermediate;
|
2591
2583
|
} else {
|
2592
2584
|
buffer = rb_str_new(NULL, len);
|
2593
|
-
len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate);
|
2585
|
+
len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate, enc_idx);
|
2594
2586
|
rb_str_set_len( buffer, len );
|
2595
2587
|
}
|
2596
2588
|
}
|
@@ -2629,13 +2621,13 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2629
2621
|
VALUE str;
|
2630
2622
|
VALUE error;
|
2631
2623
|
int ret;
|
2632
|
-
char *error_message = NULL;
|
2624
|
+
const char *error_message = NULL;
|
2633
2625
|
PGconn *conn = pg_get_pgconn(self);
|
2634
2626
|
|
2635
2627
|
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
2636
2628
|
error_message = NULL;
|
2637
2629
|
else
|
2638
|
-
error_message =
|
2630
|
+
error_message = pg_cstr_enc(str, ENCODING_GET(self));
|
2639
2631
|
|
2640
2632
|
ret = gvl_PQputCopyEnd(conn, error_message);
|
2641
2633
|
if(ret == -1) {
|
@@ -2648,15 +2640,18 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2648
2640
|
|
2649
2641
|
/*
|
2650
2642
|
* call-seq:
|
2651
|
-
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) ->
|
2643
|
+
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
|
2652
2644
|
*
|
2653
|
-
* Return
|
2645
|
+
* Return one row of data, +nil+
|
2654
2646
|
* if the copy is done, or +false+ if the call would
|
2655
2647
|
* block (only possible if _async_ is true).
|
2656
2648
|
*
|
2657
|
-
*
|
2658
|
-
*
|
2659
|
-
*
|
2649
|
+
* If _decoder_ is not set or +nil+, data is returned as binary string.
|
2650
|
+
*
|
2651
|
+
* If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
|
2652
|
+
* PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
|
2653
|
+
* COPY text format to an Array of Strings.
|
2654
|
+
* Optionally the decoder can type cast the single fields to various Ruby types in one step,
|
2660
2655
|
* if PG::TextDecoder::CopyRow#type_map is set accordingly.
|
2661
2656
|
*
|
2662
2657
|
* See also #copy_data.
|
@@ -2713,7 +2708,7 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2713
2708
|
|
2714
2709
|
/*
|
2715
2710
|
* call-seq:
|
2716
|
-
* conn.set_error_verbosity( verbosity ) ->
|
2711
|
+
* conn.set_error_verbosity( verbosity ) -> Integer
|
2717
2712
|
*
|
2718
2713
|
* Sets connection's verbosity to _verbosity_ and returns
|
2719
2714
|
* the previous setting. Available settings are:
|
@@ -2956,12 +2951,10 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2956
2951
|
|
2957
2952
|
Check_Type(str, T_STRING);
|
2958
2953
|
|
2959
|
-
if ( (
|
2960
|
-
rb_raise(rb_ePGerror, "
|
2954
|
+
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
|
2955
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
2961
2956
|
}
|
2962
|
-
#ifdef M17N_SUPPORTED
|
2963
2957
|
pgconn_set_internal_encoding_index( self );
|
2964
|
-
#endif
|
2965
2958
|
|
2966
2959
|
return Qnil;
|
2967
2960
|
}
|
@@ -3012,8 +3005,10 @@ pgconn_transaction(VALUE self)
|
|
3012
3005
|
|
3013
3006
|
/*
|
3014
3007
|
* call-seq:
|
3015
|
-
* PG::Connection.quote_ident( str ) -> String
|
3016
3008
|
* conn.quote_ident( str ) -> String
|
3009
|
+
* conn.quote_ident( array ) -> String
|
3010
|
+
* PG::Connection.quote_ident( str ) -> String
|
3011
|
+
* PG::Connection.quote_ident( array ) -> String
|
3017
3012
|
*
|
3018
3013
|
* Returns a string that is safe for inclusion in a SQL query as an
|
3019
3014
|
* identifier. Note: this is not a quote function for values, but for
|
@@ -3023,40 +3018,41 @@ pgconn_transaction(VALUE self)
|
|
3023
3018
|
* The identifier <tt>FOO</tt> is folded to lower case, so it actually
|
3024
3019
|
* means <tt>foo</tt>. If you really want to access the case-sensitive
|
3025
3020
|
* field name <tt>FOO</tt>, use this function like
|
3026
|
-
* <tt>
|
3021
|
+
* <tt>conn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
|
3027
3022
|
* (with double-quotes). PostgreSQL will see the double-quotes, and
|
3028
3023
|
* it will not fold to lower case.
|
3029
3024
|
*
|
3030
3025
|
* Similarly, this function also protects against special characters,
|
3031
3026
|
* and other things that might allow SQL injection if the identifier
|
3032
3027
|
* comes from an untrusted source.
|
3028
|
+
*
|
3029
|
+
* If the parameter is an Array, then all it's values are separately quoted
|
3030
|
+
* and then joined by a "." character. This can be used for identifiers in
|
3031
|
+
* the form "schema"."table"."column" .
|
3032
|
+
*
|
3033
|
+
* This method is functional identical to the encoder PG::TextEncoder::Identifier .
|
3034
|
+
*
|
3035
|
+
* If the instance method form is used and the input string character encoding
|
3036
|
+
* is different to the connection encoding, then the string is converted to this
|
3037
|
+
* encoding, so that the returned string is always encoded as PG::Connection#internal_encoding .
|
3038
|
+
*
|
3039
|
+
* In the singleton form (PG::Connection.quote_ident) the character encoding
|
3040
|
+
* of the result string is set to the character encoding of the input string.
|
3033
3041
|
*/
|
3034
3042
|
static VALUE
|
3035
|
-
pgconn_s_quote_ident(VALUE self, VALUE
|
3043
|
+
pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
|
3036
3044
|
{
|
3037
3045
|
VALUE ret;
|
3038
|
-
|
3039
|
-
|
3040
|
-
|
3041
|
-
|
3042
|
-
|
3043
|
-
|
3044
|
-
|
3045
|
-
|
3046
|
-
|
3047
|
-
|
3048
|
-
NAMEDATALEN-1);
|
3049
|
-
}
|
3050
|
-
buffer[j++] = '"';
|
3051
|
-
for(i = 0; i < str_len && str[i]; i++) {
|
3052
|
-
if(str[i] == '"')
|
3053
|
-
buffer[j++] = '"';
|
3054
|
-
buffer[j++] = str[i];
|
3055
|
-
}
|
3056
|
-
buffer[j++] = '"';
|
3057
|
-
ret = rb_str_new(buffer,j);
|
3058
|
-
OBJ_INFECT(ret, in_str);
|
3059
|
-
PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET( rb_obj_class(self) == rb_cPGconn ? self : in_str ));
|
3046
|
+
int enc_idx;
|
3047
|
+
|
3048
|
+
if( rb_obj_is_kind_of(self, rb_cPGconn) ){
|
3049
|
+
enc_idx = ENCODING_GET( self );
|
3050
|
+
}else{
|
3051
|
+
enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
|
3052
|
+
}
|
3053
|
+
pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
|
3054
|
+
|
3055
|
+
OBJ_INFECT(ret, str_or_array);
|
3060
3056
|
|
3061
3057
|
return ret;
|
3062
3058
|
}
|
@@ -3086,10 +3082,6 @@ static VALUE
|
|
3086
3082
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
3087
3083
|
PGconn *conn = pg_get_pgconn( self );
|
3088
3084
|
|
3089
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
3090
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
3091
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
3092
|
-
|
3093
3085
|
struct timeval timeout;
|
3094
3086
|
struct timeval *ptimeout = NULL;
|
3095
3087
|
VALUE timeout_in;
|
@@ -3156,24 +3148,186 @@ pgconn_get_last_result(VALUE self)
|
|
3156
3148
|
|
3157
3149
|
/*
|
3158
3150
|
* call-seq:
|
3159
|
-
* conn.
|
3160
|
-
*
|
3151
|
+
* conn.discard_results()
|
3152
|
+
*
|
3153
|
+
* Silently discard any prior query result that application didn't eat.
|
3154
|
+
* This is done prior of Connection#exec and sibling methods and can
|
3155
|
+
* be called explicitly when using the async API.
|
3156
|
+
*/
|
3157
|
+
static VALUE
|
3158
|
+
pgconn_discard_results(VALUE self)
|
3159
|
+
{
|
3160
|
+
PGconn *conn = pg_get_pgconn(self);
|
3161
|
+
|
3162
|
+
PGresult *cur;
|
3163
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3164
|
+
int status = PQresultStatus(cur);
|
3165
|
+
PQclear(cur);
|
3166
|
+
if (status == PGRES_COPY_IN){
|
3167
|
+
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
3168
|
+
}
|
3169
|
+
if (status == PGRES_COPY_OUT){
|
3170
|
+
char *buffer = NULL;
|
3171
|
+
while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
|
3172
|
+
PQfreemem(buffer);
|
3173
|
+
}
|
3174
|
+
}
|
3175
|
+
|
3176
|
+
return Qnil;
|
3177
|
+
}
|
3178
|
+
|
3179
|
+
/*
|
3180
|
+
* call-seq:
|
3181
|
+
* conn.async_exec(sql) -> PG::Result
|
3182
|
+
* conn.async_exec(sql) {|pg_result| block }
|
3161
3183
|
*
|
3162
|
-
* This function has the same behavior as #
|
3184
|
+
* This function has the same behavior as #sync_exec,
|
3163
3185
|
* but is implemented using the asynchronous command
|
3164
3186
|
* processing API of libpq.
|
3187
|
+
*
|
3188
|
+
* Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
|
3189
|
+
* However #async_exec has two advantages:
|
3190
|
+
*
|
3191
|
+
* 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
|
3192
|
+
* 2. Ruby VM gets notified about IO blocked operations.
|
3193
|
+
* It can therefore schedule thing like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
|
3165
3194
|
*/
|
3166
3195
|
static VALUE
|
3167
3196
|
pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
3168
3197
|
{
|
3169
3198
|
VALUE rb_pgresult = Qnil;
|
3170
3199
|
|
3171
|
-
|
3200
|
+
pgconn_discard_results( self );
|
3201
|
+
pgconn_send_query( argc, argv, self );
|
3172
3202
|
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3173
|
-
pgconn_get_last_result( self );
|
3203
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3174
3204
|
|
3175
|
-
|
3176
|
-
|
3205
|
+
if ( rb_block_given_p() ) {
|
3206
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3207
|
+
}
|
3208
|
+
return rb_pgresult;
|
3209
|
+
}
|
3210
|
+
|
3211
|
+
|
3212
|
+
/*
|
3213
|
+
* call-seq:
|
3214
|
+
* conn.async_exec_params(sql, params [, result_format [, type_map ]] ) -> nil
|
3215
|
+
* conn.async_exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
|
3216
|
+
*
|
3217
|
+
* This function has the same behavior as #sync_exec_params, but is implemented using the asynchronous command processing API of libpq.
|
3218
|
+
* See #async_exec for the differences between the two API variants.
|
3219
|
+
*/
|
3220
|
+
static VALUE
|
3221
|
+
pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
3222
|
+
{
|
3223
|
+
VALUE rb_pgresult = Qnil;
|
3224
|
+
|
3225
|
+
pgconn_discard_results( self );
|
3226
|
+
/* If called with no or nil parameters, use PQsendQuery for compatibility */
|
3227
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
3228
|
+
pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
|
3229
|
+
pgconn_send_query( argc, argv, self );
|
3230
|
+
} else {
|
3231
|
+
pgconn_send_query_params( argc, argv, self );
|
3232
|
+
}
|
3233
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3234
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3235
|
+
|
3236
|
+
if ( rb_block_given_p() ) {
|
3237
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3238
|
+
}
|
3239
|
+
return rb_pgresult;
|
3240
|
+
}
|
3241
|
+
|
3242
|
+
|
3243
|
+
/*
|
3244
|
+
* call-seq:
|
3245
|
+
* conn.async_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
|
3246
|
+
*
|
3247
|
+
* This function has the same behavior as #sync_prepare, but is implemented using the asynchronous command processing API of libpq.
|
3248
|
+
* See #async_exec for the differences between the two API variants.
|
3249
|
+
*/
|
3250
|
+
static VALUE
|
3251
|
+
pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
3252
|
+
{
|
3253
|
+
VALUE rb_pgresult = Qnil;
|
3254
|
+
|
3255
|
+
pgconn_discard_results( self );
|
3256
|
+
pgconn_send_prepare( argc, argv, self );
|
3257
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3258
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3259
|
+
|
3260
|
+
if ( rb_block_given_p() ) {
|
3261
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3262
|
+
}
|
3263
|
+
return rb_pgresult;
|
3264
|
+
}
|
3265
|
+
|
3266
|
+
|
3267
|
+
/*
|
3268
|
+
* call-seq:
|
3269
|
+
* conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
|
3270
|
+
* conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
|
3271
|
+
*
|
3272
|
+
* This function has the same behavior as #sync_exec_prepared, but is implemented using the asynchronous command processing API of libpq.
|
3273
|
+
* See #async_exec for the differences between the two API variants.
|
3274
|
+
*/
|
3275
|
+
static VALUE
|
3276
|
+
pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
3277
|
+
{
|
3278
|
+
VALUE rb_pgresult = Qnil;
|
3279
|
+
|
3280
|
+
pgconn_discard_results( self );
|
3281
|
+
pgconn_send_query_prepared( argc, argv, self );
|
3282
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3283
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3284
|
+
|
3285
|
+
if ( rb_block_given_p() ) {
|
3286
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3287
|
+
}
|
3288
|
+
return rb_pgresult;
|
3289
|
+
}
|
3290
|
+
|
3291
|
+
|
3292
|
+
/*
|
3293
|
+
* call-seq:
|
3294
|
+
* conn.async_describe_portal( portal_name ) -> PG::Result
|
3295
|
+
*
|
3296
|
+
* This function has the same behavior as #sync_describe_portal, but is implemented using the asynchronous command processing API of libpq.
|
3297
|
+
* See #async_exec for the differences between the two API variants.
|
3298
|
+
*/
|
3299
|
+
static VALUE
|
3300
|
+
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
3301
|
+
{
|
3302
|
+
VALUE rb_pgresult = Qnil;
|
3303
|
+
|
3304
|
+
pgconn_discard_results( self );
|
3305
|
+
pgconn_send_describe_portal( self, portal );
|
3306
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3307
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3308
|
+
|
3309
|
+
if ( rb_block_given_p() ) {
|
3310
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3311
|
+
}
|
3312
|
+
return rb_pgresult;
|
3313
|
+
}
|
3314
|
+
|
3315
|
+
|
3316
|
+
/*
|
3317
|
+
* call-seq:
|
3318
|
+
* conn.async_describe_prepared( statement_name ) -> PG::Result
|
3319
|
+
*
|
3320
|
+
* This function has the same behavior as #sync_describe_prepared, but is implemented using the asynchronous command processing API of libpq.
|
3321
|
+
* See #async_exec for the differences between the two API variants.
|
3322
|
+
*/
|
3323
|
+
static VALUE
|
3324
|
+
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
3325
|
+
{
|
3326
|
+
VALUE rb_pgresult = Qnil;
|
3327
|
+
|
3328
|
+
pgconn_discard_results( self );
|
3329
|
+
pgconn_send_describe_prepared( self, stmt_name );
|
3330
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3177
3331
|
rb_pgresult = pgconn_get_last_result( self );
|
3178
3332
|
|
3179
3333
|
if ( rb_block_given_p() ) {
|
@@ -3182,13 +3336,93 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3182
3336
|
return rb_pgresult;
|
3183
3337
|
}
|
3184
3338
|
|
3339
|
+
|
3340
|
+
#ifdef HAVE_PQSSLATTRIBUTE
|
3341
|
+
/*
|
3342
|
+
* call-seq:
|
3343
|
+
* conn.ssl_in_use? -> Boolean
|
3344
|
+
*
|
3345
|
+
* Returns +true+ if the connection uses SSL, +false+ if not.
|
3346
|
+
*
|
3347
|
+
* Available since PostgreSQL-9.5
|
3348
|
+
*/
|
3349
|
+
static VALUE
|
3350
|
+
pgconn_ssl_in_use(VALUE self)
|
3351
|
+
{
|
3352
|
+
return PQsslInUse(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
3353
|
+
}
|
3354
|
+
|
3355
|
+
|
3356
|
+
/*
|
3357
|
+
* call-seq:
|
3358
|
+
* conn.ssl_attribute(attribute_name) -> String
|
3359
|
+
*
|
3360
|
+
* Returns SSL-related information about the connection.
|
3361
|
+
*
|
3362
|
+
* The list of available attributes varies depending on the SSL library being used,
|
3363
|
+
* and the type of connection. If an attribute is not available, returns nil.
|
3364
|
+
*
|
3365
|
+
* The following attributes are commonly available:
|
3366
|
+
*
|
3367
|
+
* [+library+]
|
3368
|
+
* Name of the SSL implementation in use. (Currently, only "OpenSSL" is implemented)
|
3369
|
+
* [+protocol+]
|
3370
|
+
* SSL/TLS version in use. Common values are "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" and "TLSv1.2", but an implementation may return other strings if some other protocol is used.
|
3371
|
+
* [+key_bits+]
|
3372
|
+
* Number of key bits used by the encryption algorithm.
|
3373
|
+
* [+cipher+]
|
3374
|
+
* A short name of the ciphersuite used, e.g. "DHE-RSA-DES-CBC3-SHA". The names are specific to each SSL implementation.
|
3375
|
+
* [+compression+]
|
3376
|
+
* If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
|
3377
|
+
*
|
3378
|
+
*
|
3379
|
+
* See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
|
3380
|
+
*
|
3381
|
+
* Available since PostgreSQL-9.5
|
3382
|
+
*/
|
3383
|
+
static VALUE
|
3384
|
+
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
3385
|
+
{
|
3386
|
+
const char *p_attr;
|
3387
|
+
|
3388
|
+
p_attr = PQsslAttribute(pg_get_pgconn(self), StringValueCStr(attribute_name));
|
3389
|
+
return p_attr ? rb_str_new_cstr(p_attr) : Qnil;
|
3390
|
+
}
|
3391
|
+
|
3392
|
+
/*
|
3393
|
+
* call-seq:
|
3394
|
+
* conn.ssl_attribute_names -> Array<String>
|
3395
|
+
*
|
3396
|
+
* Return an array of SSL attribute names available.
|
3397
|
+
*
|
3398
|
+
* See also #ssl_attribute
|
3399
|
+
*
|
3400
|
+
* Available since PostgreSQL-9.5
|
3401
|
+
*/
|
3402
|
+
static VALUE
|
3403
|
+
pgconn_ssl_attribute_names(VALUE self)
|
3404
|
+
{
|
3405
|
+
int i;
|
3406
|
+
const char * const * p_list = PQsslAttributeNames(pg_get_pgconn(self));
|
3407
|
+
VALUE ary = rb_ary_new();
|
3408
|
+
|
3409
|
+
for ( i = 0; p_list[i]; i++ ) {
|
3410
|
+
rb_ary_push( ary, rb_str_new_cstr( p_list[i] ));
|
3411
|
+
}
|
3412
|
+
return ary;
|
3413
|
+
}
|
3414
|
+
|
3415
|
+
|
3416
|
+
#endif
|
3417
|
+
|
3418
|
+
|
3185
3419
|
/**************************************************************************
|
3186
3420
|
* LARGE OBJECT SUPPORT
|
3187
3421
|
**************************************************************************/
|
3188
3422
|
|
3189
3423
|
/*
|
3190
3424
|
* call-seq:
|
3191
|
-
* conn.lo_creat( [mode] ) ->
|
3425
|
+
* conn.lo_creat( [mode] ) -> Integer
|
3192
3426
|
*
|
3193
3427
|
* Creates a large object with mode _mode_. Returns a large object Oid.
|
3194
3428
|
* On failure, it raises PG::Error.
|
@@ -3215,7 +3449,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
3215
3449
|
|
3216
3450
|
/*
|
3217
3451
|
* call-seq:
|
3218
|
-
* conn.lo_create( oid ) ->
|
3452
|
+
* conn.lo_create( oid ) -> Integer
|
3219
3453
|
*
|
3220
3454
|
* Creates a large object with oid _oid_. Returns the large object Oid.
|
3221
3455
|
* On failure, it raises PG::Error.
|
@@ -3236,7 +3470,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
|
3236
3470
|
|
3237
3471
|
/*
|
3238
3472
|
* call-seq:
|
3239
|
-
* conn.lo_import(file) ->
|
3473
|
+
* conn.lo_import(file) -> Integer
|
3240
3474
|
*
|
3241
3475
|
* Import a file to a large object. Returns a large object Oid.
|
3242
3476
|
*
|
@@ -3281,7 +3515,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
3281
3515
|
|
3282
3516
|
/*
|
3283
3517
|
* call-seq:
|
3284
|
-
* conn.lo_open( oid, [mode] ) ->
|
3518
|
+
* conn.lo_open( oid, [mode] ) -> Integer
|
3285
3519
|
*
|
3286
3520
|
* Open a large object of _oid_. Returns a large object descriptor
|
3287
3521
|
* instance on success. The _mode_ argument specifies the mode for
|
@@ -3312,7 +3546,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
3312
3546
|
|
3313
3547
|
/*
|
3314
3548
|
* call-seq:
|
3315
|
-
* conn.lo_write( lo_desc, buffer ) ->
|
3549
|
+
* conn.lo_write( lo_desc, buffer ) -> Integer
|
3316
3550
|
*
|
3317
3551
|
* Writes the string _buffer_ to the large object _lo_desc_.
|
3318
3552
|
* Returns the number of bytes written.
|
@@ -3379,7 +3613,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3379
3613
|
|
3380
3614
|
/*
|
3381
3615
|
* call-seq:
|
3382
|
-
* conn.lo_lseek( lo_desc, offset, whence ) ->
|
3616
|
+
* conn.lo_lseek( lo_desc, offset, whence ) -> Integer
|
3383
3617
|
*
|
3384
3618
|
* Move the large object pointer _lo_desc_ to offset _offset_.
|
3385
3619
|
* Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
|
@@ -3401,7 +3635,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
3401
3635
|
|
3402
3636
|
/*
|
3403
3637
|
* call-seq:
|
3404
|
-
* conn.lo_tell( lo_desc ) ->
|
3638
|
+
* conn.lo_tell( lo_desc ) -> Integer
|
3405
3639
|
*
|
3406
3640
|
* Returns the current position of the large object _lo_desc_.
|
3407
3641
|
*/
|
@@ -3474,8 +3708,6 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3474
3708
|
}
|
3475
3709
|
|
3476
3710
|
|
3477
|
-
#ifdef M17N_SUPPORTED
|
3478
|
-
|
3479
3711
|
void
|
3480
3712
|
pgconn_set_internal_encoding_index( VALUE self )
|
3481
3713
|
{
|
@@ -3537,7 +3769,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3537
3769
|
rb_encoding *rbenc = rb_to_encoding( enc );
|
3538
3770
|
const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
|
3539
3771
|
|
3540
|
-
if (
|
3772
|
+
if ( gvl_PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
|
3541
3773
|
VALUE server_encoding = pgconn_external_encoding( self );
|
3542
3774
|
rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
|
3543
3775
|
rb_enc_name(rb_to_encoding(server_encoding)), name );
|
@@ -3579,6 +3811,34 @@ pgconn_external_encoding(VALUE self)
|
|
3579
3811
|
}
|
3580
3812
|
|
3581
3813
|
|
3814
|
+
static VALUE
|
3815
|
+
pgconn_set_client_encoding_async1( VALUE args )
|
3816
|
+
{
|
3817
|
+
VALUE self = ((VALUE*)args)[0];
|
3818
|
+
VALUE encname = ((VALUE*)args)[1];
|
3819
|
+
VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
3820
|
+
VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
3821
|
+
|
3822
|
+
pgconn_async_exec(1, &query, self);
|
3823
|
+
return 0;
|
3824
|
+
}
|
3825
|
+
|
3826
|
+
|
3827
|
+
static VALUE
|
3828
|
+
pgconn_set_client_encoding_async2( VALUE arg )
|
3829
|
+
{
|
3830
|
+
UNUSED(arg);
|
3831
|
+
return 1;
|
3832
|
+
}
|
3833
|
+
|
3834
|
+
|
3835
|
+
static VALUE
|
3836
|
+
pgconn_set_client_encoding_async( VALUE self, const char *encname )
|
3837
|
+
{
|
3838
|
+
VALUE args[] = { self, rb_str_new_cstr(encname) };
|
3839
|
+
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
3840
|
+
}
|
3841
|
+
|
3582
3842
|
|
3583
3843
|
/*
|
3584
3844
|
* call-seq:
|
@@ -3597,8 +3857,8 @@ pgconn_set_default_encoding( VALUE self )
|
|
3597
3857
|
|
3598
3858
|
if (( enc = rb_default_internal_encoding() )) {
|
3599
3859
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3600
|
-
if (
|
3601
|
-
|
3860
|
+
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
3861
|
+
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
3602
3862
|
encname, PQerrorMessage(conn) );
|
3603
3863
|
pgconn_set_internal_encoding_index( self );
|
3604
3864
|
return rb_enc_from_encoding( enc );
|
@@ -3609,8 +3869,6 @@ pgconn_set_default_encoding( VALUE self )
|
|
3609
3869
|
}
|
3610
3870
|
|
3611
3871
|
|
3612
|
-
#endif /* M17N_SUPPORTED */
|
3613
|
-
|
3614
3872
|
/*
|
3615
3873
|
* call-seq:
|
3616
3874
|
* res.type_map_for_queries = typemap
|
@@ -3729,7 +3987,7 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
|
|
3729
3987
|
*
|
3730
3988
|
* Returns either:
|
3731
3989
|
* * a kind of PG::Coder
|
3732
|
-
* * +nil+ - type encoding is disabled,
|
3990
|
+
* * +nil+ - type encoding is disabled, data must be a String.
|
3733
3991
|
*
|
3734
3992
|
*/
|
3735
3993
|
static VALUE
|
@@ -3789,7 +4047,24 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
3789
4047
|
return this->decoder_for_get_copy_data;
|
3790
4048
|
}
|
3791
4049
|
|
4050
|
+
/*
|
4051
|
+
* call-seq:
|
4052
|
+
* res.guess_result_memsize = enabled
|
4053
|
+
*
|
4054
|
+
* This method is for testing only and will probably be removed in the future.
|
4055
|
+
*/
|
4056
|
+
static VALUE
|
4057
|
+
pgconn_guess_result_memsize_set(VALUE self, VALUE enable)
|
4058
|
+
{
|
4059
|
+
t_pg_connection *this = pg_get_connection( self );
|
4060
|
+
this->guess_result_memsize = RTEST(enable);
|
4061
|
+
return enable;
|
4062
|
+
}
|
3792
4063
|
|
4064
|
+
|
4065
|
+
/*
|
4066
|
+
* Document-class: PG::Connection
|
4067
|
+
*/
|
3793
4068
|
void
|
3794
4069
|
init_pg_connection()
|
3795
4070
|
{
|
@@ -3816,9 +4091,7 @@ init_pg_connection()
|
|
3816
4091
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
3817
4092
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
3818
4093
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
3819
|
-
#ifdef HAVE_PQPING
|
3820
4094
|
rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
|
3821
|
-
#endif
|
3822
4095
|
|
3823
4096
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
3824
4097
|
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
@@ -3835,9 +4108,6 @@ init_pg_connection()
|
|
3835
4108
|
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
3836
4109
|
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
3837
4110
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
3838
|
-
#ifdef HAVE_PQHOSTADDR
|
3839
|
-
rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
|
3840
|
-
#endif
|
3841
4111
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
3842
4112
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
3843
4113
|
#ifdef HAVE_PQCONNINFO
|
@@ -3851,43 +4121,42 @@ init_pg_connection()
|
|
3851
4121
|
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
3852
4122
|
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
3853
4123
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
3854
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
3855
4124
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
3856
|
-
#endif
|
3857
4125
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
3858
4126
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
3859
4127
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
3860
4128
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
3861
4129
|
|
3862
4130
|
/****** PG::Connection INSTANCE METHODS: Command Execution ******/
|
3863
|
-
rb_define_method(rb_cPGconn, "
|
3864
|
-
|
3865
|
-
rb_define_method(rb_cPGconn, "
|
3866
|
-
rb_define_method(rb_cPGconn, "
|
3867
|
-
rb_define_method(rb_cPGconn, "
|
3868
|
-
rb_define_method(rb_cPGconn, "
|
3869
|
-
rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
|
4131
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
|
4132
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
|
4133
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
|
4134
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
|
4135
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
|
4136
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
|
3870
4137
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
3871
4138
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
3872
4139
|
rb_define_alias(rb_cPGconn, "escape", "escape_string");
|
3873
|
-
#ifdef HAVE_PQESCAPELITERAL
|
3874
4140
|
rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
|
3875
|
-
#endif
|
3876
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
3877
4141
|
rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
|
3878
|
-
#endif
|
3879
4142
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
3880
4143
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
3881
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
3882
4144
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
3883
|
-
#endif
|
3884
4145
|
|
3885
4146
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
3886
4147
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
4148
|
+
rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
|
4149
|
+
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
4150
|
+
rb_define_method(rb_cPGconn, "async_exec_params", pgconn_async_exec_params, -1);
|
4151
|
+
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
3887
4152
|
rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
|
4153
|
+
rb_define_method(rb_cPGconn, "async_prepare", pgconn_async_prepare, -1);
|
3888
4154
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4155
|
+
rb_define_method(rb_cPGconn, "async_exec_prepared", pgconn_async_exec_prepared, -1);
|
3889
4156
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4157
|
+
rb_define_method(rb_cPGconn, "async_describe_prepared", pgconn_async_describe_prepared, 1);
|
3890
4158
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4159
|
+
rb_define_method(rb_cPGconn, "async_describe_portal", pgconn_async_describe_portal, 1);
|
3891
4160
|
rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
|
3892
4161
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
3893
4162
|
rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
|
@@ -3895,6 +4164,7 @@ init_pg_connection()
|
|
3895
4164
|
rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
|
3896
4165
|
rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
|
3897
4166
|
rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
|
4167
|
+
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
3898
4168
|
|
3899
4169
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
3900
4170
|
rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
|
@@ -3911,6 +4181,7 @@ init_pg_connection()
|
|
3911
4181
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
3912
4182
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
3913
4183
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4184
|
+
rb_define_method(rb_cPGconn, "guess_result_memsize=", pgconn_guess_result_memsize_set, 1);
|
3914
4185
|
|
3915
4186
|
/****** PG::Connection INSTANCE METHODS: Notice Processing ******/
|
3916
4187
|
rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
|
@@ -3925,9 +4196,16 @@ init_pg_connection()
|
|
3925
4196
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
3926
4197
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
3927
4198
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
3928
|
-
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
3929
|
-
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
3930
4199
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
|
4200
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4201
|
+
rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
|
4202
|
+
#endif
|
4203
|
+
|
4204
|
+
#ifdef HAVE_PQSSLATTRIBUTE
|
4205
|
+
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
4206
|
+
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
4207
|
+
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4208
|
+
#endif
|
3931
4209
|
|
3932
4210
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
3933
4211
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
@@ -3957,12 +4235,10 @@ init_pg_connection()
|
|
3957
4235
|
rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
|
3958
4236
|
rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
|
3959
4237
|
|
3960
|
-
#ifdef M17N_SUPPORTED
|
3961
4238
|
rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
|
3962
4239
|
rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
|
3963
4240
|
rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
|
3964
4241
|
rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
|
3965
|
-
#endif /* M17N_SUPPORTED */
|
3966
4242
|
|
3967
4243
|
rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
|
3968
4244
|
rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
|