pg 1.6.2 → 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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +61 -0
- data/Gemfile +5 -4
- data/README.ja.md +81 -30
- data/README.md +20 -10
- data/Rakefile +13 -26
- data/certs/larskanis-2026.pem +24 -0
- data/ext/errorcodes.def +9 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +8 -1
- data/ext/extconf.rb +19 -28
- data/ext/gvl_wrappers.c +2 -2
- data/ext/gvl_wrappers.h +40 -160
- data/ext/pg.c +8 -12
- data/ext/pg.h +14 -15
- data/ext/pg_binary_decoder.c +6 -2
- data/ext/pg_binary_encoder.c +7 -0
- data/ext/pg_cancel_connection.c +6 -6
- data/ext/pg_coder.c +4 -4
- data/ext/pg_connection.c +218 -161
- data/ext/pg_copy_coder.c +34 -21
- data/ext/pg_record_coder.c +10 -6
- data/ext/pg_result.c +131 -61
- data/ext/pg_text_decoder.c +6 -6
- data/ext/pg_text_encoder.c +7 -2
- data/ext/pg_tuple.c +2 -2
- data/ext/pg_type_map.c +41 -1
- data/ext/pg_type_map_all_strings.c +2 -2
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +2 -2
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/lib/pg/basic_type_map_based_on_result.rb +5 -0
- data/lib/pg/basic_type_map_for_queries.rb +9 -2
- data/lib/pg/basic_type_map_for_results.rb +5 -0
- data/lib/pg/connection.rb +166 -76
- data/lib/pg/text_decoder/date.rb +1 -1
- data/lib/pg/text_decoder/json.rb +1 -1
- data/lib/pg/text_encoder/date.rb +7 -1
- data/lib/pg/text_encoder/json.rb +1 -1
- data/lib/pg/version.rb +1 -1
- data/misc/yugabyte/docker-compose.yml +1 -1
- data/pg.gemspec +1 -1
- data/sample/async_mixed.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +19 -20
- metadata.gz.sig +0 -0
- data/ports/patches/openssl/3.5.2/0001-aarch64-mingw.patch +0 -21
- data/ports/patches/postgresql/17.6/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +0 -52
- /data/ports/patches/krb5/{1.22.1 → 1.22.2}/0001-Allow-static-linking-krb5-library.patch +0 -0
- /data/ports/patches/krb5/{1.22.1 → 1.22.2}/0002-unknown-command-line-option-on-clang.patch +0 -0
- /data/ports/patches/postgresql/{17.6 → 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
|
|
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 );
|
|
@@ -66,6 +66,7 @@ pg_get_connection_safe( VALUE self )
|
|
|
66
66
|
t_pg_connection *this;
|
|
67
67
|
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
|
68
68
|
|
|
69
|
+
rb_check_frozen(self);
|
|
69
70
|
if ( !this->pgconn )
|
|
70
71
|
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
|
71
72
|
|
|
@@ -152,13 +153,13 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
|
|
|
152
153
|
return ary;
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
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){
|
|
156
157
|
const char *ptr = StringValueCStr(str);
|
|
157
158
|
if( ENCODING_GET(str) == enc_idx ){
|
|
158
159
|
return ptr;
|
|
159
160
|
} else {
|
|
160
|
-
|
|
161
|
-
return StringValueCStr(
|
|
161
|
+
*transcoded_str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
|
|
162
|
+
return StringValueCStr(*transcoded_str);
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
|
|
@@ -187,6 +188,7 @@ pgconn_gc_compact( void *_this )
|
|
|
187
188
|
pg_gc_location( this->socket_io );
|
|
188
189
|
pg_gc_location( this->notice_receiver );
|
|
189
190
|
pg_gc_location( this->notice_processor );
|
|
191
|
+
pg_gc_location( this->self );
|
|
190
192
|
pg_gc_location( this->type_map_for_queries );
|
|
191
193
|
pg_gc_location( this->type_map_for_results );
|
|
192
194
|
pg_gc_location( this->trace_stream );
|
|
@@ -259,6 +261,7 @@ pgconn_s_allocate( VALUE klass )
|
|
|
259
261
|
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
|
260
262
|
RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
|
|
261
263
|
RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
|
|
264
|
+
RB_OBJ_WRITE(self, &this->self, self);
|
|
262
265
|
RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
|
|
263
266
|
RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
|
|
264
267
|
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
|
|
@@ -279,7 +282,8 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
|
279
282
|
|
|
280
283
|
this = pg_get_connection( self );
|
|
281
284
|
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
|
282
|
-
this->pgconn =
|
|
285
|
+
this->pgconn = PQconnectdb(StringValueCStr(conninfo));
|
|
286
|
+
RB_GC_GUARD(conninfo);
|
|
283
287
|
|
|
284
288
|
if(this->pgconn == NULL)
|
|
285
289
|
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
|
|
@@ -328,6 +332,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
|
328
332
|
this = pg_get_connection( rb_conn );
|
|
329
333
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
|
330
334
|
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
|
335
|
+
RB_GC_GUARD(conninfo);
|
|
331
336
|
|
|
332
337
|
if( this->pgconn == NULL )
|
|
333
338
|
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
|
@@ -349,6 +354,7 @@ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
|
|
|
349
354
|
|
|
350
355
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
|
351
356
|
ping = gvl_PQping( StringValueCStr(conninfo) );
|
|
357
|
+
RB_GC_GUARD(conninfo);
|
|
352
358
|
|
|
353
359
|
return INT2FIX((int)ping);
|
|
354
360
|
}
|
|
@@ -433,7 +439,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
|
433
439
|
Check_Type(password, T_STRING);
|
|
434
440
|
Check_Type(username, T_STRING);
|
|
435
441
|
|
|
436
|
-
encrypted =
|
|
442
|
+
encrypted = PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
|
|
437
443
|
if ( encrypted ) {
|
|
438
444
|
rval = rb_str_new2( encrypted );
|
|
439
445
|
PQfreemem( encrypted );
|
|
@@ -559,7 +565,7 @@ static VALUE
|
|
|
559
565
|
pgconn_sync_reset( VALUE self )
|
|
560
566
|
{
|
|
561
567
|
pgconn_close_socket_io( self );
|
|
562
|
-
|
|
568
|
+
PQreset( pg_get_pgconn(self) );
|
|
563
569
|
return self;
|
|
564
570
|
}
|
|
565
571
|
|
|
@@ -567,13 +573,17 @@ static VALUE
|
|
|
567
573
|
pgconn_reset_start2( VALUE self, VALUE conninfo )
|
|
568
574
|
{
|
|
569
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);
|
|
570
578
|
|
|
571
579
|
/* Close old connection */
|
|
572
580
|
pgconn_close_socket_io( self );
|
|
573
581
|
PQfinish( this->pgconn );
|
|
582
|
+
this->pgconn = NULL; /* Ensure no double free can happen. */
|
|
574
583
|
|
|
575
584
|
/* Start new connection */
|
|
576
|
-
this->pgconn = gvl_PQconnectStart(
|
|
585
|
+
this->pgconn = gvl_PQconnectStart( p_conninfo );
|
|
586
|
+
RB_GC_GUARD(conninfo);
|
|
577
587
|
|
|
578
588
|
if( this->pgconn == NULL )
|
|
579
589
|
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
|
@@ -864,6 +874,33 @@ pgconn_protocol_version(VALUE self)
|
|
|
864
874
|
return INT2NUM(protocol_version);
|
|
865
875
|
}
|
|
866
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
|
+
|
|
867
904
|
/*
|
|
868
905
|
* call-seq:
|
|
869
906
|
* conn.server_version -> Integer
|
|
@@ -1012,7 +1049,7 @@ pgconn_backend_pid(VALUE self)
|
|
|
1012
1049
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
|
1013
1050
|
}
|
|
1014
1051
|
|
|
1015
|
-
#ifndef
|
|
1052
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
1016
1053
|
typedef struct
|
|
1017
1054
|
{
|
|
1018
1055
|
struct sockaddr_storage addr;
|
|
@@ -1099,11 +1136,11 @@ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
|
|
1099
1136
|
* This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
|
|
1100
1137
|
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
|
1101
1138
|
*
|
|
1102
|
-
*
|
|
1103
|
-
* However #async_exec has two advantages:
|
|
1139
|
+
* However #async_exec has some advantages:
|
|
1104
1140
|
*
|
|
1105
|
-
* 1. #async_exec
|
|
1106
|
-
* 2.
|
|
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>.
|
|
1107
1144
|
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
|
1108
1145
|
*/
|
|
1109
1146
|
static VALUE
|
|
@@ -1116,8 +1153,10 @@ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
|
|
1116
1153
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
|
1117
1154
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
|
1118
1155
|
VALUE query_str = argv[0];
|
|
1156
|
+
VALUE transcoded_str;
|
|
1119
1157
|
|
|
1120
|
-
result =
|
|
1158
|
+
result = PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx, &transcoded_str));
|
|
1159
|
+
RB_GC_GUARD(transcoded_str);
|
|
1121
1160
|
rb_pgresult = pg_new_result(result, self);
|
|
1122
1161
|
pg_result_check(rb_pgresult);
|
|
1123
1162
|
if (rb_block_given_p()) {
|
|
@@ -1255,7 +1294,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1255
1294
|
int nParams;
|
|
1256
1295
|
int i=0;
|
|
1257
1296
|
t_pg_coder *conv;
|
|
1258
|
-
|
|
1297
|
+
size_t required_pool_size;
|
|
1259
1298
|
char *memory_pool;
|
|
1260
1299
|
|
|
1261
1300
|
Check_Type(paramsData->params, T_ARRAY);
|
|
@@ -1267,7 +1306,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
|
1267
1306
|
paramsData->typecast_heap_chain = Qnil;
|
|
1268
1307
|
paramsData->gc_array = Qnil;
|
|
1269
1308
|
|
|
1270
|
-
nParams = (
|
|
1309
|
+
nParams = RARRAY_LENINT(paramsData->params);
|
|
1271
1310
|
|
|
1272
1311
|
required_pool_size = nParams * (
|
|
1273
1312
|
sizeof(char *) +
|
|
@@ -1414,6 +1453,7 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1414
1453
|
PGresult *result = NULL;
|
|
1415
1454
|
VALUE rb_pgresult;
|
|
1416
1455
|
VALUE command, in_res_fmt;
|
|
1456
|
+
VALUE transcoded_str;
|
|
1417
1457
|
int nParams;
|
|
1418
1458
|
int resultFormat;
|
|
1419
1459
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1435,9 +1475,10 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
|
|
1435
1475
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
1436
1476
|
nParams = alloc_query_params( ¶msData );
|
|
1437
1477
|
|
|
1438
|
-
result =
|
|
1478
|
+
result = PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
|
|
1439
1479
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
|
1440
1480
|
|
|
1481
|
+
RB_GC_GUARD(transcoded_str);
|
|
1441
1482
|
free_query_params( ¶msData );
|
|
1442
1483
|
|
|
1443
1484
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -1466,6 +1507,7 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1466
1507
|
VALUE rb_pgresult;
|
|
1467
1508
|
VALUE name, command, in_paramtypes;
|
|
1468
1509
|
VALUE param;
|
|
1510
|
+
VALUE transcoded_str1, transcoded_str2;
|
|
1469
1511
|
int i = 0;
|
|
1470
1512
|
int nParams = 0;
|
|
1471
1513
|
Oid *paramTypes = NULL;
|
|
@@ -1474,12 +1516,12 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1474
1516
|
int enc_idx = this->enc_idx;
|
|
1475
1517
|
|
|
1476
1518
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
|
1477
|
-
name_cstr = pg_cstr_enc(name, enc_idx);
|
|
1478
|
-
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);
|
|
1479
1521
|
|
|
1480
1522
|
if(! NIL_P(in_paramtypes)) {
|
|
1481
1523
|
Check_Type(in_paramtypes, T_ARRAY);
|
|
1482
|
-
nParams = (
|
|
1524
|
+
nParams = RARRAY_LENINT(in_paramtypes);
|
|
1483
1525
|
paramTypes = ALLOC_N(Oid, nParams);
|
|
1484
1526
|
for(i = 0; i < nParams; i++) {
|
|
1485
1527
|
param = rb_ary_entry(in_paramtypes, i);
|
|
@@ -1489,8 +1531,10 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
1489
1531
|
paramTypes[i] = NUM2UINT(param);
|
|
1490
1532
|
}
|
|
1491
1533
|
}
|
|
1492
|
-
result =
|
|
1534
|
+
result = PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
|
1493
1535
|
|
|
1536
|
+
RB_GC_GUARD(transcoded_str1);
|
|
1537
|
+
RB_GC_GUARD(transcoded_str2);
|
|
1494
1538
|
xfree(paramTypes);
|
|
1495
1539
|
|
|
1496
1540
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -1514,6 +1558,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1514
1558
|
PGresult *result = NULL;
|
|
1515
1559
|
VALUE rb_pgresult;
|
|
1516
1560
|
VALUE name, in_res_fmt;
|
|
1561
|
+
VALUE transcoded_str;
|
|
1517
1562
|
int nParams;
|
|
1518
1563
|
int resultFormat;
|
|
1519
1564
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -1529,10 +1574,11 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
1529
1574
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
1530
1575
|
nParams = alloc_query_params( ¶msData );
|
|
1531
1576
|
|
|
1532
|
-
result =
|
|
1577
|
+
result = PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
|
|
1533
1578
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
|
1534
1579
|
resultFormat);
|
|
1535
1580
|
|
|
1581
|
+
RB_GC_GUARD(transcoded_str);
|
|
1536
1582
|
free_query_params( ¶msData );
|
|
1537
1583
|
|
|
1538
1584
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -1549,9 +1595,13 @@ pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*f
|
|
|
1549
1595
|
{
|
|
1550
1596
|
PGresult *result;
|
|
1551
1597
|
VALUE rb_pgresult;
|
|
1598
|
+
VALUE transcoded_str;
|
|
1552
1599
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1553
|
-
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
|
+
|
|
1554
1602
|
result = func(this->pgconn, stmt);
|
|
1603
|
+
|
|
1604
|
+
RB_GC_GUARD(transcoded_str);
|
|
1555
1605
|
rb_pgresult = pg_new_result(result, self);
|
|
1556
1606
|
pg_result_check(rb_pgresult);
|
|
1557
1607
|
return rb_pgresult;
|
|
@@ -1568,7 +1618,7 @@ pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*f
|
|
|
1568
1618
|
static VALUE
|
|
1569
1619
|
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1570
1620
|
{
|
|
1571
|
-
return pgconn_sync_describe_close_prepared_portal(self, stmt_name,
|
|
1621
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQdescribePrepared);
|
|
1572
1622
|
}
|
|
1573
1623
|
|
|
1574
1624
|
|
|
@@ -1583,11 +1633,11 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
1583
1633
|
static VALUE
|
|
1584
1634
|
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
1585
1635
|
{
|
|
1586
|
-
return pgconn_sync_describe_close_prepared_portal(self, stmt_name,
|
|
1636
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQdescribePortal);
|
|
1587
1637
|
}
|
|
1588
1638
|
|
|
1589
1639
|
|
|
1590
|
-
#ifdef
|
|
1640
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
1591
1641
|
/*
|
|
1592
1642
|
* call-seq:
|
|
1593
1643
|
* conn.sync_close_prepared( stmt_name ) -> PG::Result
|
|
@@ -1601,7 +1651,7 @@ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
|
|
1601
1651
|
static VALUE
|
|
1602
1652
|
pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
|
|
1603
1653
|
{
|
|
1604
|
-
return pgconn_sync_describe_close_prepared_portal(self, stmt_name,
|
|
1654
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQclosePrepared);
|
|
1605
1655
|
}
|
|
1606
1656
|
|
|
1607
1657
|
/*
|
|
@@ -1617,7 +1667,7 @@ pgconn_sync_close_prepared(VALUE self, VALUE stmt_name)
|
|
|
1617
1667
|
static VALUE
|
|
1618
1668
|
pgconn_sync_close_portal(VALUE self, VALUE stmt_name)
|
|
1619
1669
|
{
|
|
1620
|
-
return pgconn_sync_describe_close_prepared_portal(self, stmt_name,
|
|
1670
|
+
return pgconn_sync_describe_close_prepared_portal(self, stmt_name, PQclosePortal);
|
|
1621
1671
|
}
|
|
1622
1672
|
#endif
|
|
1623
1673
|
|
|
@@ -1891,7 +1941,7 @@ pgconn_set_single_row_mode(VALUE self)
|
|
|
1891
1941
|
return self;
|
|
1892
1942
|
}
|
|
1893
1943
|
|
|
1894
|
-
#ifdef
|
|
1944
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
1895
1945
|
/*
|
|
1896
1946
|
* call-seq:
|
|
1897
1947
|
* conn.set_chunked_rows_mode -> self
|
|
@@ -1948,13 +1998,15 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
|
|
1948
1998
|
static VALUE
|
|
1949
1999
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1950
2000
|
{
|
|
2001
|
+
VALUE transcoded_str;
|
|
1951
2002
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
1952
2003
|
|
|
1953
2004
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
|
1954
2005
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
|
1955
|
-
if(
|
|
2006
|
+
if(PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx, &transcoded_str)) == 0)
|
|
1956
2007
|
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));
|
|
1957
2008
|
|
|
2009
|
+
RB_GC_GUARD(transcoded_str);
|
|
1958
2010
|
pgconn_wait_for_flush( self );
|
|
1959
2011
|
return Qnil;
|
|
1960
2012
|
}
|
|
@@ -2011,6 +2063,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
2011
2063
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2012
2064
|
int result;
|
|
2013
2065
|
VALUE command, in_res_fmt;
|
|
2066
|
+
VALUE transcoded_str;
|
|
2014
2067
|
int nParams;
|
|
2015
2068
|
int resultFormat;
|
|
2016
2069
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -2022,9 +2075,10 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
|
2022
2075
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
2023
2076
|
nParams = alloc_query_params( ¶msData );
|
|
2024
2077
|
|
|
2025
|
-
result =
|
|
2078
|
+
result = PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
|
|
2026
2079
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
|
2027
2080
|
|
|
2081
|
+
RB_GC_GUARD(transcoded_str);
|
|
2028
2082
|
free_query_params( ¶msData );
|
|
2029
2083
|
|
|
2030
2084
|
if(result == 0)
|
|
@@ -2061,6 +2115,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
2061
2115
|
int result;
|
|
2062
2116
|
VALUE name, command, in_paramtypes;
|
|
2063
2117
|
VALUE param;
|
|
2118
|
+
VALUE transcoded_str1, transcoded_str2;
|
|
2064
2119
|
int i = 0;
|
|
2065
2120
|
int nParams = 0;
|
|
2066
2121
|
Oid *paramTypes = NULL;
|
|
@@ -2069,12 +2124,12 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
2069
2124
|
int enc_idx = this->enc_idx;
|
|
2070
2125
|
|
|
2071
2126
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
|
2072
|
-
name_cstr = pg_cstr_enc(name, enc_idx);
|
|
2073
|
-
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);
|
|
2074
2129
|
|
|
2075
2130
|
if(! NIL_P(in_paramtypes)) {
|
|
2076
2131
|
Check_Type(in_paramtypes, T_ARRAY);
|
|
2077
|
-
nParams = (
|
|
2132
|
+
nParams = RARRAY_LENINT(in_paramtypes);
|
|
2078
2133
|
paramTypes = ALLOC_N(Oid, nParams);
|
|
2079
2134
|
for(i = 0; i < nParams; i++) {
|
|
2080
2135
|
param = rb_ary_entry(in_paramtypes, i);
|
|
@@ -2084,8 +2139,10 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
|
2084
2139
|
paramTypes[i] = NUM2UINT(param);
|
|
2085
2140
|
}
|
|
2086
2141
|
}
|
|
2087
|
-
result =
|
|
2142
|
+
result = PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
|
2088
2143
|
|
|
2144
|
+
RB_GC_GUARD(transcoded_str1);
|
|
2145
|
+
RB_GC_GUARD(transcoded_str2);
|
|
2089
2146
|
xfree(paramTypes);
|
|
2090
2147
|
|
|
2091
2148
|
if(result == 0) {
|
|
@@ -2133,6 +2190,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2133
2190
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2134
2191
|
int result;
|
|
2135
2192
|
VALUE name, in_res_fmt;
|
|
2193
|
+
VALUE transcoded_str;
|
|
2136
2194
|
int nParams;
|
|
2137
2195
|
int resultFormat;
|
|
2138
2196
|
struct query_params_data paramsData = { this->enc_idx };
|
|
@@ -2148,10 +2206,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2148
2206
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
|
2149
2207
|
nParams = alloc_query_params( ¶msData );
|
|
2150
2208
|
|
|
2151
|
-
result =
|
|
2209
|
+
result = PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
|
|
2152
2210
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
|
2153
2211
|
resultFormat);
|
|
2154
2212
|
|
|
2213
|
+
RB_GC_GUARD(transcoded_str);
|
|
2155
2214
|
free_query_params( ¶msData );
|
|
2156
2215
|
|
|
2157
2216
|
if(result == 0)
|
|
@@ -2165,12 +2224,14 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
|
2165
2224
|
static VALUE
|
|
2166
2225
|
pgconn_send_describe_close_prepared_portal(VALUE self, VALUE name, int (*func)(PGconn *, const char *), const char *funame)
|
|
2167
2226
|
{
|
|
2227
|
+
VALUE transcoded_str;
|
|
2168
2228
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2169
|
-
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);
|
|
2170
2230
|
/* returns 0 on failure */
|
|
2171
2231
|
if(func(this->pgconn, stmt) == 0)
|
|
2172
2232
|
pg_raise_conn_error( rb_eUnableToSend, self, "%s %s", funame, PQerrorMessage(this->pgconn));
|
|
2173
2233
|
|
|
2234
|
+
RB_GC_GUARD(transcoded_str);
|
|
2174
2235
|
pgconn_wait_for_flush( self );
|
|
2175
2236
|
return Qnil;
|
|
2176
2237
|
}
|
|
@@ -2186,7 +2247,7 @@ static VALUE
|
|
|
2186
2247
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2187
2248
|
{
|
|
2188
2249
|
return pgconn_send_describe_close_prepared_portal(
|
|
2189
|
-
self, stmt_name,
|
|
2250
|
+
self, stmt_name, PQsendDescribePrepared,
|
|
2190
2251
|
"PQsendDescribePrepared");
|
|
2191
2252
|
}
|
|
2192
2253
|
|
|
@@ -2202,11 +2263,11 @@ static VALUE
|
|
|
2202
2263
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
2203
2264
|
{
|
|
2204
2265
|
return pgconn_send_describe_close_prepared_portal(
|
|
2205
|
-
self, portal,
|
|
2266
|
+
self, portal, PQsendDescribePortal,
|
|
2206
2267
|
"PQsendDescribePortal");
|
|
2207
2268
|
}
|
|
2208
2269
|
|
|
2209
|
-
#ifdef
|
|
2270
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
2210
2271
|
/*
|
|
2211
2272
|
* call-seq:
|
|
2212
2273
|
* conn.send_close_prepared( statement_name ) -> nil
|
|
@@ -2220,7 +2281,7 @@ static VALUE
|
|
|
2220
2281
|
pgconn_send_close_prepared(VALUE self, VALUE stmt_name)
|
|
2221
2282
|
{
|
|
2222
2283
|
return pgconn_send_describe_close_prepared_portal(
|
|
2223
|
-
self, stmt_name,
|
|
2284
|
+
self, stmt_name, PQsendClosePrepared,
|
|
2224
2285
|
"PQsendClosePrepared");
|
|
2225
2286
|
}
|
|
2226
2287
|
|
|
@@ -2238,7 +2299,7 @@ static VALUE
|
|
|
2238
2299
|
pgconn_send_close_portal(VALUE self, VALUE portal)
|
|
2239
2300
|
{
|
|
2240
2301
|
return pgconn_send_describe_close_prepared_portal(
|
|
2241
|
-
self, portal,
|
|
2302
|
+
self, portal, PQsendClosePortal,
|
|
2242
2303
|
"PQsendClosePortal");
|
|
2243
2304
|
}
|
|
2244
2305
|
#endif
|
|
@@ -2250,7 +2311,7 @@ pgconn_sync_get_result(VALUE self)
|
|
|
2250
2311
|
PGresult *result;
|
|
2251
2312
|
VALUE rb_pgresult;
|
|
2252
2313
|
|
|
2253
|
-
result =
|
|
2314
|
+
result = PQgetResult(conn);
|
|
2254
2315
|
if(result == NULL)
|
|
2255
2316
|
return Qnil;
|
|
2256
2317
|
rb_pgresult = pg_new_result(result, self);
|
|
@@ -2292,7 +2353,7 @@ pgconn_consume_input(VALUE self)
|
|
|
2292
2353
|
static VALUE
|
|
2293
2354
|
pgconn_is_busy(VALUE self)
|
|
2294
2355
|
{
|
|
2295
|
-
return
|
|
2356
|
+
return PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
|
2296
2357
|
}
|
|
2297
2358
|
|
|
2298
2359
|
static VALUE
|
|
@@ -2332,7 +2393,7 @@ pgconn_sync_flush(VALUE self)
|
|
|
2332
2393
|
return (ret) ? Qfalse : Qtrue;
|
|
2333
2394
|
}
|
|
2334
2395
|
|
|
2335
|
-
#ifndef
|
|
2396
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
2336
2397
|
static VALUE
|
|
2337
2398
|
pgconn_sync_cancel(VALUE self)
|
|
2338
2399
|
{
|
|
@@ -2345,7 +2406,7 @@ pgconn_sync_cancel(VALUE self)
|
|
|
2345
2406
|
if(cancel == NULL)
|
|
2346
2407
|
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
|
2347
2408
|
|
|
2348
|
-
ret =
|
|
2409
|
+
ret = PQcancel(cancel, errbuf, sizeof(errbuf));
|
|
2349
2410
|
if(ret == 1)
|
|
2350
2411
|
retval = Qnil;
|
|
2351
2412
|
else
|
|
@@ -2377,12 +2438,12 @@ pgconn_notifies(VALUE self)
|
|
|
2377
2438
|
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
|
2378
2439
|
sym_extra = ID2SYM(rb_intern("extra"));
|
|
2379
2440
|
|
|
2380
|
-
notification =
|
|
2441
|
+
notification = PQnotifies(this->pgconn);
|
|
2381
2442
|
if (notification == NULL) {
|
|
2382
2443
|
return Qnil;
|
|
2383
2444
|
}
|
|
2384
2445
|
|
|
2385
|
-
hash =
|
|
2446
|
+
hash = rb_hash_new_capa(3);
|
|
2386
2447
|
relname = rb_str_new2(notification->relname);
|
|
2387
2448
|
be_pid = INT2NUM(notification->be_pid);
|
|
2388
2449
|
extra = rb_str_new2(notification->extra);
|
|
@@ -2397,33 +2458,13 @@ pgconn_notifies(VALUE self)
|
|
|
2397
2458
|
return hash;
|
|
2398
2459
|
}
|
|
2399
2460
|
|
|
2400
|
-
#ifndef HAVE_RB_IO_DESCRIPTOR
|
|
2401
|
-
static int
|
|
2402
|
-
rb_io_descriptor(VALUE io)
|
|
2403
|
-
{
|
|
2404
|
-
rb_io_t *fptr;
|
|
2405
|
-
Check_Type(io, T_FILE);
|
|
2406
|
-
fptr = RFILE(io)->fptr;
|
|
2407
|
-
rb_io_check_closed(fptr);
|
|
2408
|
-
return fptr->fd;
|
|
2409
|
-
}
|
|
2410
|
-
#endif
|
|
2411
|
-
|
|
2412
2461
|
#if defined(_WIN32)
|
|
2413
2462
|
|
|
2414
2463
|
/* We use a specialized implementation of rb_io_wait() on Windows.
|
|
2415
2464
|
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
|
2416
2465
|
*/
|
|
2417
2466
|
|
|
2418
|
-
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
|
2419
2467
|
#include <ruby/fiber/scheduler.h>
|
|
2420
|
-
#endif
|
|
2421
|
-
|
|
2422
|
-
typedef enum {
|
|
2423
|
-
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
|
2424
|
-
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2425
|
-
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2426
|
-
} pg_rb_io_event_t;
|
|
2427
2468
|
|
|
2428
2469
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2429
2470
|
|
|
@@ -2447,9 +2488,9 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2447
2488
|
timeradd(&currtime, &ptimeout, &aborttime);
|
|
2448
2489
|
}
|
|
2449
2490
|
|
|
2450
|
-
if(rb_events &
|
|
2451
|
-
if(rb_events &
|
|
2452
|
-
if(rb_events &
|
|
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;
|
|
2453
2494
|
|
|
2454
2495
|
for(;;) {
|
|
2455
2496
|
if ( WSAEventSelect(_get_osfhandle(rb_io_descriptor(io)), hEvent, w32_events) == SOCKET_ERROR ) {
|
|
@@ -2493,49 +2534,20 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
|
2493
2534
|
|
|
2494
2535
|
static VALUE
|
|
2495
2536
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2496
|
-
|
|
2497
|
-
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
|
2498
|
-
* Fortunately ruby-3.1 offers a C-API for it.
|
|
2499
|
-
*/
|
|
2537
|
+
/* Avoid slow rb_io_wait() on Windows, if no scheduler is active. */
|
|
2500
2538
|
VALUE scheduler = rb_fiber_scheduler_current();
|
|
2501
2539
|
|
|
2502
2540
|
if (!NIL_P(scheduler)) {
|
|
2503
2541
|
return rb_io_wait(io, events, timeout);
|
|
2504
2542
|
}
|
|
2505
|
-
#endif
|
|
2506
2543
|
return pg_rb_thread_io_wait(io, events, timeout);
|
|
2507
2544
|
}
|
|
2508
2545
|
|
|
2509
|
-
#elif defined(HAVE_RB_IO_WAIT)
|
|
2510
|
-
|
|
2511
|
-
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
|
2512
|
-
#define pg_rb_io_wait rb_io_wait
|
|
2513
|
-
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
|
2514
|
-
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
|
2515
|
-
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
|
2516
|
-
|
|
2517
2546
|
#else
|
|
2518
|
-
/* For compat with ruby < 3.0 */
|
|
2519
2547
|
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
|
2523
|
-
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
|
2524
|
-
} pg_rb_io_event_t;
|
|
2525
|
-
|
|
2526
|
-
static VALUE
|
|
2527
|
-
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2528
|
-
struct timeval waittime;
|
|
2529
|
-
int res;
|
|
2530
|
-
|
|
2531
|
-
if( !NIL_P(timeout) ){
|
|
2532
|
-
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
|
2533
|
-
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
|
2534
|
-
}
|
|
2535
|
-
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
|
|
2536
2550
|
|
|
2537
|
-
return UINT2NUM(res);
|
|
2538
|
-
}
|
|
2539
2551
|
#endif
|
|
2540
2552
|
|
|
2541
2553
|
static void *
|
|
@@ -2570,7 +2582,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
|
2570
2582
|
|
|
2571
2583
|
socket_io = pgconn_socket_io(self);
|
|
2572
2584
|
/* Wait for the socket to become readable before checking again */
|
|
2573
|
-
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
2585
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), wait_timeout);
|
|
2574
2586
|
} else {
|
|
2575
2587
|
ret = Qfalse;
|
|
2576
2588
|
}
|
|
@@ -2607,9 +2619,9 @@ pgconn_async_flush(VALUE self)
|
|
|
2607
2619
|
/* wait for the socket to become read- or write-ready */
|
|
2608
2620
|
int events;
|
|
2609
2621
|
VALUE socket_io = pgconn_socket_io(self);
|
|
2610
|
-
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
2622
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
|
|
2611
2623
|
|
|
2612
|
-
if (events &
|
|
2624
|
+
if (events & RUBY_IO_READABLE){
|
|
2613
2625
|
pgconn_consume_input(self);
|
|
2614
2626
|
}
|
|
2615
2627
|
}
|
|
@@ -2635,7 +2647,7 @@ pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
|
|
2635
2647
|
static void *
|
|
2636
2648
|
notify_readable(PGconn *conn)
|
|
2637
2649
|
{
|
|
2638
|
-
return (void*)
|
|
2650
|
+
return (void*)PQnotifies(conn);
|
|
2639
2651
|
}
|
|
2640
2652
|
|
|
2641
2653
|
/*
|
|
@@ -2734,7 +2746,7 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
|
2734
2746
|
|
|
2735
2747
|
Check_Type(buffer, T_STRING);
|
|
2736
2748
|
|
|
2737
|
-
ret =
|
|
2749
|
+
ret = PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
|
|
2738
2750
|
if(ret == -1)
|
|
2739
2751
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2740
2752
|
|
|
@@ -2747,6 +2759,7 @@ static VALUE
|
|
|
2747
2759
|
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2748
2760
|
{
|
|
2749
2761
|
VALUE str;
|
|
2762
|
+
VALUE transcoded_str;
|
|
2750
2763
|
int ret;
|
|
2751
2764
|
const char *error_message = NULL;
|
|
2752
2765
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
@@ -2754,15 +2767,41 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
|
2754
2767
|
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
|
2755
2768
|
error_message = NULL;
|
|
2756
2769
|
else
|
|
2757
|
-
error_message = pg_cstr_enc(str, this->enc_idx);
|
|
2770
|
+
error_message = pg_cstr_enc(str, this->enc_idx, &transcoded_str);
|
|
2758
2771
|
|
|
2759
|
-
ret =
|
|
2772
|
+
ret = PQputCopyEnd(this->pgconn, error_message);
|
|
2760
2773
|
if(ret == -1)
|
|
2761
2774
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2762
2775
|
|
|
2776
|
+
RB_GC_GUARD(transcoded_str);
|
|
2763
2777
|
return (ret) ? Qtrue : Qfalse;
|
|
2764
2778
|
}
|
|
2765
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
|
+
|
|
2766
2805
|
static VALUE
|
|
2767
2806
|
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2768
2807
|
{
|
|
@@ -2785,7 +2824,7 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2785
2824
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
|
2786
2825
|
}
|
|
2787
2826
|
|
|
2788
|
-
ret =
|
|
2827
|
+
ret = PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
|
2789
2828
|
if(ret == -2){ /* error */
|
|
2790
2829
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
|
2791
2830
|
}
|
|
@@ -2797,8 +2836,9 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
|
2797
2836
|
}
|
|
2798
2837
|
|
|
2799
2838
|
if( p_coder ){
|
|
2800
|
-
|
|
2801
|
-
|
|
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);
|
|
2802
2842
|
} else {
|
|
2803
2843
|
result = rb_str_new(buffer, ret);
|
|
2804
2844
|
}
|
|
@@ -2931,11 +2971,10 @@ pgconn_untrace(VALUE self)
|
|
|
2931
2971
|
void
|
|
2932
2972
|
notice_receiver_proxy(void *arg, const PGresult *pgresult)
|
|
2933
2973
|
{
|
|
2934
|
-
|
|
2935
|
-
t_pg_connection *this = pg_get_connection( self );
|
|
2974
|
+
t_pg_connection *this = (t_pg_connection*)arg;
|
|
2936
2975
|
|
|
2937
2976
|
if (this->notice_receiver != Qnil) {
|
|
2938
|
-
VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, self );
|
|
2977
|
+
VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, this->self );
|
|
2939
2978
|
|
|
2940
2979
|
rb_funcall(this->notice_receiver, rb_intern("call"), 1, result);
|
|
2941
2980
|
pg_result_clear( result );
|
|
@@ -2990,7 +3029,7 @@ pgconn_set_notice_receiver(VALUE self)
|
|
|
2990
3029
|
old_proc = this->notice_receiver;
|
|
2991
3030
|
if( rb_block_given_p() ) {
|
|
2992
3031
|
proc = rb_block_proc();
|
|
2993
|
-
PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)
|
|
3032
|
+
PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)this);
|
|
2994
3033
|
} else {
|
|
2995
3034
|
/* if no block is given, set back to default */
|
|
2996
3035
|
proc = Qnil;
|
|
@@ -3009,8 +3048,7 @@ pgconn_set_notice_receiver(VALUE self)
|
|
|
3009
3048
|
void
|
|
3010
3049
|
notice_processor_proxy(void *arg, const char *message)
|
|
3011
3050
|
{
|
|
3012
|
-
|
|
3013
|
-
t_pg_connection *this = pg_get_connection( self );
|
|
3051
|
+
t_pg_connection *this = (t_pg_connection*)arg;
|
|
3014
3052
|
|
|
3015
3053
|
if (this->notice_processor != Qnil) {
|
|
3016
3054
|
VALUE message_str = rb_str_new2(message);
|
|
@@ -3051,7 +3089,7 @@ pgconn_set_notice_processor(VALUE self)
|
|
|
3051
3089
|
old_proc = this->notice_processor;
|
|
3052
3090
|
if( rb_block_given_p() ) {
|
|
3053
3091
|
proc = rb_block_proc();
|
|
3054
|
-
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)
|
|
3092
|
+
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)this);
|
|
3055
3093
|
} else {
|
|
3056
3094
|
/* if no block is given, set back to default */
|
|
3057
3095
|
proc = Qnil;
|
|
@@ -3093,7 +3131,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
|
3093
3131
|
rb_check_frozen(self);
|
|
3094
3132
|
Check_Type(str, T_STRING);
|
|
3095
3133
|
|
|
3096
|
-
if ( (
|
|
3134
|
+
if ( (PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
3097
3135
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3098
3136
|
|
|
3099
3137
|
pgconn_set_internal_encoding_index( self );
|
|
@@ -3158,7 +3196,7 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
|
|
|
3158
3196
|
static void *
|
|
3159
3197
|
get_result_readable(PGconn *conn)
|
|
3160
3198
|
{
|
|
3161
|
-
return
|
|
3199
|
+
return PQisBusy(conn) ? NULL : (void*)1;
|
|
3162
3200
|
}
|
|
3163
3201
|
|
|
3164
3202
|
|
|
@@ -3216,7 +3254,7 @@ pgconn_sync_get_last_result(VALUE self)
|
|
|
3216
3254
|
|
|
3217
3255
|
|
|
3218
3256
|
cur = prev = NULL;
|
|
3219
|
-
while ((cur =
|
|
3257
|
+
while ((cur = PQgetResult(conn)) != NULL) {
|
|
3220
3258
|
int status;
|
|
3221
3259
|
|
|
3222
3260
|
if (prev) PQclear(prev);
|
|
@@ -3268,7 +3306,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
|
3268
3306
|
*/
|
|
3269
3307
|
wait_socket_readable(self, NULL, get_result_readable);
|
|
3270
3308
|
|
|
3271
|
-
cur =
|
|
3309
|
+
cur = PQgetResult(conn);
|
|
3272
3310
|
if (cur == NULL)
|
|
3273
3311
|
break;
|
|
3274
3312
|
|
|
@@ -3325,18 +3363,18 @@ pgconn_discard_results(VALUE self)
|
|
|
3325
3363
|
/* pgconn_block() raises an exception in case of errors.
|
|
3326
3364
|
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
|
3327
3365
|
*/
|
|
3328
|
-
while(
|
|
3366
|
+
while( PQisBusy(conn) ){
|
|
3329
3367
|
int events;
|
|
3330
3368
|
|
|
3331
3369
|
switch( PQflush(conn) ) {
|
|
3332
3370
|
case 1:
|
|
3333
|
-
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
3334
|
-
if (events &
|
|
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){
|
|
3335
3373
|
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3336
3374
|
}
|
|
3337
3375
|
break;
|
|
3338
3376
|
case 0:
|
|
3339
|
-
pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
3377
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
|
|
3340
3378
|
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3341
3379
|
break;
|
|
3342
3380
|
default:
|
|
@@ -3344,23 +3382,23 @@ pgconn_discard_results(VALUE self)
|
|
|
3344
3382
|
}
|
|
3345
3383
|
}
|
|
3346
3384
|
|
|
3347
|
-
cur =
|
|
3385
|
+
cur = PQgetResult(conn);
|
|
3348
3386
|
if( cur == NULL) break;
|
|
3349
3387
|
|
|
3350
3388
|
status = PQresultStatus(cur);
|
|
3351
3389
|
PQclear(cur);
|
|
3352
3390
|
if (status == PGRES_COPY_IN){
|
|
3353
|
-
while(
|
|
3391
|
+
while( PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
|
|
3354
3392
|
pgconn_async_flush(self);
|
|
3355
3393
|
}
|
|
3356
3394
|
}
|
|
3357
3395
|
if (status == PGRES_COPY_OUT){
|
|
3358
3396
|
for(;;) {
|
|
3359
3397
|
char *buffer = NULL;
|
|
3360
|
-
int st =
|
|
3398
|
+
int st = PQgetCopyData(conn, &buffer, 1);
|
|
3361
3399
|
if( st == 0 ) {
|
|
3362
3400
|
/* would block -> wait for readable data */
|
|
3363
|
-
pg_rb_io_wait(socket_io, RB_INT2NUM(
|
|
3401
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
|
|
3364
3402
|
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3365
3403
|
} else if( st > 0 ) {
|
|
3366
3404
|
/* some data retrieved -> discard it */
|
|
@@ -3397,12 +3435,12 @@ error:
|
|
|
3397
3435
|
* and the PG::Result object will automatically be cleared when the block terminates.
|
|
3398
3436
|
* In this instance, <code>conn.exec</code> returns the value of the block.
|
|
3399
3437
|
*
|
|
3400
|
-
* #exec is an alias for #async_exec which is
|
|
3438
|
+
* #exec is an alias for #async_exec which is functional identical to #sync_exec .
|
|
3401
3439
|
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
|
3402
3440
|
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
|
3403
3441
|
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
|
3404
|
-
*
|
|
3405
|
-
*
|
|
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.
|
|
3406
3444
|
* This is most notably visible by a delayed reaction to Control+C.
|
|
3407
3445
|
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
|
3408
3446
|
*
|
|
@@ -3437,12 +3475,13 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
|
3437
3475
|
* +params+ is an array of the bind parameters for the SQL query.
|
|
3438
3476
|
* Each element of the +params+ array may be either:
|
|
3439
3477
|
* a hash of the form:
|
|
3440
|
-
* {:value
|
|
3441
|
-
* :type
|
|
3442
|
-
* :
|
|
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)
|
|
3443
3482
|
* }
|
|
3444
3483
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
|
3445
|
-
* { :value
|
|
3484
|
+
* { :value => <string value>, :type => 0, :format => 0 }
|
|
3446
3485
|
*
|
|
3447
3486
|
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
|
3448
3487
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
|
@@ -3631,7 +3670,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
|
|
3631
3670
|
return pgconn_async_describe_close_prepared_potral(self, stmt_name, pgconn_send_describe_prepared);
|
|
3632
3671
|
}
|
|
3633
3672
|
|
|
3634
|
-
#ifdef
|
|
3673
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
3635
3674
|
/*
|
|
3636
3675
|
* call-seq:
|
|
3637
3676
|
* conn.close_prepared( statement_name ) -> PG::Result
|
|
@@ -3753,7 +3792,7 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
|
3753
3792
|
|
|
3754
3793
|
|
|
3755
3794
|
|
|
3756
|
-
#ifdef
|
|
3795
|
+
#ifdef LIBPQ_HAS_PIPELINING
|
|
3757
3796
|
/*
|
|
3758
3797
|
* call-seq:
|
|
3759
3798
|
* conn.pipeline_status -> Integer
|
|
@@ -3838,7 +3877,7 @@ static VALUE
|
|
|
3838
3877
|
pgconn_sync_pipeline_sync(VALUE self)
|
|
3839
3878
|
{
|
|
3840
3879
|
PGconn *conn = pg_get_pgconn(self);
|
|
3841
|
-
int res =
|
|
3880
|
+
int res = PQpipelineSync(conn);
|
|
3842
3881
|
if( res != 1 )
|
|
3843
3882
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3844
3883
|
|
|
@@ -3846,7 +3885,7 @@ pgconn_sync_pipeline_sync(VALUE self)
|
|
|
3846
3885
|
}
|
|
3847
3886
|
|
|
3848
3887
|
|
|
3849
|
-
#ifdef
|
|
3888
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
3850
3889
|
/*
|
|
3851
3890
|
* call-seq:
|
|
3852
3891
|
* conn.send_pipeline_sync -> nil
|
|
@@ -3863,7 +3902,7 @@ static VALUE
|
|
|
3863
3902
|
pgconn_send_pipeline_sync(VALUE self)
|
|
3864
3903
|
{
|
|
3865
3904
|
PGconn *conn = pg_get_pgconn(self);
|
|
3866
|
-
int res =
|
|
3905
|
+
int res = PQsendPipelineSync(conn);
|
|
3867
3906
|
if( res != 1 )
|
|
3868
3907
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3869
3908
|
|
|
@@ -4304,7 +4343,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
|
4304
4343
|
rb_encoding *rbenc = rb_to_encoding( enc );
|
|
4305
4344
|
const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
|
|
4306
4345
|
|
|
4307
|
-
if (
|
|
4346
|
+
if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
|
|
4308
4347
|
VALUE server_encoding = pgconn_external_encoding( self );
|
|
4309
4348
|
rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
|
|
4310
4349
|
rb_enc_name(rb_to_encoding(server_encoding)), name );
|
|
@@ -4344,12 +4383,12 @@ pgconn_external_encoding(VALUE self)
|
|
|
4344
4383
|
static VALUE
|
|
4345
4384
|
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4346
4385
|
{
|
|
4347
|
-
VALUE
|
|
4386
|
+
VALUE query;
|
|
4348
4387
|
|
|
4349
4388
|
rb_check_frozen(self);
|
|
4350
4389
|
Check_Type(encname, T_STRING);
|
|
4351
|
-
|
|
4352
|
-
query
|
|
4390
|
+
query = rb_str_new_cstr("set client_encoding to ");
|
|
4391
|
+
rb_str_concat(query, pgconn_escape_literal(self, encname));
|
|
4353
4392
|
|
|
4354
4393
|
pgconn_async_exec(1, &query, self);
|
|
4355
4394
|
pgconn_set_internal_encoding_index( self );
|
|
@@ -4425,9 +4464,11 @@ pgconn_set_default_encoding( VALUE self )
|
|
|
4425
4464
|
* res.type_map_for_queries = typemap
|
|
4426
4465
|
*
|
|
4427
4466
|
* Set the default TypeMap that is used for type casts of query bind parameters.
|
|
4467
|
+
* It can be overwritten per +type_map+ parameter of #exec_params and siblings.
|
|
4428
4468
|
*
|
|
4429
4469
|
* +typemap+ must be a kind of PG::TypeMap .
|
|
4430
4470
|
*
|
|
4471
|
+
* See also #type_map_for_queries
|
|
4431
4472
|
*/
|
|
4432
4473
|
static VALUE
|
|
4433
4474
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
@@ -4452,6 +4493,9 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
|
4452
4493
|
* Returns the default TypeMap that is currently set for type casts of query
|
|
4453
4494
|
* bind parameters.
|
|
4454
4495
|
*
|
|
4496
|
+
* Default is PG::TypeMapAllStrings .
|
|
4497
|
+
*
|
|
4498
|
+
* See also #type_map_for_queries=
|
|
4455
4499
|
*/
|
|
4456
4500
|
static VALUE
|
|
4457
4501
|
pgconn_type_map_for_queries_get(VALUE self)
|
|
@@ -4466,9 +4510,11 @@ pgconn_type_map_for_queries_get(VALUE self)
|
|
|
4466
4510
|
* res.type_map_for_results = typemap
|
|
4467
4511
|
*
|
|
4468
4512
|
* Set the default TypeMap that is used for type casts of result values.
|
|
4513
|
+
* It can be overwritten per PG::Result#type_map= .
|
|
4469
4514
|
*
|
|
4470
4515
|
* +typemap+ must be a kind of PG::TypeMap .
|
|
4471
4516
|
*
|
|
4517
|
+
* See also #type_map_for_results
|
|
4472
4518
|
*/
|
|
4473
4519
|
static VALUE
|
|
4474
4520
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
@@ -4490,6 +4536,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
|
4490
4536
|
*
|
|
4491
4537
|
* Returns the default TypeMap that is currently set for type casts of result values.
|
|
4492
4538
|
*
|
|
4539
|
+
* Default is PG::TypeMapAllStrings .
|
|
4540
|
+
*
|
|
4541
|
+
* See also #type_map_for_results=
|
|
4493
4542
|
*/
|
|
4494
4543
|
static VALUE
|
|
4495
4544
|
pgconn_type_map_for_results_get(VALUE self)
|
|
@@ -4506,11 +4555,13 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
|
4506
4555
|
*
|
|
4507
4556
|
* Set the default coder that is used for type casting of parameters
|
|
4508
4557
|
* to #put_copy_data .
|
|
4558
|
+
* It can be overwritten per +encoder+ parameter of #put_copy_data and +coder+ parameter of #copy_data.
|
|
4509
4559
|
*
|
|
4510
4560
|
* +encoder+ can be:
|
|
4511
4561
|
* * a kind of PG::Coder
|
|
4512
4562
|
* * +nil+ - disable type encoding, data must be a String.
|
|
4513
4563
|
*
|
|
4564
|
+
* See also #encoder_for_put_copy_data
|
|
4514
4565
|
*/
|
|
4515
4566
|
static VALUE
|
|
4516
4567
|
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
@@ -4540,6 +4591,8 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
|
4540
4591
|
* * a kind of PG::Coder
|
|
4541
4592
|
* * +nil+ - type encoding is disabled, data must be a String.
|
|
4542
4593
|
*
|
|
4594
|
+
* Default is +nil+ .
|
|
4595
|
+
* See also #encoder_for_put_copy_data=
|
|
4543
4596
|
*/
|
|
4544
4597
|
static VALUE
|
|
4545
4598
|
pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
@@ -4555,11 +4608,13 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
|
4555
4608
|
*
|
|
4556
4609
|
* Set the default coder that is used for type casting of received data
|
|
4557
4610
|
* by #get_copy_data .
|
|
4611
|
+
* It can be overwritten per +decoder+ parameter of #get_copy_data and +coder+ parameter of #copy_data.
|
|
4558
4612
|
*
|
|
4559
4613
|
* +decoder+ can be:
|
|
4560
4614
|
* * a kind of PG::Coder
|
|
4561
4615
|
* * +nil+ - disable type decoding, returned data will be a String.
|
|
4562
4616
|
*
|
|
4617
|
+
* See also #decoder_for_get_copy_data
|
|
4563
4618
|
*/
|
|
4564
4619
|
static VALUE
|
|
4565
4620
|
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
@@ -4589,6 +4644,9 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
|
4589
4644
|
* * a kind of PG::Coder
|
|
4590
4645
|
* * +nil+ - type encoding is disabled, returned data will be a String.
|
|
4591
4646
|
*
|
|
4647
|
+
* Default is +nil+ .
|
|
4648
|
+
*
|
|
4649
|
+
* See also #decoder_for_get_copy_data=
|
|
4592
4650
|
*/
|
|
4593
4651
|
static VALUE
|
|
4594
4652
|
pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
@@ -4611,7 +4669,7 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
|
4611
4669
|
*
|
|
4612
4670
|
* Settings the type of field names affects only future results.
|
|
4613
4671
|
*
|
|
4614
|
-
* See further description at PG::Result#field_name_type=
|
|
4672
|
+
* See further description at PG::Result#field_name_type= and #field_name_type .
|
|
4615
4673
|
*
|
|
4616
4674
|
*/
|
|
4617
4675
|
static VALUE
|
|
@@ -4622,7 +4680,6 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
|
4622
4680
|
rb_check_frozen(self);
|
|
4623
4681
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
|
4624
4682
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
|
4625
|
-
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
|
4626
4683
|
else if ( sym == sym_string );
|
|
4627
4684
|
else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
|
|
4628
4685
|
|
|
@@ -4644,8 +4701,6 @@ pgconn_field_name_type_get(VALUE self)
|
|
|
4644
4701
|
|
|
4645
4702
|
if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
|
|
4646
4703
|
return sym_symbol;
|
|
4647
|
-
} else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
|
|
4648
|
-
return sym_static_symbol;
|
|
4649
4704
|
} else {
|
|
4650
4705
|
return sym_string;
|
|
4651
4706
|
}
|
|
@@ -4665,7 +4720,6 @@ init_pg_connection(void)
|
|
|
4665
4720
|
sym_value = ID2SYM(rb_intern("value"));
|
|
4666
4721
|
sym_string = ID2SYM(rb_intern("string"));
|
|
4667
4722
|
sym_symbol = ID2SYM(rb_intern("symbol"));
|
|
4668
|
-
sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
|
|
4669
4723
|
|
|
4670
4724
|
rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
|
|
4671
4725
|
/* Help rdoc to known the Constants module */
|
|
@@ -4713,12 +4767,15 @@ init_pg_connection(void)
|
|
|
4713
4767
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
|
4714
4768
|
rb_define_method(rb_cPGconn, "parameter_status", pgconn_parameter_status, 1);
|
|
4715
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
|
|
4716
4773
|
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
|
4717
4774
|
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
|
4718
4775
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
|
4719
4776
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
|
4720
4777
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
|
4721
|
-
#ifndef
|
|
4778
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
4722
4779
|
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
|
4723
4780
|
#endif
|
|
4724
4781
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
|
@@ -4732,7 +4789,7 @@ init_pg_connection(void)
|
|
|
4732
4789
|
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
|
4733
4790
|
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
|
4734
4791
|
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
|
4735
|
-
#ifdef
|
|
4792
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4736
4793
|
rb_define_method(rb_cPGconn, "sync_close_prepared", pgconn_sync_close_prepared, 1);
|
|
4737
4794
|
rb_define_method(rb_cPGconn, "sync_close_portal", pgconn_sync_close_portal, 1);
|
|
4738
4795
|
#endif
|
|
@@ -4743,7 +4800,7 @@ init_pg_connection(void)
|
|
|
4743
4800
|
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
|
|
4744
4801
|
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
|
|
4745
4802
|
rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
|
|
4746
|
-
#ifdef
|
|
4803
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4747
4804
|
rb_define_method(rb_cPGconn, "close_prepared", pgconn_async_close_prepared, 1);
|
|
4748
4805
|
rb_define_method(rb_cPGconn, "close_portal", pgconn_async_close_portal, 1);
|
|
4749
4806
|
#endif
|
|
@@ -4755,7 +4812,7 @@ init_pg_connection(void)
|
|
|
4755
4812
|
rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
|
|
4756
4813
|
rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
|
|
4757
4814
|
rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
|
|
4758
|
-
#ifdef
|
|
4815
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4759
4816
|
rb_define_alias(rb_cPGconn, "async_close_prepared", "close_prepared");
|
|
4760
4817
|
rb_define_alias(rb_cPGconn, "async_close_portal", "close_portal");
|
|
4761
4818
|
#endif
|
|
@@ -4768,7 +4825,7 @@ init_pg_connection(void)
|
|
|
4768
4825
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
|
4769
4826
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
|
4770
4827
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
|
4771
|
-
#ifdef
|
|
4828
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4772
4829
|
rb_define_method(rb_cPGconn, "set_chunked_rows_mode", pgconn_set_chunked_rows_mode, 1);
|
|
4773
4830
|
#endif
|
|
4774
4831
|
|
|
@@ -4790,7 +4847,7 @@ init_pg_connection(void)
|
|
|
4790
4847
|
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
|
4791
4848
|
|
|
4792
4849
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
|
4793
|
-
#ifndef
|
|
4850
|
+
#ifndef LIBPQ_HAS_CHUNK_MODE
|
|
4794
4851
|
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
|
4795
4852
|
#endif
|
|
4796
4853
|
|
|
@@ -4832,13 +4889,13 @@ init_pg_connection(void)
|
|
|
4832
4889
|
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
|
4833
4890
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
|
4834
4891
|
|
|
4835
|
-
#ifdef
|
|
4892
|
+
#ifdef LIBPQ_HAS_PIPELINING
|
|
4836
4893
|
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
|
4837
4894
|
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
|
4838
4895
|
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
|
4839
4896
|
rb_define_method(rb_cPGconn, "sync_pipeline_sync", pgconn_sync_pipeline_sync, 0);
|
|
4840
4897
|
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
|
4841
|
-
#ifdef
|
|
4898
|
+
#ifdef LIBPQ_HAS_CHUNK_MODE
|
|
4842
4899
|
rb_define_method(rb_cPGconn, "send_pipeline_sync", pgconn_send_pipeline_sync, 0);
|
|
4843
4900
|
#endif
|
|
4844
4901
|
#endif
|