pg 0.18.4-x64-mingw32 → 0.19.0.pre20160817083826-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +686 -167
- data/History.rdoc +23 -0
- data/README.rdoc +6 -6
- data/Rakefile +10 -12
- data/Rakefile.cross +6 -6
- data/ext/errorcodes.def +16 -0
- data/ext/errorcodes.txt +5 -1
- data/ext/extconf.rb +9 -1
- data/ext/gvl_wrappers.h +4 -0
- data/ext/pg.c +1 -1
- data/ext/pg.h +6 -3
- data/ext/pg_binary_decoder.c +1 -1
- data/ext/pg_binary_encoder.c +8 -8
- data/ext/pg_coder.c +30 -9
- data/ext/pg_connection.c +203 -77
- data/ext/pg_copy_coder.c +34 -4
- data/ext/pg_result.c +2 -2
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +62 -42
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +1 -1
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +1 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/util.c +1 -1
- data/lib/2.0/pg_ext.so +0 -0
- data/lib/2.1/pg_ext.so +0 -0
- data/lib/2.2/pg_ext.so +0 -0
- data/lib/2.3/pg_ext.so +0 -0
- data/lib/libpq.dll +0 -0
- data/lib/pg.rb +3 -3
- data/lib/pg/basic_type_mapping.rb +35 -8
- data/lib/pg/connection.rb +46 -6
- data/lib/pg/result.rb +6 -2
- data/lib/pg/text_decoder.rb +7 -0
- data/lib/pg/text_encoder.rb +8 -0
- data/sample/disk_usage_report.rb +1 -1
- data/sample/pg_statistics.rb +1 -1
- data/sample/replication_monitor.rb +1 -1
- data/spec/helpers.rb +6 -9
- data/spec/pg/basic_type_mapping_spec.rb +54 -0
- data/spec/pg/connection_spec.rb +130 -23
- data/spec/pg/type_map_by_class_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_spec.rb +82 -2
- metadata +33 -35
- metadata.gz.sig +0 -0
- data/lib/x64-mingw32/libpq.dll +0 -0
data/ext/pg_connection.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_connection.c - PG::Connection class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
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
|
@@ -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
|
@@ -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
|
-
|
960
|
+
VALUE query_str = argv[0];
|
951
961
|
|
952
|
-
result = gvl_PQexec(conn,
|
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 */
|
@@ -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, ¶msData.params, &in_res_fmt, ¶msData.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( ¶msData );
|
1277
1291
|
|
1278
|
-
result = gvl_PQexecParams(conn,
|
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( ¶msData );
|
@@ -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
|
-
|
1327
|
-
|
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,
|
1342
|
-
nParams, paramTypes);
|
1358
|
+
result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
|
1343
1359
|
|
1344
1360
|
xfree(paramTypes);
|
1345
1361
|
|
@@ -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, ¶msData.params, &in_res_fmt, ¶msData.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( ¶msData );
|
1408
1423
|
|
1409
|
-
result = gvl_PQexecPrepared(conn,
|
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
|
1452
|
+
const char *stmt;
|
1453
|
+
if(NIL_P(stmt_name)) {
|
1439
1454
|
stmt = NULL;
|
1440
1455
|
}
|
1441
1456
|
else {
|
1442
|
-
|
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
|
1479
|
+
const char *stmt;
|
1480
|
+
if(NIL_P(stmt_name)) {
|
1467
1481
|
stmt = NULL;
|
1468
1482
|
}
|
1469
1483
|
else {
|
1470
|
-
|
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
|
-
|
1537
|
-
|
1538
|
-
|
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(
|
1565
|
+
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
1546
1566
|
}
|
1547
|
-
result
|
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,
|
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
|
1674
|
-
*
|
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,
|
1723
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1698
1724
|
|
1699
1725
|
return result;
|
1700
1726
|
}
|
@@ -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, ¶msData.params, &in_res_fmt, ¶msData.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,
|
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( ¶msData );
|
1828
1853
|
|
1829
|
-
result = gvl_PQsendQueryParams(conn,
|
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( ¶msData );
|
@@ -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
|
-
|
1876
|
-
|
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,
|
1891
|
-
nParams, paramTypes);
|
1918
|
+
result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
|
1892
1919
|
|
1893
1920
|
xfree(paramTypes);
|
1894
1921
|
|
@@ -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, ¶msData.params, &in_res_fmt, ¶msData.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( ¶msData );
|
1958
1984
|
|
1959
|
-
result = gvl_PQsendQueryPrepared(conn,
|
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,
|
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,
|
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 =
|
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) {
|
@@ -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 ( (
|
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>
|
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
|
3061
|
+
pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
|
3029
3062
|
{
|
3030
3063
|
VALUE ret;
|
3031
|
-
|
3064
|
+
int enc_idx;
|
3065
|
+
|
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);
|
3032
3072
|
|
3033
|
-
OBJ_INFECT(ret,
|
3034
|
-
PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET( rb_obj_is_kind_of(self, rb_cPGconn) ? self : in_str ));
|
3073
|
+
OBJ_INFECT(ret, str_or_array);
|
3035
3074
|
|
3036
3075
|
return ret;
|
3037
3076
|
}
|
@@ -3157,6 +3196,84 @@ 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
|
**************************************************************************/
|
@@ -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 (
|
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 );
|
@@ -3572,7 +3689,7 @@ pgconn_set_default_encoding( VALUE self )
|
|
3572
3689
|
|
3573
3690
|
if (( enc = rb_default_internal_encoding() )) {
|
3574
3691
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3575
|
-
if (
|
3692
|
+
if ( gvl_PQsetClientEncoding(conn, encname) != 0 )
|
3576
3693
|
rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
|
3577
3694
|
encname, PQerrorMessage(conn) );
|
3578
3695
|
pgconn_set_internal_encoding_index( self );
|
@@ -3704,7 +3821,7 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
|
|
3704
3821
|
*
|
3705
3822
|
* Returns either:
|
3706
3823
|
* * a kind of PG::Coder
|
3707
|
-
* * +nil+ - type encoding is disabled,
|
3824
|
+
* * +nil+ - type encoding is disabled, data must be a String.
|
3708
3825
|
*
|
3709
3826
|
*/
|
3710
3827
|
static VALUE
|
@@ -3765,6 +3882,9 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
3765
3882
|
}
|
3766
3883
|
|
3767
3884
|
|
3885
|
+
/*
|
3886
|
+
* Document-class: PG::Connection
|
3887
|
+
*/
|
3768
3888
|
void
|
3769
3889
|
init_pg_connection()
|
3770
3890
|
{
|
@@ -3901,6 +4021,12 @@ init_pg_connection()
|
|
3901
4021
|
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
3902
4022
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
|
3903
4023
|
|
4024
|
+
#ifdef HAVE_PQSSLATTRIBUTE
|
4025
|
+
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
4026
|
+
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
4027
|
+
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4028
|
+
#endif
|
4029
|
+
|
3904
4030
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
3905
4031
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
3906
4032
|
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|