pg 1.3.5 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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()
@@ -627,7 +702,10 @@ static VALUE
627
702
  pgconn_port(VALUE self)
628
703
  {
629
704
  char* port = PQport(pg_get_pgconn(self));
630
- return INT2NUM(atoi(port));
705
+ if (!port || port[0] == '\0')
706
+ return INT2NUM(DEF_PGPORT);
707
+ else
708
+ return INT2NUM(atoi(port));
631
709
  }
632
710
 
633
711
  /*
@@ -687,6 +765,9 @@ pgconn_conninfo( VALUE self )
687
765
  * PG::Constants::CONNECTION_BAD
688
766
  *
689
767
  * ... and other constants of kind PG::Constants::CONNECTION_*
768
+ *
769
+ * Example:
770
+ * PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
690
771
  */
691
772
  static VALUE
692
773
  pgconn_status(VALUE self)
@@ -811,7 +892,8 @@ pgconn_socket(VALUE self)
811
892
  pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
812
893
 
813
894
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
814
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
895
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
896
+
815
897
  return INT2NUM(sd);
816
898
  }
817
899
 
@@ -839,14 +921,15 @@ pgconn_socket_io(VALUE self)
839
921
  VALUE socket_io = this->socket_io;
840
922
 
841
923
  if ( !RTEST(socket_io) ) {
842
- if( (sd = PQsocket(this->pgconn)) < 0)
843
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
924
+ if( (sd = PQsocket(this->pgconn)) < 0){
925
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
926
+ }
844
927
 
845
928
  #ifdef _WIN32
846
929
  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
- }
930
+ if( ruby_sd == -1 )
931
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
932
+
850
933
  this->ruby_sd = ruby_sd;
851
934
  #else
852
935
  ruby_sd = sd;
@@ -911,7 +994,7 @@ pgconn_backend_key(VALUE self)
911
994
 
912
995
  cancel = (struct pg_cancel*)PQgetCancel(conn);
913
996
  if(cancel == NULL)
914
- rb_raise(rb_ePGerror,"Invalid connection!");
997
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
915
998
 
916
999
  if( cancel->be_pid != PQbackendPID(conn) )
917
1000
  rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
@@ -1447,8 +1530,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1447
1530
  * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1448
1531
  */
1449
1532
  static VALUE
1450
- pgconn_sync_describe_portal(self, stmt_name)
1451
- VALUE self, stmt_name;
1533
+ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1452
1534
  {
1453
1535
  PGresult *result;
1454
1536
  VALUE rb_pgresult;
@@ -1540,9 +1622,9 @@ pgconn_s_escape(VALUE self, VALUE string)
1540
1622
  if( !singleton ) {
1541
1623
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1542
1624
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1543
- if(error) {
1544
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1545
- }
1625
+ if(error)
1626
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1627
+
1546
1628
  } else {
1547
1629
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1548
1630
  }
@@ -1638,7 +1720,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
1638
1720
  {
1639
1721
  t_pg_connection *this = pg_get_connection_safe( self );
1640
1722
  char *escaped = NULL;
1641
- VALUE error;
1642
1723
  VALUE result = Qnil;
1643
1724
  int enc_idx = this->enc_idx;
1644
1725
 
@@ -1649,12 +1730,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
1649
1730
 
1650
1731
  escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1651
1732
  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
- }
1733
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1734
+
1658
1735
  result = rb_str_new2(escaped);
1659
1736
  PQfreemem(escaped);
1660
1737
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1677,7 +1754,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1677
1754
  {
1678
1755
  t_pg_connection *this = pg_get_connection_safe( self );
1679
1756
  char *escaped = NULL;
1680
- VALUE error;
1681
1757
  VALUE result = Qnil;
1682
1758
  int enc_idx = this->enc_idx;
1683
1759
 
@@ -1688,12 +1764,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1688
1764
 
1689
1765
  escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1690
1766
  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
- }
1767
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1768
+
1697
1769
  result = rb_str_new2(escaped);
1698
1770
  PQfreemem(escaped);
1699
1771
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1741,14 +1813,9 @@ static VALUE
1741
1813
  pgconn_set_single_row_mode(VALUE self)
1742
1814
  {
1743
1815
  PGconn *conn = pg_get_pgconn(self);
1744
- VALUE error;
1745
1816
 
1746
1817
  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
- }
1818
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1752
1819
 
1753
1820
  return self;
1754
1821
  }
@@ -1772,15 +1839,12 @@ static VALUE
1772
1839
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1773
1840
  {
1774
1841
  t_pg_connection *this = pg_get_connection_safe( self );
1775
- VALUE error;
1776
1842
 
1777
1843
  /* If called with no or nil parameters, use PQexec for compatibility */
1778
1844
  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
- }
1845
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
1846
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1847
+
1784
1848
  pgconn_wait_for_flush( self );
1785
1849
  return Qnil;
1786
1850
  }
@@ -1837,7 +1901,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1837
1901
  t_pg_connection *this = pg_get_connection_safe( self );
1838
1902
  int result;
1839
1903
  VALUE command, in_res_fmt;
1840
- VALUE error;
1841
1904
  int nParams;
1842
1905
  int resultFormat;
1843
1906
  struct query_params_data paramsData = { this->enc_idx };
@@ -1854,11 +1917,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1854
1917
 
1855
1918
  free_query_params( &paramsData );
1856
1919
 
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
- }
1920
+ if(result == 0)
1921
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1922
+
1862
1923
  pgconn_wait_for_flush( self );
1863
1924
  return Qnil;
1864
1925
  }
@@ -1890,7 +1951,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1890
1951
  int result;
1891
1952
  VALUE name, command, in_paramtypes;
1892
1953
  VALUE param;
1893
- VALUE error;
1894
1954
  int i = 0;
1895
1955
  int nParams = 0;
1896
1956
  Oid *paramTypes = NULL;
@@ -1919,9 +1979,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1919
1979
  xfree(paramTypes);
1920
1980
 
1921
1981
  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);
1982
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1925
1983
  }
1926
1984
  pgconn_wait_for_flush( self );
1927
1985
  return Qnil;
@@ -1965,7 +2023,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1965
2023
  t_pg_connection *this = pg_get_connection_safe( self );
1966
2024
  int result;
1967
2025
  VALUE name, in_res_fmt;
1968
- VALUE error;
1969
2026
  int nParams;
1970
2027
  int resultFormat;
1971
2028
  struct query_params_data paramsData = { this->enc_idx };
@@ -1987,11 +2044,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1987
2044
 
1988
2045
  free_query_params( &paramsData );
1989
2046
 
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
- }
2047
+ if(result == 0)
2048
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2049
+
1995
2050
  pgconn_wait_for_flush( self );
1996
2051
  return Qnil;
1997
2052
  }
@@ -2006,14 +2061,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2006
2061
  static VALUE
2007
2062
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2008
2063
  {
2009
- VALUE error;
2010
2064
  t_pg_connection *this = pg_get_connection_safe( self );
2011
2065
  /* 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
- }
2066
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
2067
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2068
+
2017
2069
  pgconn_wait_for_flush( self );
2018
2070
  return Qnil;
2019
2071
  }
@@ -2029,14 +2081,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2029
2081
  static VALUE
2030
2082
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2031
2083
  {
2032
- VALUE error;
2033
2084
  t_pg_connection *this = pg_get_connection_safe( self );
2034
2085
  /* 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
- }
2086
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
2087
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2088
+
2040
2089
  pgconn_wait_for_flush( self );
2041
2090
  return Qnil;
2042
2091
  }
@@ -2069,18 +2118,15 @@ pgconn_sync_get_result(VALUE self)
2069
2118
  * or *notifies* to see if the state has changed.
2070
2119
  */
2071
2120
  static VALUE
2072
- pgconn_consume_input(self)
2073
- VALUE self;
2121
+ pgconn_consume_input(VALUE self)
2074
2122
  {
2075
- VALUE error;
2076
2123
  PGconn *conn = pg_get_pgconn(self);
2077
2124
  /* returns 0 on error */
2078
2125
  if(PQconsumeInput(conn) == 0) {
2079
2126
  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);
2127
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2083
2128
  }
2129
+
2084
2130
  return Qnil;
2085
2131
  }
2086
2132
 
@@ -2092,18 +2138,15 @@ pgconn_consume_input(self)
2092
2138
  * #get_result would block. Otherwise returns +false+.
2093
2139
  */
2094
2140
  static VALUE
2095
- pgconn_is_busy(self)
2096
- VALUE self;
2141
+ pgconn_is_busy(VALUE self)
2097
2142
  {
2098
2143
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2099
2144
  }
2100
2145
 
2101
2146
  static VALUE
2102
- pgconn_sync_setnonblocking(self, state)
2103
- VALUE self, state;
2147
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2104
2148
  {
2105
2149
  int arg;
2106
- VALUE error;
2107
2150
  PGconn *conn = pg_get_pgconn(self);
2108
2151
  if(state == Qtrue)
2109
2152
  arg = 1;
@@ -2112,18 +2155,15 @@ pgconn_sync_setnonblocking(self, state)
2112
2155
  else
2113
2156
  rb_raise(rb_eArgError, "Boolean value expected");
2114
2157
 
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
- }
2158
+ if(PQsetnonblocking(conn, arg) == -1)
2159
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2160
+
2120
2161
  return Qnil;
2121
2162
  }
2122
2163
 
2123
2164
 
2124
2165
  static VALUE
2125
- pgconn_sync_isnonblocking(self)
2126
- VALUE self;
2166
+ pgconn_sync_isnonblocking(VALUE self)
2127
2167
  {
2128
2168
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2129
2169
  }
@@ -2132,14 +2172,10 @@ static VALUE
2132
2172
  pgconn_sync_flush(VALUE self)
2133
2173
  {
2134
2174
  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
- }
2175
+ int ret = PQflush(conn);
2176
+ if(ret == -1)
2177
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2178
+
2143
2179
  return (ret) ? Qfalse : Qtrue;
2144
2180
  }
2145
2181
 
@@ -2153,7 +2189,7 @@ pgconn_sync_cancel(VALUE self)
2153
2189
 
2154
2190
  cancel = PQgetCancel(pg_get_pgconn(self));
2155
2191
  if(cancel == NULL)
2156
- rb_raise(rb_ePGerror,"Invalid connection!");
2192
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2157
2193
 
2158
2194
  ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2159
2195
  if(ret == 1)
@@ -2362,7 +2398,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2362
2398
 
2363
2399
  /* Is the given timeout valid? */
2364
2400
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2365
- VALUE socket_io = pgconn_socket_io(self);
2401
+ VALUE socket_io;
2402
+
2403
+ /* before we wait for data, make sure everything has been sent */
2404
+ pgconn_async_flush(self);
2405
+ if ((retval=is_readable(conn)))
2406
+ return retval;
2407
+
2408
+ socket_io = pgconn_socket_io(self);
2366
2409
  /* Wait for the socket to become readable before checking again */
2367
2410
  ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2368
2411
  } else {
@@ -2377,7 +2420,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2377
2420
  /* Check for connection errors (PQisBusy is true on connection errors) */
2378
2421
  if ( PQconsumeInput(conn) == 0 ){
2379
2422
  pgconn_close_socket_io(self);
2380
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2423
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2381
2424
  }
2382
2425
  }
2383
2426
 
@@ -2390,8 +2433,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2390
2433
  *
2391
2434
  * Attempts to flush any queued output data to the server.
2392
2435
  * Returns +true+ if data is successfully flushed, +false+
2393
- * if not (can only return +false+ if connection is
2394
- * nonblocking.
2436
+ * if not. It can only return +false+ if connection is
2437
+ * in nonblocking mode.
2395
2438
  * Raises PG::Error if some other failure occurred.
2396
2439
  */
2397
2440
  static VALUE
@@ -2527,11 +2570,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2527
2570
  Check_Type(buffer, T_STRING);
2528
2571
 
2529
2572
  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
- }
2573
+ if(ret == -1)
2574
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2575
+
2535
2576
  RB_GC_GUARD(intermediate);
2536
2577
  RB_GC_GUARD(buffer);
2537
2578
 
@@ -2542,7 +2583,6 @@ static VALUE
2542
2583
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2543
2584
  {
2544
2585
  VALUE str;
2545
- VALUE error;
2546
2586
  int ret;
2547
2587
  const char *error_message = NULL;
2548
2588
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2553,11 +2593,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2553
2593
  error_message = pg_cstr_enc(str, this->enc_idx);
2554
2594
 
2555
2595
  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
- }
2596
+ if(ret == -1)
2597
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2598
+
2561
2599
  return (ret) ? Qtrue : Qfalse;
2562
2600
  }
2563
2601
 
@@ -2565,7 +2603,6 @@ static VALUE
2565
2603
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2566
2604
  {
2567
2605
  VALUE async_in;
2568
- VALUE error;
2569
2606
  VALUE result;
2570
2607
  int ret;
2571
2608
  char *buffer;
@@ -2585,10 +2622,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2585
2622
  }
2586
2623
 
2587
2624
  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);
2625
+ if(ret == -2){ /* error */
2626
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2592
2627
  }
2593
2628
  if(ret == -1) { /* No data left */
2594
2629
  return Qnil;
@@ -2893,9 +2928,9 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2893
2928
 
2894
2929
  Check_Type(str, T_STRING);
2895
2930
 
2896
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2897
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2898
- }
2931
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2932
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2933
+
2899
2934
  pgconn_set_internal_encoding_index( self );
2900
2935
 
2901
2936
  return Qnil;
@@ -3528,11 +3563,10 @@ pgconn_enter_pipeline_mode(VALUE self)
3528
3563
  {
3529
3564
  PGconn *conn = pg_get_pgconn(self);
3530
3565
  int res = PQenterPipelineMode(conn);
3531
- if( res == 1 ) {
3532
- return Qnil;
3533
- } else {
3534
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3535
- }
3566
+ if( res != 1 )
3567
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3568
+
3569
+ return Qnil;
3536
3570
  }
3537
3571
 
3538
3572
  /*
@@ -3551,11 +3585,10 @@ pgconn_exit_pipeline_mode(VALUE self)
3551
3585
  {
3552
3586
  PGconn *conn = pg_get_pgconn(self);
3553
3587
  int res = PQexitPipelineMode(conn);
3554
- if( res == 1 ) {
3555
- return Qnil;
3556
- } else {
3557
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3558
- }
3588
+ if( res != 1 )
3589
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3590
+
3591
+ return Qnil;
3559
3592
  }
3560
3593
 
3561
3594
 
@@ -3575,11 +3608,10 @@ pgconn_pipeline_sync(VALUE self)
3575
3608
  {
3576
3609
  PGconn *conn = pg_get_pgconn(self);
3577
3610
  int res = PQpipelineSync(conn);
3578
- if( res == 1 ) {
3579
- return Qnil;
3580
- } else {
3581
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3582
- }
3611
+ if( res != 1 )
3612
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3613
+
3614
+ return Qnil;
3583
3615
  }
3584
3616
 
3585
3617
  /*
@@ -3599,11 +3631,10 @@ pgconn_send_flush_request(VALUE self)
3599
3631
  {
3600
3632
  PGconn *conn = pg_get_pgconn(self);
3601
3633
  int res = PQsendFlushRequest(conn);
3602
- if( res == 1 ) {
3603
- return Qnil;
3604
- } else {
3605
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3606
- }
3634
+ if( res != 1 )
3635
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3636
+
3637
+ return Qnil;
3607
3638
  }
3608
3639
 
3609
3640
  #endif
@@ -3634,7 +3665,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3634
3665
 
3635
3666
  lo_oid = lo_creat(conn, mode);
3636
3667
  if (lo_oid == 0)
3637
- rb_raise(rb_ePGerror, "lo_creat failed");
3668
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3638
3669
 
3639
3670
  return UINT2NUM(lo_oid);
3640
3671
  }
@@ -3655,7 +3686,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3655
3686
 
3656
3687
  ret = lo_create(conn, lo_oid);
3657
3688
  if (ret == InvalidOid)
3658
- rb_raise(rb_ePGerror, "lo_create failed");
3689
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3659
3690
 
3660
3691
  return UINT2NUM(ret);
3661
3692
  }
@@ -3679,7 +3710,7 @@ pgconn_loimport(VALUE self, VALUE filename)
3679
3710
 
3680
3711
  lo_oid = lo_import(conn, StringValueCStr(filename));
3681
3712
  if (lo_oid == 0) {
3682
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3713
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3683
3714
  }
3684
3715
  return UINT2NUM(lo_oid);
3685
3716
  }
@@ -3700,7 +3731,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3700
3731
  oid = NUM2UINT(lo_oid);
3701
3732
 
3702
3733
  if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3703
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3734
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3704
3735
  }
3705
3736
  return Qnil;
3706
3737
  }
@@ -3731,7 +3762,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3731
3762
  mode = NUM2INT(nmode);
3732
3763
 
3733
3764
  if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3734
- rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3765
+ pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3735
3766
  }
3736
3767
  return INT2FIX(fd);
3737
3768
  }
@@ -3753,11 +3784,11 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3753
3784
  Check_Type(buffer, T_STRING);
3754
3785
 
3755
3786
  if( RSTRING_LEN(buffer) < 0) {
3756
- rb_raise(rb_ePGerror, "write buffer zero string");
3787
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3757
3788
  }
3758
3789
  if((n = lo_write(conn, fd, StringValuePtr(buffer),
3759
3790
  RSTRING_LEN(buffer))) < 0) {
3760
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3791
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3761
3792
  }
3762
3793
 
3763
3794
  return INT2FIX(n);
@@ -3780,16 +3811,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3780
3811
  VALUE str;
3781
3812
  char *buffer;
3782
3813
 
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
- }
3814
+ if (len < 0)
3815
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3790
3816
 
3817
+ buffer = ALLOC_N(char, len);
3791
3818
  if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3792
- rb_raise(rb_ePGerror, "lo_read failed");
3819
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3793
3820
 
3794
3821
  if(ret == 0) {
3795
3822
  xfree(buffer);
@@ -3819,7 +3846,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3819
3846
  int ret;
3820
3847
 
3821
3848
  if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3822
- rb_raise(rb_ePGerror, "lo_lseek failed");
3849
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3823
3850
  }
3824
3851
 
3825
3852
  return INT2FIX(ret);
@@ -3839,7 +3866,7 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3839
3866
  int lo_desc = NUM2INT(in_lo_desc);
3840
3867
 
3841
3868
  if((position = lo_tell(conn, lo_desc)) < 0)
3842
- rb_raise(rb_ePGerror,"lo_tell failed");
3869
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3843
3870
 
3844
3871
  return INT2FIX(position);
3845
3872
  }
@@ -3858,7 +3885,7 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3858
3885
  size_t len = NUM2INT(in_len);
3859
3886
 
3860
3887
  if(lo_truncate(conn,lo_desc,len) < 0)
3861
- rb_raise(rb_ePGerror,"lo_truncate failed");
3888
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3862
3889
 
3863
3890
  return Qnil;
3864
3891
  }
@@ -3876,7 +3903,7 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3876
3903
  int lo_desc = NUM2INT(in_lo_desc);
3877
3904
 
3878
3905
  if(lo_close(conn,lo_desc) < 0)
3879
- rb_raise(rb_ePGerror,"lo_close failed");
3906
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3880
3907
 
3881
3908
  return Qnil;
3882
3909
  }
@@ -3894,7 +3921,7 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3894
3921
  Oid oid = NUM2UINT(in_oid);
3895
3922
 
3896
3923
  if(lo_unlink(conn,oid) < 0)
3897
- rb_raise(rb_ePGerror,"lo_unlink failed");
3924
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3898
3925
 
3899
3926
  return Qnil;
3900
3927
  }
@@ -4301,7 +4328,7 @@ pgconn_field_name_type_get(VALUE self)
4301
4328
  * Document-class: PG::Connection
4302
4329
  */
4303
4330
  void
4304
- init_pg_connection()
4331
+ init_pg_connection(void)
4305
4332
  {
4306
4333
  s_id_encode = rb_intern("encode");
4307
4334
  s_id_autoclose_set = rb_intern("autoclose=");
@@ -4328,6 +4355,7 @@ init_pg_connection()
4328
4355
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4329
4356
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4330
4357
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4358
+ rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
4331
4359
  rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4332
4360
  rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4333
4361
 
@@ -4345,6 +4373,9 @@ init_pg_connection()
4345
4373
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4346
4374
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4347
4375
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4376
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
4377
+ rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
4378
+ #endif
4348
4379
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4349
4380
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4350
4381
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);