pg 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +1 -1
- data/.github/workflows/binary-gems.yml +3 -3
- data/.github/workflows/source-gem.yml +5 -6
- data/History.rdoc +98 -1
- data/Rakefile.cross +4 -2
- data/certs/larskanis-2022.pem +26 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/extconf.rb +13 -10
- data/ext/pg.h +1 -0
- data/ext/pg_connection.c +228 -212
- data/ext/pg_record_coder.c +6 -4
- data/ext/pg_result.c +16 -9
- data/ext/pg_tuple.c +2 -8
- data/ext/pg_type_map_all_strings.c +1 -0
- data/ext/pg_type_map_by_column.c +2 -0
- data/lib/pg/basic_type_registry.rb +8 -3
- data/lib/pg/connection.rb +178 -120
- data/lib/pg/exceptions.rb +7 -1
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +9 -7
- data/misc/openssl-pg-segfault.rb +0 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +0 -0
- data/sample/async_api.rb +3 -7
- data/sample/async_copyto.rb +0 -0
- data/sample/async_mixed.rb +0 -0
- data/sample/check_conn.rb +0 -0
- data/sample/copydata.rb +0 -0
- data/sample/copyfrom.rb +0 -0
- data/sample/copyto.rb +0 -0
- data/sample/cursor.rb +0 -0
- data/sample/disk_usage_report.rb +0 -0
- data/sample/issue-119.rb +0 -0
- data/sample/losample.rb +0 -0
- data/sample/minimal-testcase.rb +0 -0
- data/sample/notify_wait.rb +0 -0
- data/sample/pg_statistics.rb +0 -0
- data/sample/replication_monitor.rb +0 -0
- data/sample/test_binary_values.rb +0 -0
- data/sample/wal_shipper.rb +0 -0
- data/sample/warehouse_partitions.rb +0 -0
- data.tar.gz.sig +0 -0
- metadata +32 -28
- metadata.gz.sig +0 -0
data/ext/pg_connection.c
CHANGED
|
@@ -24,11 +24,32 @@ static VALUE pgconn_set_default_encoding( VALUE self );
|
|
|
24
24
|
static VALUE pgconn_wait_for_flush( VALUE self );
|
|
25
25
|
static void pgconn_set_internal_encoding_index( VALUE );
|
|
26
26
|
static const rb_data_type_t pg_connection_type;
|
|
27
|
+
static VALUE pgconn_async_flush(VALUE self);
|
|
27
28
|
|
|
28
29
|
/*
|
|
29
30
|
* Global functions
|
|
30
31
|
*/
|
|
31
32
|
|
|
33
|
+
/*
|
|
34
|
+
* Convenience function to raise connection errors
|
|
35
|
+
*/
|
|
36
|
+
#ifdef __GNUC__
|
|
37
|
+
__attribute__((format(printf, 3, 4)))
|
|
38
|
+
#endif
|
|
39
|
+
static void
|
|
40
|
+
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
|
41
|
+
{
|
|
42
|
+
VALUE msg, error;
|
|
43
|
+
va_list ap;
|
|
44
|
+
|
|
45
|
+
va_start(ap, format);
|
|
46
|
+
msg = rb_vsprintf(format, ap);
|
|
47
|
+
va_end(ap);
|
|
48
|
+
error = rb_exc_new_str(klass, msg);
|
|
49
|
+
rb_iv_set(error, "@connection", self);
|
|
50
|
+
rb_exc_raise(error);
|
|
51
|
+
}
|
|
52
|
+
|
|
32
53
|
/*
|
|
33
54
|
* Fetch the PG::Connection object data pointer.
|
|
34
55
|
*/
|
|
@@ -52,7 +73,7 @@ pg_get_connection_safe( VALUE self )
|
|
|
52
73
|
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
53
74
|
|
|
54
75
|
if ( !this->pgconn )
|
|
55
|
-
|
|
76
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
|
56
77
|
|
|
57
78
|
return this;
|
|
58
79
|
}
|
|
@@ -70,8 +91,9 @@ pg_get_pgconn( VALUE self )
|
|
|
70
91
|
t_pg_connection *this;
|
|
71
92
|
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
72
93
|
|
|
73
|
-
if ( !this->pgconn )
|
|
74
|
-
|
|
94
|
+
if ( !this->pgconn ){
|
|
95
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
|
96
|
+
}
|
|
75
97
|
|
|
76
98
|
return this->pgconn;
|
|
77
99
|
}
|
|
@@ -89,9 +111,8 @@ pgconn_close_socket_io( VALUE self )
|
|
|
89
111
|
|
|
90
112
|
if ( RTEST(socket_io) ) {
|
|
91
113
|
#if defined(_WIN32)
|
|
92
|
-
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
|
93
|
-
|
|
94
|
-
}
|
|
114
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
|
115
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
|
95
116
|
#endif
|
|
96
117
|
rb_funcall( socket_io, rb_intern("close"), 0 );
|
|
97
118
|
}
|
|
@@ -254,7 +275,6 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
|
254
275
|
{
|
|
255
276
|
t_pg_connection *this;
|
|
256
277
|
VALUE conninfo;
|
|
257
|
-
VALUE error;
|
|
258
278
|
VALUE self = pgconn_s_allocate( klass );
|
|
259
279
|
|
|
260
280
|
this = pg_get_connection( self );
|
|
@@ -262,13 +282,10 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
|
262
282
|
this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
|
|
263
283
|
|
|
264
284
|
if(this->pgconn == NULL)
|
|
265
|
-
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
|
|
285
|
+
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
|
|
266
286
|
|
|
267
|
-
if (PQstatus(this->pgconn) == CONNECTION_BAD)
|
|
268
|
-
|
|
269
|
-
rb_iv_set(error, "@connection", self);
|
|
270
|
-
rb_exc_raise(error);
|
|
271
|
-
}
|
|
287
|
+
if (PQstatus(this->pgconn) == CONNECTION_BAD)
|
|
288
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
|
|
272
289
|
|
|
273
290
|
pgconn_set_default_encoding( self );
|
|
274
291
|
|
|
@@ -301,7 +318,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
301
318
|
{
|
|
302
319
|
VALUE rb_conn;
|
|
303
320
|
VALUE conninfo;
|
|
304
|
-
VALUE error;
|
|
305
321
|
t_pg_connection *this;
|
|
306
322
|
|
|
307
323
|
/*
|
|
@@ -314,13 +330,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
314
330
|
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
|
315
331
|
|
|
316
332
|
if( this->pgconn == NULL )
|
|
317
|
-
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
|
|
333
|
+
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
|
318
334
|
|
|
319
|
-
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
|
320
|
-
|
|
321
|
-
rb_iv_set(error, "@connection", rb_conn);
|
|
322
|
-
rb_exc_raise(error);
|
|
323
|
-
}
|
|
335
|
+
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
|
336
|
+
pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
|
|
324
337
|
|
|
325
338
|
if ( rb_block_given_p() ) {
|
|
326
339
|
return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
|
|
@@ -376,6 +389,36 @@ pgconn_s_conndefaults(VALUE self)
|
|
|
376
389
|
return array;
|
|
377
390
|
}
|
|
378
391
|
|
|
392
|
+
/*
|
|
393
|
+
* Document-method: PG::Connection.conninfo_parse
|
|
394
|
+
*
|
|
395
|
+
* call-seq:
|
|
396
|
+
* PG::Connection.conninfo_parse(conninfo_string) -> Array
|
|
397
|
+
*
|
|
398
|
+
* Returns parsed connection options from the provided connection string as an array of hashes.
|
|
399
|
+
* Each hash has the same keys as PG::Connection.conndefaults() .
|
|
400
|
+
* The values from the +conninfo_string+ are stored in the +:val+ key.
|
|
401
|
+
*/
|
|
402
|
+
static VALUE
|
|
403
|
+
pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
|
|
404
|
+
{
|
|
405
|
+
VALUE array;
|
|
406
|
+
char *errmsg = NULL;
|
|
407
|
+
PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
|
|
408
|
+
if(errmsg){
|
|
409
|
+
VALUE error = rb_str_new_cstr(errmsg);
|
|
410
|
+
PQfreemem(errmsg);
|
|
411
|
+
rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
|
|
412
|
+
}
|
|
413
|
+
array = pgconn_make_conninfo_array( options );
|
|
414
|
+
|
|
415
|
+
PQconninfoFree(options);
|
|
416
|
+
|
|
417
|
+
UNUSED( self );
|
|
418
|
+
|
|
419
|
+
return array;
|
|
420
|
+
}
|
|
421
|
+
|
|
379
422
|
|
|
380
423
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
|
381
424
|
static VALUE
|
|
@@ -396,7 +439,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
|
396
439
|
rval = rb_str_new2( encrypted );
|
|
397
440
|
PQfreemem( encrypted );
|
|
398
441
|
} else {
|
|
399
|
-
|
|
442
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
400
443
|
}
|
|
401
444
|
|
|
402
445
|
return rval;
|
|
@@ -450,17 +493,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
|
450
493
|
* the asynchronous connection is ready
|
|
451
494
|
*
|
|
452
495
|
* Example:
|
|
453
|
-
*
|
|
454
|
-
*
|
|
496
|
+
* require "io/wait"
|
|
497
|
+
*
|
|
498
|
+
* conn = PG::Connection.connect_start(dbname: 'mydatabase')
|
|
455
499
|
* status = conn.connect_poll
|
|
456
500
|
* while(status != PG::PGRES_POLLING_OK) do
|
|
457
501
|
* # do some work while waiting for the connection to complete
|
|
458
502
|
* if(status == PG::PGRES_POLLING_READING)
|
|
459
|
-
*
|
|
503
|
+
* unless conn.socket_io.wait_readable(10.0)
|
|
460
504
|
* raise "Asynchronous connection timed out!"
|
|
461
505
|
* end
|
|
462
506
|
* elsif(status == PG::PGRES_POLLING_WRITING)
|
|
463
|
-
*
|
|
507
|
+
* unless conn.socket_io.wait_writable(10.0)
|
|
464
508
|
* raise "Asynchronous connection timed out!"
|
|
465
509
|
* end
|
|
466
510
|
* end
|
|
@@ -475,9 +519,7 @@ pgconn_connect_poll(VALUE self)
|
|
|
475
519
|
PostgresPollingStatusType status;
|
|
476
520
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
|
477
521
|
|
|
478
|
-
|
|
479
|
-
pgconn_close_socket_io(self);
|
|
480
|
-
}
|
|
522
|
+
pgconn_close_socket_io(self);
|
|
481
523
|
|
|
482
524
|
return INT2FIX((int)status);
|
|
483
525
|
}
|
|
@@ -538,7 +580,7 @@ pgconn_reset_start(VALUE self)
|
|
|
538
580
|
{
|
|
539
581
|
pgconn_close_socket_io( self );
|
|
540
582
|
if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
|
|
541
|
-
|
|
583
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
|
|
542
584
|
return Qnil;
|
|
543
585
|
}
|
|
544
586
|
|
|
@@ -556,9 +598,7 @@ pgconn_reset_poll(VALUE self)
|
|
|
556
598
|
PostgresPollingStatusType status;
|
|
557
599
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
|
558
600
|
|
|
559
|
-
|
|
560
|
-
pgconn_close_socket_io(self);
|
|
561
|
-
}
|
|
601
|
+
pgconn_close_socket_io(self);
|
|
562
602
|
|
|
563
603
|
return INT2FIX((int)status);
|
|
564
604
|
}
|
|
@@ -610,7 +650,18 @@ pgconn_pass(VALUE self)
|
|
|
610
650
|
* call-seq:
|
|
611
651
|
* conn.host()
|
|
612
652
|
*
|
|
613
|
-
* Returns the
|
|
653
|
+
* Returns the server host name of the active connection.
|
|
654
|
+
* This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
|
|
655
|
+
* (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
|
|
656
|
+
*
|
|
657
|
+
* If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
|
|
658
|
+
* If only hostaddr was specified, then that is returned.
|
|
659
|
+
* If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
|
|
660
|
+
*
|
|
661
|
+
* If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
|
|
662
|
+
*
|
|
663
|
+
* If multiple hosts were specified in the connection parameters, it is not possible to rely on the result of +host+ until the connection is established.
|
|
664
|
+
* The status of the connection can be checked using the function Connection#status .
|
|
614
665
|
*/
|
|
615
666
|
static VALUE
|
|
616
667
|
pgconn_host(VALUE self)
|
|
@@ -620,6 +671,26 @@ pgconn_host(VALUE self)
|
|
|
620
671
|
return rb_str_new2(host);
|
|
621
672
|
}
|
|
622
673
|
|
|
674
|
+
/* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
|
|
675
|
+
#if defined(HAVE_PQRESULTMEMORYSIZE)
|
|
676
|
+
/*
|
|
677
|
+
* call-seq:
|
|
678
|
+
* conn.hostaddr()
|
|
679
|
+
*
|
|
680
|
+
* Returns the server IP address of the active connection.
|
|
681
|
+
* This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
|
|
682
|
+
* If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
|
|
683
|
+
*
|
|
684
|
+
*/
|
|
685
|
+
static VALUE
|
|
686
|
+
pgconn_hostaddr(VALUE self)
|
|
687
|
+
{
|
|
688
|
+
char *host = PQhostaddr(pg_get_pgconn(self));
|
|
689
|
+
if (!host) return Qnil;
|
|
690
|
+
return rb_str_new2(host);
|
|
691
|
+
}
|
|
692
|
+
#endif
|
|
693
|
+
|
|
623
694
|
/*
|
|
624
695
|
* call-seq:
|
|
625
696
|
* conn.port()
|
|
@@ -690,6 +761,9 @@ pgconn_conninfo( VALUE self )
|
|
|
690
761
|
* PG::Constants::CONNECTION_BAD
|
|
691
762
|
*
|
|
692
763
|
* ... and other constants of kind PG::Constants::CONNECTION_*
|
|
764
|
+
*
|
|
765
|
+
* Example:
|
|
766
|
+
* PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
|
|
693
767
|
*/
|
|
694
768
|
static VALUE
|
|
695
769
|
pgconn_status(VALUE self)
|
|
@@ -814,7 +888,8 @@ pgconn_socket(VALUE self)
|
|
|
814
888
|
pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
|
|
815
889
|
|
|
816
890
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
|
817
|
-
|
|
891
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
|
892
|
+
|
|
818
893
|
return INT2NUM(sd);
|
|
819
894
|
}
|
|
820
895
|
|
|
@@ -822,13 +897,15 @@ pgconn_socket(VALUE self)
|
|
|
822
897
|
* call-seq:
|
|
823
898
|
* conn.socket_io() -> IO
|
|
824
899
|
*
|
|
825
|
-
* Fetch
|
|
826
|
-
* This object can be used for IO.select to wait for events while running
|
|
827
|
-
*
|
|
900
|
+
* Fetch an IO object created from the Connection's underlying socket.
|
|
901
|
+
* 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.
|
|
902
|
+
* <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
|
|
903
|
+
*
|
|
904
|
+
* The IO object can change while the connection is established, but is memorized afterwards.
|
|
905
|
+
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
|
828
906
|
*
|
|
829
|
-
* Using this
|
|
830
|
-
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
|
831
|
-
* goes out of scope. In contrast to #socket, it also works on Windows.
|
|
907
|
+
* Using this method also works on Windows in contrast to using #socket .
|
|
908
|
+
* It also avoids the problem of the underlying connection being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt> goes out of scope.
|
|
832
909
|
*/
|
|
833
910
|
static VALUE
|
|
834
911
|
pgconn_socket_io(VALUE self)
|
|
@@ -840,14 +917,15 @@ pgconn_socket_io(VALUE self)
|
|
|
840
917
|
VALUE socket_io = this->socket_io;
|
|
841
918
|
|
|
842
919
|
if ( !RTEST(socket_io) ) {
|
|
843
|
-
if( (sd = PQsocket(this->pgconn)) < 0)
|
|
844
|
-
|
|
920
|
+
if( (sd = PQsocket(this->pgconn)) < 0){
|
|
921
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
|
922
|
+
}
|
|
845
923
|
|
|
846
924
|
#ifdef _WIN32
|
|
847
925
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
|
848
|
-
if( ruby_sd == -1 )
|
|
849
|
-
|
|
850
|
-
|
|
926
|
+
if( ruby_sd == -1 )
|
|
927
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
|
928
|
+
|
|
851
929
|
this->ruby_sd = ruby_sd;
|
|
852
930
|
#else
|
|
853
931
|
ruby_sd = sd;
|
|
@@ -912,7 +990,7 @@ pgconn_backend_key(VALUE self)
|
|
|
912
990
|
|
|
913
991
|
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
|
914
992
|
if(cancel == NULL)
|
|
915
|
-
|
|
993
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
|
916
994
|
|
|
917
995
|
if( cancel->be_pid != PQbackendPID(conn) )
|
|
918
996
|
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
|
@@ -1541,9 +1619,9 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
|
1541
1619
|
if( !singleton ) {
|
|
1542
1620
|
size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
|
|
1543
1621
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
|
1544
|
-
if(error)
|
|
1545
|
-
|
|
1546
|
-
|
|
1622
|
+
if(error)
|
|
1623
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
|
|
1624
|
+
|
|
1547
1625
|
} else {
|
|
1548
1626
|
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
|
1549
1627
|
}
|
|
@@ -1639,7 +1717,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
|
1639
1717
|
{
|
|
1640
1718
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1641
1719
|
char *escaped = NULL;
|
|
1642
|
-
VALUE error;
|
|
1643
1720
|
VALUE result = Qnil;
|
|
1644
1721
|
int enc_idx = this->enc_idx;
|
|
1645
1722
|
|
|
@@ -1650,12 +1727,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
|
1650
1727
|
|
|
1651
1728
|
escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
|
1652
1729
|
if (escaped == NULL)
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
rb_iv_set(error, "@connection", self);
|
|
1656
|
-
rb_exc_raise(error);
|
|
1657
|
-
return Qnil;
|
|
1658
|
-
}
|
|
1730
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
1731
|
+
|
|
1659
1732
|
result = rb_str_new2(escaped);
|
|
1660
1733
|
PQfreemem(escaped);
|
|
1661
1734
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
|
@@ -1678,7 +1751,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
|
1678
1751
|
{
|
|
1679
1752
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1680
1753
|
char *escaped = NULL;
|
|
1681
|
-
VALUE error;
|
|
1682
1754
|
VALUE result = Qnil;
|
|
1683
1755
|
int enc_idx = this->enc_idx;
|
|
1684
1756
|
|
|
@@ -1689,12 +1761,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
|
1689
1761
|
|
|
1690
1762
|
escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
|
1691
1763
|
if (escaped == NULL)
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
rb_iv_set(error, "@connection", self);
|
|
1695
|
-
rb_exc_raise(error);
|
|
1696
|
-
return Qnil;
|
|
1697
|
-
}
|
|
1764
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
1765
|
+
|
|
1698
1766
|
result = rb_str_new2(escaped);
|
|
1699
1767
|
PQfreemem(escaped);
|
|
1700
1768
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
|
@@ -1742,14 +1810,9 @@ static VALUE
|
|
|
1742
1810
|
pgconn_set_single_row_mode(VALUE self)
|
|
1743
1811
|
{
|
|
1744
1812
|
PGconn *conn = pg_get_pgconn(self);
|
|
1745
|
-
VALUE error;
|
|
1746
1813
|
|
|
1747
1814
|
if( PQsetSingleRowMode(conn) == 0 )
|
|
1748
|
-
|
|
1749
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
|
1750
|
-
rb_iv_set(error, "@connection", self);
|
|
1751
|
-
rb_exc_raise(error);
|
|
1752
|
-
}
|
|
1815
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
1753
1816
|
|
|
1754
1817
|
return self;
|
|
1755
1818
|
}
|
|
@@ -1773,15 +1836,12 @@ static VALUE
|
|
|
1773
1836
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1774
1837
|
{
|
|
1775
1838
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1776
|
-
VALUE error;
|
|
1777
1839
|
|
|
1778
1840
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
|
1779
1841
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
|
1780
|
-
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
rb_exc_raise(error);
|
|
1784
|
-
}
|
|
1842
|
+
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
|
1843
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
1844
|
+
|
|
1785
1845
|
pgconn_wait_for_flush( self );
|
|
1786
1846
|
return Qnil;
|
|
1787
1847
|
}
|
|
@@ -1838,7 +1898,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1838
1898
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1839
1899
|
int result;
|
|
1840
1900
|
VALUE command, in_res_fmt;
|
|
1841
|
-
VALUE error;
|
|
1842
1901
|
int nParams;
|
|
1843
1902
|
int resultFormat;
|
|
1844
1903
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1855,11 +1914,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
1855
1914
|
|
|
1856
1915
|
free_query_params( ¶msData );
|
|
1857
1916
|
|
|
1858
|
-
if(result == 0)
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
rb_exc_raise(error);
|
|
1862
|
-
}
|
|
1917
|
+
if(result == 0)
|
|
1918
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
1919
|
+
|
|
1863
1920
|
pgconn_wait_for_flush( self );
|
|
1864
1921
|
return Qnil;
|
|
1865
1922
|
}
|
|
@@ -1891,7 +1948,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1891
1948
|
int result;
|
|
1892
1949
|
VALUE name, command, in_paramtypes;
|
|
1893
1950
|
VALUE param;
|
|
1894
|
-
VALUE error;
|
|
1895
1951
|
int i = 0;
|
|
1896
1952
|
int nParams = 0;
|
|
1897
1953
|
Oid *paramTypes = NULL;
|
|
@@ -1920,9 +1976,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1920
1976
|
xfree(paramTypes);
|
|
1921
1977
|
|
|
1922
1978
|
if(result == 0) {
|
|
1923
|
-
|
|
1924
|
-
rb_iv_set(error, "@connection", self);
|
|
1925
|
-
rb_exc_raise(error);
|
|
1979
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
1926
1980
|
}
|
|
1927
1981
|
pgconn_wait_for_flush( self );
|
|
1928
1982
|
return Qnil;
|
|
@@ -1966,7 +2020,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1966
2020
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1967
2021
|
int result;
|
|
1968
2022
|
VALUE name, in_res_fmt;
|
|
1969
|
-
VALUE error;
|
|
1970
2023
|
int nParams;
|
|
1971
2024
|
int resultFormat;
|
|
1972
2025
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1988,11 +2041,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1988
2041
|
|
|
1989
2042
|
free_query_params( ¶msData );
|
|
1990
2043
|
|
|
1991
|
-
if(result == 0)
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
rb_exc_raise(error);
|
|
1995
|
-
}
|
|
2044
|
+
if(result == 0)
|
|
2045
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2046
|
+
|
|
1996
2047
|
pgconn_wait_for_flush( self );
|
|
1997
2048
|
return Qnil;
|
|
1998
2049
|
}
|
|
@@ -2007,14 +2058,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2007
2058
|
static VALUE
|
|
2008
2059
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2009
2060
|
{
|
|
2010
|
-
VALUE error;
|
|
2011
2061
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2012
2062
|
/* returns 0 on failure */
|
|
2013
|
-
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
rb_exc_raise(error);
|
|
2017
|
-
}
|
|
2063
|
+
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
|
2064
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2065
|
+
|
|
2018
2066
|
pgconn_wait_for_flush( self );
|
|
2019
2067
|
return Qnil;
|
|
2020
2068
|
}
|
|
@@ -2030,14 +2078,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
2030
2078
|
static VALUE
|
|
2031
2079
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
2032
2080
|
{
|
|
2033
|
-
VALUE error;
|
|
2034
2081
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2035
2082
|
/* returns 0 on failure */
|
|
2036
|
-
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
rb_exc_raise(error);
|
|
2040
|
-
}
|
|
2083
|
+
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
|
2084
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
|
2085
|
+
|
|
2041
2086
|
pgconn_wait_for_flush( self );
|
|
2042
2087
|
return Qnil;
|
|
2043
2088
|
}
|
|
@@ -2070,18 +2115,15 @@ pgconn_sync_get_result(VALUE self)
|
|
|
2070
2115
|
* or *notifies* to see if the state has changed.
|
|
2071
2116
|
*/
|
|
2072
2117
|
static VALUE
|
|
2073
|
-
pgconn_consume_input(self)
|
|
2074
|
-
VALUE self;
|
|
2118
|
+
pgconn_consume_input(VALUE self)
|
|
2075
2119
|
{
|
|
2076
|
-
VALUE error;
|
|
2077
2120
|
PGconn *conn = pg_get_pgconn(self);
|
|
2078
2121
|
/* returns 0 on error */
|
|
2079
2122
|
if(PQconsumeInput(conn) == 0) {
|
|
2080
2123
|
pgconn_close_socket_io(self);
|
|
2081
|
-
|
|
2082
|
-
rb_iv_set(error, "@connection", self);
|
|
2083
|
-
rb_exc_raise(error);
|
|
2124
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
|
|
2084
2125
|
}
|
|
2126
|
+
|
|
2085
2127
|
return Qnil;
|
|
2086
2128
|
}
|
|
2087
2129
|
|
|
@@ -2093,18 +2135,15 @@ pgconn_consume_input(self)
|
|
|
2093
2135
|
* #get_result would block. Otherwise returns +false+.
|
|
2094
2136
|
*/
|
|
2095
2137
|
static VALUE
|
|
2096
|
-
pgconn_is_busy(self)
|
|
2097
|
-
VALUE self;
|
|
2138
|
+
pgconn_is_busy(VALUE self)
|
|
2098
2139
|
{
|
|
2099
2140
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2100
2141
|
}
|
|
2101
2142
|
|
|
2102
2143
|
static VALUE
|
|
2103
|
-
pgconn_sync_setnonblocking(self, state)
|
|
2104
|
-
VALUE self, state;
|
|
2144
|
+
pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
|
2105
2145
|
{
|
|
2106
2146
|
int arg;
|
|
2107
|
-
VALUE error;
|
|
2108
2147
|
PGconn *conn = pg_get_pgconn(self);
|
|
2109
2148
|
if(state == Qtrue)
|
|
2110
2149
|
arg = 1;
|
|
@@ -2113,18 +2152,15 @@ pgconn_sync_setnonblocking(self, state)
|
|
|
2113
2152
|
else
|
|
2114
2153
|
rb_raise(rb_eArgError, "Boolean value expected");
|
|
2115
2154
|
|
|
2116
|
-
if(PQsetnonblocking(conn, arg) == -1)
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
rb_exc_raise(error);
|
|
2120
|
-
}
|
|
2155
|
+
if(PQsetnonblocking(conn, arg) == -1)
|
|
2156
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2157
|
+
|
|
2121
2158
|
return Qnil;
|
|
2122
2159
|
}
|
|
2123
2160
|
|
|
2124
2161
|
|
|
2125
2162
|
static VALUE
|
|
2126
|
-
pgconn_sync_isnonblocking(self)
|
|
2127
|
-
VALUE self;
|
|
2163
|
+
pgconn_sync_isnonblocking(VALUE self)
|
|
2128
2164
|
{
|
|
2129
2165
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2130
2166
|
}
|
|
@@ -2133,14 +2169,10 @@ static VALUE
|
|
|
2133
2169
|
pgconn_sync_flush(VALUE self)
|
|
2134
2170
|
{
|
|
2135
2171
|
PGconn *conn = pg_get_pgconn(self);
|
|
2136
|
-
int ret;
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
|
2141
|
-
rb_iv_set(error, "@connection", self);
|
|
2142
|
-
rb_exc_raise(error);
|
|
2143
|
-
}
|
|
2172
|
+
int ret = PQflush(conn);
|
|
2173
|
+
if(ret == -1)
|
|
2174
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2175
|
+
|
|
2144
2176
|
return (ret) ? Qfalse : Qtrue;
|
|
2145
2177
|
}
|
|
2146
2178
|
|
|
@@ -2154,7 +2186,7 @@ pgconn_sync_cancel(VALUE self)
|
|
|
2154
2186
|
|
|
2155
2187
|
cancel = PQgetCancel(pg_get_pgconn(self));
|
|
2156
2188
|
if(cancel == NULL)
|
|
2157
|
-
|
|
2189
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
|
2158
2190
|
|
|
2159
2191
|
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
|
2160
2192
|
if(ret == 1)
|
|
@@ -2241,19 +2273,15 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2241
2273
|
GetOpenFile((io), fptr);
|
|
2242
2274
|
if( !NIL_P(timeout) ){
|
|
2243
2275
|
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2244
|
-
ptimeout.tv_usec = (time_t)(NUM2DBL(timeout) - (double)ptimeout.tv_sec);
|
|
2276
|
+
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
|
2245
2277
|
|
|
2246
2278
|
gettimeofday(&currtime, NULL);
|
|
2247
2279
|
timeradd(&currtime, &ptimeout, &aborttime);
|
|
2248
2280
|
}
|
|
2249
2281
|
|
|
2250
|
-
if(rb_events & PG_RUBY_IO_READABLE)
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
w32_events |= FD_WRITE | FD_CONNECT;
|
|
2254
|
-
} else if(rb_events & PG_RUBY_IO_PRIORITY) {
|
|
2255
|
-
w32_events |= FD_OOB;
|
|
2256
|
-
}
|
|
2282
|
+
if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
|
2283
|
+
if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
|
|
2284
|
+
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
|
2257
2285
|
|
|
2258
2286
|
for(;;) {
|
|
2259
2287
|
if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
|
|
@@ -2336,7 +2364,7 @@ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2336
2364
|
GetOpenFile((io), fptr);
|
|
2337
2365
|
if( !NIL_P(timeout) ){
|
|
2338
2366
|
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2339
|
-
waittime.tv_usec = (time_t)(NUM2DBL(timeout) - (double)waittime.tv_sec);
|
|
2367
|
+
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
|
2340
2368
|
}
|
|
2341
2369
|
res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
|
2342
2370
|
|
|
@@ -2347,21 +2375,12 @@ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2347
2375
|
static void *
|
|
2348
2376
|
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
|
2349
2377
|
{
|
|
2350
|
-
VALUE socket_io;
|
|
2351
2378
|
VALUE ret;
|
|
2352
2379
|
void *retval;
|
|
2353
2380
|
struct timeval aborttime={0,0}, currtime, waittime;
|
|
2354
2381
|
VALUE wait_timeout = Qnil;
|
|
2355
2382
|
PGconn *conn = pg_get_pgconn(self);
|
|
2356
2383
|
|
|
2357
|
-
socket_io = pgconn_socket_io(self);
|
|
2358
|
-
|
|
2359
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
|
2360
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
|
2361
|
-
pgconn_close_socket_io(self);
|
|
2362
|
-
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
|
2363
|
-
}
|
|
2364
|
-
|
|
2365
2384
|
if ( ptimeout ) {
|
|
2366
2385
|
gettimeofday(&currtime, NULL);
|
|
2367
2386
|
timeradd(&currtime, ptimeout, &aborttime);
|
|
@@ -2376,6 +2395,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
|
2376
2395
|
|
|
2377
2396
|
/* Is the given timeout valid? */
|
|
2378
2397
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
|
2398
|
+
VALUE socket_io;
|
|
2399
|
+
|
|
2400
|
+
/* before we wait for data, make sure everything has been sent */
|
|
2401
|
+
pgconn_async_flush(self);
|
|
2402
|
+
if ((retval=is_readable(conn)))
|
|
2403
|
+
return retval;
|
|
2404
|
+
|
|
2405
|
+
socket_io = pgconn_socket_io(self);
|
|
2379
2406
|
/* Wait for the socket to become readable before checking again */
|
|
2380
2407
|
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
|
2381
2408
|
} else {
|
|
@@ -2390,7 +2417,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
|
2390
2417
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
|
2391
2418
|
if ( PQconsumeInput(conn) == 0 ){
|
|
2392
2419
|
pgconn_close_socket_io(self);
|
|
2393
|
-
|
|
2420
|
+
pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
|
|
2394
2421
|
}
|
|
2395
2422
|
}
|
|
2396
2423
|
|
|
@@ -2403,8 +2430,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
|
2403
2430
|
*
|
|
2404
2431
|
* Attempts to flush any queued output data to the server.
|
|
2405
2432
|
* Returns +true+ if data is successfully flushed, +false+
|
|
2406
|
-
* if not
|
|
2407
|
-
* nonblocking.
|
|
2433
|
+
* if not. It can only return +false+ if connection is
|
|
2434
|
+
* in nonblocking mode.
|
|
2408
2435
|
* Raises PG::Error if some other failure occurred.
|
|
2409
2436
|
*/
|
|
2410
2437
|
static VALUE
|
|
@@ -2540,11 +2567,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2540
2567
|
Check_Type(buffer, T_STRING);
|
|
2541
2568
|
|
|
2542
2569
|
ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
|
|
2543
|
-
if(ret == -1)
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
rb_exc_raise(error);
|
|
2547
|
-
}
|
|
2570
|
+
if(ret == -1)
|
|
2571
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2572
|
+
|
|
2548
2573
|
RB_GC_GUARD(intermediate);
|
|
2549
2574
|
RB_GC_GUARD(buffer);
|
|
2550
2575
|
|
|
@@ -2555,7 +2580,6 @@ static VALUE
|
|
|
2555
2580
|
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2556
2581
|
{
|
|
2557
2582
|
VALUE str;
|
|
2558
|
-
VALUE error;
|
|
2559
2583
|
int ret;
|
|
2560
2584
|
const char *error_message = NULL;
|
|
2561
2585
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
@@ -2566,11 +2590,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
|
2566
2590
|
error_message = pg_cstr_enc(str, this->enc_idx);
|
|
2567
2591
|
|
|
2568
2592
|
ret = gvl_PQputCopyEnd(this->pgconn, error_message);
|
|
2569
|
-
if(ret == -1)
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
rb_exc_raise(error);
|
|
2573
|
-
}
|
|
2593
|
+
if(ret == -1)
|
|
2594
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2595
|
+
|
|
2574
2596
|
return (ret) ? Qtrue : Qfalse;
|
|
2575
2597
|
}
|
|
2576
2598
|
|
|
@@ -2578,7 +2600,6 @@ static VALUE
|
|
|
2578
2600
|
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2579
2601
|
{
|
|
2580
2602
|
VALUE async_in;
|
|
2581
|
-
VALUE error;
|
|
2582
2603
|
VALUE result;
|
|
2583
2604
|
int ret;
|
|
2584
2605
|
char *buffer;
|
|
@@ -2598,10 +2619,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2598
2619
|
}
|
|
2599
2620
|
|
|
2600
2621
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
|
2601
|
-
if(ret == -2)
|
|
2602
|
-
|
|
2603
|
-
rb_iv_set(error, "@connection", self);
|
|
2604
|
-
rb_exc_raise(error);
|
|
2622
|
+
if(ret == -2){ /* error */
|
|
2623
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2605
2624
|
}
|
|
2606
2625
|
if(ret == -1) { /* No data left */
|
|
2607
2626
|
return Qnil;
|
|
@@ -2906,9 +2925,9 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
|
2906
2925
|
|
|
2907
2926
|
Check_Type(str, T_STRING);
|
|
2908
2927
|
|
|
2909
|
-
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
2910
|
-
|
|
2911
|
-
|
|
2928
|
+
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
2929
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
2930
|
+
|
|
2912
2931
|
pgconn_set_internal_encoding_index( self );
|
|
2913
2932
|
|
|
2914
2933
|
return Qnil;
|
|
@@ -2988,7 +3007,7 @@ get_result_readable(PGconn *conn)
|
|
|
2988
3007
|
* If +true+ is returned, +conn.is_busy+ will return +false+
|
|
2989
3008
|
* and +conn.get_result+ will not block.
|
|
2990
3009
|
*/
|
|
2991
|
-
|
|
3010
|
+
VALUE
|
|
2992
3011
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
2993
3012
|
struct timeval timeout;
|
|
2994
3013
|
struct timeval *ptimeout = NULL;
|
|
@@ -3076,7 +3095,8 @@ pgconn_async_get_last_result(VALUE self)
|
|
|
3076
3095
|
for(;;) {
|
|
3077
3096
|
int status;
|
|
3078
3097
|
|
|
3079
|
-
|
|
3098
|
+
/* wait for input (without blocking) before reading each result */
|
|
3099
|
+
wait_socket_readable(self, NULL, get_result_readable);
|
|
3080
3100
|
|
|
3081
3101
|
cur = gvl_PQgetResult(conn);
|
|
3082
3102
|
if (cur == NULL)
|
|
@@ -3540,11 +3560,10 @@ pgconn_enter_pipeline_mode(VALUE self)
|
|
|
3540
3560
|
{
|
|
3541
3561
|
PGconn *conn = pg_get_pgconn(self);
|
|
3542
3562
|
int res = PQenterPipelineMode(conn);
|
|
3543
|
-
if( res
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
}
|
|
3563
|
+
if( res != 1 )
|
|
3564
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3565
|
+
|
|
3566
|
+
return Qnil;
|
|
3548
3567
|
}
|
|
3549
3568
|
|
|
3550
3569
|
/*
|
|
@@ -3563,11 +3582,10 @@ pgconn_exit_pipeline_mode(VALUE self)
|
|
|
3563
3582
|
{
|
|
3564
3583
|
PGconn *conn = pg_get_pgconn(self);
|
|
3565
3584
|
int res = PQexitPipelineMode(conn);
|
|
3566
|
-
if( res
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
}
|
|
3585
|
+
if( res != 1 )
|
|
3586
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3587
|
+
|
|
3588
|
+
return Qnil;
|
|
3571
3589
|
}
|
|
3572
3590
|
|
|
3573
3591
|
|
|
@@ -3587,11 +3605,10 @@ pgconn_pipeline_sync(VALUE self)
|
|
|
3587
3605
|
{
|
|
3588
3606
|
PGconn *conn = pg_get_pgconn(self);
|
|
3589
3607
|
int res = PQpipelineSync(conn);
|
|
3590
|
-
if( res
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
}
|
|
3608
|
+
if( res != 1 )
|
|
3609
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3610
|
+
|
|
3611
|
+
return Qnil;
|
|
3595
3612
|
}
|
|
3596
3613
|
|
|
3597
3614
|
/*
|
|
@@ -3611,11 +3628,10 @@ pgconn_send_flush_request(VALUE self)
|
|
|
3611
3628
|
{
|
|
3612
3629
|
PGconn *conn = pg_get_pgconn(self);
|
|
3613
3630
|
int res = PQsendFlushRequest(conn);
|
|
3614
|
-
if( res
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
}
|
|
3631
|
+
if( res != 1 )
|
|
3632
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3633
|
+
|
|
3634
|
+
return Qnil;
|
|
3619
3635
|
}
|
|
3620
3636
|
|
|
3621
3637
|
#endif
|
|
@@ -3646,7 +3662,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
|
3646
3662
|
|
|
3647
3663
|
lo_oid = lo_creat(conn, mode);
|
|
3648
3664
|
if (lo_oid == 0)
|
|
3649
|
-
|
|
3665
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
|
|
3650
3666
|
|
|
3651
3667
|
return UINT2NUM(lo_oid);
|
|
3652
3668
|
}
|
|
@@ -3667,7 +3683,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
|
|
3667
3683
|
|
|
3668
3684
|
ret = lo_create(conn, lo_oid);
|
|
3669
3685
|
if (ret == InvalidOid)
|
|
3670
|
-
|
|
3686
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
|
|
3671
3687
|
|
|
3672
3688
|
return UINT2NUM(ret);
|
|
3673
3689
|
}
|
|
@@ -3691,7 +3707,7 @@ pgconn_loimport(VALUE self, VALUE filename)
|
|
|
3691
3707
|
|
|
3692
3708
|
lo_oid = lo_import(conn, StringValueCStr(filename));
|
|
3693
3709
|
if (lo_oid == 0) {
|
|
3694
|
-
|
|
3710
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3695
3711
|
}
|
|
3696
3712
|
return UINT2NUM(lo_oid);
|
|
3697
3713
|
}
|
|
@@ -3712,7 +3728,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
|
3712
3728
|
oid = NUM2UINT(lo_oid);
|
|
3713
3729
|
|
|
3714
3730
|
if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
|
|
3715
|
-
|
|
3731
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3716
3732
|
}
|
|
3717
3733
|
return Qnil;
|
|
3718
3734
|
}
|
|
@@ -3743,7 +3759,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
|
3743
3759
|
mode = NUM2INT(nmode);
|
|
3744
3760
|
|
|
3745
3761
|
if((fd = lo_open(conn, lo_oid, mode)) < 0) {
|
|
3746
|
-
|
|
3762
|
+
pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
|
|
3747
3763
|
}
|
|
3748
3764
|
return INT2FIX(fd);
|
|
3749
3765
|
}
|
|
@@ -3765,11 +3781,11 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
|
3765
3781
|
Check_Type(buffer, T_STRING);
|
|
3766
3782
|
|
|
3767
3783
|
if( RSTRING_LEN(buffer) < 0) {
|
|
3768
|
-
|
|
3784
|
+
pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
|
|
3769
3785
|
}
|
|
3770
3786
|
if((n = lo_write(conn, fd, StringValuePtr(buffer),
|
|
3771
3787
|
RSTRING_LEN(buffer))) < 0) {
|
|
3772
|
-
|
|
3788
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
|
|
3773
3789
|
}
|
|
3774
3790
|
|
|
3775
3791
|
return INT2FIX(n);
|
|
@@ -3792,16 +3808,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
|
3792
3808
|
VALUE str;
|
|
3793
3809
|
char *buffer;
|
|
3794
3810
|
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
rb_raise(rb_eNoMemError, "ALLOC failed!");
|
|
3798
|
-
|
|
3799
|
-
if (len < 0){
|
|
3800
|
-
rb_raise(rb_ePGerror,"nagative length %d given", len);
|
|
3801
|
-
}
|
|
3811
|
+
if (len < 0)
|
|
3812
|
+
pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
|
|
3802
3813
|
|
|
3814
|
+
buffer = ALLOC_N(char, len);
|
|
3803
3815
|
if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
|
|
3804
|
-
|
|
3816
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
|
|
3805
3817
|
|
|
3806
3818
|
if(ret == 0) {
|
|
3807
3819
|
xfree(buffer);
|
|
@@ -3831,7 +3843,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
|
3831
3843
|
int ret;
|
|
3832
3844
|
|
|
3833
3845
|
if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
|
|
3834
|
-
|
|
3846
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
|
|
3835
3847
|
}
|
|
3836
3848
|
|
|
3837
3849
|
return INT2FIX(ret);
|
|
@@ -3851,7 +3863,7 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
|
|
3851
3863
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3852
3864
|
|
|
3853
3865
|
if((position = lo_tell(conn, lo_desc)) < 0)
|
|
3854
|
-
|
|
3866
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
|
|
3855
3867
|
|
|
3856
3868
|
return INT2FIX(position);
|
|
3857
3869
|
}
|
|
@@ -3870,7 +3882,7 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
|
3870
3882
|
size_t len = NUM2INT(in_len);
|
|
3871
3883
|
|
|
3872
3884
|
if(lo_truncate(conn,lo_desc,len) < 0)
|
|
3873
|
-
|
|
3885
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
|
|
3874
3886
|
|
|
3875
3887
|
return Qnil;
|
|
3876
3888
|
}
|
|
@@ -3888,7 +3900,7 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
|
|
3888
3900
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3889
3901
|
|
|
3890
3902
|
if(lo_close(conn,lo_desc) < 0)
|
|
3891
|
-
|
|
3903
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
|
|
3892
3904
|
|
|
3893
3905
|
return Qnil;
|
|
3894
3906
|
}
|
|
@@ -3906,7 +3918,7 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
|
3906
3918
|
Oid oid = NUM2UINT(in_oid);
|
|
3907
3919
|
|
|
3908
3920
|
if(lo_unlink(conn,oid) < 0)
|
|
3909
|
-
|
|
3921
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
|
|
3910
3922
|
|
|
3911
3923
|
return Qnil;
|
|
3912
3924
|
}
|
|
@@ -4340,6 +4352,7 @@ init_pg_connection()
|
|
|
4340
4352
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
|
4341
4353
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
|
4342
4354
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
|
4355
|
+
rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
|
|
4343
4356
|
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
|
4344
4357
|
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
|
4345
4358
|
|
|
@@ -4357,6 +4370,9 @@ init_pg_connection()
|
|
|
4357
4370
|
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
|
4358
4371
|
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
|
4359
4372
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
|
4373
|
+
#if defined(HAVE_PQRESULTMEMORYSIZE)
|
|
4374
|
+
rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
|
|
4375
|
+
#endif
|
|
4360
4376
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
|
4361
4377
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
|
4362
4378
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|