pg 1.5.9-x86-mingw32 → 1.6.0.rc1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/ext/pg_connection.c CHANGED
@@ -30,11 +30,8 @@ static VALUE pgconn_async_flush(VALUE self);
30
30
  /*
31
31
  * Convenience function to raise connection errors
32
32
  */
33
- #ifdef __GNUC__
34
- __attribute__((format(printf, 3, 4)))
35
- #endif
36
- NORETURN( static void
37
- pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...))
33
+ void
34
+ pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
38
35
  {
39
36
  VALUE msg, error;
40
37
  va_list ap;
@@ -96,6 +93,20 @@ pg_get_pgconn( VALUE self )
96
93
  }
97
94
 
98
95
 
96
+ void
97
+ pg_unwrap_socket_io( VALUE self, VALUE *p_socket_io, int ruby_sd )
98
+ {
99
+ if ( RTEST(*p_socket_io) ) {
100
+ #if defined(_WIN32)
101
+ if( rb_w32_unwrap_io_handle(ruby_sd) )
102
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
103
+ #endif
104
+ rb_funcall( *p_socket_io, rb_intern("close"), 0 );
105
+ }
106
+
107
+ RB_OBJ_WRITE(self, p_socket_io, Qnil);
108
+ }
109
+
99
110
 
100
111
  /*
101
112
  * Close the associated socket IO object if there is one.
@@ -104,17 +115,7 @@ static void
104
115
  pgconn_close_socket_io( VALUE self )
105
116
  {
106
117
  t_pg_connection *this = pg_get_connection( self );
107
- VALUE socket_io = this->socket_io;
108
-
109
- if ( RTEST(socket_io) ) {
110
- #if defined(_WIN32)
111
- if( rb_w32_unwrap_io_handle(this->ruby_sd) )
112
- pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
113
- #endif
114
- rb_funcall( socket_io, rb_intern("close"), 0 );
115
- }
116
-
117
- RB_OBJ_WRITE(self, &this->socket_io, Qnil);
118
+ pg_unwrap_socket_io( self, &this->socket_io, this->ruby_sd);
118
119
  }
119
120
 
120
121
 
@@ -230,7 +231,7 @@ static const rb_data_type_t pg_connection_type = {
230
231
  pgconn_gc_mark,
231
232
  pgconn_gc_free,
232
233
  pgconn_memsize,
233
- pg_compact_callback(pgconn_gc_compact),
234
+ pgconn_gc_compact,
234
235
  },
235
236
  0,
236
237
  0,
@@ -419,7 +420,6 @@ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
419
420
  }
420
421
 
421
422
 
422
- #ifdef HAVE_PQENCRYPTPASSWORDCONN
423
423
  static VALUE
424
424
  pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
425
425
  {
@@ -443,7 +443,6 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
443
443
 
444
444
  return rval;
445
445
  }
446
- #endif
447
446
 
448
447
 
449
448
  /*
@@ -609,7 +608,7 @@ pgconn_reset_start(VALUE self)
609
608
  * conn.reset_poll -> Integer
610
609
  *
611
610
  * Checks the status of a connection reset operation.
612
- * See #connect_start and #connect_poll for
611
+ * See Connection.connect_start and #connect_poll for
613
612
  * usage information and return values.
614
613
  */
615
614
  static VALUE
@@ -760,7 +759,6 @@ pgconn_options(VALUE self)
760
759
  *
761
760
  * Returns the connection options used by a live connection.
762
761
  *
763
- * Available since PostgreSQL-9.3
764
762
  */
765
763
  static VALUE
766
764
  pgconn_conninfo( VALUE self )
@@ -920,13 +918,42 @@ pgconn_socket(VALUE self)
920
918
  return INT2NUM(sd);
921
919
  }
922
920
 
921
+
922
+ VALUE
923
+ pg_wrap_socket_io(int sd, VALUE self, VALUE *p_socket_io, int *p_ruby_sd)
924
+ {
925
+ int ruby_sd;
926
+ VALUE cSocket;
927
+ VALUE socket_io = *p_socket_io;
928
+
929
+ #ifdef _WIN32
930
+ ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
931
+ if( ruby_sd == -1 )
932
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
933
+
934
+ *p_ruby_sd = ruby_sd;
935
+ #else
936
+ *p_ruby_sd = ruby_sd = sd;
937
+ #endif
938
+
939
+ cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
940
+ socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
941
+
942
+ /* Disable autoclose feature */
943
+ rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
944
+
945
+ RB_OBJ_WRITE(self, p_socket_io, socket_io);
946
+
947
+ return socket_io;
948
+ }
949
+
923
950
  /*
924
951
  * call-seq:
925
952
  * conn.socket_io() -> IO
926
953
  *
927
954
  * Fetch an IO object created from the Connection's underlying socket.
928
955
  * This object can be used per <tt>socket_io.wait_readable</tt>, <tt>socket_io.wait_writable</tt> or for <tt>IO.select</tt> to wait for events while running asynchronous API calls.
929
- * <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
956
+ * <tt>IO#wait_*able</tt> is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
930
957
  *
931
958
  * The IO object can change while the connection is established, but is memorized afterwards.
932
959
  * So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
@@ -937,37 +964,17 @@ pgconn_socket(VALUE self)
937
964
  static VALUE
938
965
  pgconn_socket_io(VALUE self)
939
966
  {
940
- int sd;
941
- int ruby_sd;
942
967
  t_pg_connection *this = pg_get_connection_safe( self );
943
- VALUE cSocket;
944
- VALUE socket_io = this->socket_io;
945
968
 
946
- if ( !RTEST(socket_io) ) {
969
+ if ( !RTEST(this->socket_io) ) {
970
+ int sd;
947
971
  if( (sd = PQsocket(this->pgconn)) < 0){
948
972
  pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
949
973
  }
950
-
951
- #ifdef _WIN32
952
- ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
953
- if( ruby_sd == -1 )
954
- pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
955
-
956
- this->ruby_sd = ruby_sd;
957
- #else
958
- ruby_sd = sd;
959
- #endif
960
-
961
- cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
962
- socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
963
-
964
- /* Disable autoclose feature */
965
- rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
966
-
967
- RB_OBJ_WRITE(self, &this->socket_io, socket_io);
974
+ return pg_wrap_socket_io( sd, self, &this->socket_io, &this->ruby_sd);
968
975
  }
969
976
 
970
- return socket_io;
977
+ return this->socket_io;
971
978
  }
972
979
 
973
980
  /*
@@ -984,6 +991,7 @@ pgconn_backend_pid(VALUE self)
984
991
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
985
992
  }
986
993
 
994
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
987
995
  typedef struct
988
996
  {
989
997
  struct sockaddr_storage addr;
@@ -1028,6 +1036,7 @@ pgconn_backend_key(VALUE self)
1028
1036
 
1029
1037
  return INT2NUM(be_key);
1030
1038
  }
1039
+ #endif
1031
1040
 
1032
1041
  /*
1033
1042
  * call-seq:
@@ -1300,7 +1309,7 @@ alloc_query_params(struct query_params_data *paramsData)
1300
1309
  paramsData->lengths[i] = 0;
1301
1310
  } else {
1302
1311
  t_pg_coder_enc_func enc_func = pg_coder_enc_func( conv );
1303
- VALUE intermediate;
1312
+ VALUE intermediate = Qnil;
1304
1313
 
1305
1314
  /* 1st pass for retiving the required memory space */
1306
1315
  int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
@@ -1340,8 +1349,6 @@ alloc_query_params(struct query_params_data *paramsData)
1340
1349
  required_pool_size += len;
1341
1350
  }
1342
1351
  }
1343
-
1344
- RB_GC_GUARD(intermediate);
1345
1352
  }
1346
1353
  }
1347
1354
  }
@@ -1516,6 +1523,19 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1516
1523
  return rb_pgresult;
1517
1524
  }
1518
1525
 
1526
+ static VALUE
1527
+ pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*func)(PGconn *, const char *))
1528
+ {
1529
+ PGresult *result;
1530
+ VALUE rb_pgresult;
1531
+ t_pg_connection *this = pg_get_connection_safe( self );
1532
+ const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
1533
+ result = func(this->pgconn, stmt);
1534
+ rb_pgresult = pg_new_result(result, self);
1535
+ pg_result_check(rb_pgresult);
1536
+ return rb_pgresult;
1537
+ }
1538
+
1519
1539
  /*
1520
1540
  * call-seq:
1521
1541
  * conn.sync_describe_prepared( statement_name ) -> PG::Result
@@ -1527,20 +1547,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1527
1547
  static VALUE
1528
1548
  pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1529
1549
  {
1530
- PGresult *result;
1531
- VALUE rb_pgresult;
1532
- t_pg_connection *this = pg_get_connection_safe( self );
1533
- const char *stmt;
1534
- if(NIL_P(stmt_name)) {
1535
- stmt = NULL;
1536
- }
1537
- else {
1538
- stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1539
- }
1540
- result = gvl_PQdescribePrepared(this->pgconn, stmt);
1541
- rb_pgresult = pg_new_result(result, self);
1542
- pg_result_check(rb_pgresult);
1543
- return rb_pgresult;
1550
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePrepared);
1544
1551
  }
1545
1552
 
1546
1553
 
@@ -1555,23 +1562,44 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1555
1562
  static VALUE
1556
1563
  pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1557
1564
  {
1558
- PGresult *result;
1559
- VALUE rb_pgresult;
1560
- t_pg_connection *this = pg_get_connection_safe( self );
1561
- const char *stmt;
1562
- if(NIL_P(stmt_name)) {
1563
- stmt = NULL;
1564
- }
1565
- else {
1566
- stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1567
- }
1568
- result = gvl_PQdescribePortal(this->pgconn, stmt);
1569
- rb_pgresult = pg_new_result(result, self);
1570
- pg_result_check(rb_pgresult);
1571
- return rb_pgresult;
1565
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePortal);
1572
1566
  }
1573
1567
 
1574
1568
 
1569
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
1570
+ /*
1571
+ * call-seq:
1572
+ * conn.sync_close_prepared( stmt_name ) -> PG::Result
1573
+ *
1574
+ * This function has the same behavior as #async_close_prepared, but is implemented using the synchronous command processing API of libpq.
1575
+ * See #async_exec for the differences between the two API variants.
1576
+ * It's not recommended to use explicit sync or async variants but #close_prepared instead, unless you have a good reason to do so.
1577
+ *
1578
+ * Available since PostgreSQL-17.
1579
+ */
1580
+ static VALUE
1581
+ pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
1582
+ {
1583
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQclosePrepared);
1584
+ }
1585
+
1586
+ /*
1587
+ * call-seq:
1588
+ * conn.sync_close_portal( portal_name ) -> PG::Result
1589
+ *
1590
+ * This function has the same behavior as #async_close_portal, but is implemented using the synchronous command processing API of libpq.
1591
+ * See #async_exec for the differences between the two API variants.
1592
+ * It's not recommended to use explicit sync or async variants but #close_portal instead, unless you have a good reason to do so.
1593
+ *
1594
+ * Available since PostgreSQL-17.
1595
+ */
1596
+ static VALUE
1597
+ pgconn_sync_close_portal(VALUE self, VALUE stmt_name)
1598
+ {
1599
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQclosePortal);
1600
+ }
1601
+ #endif
1602
+
1575
1603
  /*
1576
1604
  * call-seq:
1577
1605
  * conn.make_empty_pgresult( status ) -> PG::Result
@@ -1588,6 +1616,7 @@ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1588
1616
  * * +PGRES_FATAL_ERROR+
1589
1617
  * * +PGRES_COPY_BOTH+
1590
1618
  * * +PGRES_SINGLE_TUPLE+
1619
+ * * +PGRES_TUPLES_CHUNK+
1591
1620
  * * +PGRES_PIPELINE_SYNC+
1592
1621
  * * +PGRES_PIPELINE_ABORTED+
1593
1622
  */
@@ -1812,14 +1841,11 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1812
1841
  * (column names, types, etc) that an ordinary Result object for the query
1813
1842
  * would have.
1814
1843
  *
1815
- * *Caution:* While processing a query, the server may return some rows and
1816
- * then encounter an error, causing the query to be aborted. Ordinarily, pg
1817
- * discards any such rows and reports only the error. But in single-row mode,
1818
- * those rows will have already been returned to the application. Hence, the
1819
- * application will see some Result objects followed by an Error raised in get_result.
1820
- * For proper transactional behavior, the application must be designed to discard
1821
- * or undo whatever has been done with the previously-processed rows, if the query
1822
- * ultimately fails.
1844
+ * *Caution:* While processing a query, the server may return some rows and then encounter an error, causing the query to be aborted.
1845
+ * Ordinarily, pg discards any such rows and reports only the error.
1846
+ * But in single-row or chunked mode, some rows may have already been returned to the application.
1847
+ * Hence, the application will see some PGRES_SINGLE_TUPLE or PGRES_TUPLES_CHUNK PG::Result objects followed by a PG::Error raised in get_result.
1848
+ * For proper transactional behavior, the application must be designed to discard or undo whatever has been done with the previously-processed rows, if the query ultimately fails.
1823
1849
  *
1824
1850
  * Example:
1825
1851
  * conn.send_query( "your SQL command" )
@@ -1839,10 +1865,49 @@ pgconn_set_single_row_mode(VALUE self)
1839
1865
 
1840
1866
  rb_check_frozen(self);
1841
1867
  if( PQsetSingleRowMode(conn) == 0 )
1842
- pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1868
+ pg_raise_conn_error( rb_ePGerror, self, "PQsetSingleRowMode %s", PQerrorMessage(conn));
1869
+
1870
+ return self;
1871
+ }
1872
+
1873
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
1874
+ /*
1875
+ * call-seq:
1876
+ * conn.set_chunked_rows_mode -> self
1877
+ *
1878
+ * Select chunked mode for the currently-executing query.
1879
+ *
1880
+ * This function is similar to set_single_row_mode, except that it specifies retrieval of up to +chunk_size+ rows per PGresult, not necessarily just one row.
1881
+ * This function can only be called immediately after send_query or one of its sibling functions, before any other operation on the connection such as consume_input or get_result.
1882
+ * If called at the correct time, the function activates chunked mode for the current query.
1883
+ * Otherwise the mode stays unchanged and the function raises an error.
1884
+ * In any case, the mode reverts to normal after completion of the current query.
1885
+ *
1886
+ * Example:
1887
+ * conn.send_query( "your SQL command" )
1888
+ * conn.set_chunked_rows_mode(10)
1889
+ * loop do
1890
+ * res = conn.get_result or break
1891
+ * res.check
1892
+ * res.each do |row|
1893
+ * # do something with the received max. 10 rows
1894
+ * end
1895
+ * end
1896
+ *
1897
+ * Available since PostgreSQL-17
1898
+ */
1899
+ static VALUE
1900
+ pgconn_set_chunked_rows_mode(VALUE self, VALUE chunk_size)
1901
+ {
1902
+ PGconn *conn = pg_get_pgconn(self);
1903
+
1904
+ rb_check_frozen(self);
1905
+ if( PQsetChunkedRowsMode(conn, NUM2INT(chunk_size)) == 0 )
1906
+ pg_raise_conn_error( rb_ePGerror, self, "PQsetChunkedRowsMode %s", PQerrorMessage(conn));
1843
1907
 
1844
1908
  return self;
1845
1909
  }
1910
+ #endif
1846
1911
 
1847
1912
  static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1848
1913
 
@@ -1867,7 +1932,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1867
1932
  /* If called with no or nil parameters, use PQexec for compatibility */
1868
1933
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1869
1934
  if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
1870
- pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1935
+ pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));
1871
1936
 
1872
1937
  pgconn_wait_for_flush( self );
1873
1938
  return Qnil;
@@ -1942,7 +2007,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1942
2007
  free_query_params( &paramsData );
1943
2008
 
1944
2009
  if(result == 0)
1945
- pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2010
+ pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryParams %s", PQerrorMessage(this->pgconn));
1946
2011
 
1947
2012
  pgconn_wait_for_flush( self );
1948
2013
  return Qnil;
@@ -2003,7 +2068,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2003
2068
  xfree(paramTypes);
2004
2069
 
2005
2070
  if(result == 0) {
2006
- pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2071
+ pg_raise_conn_error( rb_eUnableToSend, self, "PQsendPrepare %s", PQerrorMessage(this->pgconn));
2007
2072
  }
2008
2073
  pgconn_wait_for_flush( self );
2009
2074
  return Qnil;
@@ -2069,7 +2134,21 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2069
2134
  free_query_params( &paramsData );
2070
2135
 
2071
2136
  if(result == 0)
2072
- pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2137
+ pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQueryPrepared %s", PQerrorMessage(this->pgconn));
2138
+
2139
+ pgconn_wait_for_flush( self );
2140
+ return Qnil;
2141
+ }
2142
+
2143
+
2144
+ static VALUE
2145
+ pgconn_send_describe_close_prepared_portal(VALUE self, VALUE name, int (*func)(PGconn *, const char *), const char *funame)
2146
+ {
2147
+ t_pg_connection *this = pg_get_connection_safe( self );
2148
+ const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
2149
+ /* returns 0 on failure */
2150
+ if(func(this->pgconn, stmt) == 0)
2151
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s %s", funame, PQerrorMessage(this->pgconn));
2073
2152
 
2074
2153
  pgconn_wait_for_flush( self );
2075
2154
  return Qnil;
@@ -2085,13 +2164,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2085
2164
  static VALUE
2086
2165
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2087
2166
  {
2088
- t_pg_connection *this = pg_get_connection_safe( self );
2089
- /* returns 0 on failure */
2090
- if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
2091
- pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2092
-
2093
- pgconn_wait_for_flush( self );
2094
- return Qnil;
2167
+ return pgconn_send_describe_close_prepared_portal(
2168
+ self, stmt_name, gvl_PQsendDescribePrepared,
2169
+ "PQsendDescribePrepared");
2095
2170
  }
2096
2171
 
2097
2172
 
@@ -2105,16 +2180,48 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2105
2180
  static VALUE
2106
2181
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2107
2182
  {
2108
- t_pg_connection *this = pg_get_connection_safe( self );
2109
- /* returns 0 on failure */
2110
- if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
2111
- pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2183
+ return pgconn_send_describe_close_prepared_portal(
2184
+ self, portal, gvl_PQsendDescribePortal,
2185
+ "PQsendDescribePortal");
2186
+ }
2112
2187
 
2113
- pgconn_wait_for_flush( self );
2114
- return Qnil;
2188
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
2189
+ /*
2190
+ * call-seq:
2191
+ * conn.send_close_prepared( statement_name ) -> nil
2192
+ *
2193
+ * Asynchronously send _command_ to the server. Does not block.
2194
+ * Use in combination with +conn.get_result+.
2195
+ *
2196
+ * Available since PostgreSQL-17.
2197
+ */
2198
+ static VALUE
2199
+ pgconn_send_close_prepared(VALUE self, VALUE stmt_name)
2200
+ {
2201
+ return pgconn_send_describe_close_prepared_portal(
2202
+ self, stmt_name, gvl_PQsendClosePrepared,
2203
+ "PQsendClosePrepared");
2115
2204
  }
2116
2205
 
2117
2206
 
2207
+ /*
2208
+ * call-seq:
2209
+ * conn.send_close_portal( portal_name ) -> nil
2210
+ *
2211
+ * Asynchronously send _command_ to the server. Does not block.
2212
+ * Use in combination with +conn.get_result+.
2213
+ *
2214
+ * Available since PostgreSQL-17.
2215
+ */
2216
+ static VALUE
2217
+ pgconn_send_close_portal(VALUE self, VALUE portal)
2218
+ {
2219
+ return pgconn_send_describe_close_prepared_portal(
2220
+ self, portal, gvl_PQsendClosePortal,
2221
+ "PQsendClosePortal");
2222
+ }
2223
+ #endif
2224
+
2118
2225
  static VALUE
2119
2226
  pgconn_sync_get_result(VALUE self)
2120
2227
  {
@@ -2204,6 +2311,7 @@ pgconn_sync_flush(VALUE self)
2204
2311
  return (ret) ? Qfalse : Qtrue;
2205
2312
  }
2206
2313
 
2314
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
2207
2315
  static VALUE
2208
2316
  pgconn_sync_cancel(VALUE self)
2209
2317
  {
@@ -2225,6 +2333,7 @@ pgconn_sync_cancel(VALUE self)
2225
2333
  PQfreeCancel(cancel);
2226
2334
  return retval;
2227
2335
  }
2336
+ #endif
2228
2337
 
2229
2338
 
2230
2339
  /*
@@ -2271,8 +2380,9 @@ pgconn_notifies(VALUE self)
2271
2380
  static int
2272
2381
  rb_io_descriptor(VALUE io)
2273
2382
  {
2383
+ rb_io_t *fptr;
2274
2384
  Check_Type(io, T_FILE);
2275
- rb_io_t *fptr = RFILE(io)->fptr;
2385
+ fptr = RFILE(io)->fptr;
2276
2386
  rb_io_check_closed(fptr);
2277
2387
  return fptr->fd;
2278
2388
  }
@@ -2568,7 +2678,7 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2568
2678
  VALUE value;
2569
2679
  VALUE buffer = Qnil;
2570
2680
  VALUE encoder;
2571
- VALUE intermediate;
2681
+ VALUE intermediate = Qnil;
2572
2682
  t_pg_coder *p_coder = NULL;
2573
2683
 
2574
2684
  rb_scan_args( argc, argv, "11", &value, &encoder );
@@ -2607,7 +2717,6 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2607
2717
  if(ret == -1)
2608
2718
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2609
2719
 
2610
- RB_GC_GUARD(intermediate);
2611
2720
  RB_GC_GUARD(buffer);
2612
2721
 
2613
2722
  return (ret) ? Qtrue : Qfalse;
@@ -2702,7 +2811,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2702
2811
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2703
2812
  }
2704
2813
 
2705
- #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2706
2814
  /*
2707
2815
  * call-seq:
2708
2816
  * conn.set_error_context_visibility( context_visibility ) -> Integer
@@ -2722,7 +2830,6 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2722
2830
  *
2723
2831
  * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2724
2832
  *
2725
- * Available since PostgreSQL-9.6
2726
2833
  */
2727
2834
  static VALUE
2728
2835
  pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
@@ -2731,7 +2838,6 @@ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2731
2838
  PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2732
2839
  return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2733
2840
  }
2734
- #endif
2735
2841
 
2736
2842
  /*
2737
2843
  * call-seq:
@@ -3459,6 +3565,21 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3459
3565
  return rb_pgresult;
3460
3566
  }
3461
3567
 
3568
+ static VALUE
3569
+ pgconn_async_describe_close_prepared_potral(VALUE self, VALUE name, VALUE
3570
+ (*func)(VALUE, VALUE))
3571
+ {
3572
+ VALUE rb_pgresult = Qnil;
3573
+
3574
+ pgconn_discard_results( self );
3575
+ func( self, name );
3576
+ rb_pgresult = pgconn_async_get_last_result( self );
3577
+
3578
+ if ( rb_block_given_p() ) {
3579
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3580
+ }
3581
+ return rb_pgresult;
3582
+ }
3462
3583
 
3463
3584
  /*
3464
3585
  * call-seq:
@@ -3471,16 +3592,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3471
3592
  static VALUE
3472
3593
  pgconn_async_describe_portal(VALUE self, VALUE portal)
3473
3594
  {
3474
- VALUE rb_pgresult = Qnil;
3475
-
3476
- pgconn_discard_results( self );
3477
- pgconn_send_describe_portal( self, portal );
3478
- rb_pgresult = pgconn_async_get_last_result( self );
3479
-
3480
- if ( rb_block_given_p() ) {
3481
- return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3482
- }
3483
- return rb_pgresult;
3595
+ return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_describe_portal);
3484
3596
  }
3485
3597
 
3486
3598
 
@@ -3495,27 +3607,64 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3495
3607
  static VALUE
3496
3608
  pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3497
3609
  {
3498
- VALUE rb_pgresult = Qnil;
3499
-
3500
- pgconn_discard_results( self );
3501
- pgconn_send_describe_prepared( self, stmt_name );
3502
- rb_pgresult = pgconn_async_get_last_result( self );
3610
+ return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_describe_prepared);
3611
+ }
3503
3612
 
3504
- if ( rb_block_given_p() ) {
3505
- return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3506
- }
3507
- return rb_pgresult;
3613
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
3614
+ /*
3615
+ * call-seq:
3616
+ * conn.close_prepared( statement_name ) -> PG::Result
3617
+ *
3618
+ * Submits a request to close the specified prepared statement, and waits for completion.
3619
+ * close_prepared allows an application to close a previously prepared statement.
3620
+ * Closing a statement releases all of its associated resources on the server and allows its name to be reused.
3621
+ * It's the same as using the +DEALLOCATE+ SQL statement, but on a lower protocol level.
3622
+ *
3623
+ * +statement_name+ can be "" or +nil+ to reference the unnamed statement.
3624
+ * It is fine if no statement exists with this name, in that case the operation is a no-op.
3625
+ * On success, a PG::Result with status PGRES_COMMAND_OK is returned.
3626
+ *
3627
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLOSEPREPARED].
3628
+ *
3629
+ * Available since PostgreSQL-17.
3630
+ */
3631
+ static VALUE
3632
+ pgconn_async_close_prepared(VALUE self, VALUE stmt_name)
3633
+ {
3634
+ return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_close_prepared);
3508
3635
  }
3509
3636
 
3637
+ /*
3638
+ * call-seq:
3639
+ * conn.close_portal( portal_name ) -> PG::Result
3640
+ *
3641
+ * Submits a request to close the specified portal, and waits for completion.
3642
+ *
3643
+ * close_portal allows an application to trigger a close of a previously created portal.
3644
+ * Closing a portal releases all of its associated resources on the server and allows its name to be reused.
3645
+ * (pg does not provide any direct access to portals, but you can use this function to close a cursor created with a DECLARE CURSOR SQL command.)
3646
+ *
3647
+ * +portal_name+ can be "" or +nil+ to reference the unnamed portal.
3648
+ * It is fine if no portal exists with this name, in that case the operation is a no-op.
3649
+ * On success, a PG::Result with status PGRES_COMMAND_OK is returned.
3650
+ *
3651
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQCLOSEPORTAL].
3652
+ *
3653
+ * Available since PostgreSQL-17.
3654
+ */
3655
+ static VALUE
3656
+ pgconn_async_close_portal(VALUE self, VALUE portal)
3657
+ {
3658
+ return pgconn_async_describe_close_prepared_potral(self, portal, pgconn_send_close_portal);
3659
+ }
3660
+ #endif
3510
3661
 
3511
- #ifdef HAVE_PQSSLATTRIBUTE
3512
3662
  /*
3513
3663
  * call-seq:
3514
3664
  * conn.ssl_in_use? -> Boolean
3515
3665
  *
3516
3666
  * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3517
3667
  *
3518
- * Available since PostgreSQL-9.5
3519
3668
  */
3520
3669
  static VALUE
3521
3670
  pgconn_ssl_in_use(VALUE self)
@@ -3549,7 +3698,6 @@ pgconn_ssl_in_use(VALUE self)
3549
3698
  *
3550
3699
  * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3551
3700
  *
3552
- * Available since PostgreSQL-9.5
3553
3701
  */
3554
3702
  static VALUE
3555
3703
  pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
@@ -3568,7 +3716,6 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
3568
3716
  *
3569
3717
  * See also #ssl_attribute
3570
3718
  *
3571
- * Available since PostgreSQL-9.5
3572
3719
  */
3573
3720
  static VALUE
3574
3721
  pgconn_ssl_attribute_names(VALUE self)
@@ -3584,8 +3731,6 @@ pgconn_ssl_attribute_names(VALUE self)
3584
3731
  }
3585
3732
 
3586
3733
 
3587
- #endif
3588
-
3589
3734
 
3590
3735
  #ifdef HAVE_PQENTERPIPELINEMODE
3591
3736
  /*
@@ -3620,6 +3765,8 @@ pgconn_pipeline_status(VALUE self)
3620
3765
  * Raises PG::Error and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc.
3621
3766
  * This function does not actually send anything to the server, it just changes the libpq connection state.
3622
3767
  *
3768
+ * See the {PostgreSQL documentation}[https://www.postgresql.org/docs/17/libpq-pipeline-mode.html#LIBPQ-PIPELINE-MODE].
3769
+ *
3623
3770
  * Available since PostgreSQL-14
3624
3771
  */
3625
3772
  static VALUE
@@ -3658,29 +3805,55 @@ pgconn_exit_pipeline_mode(VALUE self)
3658
3805
 
3659
3806
  /*
3660
3807
  * call-seq:
3661
- * conn.pipeline_sync -> nil
3808
+ * conn.sync_pipeline_sync -> nil
3662
3809
  *
3663
- * Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
3664
- * This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
3810
+ * This function has the same behavior as #async_pipeline_sync, but is implemented using the synchronous command processing API of libpq.
3811
+ * See #async_exec for the differences between the two API variants.
3812
+ * It's not recommended to use explicit sync or async variants but #pipeline_sync instead, unless you have a good reason to do so.
3813
+ *
3814
+ * Available since PostgreSQL-14
3815
+ */
3816
+ static VALUE
3817
+ pgconn_sync_pipeline_sync(VALUE self)
3818
+ {
3819
+ PGconn *conn = pg_get_pgconn(self);
3820
+ int res = gvl_PQpipelineSync(conn);
3821
+ if( res != 1 )
3822
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3823
+
3824
+ return Qnil;
3825
+ }
3826
+
3827
+
3828
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
3829
+ /*
3830
+ * call-seq:
3831
+ * conn.send_pipeline_sync -> nil
3832
+ *
3833
+ * Marks a synchronization point in a pipeline by sending a sync message without flushing the send buffer.
3665
3834
  *
3835
+ * This serves as the delimiter of an implicit transaction and an error recovery point.
3666
3836
  * Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
3837
+ * Note that the message is not itself flushed to the server automatically; use flush if necessary.
3667
3838
  *
3668
- * Available since PostgreSQL-14
3839
+ * Available since PostgreSQL-17
3669
3840
  */
3670
3841
  static VALUE
3671
- pgconn_pipeline_sync(VALUE self)
3842
+ pgconn_send_pipeline_sync(VALUE self)
3672
3843
  {
3673
3844
  PGconn *conn = pg_get_pgconn(self);
3674
- int res = PQpipelineSync(conn);
3845
+ int res = gvl_PQsendPipelineSync(conn);
3675
3846
  if( res != 1 )
3676
3847
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3677
3848
 
3678
3849
  return Qnil;
3679
3850
  }
3851
+ #endif
3852
+
3680
3853
 
3681
3854
  /*
3682
3855
  * call-seq:
3683
- * conn.pipeline_sync -> nil
3856
+ * conn.send_flush_request -> nil
3684
3857
  *
3685
3858
  * Sends a request for the server to flush its output buffer.
3686
3859
  *
@@ -4524,7 +4697,9 @@ init_pg_connection(void)
4524
4697
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
4525
4698
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
4526
4699
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4700
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
4527
4701
  rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
4702
+ #endif
4528
4703
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
4529
4704
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
4530
4705
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
@@ -4536,6 +4711,10 @@ init_pg_connection(void)
4536
4711
  rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4537
4712
  rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4538
4713
  rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4714
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
4715
+ rb_define_method(rb_cPGconn, "sync_close_prepared", pgconn_sync_close_prepared, 1);
4716
+ rb_define_method(rb_cPGconn, "sync_close_portal", pgconn_sync_close_portal, 1);
4717
+ #endif
4539
4718
 
4540
4719
  rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4541
4720
  rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
@@ -4543,6 +4722,10 @@ init_pg_connection(void)
4543
4722
  rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4544
4723
  rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4545
4724
  rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4725
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
4726
+ rb_define_method(rb_cPGconn, "close_prepared", pgconn_async_close_prepared, 1);
4727
+ rb_define_method(rb_cPGconn, "close_portal", pgconn_async_close_portal, 1);
4728
+ #endif
4546
4729
 
4547
4730
  rb_define_alias(rb_cPGconn, "async_exec", "exec");
4548
4731
  rb_define_alias(rb_cPGconn, "async_query", "async_exec");
@@ -4551,6 +4734,10 @@ init_pg_connection(void)
4551
4734
  rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4552
4735
  rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4553
4736
  rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4737
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
4738
+ rb_define_alias(rb_cPGconn, "async_close_prepared", "close_prepared");
4739
+ rb_define_alias(rb_cPGconn, "async_close_portal", "close_portal");
4740
+ #endif
4554
4741
 
4555
4742
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
4556
4743
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
@@ -4560,6 +4747,9 @@ init_pg_connection(void)
4560
4747
  rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
4561
4748
  rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
4562
4749
  rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
4750
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
4751
+ rb_define_method(rb_cPGconn, "set_chunked_rows_mode", pgconn_set_chunked_rows_mode, 1);
4752
+ #endif
4563
4753
 
4564
4754
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
4565
4755
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
@@ -4579,7 +4769,9 @@ init_pg_connection(void)
4579
4769
  rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4580
4770
 
4581
4771
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4772
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
4582
4773
  rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4774
+ #endif
4583
4775
 
4584
4776
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4585
4777
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
@@ -4591,9 +4783,7 @@ init_pg_connection(void)
4591
4783
 
4592
4784
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4593
4785
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4594
- #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4595
4786
  rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4596
- #endif
4597
4787
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
4598
4788
  rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
4599
4789
 
@@ -4615,22 +4805,21 @@ init_pg_connection(void)
4615
4805
  rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4616
4806
  rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4617
4807
  rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4618
- #ifdef HAVE_PQENCRYPTPASSWORDCONN
4619
4808
  rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4620
- #endif
4621
4809
 
4622
- #ifdef HAVE_PQSSLATTRIBUTE
4623
4810
  rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
4624
4811
  rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
4625
4812
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4626
- #endif
4627
4813
 
4628
4814
  #ifdef HAVE_PQENTERPIPELINEMODE
4629
4815
  rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4630
4816
  rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4631
4817
  rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4632
- rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
4818
+ rb_define_method(rb_cPGconn, "sync_pipeline_sync", pgconn_sync_pipeline_sync, 0);
4633
4819
  rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4820
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
4821
+ rb_define_method(rb_cPGconn, "send_pipeline_sync", pgconn_send_pipeline_sync, 0);
4822
+ #endif
4634
4823
  #endif
4635
4824
 
4636
4825
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/