pg 1.3.4-x86-mingw32 → 1.4.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
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
- rb_raise( rb_eConnectionBad, "connection is closed" );
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
- rb_raise( rb_eConnectionBad, "connection is closed" );
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
- rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
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
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
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
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
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
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
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
- * conn = PG::Connection.connect_start("dbname=mydatabase")
454
- * socket = conn.socket_io
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
- * if(not select([socket], [], [], 10.0))
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
- * if(not select([], [socket], [], 10.0))
507
+ * unless conn.socket_io.wait_writable(10.0)
464
508
  * raise "Asynchronous connection timed out!"
465
509
  * end
466
510
  * end
@@ -536,7 +580,7 @@ pgconn_reset_start(VALUE self)
536
580
  {
537
581
  pgconn_close_socket_io( self );
538
582
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
539
- rb_raise(rb_eUnableToSend, "reset has failed");
583
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
540
584
  return Qnil;
541
585
  }
542
586
 
@@ -606,7 +650,18 @@ pgconn_pass(VALUE self)
606
650
  * call-seq:
607
651
  * conn.host()
608
652
  *
609
- * Returns the connected server name.
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 .
610
665
  */
611
666
  static VALUE
612
667
  pgconn_host(VALUE self)
@@ -616,6 +671,26 @@ pgconn_host(VALUE self)
616
671
  return rb_str_new2(host);
617
672
  }
618
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
+
619
694
  /*
620
695
  * call-seq:
621
696
  * conn.port()
@@ -686,6 +761,9 @@ pgconn_conninfo( VALUE self )
686
761
  * PG::Constants::CONNECTION_BAD
687
762
  *
688
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
689
767
  */
690
768
  static VALUE
691
769
  pgconn_status(VALUE self)
@@ -810,7 +888,8 @@ pgconn_socket(VALUE self)
810
888
  pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
811
889
 
812
890
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
813
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
891
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
892
+
814
893
  return INT2NUM(sd);
815
894
  }
816
895
 
@@ -818,13 +897,15 @@ pgconn_socket(VALUE self)
818
897
  * call-seq:
819
898
  * conn.socket_io() -> IO
820
899
  *
821
- * Fetch a memorized IO object created from the Connection's underlying socket.
822
- * This object can be used for IO.select to wait for events while running
823
- * asynchronous API calls.
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.
824
906
  *
825
- * Using this instead of #socket avoids the problem of the underlying connection
826
- * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
827
- * 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.
828
909
  */
829
910
  static VALUE
830
911
  pgconn_socket_io(VALUE self)
@@ -836,14 +917,15 @@ pgconn_socket_io(VALUE self)
836
917
  VALUE socket_io = this->socket_io;
837
918
 
838
919
  if ( !RTEST(socket_io) ) {
839
- if( (sd = PQsocket(this->pgconn)) < 0)
840
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
920
+ if( (sd = PQsocket(this->pgconn)) < 0){
921
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
922
+ }
841
923
 
842
924
  #ifdef _WIN32
843
925
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
844
- if( ruby_sd == -1 ){
845
- rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
846
- }
926
+ if( ruby_sd == -1 )
927
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
928
+
847
929
  this->ruby_sd = ruby_sd;
848
930
  #else
849
931
  ruby_sd = sd;
@@ -908,7 +990,7 @@ pgconn_backend_key(VALUE self)
908
990
 
909
991
  cancel = (struct pg_cancel*)PQgetCancel(conn);
910
992
  if(cancel == NULL)
911
- rb_raise(rb_ePGerror,"Invalid connection!");
993
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
912
994
 
913
995
  if( cancel->be_pid != PQbackendPID(conn) )
914
996
  rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
@@ -1537,9 +1619,9 @@ pgconn_s_escape(VALUE self, VALUE string)
1537
1619
  if( !singleton ) {
1538
1620
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1539
1621
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1540
- if(error) {
1541
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1542
- }
1622
+ if(error)
1623
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1624
+
1543
1625
  } else {
1544
1626
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1545
1627
  }
@@ -1635,7 +1717,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
1635
1717
  {
1636
1718
  t_pg_connection *this = pg_get_connection_safe( self );
1637
1719
  char *escaped = NULL;
1638
- VALUE error;
1639
1720
  VALUE result = Qnil;
1640
1721
  int enc_idx = this->enc_idx;
1641
1722
 
@@ -1646,12 +1727,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
1646
1727
 
1647
1728
  escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1648
1729
  if (escaped == NULL)
1649
- {
1650
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1651
- rb_iv_set(error, "@connection", self);
1652
- rb_exc_raise(error);
1653
- return Qnil;
1654
- }
1730
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1731
+
1655
1732
  result = rb_str_new2(escaped);
1656
1733
  PQfreemem(escaped);
1657
1734
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1674,7 +1751,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1674
1751
  {
1675
1752
  t_pg_connection *this = pg_get_connection_safe( self );
1676
1753
  char *escaped = NULL;
1677
- VALUE error;
1678
1754
  VALUE result = Qnil;
1679
1755
  int enc_idx = this->enc_idx;
1680
1756
 
@@ -1685,12 +1761,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1685
1761
 
1686
1762
  escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1687
1763
  if (escaped == NULL)
1688
- {
1689
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1690
- rb_iv_set(error, "@connection", self);
1691
- rb_exc_raise(error);
1692
- return Qnil;
1693
- }
1764
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1765
+
1694
1766
  result = rb_str_new2(escaped);
1695
1767
  PQfreemem(escaped);
1696
1768
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1738,14 +1810,9 @@ static VALUE
1738
1810
  pgconn_set_single_row_mode(VALUE self)
1739
1811
  {
1740
1812
  PGconn *conn = pg_get_pgconn(self);
1741
- VALUE error;
1742
1813
 
1743
1814
  if( PQsetSingleRowMode(conn) == 0 )
1744
- {
1745
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1746
- rb_iv_set(error, "@connection", self);
1747
- rb_exc_raise(error);
1748
- }
1815
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1749
1816
 
1750
1817
  return self;
1751
1818
  }
@@ -1769,15 +1836,12 @@ static VALUE
1769
1836
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1770
1837
  {
1771
1838
  t_pg_connection *this = pg_get_connection_safe( self );
1772
- VALUE error;
1773
1839
 
1774
1840
  /* If called with no or nil parameters, use PQexec for compatibility */
1775
1841
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1776
- if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1777
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1778
- rb_iv_set(error, "@connection", self);
1779
- rb_exc_raise(error);
1780
- }
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
+
1781
1845
  pgconn_wait_for_flush( self );
1782
1846
  return Qnil;
1783
1847
  }
@@ -1834,7 +1898,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1834
1898
  t_pg_connection *this = pg_get_connection_safe( self );
1835
1899
  int result;
1836
1900
  VALUE command, in_res_fmt;
1837
- VALUE error;
1838
1901
  int nParams;
1839
1902
  int resultFormat;
1840
1903
  struct query_params_data paramsData = { this->enc_idx };
@@ -1851,11 +1914,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1851
1914
 
1852
1915
  free_query_params( &paramsData );
1853
1916
 
1854
- if(result == 0) {
1855
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1856
- rb_iv_set(error, "@connection", self);
1857
- rb_exc_raise(error);
1858
- }
1917
+ if(result == 0)
1918
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1919
+
1859
1920
  pgconn_wait_for_flush( self );
1860
1921
  return Qnil;
1861
1922
  }
@@ -1887,7 +1948,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1887
1948
  int result;
1888
1949
  VALUE name, command, in_paramtypes;
1889
1950
  VALUE param;
1890
- VALUE error;
1891
1951
  int i = 0;
1892
1952
  int nParams = 0;
1893
1953
  Oid *paramTypes = NULL;
@@ -1916,9 +1976,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1916
1976
  xfree(paramTypes);
1917
1977
 
1918
1978
  if(result == 0) {
1919
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1920
- rb_iv_set(error, "@connection", self);
1921
- rb_exc_raise(error);
1979
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1922
1980
  }
1923
1981
  pgconn_wait_for_flush( self );
1924
1982
  return Qnil;
@@ -1962,7 +2020,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1962
2020
  t_pg_connection *this = pg_get_connection_safe( self );
1963
2021
  int result;
1964
2022
  VALUE name, in_res_fmt;
1965
- VALUE error;
1966
2023
  int nParams;
1967
2024
  int resultFormat;
1968
2025
  struct query_params_data paramsData = { this->enc_idx };
@@ -1984,11 +2041,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1984
2041
 
1985
2042
  free_query_params( &paramsData );
1986
2043
 
1987
- if(result == 0) {
1988
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1989
- rb_iv_set(error, "@connection", self);
1990
- rb_exc_raise(error);
1991
- }
2044
+ if(result == 0)
2045
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2046
+
1992
2047
  pgconn_wait_for_flush( self );
1993
2048
  return Qnil;
1994
2049
  }
@@ -2003,14 +2058,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2003
2058
  static VALUE
2004
2059
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2005
2060
  {
2006
- VALUE error;
2007
2061
  t_pg_connection *this = pg_get_connection_safe( self );
2008
2062
  /* returns 0 on failure */
2009
- if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
2010
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2011
- rb_iv_set(error, "@connection", self);
2012
- rb_exc_raise(error);
2013
- }
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
+
2014
2066
  pgconn_wait_for_flush( self );
2015
2067
  return Qnil;
2016
2068
  }
@@ -2026,14 +2078,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2026
2078
  static VALUE
2027
2079
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2028
2080
  {
2029
- VALUE error;
2030
2081
  t_pg_connection *this = pg_get_connection_safe( self );
2031
2082
  /* returns 0 on failure */
2032
- if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2033
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2034
- rb_iv_set(error, "@connection", self);
2035
- rb_exc_raise(error);
2036
- }
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
+
2037
2086
  pgconn_wait_for_flush( self );
2038
2087
  return Qnil;
2039
2088
  }
@@ -2066,18 +2115,15 @@ pgconn_sync_get_result(VALUE self)
2066
2115
  * or *notifies* to see if the state has changed.
2067
2116
  */
2068
2117
  static VALUE
2069
- pgconn_consume_input(self)
2070
- VALUE self;
2118
+ pgconn_consume_input(VALUE self)
2071
2119
  {
2072
- VALUE error;
2073
2120
  PGconn *conn = pg_get_pgconn(self);
2074
2121
  /* returns 0 on error */
2075
2122
  if(PQconsumeInput(conn) == 0) {
2076
2123
  pgconn_close_socket_io(self);
2077
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2078
- rb_iv_set(error, "@connection", self);
2079
- rb_exc_raise(error);
2124
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2080
2125
  }
2126
+
2081
2127
  return Qnil;
2082
2128
  }
2083
2129
 
@@ -2089,18 +2135,15 @@ pgconn_consume_input(self)
2089
2135
  * #get_result would block. Otherwise returns +false+.
2090
2136
  */
2091
2137
  static VALUE
2092
- pgconn_is_busy(self)
2093
- VALUE self;
2138
+ pgconn_is_busy(VALUE self)
2094
2139
  {
2095
2140
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2096
2141
  }
2097
2142
 
2098
2143
  static VALUE
2099
- pgconn_sync_setnonblocking(self, state)
2100
- VALUE self, state;
2144
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2101
2145
  {
2102
2146
  int arg;
2103
- VALUE error;
2104
2147
  PGconn *conn = pg_get_pgconn(self);
2105
2148
  if(state == Qtrue)
2106
2149
  arg = 1;
@@ -2109,18 +2152,15 @@ pgconn_sync_setnonblocking(self, state)
2109
2152
  else
2110
2153
  rb_raise(rb_eArgError, "Boolean value expected");
2111
2154
 
2112
- if(PQsetnonblocking(conn, arg) == -1) {
2113
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2114
- rb_iv_set(error, "@connection", self);
2115
- rb_exc_raise(error);
2116
- }
2155
+ if(PQsetnonblocking(conn, arg) == -1)
2156
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2157
+
2117
2158
  return Qnil;
2118
2159
  }
2119
2160
 
2120
2161
 
2121
2162
  static VALUE
2122
- pgconn_sync_isnonblocking(self)
2123
- VALUE self;
2163
+ pgconn_sync_isnonblocking(VALUE self)
2124
2164
  {
2125
2165
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2126
2166
  }
@@ -2129,14 +2169,10 @@ static VALUE
2129
2169
  pgconn_sync_flush(VALUE self)
2130
2170
  {
2131
2171
  PGconn *conn = pg_get_pgconn(self);
2132
- int ret;
2133
- VALUE error;
2134
- ret = PQflush(conn);
2135
- if(ret == -1) {
2136
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2137
- rb_iv_set(error, "@connection", self);
2138
- rb_exc_raise(error);
2139
- }
2172
+ int ret = PQflush(conn);
2173
+ if(ret == -1)
2174
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2175
+
2140
2176
  return (ret) ? Qfalse : Qtrue;
2141
2177
  }
2142
2178
 
@@ -2150,7 +2186,7 @@ pgconn_sync_cancel(VALUE self)
2150
2186
 
2151
2187
  cancel = PQgetCancel(pg_get_pgconn(self));
2152
2188
  if(cancel == NULL)
2153
- rb_raise(rb_ePGerror,"Invalid connection!");
2189
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2154
2190
 
2155
2191
  ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2156
2192
  if(ret == 1)
@@ -2359,7 +2395,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2359
2395
 
2360
2396
  /* Is the given timeout valid? */
2361
2397
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2362
- VALUE socket_io = pgconn_socket_io(self);
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);
2363
2406
  /* Wait for the socket to become readable before checking again */
2364
2407
  ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2365
2408
  } else {
@@ -2374,7 +2417,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2374
2417
  /* Check for connection errors (PQisBusy is true on connection errors) */
2375
2418
  if ( PQconsumeInput(conn) == 0 ){
2376
2419
  pgconn_close_socket_io(self);
2377
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2420
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2378
2421
  }
2379
2422
  }
2380
2423
 
@@ -2387,8 +2430,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2387
2430
  *
2388
2431
  * Attempts to flush any queued output data to the server.
2389
2432
  * Returns +true+ if data is successfully flushed, +false+
2390
- * if not (can only return +false+ if connection is
2391
- * nonblocking.
2433
+ * if not. It can only return +false+ if connection is
2434
+ * in nonblocking mode.
2392
2435
  * Raises PG::Error if some other failure occurred.
2393
2436
  */
2394
2437
  static VALUE
@@ -2524,11 +2567,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2524
2567
  Check_Type(buffer, T_STRING);
2525
2568
 
2526
2569
  ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2527
- if(ret == -1) {
2528
- VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2529
- rb_iv_set(error, "@connection", self);
2530
- rb_exc_raise(error);
2531
- }
2570
+ if(ret == -1)
2571
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2572
+
2532
2573
  RB_GC_GUARD(intermediate);
2533
2574
  RB_GC_GUARD(buffer);
2534
2575
 
@@ -2539,7 +2580,6 @@ static VALUE
2539
2580
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2540
2581
  {
2541
2582
  VALUE str;
2542
- VALUE error;
2543
2583
  int ret;
2544
2584
  const char *error_message = NULL;
2545
2585
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2550,11 +2590,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2550
2590
  error_message = pg_cstr_enc(str, this->enc_idx);
2551
2591
 
2552
2592
  ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2553
- if(ret == -1) {
2554
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2555
- rb_iv_set(error, "@connection", self);
2556
- rb_exc_raise(error);
2557
- }
2593
+ if(ret == -1)
2594
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2595
+
2558
2596
  return (ret) ? Qtrue : Qfalse;
2559
2597
  }
2560
2598
 
@@ -2562,7 +2600,6 @@ static VALUE
2562
2600
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2563
2601
  {
2564
2602
  VALUE async_in;
2565
- VALUE error;
2566
2603
  VALUE result;
2567
2604
  int ret;
2568
2605
  char *buffer;
@@ -2582,10 +2619,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2582
2619
  }
2583
2620
 
2584
2621
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2585
- if(ret == -2) { /* error */
2586
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2587
- rb_iv_set(error, "@connection", self);
2588
- rb_exc_raise(error);
2622
+ if(ret == -2){ /* error */
2623
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2589
2624
  }
2590
2625
  if(ret == -1) { /* No data left */
2591
2626
  return Qnil;
@@ -2890,9 +2925,9 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2890
2925
 
2891
2926
  Check_Type(str, T_STRING);
2892
2927
 
2893
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2894
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2895
- }
2928
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2929
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2930
+
2896
2931
  pgconn_set_internal_encoding_index( self );
2897
2932
 
2898
2933
  return Qnil;
@@ -3525,11 +3560,10 @@ pgconn_enter_pipeline_mode(VALUE self)
3525
3560
  {
3526
3561
  PGconn *conn = pg_get_pgconn(self);
3527
3562
  int res = PQenterPipelineMode(conn);
3528
- if( res == 1 ) {
3529
- return Qnil;
3530
- } else {
3531
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3532
- }
3563
+ if( res != 1 )
3564
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3565
+
3566
+ return Qnil;
3533
3567
  }
3534
3568
 
3535
3569
  /*
@@ -3548,11 +3582,10 @@ pgconn_exit_pipeline_mode(VALUE self)
3548
3582
  {
3549
3583
  PGconn *conn = pg_get_pgconn(self);
3550
3584
  int res = PQexitPipelineMode(conn);
3551
- if( res == 1 ) {
3552
- return Qnil;
3553
- } else {
3554
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3555
- }
3585
+ if( res != 1 )
3586
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3587
+
3588
+ return Qnil;
3556
3589
  }
3557
3590
 
3558
3591
 
@@ -3572,11 +3605,10 @@ pgconn_pipeline_sync(VALUE self)
3572
3605
  {
3573
3606
  PGconn *conn = pg_get_pgconn(self);
3574
3607
  int res = PQpipelineSync(conn);
3575
- if( res == 1 ) {
3576
- return Qnil;
3577
- } else {
3578
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3579
- }
3608
+ if( res != 1 )
3609
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3610
+
3611
+ return Qnil;
3580
3612
  }
3581
3613
 
3582
3614
  /*
@@ -3596,11 +3628,10 @@ pgconn_send_flush_request(VALUE self)
3596
3628
  {
3597
3629
  PGconn *conn = pg_get_pgconn(self);
3598
3630
  int res = PQsendFlushRequest(conn);
3599
- if( res == 1 ) {
3600
- return Qnil;
3601
- } else {
3602
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3603
- }
3631
+ if( res != 1 )
3632
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3633
+
3634
+ return Qnil;
3604
3635
  }
3605
3636
 
3606
3637
  #endif
@@ -3631,7 +3662,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3631
3662
 
3632
3663
  lo_oid = lo_creat(conn, mode);
3633
3664
  if (lo_oid == 0)
3634
- rb_raise(rb_ePGerror, "lo_creat failed");
3665
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3635
3666
 
3636
3667
  return UINT2NUM(lo_oid);
3637
3668
  }
@@ -3652,7 +3683,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3652
3683
 
3653
3684
  ret = lo_create(conn, lo_oid);
3654
3685
  if (ret == InvalidOid)
3655
- rb_raise(rb_ePGerror, "lo_create failed");
3686
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3656
3687
 
3657
3688
  return UINT2NUM(ret);
3658
3689
  }
@@ -3676,7 +3707,7 @@ pgconn_loimport(VALUE self, VALUE filename)
3676
3707
 
3677
3708
  lo_oid = lo_import(conn, StringValueCStr(filename));
3678
3709
  if (lo_oid == 0) {
3679
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3710
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3680
3711
  }
3681
3712
  return UINT2NUM(lo_oid);
3682
3713
  }
@@ -3697,7 +3728,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3697
3728
  oid = NUM2UINT(lo_oid);
3698
3729
 
3699
3730
  if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3700
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3731
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3701
3732
  }
3702
3733
  return Qnil;
3703
3734
  }
@@ -3728,7 +3759,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3728
3759
  mode = NUM2INT(nmode);
3729
3760
 
3730
3761
  if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3731
- rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3762
+ pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3732
3763
  }
3733
3764
  return INT2FIX(fd);
3734
3765
  }
@@ -3750,11 +3781,11 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3750
3781
  Check_Type(buffer, T_STRING);
3751
3782
 
3752
3783
  if( RSTRING_LEN(buffer) < 0) {
3753
- rb_raise(rb_ePGerror, "write buffer zero string");
3784
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3754
3785
  }
3755
3786
  if((n = lo_write(conn, fd, StringValuePtr(buffer),
3756
3787
  RSTRING_LEN(buffer))) < 0) {
3757
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3788
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3758
3789
  }
3759
3790
 
3760
3791
  return INT2FIX(n);
@@ -3777,16 +3808,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3777
3808
  VALUE str;
3778
3809
  char *buffer;
3779
3810
 
3780
- buffer = ALLOC_N(char, len);
3781
- if(buffer == NULL)
3782
- rb_raise(rb_eNoMemError, "ALLOC failed!");
3783
-
3784
- if (len < 0){
3785
- rb_raise(rb_ePGerror,"nagative length %d given", len);
3786
- }
3811
+ if (len < 0)
3812
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3787
3813
 
3814
+ buffer = ALLOC_N(char, len);
3788
3815
  if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3789
- rb_raise(rb_ePGerror, "lo_read failed");
3816
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3790
3817
 
3791
3818
  if(ret == 0) {
3792
3819
  xfree(buffer);
@@ -3816,7 +3843,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3816
3843
  int ret;
3817
3844
 
3818
3845
  if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3819
- rb_raise(rb_ePGerror, "lo_lseek failed");
3846
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3820
3847
  }
3821
3848
 
3822
3849
  return INT2FIX(ret);
@@ -3836,7 +3863,7 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3836
3863
  int lo_desc = NUM2INT(in_lo_desc);
3837
3864
 
3838
3865
  if((position = lo_tell(conn, lo_desc)) < 0)
3839
- rb_raise(rb_ePGerror,"lo_tell failed");
3866
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3840
3867
 
3841
3868
  return INT2FIX(position);
3842
3869
  }
@@ -3855,7 +3882,7 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3855
3882
  size_t len = NUM2INT(in_len);
3856
3883
 
3857
3884
  if(lo_truncate(conn,lo_desc,len) < 0)
3858
- rb_raise(rb_ePGerror,"lo_truncate failed");
3885
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3859
3886
 
3860
3887
  return Qnil;
3861
3888
  }
@@ -3873,7 +3900,7 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3873
3900
  int lo_desc = NUM2INT(in_lo_desc);
3874
3901
 
3875
3902
  if(lo_close(conn,lo_desc) < 0)
3876
- rb_raise(rb_ePGerror,"lo_close failed");
3903
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3877
3904
 
3878
3905
  return Qnil;
3879
3906
  }
@@ -3891,7 +3918,7 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3891
3918
  Oid oid = NUM2UINT(in_oid);
3892
3919
 
3893
3920
  if(lo_unlink(conn,oid) < 0)
3894
- rb_raise(rb_ePGerror,"lo_unlink failed");
3921
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3895
3922
 
3896
3923
  return Qnil;
3897
3924
  }
@@ -4325,6 +4352,7 @@ init_pg_connection()
4325
4352
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4326
4353
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4327
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);
4328
4356
  rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4329
4357
  rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4330
4358
 
@@ -4342,6 +4370,9 @@ init_pg_connection()
4342
4370
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4343
4371
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4344
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
4345
4376
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4346
4377
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4347
4378
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);