pg 0.18.4 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BSDL +2 -2
  4. data/ChangeLog +689 -5
  5. data/History.rdoc +56 -0
  6. data/Manifest.txt +1 -18
  7. data/README.rdoc +13 -9
  8. data/Rakefile +15 -17
  9. data/Rakefile.cross +8 -7
  10. data/ext/errorcodes.def +25 -0
  11. data/ext/errorcodes.txt +13 -1
  12. data/ext/extconf.rb +9 -1
  13. data/ext/gvl_wrappers.h +4 -0
  14. data/ext/pg.c +4 -3
  15. data/ext/pg.h +6 -3
  16. data/ext/pg_binary_encoder.c +8 -8
  17. data/ext/pg_coder.c +31 -10
  18. data/ext/pg_connection.c +252 -98
  19. data/ext/pg_copy_coder.c +34 -4
  20. data/ext/pg_result.c +20 -14
  21. data/ext/pg_text_encoder.c +62 -42
  22. data/ext/pg_type_map.c +14 -7
  23. data/lib/pg/basic_type_mapping.rb +35 -8
  24. data/lib/pg/connection.rb +46 -10
  25. data/lib/pg/deprecated_constants.rb +21 -0
  26. data/lib/pg/result.rb +10 -5
  27. data/lib/pg/text_decoder.rb +7 -0
  28. data/lib/pg/text_encoder.rb +8 -0
  29. data/lib/pg.rb +21 -9
  30. data/spec/helpers.rb +6 -9
  31. data/spec/pg/basic_type_mapping_spec.rb +54 -0
  32. data/spec/pg/connection_spec.rb +158 -26
  33. data/spec/pg/result_spec.rb +11 -4
  34. data/spec/pg/type_map_by_class_spec.rb +2 -2
  35. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  36. data/spec/pg/type_spec.rb +82 -2
  37. data.tar.gz.sig +0 -0
  38. metadata +50 -64
  39. metadata.gz.sig +0 -0
  40. data/sample/array_insert.rb +0 -20
  41. data/sample/async_api.rb +0 -106
  42. data/sample/async_copyto.rb +0 -39
  43. data/sample/async_mixed.rb +0 -56
  44. data/sample/check_conn.rb +0 -21
  45. data/sample/copyfrom.rb +0 -81
  46. data/sample/copyto.rb +0 -19
  47. data/sample/cursor.rb +0 -21
  48. data/sample/disk_usage_report.rb +0 -186
  49. data/sample/issue-119.rb +0 -94
  50. data/sample/losample.rb +0 -69
  51. data/sample/minimal-testcase.rb +0 -17
  52. data/sample/notify_wait.rb +0 -72
  53. data/sample/pg_statistics.rb +0 -294
  54. data/sample/replication_monitor.rb +0 -231
  55. data/sample/test_binary_values.rb +0 -33
  56. data/sample/wal_shipper.rb +0 -434
  57. data/sample/warehouse_partitions.rb +0 -320
data/ext/pg_connection.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_connection.c - PG::Connection class extension
3
- * $Id: pg_connection.c,v eb4d3c003bd6 2015/05/25 20:04:04 ged $
3
+ * $Id: pg_connection.c,v 2e17f315848e 2017/01/14 20:05:06 lars $
4
4
  *
5
5
  */
6
6
 
@@ -52,7 +52,7 @@ pg_get_connection( VALUE self )
52
52
  * Fetch the PG::Connection object data pointer and check it's
53
53
  * PGconn data pointer for sanity.
54
54
  */
55
- t_pg_connection *
55
+ static t_pg_connection *
56
56
  pg_get_connection_safe( VALUE self )
57
57
  {
58
58
  t_pg_connection *this;
@@ -88,7 +88,7 @@ pg_get_pgconn( VALUE self )
88
88
  /*
89
89
  * Close the associated socket IO object if there is one.
90
90
  */
91
- void
91
+ static void
92
92
  pgconn_close_socket_io( VALUE self )
93
93
  {
94
94
  t_pg_connection *this = pg_get_connection( self );
@@ -141,6 +141,16 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
141
141
  return ary;
142
142
  }
143
143
 
144
+ static const char *pg_cstr_enc(VALUE str, int enc_idx){
145
+ const char *ptr = StringValueCStr(str);
146
+ if( ENCODING_GET(str) == enc_idx ){
147
+ return ptr;
148
+ } else {
149
+ str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
150
+ return StringValueCStr(str);
151
+ }
152
+ }
153
+
144
154
 
145
155
  /*
146
156
  * GC Mark function
@@ -342,9 +352,9 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
342
352
  #ifdef HAVE_PQPING
343
353
  /*
344
354
  * call-seq:
345
- * PG::Connection.ping(connection_hash) -> Fixnum
346
- * PG::Connection.ping(connection_string) -> Fixnum
347
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Fixnum
355
+ * PG::Connection.ping(connection_hash) -> Integer
356
+ * PG::Connection.ping(connection_string) -> Integer
357
+ * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
348
358
  *
349
359
  * Check server status.
350
360
  *
@@ -373,7 +383,7 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
373
383
 
374
384
 
375
385
  /*
376
- * Document-method: conndefaults
386
+ * Document-method: PG::Connection.conndefaults
377
387
  *
378
388
  * call-seq:
379
389
  * PG::Connection.conndefaults() -> Array
@@ -447,7 +457,7 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
447
457
 
448
458
  /*
449
459
  * call-seq:
450
- * conn.connect_poll() -> Fixnum
460
+ * conn.connect_poll() -> Integer
451
461
  *
452
462
  * Returns one of:
453
463
  * [+PGRES_POLLING_READING+]
@@ -556,7 +566,7 @@ pgconn_reset_start(VALUE self)
556
566
 
557
567
  /*
558
568
  * call-seq:
559
- * conn.reset_poll -> Fixnum
569
+ * conn.reset_poll -> Integer
560
570
  *
561
571
  * Checks the status of a connection reset operation.
562
572
  * See #connect_start and #connect_poll for
@@ -795,7 +805,7 @@ pgconn_error_message(VALUE self)
795
805
 
796
806
  /*
797
807
  * call-seq:
798
- * conn.socket() -> Fixnum
808
+ * conn.socket() -> Integer
799
809
  *
800
810
  * Returns the socket's file descriptor for this connection.
801
811
  * <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
@@ -870,7 +880,7 @@ pgconn_socket_io(VALUE self)
870
880
 
871
881
  /*
872
882
  * call-seq:
873
- * conn.backend_pid() -> Fixnum
883
+ * conn.backend_pid() -> Integer
874
884
  *
875
885
  * Returns the process ID of the backend server
876
886
  * process for this connection.
@@ -947,9 +957,9 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
947
957
 
948
958
  /* If called with no parameters, use PQexec */
949
959
  if ( argc == 1 ) {
950
- Check_Type(argv[0], T_STRING);
960
+ VALUE query_str = argv[0];
951
961
 
952
- result = gvl_PQexec(conn, StringValueCStr(argv[0]));
962
+ result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
953
963
  rb_pgresult = pg_new_result(result, self);
954
964
  pg_result_check(rb_pgresult);
955
965
  if (rb_block_given_p()) {
@@ -978,6 +988,10 @@ struct query_params_data {
978
988
  * Filled by caller
979
989
  */
980
990
 
991
+ /* The character encoding index of the connection. Any strings
992
+ * given as query parameters are converted to this encoding.
993
+ */
994
+ int enc_idx;
981
995
  /* Is the query function to execute one with types array? */
982
996
  int with_types;
983
997
  /* Array of query params from user space */
@@ -1138,7 +1152,7 @@ alloc_query_params(struct query_params_data *paramsData)
1138
1152
  VALUE intermediate;
1139
1153
 
1140
1154
  /* 1st pass for retiving the required memory space */
1141
- int len = enc_func(conv, param_value, NULL, &intermediate);
1155
+ int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
1142
1156
 
1143
1157
  if( len == -1 ){
1144
1158
  /* The intermediate value is a String that can be used directly. */
@@ -1162,7 +1176,7 @@ alloc_query_params(struct query_params_data *paramsData)
1162
1176
  }
1163
1177
 
1164
1178
  /* 2nd pass for writing the data to prepared buffer */
1165
- len = enc_func(conv, param_value, typecast_buf, &intermediate);
1179
+ len = enc_func(conv, param_value, typecast_buf, &intermediate, paramsData->enc_idx);
1166
1180
  paramsData->values[i] = typecast_buf;
1167
1181
  if( paramsData->formats[i] == 0 ){
1168
1182
  /* text format strings must be zero terminated and lengths are ignored */
@@ -1220,8 +1234,8 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1220
1234
  * Each element of the +params+ array may be either:
1221
1235
  * a hash of the form:
1222
1236
  * {:value => String (value of bind parameter)
1223
- * :type => Fixnum (oid of type of bind parameter)
1224
- * :format => Fixnum (0 for text, 1 for binary)
1237
+ * :type => Integer (oid of type of bind parameter)
1238
+ * :format => Integer (0 for text, 1 for binary)
1225
1239
  * }
1226
1240
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1227
1241
  * { :value => <string value>, :type => 0, :format => 0 }
@@ -1258,7 +1272,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1258
1272
  VALUE command, in_res_fmt;
1259
1273
  int nParams;
1260
1274
  int resultFormat;
1261
- struct query_params_data paramsData;
1275
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1262
1276
 
1263
1277
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1264
1278
  paramsData.with_types = 1;
@@ -1275,7 +1289,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1275
1289
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1276
1290
  nParams = alloc_query_params( &paramsData );
1277
1291
 
1278
- result = gvl_PQexecParams(conn, StringValueCStr(command), nParams, paramsData.types,
1292
+ result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1279
1293
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1280
1294
 
1281
1295
  free_query_params( &paramsData );
@@ -1321,10 +1335,13 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1321
1335
  int i = 0;
1322
1336
  int nParams = 0;
1323
1337
  Oid *paramTypes = NULL;
1338
+ const char *name_cstr;
1339
+ const char *command_cstr;
1340
+ int enc_idx = ENCODING_GET(self);
1324
1341
 
1325
1342
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1326
- Check_Type(name, T_STRING);
1327
- Check_Type(command, T_STRING);
1343
+ name_cstr = pg_cstr_enc(name, enc_idx);
1344
+ command_cstr = pg_cstr_enc(command, enc_idx);
1328
1345
 
1329
1346
  if(! NIL_P(in_paramtypes)) {
1330
1347
  Check_Type(in_paramtypes, T_ARRAY);
@@ -1338,8 +1355,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1338
1355
  paramTypes[i] = NUM2UINT(param);
1339
1356
  }
1340
1357
  }
1341
- result = gvl_PQprepare(conn, StringValueCStr(name), StringValueCStr(command),
1342
- nParams, paramTypes);
1358
+ result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1343
1359
 
1344
1360
  xfree(paramTypes);
1345
1361
 
@@ -1361,7 +1377,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1361
1377
  * SQL query. Each element of the +params+ array may be either:
1362
1378
  * a hash of the form:
1363
1379
  * {:value => String (value of bind parameter)
1364
- * :format => Fixnum (0 for text, 1 for binary)
1380
+ * :format => Integer (0 for text, 1 for binary)
1365
1381
  * }
1366
1382
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1367
1383
  * { :value => <string value>, :format => 0 }
@@ -1392,11 +1408,10 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1392
1408
  VALUE name, in_res_fmt;
1393
1409
  int nParams;
1394
1410
  int resultFormat;
1395
- struct query_params_data paramsData;
1411
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1396
1412
 
1397
1413
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1398
1414
  paramsData.with_types = 0;
1399
- Check_Type(name, T_STRING);
1400
1415
 
1401
1416
  if(NIL_P(paramsData.params)) {
1402
1417
  paramsData.params = rb_ary_new2(0);
@@ -1406,7 +1421,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1406
1421
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1407
1422
  nParams = alloc_query_params( &paramsData );
1408
1423
 
1409
- result = gvl_PQexecPrepared(conn, StringValueCStr(name), nParams,
1424
+ result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1410
1425
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1411
1426
  resultFormat);
1412
1427
 
@@ -1434,13 +1449,12 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1434
1449
  PGresult *result;
1435
1450
  VALUE rb_pgresult;
1436
1451
  PGconn *conn = pg_get_pgconn(self);
1437
- char *stmt;
1438
- if(stmt_name == Qnil) {
1452
+ const char *stmt;
1453
+ if(NIL_P(stmt_name)) {
1439
1454
  stmt = NULL;
1440
1455
  }
1441
1456
  else {
1442
- Check_Type(stmt_name, T_STRING);
1443
- stmt = StringValueCStr(stmt_name);
1457
+ stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1444
1458
  }
1445
1459
  result = gvl_PQdescribePrepared(conn, stmt);
1446
1460
  rb_pgresult = pg_new_result(result, self);
@@ -1462,13 +1476,12 @@ pgconn_describe_portal(self, stmt_name)
1462
1476
  PGresult *result;
1463
1477
  VALUE rb_pgresult;
1464
1478
  PGconn *conn = pg_get_pgconn(self);
1465
- char *stmt;
1466
- if(stmt_name == Qnil) {
1479
+ const char *stmt;
1480
+ if(NIL_P(stmt_name)) {
1467
1481
  stmt = NULL;
1468
1482
  }
1469
1483
  else {
1470
- Check_Type(stmt_name, T_STRING);
1471
- stmt = StringValueCStr(stmt_name);
1484
+ stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1472
1485
  }
1473
1486
  result = gvl_PQdescribePortal(conn, stmt);
1474
1487
  rb_pgresult = pg_new_result(result, self);
@@ -1510,10 +1523,6 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1510
1523
  * call-seq:
1511
1524
  * conn.escape_string( str ) -> String
1512
1525
  *
1513
- * Connection instance method for versions of 8.1 and higher of libpq
1514
- * uses PQescapeStringConn, which is safer. Avoid calling as a class method,
1515
- * the class method uses the deprecated PQescapeString() API function.
1516
- *
1517
1526
  * Returns a SQL-safe version of the String _str_.
1518
1527
  * This is the preferred way to make strings safe for inclusion in
1519
1528
  * SQL queries.
@@ -1522,32 +1531,41 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1522
1531
  * inside of SQL commands.
1523
1532
  *
1524
1533
  * Encoding of escaped string will be equal to client encoding of connection.
1534
+ *
1535
+ * NOTE: This class version of this method can only be used safely in client
1536
+ * programs that use a single PostgreSQL connection at a time (in this case it can
1537
+ * find out what it needs to know "behind the scenes"). It might give the wrong
1538
+ * results if used in programs that use multiple database connections; use the
1539
+ * same method on the connection object in such cases.
1525
1540
  */
1526
1541
  static VALUE
1527
1542
  pgconn_s_escape(VALUE self, VALUE string)
1528
1543
  {
1529
- char *escaped;
1530
1544
  size_t size;
1531
1545
  int error;
1532
1546
  VALUE result;
1547
+ int enc_idx;
1548
+ int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1533
1549
 
1534
1550
  Check_Type(string, T_STRING);
1551
+ enc_idx = ENCODING_GET( singleton ? string : self );
1552
+ if( ENCODING_GET(string) != enc_idx ){
1553
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1554
+ }
1535
1555
 
1536
- escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
1537
- if( rb_obj_is_kind_of(self, rb_cPGconn) ) {
1538
- size = PQescapeStringConn(pg_get_pgconn(self), escaped,
1556
+ result = rb_str_new(NULL, RSTRING_LEN(string) * 2 + 1);
1557
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1558
+ if( !singleton ) {
1559
+ size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1539
1560
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1540
1561
  if(error) {
1541
- xfree(escaped);
1542
1562
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1543
1563
  }
1544
1564
  } else {
1545
- size = PQescapeString(escaped, RSTRING_PTR(string), RSTRING_LENINT(string));
1565
+ size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1546
1566
  }
1547
- result = rb_str_new(escaped, size);
1548
- xfree(escaped);
1567
+ rb_str_set_len(result, size);
1549
1568
  OBJ_INFECT(result, string);
1550
- PG_ENCODING_SET_NOCHECK(result, ENCODING_GET( rb_obj_is_kind_of(self, rb_cPGconn) ? self : string ));
1551
1569
 
1552
1570
  return result;
1553
1571
  }
@@ -1556,13 +1574,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1556
1574
  * call-seq:
1557
1575
  * conn.escape_bytea( string ) -> String
1558
1576
  *
1559
- * Connection instance method for versions of 8.1 and higher of libpq
1560
- * uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
1561
- * the class method uses the deprecated PQescapeBytea() API function.
1562
- *
1563
- * Use the instance method version of this function, it is safer than the
1564
- * class method.
1565
- *
1566
1577
  * Escapes binary data for use within an SQL command with the type +bytea+.
1567
1578
  *
1568
1579
  * Certain byte values must be escaped (but all byte values may be escaped)
@@ -1575,6 +1586,12 @@ pgconn_s_escape(VALUE self, VALUE string)
1575
1586
  *
1576
1587
  * Consider using exec_params, which avoids the need for passing values inside of
1577
1588
  * SQL commands.
1589
+ *
1590
+ * NOTE: This class version of this method can only be used safely in client
1591
+ * programs that use a single PostgreSQL connection at a time (in this case it can
1592
+ * find out what it needs to know "behind the scenes"). It might give the wrong
1593
+ * results if used in programs that use multiple database connections; use the
1594
+ * same method on the connection object in such cases.
1578
1595
  */
1579
1596
  static VALUE
1580
1597
  pgconn_s_escape_bytea(VALUE self, VALUE str)
@@ -1643,8 +1660,12 @@ pgconn_escape_literal(VALUE self, VALUE string)
1643
1660
  char *escaped = NULL;
1644
1661
  VALUE error;
1645
1662
  VALUE result = Qnil;
1663
+ int enc_idx = ENCODING_GET(self);
1646
1664
 
1647
1665
  Check_Type(string, T_STRING);
1666
+ if( ENCODING_GET(string) != enc_idx ){
1667
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1668
+ }
1648
1669
 
1649
1670
  escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1650
1671
  if (escaped == NULL)
@@ -1657,7 +1678,7 @@ pgconn_escape_literal(VALUE self, VALUE string)
1657
1678
  result = rb_str_new2(escaped);
1658
1679
  PQfreemem(escaped);
1659
1680
  OBJ_INFECT(result, string);
1660
- PG_ENCODING_SET_NOCHECK(result, ENCODING_GET(self));
1681
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1661
1682
 
1662
1683
  return result;
1663
1684
  }
@@ -1670,8 +1691,9 @@ pgconn_escape_literal(VALUE self, VALUE string)
1670
1691
  *
1671
1692
  * Escape an arbitrary String +str+ as an identifier.
1672
1693
  *
1673
- * This method does the same as #quote_ident, but uses libpq to
1674
- * process the string.
1694
+ * This method does the same as #quote_ident with a String argument,
1695
+ * but it doesn't support an Array argument and it makes use of libpq
1696
+ * to process the string.
1675
1697
  */
1676
1698
  static VALUE
1677
1699
  pgconn_escape_identifier(VALUE self, VALUE string)
@@ -1680,8 +1702,12 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1680
1702
  char *escaped = NULL;
1681
1703
  VALUE error;
1682
1704
  VALUE result = Qnil;
1705
+ int enc_idx = ENCODING_GET(self);
1683
1706
 
1684
1707
  Check_Type(string, T_STRING);
1708
+ if( ENCODING_GET(string) != enc_idx ){
1709
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1710
+ }
1685
1711
 
1686
1712
  escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1687
1713
  if (escaped == NULL)
@@ -1694,7 +1720,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1694
1720
  result = rb_str_new2(escaped);
1695
1721
  PQfreemem(escaped);
1696
1722
  OBJ_INFECT(result, string);
1697
- PG_ENCODING_SET_NOCHECK(result, ENCODING_GET(self));
1723
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1698
1724
 
1699
1725
  return result;
1700
1726
  }
@@ -1767,8 +1793,8 @@ pgconn_set_single_row_mode(VALUE self)
1767
1793
  * Each element of the +params+ array may be either:
1768
1794
  * a hash of the form:
1769
1795
  * {:value => String (value of bind parameter)
1770
- * :type => Fixnum (oid of type of bind parameter)
1771
- * :format => Fixnum (0 for text, 1 for binary)
1796
+ * :type => Integer (oid of type of bind parameter)
1797
+ * :format => Integer (0 for text, 1 for binary)
1772
1798
  * }
1773
1799
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1774
1800
  * { :value => <string value>, :type => 0, :format => 0 }
@@ -1802,15 +1828,14 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1802
1828
  VALUE error;
1803
1829
  int nParams;
1804
1830
  int resultFormat;
1805
- struct query_params_data paramsData;
1831
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1806
1832
 
1807
1833
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1808
1834
  paramsData.with_types = 1;
1809
- Check_Type(command, T_STRING);
1810
1835
 
1811
1836
  /* If called with no parameters, use PQsendQuery */
1812
1837
  if(NIL_P(paramsData.params)) {
1813
- if(gvl_PQsendQuery(conn,StringValueCStr(command)) == 0) {
1838
+ if(gvl_PQsendQuery(conn, pg_cstr_enc(command, paramsData.enc_idx)) == 0) {
1814
1839
  error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1815
1840
  rb_iv_set(error, "@connection", self);
1816
1841
  rb_exc_raise(error);
@@ -1826,7 +1851,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1826
1851
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1827
1852
  nParams = alloc_query_params( &paramsData );
1828
1853
 
1829
- result = gvl_PQsendQueryParams(conn, StringValueCStr(command), nParams, paramsData.types,
1854
+ result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1830
1855
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1831
1856
 
1832
1857
  free_query_params( &paramsData );
@@ -1870,10 +1895,13 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1870
1895
  int i = 0;
1871
1896
  int nParams = 0;
1872
1897
  Oid *paramTypes = NULL;
1898
+ const char *name_cstr;
1899
+ const char *command_cstr;
1900
+ int enc_idx = ENCODING_GET(self);
1873
1901
 
1874
1902
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1875
- Check_Type(name, T_STRING);
1876
- Check_Type(command, T_STRING);
1903
+ name_cstr = pg_cstr_enc(name, enc_idx);
1904
+ command_cstr = pg_cstr_enc(command, enc_idx);
1877
1905
 
1878
1906
  if(! NIL_P(in_paramtypes)) {
1879
1907
  Check_Type(in_paramtypes, T_ARRAY);
@@ -1887,8 +1915,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1887
1915
  paramTypes[i] = NUM2UINT(param);
1888
1916
  }
1889
1917
  }
1890
- result = gvl_PQsendPrepare(conn, StringValueCStr(name), StringValueCStr(command),
1891
- nParams, paramTypes);
1918
+ result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1892
1919
 
1893
1920
  xfree(paramTypes);
1894
1921
 
@@ -1913,7 +1940,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1913
1940
  * SQL query. Each element of the +params+ array may be either:
1914
1941
  * a hash of the form:
1915
1942
  * {:value => String (value of bind parameter)
1916
- * :format => Fixnum (0 for text, 1 for binary)
1943
+ * :format => Integer (0 for text, 1 for binary)
1917
1944
  * }
1918
1945
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1919
1946
  * { :value => <string value>, :format => 0 }
@@ -1941,11 +1968,10 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1941
1968
  VALUE error;
1942
1969
  int nParams;
1943
1970
  int resultFormat;
1944
- struct query_params_data paramsData;
1971
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1945
1972
 
1946
1973
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1947
1974
  paramsData.with_types = 0;
1948
- Check_Type(name, T_STRING);
1949
1975
 
1950
1976
  if(NIL_P(paramsData.params)) {
1951
1977
  paramsData.params = rb_ary_new2(0);
@@ -1956,7 +1982,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1956
1982
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1957
1983
  nParams = alloc_query_params( &paramsData );
1958
1984
 
1959
- result = gvl_PQsendQueryPrepared(conn, StringValueCStr(name), nParams,
1985
+ result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1960
1986
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1961
1987
  resultFormat);
1962
1988
 
@@ -1983,7 +2009,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
1983
2009
  VALUE error;
1984
2010
  PGconn *conn = pg_get_pgconn(self);
1985
2011
  /* returns 0 on failure */
1986
- if(gvl_PQsendDescribePrepared(conn,StringValueCStr(stmt_name)) == 0) {
2012
+ if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
1987
2013
  error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1988
2014
  rb_iv_set(error, "@connection", self);
1989
2015
  rb_exc_raise(error);
@@ -2005,7 +2031,7 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
2005
2031
  VALUE error;
2006
2032
  PGconn *conn = pg_get_pgconn(self);
2007
2033
  /* returns 0 on failure */
2008
- if(gvl_PQsendDescribePortal(conn,StringValueCStr(portal)) == 0) {
2034
+ if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
2009
2035
  error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2010
2036
  rb_iv_set(error, "@connection", self);
2011
2037
  rb_exc_raise(error);
@@ -2565,16 +2591,17 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2565
2591
 
2566
2592
  if( p_coder ){
2567
2593
  t_pg_coder_enc_func enc_func;
2594
+ int enc_idx = ENCODING_GET(self);
2568
2595
 
2569
2596
  enc_func = pg_coder_enc_func( p_coder );
2570
- len = enc_func( p_coder, value, NULL, &intermediate );
2597
+ len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
2571
2598
 
2572
2599
  if( len == -1 ){
2573
2600
  /* The intermediate value is a String that can be used directly. */
2574
2601
  buffer = intermediate;
2575
2602
  } else {
2576
2603
  buffer = rb_str_new(NULL, len);
2577
- len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate);
2604
+ len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate, enc_idx);
2578
2605
  rb_str_set_len( buffer, len );
2579
2606
  }
2580
2607
  }
@@ -2613,13 +2640,13 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2613
2640
  VALUE str;
2614
2641
  VALUE error;
2615
2642
  int ret;
2616
- char *error_message = NULL;
2643
+ const char *error_message = NULL;
2617
2644
  PGconn *conn = pg_get_pgconn(self);
2618
2645
 
2619
2646
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2620
2647
  error_message = NULL;
2621
2648
  else
2622
- error_message = StringValueCStr(str);
2649
+ error_message = pg_cstr_enc(str, ENCODING_GET(self));
2623
2650
 
2624
2651
  ret = gvl_PQputCopyEnd(conn, error_message);
2625
2652
  if(ret == -1) {
@@ -2697,7 +2724,7 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2697
2724
 
2698
2725
  /*
2699
2726
  * call-seq:
2700
- * conn.set_error_verbosity( verbosity ) -> Fixnum
2727
+ * conn.set_error_verbosity( verbosity ) -> Integer
2701
2728
  *
2702
2729
  * Sets connection's verbosity to _verbosity_ and returns
2703
2730
  * the previous setting. Available settings are:
@@ -2940,7 +2967,7 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
2940
2967
 
2941
2968
  Check_Type(str, T_STRING);
2942
2969
 
2943
- if ( (PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2970
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2944
2971
  rb_raise(rb_ePGerror, "invalid encoding name: %s",StringValueCStr(str));
2945
2972
  }
2946
2973
  #ifdef M17N_SUPPORTED
@@ -2996,10 +3023,10 @@ pgconn_transaction(VALUE self)
2996
3023
 
2997
3024
  /*
2998
3025
  * call-seq:
2999
- * PG::Connection.quote_ident( str ) -> String
3000
- * PG::Connection.quote_ident( array ) -> String
3001
3026
  * conn.quote_ident( str ) -> String
3002
3027
  * conn.quote_ident( array ) -> String
3028
+ * PG::Connection.quote_ident( str ) -> String
3029
+ * PG::Connection.quote_ident( array ) -> String
3003
3030
  *
3004
3031
  * Returns a string that is safe for inclusion in a SQL query as an
3005
3032
  * identifier. Note: this is not a quote function for values, but for
@@ -3009,7 +3036,7 @@ pgconn_transaction(VALUE self)
3009
3036
  * The identifier <tt>FOO</tt> is folded to lower case, so it actually
3010
3037
  * means <tt>foo</tt>. If you really want to access the case-sensitive
3011
3038
  * field name <tt>FOO</tt>, use this function like
3012
- * <tt>PG::Connection.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
3039
+ * <tt>conn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
3013
3040
  * (with double-quotes). PostgreSQL will see the double-quotes, and
3014
3041
  * it will not fold to lower case.
3015
3042
  *
@@ -3023,15 +3050,27 @@ pgconn_transaction(VALUE self)
3023
3050
  *
3024
3051
  * This method is functional identical to the encoder PG::TextEncoder::Identifier .
3025
3052
  *
3053
+ * If the instance method form is used and the input string character encoding
3054
+ * is different to the connection encoding, then the string is converted to this
3055
+ * encoding, so that the returned string is always encoded as PG::Connection#internal_encoding .
3056
+ *
3057
+ * In the singleton form (PG::Connection.quote_ident) the character encoding
3058
+ * of the result string is set to the character encoding of the input string.
3026
3059
  */
3027
3060
  static VALUE
3028
- pgconn_s_quote_ident(VALUE self, VALUE in_str)
3061
+ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3029
3062
  {
3030
3063
  VALUE ret;
3031
- pg_text_enc_identifier(NULL, in_str, NULL, &ret);
3064
+ int enc_idx;
3032
3065
 
3033
- OBJ_INFECT(ret, in_str);
3034
- PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET( rb_obj_is_kind_of(self, rb_cPGconn) ? self : in_str ));
3066
+ if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3067
+ enc_idx = ENCODING_GET( self );
3068
+ }else{
3069
+ enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3070
+ }
3071
+ pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3072
+
3073
+ OBJ_INFECT(ret, str_or_array);
3035
3074
 
3036
3075
  return ret;
3037
3076
  }
@@ -3157,13 +3196,91 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3157
3196
  return rb_pgresult;
3158
3197
  }
3159
3198
 
3199
+
3200
+ #ifdef HAVE_PQSSLATTRIBUTE
3201
+ /* Since PostgreSQL-9.5: */
3202
+
3203
+ /*
3204
+ * call-seq:
3205
+ * conn.ssl_in_use? -> Boolean
3206
+ *
3207
+ * Returns +true+ if the connection uses SSL, +false+ if not.
3208
+ *
3209
+ */
3210
+ static VALUE
3211
+ pgconn_ssl_in_use(VALUE self)
3212
+ {
3213
+ return PQsslInUse(pg_get_pgconn(self)) ? Qtrue : Qfalse;
3214
+ }
3215
+
3216
+
3217
+ /*
3218
+ * call-seq:
3219
+ * conn.ssl_attribute(attribute_name) -> String
3220
+ *
3221
+ * Returns SSL-related information about the connection.
3222
+ *
3223
+ * The list of available attributes varies depending on the SSL library being used,
3224
+ * and the type of connection. If an attribute is not available, returns nil.
3225
+ *
3226
+ * The following attributes are commonly available:
3227
+ *
3228
+ * [+library+]
3229
+ * Name of the SSL implementation in use. (Currently, only "OpenSSL" is implemented)
3230
+ * [+protocol+]
3231
+ * SSL/TLS version in use. Common values are "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" and "TLSv1.2", but an implementation may return other strings if some other protocol is used.
3232
+ * [+key_bits+]
3233
+ * Number of key bits used by the encryption algorithm.
3234
+ * [+cipher+]
3235
+ * A short name of the ciphersuite used, e.g. "DHE-RSA-DES-CBC3-SHA". The names are specific to each SSL implementation.
3236
+ * [+compression+]
3237
+ * If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
3238
+ *
3239
+ *
3240
+ * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3241
+ */
3242
+ static VALUE
3243
+ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
3244
+ {
3245
+ const char *p_attr;
3246
+
3247
+ p_attr = PQsslAttribute(pg_get_pgconn(self), StringValueCStr(attribute_name));
3248
+ return p_attr ? rb_str_new_cstr(p_attr) : Qnil;
3249
+ }
3250
+
3251
+ /*
3252
+ * call-seq:
3253
+ * conn.ssl_attribute_names -> Array<String>
3254
+ *
3255
+ * Return an array of SSL attribute names available.
3256
+ *
3257
+ * See also #ssl_attribute
3258
+ *
3259
+ */
3260
+ static VALUE
3261
+ pgconn_ssl_attribute_names(VALUE self)
3262
+ {
3263
+ int i;
3264
+ const char * const * p_list = PQsslAttributeNames(pg_get_pgconn(self));
3265
+ VALUE ary = rb_ary_new();
3266
+
3267
+ for ( i = 0; p_list[i]; i++ ) {
3268
+ rb_ary_push( ary, rb_str_new_cstr( p_list[i] ));
3269
+ }
3270
+ return ary;
3271
+ }
3272
+
3273
+
3274
+ #endif
3275
+
3276
+
3160
3277
  /**************************************************************************
3161
3278
  * LARGE OBJECT SUPPORT
3162
3279
  **************************************************************************/
3163
3280
 
3164
3281
  /*
3165
3282
  * call-seq:
3166
- * conn.lo_creat( [mode] ) -> Fixnum
3283
+ * conn.lo_creat( [mode] ) -> Integer
3167
3284
  *
3168
3285
  * Creates a large object with mode _mode_. Returns a large object Oid.
3169
3286
  * On failure, it raises PG::Error.
@@ -3190,7 +3307,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3190
3307
 
3191
3308
  /*
3192
3309
  * call-seq:
3193
- * conn.lo_create( oid ) -> Fixnum
3310
+ * conn.lo_create( oid ) -> Integer
3194
3311
  *
3195
3312
  * Creates a large object with oid _oid_. Returns the large object Oid.
3196
3313
  * On failure, it raises PG::Error.
@@ -3211,7 +3328,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3211
3328
 
3212
3329
  /*
3213
3330
  * call-seq:
3214
- * conn.lo_import(file) -> Fixnum
3331
+ * conn.lo_import(file) -> Integer
3215
3332
  *
3216
3333
  * Import a file to a large object. Returns a large object Oid.
3217
3334
  *
@@ -3256,7 +3373,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3256
3373
 
3257
3374
  /*
3258
3375
  * call-seq:
3259
- * conn.lo_open( oid, [mode] ) -> Fixnum
3376
+ * conn.lo_open( oid, [mode] ) -> Integer
3260
3377
  *
3261
3378
  * Open a large object of _oid_. Returns a large object descriptor
3262
3379
  * instance on success. The _mode_ argument specifies the mode for
@@ -3287,7 +3404,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3287
3404
 
3288
3405
  /*
3289
3406
  * call-seq:
3290
- * conn.lo_write( lo_desc, buffer ) -> Fixnum
3407
+ * conn.lo_write( lo_desc, buffer ) -> Integer
3291
3408
  *
3292
3409
  * Writes the string _buffer_ to the large object _lo_desc_.
3293
3410
  * Returns the number of bytes written.
@@ -3354,7 +3471,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3354
3471
 
3355
3472
  /*
3356
3473
  * call-seq:
3357
- * conn.lo_lseek( lo_desc, offset, whence ) -> Fixnum
3474
+ * conn.lo_lseek( lo_desc, offset, whence ) -> Integer
3358
3475
  *
3359
3476
  * Move the large object pointer _lo_desc_ to offset _offset_.
3360
3477
  * Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
@@ -3376,7 +3493,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3376
3493
 
3377
3494
  /*
3378
3495
  * call-seq:
3379
- * conn.lo_tell( lo_desc ) -> Fixnum
3496
+ * conn.lo_tell( lo_desc ) -> Integer
3380
3497
  *
3381
3498
  * Returns the current position of the large object _lo_desc_.
3382
3499
  */
@@ -3512,7 +3629,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3512
3629
  rb_encoding *rbenc = rb_to_encoding( enc );
3513
3630
  const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
3514
3631
 
3515
- if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3632
+ if ( gvl_PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3516
3633
  VALUE server_encoding = pgconn_external_encoding( self );
3517
3634
  rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
3518
3635
  rb_enc_name(rb_to_encoding(server_encoding)), name );
@@ -3554,6 +3671,34 @@ pgconn_external_encoding(VALUE self)
3554
3671
  }
3555
3672
 
3556
3673
 
3674
+ static VALUE
3675
+ pgconn_set_client_encoding_async1( VALUE args )
3676
+ {
3677
+ VALUE self = ((VALUE*)args)[0];
3678
+ VALUE encname = ((VALUE*)args)[1];
3679
+ VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3680
+ VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3681
+
3682
+ pgconn_async_exec(1, &query, self);
3683
+ return 0;
3684
+ }
3685
+
3686
+
3687
+ static VALUE
3688
+ pgconn_set_client_encoding_async2( VALUE arg )
3689
+ {
3690
+ UNUSED(arg);
3691
+ return 1;
3692
+ }
3693
+
3694
+
3695
+ static VALUE
3696
+ pgconn_set_client_encoding_async( VALUE self, const char *encname )
3697
+ {
3698
+ VALUE args[] = { self, rb_str_new_cstr(encname) };
3699
+ return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3700
+ }
3701
+
3557
3702
 
3558
3703
  /*
3559
3704
  * call-seq:
@@ -3572,7 +3717,7 @@ pgconn_set_default_encoding( VALUE self )
3572
3717
 
3573
3718
  if (( enc = rb_default_internal_encoding() )) {
3574
3719
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3575
- if ( PQsetClientEncoding(conn, encname) != 0 )
3720
+ if ( pgconn_set_client_encoding_async(self, encname) != 0 )
3576
3721
  rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
3577
3722
  encname, PQerrorMessage(conn) );
3578
3723
  pgconn_set_internal_encoding_index( self );
@@ -3704,7 +3849,7 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
3704
3849
  *
3705
3850
  * Returns either:
3706
3851
  * * a kind of PG::Coder
3707
- * * +nil+ - type encoding is disabled, returned data will be a String.
3852
+ * * +nil+ - type encoding is disabled, data must be a String.
3708
3853
  *
3709
3854
  */
3710
3855
  static VALUE
@@ -3765,6 +3910,9 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
3765
3910
  }
3766
3911
 
3767
3912
 
3913
+ /*
3914
+ * Document-class: PG::Connection
3915
+ */
3768
3916
  void
3769
3917
  init_pg_connection()
3770
3918
  {
@@ -3901,6 +4049,12 @@ init_pg_connection()
3901
4049
  rb_define_alias(rb_cPGconn, "async_query", "async_exec");
3902
4050
  rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
3903
4051
 
4052
+ #ifdef HAVE_PQSSLATTRIBUTE
4053
+ rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
4054
+ rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
4055
+ rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4056
+ #endif
4057
+
3904
4058
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
3905
4059
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
3906
4060
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");