pg 1.3.5 → 1.4.3

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
  }
@@ -245,6 +266,7 @@ pgconn_s_allocate( VALUE klass )
245
266
  this->encoder_for_put_copy_data = Qnil;
246
267
  this->decoder_for_get_copy_data = Qnil;
247
268
  this->trace_stream = Qnil;
269
+ rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
248
270
 
249
271
  return self;
250
272
  }
@@ -254,7 +276,6 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
254
276
  {
255
277
  t_pg_connection *this;
256
278
  VALUE conninfo;
257
- VALUE error;
258
279
  VALUE self = pgconn_s_allocate( klass );
259
280
 
260
281
  this = pg_get_connection( self );
@@ -262,13 +283,10 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
262
283
  this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
263
284
 
264
285
  if(this->pgconn == NULL)
265
- rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
286
+ rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
266
287
 
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
- }
288
+ if (PQstatus(this->pgconn) == CONNECTION_BAD)
289
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
272
290
 
273
291
  pgconn_set_default_encoding( self );
274
292
 
@@ -301,7 +319,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
301
319
  {
302
320
  VALUE rb_conn;
303
321
  VALUE conninfo;
304
- VALUE error;
305
322
  t_pg_connection *this;
306
323
 
307
324
  /*
@@ -314,13 +331,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
314
331
  this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
315
332
 
316
333
  if( this->pgconn == NULL )
317
- rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
334
+ rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
318
335
 
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
- }
336
+ if ( PQstatus(this->pgconn) == CONNECTION_BAD )
337
+ pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
324
338
 
325
339
  if ( rb_block_given_p() ) {
326
340
  return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
@@ -376,6 +390,36 @@ pgconn_s_conndefaults(VALUE self)
376
390
  return array;
377
391
  }
378
392
 
393
+ /*
394
+ * Document-method: PG::Connection.conninfo_parse
395
+ *
396
+ * call-seq:
397
+ * PG::Connection.conninfo_parse(conninfo_string) -> Array
398
+ *
399
+ * Returns parsed connection options from the provided connection string as an array of hashes.
400
+ * Each hash has the same keys as PG::Connection.conndefaults() .
401
+ * The values from the +conninfo_string+ are stored in the +:val+ key.
402
+ */
403
+ static VALUE
404
+ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
405
+ {
406
+ VALUE array;
407
+ char *errmsg = NULL;
408
+ PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
409
+ if(errmsg){
410
+ VALUE error = rb_str_new_cstr(errmsg);
411
+ PQfreemem(errmsg);
412
+ rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
413
+ }
414
+ array = pgconn_make_conninfo_array( options );
415
+
416
+ PQconninfoFree(options);
417
+
418
+ UNUSED( self );
419
+
420
+ return array;
421
+ }
422
+
379
423
 
380
424
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
381
425
  static VALUE
@@ -396,7 +440,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
396
440
  rval = rb_str_new2( encrypted );
397
441
  PQfreemem( encrypted );
398
442
  } else {
399
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
443
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
400
444
  }
401
445
 
402
446
  return rval;
@@ -537,7 +581,7 @@ pgconn_reset_start(VALUE self)
537
581
  {
538
582
  pgconn_close_socket_io( self );
539
583
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
540
- rb_raise(rb_eUnableToSend, "reset has failed");
584
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
541
585
  return Qnil;
542
586
  }
543
587
 
@@ -607,7 +651,18 @@ pgconn_pass(VALUE self)
607
651
  * call-seq:
608
652
  * conn.host()
609
653
  *
610
- * Returns the connected server name.
654
+ * Returns the server host name of the active connection.
655
+ * This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
656
+ * (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
657
+ *
658
+ * If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
659
+ * If only hostaddr was specified, then that is returned.
660
+ * If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
661
+ *
662
+ * 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.
663
+ *
664
+ * 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.
665
+ * The status of the connection can be checked using the function Connection#status .
611
666
  */
612
667
  static VALUE
613
668
  pgconn_host(VALUE self)
@@ -617,6 +672,26 @@ pgconn_host(VALUE self)
617
672
  return rb_str_new2(host);
618
673
  }
619
674
 
675
+ /* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
676
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
677
+ /*
678
+ * call-seq:
679
+ * conn.hostaddr()
680
+ *
681
+ * Returns the server IP address of the active connection.
682
+ * This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
683
+ * 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.
684
+ *
685
+ */
686
+ static VALUE
687
+ pgconn_hostaddr(VALUE self)
688
+ {
689
+ char *host = PQhostaddr(pg_get_pgconn(self));
690
+ if (!host) return Qnil;
691
+ return rb_str_new2(host);
692
+ }
693
+ #endif
694
+
620
695
  /*
621
696
  * call-seq:
622
697
  * conn.port()
@@ -687,6 +762,9 @@ pgconn_conninfo( VALUE self )
687
762
  * PG::Constants::CONNECTION_BAD
688
763
  *
689
764
  * ... and other constants of kind PG::Constants::CONNECTION_*
765
+ *
766
+ * Example:
767
+ * PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
690
768
  */
691
769
  static VALUE
692
770
  pgconn_status(VALUE self)
@@ -811,7 +889,8 @@ pgconn_socket(VALUE self)
811
889
  pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
812
890
 
813
891
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
814
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
892
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
893
+
815
894
  return INT2NUM(sd);
816
895
  }
817
896
 
@@ -839,14 +918,15 @@ pgconn_socket_io(VALUE self)
839
918
  VALUE socket_io = this->socket_io;
840
919
 
841
920
  if ( !RTEST(socket_io) ) {
842
- if( (sd = PQsocket(this->pgconn)) < 0)
843
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
921
+ if( (sd = PQsocket(this->pgconn)) < 0){
922
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
923
+ }
844
924
 
845
925
  #ifdef _WIN32
846
926
  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
- }
927
+ if( ruby_sd == -1 )
928
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
929
+
850
930
  this->ruby_sd = ruby_sd;
851
931
  #else
852
932
  ruby_sd = sd;
@@ -911,7 +991,7 @@ pgconn_backend_key(VALUE self)
911
991
 
912
992
  cancel = (struct pg_cancel*)PQgetCancel(conn);
913
993
  if(cancel == NULL)
914
- rb_raise(rb_ePGerror,"Invalid connection!");
994
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
915
995
 
916
996
  if( cancel->be_pid != PQbackendPID(conn) )
917
997
  rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
@@ -1540,9 +1620,9 @@ pgconn_s_escape(VALUE self, VALUE string)
1540
1620
  if( !singleton ) {
1541
1621
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1542
1622
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1543
- if(error) {
1544
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1545
- }
1623
+ if(error)
1624
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1625
+
1546
1626
  } else {
1547
1627
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1548
1628
  }
@@ -1638,7 +1718,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
1638
1718
  {
1639
1719
  t_pg_connection *this = pg_get_connection_safe( self );
1640
1720
  char *escaped = NULL;
1641
- VALUE error;
1642
1721
  VALUE result = Qnil;
1643
1722
  int enc_idx = this->enc_idx;
1644
1723
 
@@ -1649,12 +1728,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
1649
1728
 
1650
1729
  escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1651
1730
  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
- }
1731
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1732
+
1658
1733
  result = rb_str_new2(escaped);
1659
1734
  PQfreemem(escaped);
1660
1735
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1677,7 +1752,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1677
1752
  {
1678
1753
  t_pg_connection *this = pg_get_connection_safe( self );
1679
1754
  char *escaped = NULL;
1680
- VALUE error;
1681
1755
  VALUE result = Qnil;
1682
1756
  int enc_idx = this->enc_idx;
1683
1757
 
@@ -1688,12 +1762,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1688
1762
 
1689
1763
  escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1690
1764
  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
- }
1765
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1766
+
1697
1767
  result = rb_str_new2(escaped);
1698
1768
  PQfreemem(escaped);
1699
1769
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1741,14 +1811,9 @@ static VALUE
1741
1811
  pgconn_set_single_row_mode(VALUE self)
1742
1812
  {
1743
1813
  PGconn *conn = pg_get_pgconn(self);
1744
- VALUE error;
1745
1814
 
1746
1815
  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
- }
1816
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1752
1817
 
1753
1818
  return self;
1754
1819
  }
@@ -1772,15 +1837,12 @@ static VALUE
1772
1837
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1773
1838
  {
1774
1839
  t_pg_connection *this = pg_get_connection_safe( self );
1775
- VALUE error;
1776
1840
 
1777
1841
  /* If called with no or nil parameters, use PQexec for compatibility */
1778
1842
  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
- }
1843
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
1844
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1845
+
1784
1846
  pgconn_wait_for_flush( self );
1785
1847
  return Qnil;
1786
1848
  }
@@ -1837,7 +1899,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1837
1899
  t_pg_connection *this = pg_get_connection_safe( self );
1838
1900
  int result;
1839
1901
  VALUE command, in_res_fmt;
1840
- VALUE error;
1841
1902
  int nParams;
1842
1903
  int resultFormat;
1843
1904
  struct query_params_data paramsData = { this->enc_idx };
@@ -1854,11 +1915,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1854
1915
 
1855
1916
  free_query_params( &paramsData );
1856
1917
 
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
- }
1918
+ if(result == 0)
1919
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1920
+
1862
1921
  pgconn_wait_for_flush( self );
1863
1922
  return Qnil;
1864
1923
  }
@@ -1890,7 +1949,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1890
1949
  int result;
1891
1950
  VALUE name, command, in_paramtypes;
1892
1951
  VALUE param;
1893
- VALUE error;
1894
1952
  int i = 0;
1895
1953
  int nParams = 0;
1896
1954
  Oid *paramTypes = NULL;
@@ -1919,9 +1977,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1919
1977
  xfree(paramTypes);
1920
1978
 
1921
1979
  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);
1980
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1925
1981
  }
1926
1982
  pgconn_wait_for_flush( self );
1927
1983
  return Qnil;
@@ -1965,7 +2021,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1965
2021
  t_pg_connection *this = pg_get_connection_safe( self );
1966
2022
  int result;
1967
2023
  VALUE name, in_res_fmt;
1968
- VALUE error;
1969
2024
  int nParams;
1970
2025
  int resultFormat;
1971
2026
  struct query_params_data paramsData = { this->enc_idx };
@@ -1987,11 +2042,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1987
2042
 
1988
2043
  free_query_params( &paramsData );
1989
2044
 
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
- }
2045
+ if(result == 0)
2046
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2047
+
1995
2048
  pgconn_wait_for_flush( self );
1996
2049
  return Qnil;
1997
2050
  }
@@ -2006,14 +2059,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2006
2059
  static VALUE
2007
2060
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2008
2061
  {
2009
- VALUE error;
2010
2062
  t_pg_connection *this = pg_get_connection_safe( self );
2011
2063
  /* 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
- }
2064
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
2065
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2066
+
2017
2067
  pgconn_wait_for_flush( self );
2018
2068
  return Qnil;
2019
2069
  }
@@ -2029,14 +2079,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2029
2079
  static VALUE
2030
2080
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2031
2081
  {
2032
- VALUE error;
2033
2082
  t_pg_connection *this = pg_get_connection_safe( self );
2034
2083
  /* 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
- }
2084
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
2085
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2086
+
2040
2087
  pgconn_wait_for_flush( self );
2041
2088
  return Qnil;
2042
2089
  }
@@ -2069,18 +2116,15 @@ pgconn_sync_get_result(VALUE self)
2069
2116
  * or *notifies* to see if the state has changed.
2070
2117
  */
2071
2118
  static VALUE
2072
- pgconn_consume_input(self)
2073
- VALUE self;
2119
+ pgconn_consume_input(VALUE self)
2074
2120
  {
2075
- VALUE error;
2076
2121
  PGconn *conn = pg_get_pgconn(self);
2077
2122
  /* returns 0 on error */
2078
2123
  if(PQconsumeInput(conn) == 0) {
2079
2124
  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);
2125
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2083
2126
  }
2127
+
2084
2128
  return Qnil;
2085
2129
  }
2086
2130
 
@@ -2092,18 +2136,15 @@ pgconn_consume_input(self)
2092
2136
  * #get_result would block. Otherwise returns +false+.
2093
2137
  */
2094
2138
  static VALUE
2095
- pgconn_is_busy(self)
2096
- VALUE self;
2139
+ pgconn_is_busy(VALUE self)
2097
2140
  {
2098
2141
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2099
2142
  }
2100
2143
 
2101
2144
  static VALUE
2102
- pgconn_sync_setnonblocking(self, state)
2103
- VALUE self, state;
2145
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2104
2146
  {
2105
2147
  int arg;
2106
- VALUE error;
2107
2148
  PGconn *conn = pg_get_pgconn(self);
2108
2149
  if(state == Qtrue)
2109
2150
  arg = 1;
@@ -2112,18 +2153,15 @@ pgconn_sync_setnonblocking(self, state)
2112
2153
  else
2113
2154
  rb_raise(rb_eArgError, "Boolean value expected");
2114
2155
 
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
- }
2156
+ if(PQsetnonblocking(conn, arg) == -1)
2157
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2158
+
2120
2159
  return Qnil;
2121
2160
  }
2122
2161
 
2123
2162
 
2124
2163
  static VALUE
2125
- pgconn_sync_isnonblocking(self)
2126
- VALUE self;
2164
+ pgconn_sync_isnonblocking(VALUE self)
2127
2165
  {
2128
2166
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2129
2167
  }
@@ -2132,14 +2170,10 @@ static VALUE
2132
2170
  pgconn_sync_flush(VALUE self)
2133
2171
  {
2134
2172
  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
- }
2173
+ int ret = PQflush(conn);
2174
+ if(ret == -1)
2175
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2176
+
2143
2177
  return (ret) ? Qfalse : Qtrue;
2144
2178
  }
2145
2179
 
@@ -2153,7 +2187,7 @@ pgconn_sync_cancel(VALUE self)
2153
2187
 
2154
2188
  cancel = PQgetCancel(pg_get_pgconn(self));
2155
2189
  if(cancel == NULL)
2156
- rb_raise(rb_ePGerror,"Invalid connection!");
2190
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2157
2191
 
2158
2192
  ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2159
2193
  if(ret == 1)
@@ -2362,7 +2396,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2362
2396
 
2363
2397
  /* Is the given timeout valid? */
2364
2398
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2365
- VALUE socket_io = pgconn_socket_io(self);
2399
+ VALUE socket_io;
2400
+
2401
+ /* before we wait for data, make sure everything has been sent */
2402
+ pgconn_async_flush(self);
2403
+ if ((retval=is_readable(conn)))
2404
+ return retval;
2405
+
2406
+ socket_io = pgconn_socket_io(self);
2366
2407
  /* Wait for the socket to become readable before checking again */
2367
2408
  ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2368
2409
  } else {
@@ -2377,7 +2418,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2377
2418
  /* Check for connection errors (PQisBusy is true on connection errors) */
2378
2419
  if ( PQconsumeInput(conn) == 0 ){
2379
2420
  pgconn_close_socket_io(self);
2380
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2421
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2381
2422
  }
2382
2423
  }
2383
2424
 
@@ -2390,8 +2431,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2390
2431
  *
2391
2432
  * Attempts to flush any queued output data to the server.
2392
2433
  * Returns +true+ if data is successfully flushed, +false+
2393
- * if not (can only return +false+ if connection is
2394
- * nonblocking.
2434
+ * if not. It can only return +false+ if connection is
2435
+ * in nonblocking mode.
2395
2436
  * Raises PG::Error if some other failure occurred.
2396
2437
  */
2397
2438
  static VALUE
@@ -2527,11 +2568,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2527
2568
  Check_Type(buffer, T_STRING);
2528
2569
 
2529
2570
  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
- }
2571
+ if(ret == -1)
2572
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2573
+
2535
2574
  RB_GC_GUARD(intermediate);
2536
2575
  RB_GC_GUARD(buffer);
2537
2576
 
@@ -2542,7 +2581,6 @@ static VALUE
2542
2581
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2543
2582
  {
2544
2583
  VALUE str;
2545
- VALUE error;
2546
2584
  int ret;
2547
2585
  const char *error_message = NULL;
2548
2586
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2553,11 +2591,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2553
2591
  error_message = pg_cstr_enc(str, this->enc_idx);
2554
2592
 
2555
2593
  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
- }
2594
+ if(ret == -1)
2595
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2596
+
2561
2597
  return (ret) ? Qtrue : Qfalse;
2562
2598
  }
2563
2599
 
@@ -2565,7 +2601,6 @@ static VALUE
2565
2601
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2566
2602
  {
2567
2603
  VALUE async_in;
2568
- VALUE error;
2569
2604
  VALUE result;
2570
2605
  int ret;
2571
2606
  char *buffer;
@@ -2585,10 +2620,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2585
2620
  }
2586
2621
 
2587
2622
  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);
2623
+ if(ret == -2){ /* error */
2624
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2592
2625
  }
2593
2626
  if(ret == -1) { /* No data left */
2594
2627
  return Qnil;
@@ -2893,9 +2926,9 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2893
2926
 
2894
2927
  Check_Type(str, T_STRING);
2895
2928
 
2896
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2897
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2898
- }
2929
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2930
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2931
+
2899
2932
  pgconn_set_internal_encoding_index( self );
2900
2933
 
2901
2934
  return Qnil;
@@ -3528,11 +3561,10 @@ pgconn_enter_pipeline_mode(VALUE self)
3528
3561
  {
3529
3562
  PGconn *conn = pg_get_pgconn(self);
3530
3563
  int res = PQenterPipelineMode(conn);
3531
- if( res == 1 ) {
3532
- return Qnil;
3533
- } else {
3534
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3535
- }
3564
+ if( res != 1 )
3565
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3566
+
3567
+ return Qnil;
3536
3568
  }
3537
3569
 
3538
3570
  /*
@@ -3551,11 +3583,10 @@ pgconn_exit_pipeline_mode(VALUE self)
3551
3583
  {
3552
3584
  PGconn *conn = pg_get_pgconn(self);
3553
3585
  int res = PQexitPipelineMode(conn);
3554
- if( res == 1 ) {
3555
- return Qnil;
3556
- } else {
3557
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3558
- }
3586
+ if( res != 1 )
3587
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3588
+
3589
+ return Qnil;
3559
3590
  }
3560
3591
 
3561
3592
 
@@ -3575,11 +3606,10 @@ pgconn_pipeline_sync(VALUE self)
3575
3606
  {
3576
3607
  PGconn *conn = pg_get_pgconn(self);
3577
3608
  int res = PQpipelineSync(conn);
3578
- if( res == 1 ) {
3579
- return Qnil;
3580
- } else {
3581
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3582
- }
3609
+ if( res != 1 )
3610
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3611
+
3612
+ return Qnil;
3583
3613
  }
3584
3614
 
3585
3615
  /*
@@ -3599,11 +3629,10 @@ pgconn_send_flush_request(VALUE self)
3599
3629
  {
3600
3630
  PGconn *conn = pg_get_pgconn(self);
3601
3631
  int res = PQsendFlushRequest(conn);
3602
- if( res == 1 ) {
3603
- return Qnil;
3604
- } else {
3605
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3606
- }
3632
+ if( res != 1 )
3633
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3634
+
3635
+ return Qnil;
3607
3636
  }
3608
3637
 
3609
3638
  #endif
@@ -3634,7 +3663,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3634
3663
 
3635
3664
  lo_oid = lo_creat(conn, mode);
3636
3665
  if (lo_oid == 0)
3637
- rb_raise(rb_ePGerror, "lo_creat failed");
3666
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3638
3667
 
3639
3668
  return UINT2NUM(lo_oid);
3640
3669
  }
@@ -3655,7 +3684,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3655
3684
 
3656
3685
  ret = lo_create(conn, lo_oid);
3657
3686
  if (ret == InvalidOid)
3658
- rb_raise(rb_ePGerror, "lo_create failed");
3687
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3659
3688
 
3660
3689
  return UINT2NUM(ret);
3661
3690
  }
@@ -3679,7 +3708,7 @@ pgconn_loimport(VALUE self, VALUE filename)
3679
3708
 
3680
3709
  lo_oid = lo_import(conn, StringValueCStr(filename));
3681
3710
  if (lo_oid == 0) {
3682
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3711
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3683
3712
  }
3684
3713
  return UINT2NUM(lo_oid);
3685
3714
  }
@@ -3700,7 +3729,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3700
3729
  oid = NUM2UINT(lo_oid);
3701
3730
 
3702
3731
  if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3703
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3732
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3704
3733
  }
3705
3734
  return Qnil;
3706
3735
  }
@@ -3731,7 +3760,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3731
3760
  mode = NUM2INT(nmode);
3732
3761
 
3733
3762
  if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3734
- rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3763
+ pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3735
3764
  }
3736
3765
  return INT2FIX(fd);
3737
3766
  }
@@ -3753,11 +3782,11 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3753
3782
  Check_Type(buffer, T_STRING);
3754
3783
 
3755
3784
  if( RSTRING_LEN(buffer) < 0) {
3756
- rb_raise(rb_ePGerror, "write buffer zero string");
3785
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3757
3786
  }
3758
3787
  if((n = lo_write(conn, fd, StringValuePtr(buffer),
3759
3788
  RSTRING_LEN(buffer))) < 0) {
3760
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3789
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3761
3790
  }
3762
3791
 
3763
3792
  return INT2FIX(n);
@@ -3780,16 +3809,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3780
3809
  VALUE str;
3781
3810
  char *buffer;
3782
3811
 
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
- }
3812
+ if (len < 0)
3813
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3790
3814
 
3815
+ buffer = ALLOC_N(char, len);
3791
3816
  if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3792
- rb_raise(rb_ePGerror, "lo_read failed");
3817
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3793
3818
 
3794
3819
  if(ret == 0) {
3795
3820
  xfree(buffer);
@@ -3819,7 +3844,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3819
3844
  int ret;
3820
3845
 
3821
3846
  if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3822
- rb_raise(rb_ePGerror, "lo_lseek failed");
3847
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3823
3848
  }
3824
3849
 
3825
3850
  return INT2FIX(ret);
@@ -3839,7 +3864,7 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3839
3864
  int lo_desc = NUM2INT(in_lo_desc);
3840
3865
 
3841
3866
  if((position = lo_tell(conn, lo_desc)) < 0)
3842
- rb_raise(rb_ePGerror,"lo_tell failed");
3867
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3843
3868
 
3844
3869
  return INT2FIX(position);
3845
3870
  }
@@ -3858,7 +3883,7 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3858
3883
  size_t len = NUM2INT(in_len);
3859
3884
 
3860
3885
  if(lo_truncate(conn,lo_desc,len) < 0)
3861
- rb_raise(rb_ePGerror,"lo_truncate failed");
3886
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3862
3887
 
3863
3888
  return Qnil;
3864
3889
  }
@@ -3876,7 +3901,7 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3876
3901
  int lo_desc = NUM2INT(in_lo_desc);
3877
3902
 
3878
3903
  if(lo_close(conn,lo_desc) < 0)
3879
- rb_raise(rb_ePGerror,"lo_close failed");
3904
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3880
3905
 
3881
3906
  return Qnil;
3882
3907
  }
@@ -3894,7 +3919,7 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3894
3919
  Oid oid = NUM2UINT(in_oid);
3895
3920
 
3896
3921
  if(lo_unlink(conn,oid) < 0)
3897
- rb_raise(rb_ePGerror,"lo_unlink failed");
3922
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3898
3923
 
3899
3924
  return Qnil;
3900
3925
  }
@@ -4328,6 +4353,7 @@ init_pg_connection()
4328
4353
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4329
4354
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4330
4355
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4356
+ rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
4331
4357
  rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4332
4358
  rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4333
4359
 
@@ -4345,6 +4371,9 @@ init_pg_connection()
4345
4371
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4346
4372
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4347
4373
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4374
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
4375
+ rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
4376
+ #endif
4348
4377
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4349
4378
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4350
4379
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);