pg 0.17.1 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/BSDL +2 -2
  4. data/ChangeLog +0 -3506
  5. data/History.rdoc +308 -0
  6. data/Manifest.txt +35 -19
  7. data/README-Windows.rdoc +17 -28
  8. data/README.ja.rdoc +1 -2
  9. data/README.rdoc +113 -14
  10. data/Rakefile +67 -30
  11. data/Rakefile.cross +109 -83
  12. data/ext/errorcodes.def +101 -0
  13. data/ext/errorcodes.rb +1 -1
  14. data/ext/errorcodes.txt +33 -2
  15. data/ext/extconf.rb +55 -58
  16. data/ext/gvl_wrappers.c +4 -0
  17. data/ext/gvl_wrappers.h +27 -39
  18. data/ext/pg.c +262 -130
  19. data/ext/pg.h +266 -54
  20. data/ext/pg_binary_decoder.c +229 -0
  21. data/ext/pg_binary_encoder.c +163 -0
  22. data/ext/pg_coder.c +561 -0
  23. data/ext/pg_connection.c +1689 -990
  24. data/ext/pg_copy_coder.c +599 -0
  25. data/ext/pg_errors.c +6 -0
  26. data/ext/pg_record_coder.c +491 -0
  27. data/ext/pg_result.c +897 -164
  28. data/ext/pg_text_decoder.c +987 -0
  29. data/ext/pg_text_encoder.c +814 -0
  30. data/ext/pg_tuple.c +549 -0
  31. data/ext/pg_type_map.c +166 -0
  32. data/ext/pg_type_map_all_strings.c +116 -0
  33. data/ext/pg_type_map_by_class.c +244 -0
  34. data/ext/pg_type_map_by_column.c +313 -0
  35. data/ext/pg_type_map_by_mri_type.c +284 -0
  36. data/ext/pg_type_map_by_oid.c +356 -0
  37. data/ext/pg_type_map_in_ruby.c +299 -0
  38. data/ext/pg_util.c +149 -0
  39. data/ext/pg_util.h +65 -0
  40. data/lib/pg/basic_type_mapping.rb +522 -0
  41. data/lib/pg/binary_decoder.rb +23 -0
  42. data/lib/pg/coder.rb +104 -0
  43. data/lib/pg/connection.rb +153 -41
  44. data/lib/pg/constants.rb +2 -1
  45. data/lib/pg/exceptions.rb +2 -1
  46. data/lib/pg/result.rb +33 -6
  47. data/lib/pg/text_decoder.rb +46 -0
  48. data/lib/pg/text_encoder.rb +59 -0
  49. data/lib/pg/tuple.rb +30 -0
  50. data/lib/pg/type_map_by_column.rb +16 -0
  51. data/lib/pg.rb +29 -9
  52. data/spec/{lib/helpers.rb → helpers.rb} +151 -64
  53. data/spec/pg/basic_type_mapping_spec.rb +630 -0
  54. data/spec/pg/connection_spec.rb +1180 -477
  55. data/spec/pg/connection_sync_spec.rb +41 -0
  56. data/spec/pg/result_spec.rb +456 -120
  57. data/spec/pg/tuple_spec.rb +333 -0
  58. data/spec/pg/type_map_by_class_spec.rb +138 -0
  59. data/spec/pg/type_map_by_column_spec.rb +226 -0
  60. data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
  61. data/spec/pg/type_map_by_oid_spec.rb +149 -0
  62. data/spec/pg/type_map_in_ruby_spec.rb +164 -0
  63. data/spec/pg/type_map_spec.rb +22 -0
  64. data/spec/pg/type_spec.rb +1123 -0
  65. data/spec/pg_spec.rb +26 -20
  66. data.tar.gz.sig +0 -0
  67. metadata +148 -91
  68. metadata.gz.sig +0 -0
  69. data/sample/array_insert.rb +0 -20
  70. data/sample/async_api.rb +0 -106
  71. data/sample/async_copyto.rb +0 -39
  72. data/sample/async_mixed.rb +0 -56
  73. data/sample/check_conn.rb +0 -21
  74. data/sample/copyfrom.rb +0 -81
  75. data/sample/copyto.rb +0 -19
  76. data/sample/cursor.rb +0 -21
  77. data/sample/disk_usage_report.rb +0 -186
  78. data/sample/issue-119.rb +0 -94
  79. data/sample/losample.rb +0 -69
  80. data/sample/minimal-testcase.rb +0 -17
  81. data/sample/notify_wait.rb +0 -72
  82. data/sample/pg_statistics.rb +0 -294
  83. data/sample/replication_monitor.rb +0 -231
  84. data/sample/test_binary_values.rb +0 -33
  85. data/sample/wal_shipper.rb +0 -434
  86. data/sample/warehouse_partitions.rb +0 -320
data/ext/pg_connection.c CHANGED
@@ -1,91 +1,160 @@
1
1
  /*
2
2
  * pg_connection.c - PG::Connection class extension
3
- * $Id: pg_connection.c,v 97c3ec224be9 2013/12/09 16:34:26 kanis $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
7
7
  #include "pg.h"
8
8
 
9
+ /* Number of bytes that are reserved on the stack for query params. */
10
+ #define QUERYDATA_BUFFER_SIZE 4000
11
+
9
12
 
10
13
  VALUE rb_cPGconn;
14
+ static ID s_id_encode;
15
+ static VALUE sym_type, sym_format, sym_value;
16
+ static VALUE sym_symbol, sym_string, sym_static_symbol;
11
17
 
12
18
  static PQnoticeReceiver default_notice_receiver = NULL;
13
19
  static PQnoticeProcessor default_notice_processor = NULL;
14
20
 
15
- static PGconn *pgconn_check( VALUE );
16
21
  static VALUE pgconn_finish( VALUE );
17
- #ifdef M17N_SUPPORTED
18
22
  static VALUE pgconn_set_default_encoding( VALUE self );
19
- #endif
20
-
21
- #ifndef HAVE_RB_THREAD_FD_SELECT
22
- #define rb_fdset_t fd_set
23
- #define rb_fd_init(f)
24
- #define rb_fd_zero(f) FD_ZERO(f)
25
- #define rb_fd_set(n, f) FD_SET(n, f)
26
- #define rb_fd_term(f)
27
- #define rb_thread_fd_select rb_thread_select
28
- #endif
23
+ static void pgconn_set_internal_encoding_index( VALUE );
29
24
 
30
25
  /*
31
26
  * Global functions
32
27
  */
33
28
 
34
29
  /*
35
- * Fetch the data pointer and check it for sanity.
30
+ * Fetch the PG::Connection object data pointer.
31
+ */
32
+ t_pg_connection *
33
+ pg_get_connection( VALUE self )
34
+ {
35
+ t_pg_connection *this;
36
+ Data_Get_Struct( self, t_pg_connection, this);
37
+
38
+ return this;
39
+ }
40
+
41
+ /*
42
+ * Fetch the PG::Connection object data pointer and check it's
43
+ * PGconn data pointer for sanity.
44
+ */
45
+ static t_pg_connection *
46
+ pg_get_connection_safe( VALUE self )
47
+ {
48
+ t_pg_connection *this;
49
+ Data_Get_Struct( self, t_pg_connection, this);
50
+
51
+ if ( !this->pgconn )
52
+ rb_raise( rb_eConnectionBad, "connection is closed" );
53
+
54
+ return this;
55
+ }
56
+
57
+ /*
58
+ * Fetch the PGconn data pointer and check it for sanity.
59
+ *
60
+ * Note: This function is used externally by the sequel_pg gem,
61
+ * so do changes carefully.
62
+ *
36
63
  */
37
64
  PGconn *
38
65
  pg_get_pgconn( VALUE self )
39
66
  {
40
- PGconn *conn = pgconn_check( self );
67
+ t_pg_connection *this;
68
+ Data_Get_Struct( self, t_pg_connection, this);
41
69
 
42
- if ( !conn )
70
+ if ( !this->pgconn )
43
71
  rb_raise( rb_eConnectionBad, "connection is closed" );
44
72
 
45
- return conn;
73
+ return this->pgconn;
46
74
  }
47
75
 
48
76
 
77
+
49
78
  /*
50
79
  * Close the associated socket IO object if there is one.
51
80
  */
52
- void
81
+ static void
53
82
  pgconn_close_socket_io( VALUE self )
54
83
  {
55
- VALUE socket_io = rb_iv_get( self, "@socket_io" );
84
+ t_pg_connection *this = pg_get_connection( self );
85
+ VALUE socket_io = this->socket_io;
56
86
 
57
87
  if ( RTEST(socket_io) ) {
58
- #if defined(_WIN32) && defined(HAVE_RB_W32_WRAP_IO_HANDLE)
59
- int ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
60
- if( rb_w32_unwrap_io_handle(ruby_sd) ){
88
+ #if defined(_WIN32)
89
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
61
90
  rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
62
91
  }
63
92
  #endif
64
93
  rb_funcall( socket_io, rb_intern("close"), 0 );
65
94
  }
66
95
 
67
- rb_iv_set( self, "@socket_io", Qnil );
96
+ this->socket_io = Qnil;
68
97
  }
69
98
 
70
99
 
71
100
  /*
72
- * Allocation/
101
+ * Create a Ruby Array of Hashes out of a PGconninfoOptions array.
73
102
  */
103
+ static VALUE
104
+ pgconn_make_conninfo_array( const PQconninfoOption *options )
105
+ {
106
+ VALUE ary = rb_ary_new();
107
+ VALUE hash;
108
+ int i = 0;
74
109
 
75
- /*
76
- * Object validity checker. Returns the data pointer.
77
- */
78
- static PGconn *
79
- pgconn_check( VALUE self ) {
110
+ if (!options) return Qnil;
111
+
112
+ for(i = 0; options[i].keyword != NULL; i++) {
113
+ hash = rb_hash_new();
114
+ if(options[i].keyword)
115
+ rb_hash_aset(hash, ID2SYM(rb_intern("keyword")), rb_str_new2(options[i].keyword));
116
+ if(options[i].envvar)
117
+ rb_hash_aset(hash, ID2SYM(rb_intern("envvar")), rb_str_new2(options[i].envvar));
118
+ if(options[i].compiled)
119
+ rb_hash_aset(hash, ID2SYM(rb_intern("compiled")), rb_str_new2(options[i].compiled));
120
+ if(options[i].val)
121
+ rb_hash_aset(hash, ID2SYM(rb_intern("val")), rb_str_new2(options[i].val));
122
+ if(options[i].label)
123
+ rb_hash_aset(hash, ID2SYM(rb_intern("label")), rb_str_new2(options[i].label));
124
+ if(options[i].dispchar)
125
+ rb_hash_aset(hash, ID2SYM(rb_intern("dispchar")), rb_str_new2(options[i].dispchar));
126
+ rb_hash_aset(hash, ID2SYM(rb_intern("dispsize")), INT2NUM(options[i].dispsize));
127
+ rb_ary_push(ary, hash);
128
+ }
129
+
130
+ return ary;
131
+ }
80
132
 
81
- Check_Type( self, T_DATA );
133
+ static const char *pg_cstr_enc(VALUE str, int enc_idx){
134
+ const char *ptr = StringValueCStr(str);
135
+ if( ENCODING_GET(str) == enc_idx ){
136
+ return ptr;
137
+ } else {
138
+ str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
139
+ return StringValueCStr(str);
140
+ }
141
+ }
82
142
 
83
- if ( !rb_obj_is_kind_of(self, rb_cPGconn) ) {
84
- rb_raise( rb_eTypeError, "wrong argument type %s (expected PG::Connection)",
85
- rb_obj_classname( self ) );
86
- }
87
143
 
88
- return DATA_PTR( self );
144
+ /*
145
+ * GC Mark function
146
+ */
147
+ static void
148
+ pgconn_gc_mark( t_pg_connection *this )
149
+ {
150
+ rb_gc_mark( this->socket_io );
151
+ rb_gc_mark( this->notice_receiver );
152
+ rb_gc_mark( this->notice_processor );
153
+ rb_gc_mark( this->type_map_for_queries );
154
+ rb_gc_mark( this->type_map_for_results );
155
+ rb_gc_mark( this->trace_stream );
156
+ rb_gc_mark( this->encoder_for_put_copy_data );
157
+ rb_gc_mark( this->decoder_for_get_copy_data );
89
158
  }
90
159
 
91
160
 
@@ -93,10 +162,16 @@ pgconn_check( VALUE self ) {
93
162
  * GC Free function
94
163
  */
95
164
  static void
96
- pgconn_gc_free( PGconn *conn )
165
+ pgconn_gc_free( t_pg_connection *this )
97
166
  {
98
- if (conn != NULL)
99
- PQfinish( conn );
167
+ #if defined(_WIN32)
168
+ if ( RTEST(this->socket_io) )
169
+ rb_w32_unwrap_io_handle( this->ruby_sd );
170
+ #endif
171
+ if (this->pgconn != NULL)
172
+ PQfinish( this->pgconn );
173
+
174
+ xfree(this);
100
175
  }
101
176
 
102
177
 
@@ -113,10 +188,19 @@ pgconn_gc_free( PGconn *conn )
113
188
  static VALUE
114
189
  pgconn_s_allocate( VALUE klass )
115
190
  {
116
- VALUE self = Data_Wrap_Struct( klass, NULL, pgconn_gc_free, NULL );
117
- rb_iv_set( self, "@socket_io", Qnil );
118
- rb_iv_set( self, "@notice_receiver", Qnil);
119
- rb_iv_set( self, "@notice_processor", Qnil);
191
+ t_pg_connection *this;
192
+ VALUE self = Data_Make_Struct( klass, t_pg_connection, pgconn_gc_mark, pgconn_gc_free, this );
193
+
194
+ this->pgconn = NULL;
195
+ this->socket_io = Qnil;
196
+ this->notice_receiver = Qnil;
197
+ this->notice_processor = Qnil;
198
+ this->type_map_for_queries = pg_typemap_all_strings;
199
+ this->type_map_for_results = pg_typemap_all_strings;
200
+ this->encoder_for_put_copy_data = Qnil;
201
+ this->decoder_for_get_copy_data = Qnil;
202
+ this->trace_stream = Qnil;
203
+
120
204
  return self;
121
205
  }
122
206
 
@@ -132,32 +216,27 @@ pgconn_s_allocate( VALUE klass )
132
216
  *
133
217
  * Create a connection to the specified server.
134
218
  *
219
+ * +connection_hash+ must be a ruby Hash with connection parameters.
220
+ * See the {list of valid parameters}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS] in the PostgreSQL documentation.
221
+ *
222
+ * There are two accepted formats for +connection_string+: plain <code>keyword = value</code> strings and URIs.
223
+ * See the documentation of {connection strings}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING].
224
+ *
225
+ * The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
135
226
  * [+host+]
136
227
  * server hostname
137
- * [+hostaddr+]
138
- * server address (avoids hostname lookup, overrides +host+)
139
228
  * [+port+]
140
229
  * server port number
230
+ * [+options+]
231
+ * backend options
232
+ * [+tty+]
233
+ * (ignored in newer versions of PostgreSQL)
141
234
  * [+dbname+]
142
235
  * connecting database name
143
236
  * [+user+]
144
237
  * login user name
145
238
  * [+password+]
146
239
  * login password
147
- * [+connect_timeout+]
148
- * maximum time to wait for connection to succeed
149
- * [+options+]
150
- * backend options
151
- * [+tty+]
152
- * (ignored in newer versions of PostgreSQL)
153
- * [+sslmode+]
154
- * (disable|allow|prefer|require)
155
- * [+krbsrvname+]
156
- * kerberos service name
157
- * [+gsslib+]
158
- * GSS library to use for GSSAPI authentication
159
- * [+service+]
160
- * service name to use for additional parameters
161
240
  *
162
241
  * Examples:
163
242
  *
@@ -173,7 +252,7 @@ pgconn_s_allocate( VALUE klass )
173
252
  * # As an Array
174
253
  * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
175
254
  *
176
- * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
255
+ * If the Ruby default internal encoding is set (i.e., <code>Encoding.default_internal != nil</code>), the
177
256
  * connection will have its +client_encoding+ set accordingly.
178
257
  *
179
258
  * Raises a PG::Error if the connection fails.
@@ -181,28 +260,24 @@ pgconn_s_allocate( VALUE klass )
181
260
  static VALUE
182
261
  pgconn_init(int argc, VALUE *argv, VALUE self)
183
262
  {
184
- PGconn *conn = NULL;
263
+ t_pg_connection *this;
185
264
  VALUE conninfo;
186
265
  VALUE error;
187
266
 
267
+ this = pg_get_connection( self );
188
268
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
189
- conn = gvl_PQconnectdb(StringValuePtr(conninfo));
269
+ this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
190
270
 
191
- if(conn == NULL)
271
+ if(this->pgconn == NULL)
192
272
  rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
193
273
 
194
- Check_Type(self, T_DATA);
195
- DATA_PTR(self) = conn;
196
-
197
- if (PQstatus(conn) == CONNECTION_BAD) {
198
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
274
+ if (PQstatus(this->pgconn) == CONNECTION_BAD) {
275
+ error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
199
276
  rb_iv_set(error, "@connection", self);
200
277
  rb_exc_raise(error);
201
278
  }
202
279
 
203
- #ifdef M17N_SUPPORTED
204
280
  pgconn_set_default_encoding( self );
205
- #endif
206
281
 
207
282
  if (rb_block_given_p()) {
208
283
  return rb_ensure(rb_yield, self, pgconn_finish, self);
@@ -216,40 +291,40 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
216
291
  * PG::Connection.connect_start(connection_string) -> conn
217
292
  * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
218
293
  *
219
- * This is an asynchronous version of PG::Connection.connect().
294
+ * This is an asynchronous version of PG::Connection.new.
220
295
  *
221
296
  * Use #connect_poll to poll the status of the connection.
222
297
  *
223
298
  * NOTE: this does *not* set the connection's +client_encoding+ for you if
224
- * Encoding.default_internal is set. To set it after the connection is established,
299
+ * +Encoding.default_internal+ is set. To set it after the connection is established,
225
300
  * call #internal_encoding=. You can also set it automatically by setting
226
- * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
301
+ * <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
302
+ *
303
+ * See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
227
304
  *
228
305
  */
229
306
  static VALUE
230
307
  pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
231
308
  {
232
- PGconn *conn = NULL;
233
309
  VALUE rb_conn;
234
310
  VALUE conninfo;
235
311
  VALUE error;
312
+ t_pg_connection *this;
236
313
 
237
314
  /*
238
315
  * PG::Connection.connect_start must act as both alloc() and initialize()
239
316
  * because it is not invoked by calling new().
240
317
  */
241
318
  rb_conn = pgconn_s_allocate( klass );
319
+ this = pg_get_connection( rb_conn );
242
320
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
243
- conn = gvl_PQconnectStart( StringValuePtr(conninfo) );
321
+ this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
244
322
 
245
- if( conn == NULL )
323
+ if( this->pgconn == NULL )
246
324
  rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
247
325
 
248
- Check_Type(rb_conn, T_DATA);
249
- DATA_PTR(rb_conn) = conn;
250
-
251
- if ( PQstatus(conn) == CONNECTION_BAD ) {
252
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
326
+ if ( PQstatus(this->pgconn) == CONNECTION_BAD ) {
327
+ error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
253
328
  rb_iv_set(error, "@connection", rb_conn);
254
329
  rb_exc_raise(error);
255
330
  }
@@ -260,15 +335,16 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
260
335
  return rb_conn;
261
336
  }
262
337
 
263
- #ifdef HAVE_PQPING
264
338
  /*
265
339
  * call-seq:
266
- * PG::Connection.ping(connection_hash) -> Fixnum
267
- * PG::Connection.ping(connection_string) -> Fixnum
268
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Fixnum
340
+ * PG::Connection.ping(connection_hash) -> Integer
341
+ * PG::Connection.ping(connection_string) -> Integer
342
+ * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
269
343
  *
270
344
  * Check server status.
271
345
  *
346
+ * See PG::Connection.new for a description of the parameters.
347
+ *
272
348
  * Returns one of:
273
349
  * [+PQPING_OK+]
274
350
  * server is accepting connections
@@ -286,15 +362,14 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
286
362
  VALUE conninfo;
287
363
 
288
364
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
289
- ping = PQping( StringValuePtr(conninfo) );
365
+ ping = PQping( StringValueCStr(conninfo) );
290
366
 
291
367
  return INT2FIX((int)ping);
292
368
  }
293
- #endif
294
369
 
295
370
 
296
371
  /*
297
- * Document-method: conndefaults
372
+ * Document-method: PG::Connection.conndefaults
298
373
  *
299
374
  * call-seq:
300
375
  * PG::Connection.conndefaults() -> Array
@@ -319,44 +394,72 @@ static VALUE
319
394
  pgconn_s_conndefaults(VALUE self)
320
395
  {
321
396
  PQconninfoOption *options = PQconndefaults();
322
- VALUE ary = rb_ary_new();
323
- VALUE hash;
324
- int i = 0;
397
+ VALUE array = pgconn_make_conninfo_array( options );
398
+
399
+ PQconninfoFree(options);
325
400
 
326
401
  UNUSED( self );
327
402
 
328
- for(i = 0; options[i].keyword != NULL; i++) {
329
- hash = rb_hash_new();
330
- if(options[i].keyword)
331
- rb_hash_aset(hash, ID2SYM(rb_intern("keyword")), rb_str_new2(options[i].keyword));
332
- if(options[i].envvar)
333
- rb_hash_aset(hash, ID2SYM(rb_intern("envvar")), rb_str_new2(options[i].envvar));
334
- if(options[i].compiled)
335
- rb_hash_aset(hash, ID2SYM(rb_intern("compiled")), rb_str_new2(options[i].compiled));
336
- if(options[i].val)
337
- rb_hash_aset(hash, ID2SYM(rb_intern("val")), rb_str_new2(options[i].val));
338
- if(options[i].label)
339
- rb_hash_aset(hash, ID2SYM(rb_intern("label")), rb_str_new2(options[i].label));
340
- if(options[i].dispchar)
341
- rb_hash_aset(hash, ID2SYM(rb_intern("dispchar")), rb_str_new2(options[i].dispchar));
342
- rb_hash_aset(hash, ID2SYM(rb_intern("dispsize")), INT2NUM(options[i].dispsize));
343
- rb_ary_push(ary, hash);
403
+ return array;
404
+ }
405
+
406
+
407
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
408
+ /*
409
+ * call-seq:
410
+ * conn.encrypt_password( password, username, algorithm=nil ) -> String
411
+ *
412
+ * This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
413
+ * It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on.
414
+ * Instead, use this function to convert the password to encrypted form before it is sent.
415
+ *
416
+ * The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
417
+ * +algorithm+ specifies the encryption algorithm to use to encrypt the password.
418
+ * Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions).
419
+ * Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
420
+ * If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
421
+ * That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
422
+ * If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm.
423
+ *
424
+ * Return value is the encrypted password.
425
+ * The caller can assume the string doesn't contain any special characters that would require escaping.
426
+ *
427
+ * Available since PostgreSQL-10.
428
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN].
429
+ */
430
+ static VALUE
431
+ pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
432
+ {
433
+ char *encrypted = NULL;
434
+ VALUE rval = Qnil;
435
+ VALUE password, username, algorithm;
436
+ PGconn *conn = pg_get_pgconn(self);
437
+
438
+ rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
439
+
440
+ Check_Type(password, T_STRING);
441
+ Check_Type(username, T_STRING);
442
+
443
+ encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
444
+ if ( encrypted ) {
445
+ rval = rb_str_new2( encrypted );
446
+ PQfreemem( encrypted );
447
+ } else {
448
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
344
449
  }
345
- PQconninfoFree(options);
346
- return ary;
450
+
451
+ return rval;
347
452
  }
453
+ #endif
348
454
 
349
455
 
350
456
  /*
351
457
  * call-seq:
352
458
  * PG::Connection.encrypt_password( password, username ) -> String
353
459
  *
354
- * This function is intended to be used by client applications that
355
- * send commands like: +ALTER USER joe PASSWORD 'pwd'+.
356
- * The arguments are the cleartext password, and the SQL name
357
- * of the user it is for.
460
+ * This is an older, deprecated version of #encrypt_password.
461
+ * The difference is that this function always uses +md5+ as the encryption algorithm.
358
462
  *
359
- * Return value is the encrypted password.
360
463
  */
361
464
  static VALUE
362
465
  pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
@@ -369,13 +472,10 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
369
472
  Check_Type(password, T_STRING);
370
473
  Check_Type(username, T_STRING);
371
474
 
372
- encrypted = PQencryptPassword(StringValuePtr(password), StringValuePtr(username));
475
+ encrypted = PQencryptPassword(StringValueCStr(password), StringValueCStr(username));
373
476
  rval = rb_str_new2( encrypted );
374
477
  PQfreemem( encrypted );
375
478
 
376
- OBJ_INFECT( rval, password );
377
- OBJ_INFECT( rval, username );
378
-
379
479
  return rval;
380
480
  }
381
481
 
@@ -386,7 +486,7 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
386
486
 
387
487
  /*
388
488
  * call-seq:
389
- * conn.connect_poll() -> Fixnum
489
+ * conn.connect_poll() -> Integer
390
490
  *
391
491
  * Returns one of:
392
492
  * [+PGRES_POLLING_READING+]
@@ -435,9 +535,11 @@ pgconn_connect_poll(VALUE self)
435
535
  static VALUE
436
536
  pgconn_finish( VALUE self )
437
537
  {
538
+ t_pg_connection *this = pg_get_connection_safe( self );
539
+
438
540
  pgconn_close_socket_io( self );
439
- PQfinish( pg_get_pgconn(self) );
440
- DATA_PTR( self ) = NULL;
541
+ PQfinish( this->pgconn );
542
+ this->pgconn = NULL;
441
543
  return Qnil;
442
544
  }
443
545
 
@@ -451,7 +553,8 @@ pgconn_finish( VALUE self )
451
553
  static VALUE
452
554
  pgconn_finished_p( VALUE self )
453
555
  {
454
- if ( DATA_PTR(self) ) return Qfalse;
556
+ t_pg_connection *this = pg_get_connection( self );
557
+ if ( this->pgconn ) return Qfalse;
455
558
  return Qtrue;
456
559
  }
457
560
 
@@ -492,7 +595,7 @@ pgconn_reset_start(VALUE self)
492
595
 
493
596
  /*
494
597
  * call-seq:
495
- * conn.reset_poll -> Fixnum
598
+ * conn.reset_poll -> Integer
496
599
  *
497
600
  * Checks the status of a connection reset operation.
498
601
  * See #connect_start and #connect_poll for
@@ -518,7 +621,7 @@ pgconn_db(VALUE self)
518
621
  {
519
622
  char *db = PQdb(pg_get_pgconn(self));
520
623
  if (!db) return Qnil;
521
- return rb_tainted_str_new2(db);
624
+ return rb_str_new2(db);
522
625
  }
523
626
 
524
627
  /*
@@ -532,21 +635,21 @@ pgconn_user(VALUE self)
532
635
  {
533
636
  char *user = PQuser(pg_get_pgconn(self));
534
637
  if (!user) return Qnil;
535
- return rb_tainted_str_new2(user);
638
+ return rb_str_new2(user);
536
639
  }
537
640
 
538
641
  /*
539
642
  * call-seq:
540
643
  * conn.pass()
541
644
  *
542
- * Returns the authenticated user name.
645
+ * Returns the authenticated password.
543
646
  */
544
647
  static VALUE
545
648
  pgconn_pass(VALUE self)
546
649
  {
547
650
  char *user = PQpass(pg_get_pgconn(self));
548
651
  if (!user) return Qnil;
549
- return rb_tainted_str_new2(user);
652
+ return rb_str_new2(user);
550
653
  }
551
654
 
552
655
  /*
@@ -560,7 +663,7 @@ pgconn_host(VALUE self)
560
663
  {
561
664
  char *host = PQhost(pg_get_pgconn(self));
562
665
  if (!host) return Qnil;
563
- return rb_tainted_str_new2(host);
666
+ return rb_str_new2(host);
564
667
  }
565
668
 
566
669
  /*
@@ -587,7 +690,7 @@ pgconn_tty(VALUE self)
587
690
  {
588
691
  char *tty = PQtty(pg_get_pgconn(self));
589
692
  if (!tty) return Qnil;
590
- return rb_tainted_str_new2(tty);
693
+ return rb_str_new2(tty);
591
694
  }
592
695
 
593
696
  /*
@@ -601,8 +704,32 @@ pgconn_options(VALUE self)
601
704
  {
602
705
  char *options = PQoptions(pg_get_pgconn(self));
603
706
  if (!options) return Qnil;
604
- return rb_tainted_str_new2(options);
707
+ return rb_str_new2(options);
708
+ }
709
+
710
+
711
+ #ifdef HAVE_PQCONNINFO
712
+ /*
713
+ * call-seq:
714
+ * conn.conninfo -> hash
715
+ *
716
+ * Returns the connection options used by a live connection.
717
+ *
718
+ * Available since PostgreSQL-9.3
719
+ */
720
+ static VALUE
721
+ pgconn_conninfo( VALUE self )
722
+ {
723
+ PGconn *conn = pg_get_pgconn(self);
724
+ PQconninfoOption *options = PQconninfo( conn );
725
+ VALUE array = pgconn_make_conninfo_array( options );
726
+
727
+ PQconninfoFree(options);
728
+
729
+ return array;
605
730
  }
731
+ #endif
732
+
606
733
 
607
734
  /*
608
735
  * call-seq:
@@ -654,11 +781,11 @@ pgconn_transaction_status(VALUE self)
654
781
  static VALUE
655
782
  pgconn_parameter_status(VALUE self, VALUE param_name)
656
783
  {
657
- const char *ret = PQparameterStatus(pg_get_pgconn(self), StringValuePtr(param_name));
784
+ const char *ret = PQparameterStatus(pg_get_pgconn(self), StringValueCStr(param_name));
658
785
  if(ret == NULL)
659
786
  return Qnil;
660
787
  else
661
- return rb_tainted_str_new2(ret);
788
+ return rb_str_new2(ret);
662
789
  }
663
790
 
664
791
  /*
@@ -703,12 +830,14 @@ pgconn_error_message(VALUE self)
703
830
  {
704
831
  char *error = PQerrorMessage(pg_get_pgconn(self));
705
832
  if (!error) return Qnil;
706
- return rb_tainted_str_new2(error);
833
+ return rb_str_new2(error);
707
834
  }
708
835
 
709
836
  /*
710
837
  * call-seq:
711
- * conn.socket() -> Fixnum
838
+ * conn.socket() -> Integer
839
+ *
840
+ * This method is deprecated. Please use the more portable method #socket_io .
712
841
  *
713
842
  * Returns the socket's file descriptor for this connection.
714
843
  * <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
@@ -718,34 +847,31 @@ pgconn_error_message(VALUE self)
718
847
  * creates an IO that's associated with the connection object itself,
719
848
  * and so won't go out of scope until the connection does.
720
849
  *
721
- * *Note:* On Windows the file descriptor is not really usable,
850
+ * *Note:* On Windows the file descriptor is not usable,
722
851
  * since it can not be used to build a Ruby IO object.
723
852
  */
724
853
  static VALUE
725
854
  pgconn_socket(VALUE self)
726
855
  {
727
856
  int sd;
857
+ pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
858
+
728
859
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
729
860
  rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
730
861
  return INT2NUM(sd);
731
862
  }
732
863
 
733
-
734
- #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
735
-
736
864
  /*
737
865
  * call-seq:
738
866
  * conn.socket_io() -> IO
739
867
  *
740
- * Fetch a memoized IO object created from the Connection's underlying socket.
868
+ * Fetch a memorized IO object created from the Connection's underlying socket.
741
869
  * This object can be used for IO.select to wait for events while running
742
870
  * asynchronous API calls.
743
871
  *
744
872
  * Using this instead of #socket avoids the problem of the underlying connection
745
873
  * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
746
- * goes out of scope.
747
- *
748
- * This method can also be used on Windows but requires Ruby-2.0+.
874
+ * goes out of scope. In contrast to #socket, it also works on Windows.
749
875
  */
750
876
  static VALUE
751
877
  pgconn_socket_io(VALUE self)
@@ -753,36 +879,34 @@ pgconn_socket_io(VALUE self)
753
879
  int sd;
754
880
  int ruby_sd;
755
881
  ID id_autoclose = rb_intern("autoclose=");
756
- VALUE socket_io = rb_iv_get( self, "@socket_io" );
882
+ t_pg_connection *this = pg_get_connection_safe( self );
883
+ VALUE socket_io = this->socket_io;
757
884
 
758
885
  if ( !RTEST(socket_io) ) {
759
- if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
886
+ if( (sd = PQsocket(this->pgconn)) < 0)
760
887
  rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
761
888
 
762
889
  #ifdef _WIN32
763
890
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
891
+ this->ruby_sd = ruby_sd;
764
892
  #else
765
893
  ruby_sd = sd;
766
894
  #endif
767
895
 
768
896
  socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
769
897
 
770
- /* Disable autoclose feature, when supported */
771
- if( rb_respond_to(socket_io, id_autoclose) ){
772
- rb_funcall( socket_io, id_autoclose, 1, Qfalse );
773
- }
898
+ /* Disable autoclose feature */
899
+ rb_funcall( socket_io, id_autoclose, 1, Qfalse );
774
900
 
775
- rb_iv_set( self, "@socket_io", socket_io );
901
+ this->socket_io = socket_io;
776
902
  }
777
903
 
778
904
  return socket_io;
779
905
  }
780
906
 
781
- #endif
782
-
783
907
  /*
784
908
  * call-seq:
785
- * conn.backend_pid() -> Fixnum
909
+ * conn.backend_pid() -> Integer
786
910
  *
787
911
  * Returns the process ID of the backend server
788
912
  * process for this connection.
@@ -828,40 +952,31 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
828
952
 
829
953
  /*
830
954
  * call-seq:
831
- * conn.exec(sql) -> PG::Result
832
- * conn.exec(sql) {|pg_result| block }
833
- *
834
- * Sends SQL query request specified by _sql_ to PostgreSQL.
835
- * Returns a PG::Result instance on success.
836
- * On failure, it raises a PG::Error.
955
+ * conn.sync_exec(sql) -> PG::Result
956
+ * conn.sync_exec(sql) {|pg_result| block }
837
957
  *
838
- * For backward compatibility, if you pass more than one parameter to this method,
839
- * it will call #exec_params for you. New code should explicitly use #exec_params if
840
- * argument placeholders are used.
958
+ * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
959
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
841
960
  *
842
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
843
- * and the PG::Result object will automatically be cleared when the block terminates.
844
- * In this instance, <code>conn.exec</code> returns the value of the block.
961
+ * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
962
+ * However #async_exec has two advantages:
845
963
  *
846
- * #exec is implemented on the synchronous command processing API of libpq, whereas
847
- * #async_exec is implemented on the asynchronous API.
848
- * #exec is somewhat faster that #async_exec, but blocks any signals to be processed until
849
- * the query is finished. This is most notably visible by a delayed reaction to Control+C.
850
- * Both methods ensure that other threads can process while waiting for the server to
851
- * complete the request.
964
+ * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
965
+ * 2. Ruby VM gets notified about IO blocked operations.
966
+ * It can therefore schedule things like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
852
967
  */
853
968
  static VALUE
854
969
  pgconn_exec(int argc, VALUE *argv, VALUE self)
855
970
  {
856
- PGconn *conn = pg_get_pgconn(self);
971
+ t_pg_connection *this = pg_get_connection_safe( self );
857
972
  PGresult *result = NULL;
858
973
  VALUE rb_pgresult;
859
974
 
860
- /* If called with no parameters, use PQexec */
861
- if ( argc == 1 ) {
862
- Check_Type(argv[0], T_STRING);
975
+ /* If called with no or nil parameters, use PQexec for compatibility */
976
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
977
+ VALUE query_str = argv[0];
863
978
 
864
- result = gvl_PQexec(conn, StringValuePtr(argv[0]));
979
+ result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
865
980
  rb_pgresult = pg_new_result(result, self);
866
981
  pg_result_check(rb_pgresult);
867
982
  if (rb_block_given_p()) {
@@ -869,157 +984,302 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
869
984
  }
870
985
  return rb_pgresult;
871
986
  }
987
+ pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
872
988
 
873
989
  /* Otherwise, just call #exec_params instead for backward-compatibility */
874
- else {
875
- return pgconn_exec_params( argc, argv, self );
876
- }
990
+ return pgconn_exec_params( argc, argv, self );
877
991
 
878
992
  }
879
993
 
880
994
 
881
- /*
882
- * call-seq:
883
- * conn.exec_params(sql, params[, result_format ] ) -> PG::Result
884
- * conn.exec_params(sql, params[, result_format ] ) {|pg_result| block }
885
- *
886
- * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
887
- * for parameters.
888
- *
889
- * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
890
- *
891
- * +params+ is an array of the bind parameters for the SQL query.
892
- * Each element of the +params+ array may be either:
893
- * a hash of the form:
894
- * {:value => String (value of bind parameter)
895
- * :type => Fixnum (oid of type of bind parameter)
896
- * :format => Fixnum (0 for text, 1 for binary)
897
- * }
898
- * or, it may be a String. If it is a string, that is equivalent to the hash:
899
- * { :value => <string value>, :type => 0, :format => 0 }
900
- *
901
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
902
- * inside the SQL query. The 0th element of the +params+ array is bound
903
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
904
- *
905
- * If the types are not specified, they will be inferred by PostgreSQL.
906
- * Instead of specifying type oids, it's recommended to simply add
907
- * explicit casts in the query to ensure that the right type is used.
908
- *
909
- * For example: "SELECT $1::int"
910
- *
911
- * The optional +result_format+ should be 0 for text results, 1
912
- * for binary.
913
- *
914
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
915
- * and the PG::Result object will automatically be cleared when the block terminates.
916
- * In this instance, <code>conn.exec</code> returns the value of the block.
917
- */
918
- static VALUE
919
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
920
- {
921
- PGconn *conn = pg_get_pgconn(self);
922
- PGresult *result = NULL;
923
- VALUE rb_pgresult;
924
- VALUE command, params, in_res_fmt;
925
- VALUE param, param_type, param_value, param_format;
926
- VALUE param_value_tmp;
927
- VALUE sym_type, sym_value, sym_format;
928
- VALUE gc_array;
929
- int i=0;
930
- int nParams;
931
- Oid *paramTypes;
932
- char ** paramValues;
933
- int *paramLengths;
934
- int *paramFormats;
935
- int resultFormat;
995
+ struct linked_typecast_data {
996
+ struct linked_typecast_data *next;
997
+ char data[0];
998
+ };
936
999
 
937
- rb_scan_args(argc, argv, "12", &command, &params, &in_res_fmt);
1000
+ /* This struct is allocated on the stack for all query execution functions. */
1001
+ struct query_params_data {
938
1002
 
939
1003
  /*
940
- * Handle the edge-case where the caller is coming from #exec, but passed an explict +nil+
941
- * for the second parameter.
1004
+ * Filled by caller
942
1005
  */
943
- if ( NIL_P(params) ) {
944
- return pgconn_exec( 1, argv, self );
945
- }
946
1006
 
947
- Check_Type(params, T_ARRAY);
1007
+ /* The character encoding index of the connection. Any strings
1008
+ * given as query parameters are converted to this encoding.
1009
+ */
1010
+ int enc_idx;
1011
+ /* Is the query function to execute one with types array? */
1012
+ int with_types;
1013
+ /* Array of query params from user space */
1014
+ VALUE params;
1015
+ /* The typemap given from user space */
1016
+ VALUE typemap;
948
1017
 
949
- if ( NIL_P(in_res_fmt) ) {
950
- resultFormat = 0;
951
- }
952
- else {
953
- resultFormat = NUM2INT(in_res_fmt);
954
- }
1018
+ /*
1019
+ * Filled by alloc_query_params()
1020
+ */
955
1021
 
956
- gc_array = rb_ary_new();
957
- rb_gc_register_address(&gc_array);
1022
+ /* Wraps the pointer of allocated memory, if function parameters dont't
1023
+ * fit in the memory_pool below.
1024
+ */
1025
+ VALUE heap_pool;
958
1026
 
959
- sym_type = ID2SYM(rb_intern("type"));
960
- sym_value = ID2SYM(rb_intern("value"));
961
- sym_format = ID2SYM(rb_intern("format"));
962
- nParams = (int)RARRAY_LEN(params);
963
- paramTypes = ALLOC_N(Oid, nParams);
964
- paramValues = ALLOC_N(char *, nParams);
965
- paramLengths = ALLOC_N(int, nParams);
966
- paramFormats = ALLOC_N(int, nParams);
967
-
968
- for ( i = 0; i < nParams; i++ ) {
969
- param = rb_ary_entry(params, i);
970
- if (TYPE(param) == T_HASH) {
971
- param_type = rb_hash_aref(param, sym_type);
972
- param_value_tmp = rb_hash_aref(param, sym_value);
973
- if(param_value_tmp == Qnil)
974
- param_value = param_value_tmp;
975
- else
976
- param_value = rb_obj_as_string(param_value_tmp);
977
- param_format = rb_hash_aref(param, sym_format);
978
- }
979
- else {
980
- param_type = Qnil;
981
- if(param == Qnil)
982
- param_value = param;
983
- else
984
- param_value = rb_obj_as_string(param);
985
- param_format = Qnil;
986
- }
1027
+ /* Pointer to the value string pointers (either within memory_pool or heap_pool).
1028
+ * The value strings itself are either directly within RString memory or,
1029
+ * in case of type casted values, within memory_pool or typecast_heap_chain.
1030
+ */
1031
+ char **values;
1032
+ /* Pointer to the param lengths (either within memory_pool or heap_pool) */
1033
+ int *lengths;
1034
+ /* Pointer to the format codes (either within memory_pool or heap_pool) */
1035
+ int *formats;
1036
+ /* Pointer to the OID types (either within memory_pool or heap_pool) */
1037
+ Oid *types;
1038
+
1039
+ /* This array takes the string values for the timeframe of the query,
1040
+ * if param value convertion is required
1041
+ */
1042
+ VALUE gc_array;
987
1043
 
988
- if(param_type == Qnil)
989
- paramTypes[i] = 0;
990
- else
991
- paramTypes[i] = NUM2INT(param_type);
1044
+ /* Wraps a single linked list of allocated memory chunks for type casted params.
1045
+ * Used when the memory_pool is to small.
1046
+ */
1047
+ VALUE typecast_heap_chain;
992
1048
 
993
- if(param_value == Qnil) {
994
- paramValues[i] = NULL;
995
- paramLengths[i] = 0;
996
- }
997
- else {
998
- Check_Type(param_value, T_STRING);
999
- /* make sure param_value doesn't get freed by the GC */
1000
- rb_ary_push(gc_array, param_value);
1001
- paramValues[i] = StringValuePtr(param_value);
1002
- paramLengths[i] = (int)RSTRING_LEN(param_value);
1003
- }
1049
+ /* This memory pool is used to place above query function parameters on it. */
1050
+ char memory_pool[QUERYDATA_BUFFER_SIZE];
1051
+ };
1004
1052
 
1005
- if(param_format == Qnil)
1006
- paramFormats[i] = 0;
1007
- else
1008
- paramFormats[i] = NUM2INT(param_format);
1053
+ static void
1054
+ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1055
+ {
1056
+ while(chain_entry){
1057
+ struct linked_typecast_data *next = chain_entry->next;
1058
+ xfree(chain_entry);
1059
+ chain_entry = next;
1009
1060
  }
1061
+ }
1010
1062
 
1011
- result = gvl_PQexecParams(conn, StringValuePtr(command), nParams, paramTypes,
1012
- (const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
1063
+ static char *
1064
+ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1065
+ {
1066
+ /* Allocate a new memory chunk from heap */
1067
+ struct linked_typecast_data *allocated =
1068
+ (struct linked_typecast_data *)xmalloc(sizeof(struct linked_typecast_data) + len);
1069
+
1070
+ /* Did we already wrap a memory chain per T_DATA object? */
1071
+ if( NIL_P( *typecast_heap_chain ) ){
1072
+ /* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
1073
+ *typecast_heap_chain = Data_Wrap_Struct( rb_cObject, NULL, free_typecast_heap_chain, allocated );
1074
+ allocated->next = NULL;
1075
+ } else {
1076
+ /* Append to the chain */
1077
+ allocated->next = DATA_PTR( *typecast_heap_chain );
1078
+ DATA_PTR( *typecast_heap_chain ) = allocated;
1079
+ }
1013
1080
 
1014
- rb_gc_unregister_address(&gc_array);
1081
+ return &allocated->data[0];
1082
+ }
1015
1083
 
1016
- xfree(paramTypes);
1017
- xfree(paramValues);
1018
- xfree(paramLengths);
1019
- xfree(paramFormats);
1020
1084
 
1021
- rb_pgresult = pg_new_result(result, self);
1022
- pg_result_check(rb_pgresult);
1085
+ static int
1086
+ alloc_query_params(struct query_params_data *paramsData)
1087
+ {
1088
+ VALUE param_value;
1089
+ t_typemap *p_typemap;
1090
+ int nParams;
1091
+ int i=0;
1092
+ t_pg_coder *conv;
1093
+ unsigned int required_pool_size;
1094
+ char *memory_pool;
1095
+
1096
+ Check_Type(paramsData->params, T_ARRAY);
1097
+
1098
+ p_typemap = DATA_PTR( paramsData->typemap );
1099
+ p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
1100
+
1101
+ paramsData->heap_pool = Qnil;
1102
+ paramsData->typecast_heap_chain = Qnil;
1103
+ paramsData->gc_array = Qnil;
1104
+
1105
+ nParams = (int)RARRAY_LEN(paramsData->params);
1106
+
1107
+ required_pool_size = nParams * (
1108
+ sizeof(char *) +
1109
+ sizeof(int) +
1110
+ sizeof(int) +
1111
+ (paramsData->with_types ? sizeof(Oid) : 0));
1112
+
1113
+ if( sizeof(paramsData->memory_pool) < required_pool_size ){
1114
+ /* Allocate one combined memory pool for all possible function parameters */
1115
+ memory_pool = (char*)xmalloc( required_pool_size );
1116
+ /* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
1117
+ paramsData->heap_pool = Data_Wrap_Struct( rb_cObject, NULL, -1, memory_pool );
1118
+ required_pool_size = 0;
1119
+ }else{
1120
+ /* Use stack memory for function parameters */
1121
+ memory_pool = paramsData->memory_pool;
1122
+ }
1123
+
1124
+ paramsData->values = (char **)memory_pool;
1125
+ paramsData->lengths = (int *)((char*)paramsData->values + sizeof(char *) * nParams);
1126
+ paramsData->formats = (int *)((char*)paramsData->lengths + sizeof(int) * nParams);
1127
+ paramsData->types = (Oid *)((char*)paramsData->formats + sizeof(int) * nParams);
1128
+
1129
+ {
1130
+ char *typecast_buf = paramsData->memory_pool + required_pool_size;
1131
+
1132
+ for ( i = 0; i < nParams; i++ ) {
1133
+ param_value = rb_ary_entry(paramsData->params, i);
1134
+
1135
+ paramsData->formats[i] = 0;
1136
+ if( paramsData->with_types )
1137
+ paramsData->types[i] = 0;
1138
+
1139
+ /* Let the given typemap select a coder for this param */
1140
+ conv = p_typemap->funcs.typecast_query_param(p_typemap, param_value, i);
1141
+
1142
+ /* Using a coder object for the param_value? Then set it's format code and oid. */
1143
+ if( conv ){
1144
+ paramsData->formats[i] = conv->format;
1145
+ if( paramsData->with_types )
1146
+ paramsData->types[i] = conv->oid;
1147
+ } else {
1148
+ /* No coder, but got we a hash form for the query param?
1149
+ * Then take format code and oid from there. */
1150
+ if (TYPE(param_value) == T_HASH) {
1151
+ VALUE format_value = rb_hash_aref(param_value, sym_format);
1152
+ if( !NIL_P(format_value) )
1153
+ paramsData->formats[i] = NUM2INT(format_value);
1154
+ if( paramsData->with_types ){
1155
+ VALUE type_value = rb_hash_aref(param_value, sym_type);
1156
+ if( !NIL_P(type_value) )
1157
+ paramsData->types[i] = NUM2UINT(type_value);
1158
+ }
1159
+ param_value = rb_hash_aref(param_value, sym_value);
1160
+ }
1161
+ }
1162
+
1163
+ if( NIL_P(param_value) ){
1164
+ paramsData->values[i] = NULL;
1165
+ paramsData->lengths[i] = 0;
1166
+ } else {
1167
+ t_pg_coder_enc_func enc_func = pg_coder_enc_func( conv );
1168
+ VALUE intermediate;
1169
+
1170
+ /* 1st pass for retiving the required memory space */
1171
+ int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
1172
+
1173
+ if( len == -1 ){
1174
+ /* The intermediate value is a String that can be used directly. */
1175
+
1176
+ /* Ensure that the String object is zero terminated as expected by libpq. */
1177
+ if( paramsData->formats[i] == 0 )
1178
+ StringValueCStr(intermediate);
1179
+ /* In case a new string object was generated, make sure it doesn't get freed by the GC */
1180
+ if( intermediate != param_value ){
1181
+ if( NIL_P(paramsData->gc_array) )
1182
+ paramsData->gc_array = rb_ary_new();
1183
+ rb_ary_push(paramsData->gc_array, intermediate);
1184
+ }
1185
+ paramsData->values[i] = RSTRING_PTR(intermediate);
1186
+ paramsData->lengths[i] = RSTRING_LENINT(intermediate);
1187
+
1188
+ } else {
1189
+ /* Is the stack memory pool too small to take the type casted value? */
1190
+ if( sizeof(paramsData->memory_pool) < required_pool_size + len + 1){
1191
+ typecast_buf = alloc_typecast_buf( &paramsData->typecast_heap_chain, len + 1 );
1192
+ }
1193
+
1194
+ /* 2nd pass for writing the data to prepared buffer */
1195
+ len = enc_func(conv, param_value, typecast_buf, &intermediate, paramsData->enc_idx);
1196
+ paramsData->values[i] = typecast_buf;
1197
+ if( paramsData->formats[i] == 0 ){
1198
+ /* text format strings must be zero terminated and lengths are ignored */
1199
+ typecast_buf[len] = 0;
1200
+ typecast_buf += len + 1;
1201
+ required_pool_size += len + 1;
1202
+ } else {
1203
+ paramsData->lengths[i] = len;
1204
+ typecast_buf += len;
1205
+ required_pool_size += len;
1206
+ }
1207
+ }
1208
+
1209
+ RB_GC_GUARD(intermediate);
1210
+ }
1211
+ }
1212
+ }
1213
+
1214
+ return nParams;
1215
+ }
1216
+
1217
+ static void
1218
+ free_query_params(struct query_params_data *paramsData)
1219
+ {
1220
+ /* currently nothing to free */
1221
+ }
1222
+
1223
+ void
1224
+ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1225
+ {
1226
+ if(NIL_P(paramsData->typemap)){
1227
+ /* Use default typemap for queries. It's type is checked when assigned. */
1228
+ paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
1229
+ }else{
1230
+ /* Check type of method param */
1231
+ if ( !rb_obj_is_kind_of(paramsData->typemap, rb_cTypeMap) ) {
1232
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1233
+ rb_obj_classname( paramsData->typemap ) );
1234
+ }
1235
+ Check_Type( paramsData->typemap, T_DATA );
1236
+ }
1237
+ }
1238
+
1239
+ /*
1240
+ * call-seq:
1241
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1242
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1243
+ *
1244
+ * This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
1245
+ * See #async_exec for the differences between the two API variants.
1246
+ * It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
1247
+ */
1248
+ static VALUE
1249
+ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1250
+ {
1251
+ t_pg_connection *this = pg_get_connection_safe( self );
1252
+ PGresult *result = NULL;
1253
+ VALUE rb_pgresult;
1254
+ VALUE command, in_res_fmt;
1255
+ int nParams;
1256
+ int resultFormat;
1257
+ struct query_params_data paramsData = { this->enc_idx };
1258
+
1259
+ /* For compatibility we accept 1 to 4 parameters */
1260
+ rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1261
+ paramsData.with_types = 1;
1262
+
1263
+ /*
1264
+ * For backward compatibility no or +nil+ for the second parameter
1265
+ * is passed to #exec
1266
+ */
1267
+ if ( NIL_P(paramsData.params) ) {
1268
+ pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1269
+ return pgconn_exec( 1, argv, self );
1270
+ }
1271
+ pgconn_query_assign_typemap( self, &paramsData );
1272
+
1273
+ resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1274
+ nParams = alloc_query_params( &paramsData );
1275
+
1276
+ result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1277
+ (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1278
+
1279
+ free_query_params( &paramsData );
1280
+
1281
+ rb_pgresult = pg_new_result(result, self);
1282
+ pg_result_check(rb_pgresult);
1023
1283
 
1024
1284
  if (rb_block_given_p()) {
1025
1285
  return rb_ensure(rb_yield, rb_pgresult, pg_result_clear, rb_pgresult);
@@ -1030,28 +1290,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1030
1290
 
1031
1291
  /*
1032
1292
  * call-seq:
1033
- * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1034
- *
1035
- * Prepares statement _sql_ with name _name_ to be executed later.
1036
- * Returns a PG::Result instance on success.
1037
- * On failure, it raises a PG::Error.
1038
- *
1039
- * +param_types+ is an optional parameter to specify the Oids of the
1040
- * types of the parameters.
1041
- *
1042
- * If the types are not specified, they will be inferred by PostgreSQL.
1043
- * Instead of specifying type oids, it's recommended to simply add
1044
- * explicit casts in the query to ensure that the right type is used.
1045
- *
1046
- * For example: "SELECT $1::int"
1293
+ * conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1047
1294
  *
1048
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1049
- * inside the SQL query.
1295
+ * This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
1296
+ * See #async_exec for the differences between the two API variants.
1297
+ * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1050
1298
  */
1051
1299
  static VALUE
1052
1300
  pgconn_prepare(int argc, VALUE *argv, VALUE self)
1053
1301
  {
1054
- PGconn *conn = pg_get_pgconn(self);
1302
+ t_pg_connection *this = pg_get_connection_safe( self );
1055
1303
  PGresult *result = NULL;
1056
1304
  VALUE rb_pgresult;
1057
1305
  VALUE name, command, in_paramtypes;
@@ -1059,10 +1307,13 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1059
1307
  int i = 0;
1060
1308
  int nParams = 0;
1061
1309
  Oid *paramTypes = NULL;
1310
+ const char *name_cstr;
1311
+ const char *command_cstr;
1312
+ int enc_idx = this->enc_idx;
1062
1313
 
1063
1314
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1064
- Check_Type(name, T_STRING);
1065
- Check_Type(command, T_STRING);
1315
+ name_cstr = pg_cstr_enc(name, enc_idx);
1316
+ command_cstr = pg_cstr_enc(command, enc_idx);
1066
1317
 
1067
1318
  if(! NIL_P(in_paramtypes)) {
1068
1319
  Check_Type(in_paramtypes, T_ARRAY);
@@ -1070,15 +1321,13 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1070
1321
  paramTypes = ALLOC_N(Oid, nParams);
1071
1322
  for(i = 0; i < nParams; i++) {
1072
1323
  param = rb_ary_entry(in_paramtypes, i);
1073
- Check_Type(param, T_FIXNUM);
1074
1324
  if(param == Qnil)
1075
1325
  paramTypes[i] = 0;
1076
1326
  else
1077
- paramTypes[i] = NUM2INT(param);
1327
+ paramTypes[i] = NUM2UINT(param);
1078
1328
  }
1079
1329
  }
1080
- result = gvl_PQprepare(conn, StringValuePtr(name), StringValuePtr(command),
1081
- nParams, paramTypes);
1330
+ result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1082
1331
 
1083
1332
  xfree(paramTypes);
1084
1333
 
@@ -1089,122 +1338,40 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1089
1338
 
1090
1339
  /*
1091
1340
  * call-seq:
1092
- * conn.exec_prepared(statement_name [, params, result_format ] ) -> PG::Result
1093
- * conn.exec_prepared(statement_name [, params, result_format ] ) {|pg_result| block }
1094
- *
1095
- * Execute prepared named statement specified by _statement_name_.
1096
- * Returns a PG::Result instance on success.
1097
- * On failure, it raises a PG::Error.
1098
- *
1099
- * +params+ is an array of the optional bind parameters for the
1100
- * SQL query. Each element of the +params+ array may be either:
1101
- * a hash of the form:
1102
- * {:value => String (value of bind parameter)
1103
- * :format => Fixnum (0 for text, 1 for binary)
1104
- * }
1105
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1106
- * { :value => <string value>, :format => 0 }
1107
- *
1108
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1109
- * inside the SQL query. The 0th element of the +params+ array is bound
1110
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1111
- *
1112
- * The optional +result_format+ should be 0 for text results, 1
1113
- * for binary.
1341
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1342
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1114
1343
  *
1115
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1116
- * and the PG::Result object will automatically be cleared when the block terminates.
1117
- * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
1344
+ * This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
1345
+ * See #async_exec for the differences between the two API variants.
1346
+ * It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
1118
1347
  */
1119
1348
  static VALUE
1120
1349
  pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1121
1350
  {
1122
- PGconn *conn = pg_get_pgconn(self);
1351
+ t_pg_connection *this = pg_get_connection_safe( self );
1123
1352
  PGresult *result = NULL;
1124
1353
  VALUE rb_pgresult;
1125
- VALUE name, params, in_res_fmt;
1126
- VALUE param, param_value, param_format;
1127
- VALUE param_value_tmp;
1128
- VALUE sym_value, sym_format;
1129
- VALUE gc_array;
1130
- int i = 0;
1354
+ VALUE name, in_res_fmt;
1131
1355
  int nParams;
1132
- char ** paramValues;
1133
- int *paramLengths;
1134
- int *paramFormats;
1135
1356
  int resultFormat;
1357
+ struct query_params_data paramsData = { this->enc_idx };
1136
1358
 
1359
+ rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1360
+ paramsData.with_types = 0;
1137
1361
 
1138
- rb_scan_args(argc, argv, "12", &name, &params, &in_res_fmt);
1139
- Check_Type(name, T_STRING);
1140
-
1141
- if(NIL_P(params)) {
1142
- params = rb_ary_new2(0);
1143
- resultFormat = 0;
1144
- }
1145
- else {
1146
- Check_Type(params, T_ARRAY);
1147
- }
1148
-
1149
- if(NIL_P(in_res_fmt)) {
1150
- resultFormat = 0;
1151
- }
1152
- else {
1153
- resultFormat = NUM2INT(in_res_fmt);
1362
+ if(NIL_P(paramsData.params)) {
1363
+ paramsData.params = rb_ary_new2(0);
1154
1364
  }
1365
+ pgconn_query_assign_typemap( self, &paramsData );
1155
1366
 
1156
- gc_array = rb_ary_new();
1157
- rb_gc_register_address(&gc_array);
1158
- sym_value = ID2SYM(rb_intern("value"));
1159
- sym_format = ID2SYM(rb_intern("format"));
1160
- nParams = (int)RARRAY_LEN(params);
1161
- paramValues = ALLOC_N(char *, nParams);
1162
- paramLengths = ALLOC_N(int, nParams);
1163
- paramFormats = ALLOC_N(int, nParams);
1164
- for(i = 0; i < nParams; i++) {
1165
- param = rb_ary_entry(params, i);
1166
- if (TYPE(param) == T_HASH) {
1167
- param_value_tmp = rb_hash_aref(param, sym_value);
1168
- if(param_value_tmp == Qnil)
1169
- param_value = param_value_tmp;
1170
- else
1171
- param_value = rb_obj_as_string(param_value_tmp);
1172
- param_format = rb_hash_aref(param, sym_format);
1173
- }
1174
- else {
1175
- if(param == Qnil)
1176
- param_value = param;
1177
- else
1178
- param_value = rb_obj_as_string(param);
1179
- param_format = INT2NUM(0);
1180
- }
1181
- if(param_value == Qnil) {
1182
- paramValues[i] = NULL;
1183
- paramLengths[i] = 0;
1184
- }
1185
- else {
1186
- Check_Type(param_value, T_STRING);
1187
- /* make sure param_value doesn't get freed by the GC */
1188
- rb_ary_push(gc_array, param_value);
1189
- paramValues[i] = StringValuePtr(param_value);
1190
- paramLengths[i] = (int)RSTRING_LEN(param_value);
1191
- }
1192
-
1193
- if(param_format == Qnil)
1194
- paramFormats[i] = 0;
1195
- else
1196
- paramFormats[i] = NUM2INT(param_format);
1197
- }
1367
+ resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1368
+ nParams = alloc_query_params( &paramsData );
1198
1369
 
1199
- result = gvl_PQexecPrepared(conn, StringValuePtr(name), nParams,
1200
- (const char * const *)paramValues, paramLengths, paramFormats,
1370
+ result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1371
+ (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1201
1372
  resultFormat);
1202
1373
 
1203
- rb_gc_unregister_address(&gc_array);
1204
-
1205
- xfree(paramValues);
1206
- xfree(paramLengths);
1207
- xfree(paramFormats);
1374
+ free_query_params( &paramsData );
1208
1375
 
1209
1376
  rb_pgresult = pg_new_result(result, self);
1210
1377
  pg_result_check(rb_pgresult);
@@ -1217,26 +1384,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1217
1384
 
1218
1385
  /*
1219
1386
  * call-seq:
1220
- * conn.describe_prepared( statement_name ) -> PG::Result
1387
+ * conn.sync_describe_prepared( statement_name ) -> PG::Result
1221
1388
  *
1222
- * Retrieve information about the prepared statement
1223
- * _statement_name_.
1389
+ * This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
1390
+ * See #async_exec for the differences between the two API variants.
1391
+ * It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
1224
1392
  */
1225
1393
  static VALUE
1226
1394
  pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1227
1395
  {
1228
1396
  PGresult *result;
1229
1397
  VALUE rb_pgresult;
1230
- PGconn *conn = pg_get_pgconn(self);
1231
- char *stmt;
1232
- if(stmt_name == Qnil) {
1398
+ t_pg_connection *this = pg_get_connection_safe( self );
1399
+ const char *stmt;
1400
+ if(NIL_P(stmt_name)) {
1233
1401
  stmt = NULL;
1234
1402
  }
1235
1403
  else {
1236
- Check_Type(stmt_name, T_STRING);
1237
- stmt = StringValuePtr(stmt_name);
1404
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1238
1405
  }
1239
- result = gvl_PQdescribePrepared(conn, stmt);
1406
+ result = gvl_PQdescribePrepared(this->pgconn, stmt);
1240
1407
  rb_pgresult = pg_new_result(result, self);
1241
1408
  pg_result_check(rb_pgresult);
1242
1409
  return rb_pgresult;
@@ -1245,9 +1412,11 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1245
1412
 
1246
1413
  /*
1247
1414
  * call-seq:
1248
- * conn.describe_portal( portal_name ) -> PG::Result
1415
+ * conn.sync_describe_portal( portal_name ) -> PG::Result
1249
1416
  *
1250
- * Retrieve information about the portal _portal_name_.
1417
+ * This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
1418
+ * See #async_exec for the differences between the two API variants.
1419
+ * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1251
1420
  */
1252
1421
  static VALUE
1253
1422
  pgconn_describe_portal(self, stmt_name)
@@ -1255,16 +1424,15 @@ pgconn_describe_portal(self, stmt_name)
1255
1424
  {
1256
1425
  PGresult *result;
1257
1426
  VALUE rb_pgresult;
1258
- PGconn *conn = pg_get_pgconn(self);
1259
- char *stmt;
1260
- if(stmt_name == Qnil) {
1427
+ t_pg_connection *this = pg_get_connection_safe( self );
1428
+ const char *stmt;
1429
+ if(NIL_P(stmt_name)) {
1261
1430
  stmt = NULL;
1262
1431
  }
1263
1432
  else {
1264
- Check_Type(stmt_name, T_STRING);
1265
- stmt = StringValuePtr(stmt_name);
1433
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1266
1434
  }
1267
- result = gvl_PQdescribePortal(conn, stmt);
1435
+ result = gvl_PQdescribePortal(this->pgconn, stmt);
1268
1436
  rb_pgresult = pg_new_result(result, self);
1269
1437
  pg_result_check(rb_pgresult);
1270
1438
  return rb_pgresult;
@@ -1304,10 +1472,6 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1304
1472
  * call-seq:
1305
1473
  * conn.escape_string( str ) -> String
1306
1474
  *
1307
- * Connection instance method for versions of 8.1 and higher of libpq
1308
- * uses PQescapeStringConn, which is safer. Avoid calling as a class method,
1309
- * the class method uses the deprecated PQescapeString() API function.
1310
- *
1311
1475
  * Returns a SQL-safe version of the String _str_.
1312
1476
  * This is the preferred way to make strings safe for inclusion in
1313
1477
  * SQL queries.
@@ -1315,44 +1479,43 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1315
1479
  * Consider using exec_params, which avoids the need for passing values
1316
1480
  * inside of SQL commands.
1317
1481
  *
1318
- * Encoding of escaped string will be equal to client encoding of connection.
1482
+ * Character encoding of escaped string will be equal to client encoding of connection.
1483
+ *
1484
+ * NOTE: This class version of this method can only be used safely in client
1485
+ * programs that use a single PostgreSQL connection at a time (in this case it can
1486
+ * find out what it needs to know "behind the scenes"). It might give the wrong
1487
+ * results if used in programs that use multiple database connections; use the
1488
+ * same method on the connection object in such cases.
1489
+ *
1490
+ * See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
1319
1491
  */
1320
1492
  static VALUE
1321
1493
  pgconn_s_escape(VALUE self, VALUE string)
1322
1494
  {
1323
- char *escaped;
1324
1495
  size_t size;
1325
1496
  int error;
1326
1497
  VALUE result;
1327
- #ifdef M17N_SUPPORTED
1328
- rb_encoding* enc;
1329
- #endif
1498
+ int enc_idx;
1499
+ int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1330
1500
 
1331
- Check_Type(string, T_STRING);
1501
+ StringValueCStr(string);
1502
+ enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
1503
+ if( ENCODING_GET(string) != enc_idx ){
1504
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1505
+ }
1332
1506
 
1333
- escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
1334
- if(rb_obj_class(self) == rb_cPGconn) {
1335
- size = PQescapeStringConn(pg_get_pgconn(self), escaped,
1507
+ result = rb_str_new(NULL, RSTRING_LEN(string) * 2 + 1);
1508
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1509
+ if( !singleton ) {
1510
+ size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1336
1511
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1337
1512
  if(error) {
1338
- xfree(escaped);
1339
1513
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1340
1514
  }
1341
1515
  } else {
1342
- size = PQescapeString(escaped, RSTRING_PTR(string), (int)RSTRING_LEN(string));
1516
+ size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1343
1517
  }
1344
- result = rb_str_new(escaped, size);
1345
- xfree(escaped);
1346
- OBJ_INFECT(result, string);
1347
-
1348
- #ifdef M17N_SUPPORTED
1349
- if ( rb_obj_class(self) == rb_cPGconn ) {
1350
- enc = pg_conn_enc_get( pg_get_pgconn(self) );
1351
- } else {
1352
- enc = rb_enc_get(string);
1353
- }
1354
- rb_enc_associate(result, enc);
1355
- #endif
1518
+ rb_str_set_len(result, size);
1356
1519
 
1357
1520
  return result;
1358
1521
  }
@@ -1361,13 +1524,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1361
1524
  * call-seq:
1362
1525
  * conn.escape_bytea( string ) -> String
1363
1526
  *
1364
- * Connection instance method for versions of 8.1 and higher of libpq
1365
- * uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
1366
- * the class method uses the deprecated PQescapeBytea() API function.
1367
- *
1368
- * Use the instance method version of this function, it is safer than the
1369
- * class method.
1370
- *
1371
1527
  * Escapes binary data for use within an SQL command with the type +bytea+.
1372
1528
  *
1373
1529
  * Certain byte values must be escaped (but all byte values may be escaped)
@@ -1380,6 +1536,12 @@ pgconn_s_escape(VALUE self, VALUE string)
1380
1536
  *
1381
1537
  * Consider using exec_params, which avoids the need for passing values inside of
1382
1538
  * SQL commands.
1539
+ *
1540
+ * NOTE: This class version of this method can only be used safely in client
1541
+ * programs that use a single PostgreSQL connection at a time (in this case it can
1542
+ * find out what it needs to know "behind the scenes"). It might give the wrong
1543
+ * results if used in programs that use multiple database connections; use the
1544
+ * same method on the connection object in such cases.
1383
1545
  */
1384
1546
  static VALUE
1385
1547
  pgconn_s_escape_bytea(VALUE self, VALUE str)
@@ -1392,14 +1554,13 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1392
1554
  from = (unsigned char*)RSTRING_PTR(str);
1393
1555
  from_len = RSTRING_LEN(str);
1394
1556
 
1395
- if(rb_obj_class(self) == rb_cPGconn) {
1557
+ if ( rb_obj_is_kind_of(self, rb_cPGconn) ) {
1396
1558
  to = PQescapeByteaConn(pg_get_pgconn(self), from, from_len, &to_len);
1397
1559
  } else {
1398
1560
  to = PQescapeBytea( from, from_len, &to_len);
1399
1561
  }
1400
1562
 
1401
1563
  ret = rb_str_new((char*)to, to_len - 1);
1402
- OBJ_INFECT(ret, str);
1403
1564
  PQfreemem(to);
1404
1565
  return ret;
1405
1566
  }
@@ -1424,94 +1585,91 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1424
1585
  UNUSED( self );
1425
1586
 
1426
1587
  Check_Type(str, T_STRING);
1427
- from = (unsigned char*)StringValuePtr(str);
1588
+ from = (unsigned char*)StringValueCStr(str);
1428
1589
 
1429
1590
  to = PQunescapeBytea(from, &to_len);
1430
1591
 
1431
1592
  ret = rb_str_new((char*)to, to_len);
1432
- OBJ_INFECT(ret, str);
1433
1593
  PQfreemem(to);
1434
1594
  return ret;
1435
1595
  }
1436
1596
 
1437
- #ifdef HAVE_PQESCAPELITERAL
1438
1597
  /*
1439
1598
  * call-seq:
1440
1599
  * conn.escape_literal( str ) -> String
1441
1600
  *
1442
1601
  * Escape an arbitrary String +str+ as a literal.
1602
+ *
1603
+ * See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
1443
1604
  */
1444
1605
  static VALUE
1445
1606
  pgconn_escape_literal(VALUE self, VALUE string)
1446
1607
  {
1447
- PGconn *conn = pg_get_pgconn(self);
1608
+ t_pg_connection *this = pg_get_connection_safe( self );
1448
1609
  char *escaped = NULL;
1449
1610
  VALUE error;
1450
1611
  VALUE result = Qnil;
1612
+ int enc_idx = this->enc_idx;
1451
1613
 
1452
- Check_Type(string, T_STRING);
1614
+ StringValueCStr(string);
1615
+ if( ENCODING_GET(string) != enc_idx ){
1616
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1617
+ }
1453
1618
 
1454
- escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1619
+ escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1455
1620
  if (escaped == NULL)
1456
1621
  {
1457
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1622
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1458
1623
  rb_iv_set(error, "@connection", self);
1459
1624
  rb_exc_raise(error);
1460
1625
  return Qnil;
1461
1626
  }
1462
1627
  result = rb_str_new2(escaped);
1463
1628
  PQfreemem(escaped);
1464
- OBJ_INFECT(result, string);
1465
-
1466
- #ifdef M17N_SUPPORTED
1467
- rb_enc_associate(result, pg_conn_enc_get( pg_get_pgconn(self) ));
1468
- #endif
1629
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1469
1630
 
1470
1631
  return result;
1471
1632
  }
1472
- #endif
1473
1633
 
1474
- #ifdef HAVE_PQESCAPEIDENTIFIER
1475
1634
  /*
1476
1635
  * call-seq:
1477
1636
  * conn.escape_identifier( str ) -> String
1478
1637
  *
1479
1638
  * Escape an arbitrary String +str+ as an identifier.
1480
1639
  *
1481
- * This method does the same as #quote_ident, but uses libpq to
1482
- * process the string.
1640
+ * This method does the same as #quote_ident with a String argument,
1641
+ * but it doesn't support an Array argument and it makes use of libpq
1642
+ * to process the string.
1483
1643
  */
1484
1644
  static VALUE
1485
1645
  pgconn_escape_identifier(VALUE self, VALUE string)
1486
1646
  {
1487
- PGconn *conn = pg_get_pgconn(self);
1647
+ t_pg_connection *this = pg_get_connection_safe( self );
1488
1648
  char *escaped = NULL;
1489
1649
  VALUE error;
1490
1650
  VALUE result = Qnil;
1651
+ int enc_idx = this->enc_idx;
1491
1652
 
1492
- Check_Type(string, T_STRING);
1653
+ StringValueCStr(string);
1654
+ if( ENCODING_GET(string) != enc_idx ){
1655
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1656
+ }
1493
1657
 
1494
- escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1658
+ escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1495
1659
  if (escaped == NULL)
1496
1660
  {
1497
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1661
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1498
1662
  rb_iv_set(error, "@connection", self);
1499
1663
  rb_exc_raise(error);
1500
1664
  return Qnil;
1501
1665
  }
1502
1666
  result = rb_str_new2(escaped);
1503
1667
  PQfreemem(escaped);
1504
- OBJ_INFECT(result, string);
1505
-
1506
- #ifdef M17N_SUPPORTED
1507
- rb_enc_associate(result, pg_conn_enc_get( pg_get_pgconn(self) ));
1508
- #endif
1668
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1509
1669
 
1510
1670
  return result;
1511
1671
  }
1512
- #endif
1513
1672
 
1514
- #ifdef HAVE_PQSETSINGLEROWMODE
1515
1673
  /*
1516
1674
  * call-seq:
1517
1675
  * conn.set_single_row_mode -> self
@@ -1522,7 +1680,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1522
1680
  * Then call Connection#get_result repeatedly, until it returns nil.
1523
1681
  *
1524
1682
  * Each (but the last) received Result has exactly one row and a
1525
- * Result#result_status of PGRES_SINGLE_TUPLE. The last row has
1683
+ * Result#result_status of PGRES_SINGLE_TUPLE. The last Result has
1526
1684
  * zero rows and is used to indicate a successful execution of the query.
1527
1685
  * All of these Result objects will contain the same row description data
1528
1686
  * (column names, types, etc) that an ordinary Result object for the query
@@ -1547,7 +1705,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1547
1705
  * # do something with the received row
1548
1706
  * end
1549
1707
  * end
1550
- *
1551
1708
  */
1552
1709
  static VALUE
1553
1710
  pgconn_set_single_row_mode(VALUE self)
@@ -1564,22 +1721,60 @@ pgconn_set_single_row_mode(VALUE self)
1564
1721
 
1565
1722
  return self;
1566
1723
  }
1567
- #endif
1724
+
1725
+ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1726
+
1727
+ /*
1728
+ * call-seq:
1729
+ * conn.send_query(sql) -> nil
1730
+ *
1731
+ * Sends SQL query request specified by _sql_ to PostgreSQL for
1732
+ * asynchronous processing, and immediately returns.
1733
+ * On failure, it raises a PG::Error.
1734
+ *
1735
+ * For backward compatibility, if you pass more than one parameter to this method,
1736
+ * it will call #send_query_params for you. New code should explicitly use #send_query_params if
1737
+ * argument placeholders are used.
1738
+ *
1739
+ */
1740
+ static VALUE
1741
+ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1742
+ {
1743
+ t_pg_connection *this = pg_get_connection_safe( self );
1744
+ VALUE error;
1745
+
1746
+ /* If called with no or nil parameters, use PQexec for compatibility */
1747
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1748
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1749
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1750
+ rb_iv_set(error, "@connection", self);
1751
+ rb_exc_raise(error);
1752
+ }
1753
+ return Qnil;
1754
+ }
1755
+
1756
+ pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
1757
+
1758
+ /* If called with parameters, and optionally result_format,
1759
+ * use PQsendQueryParams
1760
+ */
1761
+ return pgconn_send_query_params( argc, argv, self);
1762
+ }
1568
1763
 
1569
1764
  /*
1570
1765
  * call-seq:
1571
- * conn.send_query(sql [, params, result_format ] ) -> nil
1766
+ * conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
1572
1767
  *
1573
1768
  * Sends SQL query request specified by _sql_ to PostgreSQL for
1574
1769
  * asynchronous processing, and immediately returns.
1575
1770
  * On failure, it raises a PG::Error.
1576
1771
  *
1577
- * +params+ is an optional array of the bind parameters for the SQL query.
1772
+ * +params+ is an array of the bind parameters for the SQL query.
1578
1773
  * Each element of the +params+ array may be either:
1579
1774
  * a hash of the form:
1580
1775
  * {:value => String (value of bind parameter)
1581
- * :type => Fixnum (oid of type of bind parameter)
1582
- * :format => Fixnum (0 for text, 1 for binary)
1776
+ * :type => Integer (oid of type of bind parameter)
1777
+ * :format => Integer (0 for text, 1 for binary)
1583
1778
  * }
1584
1779
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1585
1780
  * { :value => <string value>, :type => 0, :format => 0 }
@@ -1596,116 +1791,39 @@ pgconn_set_single_row_mode(VALUE self)
1596
1791
  *
1597
1792
  * The optional +result_format+ should be 0 for text results, 1
1598
1793
  * for binary.
1794
+ *
1795
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1796
+ * This will type cast the params from various Ruby types before transmission
1797
+ * based on the encoders defined by the type map. When a type encoder is used
1798
+ * the format and oid of a given bind parameter are retrieved from the encoder
1799
+ * instead out of the hash form described above.
1800
+ *
1599
1801
  */
1600
1802
  static VALUE
1601
- pgconn_send_query(int argc, VALUE *argv, VALUE self)
1803
+ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1602
1804
  {
1603
- PGconn *conn = pg_get_pgconn(self);
1805
+ t_pg_connection *this = pg_get_connection_safe( self );
1604
1806
  int result;
1605
- VALUE command, params, in_res_fmt;
1606
- VALUE param, param_type, param_value, param_format;
1607
- VALUE param_value_tmp;
1608
- VALUE sym_type, sym_value, sym_format;
1609
- VALUE gc_array;
1807
+ VALUE command, in_res_fmt;
1610
1808
  VALUE error;
1611
- int i=0;
1612
1809
  int nParams;
1613
- Oid *paramTypes;
1614
- char ** paramValues;
1615
- int *paramLengths;
1616
- int *paramFormats;
1617
1810
  int resultFormat;
1811
+ struct query_params_data paramsData = { this->enc_idx };
1618
1812
 
1619
- rb_scan_args(argc, argv, "12", &command, &params, &in_res_fmt);
1620
- Check_Type(command, T_STRING);
1621
-
1622
- /* If called with no parameters, use PQsendQuery */
1623
- if(NIL_P(params)) {
1624
- if(gvl_PQsendQuery(conn,StringValuePtr(command)) == 0) {
1625
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1626
- rb_iv_set(error, "@connection", self);
1627
- rb_exc_raise(error);
1628
- }
1629
- return Qnil;
1630
- }
1631
-
1632
- /* If called with parameters, and optionally result_format,
1633
- * use PQsendQueryParams
1634
- */
1635
- Check_Type(params, T_ARRAY);
1636
-
1637
- if(NIL_P(in_res_fmt)) {
1638
- resultFormat = 0;
1639
- }
1640
- else {
1641
- resultFormat = NUM2INT(in_res_fmt);
1642
- }
1643
-
1644
- gc_array = rb_ary_new();
1645
- rb_gc_register_address(&gc_array);
1646
- sym_type = ID2SYM(rb_intern("type"));
1647
- sym_value = ID2SYM(rb_intern("value"));
1648
- sym_format = ID2SYM(rb_intern("format"));
1649
- nParams = (int)RARRAY_LEN(params);
1650
- paramTypes = ALLOC_N(Oid, nParams);
1651
- paramValues = ALLOC_N(char *, nParams);
1652
- paramLengths = ALLOC_N(int, nParams);
1653
- paramFormats = ALLOC_N(int, nParams);
1654
- for(i = 0; i < nParams; i++) {
1655
- param = rb_ary_entry(params, i);
1656
- if (TYPE(param) == T_HASH) {
1657
- param_type = rb_hash_aref(param, sym_type);
1658
- param_value_tmp = rb_hash_aref(param, sym_value);
1659
- if(param_value_tmp == Qnil)
1660
- param_value = param_value_tmp;
1661
- else
1662
- param_value = rb_obj_as_string(param_value_tmp);
1663
- param_format = rb_hash_aref(param, sym_format);
1664
- }
1665
- else {
1666
- param_type = INT2NUM(0);
1667
- if(param == Qnil)
1668
- param_value = param;
1669
- else
1670
- param_value = rb_obj_as_string(param);
1671
- param_format = INT2NUM(0);
1672
- }
1673
-
1674
- if(param_type == Qnil)
1675
- paramTypes[i] = 0;
1676
- else
1677
- paramTypes[i] = NUM2INT(param_type);
1813
+ rb_scan_args(argc, argv, "22", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1814
+ paramsData.with_types = 1;
1678
1815
 
1679
- if(param_value == Qnil) {
1680
- paramValues[i] = NULL;
1681
- paramLengths[i] = 0;
1682
- }
1683
- else {
1684
- Check_Type(param_value, T_STRING);
1685
- /* make sure param_value doesn't get freed by the GC */
1686
- rb_ary_push(gc_array, param_value);
1687
- paramValues[i] = StringValuePtr(param_value);
1688
- paramLengths[i] = (int)RSTRING_LEN(param_value);
1689
- }
1690
-
1691
- if(param_format == Qnil)
1692
- paramFormats[i] = 0;
1693
- else
1694
- paramFormats[i] = NUM2INT(param_format);
1695
- }
1696
-
1697
- result = gvl_PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
1698
- (const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
1816
+ pgconn_query_assign_typemap( self, &paramsData );
1817
+ resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1818
+ nParams = alloc_query_params( &paramsData );
1699
1819
 
1700
- rb_gc_unregister_address(&gc_array);
1820
+ result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1821
+ (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1701
1822
 
1702
- xfree(paramTypes);
1703
- xfree(paramValues);
1704
- xfree(paramLengths);
1705
- xfree(paramFormats);
1823
+ free_query_params( &paramsData );
1706
1824
 
1707
1825
  if(result == 0) {
1708
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1826
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1709
1827
  rb_iv_set(error, "@connection", self);
1710
1828
  rb_exc_raise(error);
1711
1829
  }
@@ -1735,7 +1853,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1735
1853
  static VALUE
1736
1854
  pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1737
1855
  {
1738
- PGconn *conn = pg_get_pgconn(self);
1856
+ t_pg_connection *this = pg_get_connection_safe( self );
1739
1857
  int result;
1740
1858
  VALUE name, command, in_paramtypes;
1741
1859
  VALUE param;
@@ -1743,10 +1861,13 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1743
1861
  int i = 0;
1744
1862
  int nParams = 0;
1745
1863
  Oid *paramTypes = NULL;
1864
+ const char *name_cstr;
1865
+ const char *command_cstr;
1866
+ int enc_idx = this->enc_idx;
1746
1867
 
1747
1868
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1748
- Check_Type(name, T_STRING);
1749
- Check_Type(command, T_STRING);
1869
+ name_cstr = pg_cstr_enc(name, enc_idx);
1870
+ command_cstr = pg_cstr_enc(command, enc_idx);
1750
1871
 
1751
1872
  if(! NIL_P(in_paramtypes)) {
1752
1873
  Check_Type(in_paramtypes, T_ARRAY);
@@ -1754,20 +1875,18 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1754
1875
  paramTypes = ALLOC_N(Oid, nParams);
1755
1876
  for(i = 0; i < nParams; i++) {
1756
1877
  param = rb_ary_entry(in_paramtypes, i);
1757
- Check_Type(param, T_FIXNUM);
1758
1878
  if(param == Qnil)
1759
1879
  paramTypes[i] = 0;
1760
1880
  else
1761
- paramTypes[i] = NUM2INT(param);
1881
+ paramTypes[i] = NUM2UINT(param);
1762
1882
  }
1763
1883
  }
1764
- result = gvl_PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
1765
- nParams, paramTypes);
1884
+ result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1766
1885
 
1767
1886
  xfree(paramTypes);
1768
1887
 
1769
1888
  if(result == 0) {
1770
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1889
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1771
1890
  rb_iv_set(error, "@connection", self);
1772
1891
  rb_exc_raise(error);
1773
1892
  }
@@ -1776,7 +1895,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1776
1895
 
1777
1896
  /*
1778
1897
  * call-seq:
1779
- * conn.send_query_prepared( statement_name [, params, result_format ] )
1898
+ * conn.send_query_prepared( statement_name [, params, result_format[, type_map ]] )
1780
1899
  * -> nil
1781
1900
  *
1782
1901
  * Execute prepared named statement specified by _statement_name_
@@ -1787,7 +1906,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1787
1906
  * SQL query. Each element of the +params+ array may be either:
1788
1907
  * a hash of the form:
1789
1908
  * {:value => String (value of bind parameter)
1790
- * :format => Fixnum (0 for text, 1 for binary)
1909
+ * :format => Integer (0 for text, 1 for binary)
1791
1910
  * }
1792
1911
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1793
1912
  * { :value => <string value>, :format => 0 }
@@ -1798,99 +1917,45 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1798
1917
  *
1799
1918
  * The optional +result_format+ should be 0 for text results, 1
1800
1919
  * for binary.
1920
+ *
1921
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1922
+ * This will type cast the params from various Ruby types before transmission
1923
+ * based on the encoders defined by the type map. When a type encoder is used
1924
+ * the format and oid of a given bind parameter are retrieved from the encoder
1925
+ * instead out of the hash form described above.
1926
+ *
1801
1927
  */
1802
1928
  static VALUE
1803
1929
  pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1804
1930
  {
1805
- PGconn *conn = pg_get_pgconn(self);
1931
+ t_pg_connection *this = pg_get_connection_safe( self );
1806
1932
  int result;
1807
- VALUE name, params, in_res_fmt;
1808
- VALUE param, param_value, param_format;
1809
- VALUE param_value_tmp;
1810
- VALUE sym_value, sym_format;
1811
- VALUE gc_array;
1933
+ VALUE name, in_res_fmt;
1812
1934
  VALUE error;
1813
- int i = 0;
1814
1935
  int nParams;
1815
- char ** paramValues;
1816
- int *paramLengths;
1817
- int *paramFormats;
1818
1936
  int resultFormat;
1937
+ struct query_params_data paramsData = { this->enc_idx };
1819
1938
 
1820
- rb_scan_args(argc, argv, "12", &name, &params, &in_res_fmt);
1821
- Check_Type(name, T_STRING);
1822
-
1823
- if(NIL_P(params)) {
1824
- params = rb_ary_new2(0);
1825
- resultFormat = 0;
1826
- }
1827
- else {
1828
- Check_Type(params, T_ARRAY);
1829
- }
1939
+ rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1940
+ paramsData.with_types = 0;
1830
1941
 
1831
- if(NIL_P(in_res_fmt)) {
1942
+ if(NIL_P(paramsData.params)) {
1943
+ paramsData.params = rb_ary_new2(0);
1832
1944
  resultFormat = 0;
1833
1945
  }
1834
- else {
1835
- resultFormat = NUM2INT(in_res_fmt);
1836
- }
1837
-
1838
- gc_array = rb_ary_new();
1839
- rb_gc_register_address(&gc_array);
1840
- sym_value = ID2SYM(rb_intern("value"));
1841
- sym_format = ID2SYM(rb_intern("format"));
1842
- nParams = (int)RARRAY_LEN(params);
1843
- paramValues = ALLOC_N(char *, nParams);
1844
- paramLengths = ALLOC_N(int, nParams);
1845
- paramFormats = ALLOC_N(int, nParams);
1846
- for(i = 0; i < nParams; i++) {
1847
- param = rb_ary_entry(params, i);
1848
- if (TYPE(param) == T_HASH) {
1849
- param_value_tmp = rb_hash_aref(param, sym_value);
1850
- if(param_value_tmp == Qnil)
1851
- param_value = param_value_tmp;
1852
- else
1853
- param_value = rb_obj_as_string(param_value_tmp);
1854
- param_format = rb_hash_aref(param, sym_format);
1855
- }
1856
- else {
1857
- if(param == Qnil)
1858
- param_value = param;
1859
- else
1860
- param_value = rb_obj_as_string(param);
1861
- param_format = INT2NUM(0);
1862
- }
1863
-
1864
- if(param_value == Qnil) {
1865
- paramValues[i] = NULL;
1866
- paramLengths[i] = 0;
1867
- }
1868
- else {
1869
- Check_Type(param_value, T_STRING);
1870
- /* make sure param_value doesn't get freed by the GC */
1871
- rb_ary_push(gc_array, param_value);
1872
- paramValues[i] = StringValuePtr(param_value);
1873
- paramLengths[i] = (int)RSTRING_LEN(param_value);
1874
- }
1946
+ pgconn_query_assign_typemap( self, &paramsData );
1875
1947
 
1876
- if(param_format == Qnil)
1877
- paramFormats[i] = 0;
1878
- else
1879
- paramFormats[i] = NUM2INT(param_format);
1880
- }
1948
+ resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1949
+ nParams = alloc_query_params( &paramsData );
1881
1950
 
1882
- result = gvl_PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
1883
- (const char * const *)paramValues, paramLengths, paramFormats,
1951
+ result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1952
+ (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1884
1953
  resultFormat);
1885
1954
 
1886
- rb_gc_unregister_address(&gc_array);
1887
-
1888
- xfree(paramValues);
1889
- xfree(paramLengths);
1890
- xfree(paramFormats);
1955
+ free_query_params( &paramsData );
1891
1956
 
1892
1957
  if(result == 0) {
1893
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1958
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1894
1959
  rb_iv_set(error, "@connection", self);
1895
1960
  rb_exc_raise(error);
1896
1961
  }
@@ -1908,10 +1973,10 @@ static VALUE
1908
1973
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
1909
1974
  {
1910
1975
  VALUE error;
1911
- PGconn *conn = pg_get_pgconn(self);
1976
+ t_pg_connection *this = pg_get_connection_safe( self );
1912
1977
  /* returns 0 on failure */
1913
- if(gvl_PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
1914
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1978
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
1979
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1915
1980
  rb_iv_set(error, "@connection", self);
1916
1981
  rb_exc_raise(error);
1917
1982
  }
@@ -1930,10 +1995,10 @@ static VALUE
1930
1995
  pgconn_send_describe_portal(VALUE self, VALUE portal)
1931
1996
  {
1932
1997
  VALUE error;
1933
- PGconn *conn = pg_get_pgconn(self);
1998
+ t_pg_connection *this = pg_get_connection_safe( self );
1934
1999
  /* returns 0 on failure */
1935
- if(gvl_PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
1936
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2000
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2001
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1937
2002
  rb_iv_set(error, "@connection", self);
1938
2003
  rb_exc_raise(error);
1939
2004
  }
@@ -2104,7 +2169,6 @@ pgconn_flush(self)
2104
2169
  static VALUE
2105
2170
  pgconn_cancel(VALUE self)
2106
2171
  {
2107
- #ifdef HAVE_PQGETCANCEL
2108
2172
  char errbuf[256];
2109
2173
  PGcancel *cancel;
2110
2174
  VALUE retval;
@@ -2122,9 +2186,6 @@ pgconn_cancel(VALUE self)
2122
2186
 
2123
2187
  PQfreeCancel(cancel);
2124
2188
  return retval;
2125
- #else
2126
- rb_notimplement();
2127
- #endif
2128
2189
  }
2129
2190
 
2130
2191
 
@@ -2138,7 +2199,7 @@ pgconn_cancel(VALUE self)
2138
2199
  static VALUE
2139
2200
  pgconn_notifies(VALUE self)
2140
2201
  {
2141
- PGconn* conn = pg_get_pgconn(self);
2202
+ t_pg_connection *this = pg_get_connection_safe( self );
2142
2203
  PGnotify *notification;
2143
2204
  VALUE hash;
2144
2205
  VALUE sym_relname, sym_be_pid, sym_extra;
@@ -2148,19 +2209,17 @@ pgconn_notifies(VALUE self)
2148
2209
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2149
2210
  sym_extra = ID2SYM(rb_intern("extra"));
2150
2211
 
2151
- notification = gvl_PQnotifies(conn);
2212
+ notification = gvl_PQnotifies(this->pgconn);
2152
2213
  if (notification == NULL) {
2153
2214
  return Qnil;
2154
2215
  }
2155
2216
 
2156
2217
  hash = rb_hash_new();
2157
- relname = rb_tainted_str_new2(notification->relname);
2218
+ relname = rb_str_new2(notification->relname);
2158
2219
  be_pid = INT2NUM(notification->be_pid);
2159
- extra = rb_tainted_str_new2(notification->extra);
2160
- #ifdef M17N_SUPPORTED
2161
- ENCODING_SET( relname, rb_enc_to_index(pg_conn_enc_get( conn )) );
2162
- ENCODING_SET( extra, rb_enc_to_index(pg_conn_enc_get( conn )) );
2163
- #endif
2220
+ extra = rb_str_new2(notification->extra);
2221
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2222
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2164
2223
 
2165
2224
  rb_hash_aset(hash, sym_relname, relname);
2166
2225
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -2170,56 +2229,15 @@ pgconn_notifies(VALUE self)
2170
2229
  return hash;
2171
2230
  }
2172
2231
 
2173
- /* Win32 + Ruby 1.8 */
2174
- #if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2175
-
2176
- /*
2177
- * Duplicate the sockets from libpq and create temporary CRT FDs
2178
- */
2179
- void create_crt_fd(fd_set *os_set, fd_set *crt_set)
2180
- {
2181
- int i;
2182
- crt_set->fd_count = os_set->fd_count;
2183
- for (i = 0; i < os_set->fd_count; i++) {
2184
- WSAPROTOCOL_INFO wsa_pi;
2185
- /* dupicate the SOCKET */
2186
- int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
2187
- SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
2188
- /* create the CRT fd so ruby can get back to the SOCKET */
2189
- int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
2190
- os_set->fd_array[i] = s;
2191
- crt_set->fd_array[i] = fd;
2192
- }
2193
- }
2194
-
2195
- /*
2196
- * Clean up the CRT FDs from create_crt_fd()
2197
- */
2198
- void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
2199
- {
2200
- int i;
2201
- for (i = 0; i < os_set->fd_count; i++) {
2202
- /* cleanup the CRT fd */
2203
- _close(crt_set->fd_array[i]);
2204
- /* cleanup the duplicated SOCKET */
2205
- closesocket(os_set->fd_array[i]);
2206
- }
2207
- }
2208
- #endif
2209
-
2210
2232
  /* Win32 + Ruby 1.9+ */
2211
- #if defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2233
+ #if defined( _WIN32 )
2212
2234
  /*
2213
2235
  * On Windows, use platform-specific strategies to wait for the socket
2214
- * instead of rb_thread_select().
2236
+ * instead of rb_wait_for_single_fd().
2215
2237
  */
2216
2238
 
2217
2239
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2218
2240
 
2219
- /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2220
- * and does not wait (nor sleep) any time even if timeout is given.
2221
- * Instead use the Winsock events and rb_w32_wait_events(). */
2222
-
2223
2241
  static void *
2224
2242
  wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2225
2243
  {
@@ -2296,7 +2314,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2296
2314
 
2297
2315
  #else
2298
2316
 
2299
- /* non Win32 or Win32+Ruby-1.8 */
2317
+ /* non Win32 */
2300
2318
 
2301
2319
  static void *
2302
2320
  wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
@@ -2304,11 +2322,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2304
2322
  int sd = PQsocket( conn );
2305
2323
  int ret;
2306
2324
  void *retval;
2307
- rb_fdset_t sd_rset;
2308
2325
  struct timeval aborttime={0,0}, currtime, waittime;
2309
- #ifdef _WIN32
2310
- rb_fdset_t crt_sd_rset;
2311
- #endif
2312
2326
 
2313
2327
  if ( sd < 0 )
2314
2328
  rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
@@ -2317,25 +2331,12 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2317
2331
  if ( PQconsumeInput(conn) == 0 )
2318
2332
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2319
2333
 
2320
- rb_fd_init( &sd_rset );
2321
-
2322
2334
  if ( ptimeout ) {
2323
2335
  gettimeofday(&currtime, NULL);
2324
2336
  timeradd(&currtime, ptimeout, &aborttime);
2325
2337
  }
2326
2338
 
2327
2339
  while ( !(retval=is_readable(conn)) ) {
2328
- rb_fd_zero( &sd_rset );
2329
- rb_fd_set( sd, &sd_rset );
2330
-
2331
- #ifdef _WIN32
2332
- /* Ruby's FD_SET is modified on win32 to convert a file descriptor
2333
- * to osfhandle, but we already get a osfhandle from PQsocket().
2334
- * Therefore it's overwritten here. */
2335
- sd_rset.fd_array[0] = sd;
2336
- create_crt_fd(&sd_rset, &crt_sd_rset);
2337
- #endif
2338
-
2339
2340
  if ( ptimeout ) {
2340
2341
  gettimeofday(&currtime, NULL);
2341
2342
  timersub(&aborttime, &currtime, &waittime);
@@ -2344,35 +2345,26 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2344
2345
  /* Is the given timeout valid? */
2345
2346
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2346
2347
  /* Wait for the socket to become readable before checking again */
2347
- ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout ? &waittime : NULL );
2348
+ ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
2348
2349
  } else {
2349
2350
  ret = 0;
2350
2351
  }
2351
2352
 
2352
-
2353
- #ifdef _WIN32
2354
- cleanup_crt_fd(&sd_rset, &crt_sd_rset);
2355
- #endif
2356
-
2357
2353
  if ( ret < 0 ){
2358
- rb_fd_term( &sd_rset );
2359
- rb_sys_fail( "rb_thread_select()" );
2354
+ rb_sys_fail( "rb_wait_for_single_fd()" );
2360
2355
  }
2361
2356
 
2362
2357
  /* Return false if the select() timed out */
2363
2358
  if ( ret == 0 ){
2364
- rb_fd_term( &sd_rset );
2365
2359
  return NULL;
2366
2360
  }
2367
2361
 
2368
2362
  /* Check for connection errors (PQisBusy is true on connection errors) */
2369
2363
  if ( PQconsumeInput(conn) == 0 ){
2370
- rb_fd_term( &sd_rset );
2371
2364
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2372
2365
  }
2373
2366
  }
2374
2367
 
2375
- rb_fd_term( &sd_rset );
2376
2368
  return retval;
2377
2369
  }
2378
2370
 
@@ -2387,27 +2379,20 @@ notify_readable(PGconn *conn)
2387
2379
 
2388
2380
  /*
2389
2381
  * call-seq:
2390
- * conn.wait_for_notify( [ timeout ] ) -> String
2391
- * conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
2392
- * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
2382
+ * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
2393
2383
  *
2394
2384
  * Blocks while waiting for notification(s), or until the optional
2395
2385
  * _timeout_ is reached, whichever comes first. _timeout_ is
2396
2386
  * measured in seconds and can be fractional.
2397
2387
  *
2398
- * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
2399
- * event otherwise. If used in block form, passes the name of the
2400
- * NOTIFY +event+ and the generating +pid+ into the block.
2401
- *
2402
- * Under PostgreSQL 9.0 and later, if the notification is sent with
2403
- * the optional +payload+ string, it will be given to the block as the
2404
- * third argument.
2405
- *
2388
+ * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
2389
+ * If used in block form, passes the name of the NOTIFY +event+, the generating
2390
+ * +pid+ and the optional +payload+ string into the block.
2406
2391
  */
2407
2392
  static VALUE
2408
2393
  pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2409
2394
  {
2410
- PGconn *conn = pg_get_pgconn( self );
2395
+ t_pg_connection *this = pg_get_connection_safe( self );
2411
2396
  PGnotify *pnotification;
2412
2397
  struct timeval timeout;
2413
2398
  struct timeval *ptimeout = NULL;
@@ -2423,24 +2408,18 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2423
2408
  ptimeout = &timeout;
2424
2409
  }
2425
2410
 
2426
- pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
2411
+ pnotification = (PGnotify*) wait_socket_readable( this->pgconn, ptimeout, notify_readable);
2427
2412
 
2428
2413
  /* Return nil if the select timed out */
2429
2414
  if ( !pnotification ) return Qnil;
2430
2415
 
2431
- relname = rb_tainted_str_new2( pnotification->relname );
2432
- #ifdef M17N_SUPPORTED
2433
- ENCODING_SET( relname, rb_enc_to_index(pg_conn_enc_get( conn )) );
2434
- #endif
2416
+ relname = rb_str_new2( pnotification->relname );
2417
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2435
2418
  be_pid = INT2NUM( pnotification->be_pid );
2436
- #ifdef HAVE_ST_NOTIFY_EXTRA
2437
2419
  if ( *pnotification->extra ) {
2438
- extra = rb_tainted_str_new2( pnotification->extra );
2439
- #ifdef M17N_SUPPORTED
2440
- ENCODING_SET( extra, rb_enc_to_index(pg_conn_enc_get( conn )) );
2441
- #endif
2420
+ extra = rb_str_new2( pnotification->extra );
2421
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2442
2422
  }
2443
- #endif
2444
2423
  PQfreemem( pnotification );
2445
2424
 
2446
2425
  if ( rb_block_given_p() )
@@ -2452,33 +2431,79 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2452
2431
 
2453
2432
  /*
2454
2433
  * call-seq:
2455
- * conn.put_copy_data( buffer ) -> Boolean
2434
+ * conn.put_copy_data( buffer [, encoder] ) -> Boolean
2456
2435
  *
2457
2436
  * Transmits _buffer_ as copy data to the server.
2458
2437
  * Returns true if the data was sent, false if it was
2459
2438
  * not sent (false is only possible if the connection
2460
2439
  * is in nonblocking mode, and this command would block).
2461
2440
  *
2441
+ * _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
2442
+ * This encodes the data fields given as _buffer_ from an Array of Strings to
2443
+ * PostgreSQL's COPY text format inclusive proper escaping. Optionally
2444
+ * the encoder can type cast the fields from various Ruby types in one step,
2445
+ * if PG::TextEncoder::CopyRow#type_map is set accordingly.
2446
+ *
2462
2447
  * Raises an exception if an error occurs.
2463
2448
  *
2464
2449
  * See also #copy_data.
2465
2450
  *
2466
2451
  */
2467
2452
  static VALUE
2468
- pgconn_put_copy_data(self, buffer)
2469
- VALUE self, buffer;
2453
+ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2470
2454
  {
2471
2455
  int ret;
2472
- VALUE error;
2473
- PGconn *conn = pg_get_pgconn(self);
2456
+ int len;
2457
+ t_pg_connection *this = pg_get_connection_safe( self );
2458
+ VALUE value;
2459
+ VALUE buffer = Qnil;
2460
+ VALUE encoder;
2461
+ VALUE intermediate;
2462
+ t_pg_coder *p_coder = NULL;
2463
+
2464
+ rb_scan_args( argc, argv, "11", &value, &encoder );
2465
+
2466
+ if( NIL_P(encoder) ){
2467
+ if( NIL_P(this->encoder_for_put_copy_data) ){
2468
+ buffer = value;
2469
+ } else {
2470
+ p_coder = DATA_PTR( this->encoder_for_put_copy_data );
2471
+ }
2472
+ } else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
2473
+ Data_Get_Struct( encoder, t_pg_coder, p_coder );
2474
+ } else {
2475
+ rb_raise( rb_eTypeError, "wrong encoder type %s (expected some kind of PG::Coder)",
2476
+ rb_obj_classname( encoder ) );
2477
+ }
2478
+
2479
+ if( p_coder ){
2480
+ t_pg_coder_enc_func enc_func;
2481
+ int enc_idx = this->enc_idx;
2482
+
2483
+ enc_func = pg_coder_enc_func( p_coder );
2484
+ len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
2485
+
2486
+ if( len == -1 ){
2487
+ /* The intermediate value is a String that can be used directly. */
2488
+ buffer = intermediate;
2489
+ } else {
2490
+ buffer = rb_str_new(NULL, len);
2491
+ len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate, enc_idx);
2492
+ rb_str_set_len( buffer, len );
2493
+ }
2494
+ }
2495
+
2474
2496
  Check_Type(buffer, T_STRING);
2475
2497
 
2476
- ret = gvl_PQputCopyData(conn, RSTRING_PTR(buffer), (int)RSTRING_LEN(buffer));
2498
+ ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2477
2499
  if(ret == -1) {
2478
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2500
+ VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2479
2501
  rb_iv_set(error, "@connection", self);
2480
2502
  rb_exc_raise(error);
2481
2503
  }
2504
+ RB_GC_GUARD(intermediate);
2505
+ RB_GC_GUARD(buffer);
2506
+
2482
2507
  return (ret) ? Qtrue : Qfalse;
2483
2508
  }
2484
2509
 
@@ -2502,17 +2527,17 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2502
2527
  VALUE str;
2503
2528
  VALUE error;
2504
2529
  int ret;
2505
- char *error_message = NULL;
2506
- PGconn *conn = pg_get_pgconn(self);
2530
+ const char *error_message = NULL;
2531
+ t_pg_connection *this = pg_get_connection_safe( self );
2507
2532
 
2508
2533
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2509
2534
  error_message = NULL;
2510
2535
  else
2511
- error_message = StringValuePtr(str);
2536
+ error_message = pg_cstr_enc(str, this->enc_idx);
2512
2537
 
2513
- ret = gvl_PQputCopyEnd(conn, error_message);
2538
+ ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2514
2539
  if(ret == -1) {
2515
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2540
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2516
2541
  rb_iv_set(error, "@connection", self);
2517
2542
  rb_exc_raise(error);
2518
2543
  }
@@ -2521,12 +2546,20 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2521
2546
 
2522
2547
  /*
2523
2548
  * call-seq:
2524
- * conn.get_copy_data( [ async = false ] ) -> String
2549
+ * conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
2525
2550
  *
2526
- * Return a string containing one row of data, +nil+
2551
+ * Return one row of data, +nil+
2527
2552
  * if the copy is done, or +false+ if the call would
2528
2553
  * block (only possible if _async_ is true).
2529
2554
  *
2555
+ * If _decoder_ is not set or +nil+, data is returned as binary string.
2556
+ *
2557
+ * If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
2558
+ * PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
2559
+ * COPY text format to an Array of Strings.
2560
+ * Optionally the decoder can type cast the single fields to various Ruby types in one step,
2561
+ * if PG::TextDecoder::CopyRow#type_map is set accordingly.
2562
+ *
2530
2563
  * See also #copy_data.
2531
2564
  *
2532
2565
  */
@@ -2535,20 +2568,29 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2535
2568
  {
2536
2569
  VALUE async_in;
2537
2570
  VALUE error;
2538
- VALUE result_str;
2571
+ VALUE result;
2539
2572
  int ret;
2540
- int async;
2541
2573
  char *buffer;
2542
- PGconn *conn = pg_get_pgconn(self);
2574
+ VALUE decoder;
2575
+ t_pg_coder *p_coder = NULL;
2576
+ t_pg_connection *this = pg_get_connection_safe( self );
2543
2577
 
2544
- if (rb_scan_args(argc, argv, "01", &async_in) == 0)
2545
- async = 0;
2546
- else
2547
- async = (async_in == Qfalse || async_in == Qnil) ? 0 : 1;
2578
+ rb_scan_args(argc, argv, "02", &async_in, &decoder);
2579
+
2580
+ if( NIL_P(decoder) ){
2581
+ if( !NIL_P(this->decoder_for_get_copy_data) ){
2582
+ p_coder = DATA_PTR( this->decoder_for_get_copy_data );
2583
+ }
2584
+ } else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
2585
+ Data_Get_Struct( decoder, t_pg_coder, p_coder );
2586
+ } else {
2587
+ rb_raise( rb_eTypeError, "wrong decoder type %s (expected some kind of PG::Coder)",
2588
+ rb_obj_classname( decoder ) );
2589
+ }
2548
2590
 
2549
- ret = gvl_PQgetCopyData(conn, &buffer, async);
2591
+ ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2550
2592
  if(ret == -2) { /* error */
2551
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2593
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2552
2594
  rb_iv_set(error, "@connection", self);
2553
2595
  rb_exc_raise(error);
2554
2596
  }
@@ -2558,20 +2600,34 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2558
2600
  if(ret == 0) { /* would block */
2559
2601
  return Qfalse;
2560
2602
  }
2561
- result_str = rb_tainted_str_new(buffer, ret);
2603
+
2604
+ if( p_coder ){
2605
+ t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
2606
+ result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2607
+ } else {
2608
+ result = rb_str_new(buffer, ret);
2609
+ }
2610
+
2562
2611
  PQfreemem(buffer);
2563
- return result_str;
2612
+ return result;
2564
2613
  }
2565
2614
 
2566
2615
  /*
2567
2616
  * call-seq:
2568
- * conn.set_error_verbosity( verbosity ) -> Fixnum
2617
+ * conn.set_error_verbosity( verbosity ) -> Integer
2569
2618
  *
2570
2619
  * Sets connection's verbosity to _verbosity_ and returns
2571
2620
  * the previous setting. Available settings are:
2621
+ *
2572
2622
  * * PQERRORS_TERSE
2573
2623
  * * PQERRORS_DEFAULT
2574
2624
  * * PQERRORS_VERBOSE
2625
+ * * PQERRORS_SQLSTATE
2626
+ *
2627
+ * Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2628
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
2629
+ *
2630
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
2575
2631
  */
2576
2632
  static VALUE
2577
2633
  pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
@@ -2581,6 +2637,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2581
2637
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2582
2638
  }
2583
2639
 
2640
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2641
+ /*
2642
+ * call-seq:
2643
+ * conn.set_error_context_visibility( context_visibility ) -> Integer
2644
+ *
2645
+ * Sets connection's context display mode to _context_visibility_ and returns
2646
+ * the previous setting. Available settings are:
2647
+ * * PQSHOW_CONTEXT_NEVER
2648
+ * * PQSHOW_CONTEXT_ERRORS
2649
+ * * PQSHOW_CONTEXT_ALWAYS
2650
+ *
2651
+ * This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
2652
+ * The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
2653
+ * In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
2654
+ *
2655
+ * Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2656
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
2657
+ *
2658
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2659
+ *
2660
+ * Available since PostgreSQL-9.6
2661
+ */
2662
+ static VALUE
2663
+ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2664
+ {
2665
+ PGconn *conn = pg_get_pgconn(self);
2666
+ PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2667
+ return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2668
+ }
2669
+ #endif
2670
+
2584
2671
  /*
2585
2672
  * call-seq:
2586
2673
  * conn.trace( stream ) -> nil
@@ -2597,8 +2684,9 @@ pgconn_trace(VALUE self, VALUE stream)
2597
2684
  FILE *new_fp;
2598
2685
  int old_fd, new_fd;
2599
2686
  VALUE new_file;
2687
+ t_pg_connection *this = pg_get_connection_safe( self );
2600
2688
 
2601
- if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2689
+ if(!rb_respond_to(stream,rb_intern("fileno")))
2602
2690
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2603
2691
 
2604
2692
  fileno = rb_funcall(stream, rb_intern("fileno"), 0);
@@ -2619,9 +2707,9 @@ pgconn_trace(VALUE self, VALUE stream)
2619
2707
  rb_raise(rb_eArgError, "stream is not writable");
2620
2708
 
2621
2709
  new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
2622
- rb_iv_set(self, "@trace_stream", new_file);
2710
+ this->trace_stream = new_file;
2623
2711
 
2624
- PQtrace(pg_get_pgconn(self), new_fp);
2712
+ PQtrace(this->pgconn, new_fp);
2625
2713
  return Qnil;
2626
2714
  }
2627
2715
 
@@ -2634,11 +2722,11 @@ pgconn_trace(VALUE self, VALUE stream)
2634
2722
  static VALUE
2635
2723
  pgconn_untrace(VALUE self)
2636
2724
  {
2637
- VALUE trace_stream;
2638
- PQuntrace(pg_get_pgconn(self));
2639
- trace_stream = rb_iv_get(self, "@trace_stream");
2640
- rb_funcall(trace_stream, rb_intern("close"), 0);
2641
- rb_iv_set(self, "@trace_stream", Qnil);
2725
+ t_pg_connection *this = pg_get_connection_safe( self );
2726
+
2727
+ PQuntrace(this->pgconn);
2728
+ rb_funcall(this->trace_stream, rb_intern("close"), 0);
2729
+ this->trace_stream = Qnil;
2642
2730
  return Qnil;
2643
2731
  }
2644
2732
 
@@ -2648,19 +2736,16 @@ pgconn_untrace(VALUE self)
2648
2736
  * currently-registered Ruby notice_receiver object.
2649
2737
  */
2650
2738
  void
2651
- notice_receiver_proxy(void *arg, const PGresult *result)
2739
+ notice_receiver_proxy(void *arg, const PGresult *pgresult)
2652
2740
  {
2653
- VALUE proc;
2654
2741
  VALUE self = (VALUE)arg;
2742
+ t_pg_connection *this = pg_get_connection( self );
2655
2743
 
2656
- if ((proc = rb_iv_get(self, "@notice_receiver")) != Qnil) {
2657
- VALUE val = Data_Wrap_Struct(rb_cPGresult, NULL, NULL, (PGresult*)result);
2658
- #ifdef M17N_SUPPORTED
2659
- PGconn *conn = pg_get_pgconn( self );
2660
- rb_encoding *enc = pg_conn_enc_get( conn );
2661
- ENCODING_SET( val, rb_enc_to_index(enc) );
2662
- #endif
2663
- rb_funcall(proc, rb_intern("call"), 1, val);
2744
+ if (this->notice_receiver != Qnil) {
2745
+ VALUE result = pg_new_result_autoclear( (PGresult *)pgresult, self );
2746
+
2747
+ rb_funcall(this->notice_receiver, rb_intern("call"), 1, result);
2748
+ pg_result_clear( result );
2664
2749
  }
2665
2750
  return;
2666
2751
  }
@@ -2698,7 +2783,7 @@ static VALUE
2698
2783
  pgconn_set_notice_receiver(VALUE self)
2699
2784
  {
2700
2785
  VALUE proc, old_proc;
2701
- PGconn *conn = pg_get_pgconn(self);
2786
+ t_pg_connection *this = pg_get_connection_safe( self );
2702
2787
 
2703
2788
  /* If default_notice_receiver is unset, assume that the current
2704
2789
  * notice receiver is the default, and save it to a global variable.
@@ -2706,19 +2791,19 @@ pgconn_set_notice_receiver(VALUE self)
2706
2791
  * always the same, so won't vary among connections.
2707
2792
  */
2708
2793
  if(default_notice_receiver == NULL)
2709
- default_notice_receiver = PQsetNoticeReceiver(conn, NULL, NULL);
2794
+ default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
2710
2795
 
2711
- old_proc = rb_iv_get(self, "@notice_receiver");
2796
+ old_proc = this->notice_receiver;
2712
2797
  if( rb_block_given_p() ) {
2713
2798
  proc = rb_block_proc();
2714
- PQsetNoticeReceiver(conn, gvl_notice_receiver_proxy, (void *)self);
2799
+ PQsetNoticeReceiver(this->pgconn, gvl_notice_receiver_proxy, (void *)self);
2715
2800
  } else {
2716
2801
  /* if no block is given, set back to default */
2717
2802
  proc = Qnil;
2718
- PQsetNoticeReceiver(conn, default_notice_receiver, NULL);
2803
+ PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
2719
2804
  }
2720
2805
 
2721
- rb_iv_set(self, "@notice_receiver", proc);
2806
+ this->notice_receiver = proc;
2722
2807
  return old_proc;
2723
2808
  }
2724
2809
 
@@ -2730,17 +2815,13 @@ pgconn_set_notice_receiver(VALUE self)
2730
2815
  void
2731
2816
  notice_processor_proxy(void *arg, const char *message)
2732
2817
  {
2733
- VALUE proc;
2734
2818
  VALUE self = (VALUE)arg;
2819
+ t_pg_connection *this = pg_get_connection( self );
2735
2820
 
2736
- if ((proc = rb_iv_get(self, "@notice_processor")) != Qnil) {
2737
- VALUE message_str = rb_tainted_str_new2(message);
2738
- #ifdef M17N_SUPPORTED
2739
- PGconn *conn = pg_get_pgconn( self );
2740
- rb_encoding *enc = pg_conn_enc_get( conn );
2741
- ENCODING_SET( message_str, rb_enc_to_index(enc) );
2742
- #endif
2743
- rb_funcall(proc, rb_intern("call"), 1, message_str);
2821
+ if (this->notice_receiver != Qnil) {
2822
+ VALUE message_str = rb_str_new2(message);
2823
+ PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2824
+ rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2744
2825
  }
2745
2826
  return;
2746
2827
  }
@@ -2762,7 +2843,7 @@ static VALUE
2762
2843
  pgconn_set_notice_processor(VALUE self)
2763
2844
  {
2764
2845
  VALUE proc, old_proc;
2765
- PGconn *conn = pg_get_pgconn(self);
2846
+ t_pg_connection *this = pg_get_connection_safe( self );
2766
2847
 
2767
2848
  /* If default_notice_processor is unset, assume that the current
2768
2849
  * notice processor is the default, and save it to a global variable.
@@ -2770,19 +2851,19 @@ pgconn_set_notice_processor(VALUE self)
2770
2851
  * always the same, so won't vary among connections.
2771
2852
  */
2772
2853
  if(default_notice_processor == NULL)
2773
- default_notice_processor = PQsetNoticeProcessor(conn, NULL, NULL);
2854
+ default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
2774
2855
 
2775
- old_proc = rb_iv_get(self, "@notice_processor");
2856
+ old_proc = this->notice_receiver;
2776
2857
  if( rb_block_given_p() ) {
2777
2858
  proc = rb_block_proc();
2778
- PQsetNoticeProcessor(conn, gvl_notice_processor_proxy, (void *)self);
2859
+ PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
2779
2860
  } else {
2780
2861
  /* if no block is given, set back to default */
2781
2862
  proc = Qnil;
2782
- PQsetNoticeProcessor(conn, default_notice_processor, NULL);
2863
+ PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
2783
2864
  }
2784
2865
 
2785
- rb_iv_set(self, "@notice_processor", proc);
2866
+ this->notice_receiver = proc;
2786
2867
  return old_proc;
2787
2868
  }
2788
2869
 
@@ -2797,7 +2878,7 @@ static VALUE
2797
2878
  pgconn_get_client_encoding(VALUE self)
2798
2879
  {
2799
2880
  char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2800
- return rb_tainted_str_new2(encoding);
2881
+ return rb_str_new2(encoding);
2801
2882
  }
2802
2883
 
2803
2884
 
@@ -2814,9 +2895,10 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
2814
2895
 
2815
2896
  Check_Type(str, T_STRING);
2816
2897
 
2817
- if ( (PQsetClientEncoding(conn, StringValuePtr(str))) == -1 ) {
2818
- rb_raise(rb_ePGerror, "invalid encoding name: %s",StringValuePtr(str));
2898
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2899
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2819
2900
  }
2901
+ pgconn_set_internal_encoding_index( self );
2820
2902
 
2821
2903
  return Qnil;
2822
2904
  }
@@ -2867,8 +2949,10 @@ pgconn_transaction(VALUE self)
2867
2949
 
2868
2950
  /*
2869
2951
  * call-seq:
2870
- * PG::Connection.quote_ident( str ) -> String
2871
2952
  * conn.quote_ident( str ) -> String
2953
+ * conn.quote_ident( array ) -> String
2954
+ * PG::Connection.quote_ident( str ) -> String
2955
+ * PG::Connection.quote_ident( array ) -> String
2872
2956
  *
2873
2957
  * Returns a string that is safe for inclusion in a SQL query as an
2874
2958
  * identifier. Note: this is not a quote function for values, but for
@@ -2878,52 +2962,39 @@ pgconn_transaction(VALUE self)
2878
2962
  * The identifier <tt>FOO</tt> is folded to lower case, so it actually
2879
2963
  * means <tt>foo</tt>. If you really want to access the case-sensitive
2880
2964
  * field name <tt>FOO</tt>, use this function like
2881
- * <tt>PG::Connection.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
2965
+ * <tt>conn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
2882
2966
  * (with double-quotes). PostgreSQL will see the double-quotes, and
2883
2967
  * it will not fold to lower case.
2884
2968
  *
2885
2969
  * Similarly, this function also protects against special characters,
2886
2970
  * and other things that might allow SQL injection if the identifier
2887
2971
  * comes from an untrusted source.
2972
+ *
2973
+ * If the parameter is an Array, then all it's values are separately quoted
2974
+ * and then joined by a "." character. This can be used for identifiers in
2975
+ * the form "schema"."table"."column" .
2976
+ *
2977
+ * This method is functional identical to the encoder PG::TextEncoder::Identifier .
2978
+ *
2979
+ * If the instance method form is used and the input string character encoding
2980
+ * is different to the connection encoding, then the string is converted to this
2981
+ * encoding, so that the returned string is always encoded as PG::Connection#internal_encoding .
2982
+ *
2983
+ * In the singleton form (PG::Connection.quote_ident) the character encoding
2984
+ * of the result string is set to the character encoding of the input string.
2888
2985
  */
2889
2986
  static VALUE
2890
- pgconn_s_quote_ident(VALUE self, VALUE in_str)
2987
+ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
2891
2988
  {
2892
2989
  VALUE ret;
2893
- char *str = StringValuePtr(in_str);
2894
- /* result size at most NAMEDATALEN*2 plus surrounding
2895
- * double-quotes. */
2896
- char buffer[NAMEDATALEN*2+2];
2897
- unsigned int i=0,j=0;
2898
- #ifdef M17N_SUPPORTED
2899
- rb_encoding* enc;
2900
- #endif
2990
+ int enc_idx;
2901
2991
 
2902
- UNUSED( self );
2903
-
2904
- if(strlen(str) >= NAMEDATALEN) {
2905
- rb_raise(rb_eArgError,
2906
- "Input string is longer than NAMEDATALEN-1 (%d)",
2907
- NAMEDATALEN-1);
2908
- }
2909
- buffer[j++] = '"';
2910
- for(i = 0; i < strlen(str) && str[i]; i++) {
2911
- if(str[i] == '"')
2912
- buffer[j++] = '"';
2913
- buffer[j++] = str[i];
2914
- }
2915
- buffer[j++] = '"';
2916
- ret = rb_str_new(buffer,j);
2917
- OBJ_INFECT(ret, in_str);
2918
-
2919
- #ifdef M17N_SUPPORTED
2920
- if ( rb_obj_class(self) == rb_cPGconn ) {
2921
- enc = pg_conn_enc_get( pg_get_pgconn(self) );
2922
- } else {
2923
- enc = rb_enc_get(in_str);
2992
+ if( rb_obj_is_kind_of(self, rb_cPGconn) ){
2993
+ enc_idx = pg_get_connection(self)->enc_idx;
2994
+ }else{
2995
+ enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
2924
2996
  }
2925
- rb_enc_associate(ret, enc);
2926
- #endif
2997
+ pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
2927
2998
 
2928
2999
  return ret;
2929
3000
  }
@@ -2953,10 +3024,6 @@ static VALUE
2953
3024
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
2954
3025
  PGconn *conn = pg_get_pgconn( self );
2955
3026
 
2956
- /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2957
- * and does not wait (nor sleep) any time even if timeout is given.
2958
- * Instead use the Winsock events and rb_w32_wait_events(). */
2959
-
2960
3027
  struct timeval timeout;
2961
3028
  struct timeval *ptimeout = NULL;
2962
3029
  VALUE timeout_in;
@@ -3023,24 +3090,142 @@ pgconn_get_last_result(VALUE self)
3023
3090
 
3024
3091
  /*
3025
3092
  * call-seq:
3026
- * conn.async_exec(sql [, params, result_format ] ) -> PG::Result
3027
- * conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
3093
+ * conn.discard_results()
3094
+ *
3095
+ * Silently discard any prior query result that application didn't eat.
3096
+ * This is done prior of Connection#exec and sibling methods and can
3097
+ * be called explicitly when using the async API.
3098
+ */
3099
+ static VALUE
3100
+ pgconn_discard_results(VALUE self)
3101
+ {
3102
+ PGconn *conn = pg_get_pgconn(self);
3103
+
3104
+ PGresult *cur;
3105
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
3106
+ int status = PQresultStatus(cur);
3107
+ PQclear(cur);
3108
+ if (status == PGRES_COPY_IN){
3109
+ gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
3110
+ }
3111
+ if (status == PGRES_COPY_OUT){
3112
+ char *buffer = NULL;
3113
+ while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
3114
+ PQfreemem(buffer);
3115
+ }
3116
+ }
3117
+
3118
+ return Qnil;
3119
+ }
3120
+
3121
+ /*
3122
+ * call-seq:
3123
+ * conn.exec(sql) -> PG::Result
3124
+ * conn.exec(sql) {|pg_result| block }
3125
+ *
3126
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
3127
+ * On success, it returns a PG::Result instance with all result rows and columns.
3128
+ * On failure, it raises a PG::Error.
3028
3129
  *
3029
- * This function has the same behavior as #exec,
3030
- * but is implemented using the asynchronous command
3031
- * processing API of libpq.
3130
+ * For backward compatibility, if you pass more than one parameter to this method,
3131
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
3132
+ * argument placeholders are used.
3133
+ *
3134
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3135
+ * and the PG::Result object will automatically be cleared when the block terminates.
3136
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3137
+ *
3138
+ * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3139
+ * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3140
+ * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3141
+ * Both methods ensure that other threads can process while waiting for the server to
3142
+ * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3143
+ * This is most notably visible by a delayed reaction to Control+C.
3144
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3145
+ *
3146
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
3032
3147
  */
3033
3148
  static VALUE
3034
3149
  pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3035
3150
  {
3036
3151
  VALUE rb_pgresult = Qnil;
3037
3152
 
3038
- /* remove any remaining results from the queue */
3153
+ pgconn_discard_results( self );
3154
+ pgconn_send_query( argc, argv, self );
3039
3155
  pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3040
- pgconn_get_last_result( self );
3156
+ rb_pgresult = pgconn_get_last_result( self );
3041
3157
 
3042
- pgconn_send_query( argc, argv, self );
3043
- pgconn_block( 0, NULL, self );
3158
+ if ( rb_block_given_p() ) {
3159
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3160
+ }
3161
+ return rb_pgresult;
3162
+ }
3163
+
3164
+
3165
+ /*
3166
+ * call-seq:
3167
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3168
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3169
+ *
3170
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
3171
+ * for parameters.
3172
+ *
3173
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
3174
+ *
3175
+ * +params+ is an array of the bind parameters for the SQL query.
3176
+ * Each element of the +params+ array may be either:
3177
+ * a hash of the form:
3178
+ * {:value => String (value of bind parameter)
3179
+ * :type => Integer (oid of type of bind parameter)
3180
+ * :format => Integer (0 for text, 1 for binary)
3181
+ * }
3182
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3183
+ * { :value => <string value>, :type => 0, :format => 0 }
3184
+ *
3185
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3186
+ * inside the SQL query. The 0th element of the +params+ array is bound
3187
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3188
+ *
3189
+ * If the types are not specified, they will be inferred by PostgreSQL.
3190
+ * Instead of specifying type oids, it's recommended to simply add
3191
+ * explicit casts in the query to ensure that the right type is used.
3192
+ *
3193
+ * For example: "SELECT $1::int"
3194
+ *
3195
+ * The optional +result_format+ should be 0 for text results, 1
3196
+ * for binary.
3197
+ *
3198
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3199
+ * This will type cast the params from various Ruby types before transmission
3200
+ * based on the encoders defined by the type map. When a type encoder is used
3201
+ * the format and oid of a given bind parameter are retrieved from the encoder
3202
+ * instead out of the hash form described above.
3203
+ *
3204
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3205
+ * and the PG::Result object will automatically be cleared when the block terminates.
3206
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3207
+ *
3208
+ * 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.
3209
+ * Unlike #exec, #exec_params allows at most one SQL command in the given string.
3210
+ * (There can be semicolons in it, but not more than one nonempty command.)
3211
+ * This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
3212
+ *
3213
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
3214
+ */
3215
+ static VALUE
3216
+ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3217
+ {
3218
+ VALUE rb_pgresult = Qnil;
3219
+
3220
+ pgconn_discard_results( self );
3221
+ /* If called with no or nil parameters, use PQsendQuery for compatibility */
3222
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
3223
+ pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
3224
+ pgconn_send_query( argc, argv, self );
3225
+ } else {
3226
+ pgconn_send_query_params( argc, argv, self );
3227
+ }
3228
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3044
3229
  rb_pgresult = pgconn_get_last_result( self );
3045
3230
 
3046
3231
  if ( rb_block_given_p() ) {
@@ -3049,13 +3234,236 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3049
3234
  return rb_pgresult;
3050
3235
  }
3051
3236
 
3237
+
3238
+ /*
3239
+ * call-seq:
3240
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3241
+ *
3242
+ * Prepares statement _sql_ with name _name_ to be executed later.
3243
+ * Returns a PG::Result instance on success.
3244
+ * On failure, it raises a PG::Error.
3245
+ *
3246
+ * +param_types+ is an optional parameter to specify the Oids of the
3247
+ * types of the parameters.
3248
+ *
3249
+ * If the types are not specified, they will be inferred by PostgreSQL.
3250
+ * Instead of specifying type oids, it's recommended to simply add
3251
+ * explicit casts in the query to ensure that the right type is used.
3252
+ *
3253
+ * For example: "SELECT $1::int"
3254
+ *
3255
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3256
+ * inside the SQL query.
3257
+ *
3258
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
3259
+ */
3260
+ static VALUE
3261
+ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3262
+ {
3263
+ VALUE rb_pgresult = Qnil;
3264
+
3265
+ pgconn_discard_results( self );
3266
+ pgconn_send_prepare( argc, argv, self );
3267
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3268
+ rb_pgresult = pgconn_get_last_result( self );
3269
+
3270
+ if ( rb_block_given_p() ) {
3271
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3272
+ }
3273
+ return rb_pgresult;
3274
+ }
3275
+
3276
+
3277
+ /*
3278
+ * call-seq:
3279
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3280
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3281
+ *
3282
+ * Execute prepared named statement specified by _statement_name_.
3283
+ * Returns a PG::Result instance on success.
3284
+ * On failure, it raises a PG::Error.
3285
+ *
3286
+ * +params+ is an array of the optional bind parameters for the
3287
+ * SQL query. Each element of the +params+ array may be either:
3288
+ * a hash of the form:
3289
+ * {:value => String (value of bind parameter)
3290
+ * :format => Integer (0 for text, 1 for binary)
3291
+ * }
3292
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3293
+ * { :value => <string value>, :format => 0 }
3294
+ *
3295
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3296
+ * inside the SQL query. The 0th element of the +params+ array is bound
3297
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3298
+ *
3299
+ * The optional +result_format+ should be 0 for text results, 1
3300
+ * for binary.
3301
+ *
3302
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3303
+ * This will type cast the params from various Ruby types before transmission
3304
+ * based on the encoders defined by the type map. When a type encoder is used
3305
+ * the format and oid of a given bind parameter are retrieved from the encoder
3306
+ * instead out of the hash form described above.
3307
+ *
3308
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3309
+ * and the PG::Result object will automatically be cleared when the block terminates.
3310
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
3311
+ *
3312
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
3313
+ */
3314
+ static VALUE
3315
+ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3316
+ {
3317
+ VALUE rb_pgresult = Qnil;
3318
+
3319
+ pgconn_discard_results( self );
3320
+ pgconn_send_query_prepared( argc, argv, self );
3321
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3322
+ rb_pgresult = pgconn_get_last_result( self );
3323
+
3324
+ if ( rb_block_given_p() ) {
3325
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3326
+ }
3327
+ return rb_pgresult;
3328
+ }
3329
+
3330
+
3331
+ /*
3332
+ * call-seq:
3333
+ * conn.describe_portal( portal_name ) -> PG::Result
3334
+ *
3335
+ * Retrieve information about the portal _portal_name_.
3336
+ *
3337
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
3338
+ */
3339
+ static VALUE
3340
+ pgconn_async_describe_portal(VALUE self, VALUE portal)
3341
+ {
3342
+ VALUE rb_pgresult = Qnil;
3343
+
3344
+ pgconn_discard_results( self );
3345
+ pgconn_send_describe_portal( self, portal );
3346
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3347
+ rb_pgresult = pgconn_get_last_result( self );
3348
+
3349
+ if ( rb_block_given_p() ) {
3350
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3351
+ }
3352
+ return rb_pgresult;
3353
+ }
3354
+
3355
+
3356
+ /*
3357
+ * call-seq:
3358
+ * conn.describe_prepared( statement_name ) -> PG::Result
3359
+ *
3360
+ * Retrieve information about the prepared statement _statement_name_.
3361
+ *
3362
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
3363
+ */
3364
+ static VALUE
3365
+ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3366
+ {
3367
+ VALUE rb_pgresult = Qnil;
3368
+
3369
+ pgconn_discard_results( self );
3370
+ pgconn_send_describe_prepared( self, stmt_name );
3371
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3372
+ rb_pgresult = pgconn_get_last_result( self );
3373
+
3374
+ if ( rb_block_given_p() ) {
3375
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3376
+ }
3377
+ return rb_pgresult;
3378
+ }
3379
+
3380
+
3381
+ #ifdef HAVE_PQSSLATTRIBUTE
3382
+ /*
3383
+ * call-seq:
3384
+ * conn.ssl_in_use? -> Boolean
3385
+ *
3386
+ * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3387
+ *
3388
+ * Available since PostgreSQL-9.5
3389
+ */
3390
+ static VALUE
3391
+ pgconn_ssl_in_use(VALUE self)
3392
+ {
3393
+ return PQsslInUse(pg_get_pgconn(self)) ? Qtrue : Qfalse;
3394
+ }
3395
+
3396
+
3397
+ /*
3398
+ * call-seq:
3399
+ * conn.ssl_attribute(attribute_name) -> String
3400
+ *
3401
+ * Returns SSL-related information about the connection.
3402
+ *
3403
+ * The list of available attributes varies depending on the SSL library being used,
3404
+ * and the type of connection. If an attribute is not available, returns nil.
3405
+ *
3406
+ * The following attributes are commonly available:
3407
+ *
3408
+ * [+library+]
3409
+ * Name of the SSL implementation in use. (Currently, only "OpenSSL" is implemented)
3410
+ * [+protocol+]
3411
+ * SSL/TLS version in use. Common values are "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" and "TLSv1.2", but an implementation may return other strings if some other protocol is used.
3412
+ * [+key_bits+]
3413
+ * Number of key bits used by the encryption algorithm.
3414
+ * [+cipher+]
3415
+ * A short name of the ciphersuite used, e.g. "DHE-RSA-DES-CBC3-SHA". The names are specific to each SSL implementation.
3416
+ * [+compression+]
3417
+ * 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".
3418
+ *
3419
+ *
3420
+ * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3421
+ *
3422
+ * Available since PostgreSQL-9.5
3423
+ */
3424
+ static VALUE
3425
+ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
3426
+ {
3427
+ const char *p_attr;
3428
+
3429
+ p_attr = PQsslAttribute(pg_get_pgconn(self), StringValueCStr(attribute_name));
3430
+ return p_attr ? rb_str_new_cstr(p_attr) : Qnil;
3431
+ }
3432
+
3433
+ /*
3434
+ * call-seq:
3435
+ * conn.ssl_attribute_names -> Array<String>
3436
+ *
3437
+ * Return an array of SSL attribute names available.
3438
+ *
3439
+ * See also #ssl_attribute
3440
+ *
3441
+ * Available since PostgreSQL-9.5
3442
+ */
3443
+ static VALUE
3444
+ pgconn_ssl_attribute_names(VALUE self)
3445
+ {
3446
+ int i;
3447
+ const char * const * p_list = PQsslAttributeNames(pg_get_pgconn(self));
3448
+ VALUE ary = rb_ary_new();
3449
+
3450
+ for ( i = 0; p_list[i]; i++ ) {
3451
+ rb_ary_push( ary, rb_str_new_cstr( p_list[i] ));
3452
+ }
3453
+ return ary;
3454
+ }
3455
+
3456
+
3457
+ #endif
3458
+
3459
+
3052
3460
  /**************************************************************************
3053
3461
  * LARGE OBJECT SUPPORT
3054
3462
  **************************************************************************/
3055
3463
 
3056
3464
  /*
3057
3465
  * call-seq:
3058
- * conn.lo_creat( [mode] ) -> Fixnum
3466
+ * conn.lo_creat( [mode] ) -> Integer
3059
3467
  *
3060
3468
  * Creates a large object with mode _mode_. Returns a large object Oid.
3061
3469
  * On failure, it raises PG::Error.
@@ -3077,12 +3485,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3077
3485
  if (lo_oid == 0)
3078
3486
  rb_raise(rb_ePGerror, "lo_creat failed");
3079
3487
 
3080
- return INT2FIX(lo_oid);
3488
+ return UINT2NUM(lo_oid);
3081
3489
  }
3082
3490
 
3083
3491
  /*
3084
3492
  * call-seq:
3085
- * conn.lo_create( oid ) -> Fixnum
3493
+ * conn.lo_create( oid ) -> Integer
3086
3494
  *
3087
3495
  * Creates a large object with oid _oid_. Returns the large object Oid.
3088
3496
  * On failure, it raises PG::Error.
@@ -3092,18 +3500,18 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3092
3500
  {
3093
3501
  Oid ret, lo_oid;
3094
3502
  PGconn *conn = pg_get_pgconn(self);
3095
- lo_oid = NUM2INT(in_lo_oid);
3503
+ lo_oid = NUM2UINT(in_lo_oid);
3096
3504
 
3097
3505
  ret = lo_create(conn, lo_oid);
3098
3506
  if (ret == InvalidOid)
3099
3507
  rb_raise(rb_ePGerror, "lo_create failed");
3100
3508
 
3101
- return INT2FIX(ret);
3509
+ return UINT2NUM(ret);
3102
3510
  }
3103
3511
 
3104
3512
  /*
3105
3513
  * call-seq:
3106
- * conn.lo_import(file) -> Fixnum
3514
+ * conn.lo_import(file) -> Integer
3107
3515
  *
3108
3516
  * Import a file to a large object. Returns a large object Oid.
3109
3517
  *
@@ -3118,11 +3526,11 @@ pgconn_loimport(VALUE self, VALUE filename)
3118
3526
 
3119
3527
  Check_Type(filename, T_STRING);
3120
3528
 
3121
- lo_oid = lo_import(conn, StringValuePtr(filename));
3529
+ lo_oid = lo_import(conn, StringValueCStr(filename));
3122
3530
  if (lo_oid == 0) {
3123
3531
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3124
3532
  }
3125
- return INT2FIX(lo_oid);
3533
+ return UINT2NUM(lo_oid);
3126
3534
  }
3127
3535
 
3128
3536
  /*
@@ -3135,15 +3543,12 @@ static VALUE
3135
3543
  pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3136
3544
  {
3137
3545
  PGconn *conn = pg_get_pgconn(self);
3138
- int oid;
3546
+ Oid oid;
3139
3547
  Check_Type(filename, T_STRING);
3140
3548
 
3141
- oid = NUM2INT(lo_oid);
3142
- if (oid < 0) {
3143
- rb_raise(rb_ePGerror, "invalid large object oid %d",oid);
3144
- }
3549
+ oid = NUM2UINT(lo_oid);
3145
3550
 
3146
- if (lo_export(conn, oid, StringValuePtr(filename)) < 0) {
3551
+ if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3147
3552
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3148
3553
  }
3149
3554
  return Qnil;
@@ -3151,7 +3556,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3151
3556
 
3152
3557
  /*
3153
3558
  * call-seq:
3154
- * conn.lo_open( oid, [mode] ) -> Fixnum
3559
+ * conn.lo_open( oid, [mode] ) -> Integer
3155
3560
  *
3156
3561
  * Open a large object of _oid_. Returns a large object descriptor
3157
3562
  * instance on success. The _mode_ argument specifies the mode for
@@ -3168,7 +3573,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3168
3573
  PGconn *conn = pg_get_pgconn(self);
3169
3574
 
3170
3575
  rb_scan_args(argc, argv, "11", &selfid, &nmode);
3171
- lo_oid = NUM2INT(selfid);
3576
+ lo_oid = NUM2UINT(selfid);
3172
3577
  if(NIL_P(nmode))
3173
3578
  mode = INV_READ;
3174
3579
  else
@@ -3182,7 +3587,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3182
3587
 
3183
3588
  /*
3184
3589
  * call-seq:
3185
- * conn.lo_write( lo_desc, buffer ) -> Fixnum
3590
+ * conn.lo_write( lo_desc, buffer ) -> Integer
3186
3591
  *
3187
3592
  * Writes the string _buffer_ to the large object _lo_desc_.
3188
3593
  * Returns the number of bytes written.
@@ -3240,7 +3645,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3240
3645
  return Qnil;
3241
3646
  }
3242
3647
 
3243
- str = rb_tainted_str_new(buffer, ret);
3648
+ str = rb_str_new(buffer, ret);
3244
3649
  xfree(buffer);
3245
3650
 
3246
3651
  return str;
@@ -3249,7 +3654,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3249
3654
 
3250
3655
  /*
3251
3656
  * call-seq:
3252
- * conn.lo_lseek( lo_desc, offset, whence ) -> Fixnum
3657
+ * conn.lo_lseek( lo_desc, offset, whence ) -> Integer
3253
3658
  *
3254
3659
  * Move the large object pointer _lo_desc_ to offset _offset_.
3255
3660
  * Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
@@ -3271,7 +3676,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3271
3676
 
3272
3677
  /*
3273
3678
  * call-seq:
3274
- * conn.lo_tell( lo_desc ) -> Fixnum
3679
+ * conn.lo_tell( lo_desc ) -> Integer
3275
3680
  *
3276
3681
  * Returns the current position of the large object _lo_desc_.
3277
3682
  */
@@ -3335,10 +3740,7 @@ static VALUE
3335
3740
  pgconn_lounlink(VALUE self, VALUE in_oid)
3336
3741
  {
3337
3742
  PGconn *conn = pg_get_pgconn(self);
3338
- int oid = NUM2INT(in_oid);
3339
-
3340
- if (oid < 0)
3341
- rb_raise(rb_ePGerror, "invalid oid %d",oid);
3743
+ Oid oid = NUM2UINT(in_oid);
3342
3744
 
3343
3745
  if(lo_unlink(conn,oid) < 0)
3344
3746
  rb_raise(rb_ePGerror,"lo_unlink failed");
@@ -3347,7 +3749,16 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3347
3749
  }
3348
3750
 
3349
3751
 
3350
- #ifdef M17N_SUPPORTED
3752
+ static void
3753
+ pgconn_set_internal_encoding_index( VALUE self )
3754
+ {
3755
+ int enc_idx;
3756
+ t_pg_connection *this = pg_get_connection_safe( self );
3757
+ rb_encoding *enc = pg_conn_enc_get( this->pgconn );
3758
+ enc_idx = rb_enc_to_index(enc);
3759
+ if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
3760
+ this->enc_idx = enc_idx;
3761
+ }
3351
3762
 
3352
3763
  /*
3353
3764
  * call-seq:
@@ -3393,7 +3804,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3393
3804
  pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3394
3805
  return enc;
3395
3806
  }
3396
- else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", RSTRING_PTR(enc)) == 0 ) {
3807
+ else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
3397
3808
  pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3398
3809
  return enc;
3399
3810
  }
@@ -3401,17 +3812,14 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3401
3812
  rb_encoding *rbenc = rb_to_encoding( enc );
3402
3813
  const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
3403
3814
 
3404
- if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3815
+ if ( gvl_PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3405
3816
  VALUE server_encoding = pgconn_external_encoding( self );
3406
3817
  rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
3407
3818
  rb_enc_name(rb_to_encoding(server_encoding)), name );
3408
3819
  }
3820
+ pgconn_set_internal_encoding_index( self );
3409
3821
  return enc;
3410
3822
  }
3411
-
3412
- rb_raise( rb_ePGerror, "unknown encoding: %s", RSTRING_PTR(rb_inspect(enc)) );
3413
-
3414
- return Qnil;
3415
3823
  }
3416
3824
 
3417
3825
 
@@ -3426,24 +3834,45 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3426
3834
  static VALUE
3427
3835
  pgconn_external_encoding(VALUE self)
3428
3836
  {
3429
- PGconn *conn = pg_get_pgconn( self );
3430
- VALUE encoding = rb_iv_get( self, "@external_encoding" );
3837
+ t_pg_connection *this = pg_get_connection_safe( self );
3431
3838
  rb_encoding *enc = NULL;
3432
3839
  const char *pg_encname = NULL;
3433
3840
 
3434
- /* Use cached value if found */
3435
- if ( RTEST(encoding) ) return encoding;
3436
-
3437
- pg_encname = PQparameterStatus( conn, "server_encoding" );
3841
+ pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
3438
3842
  enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
3439
- encoding = rb_enc_from_encoding( enc );
3843
+ return rb_enc_from_encoding( enc );
3844
+ }
3845
+
3846
+
3847
+ static VALUE
3848
+ pgconn_set_client_encoding_async1( VALUE args )
3849
+ {
3850
+ VALUE self = ((VALUE*)args)[0];
3851
+ VALUE encname = ((VALUE*)args)[1];
3852
+ VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3853
+ VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3854
+
3855
+ pgconn_async_exec(1, &query, self);
3856
+ return 0;
3857
+ }
3440
3858
 
3441
- rb_iv_set( self, "@external_encoding", encoding );
3442
3859
 
3443
- return encoding;
3860
+ static VALUE
3861
+ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3862
+ {
3863
+ UNUSED(arg);
3864
+ UNUSED(ex);
3865
+ return 1;
3444
3866
  }
3445
3867
 
3446
3868
 
3869
+ static VALUE
3870
+ pgconn_set_client_encoding_async( VALUE self, const char *encname )
3871
+ {
3872
+ VALUE args[] = { self, rb_str_new_cstr(encname) };
3873
+ return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3874
+ }
3875
+
3447
3876
 
3448
3877
  /*
3449
3878
  * call-seq:
@@ -3462,24 +3891,266 @@ pgconn_set_default_encoding( VALUE self )
3462
3891
 
3463
3892
  if (( enc = rb_default_internal_encoding() )) {
3464
3893
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3465
- if ( PQsetClientEncoding(conn, encname) != 0 )
3466
- rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
3894
+ if ( pgconn_set_client_encoding_async(self, encname) != 0 )
3895
+ rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
3467
3896
  encname, PQerrorMessage(conn) );
3897
+ pgconn_set_internal_encoding_index( self );
3468
3898
  return rb_enc_from_encoding( enc );
3469
3899
  } else {
3900
+ pgconn_set_internal_encoding_index( self );
3470
3901
  return Qnil;
3471
3902
  }
3472
3903
  }
3473
3904
 
3474
3905
 
3475
- #endif /* M17N_SUPPORTED */
3906
+ /*
3907
+ * call-seq:
3908
+ * res.type_map_for_queries = typemap
3909
+ *
3910
+ * Set the default TypeMap that is used for type casts of query bind parameters.
3911
+ *
3912
+ * +typemap+ must be a kind of PG::TypeMap .
3913
+ *
3914
+ */
3915
+ static VALUE
3916
+ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
3917
+ {
3918
+ t_pg_connection *this = pg_get_connection( self );
3476
3919
 
3920
+ if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3921
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3922
+ rb_obj_classname( typemap ) );
3923
+ }
3924
+ Check_Type(typemap, T_DATA);
3925
+ this->type_map_for_queries = typemap;
3477
3926
 
3927
+ return typemap;
3928
+ }
3478
3929
 
3930
+ /*
3931
+ * call-seq:
3932
+ * res.type_map_for_queries -> TypeMap
3933
+ *
3934
+ * Returns the default TypeMap that is currently set for type casts of query
3935
+ * bind parameters.
3936
+ *
3937
+ */
3938
+ static VALUE
3939
+ pgconn_type_map_for_queries_get(VALUE self)
3940
+ {
3941
+ t_pg_connection *this = pg_get_connection( self );
3942
+
3943
+ return this->type_map_for_queries;
3944
+ }
3945
+
3946
+ /*
3947
+ * call-seq:
3948
+ * res.type_map_for_results = typemap
3949
+ *
3950
+ * Set the default TypeMap that is used for type casts of result values.
3951
+ *
3952
+ * +typemap+ must be a kind of PG::TypeMap .
3953
+ *
3954
+ */
3955
+ static VALUE
3956
+ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
3957
+ {
3958
+ t_pg_connection *this = pg_get_connection( self );
3959
+
3960
+ if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3961
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3962
+ rb_obj_classname( typemap ) );
3963
+ }
3964
+ Check_Type(typemap, T_DATA);
3965
+ this->type_map_for_results = typemap;
3966
+
3967
+ return typemap;
3968
+ }
3969
+
3970
+ /*
3971
+ * call-seq:
3972
+ * res.type_map_for_results -> TypeMap
3973
+ *
3974
+ * Returns the default TypeMap that is currently set for type casts of result values.
3975
+ *
3976
+ */
3977
+ static VALUE
3978
+ pgconn_type_map_for_results_get(VALUE self)
3979
+ {
3980
+ t_pg_connection *this = pg_get_connection( self );
3981
+
3982
+ return this->type_map_for_results;
3983
+ }
3984
+
3985
+
3986
+ /*
3987
+ * call-seq:
3988
+ * res.encoder_for_put_copy_data = encoder
3989
+ *
3990
+ * Set the default coder that is used for type casting of parameters
3991
+ * to #put_copy_data .
3992
+ *
3993
+ * +encoder+ can be:
3994
+ * * a kind of PG::Coder
3995
+ * * +nil+ - disable type encoding, data must be a String.
3996
+ *
3997
+ */
3998
+ static VALUE
3999
+ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
4000
+ {
4001
+ t_pg_connection *this = pg_get_connection( self );
4002
+
4003
+ if( typemap != Qnil ){
4004
+ if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
4005
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
4006
+ rb_obj_classname( typemap ) );
4007
+ }
4008
+ Check_Type(typemap, T_DATA);
4009
+ }
4010
+ this->encoder_for_put_copy_data = typemap;
4011
+
4012
+ return typemap;
4013
+ }
4014
+
4015
+ /*
4016
+ * call-seq:
4017
+ * res.encoder_for_put_copy_data -> PG::Coder
4018
+ *
4019
+ * Returns the default coder object that is currently set for type casting of parameters
4020
+ * to #put_copy_data .
4021
+ *
4022
+ * Returns either:
4023
+ * * a kind of PG::Coder
4024
+ * * +nil+ - type encoding is disabled, data must be a String.
4025
+ *
4026
+ */
4027
+ static VALUE
4028
+ pgconn_encoder_for_put_copy_data_get(VALUE self)
4029
+ {
4030
+ t_pg_connection *this = pg_get_connection( self );
4031
+
4032
+ return this->encoder_for_put_copy_data;
4033
+ }
4034
+
4035
+ /*
4036
+ * call-seq:
4037
+ * res.decoder_for_get_copy_data = decoder
4038
+ *
4039
+ * Set the default coder that is used for type casting of received data
4040
+ * by #get_copy_data .
4041
+ *
4042
+ * +decoder+ can be:
4043
+ * * a kind of PG::Coder
4044
+ * * +nil+ - disable type decoding, returned data will be a String.
4045
+ *
4046
+ */
4047
+ static VALUE
4048
+ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE typemap)
4049
+ {
4050
+ t_pg_connection *this = pg_get_connection( self );
4051
+
4052
+ if( typemap != Qnil ){
4053
+ if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
4054
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
4055
+ rb_obj_classname( typemap ) );
4056
+ }
4057
+ Check_Type(typemap, T_DATA);
4058
+ }
4059
+ this->decoder_for_get_copy_data = typemap;
4060
+
4061
+ return typemap;
4062
+ }
4063
+
4064
+ /*
4065
+ * call-seq:
4066
+ * res.decoder_for_get_copy_data -> PG::Coder
4067
+ *
4068
+ * Returns the default coder object that is currently set for type casting of received
4069
+ * data by #get_copy_data .
4070
+ *
4071
+ * Returns either:
4072
+ * * a kind of PG::Coder
4073
+ * * +nil+ - type encoding is disabled, returned data will be a String.
4074
+ *
4075
+ */
4076
+ static VALUE
4077
+ pgconn_decoder_for_get_copy_data_get(VALUE self)
4078
+ {
4079
+ t_pg_connection *this = pg_get_connection( self );
4080
+
4081
+ return this->decoder_for_get_copy_data;
4082
+ }
4083
+
4084
+ /*
4085
+ * call-seq:
4086
+ * conn.field_name_type = Symbol
4087
+ *
4088
+ * Set default type of field names of results retrieved by this connection.
4089
+ * It can be set to one of:
4090
+ * * +:string+ to use String based field names
4091
+ * * +:symbol+ to use Symbol based field names
4092
+ *
4093
+ * The default is +:string+ .
4094
+ *
4095
+ * Settings the type of field names affects only future results.
4096
+ *
4097
+ * See further description at PG::Result#field_name_type=
4098
+ *
4099
+ */
4100
+ static VALUE
4101
+ pgconn_field_name_type_set(VALUE self, VALUE sym)
4102
+ {
4103
+ t_pg_connection *this = pg_get_connection( self );
4104
+
4105
+ this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4106
+ if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4107
+ else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4108
+ else if ( sym == sym_string );
4109
+ else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4110
+
4111
+ return sym;
4112
+ }
4113
+
4114
+ /*
4115
+ * call-seq:
4116
+ * conn.field_name_type -> Symbol
4117
+ *
4118
+ * Get type of field names.
4119
+ *
4120
+ * See description at #field_name_type=
4121
+ */
4122
+ static VALUE
4123
+ pgconn_field_name_type_get(VALUE self)
4124
+ {
4125
+ t_pg_connection *this = pg_get_connection( self );
4126
+
4127
+ if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4128
+ return sym_symbol;
4129
+ } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4130
+ return sym_static_symbol;
4131
+ } else {
4132
+ return sym_string;
4133
+ }
4134
+ }
4135
+
4136
+
4137
+ /*
4138
+ * Document-class: PG::Connection
4139
+ */
3479
4140
  void
3480
4141
  init_pg_connection()
3481
4142
  {
4143
+ s_id_encode = rb_intern("encode");
4144
+ sym_type = ID2SYM(rb_intern("type"));
4145
+ sym_format = ID2SYM(rb_intern("format"));
4146
+ sym_value = ID2SYM(rb_intern("value"));
4147
+ sym_string = ID2SYM(rb_intern("string"));
4148
+ sym_symbol = ID2SYM(rb_intern("symbol"));
4149
+ sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
4150
+
3482
4151
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4152
+ /* Help rdoc to known the Constants module */
4153
+ /* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
3483
4154
  rb_include_module(rb_cPGconn, rb_mPGconstants);
3484
4155
 
3485
4156
  /****** PG::Connection CLASS METHODS ******/
@@ -3497,9 +4168,7 @@ init_pg_connection()
3497
4168
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
3498
4169
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
3499
4170
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
3500
- #ifdef HAVE_PQPING
3501
4171
  rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
3502
- #endif
3503
4172
 
3504
4173
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
3505
4174
  rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
@@ -3518,6 +4187,9 @@ init_pg_connection()
3518
4187
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
3519
4188
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
3520
4189
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4190
+ #ifdef HAVE_PQCONNINFO
4191
+ rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
4192
+ #endif
3521
4193
  rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
3522
4194
  rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
3523
4195
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
@@ -3526,39 +4198,47 @@ init_pg_connection()
3526
4198
  rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
3527
4199
  rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
3528
4200
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
3529
- #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
3530
4201
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
3531
- #endif
3532
4202
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
3533
4203
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
3534
4204
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
3535
4205
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
3536
4206
 
3537
4207
  /****** PG::Connection INSTANCE METHODS: Command Execution ******/
3538
- rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
3539
- rb_define_alias(rb_cPGconn, "query", "exec");
3540
- rb_define_method(rb_cPGconn, "exec_params", pgconn_exec_params, -1);
3541
- rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
3542
- rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
3543
- rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
3544
- rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
4208
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
4209
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
4210
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
4211
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
4212
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
4213
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
4214
+
4215
+ rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4216
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
4217
+ rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
4218
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4219
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4220
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4221
+
4222
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
4223
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4224
+ rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
4225
+ rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
4226
+ rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4227
+ rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4228
+ rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4229
+
3545
4230
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
3546
4231
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3547
4232
  rb_define_alias(rb_cPGconn, "escape", "escape_string");
3548
- #ifdef HAVE_PQESCAPELITERAL
3549
4233
  rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
3550
- #endif
3551
- #ifdef HAVE_PQESCAPEIDENTIFIER
3552
4234
  rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
3553
- #endif
3554
4235
  rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
3555
4236
  rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
3556
- #ifdef HAVE_PQSETSINGLEROWMODE
3557
4237
  rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
3558
- #endif
3559
4238
 
3560
4239
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
3561
4240
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
4241
+ rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
3562
4242
  rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
3563
4243
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
3564
4244
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
@@ -3570,6 +4250,7 @@ init_pg_connection()
3570
4250
  rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
3571
4251
  rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
3572
4252
  rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
4253
+ rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
3573
4254
 
3574
4255
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
3575
4256
  rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
@@ -3578,12 +4259,15 @@ init_pg_connection()
3578
4259
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
3579
4260
 
3580
4261
  /****** PG::Connection INSTANCE METHODS: COPY ******/
3581
- rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, 1);
4262
+ rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, -1);
3582
4263
  rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
3583
4264
  rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
3584
4265
 
3585
4266
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
3586
4267
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4268
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4269
+ rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4270
+ #endif
3587
4271
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
3588
4272
  rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
3589
4273
 
@@ -3600,9 +4284,16 @@ init_pg_connection()
3600
4284
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
3601
4285
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
3602
4286
  rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
3603
- rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
3604
- rb_define_alias(rb_cPGconn, "async_query", "async_exec");
3605
4287
  rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
4288
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
4289
+ rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
4290
+ #endif
4291
+
4292
+ #ifdef HAVE_PQSSLATTRIBUTE
4293
+ rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
4294
+ rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
4295
+ rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4296
+ #endif
3606
4297
 
3607
4298
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
3608
4299
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
@@ -3632,12 +4323,20 @@ init_pg_connection()
3632
4323
  rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
3633
4324
  rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
3634
4325
 
3635
- #ifdef M17N_SUPPORTED
3636
4326
  rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
3637
4327
  rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
3638
4328
  rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
3639
4329
  rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
3640
- #endif /* M17N_SUPPORTED */
3641
4330
 
4331
+ rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
4332
+ rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
4333
+ rb_define_method(rb_cPGconn, "type_map_for_results=", pgconn_type_map_for_results_set, 1);
4334
+ rb_define_method(rb_cPGconn, "type_map_for_results", pgconn_type_map_for_results_get, 0);
4335
+ rb_define_method(rb_cPGconn, "encoder_for_put_copy_data=", pgconn_encoder_for_put_copy_data_set, 1);
4336
+ rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
4337
+ rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
4338
+ rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
4339
+
4340
+ rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
4341
+ rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
3642
4342
  }
3643
-