pg 0.21.0 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +36 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +86 -0
- data/.github/workflows/source-gem.yml +130 -0
- data/.gitignore +13 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.rdoc +291 -4
- data/Manifest.txt +8 -4
- data/README-Windows.rdoc +4 -4
- data/README.ja.rdoc +1 -2
- data/README.rdoc +62 -16
- data/Rakefile +32 -142
- data/Rakefile.cross +69 -71
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/ext/errorcodes.def +84 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +23 -2
- data/ext/extconf.rb +109 -52
- data/ext/gvl_wrappers.c +8 -0
- data/ext/gvl_wrappers.h +40 -33
- data/ext/pg.c +211 -146
- data/ext/pg.h +85 -95
- data/ext/pg_binary_decoder.c +82 -15
- data/ext/pg_binary_encoder.c +13 -12
- data/ext/pg_coder.c +145 -30
- data/ext/pg_connection.c +1349 -929
- data/ext/pg_copy_coder.c +60 -23
- data/ext/pg_record_coder.c +519 -0
- data/ext/pg_result.c +613 -207
- data/ext/pg_text_decoder.c +606 -40
- data/ext/pg_text_encoder.c +190 -59
- data/ext/pg_tuple.c +575 -0
- data/ext/pg_type_map.c +42 -9
- data/ext/pg_type_map_all_strings.c +19 -5
- data/ext/pg_type_map_by_class.c +54 -24
- data/ext/pg_type_map_by_column.c +73 -34
- data/ext/pg_type_map_by_mri_type.c +48 -19
- data/ext/pg_type_map_by_oid.c +55 -25
- data/ext/pg_type_map_in_ruby.c +51 -20
- data/ext/{util.c → pg_util.c} +12 -12
- data/ext/{util.h → pg_util.h} +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +47 -0
- data/lib/pg/basic_type_map_for_queries.rb +193 -0
- data/lib/pg/basic_type_map_for_results.rb +81 -0
- data/lib/pg/basic_type_registry.rb +296 -0
- data/lib/pg/binary_decoder.rb +23 -0
- data/lib/pg/coder.rb +24 -3
- data/lib/pg/connection.rb +600 -46
- data/lib/pg/constants.rb +2 -1
- data/lib/pg/exceptions.rb +2 -1
- data/lib/pg/result.rb +14 -2
- data/lib/pg/text_decoder.rb +21 -26
- data/lib/pg/text_encoder.rb +32 -8
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +3 -2
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +51 -38
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +32 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +106 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data.tar.gz.sig +0 -0
- metadata +96 -229
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/lib/pg/basic_type_mapping.rb +0 -426
- data/lib/pg/deprecated_constants.rb +0 -21
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -352
- data/spec/pg/basic_type_mapping_spec.rb +0 -305
- data/spec/pg/connection_spec.rb +0 -1676
- data/spec/pg/result_spec.rb +0 -456
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -222
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -777
- data/spec/pg_spec.rb +0 -50
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
|
|
@@ -12,25 +12,18 @@
|
|
12
12
|
|
13
13
|
VALUE rb_cPGconn;
|
14
14
|
static ID s_id_encode;
|
15
|
+
static ID s_id_autoclose_set;
|
15
16
|
static VALUE sym_type, sym_format, sym_value;
|
17
|
+
static VALUE sym_symbol, sym_string, sym_static_symbol;
|
16
18
|
|
17
19
|
static PQnoticeReceiver default_notice_receiver = NULL;
|
18
20
|
static PQnoticeProcessor default_notice_processor = NULL;
|
19
21
|
|
20
22
|
static VALUE pgconn_finish( VALUE );
|
21
|
-
#ifdef M17N_SUPPORTED
|
22
23
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
#ifndef HAVE_RB_THREAD_FD_SELECT
|
27
|
-
#define rb_fdset_t fd_set
|
28
|
-
#define rb_fd_init(f)
|
29
|
-
#define rb_fd_zero(f) FD_ZERO(f)
|
30
|
-
#define rb_fd_set(n, f) FD_SET(n, f)
|
31
|
-
#define rb_fd_term(f)
|
32
|
-
#define rb_thread_fd_select rb_thread_select
|
33
|
-
#endif
|
24
|
+
static VALUE pgconn_wait_for_flush( VALUE self );
|
25
|
+
static void pgconn_set_internal_encoding_index( VALUE );
|
26
|
+
static const rb_data_type_t pg_connection_type;
|
34
27
|
|
35
28
|
/*
|
36
29
|
* Global functions
|
@@ -43,7 +36,7 @@ t_pg_connection *
|
|
43
36
|
pg_get_connection( VALUE self )
|
44
37
|
{
|
45
38
|
t_pg_connection *this;
|
46
|
-
|
39
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
47
40
|
|
48
41
|
return this;
|
49
42
|
}
|
@@ -56,7 +49,7 @@ static t_pg_connection *
|
|
56
49
|
pg_get_connection_safe( VALUE self )
|
57
50
|
{
|
58
51
|
t_pg_connection *this;
|
59
|
-
|
52
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
60
53
|
|
61
54
|
if ( !this->pgconn )
|
62
55
|
rb_raise( rb_eConnectionBad, "connection is closed" );
|
@@ -75,7 +68,7 @@ PGconn *
|
|
75
68
|
pg_get_pgconn( VALUE self )
|
76
69
|
{
|
77
70
|
t_pg_connection *this;
|
78
|
-
|
71
|
+
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
79
72
|
|
80
73
|
if ( !this->pgconn )
|
81
74
|
rb_raise( rb_eConnectionBad, "connection is closed" );
|
@@ -95,9 +88,8 @@ pgconn_close_socket_io( VALUE self )
|
|
95
88
|
VALUE socket_io = this->socket_io;
|
96
89
|
|
97
90
|
if ( RTEST(socket_io) ) {
|
98
|
-
#if defined(_WIN32)
|
99
|
-
|
100
|
-
if( rb_w32_unwrap_io_handle(ruby_sd) ){
|
91
|
+
#if defined(_WIN32)
|
92
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
101
93
|
rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
|
102
94
|
}
|
103
95
|
#endif
|
@@ -156,17 +148,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
|
|
156
148
|
* GC Mark function
|
157
149
|
*/
|
158
150
|
static void
|
159
|
-
pgconn_gc_mark(
|
151
|
+
pgconn_gc_mark( void *_this )
|
152
|
+
{
|
153
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
154
|
+
rb_gc_mark_movable( this->socket_io );
|
155
|
+
rb_gc_mark_movable( this->notice_receiver );
|
156
|
+
rb_gc_mark_movable( this->notice_processor );
|
157
|
+
rb_gc_mark_movable( this->type_map_for_queries );
|
158
|
+
rb_gc_mark_movable( this->type_map_for_results );
|
159
|
+
rb_gc_mark_movable( this->trace_stream );
|
160
|
+
rb_gc_mark_movable( this->encoder_for_put_copy_data );
|
161
|
+
rb_gc_mark_movable( this->decoder_for_get_copy_data );
|
162
|
+
}
|
163
|
+
|
164
|
+
static void
|
165
|
+
pgconn_gc_compact( void *_this )
|
160
166
|
{
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
167
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
168
|
+
pg_gc_location( this->socket_io );
|
169
|
+
pg_gc_location( this->notice_receiver );
|
170
|
+
pg_gc_location( this->notice_processor );
|
171
|
+
pg_gc_location( this->type_map_for_queries );
|
172
|
+
pg_gc_location( this->type_map_for_results );
|
173
|
+
pg_gc_location( this->trace_stream );
|
174
|
+
pg_gc_location( this->encoder_for_put_copy_data );
|
175
|
+
pg_gc_location( this->decoder_for_get_copy_data );
|
170
176
|
}
|
171
177
|
|
172
178
|
|
@@ -174,14 +180,45 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
174
180
|
* GC Free function
|
175
181
|
*/
|
176
182
|
static void
|
177
|
-
pgconn_gc_free(
|
183
|
+
pgconn_gc_free( void *_this )
|
178
184
|
{
|
185
|
+
t_pg_connection *this = (t_pg_connection *)_this;
|
186
|
+
#if defined(_WIN32)
|
187
|
+
if ( RTEST(this->socket_io) ) {
|
188
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
189
|
+
rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
|
190
|
+
}
|
191
|
+
}
|
192
|
+
#endif
|
179
193
|
if (this->pgconn != NULL)
|
180
194
|
PQfinish( this->pgconn );
|
181
195
|
|
182
196
|
xfree(this);
|
183
197
|
}
|
184
198
|
|
199
|
+
/*
|
200
|
+
* Object Size function
|
201
|
+
*/
|
202
|
+
static size_t
|
203
|
+
pgconn_memsize( const void *_this )
|
204
|
+
{
|
205
|
+
const t_pg_connection *this = (const t_pg_connection *)_this;
|
206
|
+
return sizeof(*this);
|
207
|
+
}
|
208
|
+
|
209
|
+
static const rb_data_type_t pg_connection_type = {
|
210
|
+
"PG::Connection",
|
211
|
+
{
|
212
|
+
pgconn_gc_mark,
|
213
|
+
pgconn_gc_free,
|
214
|
+
pgconn_memsize,
|
215
|
+
pg_compact_callback(pgconn_gc_compact),
|
216
|
+
},
|
217
|
+
0,
|
218
|
+
0,
|
219
|
+
0,
|
220
|
+
};
|
221
|
+
|
185
222
|
|
186
223
|
/**************************************************************************
|
187
224
|
* Class Methods
|
@@ -197,7 +234,7 @@ static VALUE
|
|
197
234
|
pgconn_s_allocate( VALUE klass )
|
198
235
|
{
|
199
236
|
t_pg_connection *this;
|
200
|
-
VALUE self =
|
237
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
|
201
238
|
|
202
239
|
this->pgconn = NULL;
|
203
240
|
this->socket_io = Qnil;
|
@@ -208,75 +245,17 @@ pgconn_s_allocate( VALUE klass )
|
|
208
245
|
this->encoder_for_put_copy_data = Qnil;
|
209
246
|
this->decoder_for_get_copy_data = Qnil;
|
210
247
|
this->trace_stream = Qnil;
|
211
|
-
this->external_encoding = Qnil;
|
212
248
|
|
213
249
|
return self;
|
214
250
|
}
|
215
251
|
|
216
|
-
|
217
|
-
/*
|
218
|
-
* Document-method: new
|
219
|
-
*
|
220
|
-
* call-seq:
|
221
|
-
* PG::Connection.new -> conn
|
222
|
-
* PG::Connection.new(connection_hash) -> conn
|
223
|
-
* PG::Connection.new(connection_string) -> conn
|
224
|
-
* PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
|
225
|
-
*
|
226
|
-
* Create a connection to the specified server.
|
227
|
-
*
|
228
|
-
* [+host+]
|
229
|
-
* server hostname
|
230
|
-
* [+hostaddr+]
|
231
|
-
* server address (avoids hostname lookup, overrides +host+)
|
232
|
-
* [+port+]
|
233
|
-
* server port number
|
234
|
-
* [+dbname+]
|
235
|
-
* connecting database name
|
236
|
-
* [+user+]
|
237
|
-
* login user name
|
238
|
-
* [+password+]
|
239
|
-
* login password
|
240
|
-
* [+connect_timeout+]
|
241
|
-
* maximum time to wait for connection to succeed
|
242
|
-
* [+options+]
|
243
|
-
* backend options
|
244
|
-
* [+tty+]
|
245
|
-
* (ignored in newer versions of PostgreSQL)
|
246
|
-
* [+sslmode+]
|
247
|
-
* (disable|allow|prefer|require)
|
248
|
-
* [+krbsrvname+]
|
249
|
-
* kerberos service name
|
250
|
-
* [+gsslib+]
|
251
|
-
* GSS library to use for GSSAPI authentication
|
252
|
-
* [+service+]
|
253
|
-
* service name to use for additional parameters
|
254
|
-
*
|
255
|
-
* Examples:
|
256
|
-
*
|
257
|
-
* # Connect using all defaults
|
258
|
-
* PG::Connection.new
|
259
|
-
*
|
260
|
-
* # As a Hash
|
261
|
-
* PG::Connection.new( :dbname => 'test', :port => 5432 )
|
262
|
-
*
|
263
|
-
* # As a String
|
264
|
-
* PG::Connection.new( "dbname=test port=5432" )
|
265
|
-
*
|
266
|
-
* # As an Array
|
267
|
-
* PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
|
268
|
-
*
|
269
|
-
* If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
|
270
|
-
* connection will have its +client_encoding+ set accordingly.
|
271
|
-
*
|
272
|
-
* Raises a PG::Error if the connection fails.
|
273
|
-
*/
|
274
252
|
static VALUE
|
275
|
-
|
253
|
+
pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
276
254
|
{
|
277
255
|
t_pg_connection *this;
|
278
256
|
VALUE conninfo;
|
279
257
|
VALUE error;
|
258
|
+
VALUE self = pgconn_s_allocate( klass );
|
280
259
|
|
281
260
|
this = pg_get_connection( self );
|
282
261
|
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
@@ -291,9 +270,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
291
270
|
rb_exc_raise(error);
|
292
271
|
}
|
293
272
|
|
294
|
-
#ifdef M17N_SUPPORTED
|
295
273
|
pgconn_set_default_encoding( self );
|
296
|
-
#endif
|
297
274
|
|
298
275
|
if (rb_block_given_p()) {
|
299
276
|
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
@@ -307,14 +284,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
307
284
|
* PG::Connection.connect_start(connection_string) -> conn
|
308
285
|
* PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
|
309
286
|
*
|
310
|
-
* This is an asynchronous version of PG::Connection.
|
287
|
+
* This is an asynchronous version of PG::Connection.new.
|
311
288
|
*
|
312
289
|
* Use #connect_poll to poll the status of the connection.
|
313
290
|
*
|
314
291
|
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
315
|
-
* Encoding.default_internal is set. To set it after the connection is established,
|
292
|
+
* +Encoding.default_internal+ is set. To set it after the connection is established,
|
316
293
|
* call #internal_encoding=. You can also set it automatically by setting
|
317
|
-
* ENV['PGCLIENTENCODING']
|
294
|
+
* <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
|
295
|
+
*
|
296
|
+
* See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
|
318
297
|
*
|
319
298
|
*/
|
320
299
|
static VALUE
|
@@ -349,37 +328,17 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
349
328
|
return rb_conn;
|
350
329
|
}
|
351
330
|
|
352
|
-
#ifdef HAVE_PQPING
|
353
|
-
/*
|
354
|
-
* call-seq:
|
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
|
358
|
-
*
|
359
|
-
* Check server status.
|
360
|
-
*
|
361
|
-
* Returns one of:
|
362
|
-
* [+PQPING_OK+]
|
363
|
-
* server is accepting connections
|
364
|
-
* [+PQPING_REJECT+]
|
365
|
-
* server is alive but rejecting connections
|
366
|
-
* [+PQPING_NO_RESPONSE+]
|
367
|
-
* could not establish connection
|
368
|
-
* [+PQPING_NO_ATTEMPT+]
|
369
|
-
* connection not attempted (bad params)
|
370
|
-
*/
|
371
331
|
static VALUE
|
372
|
-
|
332
|
+
pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
|
373
333
|
{
|
374
334
|
PGPing ping;
|
375
335
|
VALUE conninfo;
|
376
336
|
|
377
337
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
378
|
-
ping =
|
338
|
+
ping = gvl_PQping( StringValueCStr(conninfo) );
|
379
339
|
|
380
340
|
return INT2FIX((int)ping);
|
381
341
|
}
|
382
|
-
#endif
|
383
342
|
|
384
343
|
|
385
344
|
/*
|
@@ -418,16 +377,40 @@ pgconn_s_conndefaults(VALUE self)
|
|
418
377
|
}
|
419
378
|
|
420
379
|
|
380
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
381
|
+
static VALUE
|
382
|
+
pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
383
|
+
{
|
384
|
+
char *encrypted = NULL;
|
385
|
+
VALUE rval = Qnil;
|
386
|
+
VALUE password, username, algorithm;
|
387
|
+
PGconn *conn = pg_get_pgconn(self);
|
388
|
+
|
389
|
+
rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
|
390
|
+
|
391
|
+
Check_Type(password, T_STRING);
|
392
|
+
Check_Type(username, T_STRING);
|
393
|
+
|
394
|
+
encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
|
395
|
+
if ( encrypted ) {
|
396
|
+
rval = rb_str_new2( encrypted );
|
397
|
+
PQfreemem( encrypted );
|
398
|
+
} else {
|
399
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
400
|
+
}
|
401
|
+
|
402
|
+
return rval;
|
403
|
+
}
|
404
|
+
#endif
|
405
|
+
|
406
|
+
|
421
407
|
/*
|
422
408
|
* call-seq:
|
423
409
|
* PG::Connection.encrypt_password( password, username ) -> String
|
424
410
|
*
|
425
|
-
* This
|
426
|
-
*
|
427
|
-
* The arguments are the cleartext password, and the SQL name
|
428
|
-
* of the user it is for.
|
411
|
+
* This is an older, deprecated version of #encrypt_password.
|
412
|
+
* The difference is that this function always uses +md5+ as the encryption algorithm.
|
429
413
|
*
|
430
|
-
* Return value is the encrypted password.
|
431
414
|
*/
|
432
415
|
static VALUE
|
433
416
|
pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
@@ -444,9 +427,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
444
427
|
rval = rb_str_new2( encrypted );
|
445
428
|
PQfreemem( encrypted );
|
446
429
|
|
447
|
-
OBJ_INFECT( rval, password );
|
448
|
-
OBJ_INFECT( rval, username );
|
449
|
-
|
450
430
|
return rval;
|
451
431
|
}
|
452
432
|
|
@@ -494,6 +474,11 @@ pgconn_connect_poll(VALUE self)
|
|
494
474
|
{
|
495
475
|
PostgresPollingStatusType status;
|
496
476
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
477
|
+
|
478
|
+
if ( status == PGRES_POLLING_FAILED ) {
|
479
|
+
pgconn_close_socket_io(self);
|
480
|
+
}
|
481
|
+
|
497
482
|
return INT2FIX((int)status);
|
498
483
|
}
|
499
484
|
|
@@ -530,15 +515,8 @@ pgconn_finished_p( VALUE self )
|
|
530
515
|
}
|
531
516
|
|
532
517
|
|
533
|
-
/*
|
534
|
-
* call-seq:
|
535
|
-
* conn.reset()
|
536
|
-
*
|
537
|
-
* Resets the backend connection. This method closes the
|
538
|
-
* backend connection and tries to re-connect.
|
539
|
-
*/
|
540
518
|
static VALUE
|
541
|
-
|
519
|
+
pgconn_sync_reset( VALUE self )
|
542
520
|
{
|
543
521
|
pgconn_close_socket_io( self );
|
544
522
|
gvl_PQreset( pg_get_pgconn(self) );
|
@@ -577,6 +555,11 @@ pgconn_reset_poll(VALUE self)
|
|
577
555
|
{
|
578
556
|
PostgresPollingStatusType status;
|
579
557
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
558
|
+
|
559
|
+
if ( status == PGRES_POLLING_FAILED ) {
|
560
|
+
pgconn_close_socket_io(self);
|
561
|
+
}
|
562
|
+
|
580
563
|
return INT2FIX((int)status);
|
581
564
|
}
|
582
565
|
|
@@ -592,7 +575,7 @@ pgconn_db(VALUE self)
|
|
592
575
|
{
|
593
576
|
char *db = PQdb(pg_get_pgconn(self));
|
594
577
|
if (!db) return Qnil;
|
595
|
-
return
|
578
|
+
return rb_str_new2(db);
|
596
579
|
}
|
597
580
|
|
598
581
|
/*
|
@@ -606,21 +589,21 @@ pgconn_user(VALUE self)
|
|
606
589
|
{
|
607
590
|
char *user = PQuser(pg_get_pgconn(self));
|
608
591
|
if (!user) return Qnil;
|
609
|
-
return
|
592
|
+
return rb_str_new2(user);
|
610
593
|
}
|
611
594
|
|
612
595
|
/*
|
613
596
|
* call-seq:
|
614
597
|
* conn.pass()
|
615
598
|
*
|
616
|
-
* Returns the authenticated
|
599
|
+
* Returns the authenticated password.
|
617
600
|
*/
|
618
601
|
static VALUE
|
619
602
|
pgconn_pass(VALUE self)
|
620
603
|
{
|
621
604
|
char *user = PQpass(pg_get_pgconn(self));
|
622
605
|
if (!user) return Qnil;
|
623
|
-
return
|
606
|
+
return rb_str_new2(user);
|
624
607
|
}
|
625
608
|
|
626
609
|
/*
|
@@ -634,7 +617,7 @@ pgconn_host(VALUE self)
|
|
634
617
|
{
|
635
618
|
char *host = PQhost(pg_get_pgconn(self));
|
636
619
|
if (!host) return Qnil;
|
637
|
-
return
|
620
|
+
return rb_str_new2(host);
|
638
621
|
}
|
639
622
|
|
640
623
|
/*
|
@@ -647,21 +630,19 @@ static VALUE
|
|
647
630
|
pgconn_port(VALUE self)
|
648
631
|
{
|
649
632
|
char* port = PQport(pg_get_pgconn(self));
|
650
|
-
return INT2NUM(
|
633
|
+
return INT2NUM(atoi(port));
|
651
634
|
}
|
652
635
|
|
653
636
|
/*
|
654
637
|
* call-seq:
|
655
638
|
* conn.tty()
|
656
639
|
*
|
657
|
-
*
|
640
|
+
* Obsolete function.
|
658
641
|
*/
|
659
642
|
static VALUE
|
660
643
|
pgconn_tty(VALUE self)
|
661
644
|
{
|
662
|
-
|
663
|
-
if (!tty) return Qnil;
|
664
|
-
return rb_tainted_str_new2(tty);
|
645
|
+
return rb_str_new2("");
|
665
646
|
}
|
666
647
|
|
667
648
|
/*
|
@@ -675,17 +656,17 @@ pgconn_options(VALUE self)
|
|
675
656
|
{
|
676
657
|
char *options = PQoptions(pg_get_pgconn(self));
|
677
658
|
if (!options) return Qnil;
|
678
|
-
return
|
659
|
+
return rb_str_new2(options);
|
679
660
|
}
|
680
661
|
|
681
662
|
|
682
|
-
#ifdef HAVE_PQCONNINFO
|
683
663
|
/*
|
684
664
|
* call-seq:
|
685
665
|
* conn.conninfo -> hash
|
686
666
|
*
|
687
667
|
* Returns the connection options used by a live connection.
|
688
668
|
*
|
669
|
+
* Available since PostgreSQL-9.3
|
689
670
|
*/
|
690
671
|
static VALUE
|
691
672
|
pgconn_conninfo( VALUE self )
|
@@ -698,14 +679,17 @@ pgconn_conninfo( VALUE self )
|
|
698
679
|
|
699
680
|
return array;
|
700
681
|
}
|
701
|
-
#endif
|
702
682
|
|
703
683
|
|
704
684
|
/*
|
705
685
|
* call-seq:
|
706
686
|
* conn.status()
|
707
687
|
*
|
708
|
-
* Returns status of connection
|
688
|
+
* Returns the status of the connection, which is one:
|
689
|
+
* PG::Constants::CONNECTION_OK
|
690
|
+
* PG::Constants::CONNECTION_BAD
|
691
|
+
*
|
692
|
+
* ... and other constants of kind PG::Constants::CONNECTION_*
|
709
693
|
*/
|
710
694
|
static VALUE
|
711
695
|
pgconn_status(VALUE self)
|
@@ -755,7 +739,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
755
739
|
if(ret == NULL)
|
756
740
|
return Qnil;
|
757
741
|
else
|
758
|
-
return
|
742
|
+
return rb_str_new2(ret);
|
759
743
|
}
|
760
744
|
|
761
745
|
/*
|
@@ -793,20 +777,25 @@ pgconn_server_version(VALUE self)
|
|
793
777
|
* call-seq:
|
794
778
|
* conn.error_message -> String
|
795
779
|
*
|
796
|
-
* Returns the error message
|
780
|
+
* Returns the error message most recently generated by an operation on the connection.
|
781
|
+
*
|
782
|
+
* Nearly all libpq functions will set a message for conn.error_message if they fail.
|
783
|
+
* Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
|
797
784
|
*/
|
798
785
|
static VALUE
|
799
786
|
pgconn_error_message(VALUE self)
|
800
787
|
{
|
801
788
|
char *error = PQerrorMessage(pg_get_pgconn(self));
|
802
789
|
if (!error) return Qnil;
|
803
|
-
return
|
790
|
+
return rb_str_new2(error);
|
804
791
|
}
|
805
792
|
|
806
793
|
/*
|
807
794
|
* call-seq:
|
808
795
|
* conn.socket() -> Integer
|
809
796
|
*
|
797
|
+
* This method is deprecated. Please use the more portable method #socket_io .
|
798
|
+
*
|
810
799
|
* Returns the socket's file descriptor for this connection.
|
811
800
|
* <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
|
812
801
|
* If you do so, you will likely also want to set <tt>autoclose=false</tt>
|
@@ -815,42 +804,39 @@ pgconn_error_message(VALUE self)
|
|
815
804
|
* creates an IO that's associated with the connection object itself,
|
816
805
|
* and so won't go out of scope until the connection does.
|
817
806
|
*
|
818
|
-
* *Note:* On Windows the file descriptor is not
|
807
|
+
* *Note:* On Windows the file descriptor is not usable,
|
819
808
|
* since it can not be used to build a Ruby IO object.
|
820
809
|
*/
|
821
810
|
static VALUE
|
822
811
|
pgconn_socket(VALUE self)
|
823
812
|
{
|
824
813
|
int sd;
|
814
|
+
pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
|
815
|
+
|
825
816
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
826
817
|
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
827
818
|
return INT2NUM(sd);
|
828
819
|
}
|
829
820
|
|
830
|
-
|
831
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
832
|
-
|
833
821
|
/*
|
834
822
|
* call-seq:
|
835
823
|
* conn.socket_io() -> IO
|
836
824
|
*
|
837
|
-
* Fetch a
|
825
|
+
* Fetch a memorized IO object created from the Connection's underlying socket.
|
838
826
|
* This object can be used for IO.select to wait for events while running
|
839
827
|
* asynchronous API calls.
|
840
828
|
*
|
841
829
|
* Using this instead of #socket avoids the problem of the underlying connection
|
842
830
|
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
843
|
-
* goes out of scope.
|
844
|
-
*
|
845
|
-
* This method can also be used on Windows but requires Ruby-2.0+.
|
831
|
+
* goes out of scope. In contrast to #socket, it also works on Windows.
|
846
832
|
*/
|
847
833
|
static VALUE
|
848
834
|
pgconn_socket_io(VALUE self)
|
849
835
|
{
|
850
836
|
int sd;
|
851
837
|
int ruby_sd;
|
852
|
-
ID id_autoclose = rb_intern("autoclose=");
|
853
838
|
t_pg_connection *this = pg_get_connection_safe( self );
|
839
|
+
VALUE cSocket;
|
854
840
|
VALUE socket_io = this->socket_io;
|
855
841
|
|
856
842
|
if ( !RTEST(socket_io) ) {
|
@@ -859,16 +845,19 @@ pgconn_socket_io(VALUE self)
|
|
859
845
|
|
860
846
|
#ifdef _WIN32
|
861
847
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
848
|
+
if( ruby_sd == -1 ){
|
849
|
+
rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
|
850
|
+
}
|
851
|
+
this->ruby_sd = ruby_sd;
|
862
852
|
#else
|
863
853
|
ruby_sd = sd;
|
864
854
|
#endif
|
865
855
|
|
866
|
-
|
856
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
857
|
+
socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
|
867
858
|
|
868
|
-
/* Disable autoclose feature
|
869
|
-
|
870
|
-
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
871
|
-
}
|
859
|
+
/* Disable autoclose feature */
|
860
|
+
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
872
861
|
|
873
862
|
this->socket_io = socket_io;
|
874
863
|
}
|
@@ -876,8 +865,6 @@ pgconn_socket_io(VALUE self)
|
|
876
865
|
return socket_io;
|
877
866
|
}
|
878
867
|
|
879
|
-
#endif
|
880
|
-
|
881
868
|
/*
|
882
869
|
* call-seq:
|
883
870
|
* conn.backend_pid() -> Integer
|
@@ -892,6 +879,51 @@ pgconn_backend_pid(VALUE self)
|
|
892
879
|
return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
|
893
880
|
}
|
894
881
|
|
882
|
+
typedef struct
|
883
|
+
{
|
884
|
+
struct sockaddr_storage addr;
|
885
|
+
socklen_t salen;
|
886
|
+
} SockAddr;
|
887
|
+
|
888
|
+
/* Copy of struct pg_cancel from libpq-int.h
|
889
|
+
*
|
890
|
+
* See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
|
891
|
+
*/
|
892
|
+
struct pg_cancel
|
893
|
+
{
|
894
|
+
SockAddr raddr; /* Remote address */
|
895
|
+
int be_pid; /* PID of backend --- needed for cancels */
|
896
|
+
int be_key; /* key of backend --- needed for cancels */
|
897
|
+
};
|
898
|
+
|
899
|
+
/*
|
900
|
+
* call-seq:
|
901
|
+
* conn.backend_key() -> Integer
|
902
|
+
*
|
903
|
+
* Returns the key of the backend server process for this connection.
|
904
|
+
* This key can be used to cancel queries on the server.
|
905
|
+
*/
|
906
|
+
static VALUE
|
907
|
+
pgconn_backend_key(VALUE self)
|
908
|
+
{
|
909
|
+
int be_key;
|
910
|
+
struct pg_cancel *cancel;
|
911
|
+
PGconn *conn = pg_get_pgconn(self);
|
912
|
+
|
913
|
+
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
914
|
+
if(cancel == NULL)
|
915
|
+
rb_raise(rb_ePGerror,"Invalid connection!");
|
916
|
+
|
917
|
+
if( cancel->be_pid != PQbackendPID(conn) )
|
918
|
+
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
919
|
+
|
920
|
+
be_key = cancel->be_key;
|
921
|
+
|
922
|
+
PQfreeCancel(cancel);
|
923
|
+
|
924
|
+
return INT2NUM(be_key);
|
925
|
+
}
|
926
|
+
|
895
927
|
/*
|
896
928
|
* call-seq:
|
897
929
|
* conn.connection_needs_password() -> Boolean
|
@@ -922,44 +954,35 @@ pgconn_connection_used_password(VALUE self)
|
|
922
954
|
/* :TODO: get_ssl */
|
923
955
|
|
924
956
|
|
925
|
-
static VALUE
|
957
|
+
static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
|
926
958
|
|
927
959
|
/*
|
928
960
|
* call-seq:
|
929
|
-
* conn.
|
930
|
-
* conn.
|
931
|
-
*
|
932
|
-
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
933
|
-
* Returns a PG::Result instance on success.
|
934
|
-
* On failure, it raises a PG::Error.
|
961
|
+
* conn.sync_exec(sql) -> PG::Result
|
962
|
+
* conn.sync_exec(sql) {|pg_result| block }
|
935
963
|
*
|
936
|
-
*
|
937
|
-
*
|
938
|
-
* argument placeholders are used.
|
964
|
+
* This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
|
965
|
+
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
939
966
|
*
|
940
|
-
*
|
941
|
-
*
|
942
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
967
|
+
* Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
|
968
|
+
* However #async_exec has two advantages:
|
943
969
|
*
|
944
|
-
* #
|
945
|
-
*
|
946
|
-
*
|
947
|
-
* the query is finished. This is most notably visible by a delayed reaction to Control+C.
|
948
|
-
* Both methods ensure that other threads can process while waiting for the server to
|
949
|
-
* complete the request.
|
970
|
+
* 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
|
971
|
+
* 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
|
972
|
+
* So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
|
950
973
|
*/
|
951
974
|
static VALUE
|
952
|
-
|
975
|
+
pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
|
953
976
|
{
|
954
|
-
|
977
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
955
978
|
PGresult *result = NULL;
|
956
979
|
VALUE rb_pgresult;
|
957
980
|
|
958
|
-
/* If called with no parameters, use PQexec */
|
959
|
-
if ( argc == 1 ) {
|
981
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
982
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
960
983
|
VALUE query_str = argv[0];
|
961
984
|
|
962
|
-
result = gvl_PQexec(
|
985
|
+
result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
|
963
986
|
rb_pgresult = pg_new_result(result, self);
|
964
987
|
pg_result_check(rb_pgresult);
|
965
988
|
if (rb_block_given_p()) {
|
@@ -967,11 +990,10 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
967
990
|
}
|
968
991
|
return rb_pgresult;
|
969
992
|
}
|
993
|
+
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
970
994
|
|
971
995
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
972
|
-
|
973
|
-
return pgconn_exec_params( argc, argv, self );
|
974
|
-
}
|
996
|
+
return pgconn_sync_exec_params( argc, argv, self );
|
975
997
|
|
976
998
|
}
|
977
999
|
|
@@ -1003,7 +1025,7 @@ struct query_params_data {
|
|
1003
1025
|
* Filled by alloc_query_params()
|
1004
1026
|
*/
|
1005
1027
|
|
1006
|
-
/* Wraps the pointer of allocated memory, if function parameters
|
1028
|
+
/* Wraps the pointer of allocated memory, if function parameters don't
|
1007
1029
|
* fit in the memory_pool below.
|
1008
1030
|
*/
|
1009
1031
|
VALUE heap_pool;
|
@@ -1021,7 +1043,7 @@ struct query_params_data {
|
|
1021
1043
|
Oid *types;
|
1022
1044
|
|
1023
1045
|
/* This array takes the string values for the timeframe of the query,
|
1024
|
-
* if param value
|
1046
|
+
* if param value conversion is required
|
1025
1047
|
*/
|
1026
1048
|
VALUE gc_array;
|
1027
1049
|
|
@@ -1035,8 +1057,9 @@ struct query_params_data {
|
|
1035
1057
|
};
|
1036
1058
|
|
1037
1059
|
static void
|
1038
|
-
free_typecast_heap_chain(
|
1060
|
+
free_typecast_heap_chain(void *_chain_entry)
|
1039
1061
|
{
|
1062
|
+
struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
|
1040
1063
|
while(chain_entry){
|
1041
1064
|
struct linked_typecast_data *next = chain_entry->next;
|
1042
1065
|
xfree(chain_entry);
|
@@ -1044,6 +1067,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
|
|
1044
1067
|
}
|
1045
1068
|
}
|
1046
1069
|
|
1070
|
+
static const rb_data_type_t pg_typecast_buffer_type = {
|
1071
|
+
"PG::Connection typecast buffer chain",
|
1072
|
+
{
|
1073
|
+
(RUBY_DATA_FUNC) NULL,
|
1074
|
+
free_typecast_heap_chain,
|
1075
|
+
(size_t (*)(const void *))NULL,
|
1076
|
+
},
|
1077
|
+
0,
|
1078
|
+
0,
|
1079
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1080
|
+
};
|
1081
|
+
|
1047
1082
|
static char *
|
1048
1083
|
alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
1049
1084
|
{
|
@@ -1054,17 +1089,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
|
|
1054
1089
|
/* Did we already wrap a memory chain per T_DATA object? */
|
1055
1090
|
if( NIL_P( *typecast_heap_chain ) ){
|
1056
1091
|
/* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
|
1057
|
-
*typecast_heap_chain =
|
1092
|
+
*typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
|
1058
1093
|
allocated->next = NULL;
|
1059
1094
|
} else {
|
1060
1095
|
/* Append to the chain */
|
1061
|
-
allocated->next =
|
1062
|
-
|
1096
|
+
allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
|
1097
|
+
RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
|
1063
1098
|
}
|
1064
1099
|
|
1065
1100
|
return &allocated->data[0];
|
1066
1101
|
}
|
1067
1102
|
|
1103
|
+
static const rb_data_type_t pg_query_heap_pool_type = {
|
1104
|
+
"PG::Connection query heap pool",
|
1105
|
+
{
|
1106
|
+
(RUBY_DATA_FUNC) NULL,
|
1107
|
+
RUBY_TYPED_DEFAULT_FREE,
|
1108
|
+
(size_t (*)(const void *))NULL,
|
1109
|
+
},
|
1110
|
+
0,
|
1111
|
+
0,
|
1112
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1113
|
+
};
|
1068
1114
|
|
1069
1115
|
static int
|
1070
1116
|
alloc_query_params(struct query_params_data *paramsData)
|
@@ -1079,7 +1125,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1079
1125
|
|
1080
1126
|
Check_Type(paramsData->params, T_ARRAY);
|
1081
1127
|
|
1082
|
-
p_typemap =
|
1128
|
+
p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
|
1083
1129
|
p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
|
1084
1130
|
|
1085
1131
|
paramsData->heap_pool = Qnil;
|
@@ -1098,7 +1144,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1098
1144
|
/* Allocate one combined memory pool for all possible function parameters */
|
1099
1145
|
memory_pool = (char*)xmalloc( required_pool_size );
|
1100
1146
|
/* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
|
1101
|
-
paramsData->heap_pool =
|
1147
|
+
paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
|
1102
1148
|
required_pool_size = 0;
|
1103
1149
|
}else{
|
1104
1150
|
/* Use stack memory for function parameters */
|
@@ -1211,85 +1257,52 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1211
1257
|
/* Use default typemap for queries. It's type is checked when assigned. */
|
1212
1258
|
paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
|
1213
1259
|
}else{
|
1260
|
+
t_typemap *tm;
|
1261
|
+
UNUSED(tm);
|
1262
|
+
|
1214
1263
|
/* Check type of method param */
|
1215
|
-
|
1216
|
-
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
|
1217
|
-
rb_obj_classname( paramsData->typemap ) );
|
1218
|
-
}
|
1219
|
-
Check_Type( paramsData->typemap, T_DATA );
|
1264
|
+
TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
|
1220
1265
|
}
|
1221
1266
|
}
|
1222
1267
|
|
1223
1268
|
/*
|
1224
1269
|
* call-seq:
|
1225
|
-
* conn.
|
1226
|
-
* conn.
|
1227
|
-
*
|
1228
|
-
* Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
|
1229
|
-
* for parameters.
|
1230
|
-
*
|
1231
|
-
* Returns a PG::Result instance on success. On failure, it raises a PG::Error.
|
1270
|
+
* conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
|
1271
|
+
* conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
|
1232
1272
|
*
|
1233
|
-
*
|
1234
|
-
*
|
1235
|
-
*
|
1236
|
-
* {:value => String (value of bind parameter)
|
1237
|
-
* :type => Integer (oid of type of bind parameter)
|
1238
|
-
* :format => Integer (0 for text, 1 for binary)
|
1239
|
-
* }
|
1240
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1241
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
1242
|
-
*
|
1243
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1244
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1245
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1246
|
-
*
|
1247
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1248
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1249
|
-
* explicit casts in the query to ensure that the right type is used.
|
1250
|
-
*
|
1251
|
-
* For example: "SELECT $1::int"
|
1252
|
-
*
|
1253
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1254
|
-
* for binary.
|
1255
|
-
*
|
1256
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1257
|
-
* This will type cast the params form various Ruby types before transmission
|
1258
|
-
* based on the encoders defined by the type map. When a type encoder is used
|
1259
|
-
* the format and oid of a given bind parameter are retrieved from the encoder
|
1260
|
-
* instead out of the hash form described above.
|
1261
|
-
*
|
1262
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1263
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
1264
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
1273
|
+
* This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
|
1274
|
+
* See #async_exec for the differences between the two API variants.
|
1275
|
+
* It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
|
1265
1276
|
*/
|
1266
1277
|
static VALUE
|
1267
|
-
|
1278
|
+
pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
|
1268
1279
|
{
|
1269
|
-
|
1280
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1270
1281
|
PGresult *result = NULL;
|
1271
1282
|
VALUE rb_pgresult;
|
1272
1283
|
VALUE command, in_res_fmt;
|
1273
1284
|
int nParams;
|
1274
1285
|
int resultFormat;
|
1275
|
-
struct query_params_data paramsData = {
|
1286
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1276
1287
|
|
1288
|
+
/* For compatibility we accept 1 to 4 parameters */
|
1277
1289
|
rb_scan_args(argc, argv, "13", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1278
1290
|
paramsData.with_types = 1;
|
1279
1291
|
|
1280
1292
|
/*
|
1281
|
-
*
|
1282
|
-
*
|
1293
|
+
* For backward compatibility no or +nil+ for the second parameter
|
1294
|
+
* is passed to #exec
|
1283
1295
|
*/
|
1284
1296
|
if ( NIL_P(paramsData.params) ) {
|
1285
|
-
|
1297
|
+
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
1298
|
+
return pgconn_sync_exec( 1, argv, self );
|
1286
1299
|
}
|
1287
1300
|
pgconn_query_assign_typemap( self, ¶msData );
|
1288
1301
|
|
1289
1302
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1290
1303
|
nParams = alloc_query_params( ¶msData );
|
1291
1304
|
|
1292
|
-
result = gvl_PQexecParams(
|
1305
|
+
result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
|
1293
1306
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
1294
1307
|
|
1295
1308
|
free_query_params( ¶msData );
|
@@ -1306,28 +1319,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1306
1319
|
|
1307
1320
|
/*
|
1308
1321
|
* call-seq:
|
1309
|
-
* conn.
|
1322
|
+
* conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
|
1310
1323
|
*
|
1311
|
-
*
|
1312
|
-
*
|
1313
|
-
*
|
1314
|
-
*
|
1315
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1316
|
-
* types of the parameters.
|
1317
|
-
*
|
1318
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1319
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1320
|
-
* explicit casts in the query to ensure that the right type is used.
|
1321
|
-
*
|
1322
|
-
* For example: "SELECT $1::int"
|
1323
|
-
*
|
1324
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1325
|
-
* inside the SQL query.
|
1324
|
+
* This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
|
1325
|
+
* See #async_exec for the differences between the two API variants.
|
1326
|
+
* It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
|
1326
1327
|
*/
|
1327
1328
|
static VALUE
|
1328
|
-
|
1329
|
+
pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
|
1329
1330
|
{
|
1330
|
-
|
1331
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1331
1332
|
PGresult *result = NULL;
|
1332
1333
|
VALUE rb_pgresult;
|
1333
1334
|
VALUE name, command, in_paramtypes;
|
@@ -1337,7 +1338,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1337
1338
|
Oid *paramTypes = NULL;
|
1338
1339
|
const char *name_cstr;
|
1339
1340
|
const char *command_cstr;
|
1340
|
-
int enc_idx =
|
1341
|
+
int enc_idx = this->enc_idx;
|
1341
1342
|
|
1342
1343
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1343
1344
|
name_cstr = pg_cstr_enc(name, enc_idx);
|
@@ -1355,7 +1356,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1355
1356
|
paramTypes[i] = NUM2UINT(param);
|
1356
1357
|
}
|
1357
1358
|
}
|
1358
|
-
result = gvl_PQprepare(
|
1359
|
+
result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
1359
1360
|
|
1360
1361
|
xfree(paramTypes);
|
1361
1362
|
|
@@ -1366,49 +1367,23 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1366
1367
|
|
1367
1368
|
/*
|
1368
1369
|
* call-seq:
|
1369
|
-
* conn.
|
1370
|
-
* conn.
|
1371
|
-
*
|
1372
|
-
* Execute prepared named statement specified by _statement_name_.
|
1373
|
-
* Returns a PG::Result instance on success.
|
1374
|
-
* On failure, it raises a PG::Error.
|
1375
|
-
*
|
1376
|
-
* +params+ is an array of the optional bind parameters for the
|
1377
|
-
* SQL query. Each element of the +params+ array may be either:
|
1378
|
-
* a hash of the form:
|
1379
|
-
* {:value => String (value of bind parameter)
|
1380
|
-
* :format => Integer (0 for text, 1 for binary)
|
1381
|
-
* }
|
1382
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1383
|
-
* { :value => <string value>, :format => 0 }
|
1384
|
-
*
|
1385
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1386
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1387
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1388
|
-
*
|
1389
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1390
|
-
* for binary.
|
1391
|
-
*
|
1392
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1393
|
-
* This will type cast the params form various Ruby types before transmission
|
1394
|
-
* based on the encoders defined by the type map. When a type encoder is used
|
1395
|
-
* the format and oid of a given bind parameter are retrieved from the encoder
|
1396
|
-
* instead out of the hash form described above.
|
1370
|
+
* conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
|
1371
|
+
* conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
|
1397
1372
|
*
|
1398
|
-
*
|
1399
|
-
*
|
1400
|
-
*
|
1373
|
+
* This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
|
1374
|
+
* See #async_exec for the differences between the two API variants.
|
1375
|
+
* It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
|
1401
1376
|
*/
|
1402
1377
|
static VALUE
|
1403
|
-
|
1378
|
+
pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
|
1404
1379
|
{
|
1405
|
-
|
1380
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1406
1381
|
PGresult *result = NULL;
|
1407
1382
|
VALUE rb_pgresult;
|
1408
1383
|
VALUE name, in_res_fmt;
|
1409
1384
|
int nParams;
|
1410
1385
|
int resultFormat;
|
1411
|
-
struct query_params_data paramsData = {
|
1386
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1412
1387
|
|
1413
1388
|
rb_scan_args(argc, argv, "13", &name, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1414
1389
|
paramsData.with_types = 0;
|
@@ -1421,7 +1396,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1421
1396
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1422
1397
|
nParams = alloc_query_params( ¶msData );
|
1423
1398
|
|
1424
|
-
result = gvl_PQexecPrepared(
|
1399
|
+
result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
|
1425
1400
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
1426
1401
|
resultFormat);
|
1427
1402
|
|
@@ -1438,25 +1413,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1438
1413
|
|
1439
1414
|
/*
|
1440
1415
|
* call-seq:
|
1441
|
-
* conn.
|
1416
|
+
* conn.sync_describe_prepared( statement_name ) -> PG::Result
|
1442
1417
|
*
|
1443
|
-
*
|
1444
|
-
*
|
1418
|
+
* This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
|
1419
|
+
* See #async_exec for the differences between the two API variants.
|
1420
|
+
* It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
|
1445
1421
|
*/
|
1446
1422
|
static VALUE
|
1447
|
-
|
1423
|
+
pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
1448
1424
|
{
|
1449
1425
|
PGresult *result;
|
1450
1426
|
VALUE rb_pgresult;
|
1451
|
-
|
1427
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1452
1428
|
const char *stmt;
|
1453
1429
|
if(NIL_P(stmt_name)) {
|
1454
1430
|
stmt = NULL;
|
1455
1431
|
}
|
1456
1432
|
else {
|
1457
|
-
stmt = pg_cstr_enc(stmt_name,
|
1433
|
+
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1458
1434
|
}
|
1459
|
-
result = gvl_PQdescribePrepared(
|
1435
|
+
result = gvl_PQdescribePrepared(this->pgconn, stmt);
|
1460
1436
|
rb_pgresult = pg_new_result(result, self);
|
1461
1437
|
pg_result_check(rb_pgresult);
|
1462
1438
|
return rb_pgresult;
|
@@ -1465,25 +1441,27 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1465
1441
|
|
1466
1442
|
/*
|
1467
1443
|
* call-seq:
|
1468
|
-
* conn.
|
1444
|
+
* conn.sync_describe_portal( portal_name ) -> PG::Result
|
1469
1445
|
*
|
1470
|
-
*
|
1446
|
+
* This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
|
1447
|
+
* See #async_exec for the differences between the two API variants.
|
1448
|
+
* It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
|
1471
1449
|
*/
|
1472
1450
|
static VALUE
|
1473
|
-
|
1451
|
+
pgconn_sync_describe_portal(self, stmt_name)
|
1474
1452
|
VALUE self, stmt_name;
|
1475
1453
|
{
|
1476
1454
|
PGresult *result;
|
1477
1455
|
VALUE rb_pgresult;
|
1478
|
-
|
1456
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1479
1457
|
const char *stmt;
|
1480
1458
|
if(NIL_P(stmt_name)) {
|
1481
1459
|
stmt = NULL;
|
1482
1460
|
}
|
1483
1461
|
else {
|
1484
|
-
stmt = pg_cstr_enc(stmt_name,
|
1462
|
+
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1485
1463
|
}
|
1486
|
-
result = gvl_PQdescribePortal(
|
1464
|
+
result = gvl_PQdescribePortal(this->pgconn, stmt);
|
1487
1465
|
rb_pgresult = pg_new_result(result, self);
|
1488
1466
|
pg_result_check(rb_pgresult);
|
1489
1467
|
return rb_pgresult;
|
@@ -1505,6 +1483,9 @@ pgconn_describe_portal(self, stmt_name)
|
|
1505
1483
|
* * +PGRES_NONFATAL_ERROR+
|
1506
1484
|
* * +PGRES_FATAL_ERROR+
|
1507
1485
|
* * +PGRES_COPY_BOTH+
|
1486
|
+
* * +PGRES_SINGLE_TUPLE+
|
1487
|
+
* * +PGRES_PIPELINE_SYNC+
|
1488
|
+
* * +PGRES_PIPELINE_ABORTED+
|
1508
1489
|
*/
|
1509
1490
|
static VALUE
|
1510
1491
|
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
@@ -1530,13 +1511,15 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
1530
1511
|
* Consider using exec_params, which avoids the need for passing values
|
1531
1512
|
* inside of SQL commands.
|
1532
1513
|
*
|
1533
|
-
*
|
1514
|
+
* Character encoding of escaped string will be equal to client encoding of connection.
|
1534
1515
|
*
|
1535
1516
|
* NOTE: This class version of this method can only be used safely in client
|
1536
1517
|
* programs that use a single PostgreSQL connection at a time (in this case it can
|
1537
1518
|
* find out what it needs to know "behind the scenes"). It might give the wrong
|
1538
1519
|
* results if used in programs that use multiple database connections; use the
|
1539
1520
|
* same method on the connection object in such cases.
|
1521
|
+
*
|
1522
|
+
* See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
|
1540
1523
|
*/
|
1541
1524
|
static VALUE
|
1542
1525
|
pgconn_s_escape(VALUE self, VALUE string)
|
@@ -1547,8 +1530,8 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1547
1530
|
int enc_idx;
|
1548
1531
|
int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
|
1549
1532
|
|
1550
|
-
|
1551
|
-
enc_idx =
|
1533
|
+
StringValueCStr(string);
|
1534
|
+
enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
|
1552
1535
|
if( ENCODING_GET(string) != enc_idx ){
|
1553
1536
|
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1554
1537
|
}
|
@@ -1565,7 +1548,6 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1565
1548
|
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
1566
1549
|
}
|
1567
1550
|
rb_str_set_len(result, size);
|
1568
|
-
OBJ_INFECT(result, string);
|
1569
1551
|
|
1570
1552
|
return result;
|
1571
1553
|
}
|
@@ -1611,7 +1593,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
|
|
1611
1593
|
}
|
1612
1594
|
|
1613
1595
|
ret = rb_str_new((char*)to, to_len - 1);
|
1614
|
-
OBJ_INFECT(ret, str);
|
1615
1596
|
PQfreemem(to);
|
1616
1597
|
return ret;
|
1617
1598
|
}
|
@@ -1641,50 +1622,47 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
|
|
1641
1622
|
to = PQunescapeBytea(from, &to_len);
|
1642
1623
|
|
1643
1624
|
ret = rb_str_new((char*)to, to_len);
|
1644
|
-
OBJ_INFECT(ret, str);
|
1645
1625
|
PQfreemem(to);
|
1646
1626
|
return ret;
|
1647
1627
|
}
|
1648
1628
|
|
1649
|
-
#ifdef HAVE_PQESCAPELITERAL
|
1650
1629
|
/*
|
1651
1630
|
* call-seq:
|
1652
1631
|
* conn.escape_literal( str ) -> String
|
1653
1632
|
*
|
1654
1633
|
* Escape an arbitrary String +str+ as a literal.
|
1634
|
+
*
|
1635
|
+
* See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
|
1655
1636
|
*/
|
1656
1637
|
static VALUE
|
1657
1638
|
pgconn_escape_literal(VALUE self, VALUE string)
|
1658
1639
|
{
|
1659
|
-
|
1640
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1660
1641
|
char *escaped = NULL;
|
1661
1642
|
VALUE error;
|
1662
1643
|
VALUE result = Qnil;
|
1663
|
-
int enc_idx =
|
1644
|
+
int enc_idx = this->enc_idx;
|
1664
1645
|
|
1665
|
-
|
1646
|
+
StringValueCStr(string);
|
1666
1647
|
if( ENCODING_GET(string) != enc_idx ){
|
1667
1648
|
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1668
1649
|
}
|
1669
1650
|
|
1670
|
-
escaped = PQescapeLiteral(
|
1651
|
+
escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1671
1652
|
if (escaped == NULL)
|
1672
1653
|
{
|
1673
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(
|
1654
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
|
1674
1655
|
rb_iv_set(error, "@connection", self);
|
1675
1656
|
rb_exc_raise(error);
|
1676
1657
|
return Qnil;
|
1677
1658
|
}
|
1678
1659
|
result = rb_str_new2(escaped);
|
1679
1660
|
PQfreemem(escaped);
|
1680
|
-
OBJ_INFECT(result, string);
|
1681
1661
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1682
1662
|
|
1683
1663
|
return result;
|
1684
1664
|
}
|
1685
|
-
#endif
|
1686
1665
|
|
1687
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
1688
1666
|
/*
|
1689
1667
|
* call-seq:
|
1690
1668
|
* conn.escape_identifier( str ) -> String
|
@@ -1698,35 +1676,32 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1698
1676
|
static VALUE
|
1699
1677
|
pgconn_escape_identifier(VALUE self, VALUE string)
|
1700
1678
|
{
|
1701
|
-
|
1679
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1702
1680
|
char *escaped = NULL;
|
1703
1681
|
VALUE error;
|
1704
1682
|
VALUE result = Qnil;
|
1705
|
-
int enc_idx =
|
1683
|
+
int enc_idx = this->enc_idx;
|
1706
1684
|
|
1707
|
-
|
1685
|
+
StringValueCStr(string);
|
1708
1686
|
if( ENCODING_GET(string) != enc_idx ){
|
1709
1687
|
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1710
1688
|
}
|
1711
1689
|
|
1712
|
-
escaped = PQescapeIdentifier(
|
1690
|
+
escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1713
1691
|
if (escaped == NULL)
|
1714
1692
|
{
|
1715
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(
|
1693
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
|
1716
1694
|
rb_iv_set(error, "@connection", self);
|
1717
1695
|
rb_exc_raise(error);
|
1718
1696
|
return Qnil;
|
1719
1697
|
}
|
1720
1698
|
result = rb_str_new2(escaped);
|
1721
1699
|
PQfreemem(escaped);
|
1722
|
-
OBJ_INFECT(result, string);
|
1723
1700
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1724
1701
|
|
1725
1702
|
return result;
|
1726
1703
|
}
|
1727
|
-
#endif
|
1728
1704
|
|
1729
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1730
1705
|
/*
|
1731
1706
|
* call-seq:
|
1732
1707
|
* conn.set_single_row_mode -> self
|
@@ -1762,7 +1737,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1762
1737
|
* # do something with the received row
|
1763
1738
|
* end
|
1764
1739
|
* end
|
1765
|
-
*
|
1766
1740
|
*/
|
1767
1741
|
static VALUE
|
1768
1742
|
pgconn_set_single_row_mode(VALUE self)
|
@@ -1779,88 +1753,114 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1779
1753
|
|
1780
1754
|
return self;
|
1781
1755
|
}
|
1782
|
-
|
1756
|
+
|
1757
|
+
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
1783
1758
|
|
1784
1759
|
/*
|
1785
1760
|
* call-seq:
|
1786
|
-
* conn.send_query(sql
|
1761
|
+
* conn.send_query(sql) -> nil
|
1787
1762
|
*
|
1788
1763
|
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1789
1764
|
* asynchronous processing, and immediately returns.
|
1790
1765
|
* On failure, it raises a PG::Error.
|
1791
1766
|
*
|
1792
|
-
*
|
1793
|
-
*
|
1794
|
-
*
|
1795
|
-
* {:value => String (value of bind parameter)
|
1796
|
-
* :type => Integer (oid of type of bind parameter)
|
1797
|
-
* :format => Integer (0 for text, 1 for binary)
|
1798
|
-
* }
|
1799
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1800
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
1801
|
-
*
|
1802
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1803
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1804
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1805
|
-
*
|
1806
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1807
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1808
|
-
* explicit casts in the query to ensure that the right type is used.
|
1809
|
-
*
|
1810
|
-
* For example: "SELECT $1::int"
|
1811
|
-
*
|
1812
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1813
|
-
* for binary.
|
1814
|
-
*
|
1815
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1816
|
-
* This will type cast the params form various Ruby types before transmission
|
1817
|
-
* based on the encoders defined by the type map. When a type encoder is used
|
1818
|
-
* the format and oid of a given bind parameter are retrieved from the encoder
|
1819
|
-
* instead out of the hash form described above.
|
1767
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
1768
|
+
* it will call #send_query_params for you. New code should explicitly use #send_query_params if
|
1769
|
+
* argument placeholders are used.
|
1820
1770
|
*
|
1821
1771
|
*/
|
1822
1772
|
static VALUE
|
1823
1773
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1824
1774
|
{
|
1825
|
-
|
1826
|
-
int result;
|
1827
|
-
VALUE command, in_res_fmt;
|
1775
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1828
1776
|
VALUE error;
|
1829
|
-
int nParams;
|
1830
|
-
int resultFormat;
|
1831
|
-
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1832
1777
|
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
if(NIL_P(paramsData.params)) {
|
1838
|
-
if(gvl_PQsendQuery(conn, pg_cstr_enc(command, paramsData.enc_idx)) == 0) {
|
1839
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1778
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
1779
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1780
|
+
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
|
1781
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1840
1782
|
rb_iv_set(error, "@connection", self);
|
1841
1783
|
rb_exc_raise(error);
|
1842
1784
|
}
|
1785
|
+
pgconn_wait_for_flush( self );
|
1843
1786
|
return Qnil;
|
1844
1787
|
}
|
1845
1788
|
|
1789
|
+
pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
|
1790
|
+
|
1846
1791
|
/* If called with parameters, and optionally result_format,
|
1847
1792
|
* use PQsendQueryParams
|
1848
1793
|
*/
|
1794
|
+
return pgconn_send_query_params( argc, argv, self);
|
1795
|
+
}
|
1796
|
+
|
1797
|
+
/*
|
1798
|
+
* call-seq:
|
1799
|
+
* conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
|
1800
|
+
*
|
1801
|
+
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1802
|
+
* asynchronous processing, and immediately returns.
|
1803
|
+
* On failure, it raises a PG::Error.
|
1804
|
+
*
|
1805
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
1806
|
+
* Each element of the +params+ array may be either:
|
1807
|
+
* a hash of the form:
|
1808
|
+
* {:value => String (value of bind parameter)
|
1809
|
+
* :type => Integer (oid of type of bind parameter)
|
1810
|
+
* :format => Integer (0 for text, 1 for binary)
|
1811
|
+
* }
|
1812
|
+
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1813
|
+
* { :value => <string value>, :type => 0, :format => 0 }
|
1814
|
+
*
|
1815
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1816
|
+
* inside the SQL query. The 0th element of the +params+ array is bound
|
1817
|
+
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1818
|
+
*
|
1819
|
+
* If the types are not specified, they will be inferred by PostgreSQL.
|
1820
|
+
* Instead of specifying type oids, it's recommended to simply add
|
1821
|
+
* explicit casts in the query to ensure that the right type is used.
|
1822
|
+
*
|
1823
|
+
* For example: "SELECT $1::int"
|
1824
|
+
*
|
1825
|
+
* The optional +result_format+ should be 0 for text results, 1
|
1826
|
+
* for binary.
|
1827
|
+
*
|
1828
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1829
|
+
* This will type cast the params from various Ruby types before transmission
|
1830
|
+
* based on the encoders defined by the type map. When a type encoder is used
|
1831
|
+
* the format and oid of a given bind parameter are retrieved from the encoder
|
1832
|
+
* instead out of the hash form described above.
|
1833
|
+
*
|
1834
|
+
*/
|
1835
|
+
static VALUE
|
1836
|
+
pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
1837
|
+
{
|
1838
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1839
|
+
int result;
|
1840
|
+
VALUE command, in_res_fmt;
|
1841
|
+
VALUE error;
|
1842
|
+
int nParams;
|
1843
|
+
int resultFormat;
|
1844
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1845
|
+
|
1846
|
+
rb_scan_args(argc, argv, "22", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1847
|
+
paramsData.with_types = 1;
|
1849
1848
|
|
1850
1849
|
pgconn_query_assign_typemap( self, ¶msData );
|
1851
1850
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1852
1851
|
nParams = alloc_query_params( ¶msData );
|
1853
1852
|
|
1854
|
-
result = gvl_PQsendQueryParams(
|
1853
|
+
result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
|
1855
1854
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
1856
1855
|
|
1857
1856
|
free_query_params( ¶msData );
|
1858
1857
|
|
1859
1858
|
if(result == 0) {
|
1860
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1859
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1861
1860
|
rb_iv_set(error, "@connection", self);
|
1862
1861
|
rb_exc_raise(error);
|
1863
1862
|
}
|
1863
|
+
pgconn_wait_for_flush( self );
|
1864
1864
|
return Qnil;
|
1865
1865
|
}
|
1866
1866
|
|
@@ -1881,13 +1881,13 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1881
1881
|
*
|
1882
1882
|
* For example: "SELECT $1::int"
|
1883
1883
|
*
|
1884
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1884
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1885
1885
|
* inside the SQL query.
|
1886
1886
|
*/
|
1887
1887
|
static VALUE
|
1888
1888
|
pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
1889
1889
|
{
|
1890
|
-
|
1890
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1891
1891
|
int result;
|
1892
1892
|
VALUE name, command, in_paramtypes;
|
1893
1893
|
VALUE param;
|
@@ -1897,7 +1897,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1897
1897
|
Oid *paramTypes = NULL;
|
1898
1898
|
const char *name_cstr;
|
1899
1899
|
const char *command_cstr;
|
1900
|
-
int enc_idx =
|
1900
|
+
int enc_idx = this->enc_idx;
|
1901
1901
|
|
1902
1902
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1903
1903
|
name_cstr = pg_cstr_enc(name, enc_idx);
|
@@ -1915,15 +1915,16 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1915
1915
|
paramTypes[i] = NUM2UINT(param);
|
1916
1916
|
}
|
1917
1917
|
}
|
1918
|
-
result = gvl_PQsendPrepare(
|
1918
|
+
result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
1919
1919
|
|
1920
1920
|
xfree(paramTypes);
|
1921
1921
|
|
1922
1922
|
if(result == 0) {
|
1923
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1923
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1924
1924
|
rb_iv_set(error, "@connection", self);
|
1925
1925
|
rb_exc_raise(error);
|
1926
1926
|
}
|
1927
|
+
pgconn_wait_for_flush( self );
|
1927
1928
|
return Qnil;
|
1928
1929
|
}
|
1929
1930
|
|
@@ -1945,15 +1946,15 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1945
1946
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1946
1947
|
* { :value => <string value>, :format => 0 }
|
1947
1948
|
*
|
1948
|
-
* PostgreSQL bind parameters are represented as $1, $
|
1949
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
1949
1950
|
* inside the SQL query. The 0th element of the +params+ array is bound
|
1950
1951
|
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1951
1952
|
*
|
1952
1953
|
* The optional +result_format+ should be 0 for text results, 1
|
1953
1954
|
* for binary.
|
1954
1955
|
*
|
1955
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1956
|
-
* This will type cast the params
|
1956
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1957
|
+
* This will type cast the params from various Ruby types before transmission
|
1957
1958
|
* based on the encoders defined by the type map. When a type encoder is used
|
1958
1959
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1959
1960
|
* instead out of the hash form described above.
|
@@ -1962,37 +1963,37 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1962
1963
|
static VALUE
|
1963
1964
|
pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
1964
1965
|
{
|
1965
|
-
|
1966
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1966
1967
|
int result;
|
1967
1968
|
VALUE name, in_res_fmt;
|
1968
1969
|
VALUE error;
|
1969
1970
|
int nParams;
|
1970
1971
|
int resultFormat;
|
1971
|
-
struct query_params_data paramsData = {
|
1972
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1972
1973
|
|
1973
1974
|
rb_scan_args(argc, argv, "13", &name, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1974
1975
|
paramsData.with_types = 0;
|
1975
1976
|
|
1976
1977
|
if(NIL_P(paramsData.params)) {
|
1977
1978
|
paramsData.params = rb_ary_new2(0);
|
1978
|
-
resultFormat = 0;
|
1979
1979
|
}
|
1980
1980
|
pgconn_query_assign_typemap( self, ¶msData );
|
1981
1981
|
|
1982
1982
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1983
1983
|
nParams = alloc_query_params( ¶msData );
|
1984
1984
|
|
1985
|
-
result = gvl_PQsendQueryPrepared(
|
1985
|
+
result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
|
1986
1986
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
1987
1987
|
resultFormat);
|
1988
1988
|
|
1989
1989
|
free_query_params( ¶msData );
|
1990
1990
|
|
1991
1991
|
if(result == 0) {
|
1992
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1992
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1993
1993
|
rb_iv_set(error, "@connection", self);
|
1994
1994
|
rb_exc_raise(error);
|
1995
1995
|
}
|
1996
|
+
pgconn_wait_for_flush( self );
|
1996
1997
|
return Qnil;
|
1997
1998
|
}
|
1998
1999
|
|
@@ -2007,13 +2008,14 @@ static VALUE
|
|
2007
2008
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
2008
2009
|
{
|
2009
2010
|
VALUE error;
|
2010
|
-
|
2011
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2011
2012
|
/* returns 0 on failure */
|
2012
|
-
if(gvl_PQsendDescribePrepared(
|
2013
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
2013
|
+
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
|
2014
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
2014
2015
|
rb_iv_set(error, "@connection", self);
|
2015
2016
|
rb_exc_raise(error);
|
2016
2017
|
}
|
2018
|
+
pgconn_wait_for_flush( self );
|
2017
2019
|
return Qnil;
|
2018
2020
|
}
|
2019
2021
|
|
@@ -2029,35 +2031,20 @@ static VALUE
|
|
2029
2031
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
2030
2032
|
{
|
2031
2033
|
VALUE error;
|
2032
|
-
|
2034
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2033
2035
|
/* returns 0 on failure */
|
2034
|
-
if(gvl_PQsendDescribePortal(
|
2035
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
2036
|
+
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
|
2037
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
2036
2038
|
rb_iv_set(error, "@connection", self);
|
2037
2039
|
rb_exc_raise(error);
|
2038
2040
|
}
|
2041
|
+
pgconn_wait_for_flush( self );
|
2039
2042
|
return Qnil;
|
2040
2043
|
}
|
2041
2044
|
|
2042
2045
|
|
2043
|
-
/*
|
2044
|
-
* call-seq:
|
2045
|
-
* conn.get_result() -> PG::Result
|
2046
|
-
* conn.get_result() {|pg_result| block }
|
2047
|
-
*
|
2048
|
-
* Blocks waiting for the next result from a call to
|
2049
|
-
* #send_query (or another asynchronous command), and returns
|
2050
|
-
* it. Returns +nil+ if no more results are available.
|
2051
|
-
*
|
2052
|
-
* Note: call this function repeatedly until it returns +nil+, or else
|
2053
|
-
* you will not be able to issue further commands.
|
2054
|
-
*
|
2055
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
2056
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
2057
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
2058
|
-
*/
|
2059
2046
|
static VALUE
|
2060
|
-
|
2047
|
+
pgconn_sync_get_result(VALUE self)
|
2061
2048
|
{
|
2062
2049
|
PGconn *conn = pg_get_pgconn(self);
|
2063
2050
|
PGresult *result;
|
@@ -2090,6 +2077,7 @@ pgconn_consume_input(self)
|
|
2090
2077
|
PGconn *conn = pg_get_pgconn(self);
|
2091
2078
|
/* returns 0 on error */
|
2092
2079
|
if(PQconsumeInput(conn) == 0) {
|
2080
|
+
pgconn_close_socket_io(self);
|
2093
2081
|
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
2094
2082
|
rb_iv_set(error, "@connection", self);
|
2095
2083
|
rb_exc_raise(error);
|
@@ -2102,7 +2090,7 @@ pgconn_consume_input(self)
|
|
2102
2090
|
* conn.is_busy() -> Boolean
|
2103
2091
|
*
|
2104
2092
|
* Returns +true+ if a command is busy, that is, if
|
2105
|
-
*
|
2093
|
+
* #get_result would block. Otherwise returns +false+.
|
2106
2094
|
*/
|
2107
2095
|
static VALUE
|
2108
2096
|
pgconn_is_busy(self)
|
@@ -2111,24 +2099,8 @@ pgconn_is_busy(self)
|
|
2111
2099
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2112
2100
|
}
|
2113
2101
|
|
2114
|
-
/*
|
2115
|
-
* call-seq:
|
2116
|
-
* conn.setnonblocking(Boolean) -> nil
|
2117
|
-
*
|
2118
|
-
* Sets the nonblocking status of the connection.
|
2119
|
-
* In the blocking state, calls to #send_query
|
2120
|
-
* will block until the message is sent to the server,
|
2121
|
-
* but will not wait for the query results.
|
2122
|
-
* In the nonblocking state, calls to #send_query
|
2123
|
-
* will return an error if the socket is not ready for
|
2124
|
-
* writing.
|
2125
|
-
* Note: This function does not affect #exec, because
|
2126
|
-
* that function doesn't return until the server has
|
2127
|
-
* processed the query and returned the results.
|
2128
|
-
* Returns +nil+.
|
2129
|
-
*/
|
2130
2102
|
static VALUE
|
2131
|
-
|
2103
|
+
pgconn_sync_setnonblocking(self, state)
|
2132
2104
|
VALUE self, state;
|
2133
2105
|
{
|
2134
2106
|
int arg;
|
@@ -2150,33 +2122,15 @@ pgconn_setnonblocking(self, state)
|
|
2150
2122
|
}
|
2151
2123
|
|
2152
2124
|
|
2153
|
-
/*
|
2154
|
-
* call-seq:
|
2155
|
-
* conn.isnonblocking() -> Boolean
|
2156
|
-
*
|
2157
|
-
* Returns +true+ if a command is busy, that is, if
|
2158
|
-
* PQgetResult would block. Otherwise returns +false+.
|
2159
|
-
*/
|
2160
2125
|
static VALUE
|
2161
|
-
|
2126
|
+
pgconn_sync_isnonblocking(self)
|
2162
2127
|
VALUE self;
|
2163
2128
|
{
|
2164
2129
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2165
2130
|
}
|
2166
2131
|
|
2167
|
-
/*
|
2168
|
-
* call-seq:
|
2169
|
-
* conn.flush() -> Boolean
|
2170
|
-
*
|
2171
|
-
* Attempts to flush any queued output data to the server.
|
2172
|
-
* Returns +true+ if data is successfully flushed, +false+
|
2173
|
-
* if not (can only return +false+ if connection is
|
2174
|
-
* nonblocking.
|
2175
|
-
* Raises PG::Error if some other failure occurred.
|
2176
|
-
*/
|
2177
2132
|
static VALUE
|
2178
|
-
|
2179
|
-
VALUE self;
|
2133
|
+
pgconn_sync_flush(VALUE self)
|
2180
2134
|
{
|
2181
2135
|
PGconn *conn = pg_get_pgconn(self);
|
2182
2136
|
int ret;
|
@@ -2190,20 +2144,9 @@ pgconn_flush(self)
|
|
2190
2144
|
return (ret) ? Qfalse : Qtrue;
|
2191
2145
|
}
|
2192
2146
|
|
2193
|
-
/*
|
2194
|
-
* call-seq:
|
2195
|
-
* conn.cancel() -> String
|
2196
|
-
*
|
2197
|
-
* Requests cancellation of the command currently being
|
2198
|
-
* processed. (Only implemented in PostgreSQL >= 8.0)
|
2199
|
-
*
|
2200
|
-
* Returns +nil+ on success, or a string containing the
|
2201
|
-
* error message if a failure occurs.
|
2202
|
-
*/
|
2203
2147
|
static VALUE
|
2204
|
-
|
2148
|
+
pgconn_sync_cancel(VALUE self)
|
2205
2149
|
{
|
2206
|
-
#ifdef HAVE_PQGETCANCEL
|
2207
2150
|
char errbuf[256];
|
2208
2151
|
PGcancel *cancel;
|
2209
2152
|
VALUE retval;
|
@@ -2213,7 +2156,7 @@ pgconn_cancel(VALUE self)
|
|
2213
2156
|
if(cancel == NULL)
|
2214
2157
|
rb_raise(rb_ePGerror,"Invalid connection!");
|
2215
2158
|
|
2216
|
-
ret = gvl_PQcancel(cancel, errbuf,
|
2159
|
+
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
2217
2160
|
if(ret == 1)
|
2218
2161
|
retval = Qnil;
|
2219
2162
|
else
|
@@ -2221,9 +2164,6 @@ pgconn_cancel(VALUE self)
|
|
2221
2164
|
|
2222
2165
|
PQfreeCancel(cancel);
|
2223
2166
|
return retval;
|
2224
|
-
#else
|
2225
|
-
rb_notimplement();
|
2226
|
-
#endif
|
2227
2167
|
}
|
2228
2168
|
|
2229
2169
|
|
@@ -2237,7 +2177,7 @@ pgconn_cancel(VALUE self)
|
|
2237
2177
|
static VALUE
|
2238
2178
|
pgconn_notifies(VALUE self)
|
2239
2179
|
{
|
2240
|
-
|
2180
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2241
2181
|
PGnotify *notification;
|
2242
2182
|
VALUE hash;
|
2243
2183
|
VALUE sym_relname, sym_be_pid, sym_extra;
|
@@ -2247,17 +2187,17 @@ pgconn_notifies(VALUE self)
|
|
2247
2187
|
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
2248
2188
|
sym_extra = ID2SYM(rb_intern("extra"));
|
2249
2189
|
|
2250
|
-
notification = gvl_PQnotifies(
|
2190
|
+
notification = gvl_PQnotifies(this->pgconn);
|
2251
2191
|
if (notification == NULL) {
|
2252
2192
|
return Qnil;
|
2253
2193
|
}
|
2254
2194
|
|
2255
2195
|
hash = rb_hash_new();
|
2256
|
-
relname =
|
2196
|
+
relname = rb_str_new2(notification->relname);
|
2257
2197
|
be_pid = INT2NUM(notification->be_pid);
|
2258
|
-
extra =
|
2259
|
-
PG_ENCODING_SET_NOCHECK( relname,
|
2260
|
-
PG_ENCODING_SET_NOCHECK( extra,
|
2198
|
+
extra = rb_str_new2(notification->extra);
|
2199
|
+
PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
|
2200
|
+
PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
|
2261
2201
|
|
2262
2202
|
rb_hash_aset(hash, sym_relname, relname);
|
2263
2203
|
rb_hash_aset(hash, sym_be_pid, be_pid);
|
@@ -2267,96 +2207,63 @@ pgconn_notifies(VALUE self)
|
|
2267
2207
|
return hash;
|
2268
2208
|
}
|
2269
2209
|
|
2270
|
-
|
2271
|
-
#if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
|
2210
|
+
#if defined(_WIN32)
|
2272
2211
|
|
2273
|
-
/*
|
2274
|
-
*
|
2212
|
+
/* We use a specialized implementation of rb_io_wait() on Windows.
|
2213
|
+
* This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
|
2275
2214
|
*/
|
2276
|
-
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2277
|
-
{
|
2278
|
-
int i;
|
2279
|
-
crt_set->fd_count = os_set->fd_count;
|
2280
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2281
|
-
WSAPROTOCOL_INFO wsa_pi;
|
2282
|
-
/* dupicate the SOCKET */
|
2283
|
-
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2284
|
-
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2285
|
-
/* create the CRT fd so ruby can get back to the SOCKET */
|
2286
|
-
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2287
|
-
os_set->fd_array[i] = s;
|
2288
|
-
crt_set->fd_array[i] = fd;
|
2289
|
-
}
|
2290
|
-
}
|
2291
2215
|
|
2292
|
-
|
2293
|
-
|
2294
|
-
*/
|
2295
|
-
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2296
|
-
{
|
2297
|
-
int i;
|
2298
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2299
|
-
/* cleanup the CRT fd */
|
2300
|
-
_close(crt_set->fd_array[i]);
|
2301
|
-
/* cleanup the duplicated SOCKET */
|
2302
|
-
closesocket(os_set->fd_array[i]);
|
2303
|
-
}
|
2304
|
-
}
|
2216
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2217
|
+
#include <ruby/fiber/scheduler.h>
|
2305
2218
|
#endif
|
2306
2219
|
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
*/
|
2220
|
+
typedef enum {
|
2221
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
2222
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
2223
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
2224
|
+
} pg_rb_io_event_t;
|
2313
2225
|
|
2314
2226
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2315
2227
|
|
2316
|
-
|
2317
|
-
|
2318
|
-
*
|
2228
|
+
static VALUE
|
2229
|
+
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2230
|
+
rb_io_t *fptr;
|
2231
|
+
struct timeval ptimeout;
|
2319
2232
|
|
2320
|
-
static void *
|
2321
|
-
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
|
2322
|
-
{
|
2323
|
-
int sd = PQsocket( conn );
|
2324
|
-
void *retval;
|
2325
2233
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2326
2234
|
DWORD timeout_milisec = INFINITE;
|
2327
|
-
|
2328
|
-
WSAEVENT hEvent;
|
2329
|
-
|
2330
|
-
if ( sd < 0 )
|
2331
|
-
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
2235
|
+
HANDLE hEvent = WSACreateEvent();
|
2332
2236
|
|
2333
|
-
|
2237
|
+
long rb_events = NUM2UINT(events);
|
2238
|
+
long w32_events = 0;
|
2239
|
+
DWORD wait_ret;
|
2334
2240
|
|
2335
|
-
|
2336
|
-
if(
|
2337
|
-
|
2338
|
-
|
2339
|
-
}
|
2241
|
+
GetOpenFile((io), fptr);
|
2242
|
+
if( !NIL_P(timeout) ){
|
2243
|
+
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
2244
|
+
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
2340
2245
|
|
2341
|
-
if ( ptimeout ) {
|
2342
2246
|
gettimeofday(&currtime, NULL);
|
2343
|
-
timeradd(&currtime, ptimeout, &aborttime);
|
2247
|
+
timeradd(&currtime, &ptimeout, &aborttime);
|
2344
2248
|
}
|
2345
2249
|
|
2346
|
-
|
2347
|
-
|
2250
|
+
if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
|
2251
|
+
if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
|
2252
|
+
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
2253
|
+
|
2254
|
+
for(;;) {
|
2255
|
+
if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
|
2348
2256
|
WSACloseEvent( hEvent );
|
2349
2257
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2350
2258
|
}
|
2351
2259
|
|
2352
|
-
if (
|
2260
|
+
if ( !NIL_P(timeout) ) {
|
2353
2261
|
gettimeofday(&currtime, NULL);
|
2354
2262
|
timersub(&aborttime, &currtime, &waittime);
|
2355
2263
|
timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
|
2356
2264
|
}
|
2357
2265
|
|
2358
|
-
|
2359
|
-
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2266
|
+
if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2360
2267
|
/* Wait for the socket to become readable before checking again */
|
2361
2268
|
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
2362
2269
|
} else {
|
@@ -2365,9 +2272,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2365
2272
|
|
2366
2273
|
if ( wait_ret == WAIT_TIMEOUT ) {
|
2367
2274
|
WSACloseEvent( hEvent );
|
2368
|
-
return
|
2275
|
+
return UINT2NUM(0);
|
2369
2276
|
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2277
|
+
WSACloseEvent( hEvent );
|
2370
2278
|
/* The event we were waiting for. */
|
2279
|
+
return UINT2NUM(rb_events);
|
2371
2280
|
} else if ( wait_ret == WAIT_OBJECT_0 + 1) {
|
2372
2281
|
/* This indicates interruption from timer thread, GC, exception
|
2373
2282
|
* from other threads etc... */
|
@@ -2379,42 +2288,75 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2379
2288
|
WSACloseEvent( hEvent );
|
2380
2289
|
rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2381
2290
|
}
|
2382
|
-
|
2383
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2384
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
2385
|
-
WSACloseEvent( hEvent );
|
2386
|
-
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2387
|
-
}
|
2388
2291
|
}
|
2292
|
+
}
|
2389
2293
|
|
2390
|
-
|
2391
|
-
|
2294
|
+
static VALUE
|
2295
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2296
|
+
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2297
|
+
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
2298
|
+
* Fortunatelly ruby-3.1 offers a C-API for it.
|
2299
|
+
*/
|
2300
|
+
VALUE scheduler = rb_fiber_scheduler_current();
|
2301
|
+
|
2302
|
+
if (!NIL_P(scheduler)) {
|
2303
|
+
return rb_io_wait(io, events, timeout);
|
2304
|
+
}
|
2305
|
+
#endif
|
2306
|
+
return pg_rb_thread_io_wait(io, events, timeout);
|
2392
2307
|
}
|
2393
2308
|
|
2309
|
+
#elif defined(HAVE_RB_IO_WAIT)
|
2310
|
+
|
2311
|
+
/* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
|
2312
|
+
#define pg_rb_io_wait rb_io_wait
|
2313
|
+
#define PG_RUBY_IO_READABLE RUBY_IO_READABLE
|
2314
|
+
#define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
|
2315
|
+
#define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
|
2316
|
+
|
2394
2317
|
#else
|
2318
|
+
/* For compat with ruby < 3.0 */
|
2319
|
+
|
2320
|
+
typedef enum {
|
2321
|
+
PG_RUBY_IO_READABLE = RB_WAITFD_IN,
|
2322
|
+
PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
|
2323
|
+
PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
|
2324
|
+
} pg_rb_io_event_t;
|
2325
|
+
|
2326
|
+
static VALUE
|
2327
|
+
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2328
|
+
rb_io_t *fptr;
|
2329
|
+
struct timeval waittime;
|
2330
|
+
int res;
|
2331
|
+
|
2332
|
+
GetOpenFile((io), fptr);
|
2333
|
+
if( !NIL_P(timeout) ){
|
2334
|
+
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
2335
|
+
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
2336
|
+
}
|
2337
|
+
res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
2395
2338
|
|
2396
|
-
|
2339
|
+
return UINT2NUM(res);
|
2340
|
+
}
|
2341
|
+
#endif
|
2397
2342
|
|
2398
2343
|
static void *
|
2399
|
-
wait_socket_readable(
|
2344
|
+
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
2400
2345
|
{
|
2401
|
-
|
2402
|
-
|
2346
|
+
VALUE socket_io;
|
2347
|
+
VALUE ret;
|
2403
2348
|
void *retval;
|
2404
|
-
rb_fdset_t sd_rset;
|
2405
2349
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2406
|
-
|
2407
|
-
|
2408
|
-
#endif
|
2350
|
+
VALUE wait_timeout = Qnil;
|
2351
|
+
PGconn *conn = pg_get_pgconn(self);
|
2409
2352
|
|
2410
|
-
|
2411
|
-
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
2353
|
+
socket_io = pgconn_socket_io(self);
|
2412
2354
|
|
2413
2355
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2414
|
-
if ( PQconsumeInput(conn) == 0 )
|
2356
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
2357
|
+
pgconn_close_socket_io(self);
|
2415
2358
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2416
|
-
|
2417
|
-
rb_fd_init( &sd_rset );
|
2359
|
+
}
|
2418
2360
|
|
2419
2361
|
if ( ptimeout ) {
|
2420
2362
|
gettimeofday(&currtime, NULL);
|
@@ -2422,59 +2364,74 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2422
2364
|
}
|
2423
2365
|
|
2424
2366
|
while ( !(retval=is_readable(conn)) ) {
|
2425
|
-
rb_fd_zero( &sd_rset );
|
2426
|
-
rb_fd_set( sd, &sd_rset );
|
2427
|
-
|
2428
|
-
#ifdef _WIN32
|
2429
|
-
/* Ruby's FD_SET is modified on win32 to convert a file descriptor
|
2430
|
-
* to osfhandle, but we already get a osfhandle from PQsocket().
|
2431
|
-
* Therefore it's overwritten here. */
|
2432
|
-
sd_rset.fd_array[0] = sd;
|
2433
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2434
|
-
#endif
|
2435
|
-
|
2436
2367
|
if ( ptimeout ) {
|
2437
2368
|
gettimeofday(&currtime, NULL);
|
2438
2369
|
timersub(&aborttime, &currtime, &waittime);
|
2370
|
+
wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
|
2439
2371
|
}
|
2440
2372
|
|
2441
2373
|
/* Is the given timeout valid? */
|
2442
2374
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2443
2375
|
/* Wait for the socket to become readable before checking again */
|
2444
|
-
ret =
|
2376
|
+
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
2445
2377
|
} else {
|
2446
|
-
ret =
|
2447
|
-
}
|
2448
|
-
|
2449
|
-
|
2450
|
-
#ifdef _WIN32
|
2451
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2452
|
-
#endif
|
2453
|
-
|
2454
|
-
if ( ret < 0 ){
|
2455
|
-
rb_fd_term( &sd_rset );
|
2456
|
-
rb_sys_fail( "rb_thread_select()" );
|
2378
|
+
ret = Qfalse;
|
2457
2379
|
}
|
2458
2380
|
|
2459
2381
|
/* Return false if the select() timed out */
|
2460
|
-
if ( ret ==
|
2461
|
-
rb_fd_term( &sd_rset );
|
2382
|
+
if ( ret == Qfalse ){
|
2462
2383
|
return NULL;
|
2463
2384
|
}
|
2464
2385
|
|
2465
2386
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2466
2387
|
if ( PQconsumeInput(conn) == 0 ){
|
2467
|
-
|
2388
|
+
pgconn_close_socket_io(self);
|
2468
2389
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2469
2390
|
}
|
2470
2391
|
}
|
2471
2392
|
|
2472
|
-
rb_fd_term( &sd_rset );
|
2473
2393
|
return retval;
|
2474
2394
|
}
|
2475
2395
|
|
2396
|
+
/*
|
2397
|
+
* call-seq:
|
2398
|
+
* conn.flush() -> Boolean
|
2399
|
+
*
|
2400
|
+
* Attempts to flush any queued output data to the server.
|
2401
|
+
* Returns +true+ if data is successfully flushed, +false+
|
2402
|
+
* if not (can only return +false+ if connection is
|
2403
|
+
* nonblocking.
|
2404
|
+
* Raises PG::Error if some other failure occurred.
|
2405
|
+
*/
|
2406
|
+
static VALUE
|
2407
|
+
pgconn_async_flush(VALUE self)
|
2408
|
+
{
|
2409
|
+
while( pgconn_sync_flush(self) == Qfalse ){
|
2410
|
+
/* wait for the socket to become read- or write-ready */
|
2411
|
+
int events;
|
2412
|
+
VALUE socket_io = pgconn_socket_io(self);
|
2413
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
2414
|
+
|
2415
|
+
if (events & PG_RUBY_IO_READABLE)
|
2416
|
+
pgconn_consume_input(self);
|
2417
|
+
}
|
2418
|
+
return Qtrue;
|
2419
|
+
}
|
2420
|
+
|
2421
|
+
static VALUE
|
2422
|
+
pgconn_wait_for_flush( VALUE self ){
|
2423
|
+
if( !pg_get_connection_safe(self)->flush_data )
|
2424
|
+
return Qnil;
|
2425
|
+
|
2426
|
+
return pgconn_async_flush(self);
|
2427
|
+
}
|
2476
2428
|
|
2477
|
-
|
2429
|
+
static VALUE
|
2430
|
+
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2431
|
+
t_pg_connection *conn = pg_get_connection(self);
|
2432
|
+
conn->flush_data = RTEST(enabled);
|
2433
|
+
return enabled;
|
2434
|
+
}
|
2478
2435
|
|
2479
2436
|
static void *
|
2480
2437
|
notify_readable(PGconn *conn)
|
@@ -2484,27 +2441,20 @@ notify_readable(PGconn *conn)
|
|
2484
2441
|
|
2485
2442
|
/*
|
2486
2443
|
* call-seq:
|
2487
|
-
* conn.wait_for_notify( [ timeout ] ) -> String
|
2488
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
|
2489
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
|
2444
|
+
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
|
2490
2445
|
*
|
2491
2446
|
* Blocks while waiting for notification(s), or until the optional
|
2492
2447
|
* _timeout_ is reached, whichever comes first. _timeout_ is
|
2493
2448
|
* measured in seconds and can be fractional.
|
2494
2449
|
*
|
2495
|
-
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2496
|
-
*
|
2497
|
-
*
|
2498
|
-
*
|
2499
|
-
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2500
|
-
* the optional +payload+ string, it will be given to the block as the
|
2501
|
-
* third argument.
|
2502
|
-
*
|
2450
|
+
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
|
2451
|
+
* If used in block form, passes the name of the NOTIFY +event+, the generating
|
2452
|
+
* +pid+ and the optional +payload+ string into the block.
|
2503
2453
|
*/
|
2504
2454
|
static VALUE
|
2505
2455
|
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
2506
2456
|
{
|
2507
|
-
|
2457
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2508
2458
|
PGnotify *pnotification;
|
2509
2459
|
struct timeval timeout;
|
2510
2460
|
struct timeval *ptimeout = NULL;
|
@@ -2520,20 +2470,18 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2520
2470
|
ptimeout = &timeout;
|
2521
2471
|
}
|
2522
2472
|
|
2523
|
-
pnotification = (PGnotify*) wait_socket_readable(
|
2473
|
+
pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
|
2524
2474
|
|
2525
2475
|
/* Return nil if the select timed out */
|
2526
2476
|
if ( !pnotification ) return Qnil;
|
2527
2477
|
|
2528
|
-
relname =
|
2529
|
-
PG_ENCODING_SET_NOCHECK( relname,
|
2478
|
+
relname = rb_str_new2( pnotification->relname );
|
2479
|
+
PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
|
2530
2480
|
be_pid = INT2NUM( pnotification->be_pid );
|
2531
|
-
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2532
2481
|
if ( *pnotification->extra ) {
|
2533
|
-
extra =
|
2534
|
-
PG_ENCODING_SET_NOCHECK( extra,
|
2482
|
+
extra = rb_str_new2( pnotification->extra );
|
2483
|
+
PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
|
2535
2484
|
}
|
2536
|
-
#endif
|
2537
2485
|
PQfreemem( pnotification );
|
2538
2486
|
|
2539
2487
|
if ( rb_block_given_p() )
|
@@ -2543,27 +2491,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2543
2491
|
}
|
2544
2492
|
|
2545
2493
|
|
2546
|
-
/*
|
2547
|
-
* call-seq:
|
2548
|
-
* conn.put_copy_data( buffer [, encoder] ) -> Boolean
|
2549
|
-
*
|
2550
|
-
* Transmits _buffer_ as copy data to the server.
|
2551
|
-
* Returns true if the data was sent, false if it was
|
2552
|
-
* not sent (false is only possible if the connection
|
2553
|
-
* is in nonblocking mode, and this command would block).
|
2554
|
-
*
|
2555
|
-
* encoder can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
|
2556
|
-
* This encodes the received data fields from an Array of Strings. Optionally
|
2557
|
-
* the encoder can type cast the fields form various Ruby types in one step,
|
2558
|
-
* if PG::TextEncoder::CopyRow#type_map is set accordingly.
|
2559
|
-
*
|
2560
|
-
* Raises an exception if an error occurs.
|
2561
|
-
*
|
2562
|
-
* See also #copy_data.
|
2563
|
-
*
|
2564
|
-
*/
|
2565
2494
|
static VALUE
|
2566
|
-
|
2495
|
+
pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
2567
2496
|
{
|
2568
2497
|
int ret;
|
2569
2498
|
int len;
|
@@ -2580,18 +2509,16 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2580
2509
|
if( NIL_P(this->encoder_for_put_copy_data) ){
|
2581
2510
|
buffer = value;
|
2582
2511
|
} else {
|
2583
|
-
p_coder =
|
2512
|
+
p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
|
2584
2513
|
}
|
2585
|
-
} else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
|
2586
|
-
Data_Get_Struct( encoder, t_pg_coder, p_coder );
|
2587
2514
|
} else {
|
2588
|
-
|
2589
|
-
|
2515
|
+
/* Check argument type and use argument encoder */
|
2516
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
|
2590
2517
|
}
|
2591
2518
|
|
2592
2519
|
if( p_coder ){
|
2593
2520
|
t_pg_coder_enc_func enc_func;
|
2594
|
-
int enc_idx =
|
2521
|
+
int enc_idx = this->enc_idx;
|
2595
2522
|
|
2596
2523
|
enc_func = pg_coder_enc_func( p_coder );
|
2597
2524
|
len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
|
@@ -2620,61 +2547,31 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2620
2547
|
return (ret) ? Qtrue : Qfalse;
|
2621
2548
|
}
|
2622
2549
|
|
2623
|
-
/*
|
2624
|
-
* call-seq:
|
2625
|
-
* conn.put_copy_end( [ error_message ] ) -> Boolean
|
2626
|
-
*
|
2627
|
-
* Sends end-of-data indication to the server.
|
2628
|
-
*
|
2629
|
-
* _error_message_ is an optional parameter, and if set,
|
2630
|
-
* forces the COPY command to fail with the string
|
2631
|
-
* _error_message_.
|
2632
|
-
*
|
2633
|
-
* Returns true if the end-of-data was sent, false if it was
|
2634
|
-
* not sent (false is only possible if the connection
|
2635
|
-
* is in nonblocking mode, and this command would block).
|
2636
|
-
*/
|
2637
2550
|
static VALUE
|
2638
|
-
|
2551
|
+
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2639
2552
|
{
|
2640
2553
|
VALUE str;
|
2641
2554
|
VALUE error;
|
2642
2555
|
int ret;
|
2643
2556
|
const char *error_message = NULL;
|
2644
|
-
|
2557
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2645
2558
|
|
2646
2559
|
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
2647
2560
|
error_message = NULL;
|
2648
2561
|
else
|
2649
|
-
error_message = pg_cstr_enc(str,
|
2562
|
+
error_message = pg_cstr_enc(str, this->enc_idx);
|
2650
2563
|
|
2651
|
-
ret = gvl_PQputCopyEnd(
|
2564
|
+
ret = gvl_PQputCopyEnd(this->pgconn, error_message);
|
2652
2565
|
if(ret == -1) {
|
2653
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(
|
2566
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
|
2654
2567
|
rb_iv_set(error, "@connection", self);
|
2655
2568
|
rb_exc_raise(error);
|
2656
2569
|
}
|
2657
2570
|
return (ret) ? Qtrue : Qfalse;
|
2658
2571
|
}
|
2659
2572
|
|
2660
|
-
/*
|
2661
|
-
* call-seq:
|
2662
|
-
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> String
|
2663
|
-
*
|
2664
|
-
* Return a string containing one row of data, +nil+
|
2665
|
-
* if the copy is done, or +false+ if the call would
|
2666
|
-
* block (only possible if _async_ is true).
|
2667
|
-
*
|
2668
|
-
* decoder can be a PG::Coder derivation (typically PG::TextDecoder::CopyRow).
|
2669
|
-
* This decodes the received data fields as Array of Strings. Optionally
|
2670
|
-
* the decoder can type cast the fields to various Ruby types in one step,
|
2671
|
-
* if PG::TextDecoder::CopyRow#type_map is set accordingly.
|
2672
|
-
*
|
2673
|
-
* See also #copy_data.
|
2674
|
-
*
|
2675
|
-
*/
|
2676
2573
|
static VALUE
|
2677
|
-
|
2574
|
+
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2678
2575
|
{
|
2679
2576
|
VALUE async_in;
|
2680
2577
|
VALUE error;
|
@@ -2689,13 +2586,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2689
2586
|
|
2690
2587
|
if( NIL_P(decoder) ){
|
2691
2588
|
if( !NIL_P(this->decoder_for_get_copy_data) ){
|
2692
|
-
p_coder =
|
2589
|
+
p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
|
2693
2590
|
}
|
2694
|
-
} else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
|
2695
|
-
Data_Get_Struct( decoder, t_pg_coder, p_coder );
|
2696
2591
|
} else {
|
2697
|
-
|
2698
|
-
|
2592
|
+
/* Check argument type and use argument decoder */
|
2593
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
|
2699
2594
|
}
|
2700
2595
|
|
2701
2596
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
@@ -2713,9 +2608,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2713
2608
|
|
2714
2609
|
if( p_coder ){
|
2715
2610
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
|
2716
|
-
result = dec_func( p_coder, buffer, ret, 0, 0,
|
2611
|
+
result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
|
2717
2612
|
} else {
|
2718
|
-
result =
|
2613
|
+
result = rb_str_new(buffer, ret);
|
2719
2614
|
}
|
2720
2615
|
|
2721
2616
|
PQfreemem(buffer);
|
@@ -2728,9 +2623,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2728
2623
|
*
|
2729
2624
|
* Sets connection's verbosity to _verbosity_ and returns
|
2730
2625
|
* the previous setting. Available settings are:
|
2626
|
+
*
|
2731
2627
|
* * PQERRORS_TERSE
|
2732
2628
|
* * PQERRORS_DEFAULT
|
2733
2629
|
* * PQERRORS_VERBOSE
|
2630
|
+
* * PQERRORS_SQLSTATE
|
2631
|
+
*
|
2632
|
+
* Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
|
2633
|
+
* (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
|
2634
|
+
*
|
2635
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
|
2734
2636
|
*/
|
2735
2637
|
static VALUE
|
2736
2638
|
pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
@@ -2740,6 +2642,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2740
2642
|
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
2741
2643
|
}
|
2742
2644
|
|
2645
|
+
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
2646
|
+
/*
|
2647
|
+
* call-seq:
|
2648
|
+
* conn.set_error_context_visibility( context_visibility ) -> Integer
|
2649
|
+
*
|
2650
|
+
* Sets connection's context display mode to _context_visibility_ and returns
|
2651
|
+
* the previous setting. Available settings are:
|
2652
|
+
* * PQSHOW_CONTEXT_NEVER
|
2653
|
+
* * PQSHOW_CONTEXT_ERRORS
|
2654
|
+
* * PQSHOW_CONTEXT_ALWAYS
|
2655
|
+
*
|
2656
|
+
* This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
|
2657
|
+
* The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
|
2658
|
+
* In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
|
2659
|
+
*
|
2660
|
+
* Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
|
2661
|
+
* (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
|
2662
|
+
*
|
2663
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
|
2664
|
+
*
|
2665
|
+
* Available since PostgreSQL-9.6
|
2666
|
+
*/
|
2667
|
+
static VALUE
|
2668
|
+
pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
2669
|
+
{
|
2670
|
+
PGconn *conn = pg_get_pgconn(self);
|
2671
|
+
PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
|
2672
|
+
return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
|
2673
|
+
}
|
2674
|
+
#endif
|
2675
|
+
|
2743
2676
|
/*
|
2744
2677
|
* call-seq:
|
2745
2678
|
* conn.trace( stream ) -> nil
|
@@ -2758,7 +2691,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2758
2691
|
VALUE new_file;
|
2759
2692
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2760
2693
|
|
2761
|
-
if(rb_respond_to(stream,rb_intern("fileno"))
|
2694
|
+
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2762
2695
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2763
2696
|
|
2764
2697
|
fileno = rb_funcall(stream, rb_intern("fileno"), 0);
|
@@ -2891,8 +2824,8 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2891
2824
|
t_pg_connection *this = pg_get_connection( self );
|
2892
2825
|
|
2893
2826
|
if (this->notice_receiver != Qnil) {
|
2894
|
-
VALUE message_str =
|
2895
|
-
PG_ENCODING_SET_NOCHECK( message_str,
|
2827
|
+
VALUE message_str = rb_str_new2(message);
|
2828
|
+
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2896
2829
|
rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
|
2897
2830
|
}
|
2898
2831
|
return;
|
@@ -2902,7 +2835,7 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2902
2835
|
* call-seq:
|
2903
2836
|
* conn.set_notice_processor {|message| ... } -> Proc
|
2904
2837
|
*
|
2905
|
-
* See #set_notice_receiver for the
|
2838
|
+
* See #set_notice_receiver for the description of what this and the
|
2906
2839
|
* notice_processor methods do.
|
2907
2840
|
*
|
2908
2841
|
* This function takes a new block to act as the notice processor and returns
|
@@ -2950,83 +2883,40 @@ static VALUE
|
|
2950
2883
|
pgconn_get_client_encoding(VALUE self)
|
2951
2884
|
{
|
2952
2885
|
char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
|
2953
|
-
return
|
2886
|
+
return rb_str_new2(encoding);
|
2954
2887
|
}
|
2955
2888
|
|
2956
2889
|
|
2957
2890
|
/*
|
2958
2891
|
* call-seq:
|
2959
|
-
* conn.
|
2892
|
+
* conn.sync_set_client_encoding( encoding )
|
2960
2893
|
*
|
2961
|
-
*
|
2894
|
+
* This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
|
2895
|
+
* See #async_exec for the differences between the two API variants.
|
2896
|
+
* It's not recommended to use explicit sync or async variants but #set_client_encoding instead, unless you have a good reason to do so.
|
2962
2897
|
*/
|
2963
2898
|
static VALUE
|
2964
|
-
|
2899
|
+
pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
2965
2900
|
{
|
2966
2901
|
PGconn *conn = pg_get_pgconn( self );
|
2967
2902
|
|
2968
2903
|
Check_Type(str, T_STRING);
|
2969
2904
|
|
2970
2905
|
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
|
2971
|
-
rb_raise(rb_ePGerror, "
|
2906
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
2972
2907
|
}
|
2973
|
-
#ifdef M17N_SUPPORTED
|
2974
2908
|
pgconn_set_internal_encoding_index( self );
|
2975
|
-
#endif
|
2976
2909
|
|
2977
2910
|
return Qnil;
|
2978
2911
|
}
|
2979
2912
|
|
2913
|
+
|
2980
2914
|
/*
|
2981
2915
|
* call-seq:
|
2982
|
-
* conn.
|
2983
|
-
*
|
2984
|
-
*
|
2985
|
-
*
|
2986
|
-
* +ROLLBACK+ if any exception occurs.
|
2987
|
-
*/
|
2988
|
-
static VALUE
|
2989
|
-
pgconn_transaction(VALUE self)
|
2990
|
-
{
|
2991
|
-
PGconn *conn = pg_get_pgconn(self);
|
2992
|
-
PGresult *result;
|
2993
|
-
VALUE rb_pgresult;
|
2994
|
-
VALUE block_result = Qnil;
|
2995
|
-
int status;
|
2996
|
-
|
2997
|
-
if (rb_block_given_p()) {
|
2998
|
-
result = gvl_PQexec(conn, "BEGIN");
|
2999
|
-
rb_pgresult = pg_new_result(result, self);
|
3000
|
-
pg_result_check(rb_pgresult);
|
3001
|
-
block_result = rb_protect(rb_yield, self, &status);
|
3002
|
-
if(status == 0) {
|
3003
|
-
result = gvl_PQexec(conn, "COMMIT");
|
3004
|
-
rb_pgresult = pg_new_result(result, self);
|
3005
|
-
pg_result_check(rb_pgresult);
|
3006
|
-
}
|
3007
|
-
else {
|
3008
|
-
/* exception occurred, ROLLBACK and re-raise */
|
3009
|
-
result = gvl_PQexec(conn, "ROLLBACK");
|
3010
|
-
rb_pgresult = pg_new_result(result, self);
|
3011
|
-
pg_result_check(rb_pgresult);
|
3012
|
-
rb_jump_tag(status);
|
3013
|
-
}
|
3014
|
-
|
3015
|
-
}
|
3016
|
-
else {
|
3017
|
-
/* no block supplied? */
|
3018
|
-
rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
|
3019
|
-
}
|
3020
|
-
return block_result;
|
3021
|
-
}
|
3022
|
-
|
3023
|
-
|
3024
|
-
/*
|
3025
|
-
* call-seq:
|
3026
|
-
* conn.quote_ident( str ) -> String
|
3027
|
-
* conn.quote_ident( array ) -> String
|
3028
|
-
* PG::Connection.quote_ident( str ) -> String
|
3029
|
-
* PG::Connection.quote_ident( array ) -> String
|
2916
|
+
* conn.quote_ident( str ) -> String
|
2917
|
+
* conn.quote_ident( array ) -> String
|
2918
|
+
* PG::Connection.quote_ident( str ) -> String
|
2919
|
+
* PG::Connection.quote_ident( array ) -> String
|
3030
2920
|
*
|
3031
2921
|
* Returns a string that is safe for inclusion in a SQL query as an
|
3032
2922
|
* identifier. Note: this is not a quote function for values, but for
|
@@ -3064,14 +2954,12 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
|
|
3064
2954
|
int enc_idx;
|
3065
2955
|
|
3066
2956
|
if( rb_obj_is_kind_of(self, rb_cPGconn) ){
|
3067
|
-
enc_idx =
|
2957
|
+
enc_idx = pg_get_connection(self)->enc_idx;
|
3068
2958
|
}else{
|
3069
2959
|
enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
|
3070
2960
|
}
|
3071
2961
|
pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
|
3072
2962
|
|
3073
|
-
OBJ_INFECT(ret, str_or_array);
|
3074
|
-
|
3075
2963
|
return ret;
|
3076
2964
|
}
|
3077
2965
|
|
@@ -3085,110 +2973,442 @@ get_result_readable(PGconn *conn)
|
|
3085
2973
|
|
3086
2974
|
/*
|
3087
2975
|
* call-seq:
|
3088
|
-
* conn.block( [ timeout ] ) -> Boolean
|
2976
|
+
* conn.block( [ timeout ] ) -> Boolean
|
2977
|
+
*
|
2978
|
+
* Blocks until the server is no longer busy, or until the
|
2979
|
+
* optional _timeout_ is reached, whichever comes first.
|
2980
|
+
* _timeout_ is measured in seconds and can be fractional.
|
2981
|
+
*
|
2982
|
+
* Returns +false+ if _timeout_ is reached, +true+ otherwise.
|
2983
|
+
*
|
2984
|
+
* If +true+ is returned, +conn.is_busy+ will return +false+
|
2985
|
+
* and +conn.get_result+ will not block.
|
2986
|
+
*/
|
2987
|
+
static VALUE
|
2988
|
+
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2989
|
+
struct timeval timeout;
|
2990
|
+
struct timeval *ptimeout = NULL;
|
2991
|
+
VALUE timeout_in;
|
2992
|
+
double timeout_sec;
|
2993
|
+
void *ret;
|
2994
|
+
|
2995
|
+
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2996
|
+
timeout_sec = NUM2DBL( timeout_in );
|
2997
|
+
timeout.tv_sec = (time_t)timeout_sec;
|
2998
|
+
timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
|
2999
|
+
ptimeout = &timeout;
|
3000
|
+
}
|
3001
|
+
|
3002
|
+
ret = wait_socket_readable( self, ptimeout, get_result_readable);
|
3003
|
+
|
3004
|
+
if( !ret )
|
3005
|
+
return Qfalse;
|
3006
|
+
|
3007
|
+
return Qtrue;
|
3008
|
+
}
|
3009
|
+
|
3010
|
+
|
3011
|
+
/*
|
3012
|
+
* call-seq:
|
3013
|
+
* conn.sync_get_last_result( ) -> PG::Result
|
3014
|
+
*
|
3015
|
+
* This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
|
3016
|
+
* See #async_exec for the differences between the two API variants.
|
3017
|
+
* It's not recommended to use explicit sync or async variants but #get_last_result instead, unless you have a good reason to do so.
|
3018
|
+
*/
|
3019
|
+
static VALUE
|
3020
|
+
pgconn_sync_get_last_result(VALUE self)
|
3021
|
+
{
|
3022
|
+
PGconn *conn = pg_get_pgconn(self);
|
3023
|
+
VALUE rb_pgresult = Qnil;
|
3024
|
+
PGresult *cur, *prev;
|
3025
|
+
|
3026
|
+
|
3027
|
+
cur = prev = NULL;
|
3028
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3029
|
+
int status;
|
3030
|
+
|
3031
|
+
if (prev) PQclear(prev);
|
3032
|
+
prev = cur;
|
3033
|
+
|
3034
|
+
status = PQresultStatus(cur);
|
3035
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
3036
|
+
break;
|
3037
|
+
}
|
3038
|
+
|
3039
|
+
if (prev) {
|
3040
|
+
rb_pgresult = pg_new_result( prev, self );
|
3041
|
+
pg_result_check(rb_pgresult);
|
3042
|
+
}
|
3043
|
+
|
3044
|
+
return rb_pgresult;
|
3045
|
+
}
|
3046
|
+
|
3047
|
+
/*
|
3048
|
+
* call-seq:
|
3049
|
+
* conn.get_last_result( ) -> PG::Result
|
3050
|
+
*
|
3051
|
+
* This function retrieves all available results
|
3052
|
+
* on the current connection (from previously issued
|
3053
|
+
* asynchronous commands like +send_query()+) and
|
3054
|
+
* returns the last non-NULL result, or +nil+ if no
|
3055
|
+
* results are available.
|
3056
|
+
*
|
3057
|
+
* If the last result contains a bad result_status, an
|
3058
|
+
* appropriate exception is raised.
|
3059
|
+
*
|
3060
|
+
* This function is similar to #get_result
|
3061
|
+
* except that it is designed to get one and only
|
3062
|
+
* one result and that it checks the result state.
|
3063
|
+
*/
|
3064
|
+
static VALUE
|
3065
|
+
pgconn_async_get_last_result(VALUE self)
|
3066
|
+
{
|
3067
|
+
PGconn *conn = pg_get_pgconn(self);
|
3068
|
+
VALUE rb_pgresult = Qnil;
|
3069
|
+
PGresult *cur, *prev;
|
3070
|
+
|
3071
|
+
cur = prev = NULL;
|
3072
|
+
for(;;) {
|
3073
|
+
int status;
|
3074
|
+
|
3075
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3076
|
+
|
3077
|
+
cur = gvl_PQgetResult(conn);
|
3078
|
+
if (cur == NULL)
|
3079
|
+
break;
|
3080
|
+
|
3081
|
+
if (prev) PQclear(prev);
|
3082
|
+
prev = cur;
|
3083
|
+
|
3084
|
+
status = PQresultStatus(cur);
|
3085
|
+
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
|
3086
|
+
break;
|
3087
|
+
}
|
3088
|
+
|
3089
|
+
if (prev) {
|
3090
|
+
rb_pgresult = pg_new_result( prev, self );
|
3091
|
+
pg_result_check(rb_pgresult);
|
3092
|
+
}
|
3093
|
+
|
3094
|
+
return rb_pgresult;
|
3095
|
+
}
|
3096
|
+
|
3097
|
+
/*
|
3098
|
+
* call-seq:
|
3099
|
+
* conn.discard_results()
|
3100
|
+
*
|
3101
|
+
* Silently discard any prior query result that application didn't eat.
|
3102
|
+
* This is done prior of Connection#exec and sibling methods and can
|
3103
|
+
* be called explicitly when using the async API.
|
3104
|
+
*/
|
3105
|
+
static VALUE
|
3106
|
+
pgconn_discard_results(VALUE self)
|
3107
|
+
{
|
3108
|
+
PGconn *conn = pg_get_pgconn(self);
|
3109
|
+
VALUE socket_io;
|
3110
|
+
|
3111
|
+
if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
|
3112
|
+
return Qnil;
|
3113
|
+
}
|
3114
|
+
|
3115
|
+
socket_io = pgconn_socket_io(self);
|
3116
|
+
|
3117
|
+
for(;;) {
|
3118
|
+
PGresult *cur;
|
3119
|
+
int status;
|
3120
|
+
|
3121
|
+
/* pgconn_block() raises an exception in case of errors.
|
3122
|
+
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
3123
|
+
*/
|
3124
|
+
while( gvl_PQisBusy(conn) ){
|
3125
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3126
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
3127
|
+
pgconn_close_socket_io(self);
|
3128
|
+
return Qfalse;
|
3129
|
+
}
|
3130
|
+
}
|
3131
|
+
|
3132
|
+
cur = gvl_PQgetResult(conn);
|
3133
|
+
if( cur == NULL) break;
|
3134
|
+
|
3135
|
+
status = PQresultStatus(cur);
|
3136
|
+
PQclear(cur);
|
3137
|
+
if (status == PGRES_COPY_IN){
|
3138
|
+
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
3139
|
+
}
|
3140
|
+
if (status == PGRES_COPY_OUT){
|
3141
|
+
for(;;) {
|
3142
|
+
char *buffer = NULL;
|
3143
|
+
int st = gvl_PQgetCopyData(conn, &buffer, 1);
|
3144
|
+
if( st == 0 ) {
|
3145
|
+
/* would block -> wait for readable data */
|
3146
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3147
|
+
if ( PQconsumeInput(conn) == 0 ) {
|
3148
|
+
pgconn_close_socket_io(self);
|
3149
|
+
return Qfalse;
|
3150
|
+
}
|
3151
|
+
} else if( st > 0 ) {
|
3152
|
+
/* some data retrieved -> discard it */
|
3153
|
+
PQfreemem(buffer);
|
3154
|
+
} else {
|
3155
|
+
/* no more data */
|
3156
|
+
break;
|
3157
|
+
}
|
3158
|
+
}
|
3159
|
+
}
|
3160
|
+
}
|
3161
|
+
|
3162
|
+
return Qtrue;
|
3163
|
+
}
|
3164
|
+
|
3165
|
+
/*
|
3166
|
+
* call-seq:
|
3167
|
+
* conn.exec(sql) -> PG::Result
|
3168
|
+
* conn.exec(sql) {|pg_result| block }
|
3169
|
+
*
|
3170
|
+
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
3171
|
+
* On success, it returns a PG::Result instance with all result rows and columns.
|
3172
|
+
* On failure, it raises a PG::Error.
|
3173
|
+
*
|
3174
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
3175
|
+
* it will call #exec_params for you. New code should explicitly use #exec_params if
|
3176
|
+
* argument placeholders are used.
|
3177
|
+
*
|
3178
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
3179
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
3180
|
+
* In this instance, <code>conn.exec</code> returns the value of the block.
|
3181
|
+
*
|
3182
|
+
* #exec is an alias for #async_exec which is almost identical to #sync_exec .
|
3183
|
+
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
3184
|
+
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
3185
|
+
* Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
|
3186
|
+
* Both methods ensure that other threads can process while waiting for the server to
|
3187
|
+
* complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
|
3188
|
+
* This is most notably visible by a delayed reaction to Control+C.
|
3189
|
+
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
3190
|
+
*
|
3191
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
|
3192
|
+
*/
|
3193
|
+
static VALUE
|
3194
|
+
pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
3195
|
+
{
|
3196
|
+
VALUE rb_pgresult = Qnil;
|
3197
|
+
|
3198
|
+
pgconn_discard_results( self );
|
3199
|
+
pgconn_send_query( argc, argv, self );
|
3200
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3201
|
+
|
3202
|
+
if ( rb_block_given_p() ) {
|
3203
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3204
|
+
}
|
3205
|
+
return rb_pgresult;
|
3206
|
+
}
|
3207
|
+
|
3208
|
+
|
3209
|
+
/*
|
3210
|
+
* call-seq:
|
3211
|
+
* conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
|
3212
|
+
* conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
|
3213
|
+
*
|
3214
|
+
* Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
|
3215
|
+
* for parameters.
|
3216
|
+
*
|
3217
|
+
* Returns a PG::Result instance on success. On failure, it raises a PG::Error.
|
3218
|
+
*
|
3219
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
3220
|
+
* Each element of the +params+ array may be either:
|
3221
|
+
* a hash of the form:
|
3222
|
+
* {:value => String (value of bind parameter)
|
3223
|
+
* :type => Integer (oid of type of bind parameter)
|
3224
|
+
* :format => Integer (0 for text, 1 for binary)
|
3225
|
+
* }
|
3226
|
+
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3227
|
+
* { :value => <string value>, :type => 0, :format => 0 }
|
3228
|
+
*
|
3229
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3230
|
+
* inside the SQL query. The 0th element of the +params+ array is bound
|
3231
|
+
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3232
|
+
*
|
3233
|
+
* If the types are not specified, they will be inferred by PostgreSQL.
|
3234
|
+
* Instead of specifying type oids, it's recommended to simply add
|
3235
|
+
* explicit casts in the query to ensure that the right type is used.
|
3236
|
+
*
|
3237
|
+
* For example: "SELECT $1::int"
|
3238
|
+
*
|
3239
|
+
* The optional +result_format+ should be 0 for text results, 1
|
3240
|
+
* for binary.
|
3241
|
+
*
|
3242
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
3243
|
+
* This will type cast the params from various Ruby types before transmission
|
3244
|
+
* based on the encoders defined by the type map. When a type encoder is used
|
3245
|
+
* the format and oid of a given bind parameter are retrieved from the encoder
|
3246
|
+
* instead out of the hash form described above.
|
3247
|
+
*
|
3248
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
3249
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
3250
|
+
* In this instance, <code>conn.exec</code> returns the value of the block.
|
3251
|
+
*
|
3252
|
+
* The primary advantage of #exec_params over #exec is that parameter values can be separated from the command string, thus avoiding the need for tedious and error-prone quoting and escaping.
|
3253
|
+
* Unlike #exec, #exec_params allows at most one SQL command in the given string.
|
3254
|
+
* (There can be semicolons in it, but not more than one nonempty command.)
|
3255
|
+
* This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
|
3256
|
+
*
|
3257
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
|
3258
|
+
*/
|
3259
|
+
static VALUE
|
3260
|
+
pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
3261
|
+
{
|
3262
|
+
VALUE rb_pgresult = Qnil;
|
3263
|
+
|
3264
|
+
pgconn_discard_results( self );
|
3265
|
+
/* If called with no or nil parameters, use PQsendQuery for compatibility */
|
3266
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
3267
|
+
pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
|
3268
|
+
pgconn_send_query( argc, argv, self );
|
3269
|
+
} else {
|
3270
|
+
pgconn_send_query_params( argc, argv, self );
|
3271
|
+
}
|
3272
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3273
|
+
|
3274
|
+
if ( rb_block_given_p() ) {
|
3275
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3276
|
+
}
|
3277
|
+
return rb_pgresult;
|
3278
|
+
}
|
3279
|
+
|
3280
|
+
|
3281
|
+
/*
|
3282
|
+
* call-seq:
|
3283
|
+
* conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
|
3284
|
+
*
|
3285
|
+
* Prepares statement _sql_ with name _name_ to be executed later.
|
3286
|
+
* Returns a PG::Result instance on success.
|
3287
|
+
* On failure, it raises a PG::Error.
|
3288
|
+
*
|
3289
|
+
* +param_types+ is an optional parameter to specify the Oids of the
|
3290
|
+
* types of the parameters.
|
3291
|
+
*
|
3292
|
+
* If the types are not specified, they will be inferred by PostgreSQL.
|
3293
|
+
* Instead of specifying type oids, it's recommended to simply add
|
3294
|
+
* explicit casts in the query to ensure that the right type is used.
|
3295
|
+
*
|
3296
|
+
* For example: "SELECT $1::int"
|
3297
|
+
*
|
3298
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3299
|
+
* inside the SQL query.
|
3300
|
+
*
|
3301
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
|
3302
|
+
*/
|
3303
|
+
static VALUE
|
3304
|
+
pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
3305
|
+
{
|
3306
|
+
VALUE rb_pgresult = Qnil;
|
3307
|
+
|
3308
|
+
pgconn_discard_results( self );
|
3309
|
+
pgconn_send_prepare( argc, argv, self );
|
3310
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3311
|
+
|
3312
|
+
if ( rb_block_given_p() ) {
|
3313
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3314
|
+
}
|
3315
|
+
return rb_pgresult;
|
3316
|
+
}
|
3317
|
+
|
3318
|
+
|
3319
|
+
/*
|
3320
|
+
* call-seq:
|
3321
|
+
* conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
|
3322
|
+
* conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
|
3089
3323
|
*
|
3090
|
-
*
|
3091
|
-
*
|
3092
|
-
*
|
3324
|
+
* Execute prepared named statement specified by _statement_name_.
|
3325
|
+
* Returns a PG::Result instance on success.
|
3326
|
+
* On failure, it raises a PG::Error.
|
3093
3327
|
*
|
3094
|
-
*
|
3328
|
+
* +params+ is an array of the optional bind parameters for the
|
3329
|
+
* SQL query. Each element of the +params+ array may be either:
|
3330
|
+
* a hash of the form:
|
3331
|
+
* {:value => String (value of bind parameter)
|
3332
|
+
* :format => Integer (0 for text, 1 for binary)
|
3333
|
+
* }
|
3334
|
+
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3335
|
+
* { :value => <string value>, :format => 0 }
|
3095
3336
|
*
|
3096
|
-
*
|
3097
|
-
*
|
3337
|
+
* PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
|
3338
|
+
* inside the SQL query. The 0th element of the +params+ array is bound
|
3339
|
+
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3340
|
+
*
|
3341
|
+
* The optional +result_format+ should be 0 for text results, 1
|
3342
|
+
* for binary.
|
3343
|
+
*
|
3344
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
3345
|
+
* This will type cast the params from various Ruby types before transmission
|
3346
|
+
* based on the encoders defined by the type map. When a type encoder is used
|
3347
|
+
* the format and oid of a given bind parameter are retrieved from the encoder
|
3348
|
+
* instead out of the hash form described above.
|
3349
|
+
*
|
3350
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
3351
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
3352
|
+
* In this instance, <code>conn.exec_prepared</code> returns the value of the block.
|
3353
|
+
*
|
3354
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
|
3098
3355
|
*/
|
3099
3356
|
static VALUE
|
3100
|
-
|
3101
|
-
|
3102
|
-
|
3103
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
3104
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
3105
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
3357
|
+
pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
3358
|
+
{
|
3359
|
+
VALUE rb_pgresult = Qnil;
|
3106
3360
|
|
3107
|
-
|
3108
|
-
|
3109
|
-
|
3110
|
-
double timeout_sec;
|
3111
|
-
void *ret;
|
3361
|
+
pgconn_discard_results( self );
|
3362
|
+
pgconn_send_query_prepared( argc, argv, self );
|
3363
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3112
3364
|
|
3113
|
-
if (
|
3114
|
-
|
3115
|
-
timeout.tv_sec = (time_t)timeout_sec;
|
3116
|
-
timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
|
3117
|
-
ptimeout = &timeout;
|
3365
|
+
if ( rb_block_given_p() ) {
|
3366
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3118
3367
|
}
|
3119
|
-
|
3120
|
-
ret = wait_socket_readable( conn, ptimeout, get_result_readable);
|
3121
|
-
|
3122
|
-
if( !ret )
|
3123
|
-
return Qfalse;
|
3124
|
-
|
3125
|
-
return Qtrue;
|
3368
|
+
return rb_pgresult;
|
3126
3369
|
}
|
3127
3370
|
|
3128
3371
|
|
3129
3372
|
/*
|
3130
3373
|
* call-seq:
|
3131
|
-
* conn.
|
3374
|
+
* conn.describe_portal( portal_name ) -> PG::Result
|
3132
3375
|
*
|
3133
|
-
*
|
3134
|
-
* on the current connection (from previously issued
|
3135
|
-
* asynchronous commands like +send_query()+) and
|
3136
|
-
* returns the last non-NULL result, or +nil+ if no
|
3137
|
-
* results are available.
|
3376
|
+
* Retrieve information about the portal _portal_name_.
|
3138
3377
|
*
|
3139
|
-
*
|
3140
|
-
* except that it is designed to get one and only
|
3141
|
-
* one result.
|
3378
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
|
3142
3379
|
*/
|
3143
3380
|
static VALUE
|
3144
|
-
|
3381
|
+
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
3145
3382
|
{
|
3146
|
-
PGconn *conn = pg_get_pgconn(self);
|
3147
3383
|
VALUE rb_pgresult = Qnil;
|
3148
|
-
PGresult *cur, *prev;
|
3149
|
-
|
3150
|
-
|
3151
|
-
cur = prev = NULL;
|
3152
|
-
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3153
|
-
int status;
|
3154
3384
|
|
3155
|
-
|
3156
|
-
|
3157
|
-
|
3158
|
-
status = PQresultStatus(cur);
|
3159
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
3160
|
-
break;
|
3161
|
-
}
|
3385
|
+
pgconn_discard_results( self );
|
3386
|
+
pgconn_send_describe_portal( self, portal );
|
3387
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3162
3388
|
|
3163
|
-
if (
|
3164
|
-
|
3165
|
-
pg_result_check(rb_pgresult);
|
3389
|
+
if ( rb_block_given_p() ) {
|
3390
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3166
3391
|
}
|
3167
|
-
|
3168
3392
|
return rb_pgresult;
|
3169
3393
|
}
|
3170
3394
|
|
3395
|
+
|
3171
3396
|
/*
|
3172
3397
|
* call-seq:
|
3173
|
-
* conn.
|
3174
|
-
* conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
|
3398
|
+
* conn.describe_prepared( statement_name ) -> PG::Result
|
3175
3399
|
*
|
3176
|
-
*
|
3177
|
-
*
|
3178
|
-
*
|
3400
|
+
* Retrieve information about the prepared statement _statement_name_.
|
3401
|
+
*
|
3402
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
|
3179
3403
|
*/
|
3180
3404
|
static VALUE
|
3181
|
-
|
3405
|
+
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
3182
3406
|
{
|
3183
3407
|
VALUE rb_pgresult = Qnil;
|
3184
3408
|
|
3185
|
-
|
3186
|
-
|
3187
|
-
|
3188
|
-
|
3189
|
-
pgconn_send_query( argc, argv, self );
|
3190
|
-
pgconn_block( 0, NULL, self );
|
3191
|
-
rb_pgresult = pgconn_get_last_result( self );
|
3409
|
+
pgconn_discard_results( self );
|
3410
|
+
pgconn_send_describe_prepared( self, stmt_name );
|
3411
|
+
rb_pgresult = pgconn_async_get_last_result( self );
|
3192
3412
|
|
3193
3413
|
if ( rb_block_given_p() ) {
|
3194
3414
|
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
@@ -3198,14 +3418,13 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3198
3418
|
|
3199
3419
|
|
3200
3420
|
#ifdef HAVE_PQSSLATTRIBUTE
|
3201
|
-
/* Since PostgreSQL-9.5: */
|
3202
|
-
|
3203
3421
|
/*
|
3204
3422
|
* call-seq:
|
3205
3423
|
* conn.ssl_in_use? -> Boolean
|
3206
3424
|
*
|
3207
|
-
* Returns +true+ if the connection uses SSL, +false+ if not.
|
3425
|
+
* Returns +true+ if the connection uses SSL/TLS, +false+ if not.
|
3208
3426
|
*
|
3427
|
+
* Available since PostgreSQL-9.5
|
3209
3428
|
*/
|
3210
3429
|
static VALUE
|
3211
3430
|
pgconn_ssl_in_use(VALUE self)
|
@@ -3237,7 +3456,9 @@ pgconn_ssl_in_use(VALUE self)
|
|
3237
3456
|
* 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
3457
|
*
|
3239
3458
|
*
|
3240
|
-
* See also #ssl_attribute_names and
|
3459
|
+
* See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
|
3460
|
+
*
|
3461
|
+
* Available since PostgreSQL-9.5
|
3241
3462
|
*/
|
3242
3463
|
static VALUE
|
3243
3464
|
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
@@ -3256,6 +3477,7 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
|
3256
3477
|
*
|
3257
3478
|
* See also #ssl_attribute
|
3258
3479
|
*
|
3480
|
+
* Available since PostgreSQL-9.5
|
3259
3481
|
*/
|
3260
3482
|
static VALUE
|
3261
3483
|
pgconn_ssl_attribute_names(VALUE self)
|
@@ -3274,6 +3496,126 @@ pgconn_ssl_attribute_names(VALUE self)
|
|
3274
3496
|
#endif
|
3275
3497
|
|
3276
3498
|
|
3499
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
3500
|
+
/*
|
3501
|
+
* call-seq:
|
3502
|
+
* conn.pipeline_status -> Integer
|
3503
|
+
*
|
3504
|
+
* Returns the current pipeline mode status of the libpq connection.
|
3505
|
+
*
|
3506
|
+
* PQpipelineStatus can return one of the following values:
|
3507
|
+
*
|
3508
|
+
* * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
|
3509
|
+
* * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
|
3510
|
+
* * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
3511
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
3512
|
+
*
|
3513
|
+
* Available since PostgreSQL-14
|
3514
|
+
*/
|
3515
|
+
static VALUE
|
3516
|
+
pgconn_pipeline_status(VALUE self)
|
3517
|
+
{
|
3518
|
+
int res = PQpipelineStatus(pg_get_pgconn(self));
|
3519
|
+
return INT2FIX(res);
|
3520
|
+
}
|
3521
|
+
|
3522
|
+
|
3523
|
+
/*
|
3524
|
+
* call-seq:
|
3525
|
+
* conn.enter_pipeline_mode -> nil
|
3526
|
+
*
|
3527
|
+
* Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
|
3528
|
+
*
|
3529
|
+
* Raises PG::Error and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc.
|
3530
|
+
* This function does not actually send anything to the server, it just changes the libpq connection state.
|
3531
|
+
*
|
3532
|
+
* Available since PostgreSQL-14
|
3533
|
+
*/
|
3534
|
+
static VALUE
|
3535
|
+
pgconn_enter_pipeline_mode(VALUE self)
|
3536
|
+
{
|
3537
|
+
PGconn *conn = pg_get_pgconn(self);
|
3538
|
+
int res = PQenterPipelineMode(conn);
|
3539
|
+
if( res == 1 ) {
|
3540
|
+
return Qnil;
|
3541
|
+
} else {
|
3542
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3543
|
+
}
|
3544
|
+
}
|
3545
|
+
|
3546
|
+
/*
|
3547
|
+
* call-seq:
|
3548
|
+
* conn.exit_pipeline_mode -> nil
|
3549
|
+
*
|
3550
|
+
* Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
|
3551
|
+
*
|
3552
|
+
* Takes no action if not in pipeline mode.
|
3553
|
+
* Raises PG::Error if the current statement isn't finished processing, or PQgetResult has not been called to collect results from all previously sent query.
|
3554
|
+
*
|
3555
|
+
* Available since PostgreSQL-14
|
3556
|
+
*/
|
3557
|
+
static VALUE
|
3558
|
+
pgconn_exit_pipeline_mode(VALUE self)
|
3559
|
+
{
|
3560
|
+
PGconn *conn = pg_get_pgconn(self);
|
3561
|
+
int res = PQexitPipelineMode(conn);
|
3562
|
+
if( res == 1 ) {
|
3563
|
+
return Qnil;
|
3564
|
+
} else {
|
3565
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3566
|
+
}
|
3567
|
+
}
|
3568
|
+
|
3569
|
+
|
3570
|
+
/*
|
3571
|
+
* call-seq:
|
3572
|
+
* conn.pipeline_sync -> nil
|
3573
|
+
*
|
3574
|
+
* Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
|
3575
|
+
* This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
|
3576
|
+
*
|
3577
|
+
* Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
3578
|
+
*
|
3579
|
+
* Available since PostgreSQL-14
|
3580
|
+
*/
|
3581
|
+
static VALUE
|
3582
|
+
pgconn_pipeline_sync(VALUE self)
|
3583
|
+
{
|
3584
|
+
PGconn *conn = pg_get_pgconn(self);
|
3585
|
+
int res = PQpipelineSync(conn);
|
3586
|
+
if( res == 1 ) {
|
3587
|
+
return Qnil;
|
3588
|
+
} else {
|
3589
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3590
|
+
}
|
3591
|
+
}
|
3592
|
+
|
3593
|
+
/*
|
3594
|
+
* call-seq:
|
3595
|
+
* conn.pipeline_sync -> nil
|
3596
|
+
*
|
3597
|
+
* Sends a request for the server to flush its output buffer.
|
3598
|
+
*
|
3599
|
+
* The server flushes its output buffer automatically as a result of Connection#pipeline_sync being called, or on any request when not in pipeline mode.
|
3600
|
+
* This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
|
3601
|
+
* Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
|
3602
|
+
*
|
3603
|
+
* Available since PostgreSQL-14
|
3604
|
+
*/
|
3605
|
+
static VALUE
|
3606
|
+
pgconn_send_flush_request(VALUE self)
|
3607
|
+
{
|
3608
|
+
PGconn *conn = pg_get_pgconn(self);
|
3609
|
+
int res = PQsendFlushRequest(conn);
|
3610
|
+
if( res == 1 ) {
|
3611
|
+
return Qnil;
|
3612
|
+
} else {
|
3613
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
3614
|
+
}
|
3615
|
+
}
|
3616
|
+
|
3617
|
+
#endif
|
3618
|
+
|
3277
3619
|
/**************************************************************************
|
3278
3620
|
* LARGE OBJECT SUPPORT
|
3279
3621
|
**************************************************************************/
|
@@ -3462,7 +3804,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3462
3804
|
return Qnil;
|
3463
3805
|
}
|
3464
3806
|
|
3465
|
-
str =
|
3807
|
+
str = rb_str_new(buffer, ret);
|
3466
3808
|
xfree(buffer);
|
3467
3809
|
|
3468
3810
|
return str;
|
@@ -3566,14 +3908,15 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3566
3908
|
}
|
3567
3909
|
|
3568
3910
|
|
3569
|
-
|
3570
|
-
|
3571
|
-
void
|
3911
|
+
static void
|
3572
3912
|
pgconn_set_internal_encoding_index( VALUE self )
|
3573
3913
|
{
|
3574
|
-
|
3575
|
-
|
3576
|
-
|
3914
|
+
int enc_idx;
|
3915
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
3916
|
+
rb_encoding *enc = pg_conn_enc_get( this->pgconn );
|
3917
|
+
enc_idx = rb_enc_to_index(enc);
|
3918
|
+
if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
|
3919
|
+
this->enc_idx = enc_idx;
|
3577
3920
|
}
|
3578
3921
|
|
3579
3922
|
/*
|
@@ -3616,13 +3959,12 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
3616
3959
|
static VALUE
|
3617
3960
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3618
3961
|
{
|
3619
|
-
VALUE enc_inspect;
|
3620
3962
|
if (NIL_P(enc)) {
|
3621
|
-
|
3963
|
+
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3622
3964
|
return enc;
|
3623
3965
|
}
|
3624
3966
|
else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
|
3625
|
-
|
3967
|
+
pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
3626
3968
|
return enc;
|
3627
3969
|
}
|
3628
3970
|
else {
|
@@ -3637,11 +3979,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3637
3979
|
pgconn_set_internal_encoding_index( self );
|
3638
3980
|
return enc;
|
3639
3981
|
}
|
3640
|
-
|
3641
|
-
enc_inspect = rb_inspect(enc);
|
3642
|
-
rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
|
3643
|
-
|
3644
|
-
return Qnil;
|
3645
3982
|
}
|
3646
3983
|
|
3647
3984
|
|
@@ -3660,42 +3997,55 @@ pgconn_external_encoding(VALUE self)
|
|
3660
3997
|
rb_encoding *enc = NULL;
|
3661
3998
|
const char *pg_encname = NULL;
|
3662
3999
|
|
3663
|
-
/* Use cached value if found */
|
3664
|
-
if ( RTEST(this->external_encoding) ) return this->external_encoding;
|
3665
|
-
|
3666
4000
|
pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
|
3667
4001
|
enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
|
3668
|
-
|
3669
|
-
|
3670
|
-
return this->external_encoding;
|
4002
|
+
return rb_enc_from_encoding( enc );
|
3671
4003
|
}
|
3672
4004
|
|
4005
|
+
/*
|
4006
|
+
* call-seq:
|
4007
|
+
* conn.set_client_encoding( encoding )
|
4008
|
+
*
|
4009
|
+
* Sets the client encoding to the _encoding_ String.
|
4010
|
+
*/
|
4011
|
+
static VALUE
|
4012
|
+
pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
4013
|
+
{
|
4014
|
+
VALUE query_format, query;
|
4015
|
+
|
4016
|
+
Check_Type(encname, T_STRING);
|
4017
|
+
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4018
|
+
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
4019
|
+
|
4020
|
+
pgconn_async_exec(1, &query, self);
|
4021
|
+
pgconn_set_internal_encoding_index( self );
|
4022
|
+
|
4023
|
+
return Qnil;
|
4024
|
+
}
|
3673
4025
|
|
3674
4026
|
static VALUE
|
3675
4027
|
pgconn_set_client_encoding_async1( VALUE args )
|
3676
4028
|
{
|
3677
4029
|
VALUE self = ((VALUE*)args)[0];
|
3678
4030
|
VALUE encname = ((VALUE*)args)[1];
|
3679
|
-
|
3680
|
-
VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
3681
|
-
|
3682
|
-
pgconn_async_exec(1, &query, self);
|
4031
|
+
pgconn_async_set_client_encoding(self, encname);
|
3683
4032
|
return 0;
|
3684
4033
|
}
|
3685
4034
|
|
3686
4035
|
|
3687
4036
|
static VALUE
|
3688
|
-
pgconn_set_client_encoding_async2( VALUE arg )
|
4037
|
+
pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
|
3689
4038
|
{
|
3690
4039
|
UNUSED(arg);
|
4040
|
+
UNUSED(ex);
|
3691
4041
|
return 1;
|
3692
4042
|
}
|
3693
4043
|
|
3694
4044
|
|
3695
4045
|
static VALUE
|
3696
|
-
pgconn_set_client_encoding_async( VALUE self,
|
4046
|
+
pgconn_set_client_encoding_async( VALUE self, VALUE encname )
|
3697
4047
|
{
|
3698
|
-
VALUE args[] = { self,
|
4048
|
+
VALUE args[] = { self, encname };
|
3699
4049
|
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
3700
4050
|
}
|
3701
4051
|
|
@@ -3717,10 +4067,9 @@ pgconn_set_default_encoding( VALUE self )
|
|
3717
4067
|
|
3718
4068
|
if (( enc = rb_default_internal_encoding() )) {
|
3719
4069
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3720
|
-
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
3721
|
-
|
4070
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
4071
|
+
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
3722
4072
|
encname, PQerrorMessage(conn) );
|
3723
|
-
pgconn_set_internal_encoding_index( self );
|
3724
4073
|
return rb_enc_from_encoding( enc );
|
3725
4074
|
} else {
|
3726
4075
|
pgconn_set_internal_encoding_index( self );
|
@@ -3729,8 +4078,6 @@ pgconn_set_default_encoding( VALUE self )
|
|
3729
4078
|
}
|
3730
4079
|
|
3731
4080
|
|
3732
|
-
#endif /* M17N_SUPPORTED */
|
3733
|
-
|
3734
4081
|
/*
|
3735
4082
|
* call-seq:
|
3736
4083
|
* res.type_map_for_queries = typemap
|
@@ -3744,12 +4091,12 @@ static VALUE
|
|
3744
4091
|
pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
3745
4092
|
{
|
3746
4093
|
t_pg_connection *this = pg_get_connection( self );
|
4094
|
+
t_typemap *tm;
|
4095
|
+
UNUSED(tm);
|
4096
|
+
|
4097
|
+
/* Check type of method param */
|
4098
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
3747
4099
|
|
3748
|
-
if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
|
3749
|
-
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
|
3750
|
-
rb_obj_classname( typemap ) );
|
3751
|
-
}
|
3752
|
-
Check_Type(typemap, T_DATA);
|
3753
4100
|
this->type_map_for_queries = typemap;
|
3754
4101
|
|
3755
4102
|
return typemap;
|
@@ -3784,12 +4131,10 @@ static VALUE
|
|
3784
4131
|
pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
3785
4132
|
{
|
3786
4133
|
t_pg_connection *this = pg_get_connection( self );
|
4134
|
+
t_typemap *tm;
|
4135
|
+
UNUSED(tm);
|
3787
4136
|
|
3788
|
-
|
3789
|
-
rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
|
3790
|
-
rb_obj_classname( typemap ) );
|
3791
|
-
}
|
3792
|
-
Check_Type(typemap, T_DATA);
|
4137
|
+
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
3793
4138
|
this->type_map_for_results = typemap;
|
3794
4139
|
|
3795
4140
|
return typemap;
|
@@ -3824,20 +4169,19 @@ pgconn_type_map_for_results_get(VALUE self)
|
|
3824
4169
|
*
|
3825
4170
|
*/
|
3826
4171
|
static VALUE
|
3827
|
-
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE
|
4172
|
+
pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
3828
4173
|
{
|
3829
4174
|
t_pg_connection *this = pg_get_connection( self );
|
3830
4175
|
|
3831
|
-
if(
|
3832
|
-
|
3833
|
-
|
3834
|
-
|
3835
|
-
|
3836
|
-
Check_Type(typemap, T_DATA);
|
4176
|
+
if( encoder != Qnil ){
|
4177
|
+
t_pg_coder *co;
|
4178
|
+
UNUSED(co);
|
4179
|
+
/* Check argument type */
|
4180
|
+
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
3837
4181
|
}
|
3838
|
-
this->encoder_for_put_copy_data =
|
4182
|
+
this->encoder_for_put_copy_data = encoder;
|
3839
4183
|
|
3840
|
-
return
|
4184
|
+
return encoder;
|
3841
4185
|
}
|
3842
4186
|
|
3843
4187
|
/*
|
@@ -3873,20 +4217,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
|
|
3873
4217
|
*
|
3874
4218
|
*/
|
3875
4219
|
static VALUE
|
3876
|
-
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE
|
4220
|
+
pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
3877
4221
|
{
|
3878
4222
|
t_pg_connection *this = pg_get_connection( self );
|
3879
4223
|
|
3880
|
-
if(
|
3881
|
-
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
3885
|
-
Check_Type(typemap, T_DATA);
|
4224
|
+
if( decoder != Qnil ){
|
4225
|
+
t_pg_coder *co;
|
4226
|
+
UNUSED(co);
|
4227
|
+
/* Check argument type */
|
4228
|
+
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
3886
4229
|
}
|
3887
|
-
this->decoder_for_get_copy_data =
|
4230
|
+
this->decoder_for_get_copy_data = decoder;
|
3888
4231
|
|
3889
|
-
return
|
4232
|
+
return decoder;
|
3890
4233
|
}
|
3891
4234
|
|
3892
4235
|
/*
|
@@ -3909,6 +4252,58 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
3909
4252
|
return this->decoder_for_get_copy_data;
|
3910
4253
|
}
|
3911
4254
|
|
4255
|
+
/*
|
4256
|
+
* call-seq:
|
4257
|
+
* conn.field_name_type = Symbol
|
4258
|
+
*
|
4259
|
+
* Set default type of field names of results retrieved by this connection.
|
4260
|
+
* It can be set to one of:
|
4261
|
+
* * +:string+ to use String based field names
|
4262
|
+
* * +:symbol+ to use Symbol based field names
|
4263
|
+
*
|
4264
|
+
* The default is +:string+ .
|
4265
|
+
*
|
4266
|
+
* Settings the type of field names affects only future results.
|
4267
|
+
*
|
4268
|
+
* See further description at PG::Result#field_name_type=
|
4269
|
+
*
|
4270
|
+
*/
|
4271
|
+
static VALUE
|
4272
|
+
pgconn_field_name_type_set(VALUE self, VALUE sym)
|
4273
|
+
{
|
4274
|
+
t_pg_connection *this = pg_get_connection( self );
|
4275
|
+
|
4276
|
+
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4277
|
+
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4278
|
+
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
4279
|
+
else if ( sym == sym_string );
|
4280
|
+
else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
|
4281
|
+
|
4282
|
+
return sym;
|
4283
|
+
}
|
4284
|
+
|
4285
|
+
/*
|
4286
|
+
* call-seq:
|
4287
|
+
* conn.field_name_type -> Symbol
|
4288
|
+
*
|
4289
|
+
* Get type of field names.
|
4290
|
+
*
|
4291
|
+
* See description at #field_name_type=
|
4292
|
+
*/
|
4293
|
+
static VALUE
|
4294
|
+
pgconn_field_name_type_get(VALUE self)
|
4295
|
+
{
|
4296
|
+
t_pg_connection *this = pg_get_connection( self );
|
4297
|
+
|
4298
|
+
if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
|
4299
|
+
return sym_symbol;
|
4300
|
+
} else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
|
4301
|
+
return sym_static_symbol;
|
4302
|
+
} else {
|
4303
|
+
return sym_string;
|
4304
|
+
}
|
4305
|
+
}
|
4306
|
+
|
3912
4307
|
|
3913
4308
|
/*
|
3914
4309
|
* Document-class: PG::Connection
|
@@ -3917,20 +4312,22 @@ void
|
|
3917
4312
|
init_pg_connection()
|
3918
4313
|
{
|
3919
4314
|
s_id_encode = rb_intern("encode");
|
4315
|
+
s_id_autoclose_set = rb_intern("autoclose=");
|
3920
4316
|
sym_type = ID2SYM(rb_intern("type"));
|
3921
4317
|
sym_format = ID2SYM(rb_intern("format"));
|
3922
4318
|
sym_value = ID2SYM(rb_intern("value"));
|
4319
|
+
sym_string = ID2SYM(rb_intern("string"));
|
4320
|
+
sym_symbol = ID2SYM(rb_intern("symbol"));
|
4321
|
+
sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
|
3923
4322
|
|
3924
4323
|
rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
|
4324
|
+
/* Help rdoc to known the Constants module */
|
4325
|
+
/* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
|
3925
4326
|
rb_include_module(rb_cPGconn, rb_mPGconstants);
|
3926
4327
|
|
3927
4328
|
/****** PG::Connection CLASS METHODS ******/
|
3928
4329
|
rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
|
3929
4330
|
|
3930
|
-
SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
|
3931
|
-
SINGLETON_ALIAS(rb_cPGconn, "open", "new");
|
3932
|
-
SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
|
3933
|
-
SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
|
3934
4331
|
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
3935
4332
|
SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
|
3936
4333
|
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
@@ -3939,16 +4336,14 @@ init_pg_connection()
|
|
3939
4336
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
3940
4337
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
3941
4338
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
3942
|
-
|
3943
|
-
rb_define_singleton_method(rb_cPGconn, "
|
3944
|
-
#endif
|
4339
|
+
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
4340
|
+
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
3945
4341
|
|
3946
4342
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
3947
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
3948
4343
|
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
3949
4344
|
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
3950
4345
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
3951
|
-
rb_define_method(rb_cPGconn, "
|
4346
|
+
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
3952
4347
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
3953
4348
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
3954
4349
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
@@ -3960,9 +4355,7 @@ init_pg_connection()
|
|
3960
4355
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
3961
4356
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
3962
4357
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
3963
|
-
#ifdef HAVE_PQCONNINFO
|
3964
4358
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|
3965
|
-
#endif
|
3966
4359
|
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
3967
4360
|
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
3968
4361
|
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
@@ -3971,64 +4364,78 @@ init_pg_connection()
|
|
3971
4364
|
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
3972
4365
|
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
3973
4366
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
3974
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
3975
4367
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
3976
|
-
#endif
|
3977
4368
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4369
|
+
rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
|
3978
4370
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
3979
4371
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
3980
4372
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
3981
4373
|
|
3982
4374
|
/****** PG::Connection INSTANCE METHODS: Command Execution ******/
|
3983
|
-
rb_define_method(rb_cPGconn, "
|
3984
|
-
|
3985
|
-
rb_define_method(rb_cPGconn, "
|
3986
|
-
rb_define_method(rb_cPGconn, "
|
3987
|
-
rb_define_method(rb_cPGconn, "
|
3988
|
-
rb_define_method(rb_cPGconn, "
|
3989
|
-
|
4375
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
|
4376
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
|
4377
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
|
4378
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
|
4379
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
|
4380
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
|
4381
|
+
|
4382
|
+
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
4383
|
+
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
4384
|
+
rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
|
4385
|
+
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
|
4386
|
+
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
|
4387
|
+
rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
|
4388
|
+
|
4389
|
+
rb_define_alias(rb_cPGconn, "async_exec", "exec");
|
4390
|
+
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
4391
|
+
rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
|
4392
|
+
rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
|
4393
|
+
rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
|
4394
|
+
rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
|
4395
|
+
rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
|
4396
|
+
|
3990
4397
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
3991
4398
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
3992
4399
|
rb_define_alias(rb_cPGconn, "escape", "escape_string");
|
3993
|
-
#ifdef HAVE_PQESCAPELITERAL
|
3994
4400
|
rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
|
3995
|
-
#endif
|
3996
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
3997
4401
|
rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
|
3998
|
-
#endif
|
3999
4402
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4000
4403
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4001
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
4002
4404
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
4003
|
-
#endif
|
4004
4405
|
|
4005
4406
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
4006
4407
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
4408
|
+
rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
|
4007
4409
|
rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
|
4008
4410
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4009
4411
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4010
4412
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4011
|
-
rb_define_method(rb_cPGconn, "
|
4413
|
+
rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
|
4012
4414
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
4013
4415
|
rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
|
4014
|
-
rb_define_method(rb_cPGconn, "
|
4015
|
-
rb_define_method(rb_cPGconn, "
|
4016
|
-
|
4017
|
-
rb_define_method(rb_cPGconn, "flush",
|
4416
|
+
rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
|
4417
|
+
rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
|
4418
|
+
rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
|
4419
|
+
rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
|
4420
|
+
rb_define_alias(rb_cPGconn, "async_flush", "flush");
|
4421
|
+
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
4018
4422
|
|
4019
4423
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4020
|
-
rb_define_method(rb_cPGconn, "
|
4424
|
+
rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
|
4021
4425
|
|
4022
4426
|
/****** PG::Connection INSTANCE METHODS: NOTIFY ******/
|
4023
4427
|
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
4024
4428
|
|
4025
4429
|
/****** PG::Connection INSTANCE METHODS: COPY ******/
|
4026
|
-
rb_define_method(rb_cPGconn, "
|
4027
|
-
rb_define_method(rb_cPGconn, "
|
4028
|
-
rb_define_method(rb_cPGconn, "
|
4430
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
|
4431
|
+
rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
|
4432
|
+
rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
|
4029
4433
|
|
4030
4434
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
4031
4435
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4436
|
+
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
4437
|
+
rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
|
4438
|
+
#endif
|
4032
4439
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
4033
4440
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4034
4441
|
|
@@ -4038,16 +4445,21 @@ init_pg_connection()
|
|
4038
4445
|
|
4039
4446
|
/****** PG::Connection INSTANCE METHODS: Other ******/
|
4040
4447
|
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
4041
|
-
rb_define_method(rb_cPGconn, "
|
4448
|
+
rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
|
4449
|
+
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
|
4450
|
+
rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
|
4042
4451
|
rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
|
4043
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
4044
4452
|
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
4453
|
+
rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
|
4045
4454
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
4046
4455
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
4047
4456
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4048
|
-
rb_define_method(rb_cPGconn, "
|
4049
|
-
|
4050
|
-
|
4457
|
+
rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
|
4458
|
+
rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
|
4459
|
+
rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
|
4460
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4461
|
+
rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
|
4462
|
+
#endif
|
4051
4463
|
|
4052
4464
|
#ifdef HAVE_PQSSLATTRIBUTE
|
4053
4465
|
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
@@ -4055,6 +4467,14 @@ init_pg_connection()
|
|
4055
4467
|
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4056
4468
|
#endif
|
4057
4469
|
|
4470
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
4471
|
+
rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
|
4472
|
+
rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
|
4473
|
+
rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
|
4474
|
+
rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
|
4475
|
+
rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
|
4476
|
+
#endif
|
4477
|
+
|
4058
4478
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
4059
4479
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
4060
4480
|
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|
@@ -4083,12 +4503,10 @@ init_pg_connection()
|
|
4083
4503
|
rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
|
4084
4504
|
rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
|
4085
4505
|
|
4086
|
-
#ifdef M17N_SUPPORTED
|
4087
4506
|
rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
|
4088
4507
|
rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
|
4089
4508
|
rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
|
4090
4509
|
rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
|
4091
|
-
#endif /* M17N_SUPPORTED */
|
4092
4510
|
|
4093
4511
|
rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
|
4094
4512
|
rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
|
@@ -4098,5 +4516,7 @@ init_pg_connection()
|
|
4098
4516
|
rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
|
4099
4517
|
rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
|
4100
4518
|
rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
|
4101
|
-
}
|
4102
4519
|
|
4520
|
+
rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
|
4521
|
+
rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
|
4522
|
+
}
|