pg 1.3.5 → 1.4.0

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;
@@ -537,7 +580,7 @@ pgconn_reset_start(VALUE self)
537
580
  {
538
581
  pgconn_close_socket_io( self );
539
582
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
540
- rb_raise(rb_eUnableToSend, "reset has failed");
583
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
541
584
  return Qnil;
542
585
  }
543
586
 
@@ -607,7 +650,18 @@ pgconn_pass(VALUE self)
607
650
  * call-seq:
608
651
  * conn.host()
609
652
  *
610
- * 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 .
611
665
  */
612
666
  static VALUE
613
667
  pgconn_host(VALUE self)
@@ -617,6 +671,26 @@ pgconn_host(VALUE self)
617
671
  return rb_str_new2(host);
618
672
  }
619
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
+
620
694
  /*
621
695
  * call-seq:
622
696
  * conn.port()
@@ -687,6 +761,9 @@ pgconn_conninfo( VALUE self )
687
761
  * PG::Constants::CONNECTION_BAD
688
762
  *
689
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
690
767
  */
691
768
  static VALUE
692
769
  pgconn_status(VALUE self)
@@ -811,7 +888,8 @@ pgconn_socket(VALUE self)
811
888
  pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
812
889
 
813
890
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
814
- 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
+
815
893
  return INT2NUM(sd);
816
894
  }
817
895
 
@@ -839,14 +917,15 @@ pgconn_socket_io(VALUE self)
839
917
  VALUE socket_io = this->socket_io;
840
918
 
841
919
  if ( !RTEST(socket_io) ) {
842
- if( (sd = PQsocket(this->pgconn)) < 0)
843
- 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
+ }
844
923
 
845
924
  #ifdef _WIN32
846
925
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
847
- if( ruby_sd == -1 ){
848
- rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
849
- }
926
+ if( ruby_sd == -1 )
927
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
928
+
850
929
  this->ruby_sd = ruby_sd;
851
930
  #else
852
931
  ruby_sd = sd;
@@ -911,7 +990,7 @@ pgconn_backend_key(VALUE self)
911
990
 
912
991
  cancel = (struct pg_cancel*)PQgetCancel(conn);
913
992
  if(cancel == NULL)
914
- rb_raise(rb_ePGerror,"Invalid connection!");
993
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
915
994
 
916
995
  if( cancel->be_pid != PQbackendPID(conn) )
917
996
  rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
@@ -1540,9 +1619,9 @@ pgconn_s_escape(VALUE self, VALUE string)
1540
1619
  if( !singleton ) {
1541
1620
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1542
1621
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1543
- if(error) {
1544
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1545
- }
1622
+ if(error)
1623
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1624
+
1546
1625
  } else {
1547
1626
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1548
1627
  }
@@ -1638,7 +1717,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
1638
1717
  {
1639
1718
  t_pg_connection *this = pg_get_connection_safe( self );
1640
1719
  char *escaped = NULL;
1641
- VALUE error;
1642
1720
  VALUE result = Qnil;
1643
1721
  int enc_idx = this->enc_idx;
1644
1722
 
@@ -1649,12 +1727,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
1649
1727
 
1650
1728
  escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1651
1729
  if (escaped == NULL)
1652
- {
1653
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1654
- rb_iv_set(error, "@connection", self);
1655
- rb_exc_raise(error);
1656
- return Qnil;
1657
- }
1730
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1731
+
1658
1732
  result = rb_str_new2(escaped);
1659
1733
  PQfreemem(escaped);
1660
1734
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1677,7 +1751,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1677
1751
  {
1678
1752
  t_pg_connection *this = pg_get_connection_safe( self );
1679
1753
  char *escaped = NULL;
1680
- VALUE error;
1681
1754
  VALUE result = Qnil;
1682
1755
  int enc_idx = this->enc_idx;
1683
1756
 
@@ -1688,12 +1761,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1688
1761
 
1689
1762
  escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1690
1763
  if (escaped == NULL)
1691
- {
1692
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1693
- rb_iv_set(error, "@connection", self);
1694
- rb_exc_raise(error);
1695
- return Qnil;
1696
- }
1764
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1765
+
1697
1766
  result = rb_str_new2(escaped);
1698
1767
  PQfreemem(escaped);
1699
1768
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1741,14 +1810,9 @@ static VALUE
1741
1810
  pgconn_set_single_row_mode(VALUE self)
1742
1811
  {
1743
1812
  PGconn *conn = pg_get_pgconn(self);
1744
- VALUE error;
1745
1813
 
1746
1814
  if( PQsetSingleRowMode(conn) == 0 )
1747
- {
1748
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1749
- rb_iv_set(error, "@connection", self);
1750
- rb_exc_raise(error);
1751
- }
1815
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1752
1816
 
1753
1817
  return self;
1754
1818
  }
@@ -1772,15 +1836,12 @@ static VALUE
1772
1836
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1773
1837
  {
1774
1838
  t_pg_connection *this = pg_get_connection_safe( self );
1775
- VALUE error;
1776
1839
 
1777
1840
  /* If called with no or nil parameters, use PQexec for compatibility */
1778
1841
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1779
- if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1780
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1781
- rb_iv_set(error, "@connection", self);
1782
- rb_exc_raise(error);
1783
- }
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
+
1784
1845
  pgconn_wait_for_flush( self );
1785
1846
  return Qnil;
1786
1847
  }
@@ -1837,7 +1898,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1837
1898
  t_pg_connection *this = pg_get_connection_safe( self );
1838
1899
  int result;
1839
1900
  VALUE command, in_res_fmt;
1840
- VALUE error;
1841
1901
  int nParams;
1842
1902
  int resultFormat;
1843
1903
  struct query_params_data paramsData = { this->enc_idx };
@@ -1854,11 +1914,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1854
1914
 
1855
1915
  free_query_params( &paramsData );
1856
1916
 
1857
- if(result == 0) {
1858
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1859
- rb_iv_set(error, "@connection", self);
1860
- rb_exc_raise(error);
1861
- }
1917
+ if(result == 0)
1918
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1919
+
1862
1920
  pgconn_wait_for_flush( self );
1863
1921
  return Qnil;
1864
1922
  }
@@ -1890,7 +1948,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1890
1948
  int result;
1891
1949
  VALUE name, command, in_paramtypes;
1892
1950
  VALUE param;
1893
- VALUE error;
1894
1951
  int i = 0;
1895
1952
  int nParams = 0;
1896
1953
  Oid *paramTypes = NULL;
@@ -1919,9 +1976,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1919
1976
  xfree(paramTypes);
1920
1977
 
1921
1978
  if(result == 0) {
1922
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1923
- rb_iv_set(error, "@connection", self);
1924
- rb_exc_raise(error);
1979
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1925
1980
  }
1926
1981
  pgconn_wait_for_flush( self );
1927
1982
  return Qnil;
@@ -1965,7 +2020,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1965
2020
  t_pg_connection *this = pg_get_connection_safe( self );
1966
2021
  int result;
1967
2022
  VALUE name, in_res_fmt;
1968
- VALUE error;
1969
2023
  int nParams;
1970
2024
  int resultFormat;
1971
2025
  struct query_params_data paramsData = { this->enc_idx };
@@ -1987,11 +2041,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1987
2041
 
1988
2042
  free_query_params( &paramsData );
1989
2043
 
1990
- if(result == 0) {
1991
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1992
- rb_iv_set(error, "@connection", self);
1993
- rb_exc_raise(error);
1994
- }
2044
+ if(result == 0)
2045
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2046
+
1995
2047
  pgconn_wait_for_flush( self );
1996
2048
  return Qnil;
1997
2049
  }
@@ -2006,14 +2058,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2006
2058
  static VALUE
2007
2059
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2008
2060
  {
2009
- VALUE error;
2010
2061
  t_pg_connection *this = pg_get_connection_safe( self );
2011
2062
  /* returns 0 on failure */
2012
- if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
2013
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2014
- rb_iv_set(error, "@connection", self);
2015
- rb_exc_raise(error);
2016
- }
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
+
2017
2066
  pgconn_wait_for_flush( self );
2018
2067
  return Qnil;
2019
2068
  }
@@ -2029,14 +2078,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2029
2078
  static VALUE
2030
2079
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2031
2080
  {
2032
- VALUE error;
2033
2081
  t_pg_connection *this = pg_get_connection_safe( self );
2034
2082
  /* returns 0 on failure */
2035
- if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2036
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2037
- rb_iv_set(error, "@connection", self);
2038
- rb_exc_raise(error);
2039
- }
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
+
2040
2086
  pgconn_wait_for_flush( self );
2041
2087
  return Qnil;
2042
2088
  }
@@ -2069,18 +2115,15 @@ pgconn_sync_get_result(VALUE self)
2069
2115
  * or *notifies* to see if the state has changed.
2070
2116
  */
2071
2117
  static VALUE
2072
- pgconn_consume_input(self)
2073
- VALUE self;
2118
+ pgconn_consume_input(VALUE self)
2074
2119
  {
2075
- VALUE error;
2076
2120
  PGconn *conn = pg_get_pgconn(self);
2077
2121
  /* returns 0 on error */
2078
2122
  if(PQconsumeInput(conn) == 0) {
2079
2123
  pgconn_close_socket_io(self);
2080
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2081
- rb_iv_set(error, "@connection", self);
2082
- rb_exc_raise(error);
2124
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2083
2125
  }
2126
+
2084
2127
  return Qnil;
2085
2128
  }
2086
2129
 
@@ -2092,18 +2135,15 @@ pgconn_consume_input(self)
2092
2135
  * #get_result would block. Otherwise returns +false+.
2093
2136
  */
2094
2137
  static VALUE
2095
- pgconn_is_busy(self)
2096
- VALUE self;
2138
+ pgconn_is_busy(VALUE self)
2097
2139
  {
2098
2140
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2099
2141
  }
2100
2142
 
2101
2143
  static VALUE
2102
- pgconn_sync_setnonblocking(self, state)
2103
- VALUE self, state;
2144
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2104
2145
  {
2105
2146
  int arg;
2106
- VALUE error;
2107
2147
  PGconn *conn = pg_get_pgconn(self);
2108
2148
  if(state == Qtrue)
2109
2149
  arg = 1;
@@ -2112,18 +2152,15 @@ pgconn_sync_setnonblocking(self, state)
2112
2152
  else
2113
2153
  rb_raise(rb_eArgError, "Boolean value expected");
2114
2154
 
2115
- if(PQsetnonblocking(conn, arg) == -1) {
2116
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2117
- rb_iv_set(error, "@connection", self);
2118
- rb_exc_raise(error);
2119
- }
2155
+ if(PQsetnonblocking(conn, arg) == -1)
2156
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2157
+
2120
2158
  return Qnil;
2121
2159
  }
2122
2160
 
2123
2161
 
2124
2162
  static VALUE
2125
- pgconn_sync_isnonblocking(self)
2126
- VALUE self;
2163
+ pgconn_sync_isnonblocking(VALUE self)
2127
2164
  {
2128
2165
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2129
2166
  }
@@ -2132,14 +2169,10 @@ static VALUE
2132
2169
  pgconn_sync_flush(VALUE self)
2133
2170
  {
2134
2171
  PGconn *conn = pg_get_pgconn(self);
2135
- int ret;
2136
- VALUE error;
2137
- ret = PQflush(conn);
2138
- if(ret == -1) {
2139
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2140
- rb_iv_set(error, "@connection", self);
2141
- rb_exc_raise(error);
2142
- }
2172
+ int ret = PQflush(conn);
2173
+ if(ret == -1)
2174
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2175
+
2143
2176
  return (ret) ? Qfalse : Qtrue;
2144
2177
  }
2145
2178
 
@@ -2153,7 +2186,7 @@ pgconn_sync_cancel(VALUE self)
2153
2186
 
2154
2187
  cancel = PQgetCancel(pg_get_pgconn(self));
2155
2188
  if(cancel == NULL)
2156
- rb_raise(rb_ePGerror,"Invalid connection!");
2189
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2157
2190
 
2158
2191
  ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2159
2192
  if(ret == 1)
@@ -2362,7 +2395,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2362
2395
 
2363
2396
  /* Is the given timeout valid? */
2364
2397
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2365
- 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);
2366
2406
  /* Wait for the socket to become readable before checking again */
2367
2407
  ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2368
2408
  } else {
@@ -2377,7 +2417,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2377
2417
  /* Check for connection errors (PQisBusy is true on connection errors) */
2378
2418
  if ( PQconsumeInput(conn) == 0 ){
2379
2419
  pgconn_close_socket_io(self);
2380
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2420
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2381
2421
  }
2382
2422
  }
2383
2423
 
@@ -2390,8 +2430,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2390
2430
  *
2391
2431
  * Attempts to flush any queued output data to the server.
2392
2432
  * Returns +true+ if data is successfully flushed, +false+
2393
- * if not (can only return +false+ if connection is
2394
- * nonblocking.
2433
+ * if not. It can only return +false+ if connection is
2434
+ * in nonblocking mode.
2395
2435
  * Raises PG::Error if some other failure occurred.
2396
2436
  */
2397
2437
  static VALUE
@@ -2527,11 +2567,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2527
2567
  Check_Type(buffer, T_STRING);
2528
2568
 
2529
2569
  ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2530
- if(ret == -1) {
2531
- VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2532
- rb_iv_set(error, "@connection", self);
2533
- rb_exc_raise(error);
2534
- }
2570
+ if(ret == -1)
2571
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2572
+
2535
2573
  RB_GC_GUARD(intermediate);
2536
2574
  RB_GC_GUARD(buffer);
2537
2575
 
@@ -2542,7 +2580,6 @@ static VALUE
2542
2580
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2543
2581
  {
2544
2582
  VALUE str;
2545
- VALUE error;
2546
2583
  int ret;
2547
2584
  const char *error_message = NULL;
2548
2585
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2553,11 +2590,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2553
2590
  error_message = pg_cstr_enc(str, this->enc_idx);
2554
2591
 
2555
2592
  ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2556
- if(ret == -1) {
2557
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2558
- rb_iv_set(error, "@connection", self);
2559
- rb_exc_raise(error);
2560
- }
2593
+ if(ret == -1)
2594
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2595
+
2561
2596
  return (ret) ? Qtrue : Qfalse;
2562
2597
  }
2563
2598
 
@@ -2565,7 +2600,6 @@ static VALUE
2565
2600
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2566
2601
  {
2567
2602
  VALUE async_in;
2568
- VALUE error;
2569
2603
  VALUE result;
2570
2604
  int ret;
2571
2605
  char *buffer;
@@ -2585,10 +2619,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2585
2619
  }
2586
2620
 
2587
2621
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2588
- if(ret == -2) { /* error */
2589
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2590
- rb_iv_set(error, "@connection", self);
2591
- rb_exc_raise(error);
2622
+ if(ret == -2){ /* error */
2623
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2592
2624
  }
2593
2625
  if(ret == -1) { /* No data left */
2594
2626
  return Qnil;
@@ -2893,9 +2925,9 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2893
2925
 
2894
2926
  Check_Type(str, T_STRING);
2895
2927
 
2896
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2897
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2898
- }
2928
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2929
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2930
+
2899
2931
  pgconn_set_internal_encoding_index( self );
2900
2932
 
2901
2933
  return Qnil;
@@ -3528,11 +3560,10 @@ pgconn_enter_pipeline_mode(VALUE self)
3528
3560
  {
3529
3561
  PGconn *conn = pg_get_pgconn(self);
3530
3562
  int res = PQenterPipelineMode(conn);
3531
- if( res == 1 ) {
3532
- return Qnil;
3533
- } else {
3534
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3535
- }
3563
+ if( res != 1 )
3564
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3565
+
3566
+ return Qnil;
3536
3567
  }
3537
3568
 
3538
3569
  /*
@@ -3551,11 +3582,10 @@ pgconn_exit_pipeline_mode(VALUE self)
3551
3582
  {
3552
3583
  PGconn *conn = pg_get_pgconn(self);
3553
3584
  int res = PQexitPipelineMode(conn);
3554
- if( res == 1 ) {
3555
- return Qnil;
3556
- } else {
3557
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3558
- }
3585
+ if( res != 1 )
3586
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3587
+
3588
+ return Qnil;
3559
3589
  }
3560
3590
 
3561
3591
 
@@ -3575,11 +3605,10 @@ pgconn_pipeline_sync(VALUE self)
3575
3605
  {
3576
3606
  PGconn *conn = pg_get_pgconn(self);
3577
3607
  int res = PQpipelineSync(conn);
3578
- if( res == 1 ) {
3579
- return Qnil;
3580
- } else {
3581
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3582
- }
3608
+ if( res != 1 )
3609
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3610
+
3611
+ return Qnil;
3583
3612
  }
3584
3613
 
3585
3614
  /*
@@ -3599,11 +3628,10 @@ pgconn_send_flush_request(VALUE self)
3599
3628
  {
3600
3629
  PGconn *conn = pg_get_pgconn(self);
3601
3630
  int res = PQsendFlushRequest(conn);
3602
- if( res == 1 ) {
3603
- return Qnil;
3604
- } else {
3605
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3606
- }
3631
+ if( res != 1 )
3632
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3633
+
3634
+ return Qnil;
3607
3635
  }
3608
3636
 
3609
3637
  #endif
@@ -3634,7 +3662,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3634
3662
 
3635
3663
  lo_oid = lo_creat(conn, mode);
3636
3664
  if (lo_oid == 0)
3637
- rb_raise(rb_ePGerror, "lo_creat failed");
3665
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3638
3666
 
3639
3667
  return UINT2NUM(lo_oid);
3640
3668
  }
@@ -3655,7 +3683,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3655
3683
 
3656
3684
  ret = lo_create(conn, lo_oid);
3657
3685
  if (ret == InvalidOid)
3658
- rb_raise(rb_ePGerror, "lo_create failed");
3686
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3659
3687
 
3660
3688
  return UINT2NUM(ret);
3661
3689
  }
@@ -3679,7 +3707,7 @@ pgconn_loimport(VALUE self, VALUE filename)
3679
3707
 
3680
3708
  lo_oid = lo_import(conn, StringValueCStr(filename));
3681
3709
  if (lo_oid == 0) {
3682
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3710
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3683
3711
  }
3684
3712
  return UINT2NUM(lo_oid);
3685
3713
  }
@@ -3700,7 +3728,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3700
3728
  oid = NUM2UINT(lo_oid);
3701
3729
 
3702
3730
  if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3703
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3731
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3704
3732
  }
3705
3733
  return Qnil;
3706
3734
  }
@@ -3731,7 +3759,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3731
3759
  mode = NUM2INT(nmode);
3732
3760
 
3733
3761
  if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3734
- 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));
3735
3763
  }
3736
3764
  return INT2FIX(fd);
3737
3765
  }
@@ -3753,11 +3781,11 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3753
3781
  Check_Type(buffer, T_STRING);
3754
3782
 
3755
3783
  if( RSTRING_LEN(buffer) < 0) {
3756
- rb_raise(rb_ePGerror, "write buffer zero string");
3784
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3757
3785
  }
3758
3786
  if((n = lo_write(conn, fd, StringValuePtr(buffer),
3759
3787
  RSTRING_LEN(buffer))) < 0) {
3760
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3788
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3761
3789
  }
3762
3790
 
3763
3791
  return INT2FIX(n);
@@ -3780,16 +3808,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3780
3808
  VALUE str;
3781
3809
  char *buffer;
3782
3810
 
3783
- buffer = ALLOC_N(char, len);
3784
- if(buffer == NULL)
3785
- rb_raise(rb_eNoMemError, "ALLOC failed!");
3786
-
3787
- if (len < 0){
3788
- rb_raise(rb_ePGerror,"nagative length %d given", len);
3789
- }
3811
+ if (len < 0)
3812
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3790
3813
 
3814
+ buffer = ALLOC_N(char, len);
3791
3815
  if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3792
- rb_raise(rb_ePGerror, "lo_read failed");
3816
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3793
3817
 
3794
3818
  if(ret == 0) {
3795
3819
  xfree(buffer);
@@ -3819,7 +3843,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3819
3843
  int ret;
3820
3844
 
3821
3845
  if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3822
- rb_raise(rb_ePGerror, "lo_lseek failed");
3846
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3823
3847
  }
3824
3848
 
3825
3849
  return INT2FIX(ret);
@@ -3839,7 +3863,7 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3839
3863
  int lo_desc = NUM2INT(in_lo_desc);
3840
3864
 
3841
3865
  if((position = lo_tell(conn, lo_desc)) < 0)
3842
- rb_raise(rb_ePGerror,"lo_tell failed");
3866
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3843
3867
 
3844
3868
  return INT2FIX(position);
3845
3869
  }
@@ -3858,7 +3882,7 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3858
3882
  size_t len = NUM2INT(in_len);
3859
3883
 
3860
3884
  if(lo_truncate(conn,lo_desc,len) < 0)
3861
- rb_raise(rb_ePGerror,"lo_truncate failed");
3885
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3862
3886
 
3863
3887
  return Qnil;
3864
3888
  }
@@ -3876,7 +3900,7 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3876
3900
  int lo_desc = NUM2INT(in_lo_desc);
3877
3901
 
3878
3902
  if(lo_close(conn,lo_desc) < 0)
3879
- rb_raise(rb_ePGerror,"lo_close failed");
3903
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3880
3904
 
3881
3905
  return Qnil;
3882
3906
  }
@@ -3894,7 +3918,7 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3894
3918
  Oid oid = NUM2UINT(in_oid);
3895
3919
 
3896
3920
  if(lo_unlink(conn,oid) < 0)
3897
- rb_raise(rb_ePGerror,"lo_unlink failed");
3921
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3898
3922
 
3899
3923
  return Qnil;
3900
3924
  }
@@ -4328,6 +4352,7 @@ init_pg_connection()
4328
4352
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4329
4353
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4330
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);
4331
4356
  rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4332
4357
  rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4333
4358
 
@@ -4345,6 +4370,9 @@ init_pg_connection()
4345
4370
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4346
4371
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4347
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
4348
4376
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4349
4377
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4350
4378
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);