pg 1.6.3 → 1.7.0

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +52 -6
  4. data/Gemfile +1 -0
  5. data/README.ja.md +81 -30
  6. data/README.md +14 -7
  7. data/Rakefile +8 -7
  8. data/certs/larskanis-2026.pem +24 -0
  9. data/ext/extconf.rb +18 -28
  10. data/ext/gvl_wrappers.c +2 -2
  11. data/ext/gvl_wrappers.h +40 -160
  12. data/ext/pg.c +8 -12
  13. data/ext/pg.h +8 -11
  14. data/ext/pg_binary_decoder.c +6 -2
  15. data/ext/pg_binary_encoder.c +7 -0
  16. data/ext/pg_cancel_connection.c +6 -6
  17. data/ext/pg_coder.c +4 -4
  18. data/ext/pg_connection.c +196 -159
  19. data/ext/pg_copy_coder.c +34 -21
  20. data/ext/pg_record_coder.c +10 -6
  21. data/ext/pg_result.c +42 -26
  22. data/ext/pg_text_decoder.c +6 -6
  23. data/ext/pg_text_encoder.c +7 -2
  24. data/ext/pg_tuple.c +1 -1
  25. data/ext/pg_type_map.c +41 -1
  26. data/ext/pg_type_map_all_strings.c +2 -2
  27. data/ext/pg_type_map_by_class.c +1 -1
  28. data/ext/pg_type_map_by_column.c +2 -2
  29. data/ext/pg_type_map_by_oid.c +1 -1
  30. data/ext/pg_type_map_in_ruby.c +1 -1
  31. data/lib/pg/basic_type_map_based_on_result.rb +5 -0
  32. data/lib/pg/basic_type_map_for_queries.rb +9 -2
  33. data/lib/pg/basic_type_map_for_results.rb +5 -0
  34. data/lib/pg/connection.rb +166 -76
  35. data/lib/pg/text_decoder/date.rb +1 -1
  36. data/lib/pg/text_decoder/json.rb +1 -1
  37. data/lib/pg/text_encoder/date.rb +7 -1
  38. data/lib/pg/text_encoder/json.rb +1 -1
  39. data/lib/pg/version.rb +1 -1
  40. data/misc/yugabyte/docker-compose.yml +1 -1
  41. data/pg.gemspec +1 -1
  42. data/sample/async_mixed.rb +1 -1
  43. data.tar.gz.sig +0 -0
  44. metadata +18 -19
  45. metadata.gz.sig +0 -0
  46. data/ports/patches/openssl/3.5.2/0001-aarch64-mingw.patch +0 -21
  47. data/ports/patches/postgresql/18.1/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +0 -52
  48. /data/ports/patches/krb5/{1.22.1 → 1.22.2}/0001-Allow-static-linking-krb5-library.patch +0 -0
  49. /data/ports/patches/krb5/{1.22.1 → 1.22.2}/0002-unknown-command-line-option-on-clang.patch +0 -0
  50. /data/ports/patches/postgresql/{18.1 → 18.6}/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +0 -0
data/ext/pg_connection.c CHANGED
@@ -14,7 +14,7 @@ VALUE rb_cPGconn;
14
14
  static ID s_id_encode;
15
15
  static ID s_id_autoclose_set;
16
16
  static VALUE sym_type, sym_format, sym_value;
17
- static VALUE sym_symbol, sym_string, sym_static_symbol;
17
+ static VALUE sym_symbol, sym_string;
18
18
 
19
19
  static VALUE pgconn_finish( VALUE );
20
20
  static VALUE pgconn_set_default_encoding( VALUE self );
@@ -153,13 +153,13 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
153
153
  return ary;
154
154
  }
155
155
 
156
- static const char *pg_cstr_enc(VALUE str, int enc_idx){
156
+ static const char *pg_cstr_enc(VALUE str, int enc_idx, VALUE *transcoded_str){
157
157
  const char *ptr = StringValueCStr(str);
158
158
  if( ENCODING_GET(str) == enc_idx ){
159
159
  return ptr;
160
160
  } else {
161
- str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
162
- return StringValueCStr(str);
161
+ *transcoded_str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
162
+ return StringValueCStr(*transcoded_str);
163
163
  }
164
164
  }
165
165
 
@@ -188,6 +188,7 @@ pgconn_gc_compact( void *_this )
188
188
  pg_gc_location( this->socket_io );
189
189
  pg_gc_location( this->notice_receiver );
190
190
  pg_gc_location( this->notice_processor );
191
+ pg_gc_location( this->self );
191
192
  pg_gc_location( this->type_map_for_queries );
192
193
  pg_gc_location( this->type_map_for_results );
193
194
  pg_gc_location( this->trace_stream );
@@ -260,6 +261,7 @@ pgconn_s_allocate( VALUE klass )
260
261
  RB_OBJ_WRITE(self, &this->socket_io, Qnil);
261
262
  RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
262
263
  RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
264
+ RB_OBJ_WRITE(self, &this->self, self);
263
265
  RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
264
266
  RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
265
267
  RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
@@ -280,7 +282,8 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
280
282
 
281
283
  this = pg_get_connection( self );
282
284
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
283
- this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
285
+ this->pgconn = PQconnectdb(StringValueCStr(conninfo));
286
+ RB_GC_GUARD(conninfo);
284
287
 
285
288
  if(this->pgconn == NULL)
286
289
  rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
@@ -329,6 +332,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
329
332
  this = pg_get_connection( rb_conn );
330
333
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
331
334
  this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
335
+ RB_GC_GUARD(conninfo);
332
336
 
333
337
  if( this->pgconn == NULL )
334
338
  rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
@@ -350,6 +354,7 @@ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
350
354
 
351
355
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
352
356
  ping = gvl_PQping( StringValueCStr(conninfo) );
357
+ RB_GC_GUARD(conninfo);
353
358
 
354
359
  return INT2FIX((int)ping);
355
360
  }
@@ -434,7 +439,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
434
439
  Check_Type(password, T_STRING);
435
440
  Check_Type(username, T_STRING);
436
441
 
437
- encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
442
+ encrypted = PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
438
443
  if ( encrypted ) {
439
444
  rval = rb_str_new2( encrypted );
440
445
  PQfreemem( encrypted );
@@ -560,7 +565,7 @@ static VALUE
560
565
  pgconn_sync_reset( VALUE self )
561
566
  {
562
567
  pgconn_close_socket_io( self );
563
- gvl_PQreset( pg_get_pgconn(self) );
568
+ PQreset( pg_get_pgconn(self) );
564
569
  return self;
565
570
  }
566
571
 
@@ -568,13 +573,17 @@ static VALUE
568
573
  pgconn_reset_start2( VALUE self, VALUE conninfo )
569
574
  {
570
575
  t_pg_connection *this = pg_get_connection( self );
576
+ /* Ensure conninfo is a valid C string before closing the connection. */
577
+ char *p_conninfo = StringValueCStr(conninfo);
571
578
 
572
579
  /* Close old connection */
573
580
  pgconn_close_socket_io( self );
574
581
  PQfinish( this->pgconn );
582
+ this->pgconn = NULL; /* Ensure no double free can happen. */
575
583
 
576
584
  /* Start new connection */
577
- this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
585
+ this->pgconn = gvl_PQconnectStart( p_conninfo );
586
+ RB_GC_GUARD(conninfo);
578
587
 
579
588
  if( this->pgconn == NULL )
580
589
  rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
@@ -865,6 +874,33 @@ pgconn_protocol_version(VALUE self)
865
874
  return INT2NUM(protocol_version);
866
875
  }
867
876
 
877
+ #ifdef LIBPQ_HAS_FULL_PROTOCOL_VERSION
878
+ /*
879
+ * call-seq:
880
+ * conn.full_protocol_version -> Integer
881
+ *
882
+ * Interrogates the frontend/backend protocol being used, including minor version.
883
+ *
884
+ * Applications might wish to use this function to determine whether certain features are supported.
885
+ * The result is the major version multiplied by 10000 added to the minor version, e.g. 30002 for version 3.2.
886
+ * The protocol version will not change after connection startup is complete, but it could theoretically change during a connection reset.
887
+ * The 3.0 protocol is supported by PostgreSQL server versions 7.4 and above.
888
+ *
889
+ * PG::ConnectionBad is raised if the connection is bad.
890
+ *
891
+ * Available since PostgreSQL-18.
892
+ */
893
+ static VALUE
894
+ pgconn_full_protocol_version(VALUE self)
895
+ {
896
+ int protocol_version = PQfullProtocolVersion(pg_get_pgconn(self));
897
+ if (protocol_version == 0) {
898
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQfullProtocolVersion() can't get protocol version");
899
+ }
900
+ return INT2NUM(protocol_version);
901
+ }
902
+ #endif
903
+
868
904
  /*
869
905
  * call-seq:
870
906
  * conn.server_version -> Integer
@@ -1013,7 +1049,7 @@ pgconn_backend_pid(VALUE self)
1013
1049
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
1014
1050
  }
1015
1051
 
1016
- #ifndef HAVE_PQSETCHUNKEDROWSMODE
1052
+ #ifndef LIBPQ_HAS_CHUNK_MODE
1017
1053
  typedef struct
1018
1054
  {
1019
1055
  struct sockaddr_storage addr;
@@ -1100,11 +1136,11 @@ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
1100
1136
  * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
1101
1137
  * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
1102
1138
  *
1103
- * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
1104
- * However #async_exec has two advantages:
1139
+ * However #async_exec has some advantages:
1105
1140
  *
1106
- * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
1107
- * 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
1141
+ * 1. Only #async_exec allows concurrent threads to run, while waiting for a server response.
1142
+ * 2. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
1143
+ * 3. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
1108
1144
  * So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
1109
1145
  */
1110
1146
  static VALUE
@@ -1117,8 +1153,10 @@ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
1117
1153
  /* If called with no or nil parameters, use PQexec for compatibility */
1118
1154
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1119
1155
  VALUE query_str = argv[0];
1156
+ VALUE transcoded_str;
1120
1157
 
1121
- result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
1158
+ result = PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx, &transcoded_str));
1159
+ RB_GC_GUARD(transcoded_str);
1122
1160
  rb_pgresult = pg_new_result(result, self);
1123
1161
  pg_result_check(rb_pgresult);
1124
1162
  if (rb_block_given_p()) {
@@ -1256,7 +1294,7 @@ alloc_query_params(struct query_params_data *paramsData)
1256
1294
  int nParams;
1257
1295
  int i=0;
1258
1296
  t_pg_coder *conv;
1259
- unsigned int required_pool_size;
1297
+ size_t required_pool_size;
1260
1298
  char *memory_pool;
1261
1299
 
1262
1300
  Check_Type(paramsData->params, T_ARRAY);
@@ -1268,7 +1306,7 @@ alloc_query_params(struct query_params_data *paramsData)
1268
1306
  paramsData->typecast_heap_chain = Qnil;
1269
1307
  paramsData->gc_array = Qnil;
1270
1308
 
1271
- nParams = (int)RARRAY_LEN(paramsData->params);
1309
+ nParams = RARRAY_LENINT(paramsData->params);
1272
1310
 
1273
1311
  required_pool_size = nParams * (
1274
1312
  sizeof(char *) +
@@ -1415,6 +1453,7 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1415
1453
  PGresult *result = NULL;
1416
1454
  VALUE rb_pgresult;
1417
1455
  VALUE command, in_res_fmt;
1456
+ VALUE transcoded_str;
1418
1457
  int nParams;
1419
1458
  int resultFormat;
1420
1459
  struct query_params_data paramsData = { this->enc_idx };
@@ -1436,9 +1475,10 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1436
1475
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1437
1476
  nParams = alloc_query_params( &paramsData );
1438
1477
 
1439
- result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1478
+ result = PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
1440
1479
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1441
1480
 
1481
+ RB_GC_GUARD(transcoded_str);
1442
1482
  free_query_params( &paramsData );
1443
1483
 
1444
1484
  rb_pgresult = pg_new_result(result, self);
@@ -1467,6 +1507,7 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1467
1507
  VALUE rb_pgresult;
1468
1508
  VALUE name, command, in_paramtypes;
1469
1509
  VALUE param;
1510
+ VALUE transcoded_str1, transcoded_str2;
1470
1511
  int i = 0;
1471
1512
  int nParams = 0;
1472
1513
  Oid *paramTypes = NULL;
@@ -1475,12 +1516,12 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1475
1516
  int enc_idx = this->enc_idx;
1476
1517
 
1477
1518
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1478
- name_cstr = pg_cstr_enc(name, enc_idx);
1479
- command_cstr = pg_cstr_enc(command, enc_idx);
1519
+ name_cstr = pg_cstr_enc(name, enc_idx, &transcoded_str1);
1520
+ command_cstr = pg_cstr_enc(command, enc_idx, &transcoded_str2);
1480
1521
 
1481
1522
  if(! NIL_P(in_paramtypes)) {
1482
1523
  Check_Type(in_paramtypes, T_ARRAY);
1483
- nParams = (int)RARRAY_LEN(in_paramtypes);
1524
+ nParams = RARRAY_LENINT(in_paramtypes);
1484
1525
  paramTypes = ALLOC_N(Oid, nParams);
1485
1526
  for(i = 0; i < nParams; i++) {
1486
1527
  param = rb_ary_entry(in_paramtypes, i);
@@ -1490,8 +1531,10 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1490
1531
  paramTypes[i] = NUM2UINT(param);
1491
1532
  }
1492
1533
  }
1493
- result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1534
+ result = PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1494
1535
 
1536
+ RB_GC_GUARD(transcoded_str1);
1537
+ RB_GC_GUARD(transcoded_str2);
1495
1538
  xfree(paramTypes);
1496
1539
 
1497
1540
  rb_pgresult = pg_new_result(result, self);
@@ -1515,6 +1558,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1515
1558
  PGresult *result = NULL;
1516
1559
  VALUE rb_pgresult;
1517
1560
  VALUE name, in_res_fmt;
1561
+ VALUE transcoded_str;
1518
1562
  int nParams;
1519
1563
  int resultFormat;
1520
1564
  struct query_params_data paramsData = { this->enc_idx };
@@ -1530,10 +1574,11 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1530
1574
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1531
1575
  nParams = alloc_query_params( &paramsData );
1532
1576
 
1533
- result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1577
+ result = PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
1534
1578
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1535
1579
  resultFormat);
1536
1580
 
1581
+ RB_GC_GUARD(transcoded_str);
1537
1582
  free_query_params( &paramsData );
1538
1583
 
1539
1584
  rb_pgresult = pg_new_result(result, self);
@@ -1550,9 +1595,13 @@ pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*f
1550
1595
  {
1551
1596
  PGresult *result;
1552
1597
  VALUE rb_pgresult;
1598
+ VALUE transcoded_str;
1553
1599
  t_pg_connection *this = pg_get_connection_safe( self );
1554
- const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
1600
+ const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx, &transcoded_str);
1601
+
1555
1602
  result = func(this->pgconn, stmt);
1603
+
1604
+ RB_GC_GUARD(transcoded_str);
1556
1605
  rb_pgresult = pg_new_result(result, self);
1557
1606
  pg_result_check(rb_pgresult);
1558
1607
  return rb_pgresult;
@@ -1569,7 +1618,7 @@ pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*f
1569
1618
  static VALUE
1570
1619
  pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1571
1620
  {
1572
- return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePrepared);
1621
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQdescribePrepared);
1573
1622
  }
1574
1623
 
1575
1624
 
@@ -1584,11 +1633,11 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1584
1633
  static VALUE
1585
1634
  pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1586
1635
  {
1587
- return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQdescribePortal);
1636
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQdescribePortal);
1588
1637
  }
1589
1638
 
1590
1639
 
1591
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
1640
+ #ifdef LIBPQ_HAS_CHUNK_MODE
1592
1641
  /*
1593
1642
  * call-seq:
1594
1643
  * conn.sync_close_prepared( stmt_name ) -> PG::Result
@@ -1602,7 +1651,7 @@ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1602
1651
  static VALUE
1603
1652
  pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
1604
1653
  {
1605
- return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQclosePrepared);
1654
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQclosePrepared);
1606
1655
  }
1607
1656
 
1608
1657
  /*
@@ -1618,7 +1667,7 @@ pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
1618
1667
  static VALUE
1619
1668
  pgconn_sync_close_portal(VALUE self, VALUE stmt_name)
1620
1669
  {
1621
- return pgconn_sync_describe_close_prepared_portal(self, stmt_name, gvl_PQclosePortal);
1670
+ return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQclosePortal);
1622
1671
  }
1623
1672
  #endif
1624
1673
 
@@ -1892,7 +1941,7 @@ pgconn_set_single_row_mode(VALUE self)
1892
1941
  return self;
1893
1942
  }
1894
1943
 
1895
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
1944
+ #ifdef LIBPQ_HAS_CHUNK_MODE
1896
1945
  /*
1897
1946
  * call-seq:
1898
1947
  * conn.set_chunked_rows_mode -> self
@@ -1949,13 +1998,15 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1949
1998
  static VALUE
1950
1999
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1951
2000
  {
2001
+ VALUE transcoded_str;
1952
2002
  t_pg_connection *this = pg_get_connection_safe( self );
1953
2003
 
1954
2004
  /* If called with no or nil parameters, use PQexec for compatibility */
1955
2005
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1956
- if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
2006
+ if(PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx, &transcoded_str)) == 0)
1957
2007
  pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));
1958
2008
 
2009
+ RB_GC_GUARD(transcoded_str);
1959
2010
  pgconn_wait_for_flush( self );
1960
2011
  return Qnil;
1961
2012
  }
@@ -2012,6 +2063,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
2012
2063
  t_pg_connection *this = pg_get_connection_safe( self );
2013
2064
  int result;
2014
2065
  VALUE command, in_res_fmt;
2066
+ VALUE transcoded_str;
2015
2067
  int nParams;
2016
2068
  int resultFormat;
2017
2069
  struct query_params_data paramsData = { this->enc_idx };
@@ -2023,9 +2075,10 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
2023
2075
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
2024
2076
  nParams = alloc_query_params( &paramsData );
2025
2077
 
2026
- result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
2078
+ result = PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
2027
2079
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
2028
2080
 
2081
+ RB_GC_GUARD(transcoded_str);
2029
2082
  free_query_params( &paramsData );
2030
2083
 
2031
2084
  if(result == 0)
@@ -2062,6 +2115,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2062
2115
  int result;
2063
2116
  VALUE name, command, in_paramtypes;
2064
2117
  VALUE param;
2118
+ VALUE transcoded_str1, transcoded_str2;
2065
2119
  int i = 0;
2066
2120
  int nParams = 0;
2067
2121
  Oid *paramTypes = NULL;
@@ -2070,12 +2124,12 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2070
2124
  int enc_idx = this->enc_idx;
2071
2125
 
2072
2126
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
2073
- name_cstr = pg_cstr_enc(name, enc_idx);
2074
- command_cstr = pg_cstr_enc(command, enc_idx);
2127
+ name_cstr = pg_cstr_enc(name, enc_idx, &transcoded_str1);
2128
+ command_cstr = pg_cstr_enc(command, enc_idx, &transcoded_str2);
2075
2129
 
2076
2130
  if(! NIL_P(in_paramtypes)) {
2077
2131
  Check_Type(in_paramtypes, T_ARRAY);
2078
- nParams = (int)RARRAY_LEN(in_paramtypes);
2132
+ nParams = RARRAY_LENINT(in_paramtypes);
2079
2133
  paramTypes = ALLOC_N(Oid, nParams);
2080
2134
  for(i = 0; i < nParams; i++) {
2081
2135
  param = rb_ary_entry(in_paramtypes, i);
@@ -2085,8 +2139,10 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2085
2139
  paramTypes[i] = NUM2UINT(param);
2086
2140
  }
2087
2141
  }
2088
- result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
2142
+ result = PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
2089
2143
 
2144
+ RB_GC_GUARD(transcoded_str1);
2145
+ RB_GC_GUARD(transcoded_str2);
2090
2146
  xfree(paramTypes);
2091
2147
 
2092
2148
  if(result == 0) {
@@ -2134,6 +2190,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2134
2190
  t_pg_connection *this = pg_get_connection_safe( self );
2135
2191
  int result;
2136
2192
  VALUE name, in_res_fmt;
2193
+ VALUE transcoded_str;
2137
2194
  int nParams;
2138
2195
  int resultFormat;
2139
2196
  struct query_params_data paramsData = { this->enc_idx };
@@ -2149,10 +2206,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2149
2206
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
2150
2207
  nParams = alloc_query_params( &paramsData );
2151
2208
 
2152
- result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
2209
+ result = PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
2153
2210
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
2154
2211
  resultFormat);
2155
2212
 
2213
+ RB_GC_GUARD(transcoded_str);
2156
2214
  free_query_params( &paramsData );
2157
2215
 
2158
2216
  if(result == 0)
@@ -2166,12 +2224,14 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2166
2224
  static VALUE
2167
2225
  pgconn_send_describe_close_prepared_portal(VALUE self, VALUE name, int (*func)(PGconn *, const char *), const char *funame)
2168
2226
  {
2227
+ VALUE transcoded_str;
2169
2228
  t_pg_connection *this = pg_get_connection_safe( self );
2170
- const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
2229
+ const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx, &transcoded_str);
2171
2230
  /* returns 0 on failure */
2172
2231
  if(func(this->pgconn, stmt) == 0)
2173
2232
  pg_raise_conn_error( rb_eUnableToSend, self, "%s %s", funame, PQerrorMessage(this->pgconn));
2174
2233
 
2234
+ RB_GC_GUARD(transcoded_str);
2175
2235
  pgconn_wait_for_flush( self );
2176
2236
  return Qnil;
2177
2237
  }
@@ -2187,7 +2247,7 @@ static VALUE
2187
2247
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2188
2248
  {
2189
2249
  return pgconn_send_describe_close_prepared_portal(
2190
- self, stmt_name, gvl_PQsendDescribePrepared,
2250
+ self, stmt_name, PQsendDescribePrepared,
2191
2251
  "PQsendDescribePrepared");
2192
2252
  }
2193
2253
 
@@ -2203,11 +2263,11 @@ static VALUE
2203
2263
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2204
2264
  {
2205
2265
  return pgconn_send_describe_close_prepared_portal(
2206
- self, portal, gvl_PQsendDescribePortal,
2266
+ self, portal, PQsendDescribePortal,
2207
2267
  "PQsendDescribePortal");
2208
2268
  }
2209
2269
 
2210
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
2270
+ #ifdef LIBPQ_HAS_CHUNK_MODE
2211
2271
  /*
2212
2272
  * call-seq:
2213
2273
  * conn.send_close_prepared( statement_name ) -> nil
@@ -2221,7 +2281,7 @@ static VALUE
2221
2281
  pgconn_send_close_prepared(VALUE self, VALUE stmt_name)
2222
2282
  {
2223
2283
  return pgconn_send_describe_close_prepared_portal(
2224
- self, stmt_name, gvl_PQsendClosePrepared,
2284
+ self, stmt_name, PQsendClosePrepared,
2225
2285
  "PQsendClosePrepared");
2226
2286
  }
2227
2287
 
@@ -2239,7 +2299,7 @@ static VALUE
2239
2299
  pgconn_send_close_portal(VALUE self, VALUE portal)
2240
2300
  {
2241
2301
  return pgconn_send_describe_close_prepared_portal(
2242
- self, portal, gvl_PQsendClosePortal,
2302
+ self, portal, PQsendClosePortal,
2243
2303
  "PQsendClosePortal");
2244
2304
  }
2245
2305
  #endif
@@ -2251,7 +2311,7 @@ pgconn_sync_get_result(VALUE self)
2251
2311
  PGresult *result;
2252
2312
  VALUE rb_pgresult;
2253
2313
 
2254
- result = gvl_PQgetResult(conn);
2314
+ result = PQgetResult(conn);
2255
2315
  if(result == NULL)
2256
2316
  return Qnil;
2257
2317
  rb_pgresult = pg_new_result(result, self);
@@ -2293,7 +2353,7 @@ pgconn_consume_input(VALUE self)
2293
2353
  static VALUE
2294
2354
  pgconn_is_busy(VALUE self)
2295
2355
  {
2296
- return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2356
+ return PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2297
2357
  }
2298
2358
 
2299
2359
  static VALUE
@@ -2333,7 +2393,7 @@ pgconn_sync_flush(VALUE self)
2333
2393
  return (ret) ? Qfalse : Qtrue;
2334
2394
  }
2335
2395
 
2336
- #ifndef HAVE_PQSETCHUNKEDROWSMODE
2396
+ #ifndef LIBPQ_HAS_CHUNK_MODE
2337
2397
  static VALUE
2338
2398
  pgconn_sync_cancel(VALUE self)
2339
2399
  {
@@ -2346,7 +2406,7 @@ pgconn_sync_cancel(VALUE self)
2346
2406
  if(cancel == NULL)
2347
2407
  pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2348
2408
 
2349
- ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2409
+ ret = PQcancel(cancel, errbuf, sizeof(errbuf));
2350
2410
  if(ret == 1)
2351
2411
  retval = Qnil;
2352
2412
  else
@@ -2378,7 +2438,7 @@ pgconn_notifies(VALUE self)
2378
2438
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2379
2439
  sym_extra = ID2SYM(rb_intern("extra"));
2380
2440
 
2381
- notification = gvl_PQnotifies(this->pgconn);
2441
+ notification = PQnotifies(this->pgconn);
2382
2442
  if (notification == NULL) {
2383
2443
  return Qnil;
2384
2444
  }
@@ -2398,33 +2458,13 @@ pgconn_notifies(VALUE self)
2398
2458
  return hash;
2399
2459
  }
2400
2460
 
2401
- #ifndef HAVE_RB_IO_DESCRIPTOR
2402
- static int
2403
- rb_io_descriptor(VALUE io)
2404
- {
2405
- rb_io_t *fptr;
2406
- Check_Type(io, T_FILE);
2407
- fptr = RFILE(io)->fptr;
2408
- rb_io_check_closed(fptr);
2409
- return fptr->fd;
2410
- }
2411
- #endif
2412
-
2413
2461
  #if defined(_WIN32)
2414
2462
 
2415
2463
  /* We use a specialized implementation of rb_io_wait() on Windows.
2416
2464
  * This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
2417
2465
  */
2418
2466
 
2419
- #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2420
2467
  #include <ruby/fiber/scheduler.h>
2421
- #endif
2422
-
2423
- typedef enum {
2424
- PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2425
- PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2426
- PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2427
- } pg_rb_io_event_t;
2428
2468
 
2429
2469
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2430
2470
 
@@ -2448,9 +2488,9 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
2448
2488
  timeradd(&currtime, &ptimeout, &aborttime);
2449
2489
  }
2450
2490
 
2451
- if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2452
- if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
2453
- if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
2491
+ if(rb_events & RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2492
+ if(rb_events & RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
2493
+ if(rb_events & RUBY_IO_PRIORITY) w32_events |= FD_OOB;
2454
2494
 
2455
2495
  for(;;) {
2456
2496
  if ( WSAEventSelect(_get_osfhandle(rb_io_descriptor(io)), hEvent, w32_events) == SOCKET_ERROR ) {
@@ -2494,49 +2534,20 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
2494
2534
 
2495
2535
  static VALUE
2496
2536
  pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2497
- #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2498
- /* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
2499
- * Fortunately ruby-3.1 offers a C-API for it.
2500
- */
2537
+ /* Avoid slow rb_io_wait() on Windows, if no scheduler is active. */
2501
2538
  VALUE scheduler = rb_fiber_scheduler_current();
2502
2539
 
2503
2540
  if (!NIL_P(scheduler)) {
2504
2541
  return rb_io_wait(io, events, timeout);
2505
2542
  }
2506
- #endif
2507
2543
  return pg_rb_thread_io_wait(io, events, timeout);
2508
2544
  }
2509
2545
 
2510
- #elif defined(HAVE_RB_IO_WAIT)
2511
-
2512
- /* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
2513
- #define pg_rb_io_wait rb_io_wait
2514
- #define PG_RUBY_IO_READABLE RUBY_IO_READABLE
2515
- #define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
2516
- #define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
2517
-
2518
2546
  #else
2519
- /* For compat with ruby < 3.0 */
2520
-
2521
- typedef enum {
2522
- PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2523
- PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2524
- PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2525
- } pg_rb_io_event_t;
2526
-
2527
- static VALUE
2528
- pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2529
- struct timeval waittime;
2530
- int res;
2531
2547
 
2532
- if( !NIL_P(timeout) ){
2533
- waittime.tv_sec = (time_t)(NUM2DBL(timeout));
2534
- waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
2535
- }
2536
- res = rb_wait_for_single_fd(rb_io_descriptor(io), NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
2548
+ /* Use rb_io_wait on non-Windows systems */
2549
+ #define pg_rb_io_wait rb_io_wait
2537
2550
 
2538
- return UINT2NUM(res);
2539
- }
2540
2551
  #endif
2541
2552
 
2542
2553
  static void *
@@ -2571,7 +2582,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2571
2582
 
2572
2583
  socket_io = pgconn_socket_io(self);
2573
2584
  /* Wait for the socket to become readable before checking again */
2574
- ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2585
+ ret = pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), wait_timeout);
2575
2586
  } else {
2576
2587
  ret = Qfalse;
2577
2588
  }
@@ -2608,9 +2619,9 @@ pgconn_async_flush(VALUE self)
2608
2619
  /* wait for the socket to become read- or write-ready */
2609
2620
  int events;
2610
2621
  VALUE socket_io = pgconn_socket_io(self);
2611
- events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2622
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
2612
2623
 
2613
- if (events & PG_RUBY_IO_READABLE){
2624
+ if (events & RUBY_IO_READABLE){
2614
2625
  pgconn_consume_input(self);
2615
2626
  }
2616
2627
  }
@@ -2636,7 +2647,7 @@ pgconn_flush_data_set( VALUE self, VALUE enabled ){
2636
2647
  static void *
2637
2648
  notify_readable(PGconn *conn)
2638
2649
  {
2639
- return (void*)gvl_PQnotifies(conn);
2650
+ return (void*)PQnotifies(conn);
2640
2651
  }
2641
2652
 
2642
2653
  /*
@@ -2735,7 +2746,7 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2735
2746
 
2736
2747
  Check_Type(buffer, T_STRING);
2737
2748
 
2738
- ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2749
+ ret = PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2739
2750
  if(ret == -1)
2740
2751
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2741
2752
 
@@ -2748,6 +2759,7 @@ static VALUE
2748
2759
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2749
2760
  {
2750
2761
  VALUE str;
2762
+ VALUE transcoded_str;
2751
2763
  int ret;
2752
2764
  const char *error_message = NULL;
2753
2765
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2755,15 +2767,41 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2755
2767
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2756
2768
  error_message = NULL;
2757
2769
  else
2758
- error_message = pg_cstr_enc(str, this->enc_idx);
2770
+ error_message = pg_cstr_enc(str, this->enc_idx, &transcoded_str);
2759
2771
 
2760
- ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2772
+ ret = PQputCopyEnd(this->pgconn, error_message);
2761
2773
  if(ret == -1)
2762
2774
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2763
2775
 
2776
+ RB_GC_GUARD(transcoded_str);
2764
2777
  return (ret) ? Qtrue : Qfalse;
2765
2778
  }
2766
2779
 
2780
+ struct pgconn_copy_data {
2781
+ t_pg_coder *coder;
2782
+ char *buffer;
2783
+ int length;
2784
+ int enc_idx;
2785
+ };
2786
+
2787
+ static VALUE
2788
+ pgconn_decode_copy_data(VALUE data_ptr)
2789
+ {
2790
+ struct pgconn_copy_data *data = (struct pgconn_copy_data *)data_ptr;
2791
+ t_pg_coder_dec_func dec_func = pg_coder_dec_func(data->coder, data->coder->format);
2792
+
2793
+ return dec_func(data->coder, data->buffer, data->length, 0, 0, data->enc_idx);
2794
+ }
2795
+
2796
+ static VALUE
2797
+ pgconn_free_copy_data(VALUE data_ptr)
2798
+ {
2799
+ struct pgconn_copy_data *data = (struct pgconn_copy_data *)data_ptr;
2800
+
2801
+ PQfreemem(data->buffer);
2802
+ return Qnil;
2803
+ }
2804
+
2767
2805
  static VALUE
2768
2806
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2769
2807
  {
@@ -2786,7 +2824,7 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2786
2824
  TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
2787
2825
  }
2788
2826
 
2789
- ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2827
+ ret = PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2790
2828
  if(ret == -2){ /* error */
2791
2829
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2792
2830
  }
@@ -2798,8 +2836,9 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2798
2836
  }
2799
2837
 
2800
2838
  if( p_coder ){
2801
- t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
2802
- result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2839
+ struct pgconn_copy_data data = { p_coder, buffer, ret, this->enc_idx };
2840
+
2841
+ return rb_ensure(pgconn_decode_copy_data, (VALUE)&data, pgconn_free_copy_data, (VALUE)&data);
2803
2842
  } else {
2804
2843
  result = rb_str_new(buffer, ret);
2805
2844
  }
@@ -2932,11 +2971,10 @@ pgconn_untrace(VALUE self)
2932
2971
  void
2933
2972
  notice_receiver_proxy(void *arg, const PGresult *pgresult)
2934
2973
  {
2935
- VALUE self = (VALUE)arg;
2936
- t_pg_connection *this = pg_get_connection( self );
2974
+ t_pg_connection *this = (t_pg_connection*)arg;
2937
2975
 
2938
2976
  if (this->notice_receiver != Qnil) {
2939
- VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, self );
2977
+ VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, this->self );
2940
2978
 
2941
2979
  rb_funcall(this->notice_receiver, rb_intern("call"), 1, result);
2942
2980
  pg_result_clear( result );
@@ -2991,7 +3029,7 @@ pgconn_set_notice_receiver(VALUE self)
2991
3029
  old_proc = this->notice_receiver;
2992
3030
  if( rb_block_given_p() ) {
2993
3031
  proc = rb_block_proc();
2994
- PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)self);
3032
+ PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)this);
2995
3033
  } else {
2996
3034
  /* if no block is given, set back to default */
2997
3035
  proc = Qnil;
@@ -3010,8 +3048,7 @@ pgconn_set_notice_receiver(VALUE self)
3010
3048
  void
3011
3049
  notice_processor_proxy(void *arg, const char *message)
3012
3050
  {
3013
- VALUE self = (VALUE)arg;
3014
- t_pg_connection *this = pg_get_connection( self );
3051
+ t_pg_connection *this = (t_pg_connection*)arg;
3015
3052
 
3016
3053
  if (this->notice_processor != Qnil) {
3017
3054
  VALUE message_str = rb_str_new2(message);
@@ -3052,7 +3089,7 @@ pgconn_set_notice_processor(VALUE self)
3052
3089
  old_proc = this->notice_processor;
3053
3090
  if( rb_block_given_p() ) {
3054
3091
  proc = rb_block_proc();
3055
- PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
3092
+ PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)this);
3056
3093
  } else {
3057
3094
  /* if no block is given, set back to default */
3058
3095
  proc = Qnil;
@@ -3094,7 +3131,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
3094
3131
  rb_check_frozen(self);
3095
3132
  Check_Type(str, T_STRING);
3096
3133
 
3097
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
3134
+ if ( (PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
3098
3135
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3099
3136
 
3100
3137
  pgconn_set_internal_encoding_index( self );
@@ -3159,7 +3196,7 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3159
3196
  static void *
3160
3197
  get_result_readable(PGconn *conn)
3161
3198
  {
3162
- return gvl_PQisBusy(conn) ? NULL : (void*)1;
3199
+ return PQisBusy(conn) ? NULL : (void*)1;
3163
3200
  }
3164
3201
 
3165
3202
 
@@ -3217,7 +3254,7 @@ pgconn_sync_get_last_result(VALUE self)
3217
3254
 
3218
3255
 
3219
3256
  cur = prev = NULL;
3220
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3257
+ while ((cur = PQgetResult(conn)) != NULL) {
3221
3258
  int status;
3222
3259
 
3223
3260
  if (prev) PQclear(prev);
@@ -3269,7 +3306,7 @@ pgconn_async_get_last_result(VALUE self)
3269
3306
  */
3270
3307
  wait_socket_readable(self, NULL, get_result_readable);
3271
3308
 
3272
- cur = gvl_PQgetResult(conn);
3309
+ cur = PQgetResult(conn);
3273
3310
  if (cur == NULL)
3274
3311
  break;
3275
3312
 
@@ -3326,18 +3363,18 @@ pgconn_discard_results(VALUE self)
3326
3363
  /* pgconn_block() raises an exception in case of errors.
3327
3364
  * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3328
3365
  */
3329
- while( gvl_PQisBusy(conn) ){
3366
+ while( PQisBusy(conn) ){
3330
3367
  int events;
3331
3368
 
3332
3369
  switch( PQflush(conn) ) {
3333
3370
  case 1:
3334
- events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
3335
- if (events & PG_RUBY_IO_READABLE){
3371
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
3372
+ if (events & RUBY_IO_READABLE){
3336
3373
  if ( PQconsumeInput(conn) == 0 ) goto error;
3337
3374
  }
3338
3375
  break;
3339
3376
  case 0:
3340
- pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3377
+ pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
3341
3378
  if ( PQconsumeInput(conn) == 0 ) goto error;
3342
3379
  break;
3343
3380
  default:
@@ -3345,23 +3382,23 @@ pgconn_discard_results(VALUE self)
3345
3382
  }
3346
3383
  }
3347
3384
 
3348
- cur = gvl_PQgetResult(conn);
3385
+ cur = PQgetResult(conn);
3349
3386
  if( cur == NULL) break;
3350
3387
 
3351
3388
  status = PQresultStatus(cur);
3352
3389
  PQclear(cur);
3353
3390
  if (status == PGRES_COPY_IN){
3354
- while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
3391
+ while( PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
3355
3392
  pgconn_async_flush(self);
3356
3393
  }
3357
3394
  }
3358
3395
  if (status == PGRES_COPY_OUT){
3359
3396
  for(;;) {
3360
3397
  char *buffer = NULL;
3361
- int st = gvl_PQgetCopyData(conn, &buffer, 1);
3398
+ int st = PQgetCopyData(conn, &buffer, 1);
3362
3399
  if( st == 0 ) {
3363
3400
  /* would block -> wait for readable data */
3364
- pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3401
+ pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
3365
3402
  if ( PQconsumeInput(conn) == 0 ) goto error;
3366
3403
  } else if( st > 0 ) {
3367
3404
  /* some data retrieved -> discard it */
@@ -3398,12 +3435,12 @@ error:
3398
3435
  * and the PG::Result object will automatically be cleared when the block terminates.
3399
3436
  * In this instance, <code>conn.exec</code> returns the value of the block.
3400
3437
  *
3401
- * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3438
+ * #exec is an alias for #async_exec which is functional identical to #sync_exec .
3402
3439
  * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3403
3440
  * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3404
3441
  * Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
3405
- * Both methods ensure that other threads can process while waiting for the server to
3406
- * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3442
+ * Only #async_exec ensures that other threads can process while waiting for the server to complete the request.
3443
+ * In contrast #sync_exec blocks all threads and signals to be processed until the query is finished.
3407
3444
  * This is most notably visible by a delayed reaction to Control+C.
3408
3445
  * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3409
3446
  *
@@ -3438,12 +3475,13 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3438
3475
  * +params+ is an array of the bind parameters for the SQL query.
3439
3476
  * Each element of the +params+ array may be either:
3440
3477
  * a hash of the form:
3441
- * {:value => String (value of bind parameter)
3442
- * :type => Integer (oid of type of bind parameter)
3443
- * :format => Integer (0 for text, 1 for binary)
3478
+ * {:value => String (value of bind parameter)
3479
+ * :type => Integer (oid of type of bind parameter)
3480
+ * :typename => String (name of type of bind parameter, only used for conn.embed_params )
3481
+ * :format => Integer (0 for text, 1 for binary)
3444
3482
  * }
3445
3483
  * or, it may be a String. If it is a string, that is equivalent to the hash:
3446
- * { :value => <string value>, :type => 0, :format => 0 }
3484
+ * { :value => <string value>, :type => 0, :format => 0 }
3447
3485
  *
3448
3486
  * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3449
3487
  * inside the SQL query. The 0th element of the +params+ array is bound
@@ -3632,7 +3670,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3632
3670
  return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_describe_prepared);
3633
3671
  }
3634
3672
 
3635
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
3673
+ #ifdef LIBPQ_HAS_CHUNK_MODE
3636
3674
  /*
3637
3675
  * call-seq:
3638
3676
  * conn.close_prepared( statement_name ) -> PG::Result
@@ -3754,7 +3792,7 @@ pgconn_ssl_attribute_names(VALUE self)
3754
3792
 
3755
3793
 
3756
3794
 
3757
- #ifdef HAVE_PQENTERPIPELINEMODE
3795
+ #ifdef LIBPQ_HAS_PIPELINING
3758
3796
  /*
3759
3797
  * call-seq:
3760
3798
  * conn.pipeline_status -> Integer
@@ -3839,7 +3877,7 @@ static VALUE
3839
3877
  pgconn_sync_pipeline_sync(VALUE self)
3840
3878
  {
3841
3879
  PGconn *conn = pg_get_pgconn(self);
3842
- int res = gvl_PQpipelineSync(conn);
3880
+ int res = PQpipelineSync(conn);
3843
3881
  if( res != 1 )
3844
3882
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3845
3883
 
@@ -3847,7 +3885,7 @@ pgconn_sync_pipeline_sync(VALUE self)
3847
3885
  }
3848
3886
 
3849
3887
 
3850
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
3888
+ #ifdef LIBPQ_HAS_CHUNK_MODE
3851
3889
  /*
3852
3890
  * call-seq:
3853
3891
  * conn.send_pipeline_sync -> nil
@@ -3864,7 +3902,7 @@ static VALUE
3864
3902
  pgconn_send_pipeline_sync(VALUE self)
3865
3903
  {
3866
3904
  PGconn *conn = pg_get_pgconn(self);
3867
- int res = gvl_PQsendPipelineSync(conn);
3905
+ int res = PQsendPipelineSync(conn);
3868
3906
  if( res != 1 )
3869
3907
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3870
3908
 
@@ -4305,7 +4343,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
4305
4343
  rb_encoding *rbenc = rb_to_encoding( enc );
4306
4344
  const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
4307
4345
 
4308
- if ( gvl_PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
4346
+ if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
4309
4347
  VALUE server_encoding = pgconn_external_encoding( self );
4310
4348
  rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
4311
4349
  rb_enc_name(rb_to_encoding(server_encoding)), name );
@@ -4345,12 +4383,12 @@ pgconn_external_encoding(VALUE self)
4345
4383
  static VALUE
4346
4384
  pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4347
4385
  {
4348
- VALUE query_format, query;
4386
+ VALUE query;
4349
4387
 
4350
4388
  rb_check_frozen(self);
4351
4389
  Check_Type(encname, T_STRING);
4352
- query_format = rb_str_new_cstr("set client_encoding to '%s'");
4353
- query = rb_funcall(query_format, rb_intern("%"), 1, encname);
4390
+ query = rb_str_new_cstr("set client_encoding to ");
4391
+ rb_str_concat(query, pgconn_escape_literal(self, encname));
4354
4392
 
4355
4393
  pgconn_async_exec(1, &query, self);
4356
4394
  pgconn_set_internal_encoding_index( self );
@@ -4642,7 +4680,6 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
4642
4680
  rb_check_frozen(self);
4643
4681
  this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4644
4682
  if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4645
- else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4646
4683
  else if ( sym == sym_string );
4647
4684
  else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4648
4685
 
@@ -4664,8 +4701,6 @@ pgconn_field_name_type_get(VALUE self)
4664
4701
 
4665
4702
  if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4666
4703
  return sym_symbol;
4667
- } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4668
- return sym_static_symbol;
4669
4704
  } else {
4670
4705
  return sym_string;
4671
4706
  }
@@ -4685,7 +4720,6 @@ init_pg_connection(void)
4685
4720
  sym_value = ID2SYM(rb_intern("value"));
4686
4721
  sym_string = ID2SYM(rb_intern("string"));
4687
4722
  sym_symbol = ID2SYM(rb_intern("symbol"));
4688
- sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
4689
4723
 
4690
4724
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4691
4725
  /* Help rdoc to known the Constants module */
@@ -4733,12 +4767,15 @@ init_pg_connection(void)
4733
4767
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
4734
4768
  rb_define_method(rb_cPGconn, "parameter_status", pgconn_parameter_status, 1);
4735
4769
  rb_define_method(rb_cPGconn, "protocol_version", pgconn_protocol_version, 0);
4770
+ #ifdef LIBPQ_HAS_FULL_PROTOCOL_VERSION
4771
+ rb_define_method(rb_cPGconn, "full_protocol_version", pgconn_full_protocol_version, 0);
4772
+ #endif
4736
4773
  rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
4737
4774
  rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
4738
4775
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
4739
4776
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
4740
4777
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4741
- #ifndef HAVE_PQSETCHUNKEDROWSMODE
4778
+ #ifndef LIBPQ_HAS_CHUNK_MODE
4742
4779
  rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
4743
4780
  #endif
4744
4781
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
@@ -4752,7 +4789,7 @@ init_pg_connection(void)
4752
4789
  rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4753
4790
  rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4754
4791
  rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4755
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
4792
+ #ifdef LIBPQ_HAS_CHUNK_MODE
4756
4793
  rb_define_method(rb_cPGconn, "sync_close_prepared", pgconn_sync_close_prepared, 1);
4757
4794
  rb_define_method(rb_cPGconn, "sync_close_portal", pgconn_sync_close_portal, 1);
4758
4795
  #endif
@@ -4763,7 +4800,7 @@ init_pg_connection(void)
4763
4800
  rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4764
4801
  rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4765
4802
  rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4766
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
4803
+ #ifdef LIBPQ_HAS_CHUNK_MODE
4767
4804
  rb_define_method(rb_cPGconn, "close_prepared", pgconn_async_close_prepared, 1);
4768
4805
  rb_define_method(rb_cPGconn, "close_portal", pgconn_async_close_portal, 1);
4769
4806
  #endif
@@ -4775,7 +4812,7 @@ init_pg_connection(void)
4775
4812
  rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4776
4813
  rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4777
4814
  rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4778
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
4815
+ #ifdef LIBPQ_HAS_CHUNK_MODE
4779
4816
  rb_define_alias(rb_cPGconn, "async_close_prepared", "close_prepared");
4780
4817
  rb_define_alias(rb_cPGconn, "async_close_portal", "close_portal");
4781
4818
  #endif
@@ -4788,7 +4825,7 @@ init_pg_connection(void)
4788
4825
  rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
4789
4826
  rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
4790
4827
  rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
4791
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
4828
+ #ifdef LIBPQ_HAS_CHUNK_MODE
4792
4829
  rb_define_method(rb_cPGconn, "set_chunked_rows_mode", pgconn_set_chunked_rows_mode, 1);
4793
4830
  #endif
4794
4831
 
@@ -4810,7 +4847,7 @@ init_pg_connection(void)
4810
4847
  rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4811
4848
 
4812
4849
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4813
- #ifndef HAVE_PQSETCHUNKEDROWSMODE
4850
+ #ifndef LIBPQ_HAS_CHUNK_MODE
4814
4851
  rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4815
4852
  #endif
4816
4853
 
@@ -4852,13 +4889,13 @@ init_pg_connection(void)
4852
4889
  rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
4853
4890
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4854
4891
 
4855
- #ifdef HAVE_PQENTERPIPELINEMODE
4892
+ #ifdef LIBPQ_HAS_PIPELINING
4856
4893
  rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4857
4894
  rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4858
4895
  rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4859
4896
  rb_define_method(rb_cPGconn, "sync_pipeline_sync", pgconn_sync_pipeline_sync, 0);
4860
4897
  rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4861
- #ifdef HAVE_PQSETCHUNKEDROWSMODE
4898
+ #ifdef LIBPQ_HAS_CHUNK_MODE
4862
4899
  rb_define_method(rb_cPGconn, "send_pipeline_sync", pgconn_send_pipeline_sync, 0);
4863
4900
  #endif
4864
4901
  #endif