pg 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/errorcodes.txt CHANGED
@@ -2,7 +2,7 @@
2
2
  # errcodes.txt
3
3
  # PostgreSQL error codes
4
4
  #
5
- # Copyright (c) 2003-2013, PostgreSQL Global Development Group
5
+ # Copyright (c) 2003-2016, PostgreSQL Global Development Group
6
6
  #
7
7
  # This list serves as the basis for generating source files containing error
8
8
  # codes. It is kept in a common format to make sure all these source files have
@@ -177,6 +177,8 @@ Section: Class 22 - Data Exception
177
177
  2201B E ERRCODE_INVALID_REGULAR_EXPRESSION invalid_regular_expression
178
178
  2201W E ERRCODE_INVALID_ROW_COUNT_IN_LIMIT_CLAUSE invalid_row_count_in_limit_clause
179
179
  2201X E ERRCODE_INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE invalid_row_count_in_result_offset_clause
180
+ 2202H E ERRCODE_INVALID_TABLESAMPLE_ARGUMENT invalid_tablesample_argument
181
+ 2202G E ERRCODE_INVALID_TABLESAMPLE_REPEAT invalid_tablesample_repeat
180
182
  22009 E ERRCODE_INVALID_TIME_ZONE_DISPLACEMENT_VALUE invalid_time_zone_displacement_value
181
183
  2200C E ERRCODE_INVALID_USE_OF_ESCAPE_CHARACTER invalid_use_of_escape_character
182
184
  2200G E ERRCODE_MOST_SPECIFIC_TYPE_MISMATCH most_specific_type_mismatch
@@ -278,6 +280,7 @@ Section: Class 39 - External Routine Invocation Exception
278
280
  39004 E ERRCODE_E_R_I_E_NULL_VALUE_NOT_ALLOWED null_value_not_allowed
279
281
  39P01 E ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED trigger_protocol_violated
280
282
  39P02 E ERRCODE_E_R_I_E_SRF_PROTOCOL_VIOLATED srf_protocol_violated
283
+ 39P03 E ERRCODE_E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED event_trigger_protocol_violated
281
284
 
282
285
  Section: Class 3B - Savepoint Exception
283
286
 
@@ -454,6 +457,7 @@ P0000 E ERRCODE_PLPGSQL_ERROR plp
454
457
  P0001 E ERRCODE_RAISE_EXCEPTION raise_exception
455
458
  P0002 E ERRCODE_NO_DATA_FOUND no_data_found
456
459
  P0003 E ERRCODE_TOO_MANY_ROWS too_many_rows
460
+ P0004 E ERRCODE_ASSERT_FAILURE assert_failure
457
461
 
458
462
  Section: Class XX - Internal Error
459
463
 
data/ext/extconf.rb CHANGED
@@ -24,7 +24,11 @@ if enable_config("windows-cross")
24
24
  else
25
25
  # Native build
26
26
 
27
- if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
27
+ pgconfig = with_config('pg-config') ||
28
+ with_config('pg_config') ||
29
+ find_executable('pg_config')
30
+
31
+ if pgconfig && pgconfig != 'ignore'
28
32
  $stderr.puts "Using config values from %s" % [ pgconfig ]
29
33
  incdir = `"#{pgconfig}" --includedir`.chomp
30
34
  libdir = `"#{pgconfig}" --libdir`.chomp
@@ -43,6 +47,9 @@ else
43
47
  end
44
48
  end
45
49
 
50
+ if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
51
+ append_cppflags( '-D__EXTENSIONS__' )
52
+ end
46
53
 
47
54
  find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
48
55
  find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
@@ -73,7 +80,7 @@ have_func 'PQlibVersion'
73
80
  have_func 'PQping'
74
81
  have_func 'PQsetSingleRowMode'
75
82
  have_func 'PQconninfo'
76
- have_func 'PQhostaddr'
83
+ have_func 'PQsslAttribute'
77
84
 
78
85
  have_func 'rb_encdb_alias'
79
86
  have_func 'rb_enc_alias'
@@ -93,8 +100,13 @@ $defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
93
100
 
94
101
  # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
95
102
  have_header 'unistd.h'
103
+ have_header 'inttypes.h'
96
104
  have_header 'ruby/st.h' or have_header 'st.h' or abort "pg currently requires the ruby/st.h header"
97
105
 
106
+ checking_for "C99 variable length arrays" do
107
+ $defs.push( "-DHAVE_VARIABLE_LENGTH_ARRAYS" ) if try_compile('void test_vla(int l){ int vla[l]; }')
108
+ end
109
+
98
110
  create_header()
99
111
  create_makefile( "pg_ext" )
100
112
 
data/ext/gvl_wrappers.h CHANGED
@@ -195,6 +195,9 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
195
195
  #define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
196
196
  param(PGconn *, conn)
197
197
 
198
+ #define FOR_EACH_PARAM_OF_PQsetClientEncoding(param) \
199
+ param(PGconn *, conn)
200
+
198
201
  #define FOR_EACH_PARAM_OF_PQisBusy(param)
199
202
 
200
203
  #define FOR_EACH_PARAM_OF_PQcancel(param) \
@@ -226,6 +229,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
226
229
  function(PQsendQueryPrepared, GVL_TYPE_NONVOID, int, int, resultFormat) \
227
230
  function(PQsendDescribePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
228
231
  function(PQsendDescribePortal, GVL_TYPE_NONVOID, int, const char *, portal) \
232
+ function(PQsetClientEncoding, GVL_TYPE_NONVOID, int, const char *, encoding) \
229
233
  function(PQisBusy, GVL_TYPE_NONVOID, int, PGconn *, conn) \
230
234
  function(PQcancel, GVL_TYPE_NONVOID, int, int, errbufsize);
231
235
 
data/ext/pg.c CHANGED
@@ -1,12 +1,13 @@
1
1
  /*
2
2
  * pg.c - Toplevel extension
3
- * $Id: pg.c,v a9724aef9116 2014/12/12 21:03:27 lars $
3
+ * $Id: pg.c,v c77d0997b4e4 2016/08/20 17:30:03 ged $
4
4
  *
5
5
  * Author/s:
6
6
  *
7
7
  * - Jeff Davis <ruby-pg@j-davis.com>
8
8
  * - Guy Decoux (ts) <decoux@moulon.inra.fr>
9
9
  * - Michael Granger <ged@FaerieMUD.org>
10
+ * - Lars Kanis <lars@greiz-reinsdorf.de>
10
11
  * - Dave Lee
11
12
  * - Eiji Matsumoto <usagi@ruby.club.or.jp>
12
13
  * - Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -15,10 +16,10 @@
15
16
  * See Contributors.rdoc for the many additional fine people that have contributed
16
17
  * to this library over the years.
17
18
  *
18
- * Copyright (c) 1997-2012 by the authors.
19
+ * Copyright (c) 1997-2016 by the authors.
19
20
  *
20
21
  * You may redistribute this software under the same terms as Ruby itself; see
21
- * http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
22
+ * https://www.ruby-lang.org/en/about/license.txt or the BSDL file in the source
22
23
  * for details.
23
24
  *
24
25
  * Portions of the code are from the PostgreSQL project, and are distributed
@@ -252,7 +253,7 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
252
253
  * char *current_out, *end_capa;
253
254
  * PG_RB_STR_NEW( string, current_out, end_capa );
254
255
  * while( data_is_going_to_be_processed ){
255
- * PG_RB_STR_ENSURE_CAPA( string, 2 current_out, end_capa );
256
+ * PG_RB_STR_ENSURE_CAPA( string, 2, current_out, end_capa );
256
257
  * *current_out++ = databyte1;
257
258
  * *current_out++ = databyte2;
258
259
  * }
data/ext/pg.h CHANGED
@@ -9,6 +9,9 @@
9
9
  #include <stdio.h>
10
10
  #include <stdlib.h>
11
11
  #include <sys/types.h>
12
+ #if !defined(_WIN32)
13
+ # include <sys/time.h>
14
+ #endif
12
15
  #if defined(HAVE_UNISTD_H) && !defined(_WIN32)
13
16
  # include <unistd.h>
14
17
  #endif /* HAVE_UNISTD_H */
@@ -133,6 +136,15 @@
133
136
  typedef long suseconds_t;
134
137
  #endif
135
138
 
139
+ #if defined(HAVE_VARIABLE_LENGTH_ARRAYS)
140
+ #define PG_VARIABLE_LENGTH_ARRAY(type, name, len, maxlen) type name[(len)];
141
+ #else
142
+ #define PG_VARIABLE_LENGTH_ARRAY(type, name, len, maxlen) \
143
+ type name[(maxlen)] = {(len)>(maxlen) ? (rb_raise(rb_eArgError, "Number of " #name " (%d) exceeds allowed maximum of " #maxlen, (len) ), (type)1) : (type)0};
144
+
145
+ #define PG_MAX_COLUMNS 4000
146
+ #endif
147
+
136
148
  /* The data behind each PG::Connection object */
137
149
  typedef struct {
138
150
  PGconn *pgconn;
@@ -196,7 +208,7 @@ typedef struct {
196
208
  } t_pg_result;
197
209
 
198
210
 
199
- typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
211
+ typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *, int);
200
212
  typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
201
213
  typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
202
214
  typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
@@ -312,7 +324,8 @@ void init_pg_binary_decoder _(( void ));
312
324
  VALUE lookup_error_class _(( const char * ));
313
325
  VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
314
326
  VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
315
- int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *));
327
+ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *, int));
328
+ int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
316
329
  t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
317
330
  t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
318
331
  void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
@@ -1,12 +1,14 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_decoder.c,v 185638b52684 2014/11/08 20:43:53 lars $
3
+ * $Id: pg_binary_decoder.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
4
4
  *
5
5
  */
6
6
 
7
7
  #include "pg.h"
8
8
  #include "util.h"
9
+ #ifdef HAVE_INTTYPES_H
9
10
  #include <inttypes.h>
11
+ #endif
10
12
 
11
13
  VALUE rb_mPG_BinaryDecoder;
12
14
 
@@ -1,12 +1,14 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_encoder.c,v ac23631c96d9 2014/10/14 11:50:21 lars $
3
+ * $Id: pg_binary_encoder.c,v e61a06f1f5ed 2015/12/25 21:14:21 lars $
4
4
  *
5
5
  */
6
6
 
7
7
  #include "pg.h"
8
8
  #include "util.h"
9
+ #ifdef HAVE_INTTYPES_H
9
10
  #include <inttypes.h>
11
+ #endif
10
12
 
11
13
  VALUE rb_mPG_BinaryEncoder;
12
14
 
@@ -20,16 +22,16 @@ VALUE rb_mPG_BinaryEncoder;
20
22
  *
21
23
  */
22
24
  static int
23
- pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
25
+ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
24
26
  {
25
- char bool;
27
+ char mybool;
26
28
  switch(value){
27
- case Qtrue : bool = 1; break;
28
- case Qfalse : bool = 0; break;
29
+ case Qtrue : mybool = 1; break;
30
+ case Qfalse : mybool = 0; break;
29
31
  default :
30
32
  rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
31
33
  }
32
- if(out) *out = bool;
34
+ if(out) *out = mybool;
33
35
  return 1;
34
36
  }
35
37
 
@@ -42,7 +44,7 @@ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
42
44
  *
43
45
  */
44
46
  static int
45
- pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
47
+ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
46
48
  {
47
49
  if(out){
48
50
  write_nbo16(NUM2INT(*intermediate), out);
@@ -61,7 +63,7 @@ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
61
63
  *
62
64
  */
63
65
  static int
64
- pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
66
+ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
65
67
  {
66
68
  if(out){
67
69
  write_nbo32(NUM2LONG(*intermediate), out);
@@ -80,7 +82,7 @@ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
80
82
  *
81
83
  */
82
84
  static int
83
- pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
85
+ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
84
86
  {
85
87
  if(out){
86
88
  write_nbo64(NUM2LL(*intermediate), out);
@@ -98,7 +100,7 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
98
100
  *
99
101
  */
100
102
  static int
101
- pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
103
+ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
102
104
  {
103
105
  int strlen;
104
106
  VALUE subint;
@@ -107,13 +109,13 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
107
109
 
108
110
  if(out){
109
111
  /* Second encoder pass, if required */
110
- strlen = enc_func(this->elem, value, out, intermediate);
112
+ strlen = enc_func(this->elem, value, out, intermediate, enc_idx);
111
113
  strlen = base64_decode( out, out, strlen );
112
114
 
113
115
  return strlen;
114
116
  } else {
115
117
  /* First encoder pass */
116
- strlen = enc_func(this->elem, value, NULL, &subint);
118
+ strlen = enc_func(this->elem, value, NULL, &subint, enc_idx);
117
119
 
118
120
  if( strlen == -1 ){
119
121
  /* Encoded string is returned in subint */
data/ext/pg_coder.c CHANGED
@@ -114,13 +114,24 @@ pg_composite_decoder_allocate( VALUE klass )
114
114
  *
115
115
  */
116
116
  static VALUE
117
- pg_coder_encode(VALUE self, VALUE value)
117
+ pg_coder_encode(int argc, VALUE *argv, VALUE self)
118
118
  {
119
119
  VALUE res;
120
120
  VALUE intermediate;
121
+ VALUE value;
121
122
  int len, len2;
123
+ int enc_idx;
122
124
  t_pg_coder *this = DATA_PTR(self);
123
125
 
126
+ if(argc < 1 || argc > 2){
127
+ rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
128
+ }else if(argc == 1){
129
+ enc_idx = rb_ascii8bit_encindex();
130
+ }else{
131
+ enc_idx = rb_to_encoding_index(argv[1]);
132
+ }
133
+ value = argv[0];
134
+
124
135
  if( NIL_P(value) )
125
136
  return Qnil;
126
137
 
@@ -128,7 +139,7 @@ pg_coder_encode(VALUE self, VALUE value)
128
139
  rb_raise(rb_eRuntimeError, "no encoder function defined");
129
140
  }
130
141
 
131
- len = this->enc_func( this, value, NULL, &intermediate );
142
+ len = this->enc_func( this, value, NULL, &intermediate, enc_idx );
132
143
 
133
144
  if( len == -1 ){
134
145
  /* The intermediate value is a String that can be used directly. */
@@ -137,7 +148,8 @@ pg_coder_encode(VALUE self, VALUE value)
137
148
  }
138
149
 
139
150
  res = rb_str_new(NULL, len);
140
- len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate);
151
+ PG_ENCODING_SET_NOCHECK(res, enc_idx);
152
+ len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate, enc_idx );
141
153
  if( len < len2 ){
142
154
  rb_bug("%s: result length of first encoder run (%i) is less than second run (%i)",
143
155
  rb_obj_classname( self ), len, len2 );
@@ -165,8 +177,8 @@ static VALUE
165
177
  pg_coder_decode(int argc, VALUE *argv, VALUE self)
166
178
  {
167
179
  char *val;
168
- VALUE tuple = -1;
169
- VALUE field = -1;
180
+ int tuple = -1;
181
+ int field = -1;
170
182
  VALUE res;
171
183
  t_pg_coder *this = DATA_PTR(self);
172
184
 
@@ -359,10 +371,19 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
359
371
 
360
372
 
361
373
  static int
362
- pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
374
+ pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
363
375
  {
364
- *intermediate = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
365
- StringValue( *intermediate );
376
+ int arity = rb_obj_method_arity(conv->coder_obj, s_id_encode);
377
+ if( arity == 1 ){
378
+ VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
379
+ StringValue( out_str );
380
+ *intermediate = rb_str_export_to_enc(out_str, rb_enc_from_index(enc_idx));
381
+ }else{
382
+ VALUE enc = rb_enc_from_encoding(rb_enc_from_index(enc_idx));
383
+ VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 2, value, enc );
384
+ StringValue( out_str );
385
+ *intermediate = out_str;
386
+ }
366
387
  return -1;
367
388
  }
368
389
 
@@ -442,7 +463,7 @@ init_pg_coder()
442
463
  * This accessor is only used in PG::Coder#inspect .
443
464
  */
444
465
  rb_define_attr( rb_cPG_Coder, "name", 1, 1 );
445
- rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, 1 );
466
+ rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, -1 );
446
467
  rb_define_method( rb_cPG_Coder, "decode", pg_coder_decode, -1 );
447
468
 
448
469
  /* Document-class: PG::SimpleCoder < PG::Coder */
data/ext/pg_connection.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_connection.c - PG::Connection class extension
3
- * $Id: pg_connection.c,v a7befacdef4e 2014/12/12 20:57:14 lars $
3
+ * $Id: pg_connection.c,v 4d9c4ee44d11 2016/09/04 17:32:03 lars $
4
4
  *
5
5
  */
6
6
 
@@ -52,7 +52,7 @@ pg_get_connection( VALUE self )
52
52
  * Fetch the PG::Connection object data pointer and check it's
53
53
  * PGconn data pointer for sanity.
54
54
  */
55
- t_pg_connection *
55
+ static t_pg_connection *
56
56
  pg_get_connection_safe( VALUE self )
57
57
  {
58
58
  t_pg_connection *this;
@@ -88,7 +88,7 @@ pg_get_pgconn( VALUE self )
88
88
  /*
89
89
  * Close the associated socket IO object if there is one.
90
90
  */
91
- void
91
+ static void
92
92
  pgconn_close_socket_io( VALUE self )
93
93
  {
94
94
  t_pg_connection *this = pg_get_connection( self );
@@ -141,6 +141,16 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
141
141
  return ary;
142
142
  }
143
143
 
144
+ static const char *pg_cstr_enc(VALUE str, int enc_idx){
145
+ const char *ptr = StringValueCStr(str);
146
+ if( ENCODING_GET(str) == enc_idx ){
147
+ return ptr;
148
+ } else {
149
+ str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
150
+ return StringValueCStr(str);
151
+ }
152
+ }
153
+
144
154
 
145
155
  /*
146
156
  * GC Mark function
@@ -373,7 +383,7 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
373
383
 
374
384
 
375
385
  /*
376
- * Document-method: conndefaults
386
+ * Document-method: PG::Connection.conndefaults
377
387
  *
378
388
  * call-seq:
379
389
  * PG::Connection.conndefaults() -> Array
@@ -627,22 +637,6 @@ pgconn_host(VALUE self)
627
637
  return rb_tainted_str_new2(host);
628
638
  }
629
639
 
630
- #ifdef HAVE_PQHOSTADDR
631
- /*
632
- * call-seq:
633
- * conn.hostaddr()
634
- *
635
- * Returns the server numeric IP address of the connection.
636
- */
637
- static VALUE
638
- pgconn_hostaddr(VALUE self)
639
- {
640
- char *hostaddr = PQhostaddr(pg_get_pgconn(self));
641
- if (!hostaddr) return Qnil;
642
- return rb_tainted_str_new2(hostaddr);
643
- }
644
- #endif
645
-
646
640
  /*
647
641
  * call-seq:
648
642
  * conn.port()
@@ -963,9 +957,9 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
963
957
 
964
958
  /* If called with no parameters, use PQexec */
965
959
  if ( argc == 1 ) {
966
- Check_Type(argv[0], T_STRING);
960
+ VALUE query_str = argv[0];
967
961
 
968
- result = gvl_PQexec(conn, StringValueCStr(argv[0]));
962
+ result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
969
963
  rb_pgresult = pg_new_result(result, self);
970
964
  pg_result_check(rb_pgresult);
971
965
  if (rb_block_given_p()) {
@@ -994,6 +988,10 @@ struct query_params_data {
994
988
  * Filled by caller
995
989
  */
996
990
 
991
+ /* The character encoding index of the connection. Any strings
992
+ * given as query parameters are converted to this encoding.
993
+ */
994
+ int enc_idx;
997
995
  /* Is the query function to execute one with types array? */
998
996
  int with_types;
999
997
  /* Array of query params from user space */
@@ -1154,7 +1152,7 @@ alloc_query_params(struct query_params_data *paramsData)
1154
1152
  VALUE intermediate;
1155
1153
 
1156
1154
  /* 1st pass for retiving the required memory space */
1157
- int len = enc_func(conv, param_value, NULL, &intermediate);
1155
+ int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
1158
1156
 
1159
1157
  if( len == -1 ){
1160
1158
  /* The intermediate value is a String that can be used directly. */
@@ -1178,7 +1176,7 @@ alloc_query_params(struct query_params_data *paramsData)
1178
1176
  }
1179
1177
 
1180
1178
  /* 2nd pass for writing the data to prepared buffer */
1181
- len = enc_func(conv, param_value, typecast_buf, &intermediate);
1179
+ len = enc_func(conv, param_value, typecast_buf, &intermediate, paramsData->enc_idx);
1182
1180
  paramsData->values[i] = typecast_buf;
1183
1181
  if( paramsData->formats[i] == 0 ){
1184
1182
  /* text format strings must be zero terminated and lengths are ignored */
@@ -1274,7 +1272,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1274
1272
  VALUE command, in_res_fmt;
1275
1273
  int nParams;
1276
1274
  int resultFormat;
1277
- struct query_params_data paramsData;
1275
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1278
1276
 
1279
1277
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1280
1278
  paramsData.with_types = 1;
@@ -1291,7 +1289,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1291
1289
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1292
1290
  nParams = alloc_query_params( &paramsData );
1293
1291
 
1294
- result = gvl_PQexecParams(conn, StringValueCStr(command), nParams, paramsData.types,
1292
+ result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1295
1293
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1296
1294
 
1297
1295
  free_query_params( &paramsData );
@@ -1337,10 +1335,13 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1337
1335
  int i = 0;
1338
1336
  int nParams = 0;
1339
1337
  Oid *paramTypes = NULL;
1338
+ const char *name_cstr;
1339
+ const char *command_cstr;
1340
+ int enc_idx = ENCODING_GET(self);
1340
1341
 
1341
1342
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1342
- Check_Type(name, T_STRING);
1343
- Check_Type(command, T_STRING);
1343
+ name_cstr = pg_cstr_enc(name, enc_idx);
1344
+ command_cstr = pg_cstr_enc(command, enc_idx);
1344
1345
 
1345
1346
  if(! NIL_P(in_paramtypes)) {
1346
1347
  Check_Type(in_paramtypes, T_ARRAY);
@@ -1354,8 +1355,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1354
1355
  paramTypes[i] = NUM2UINT(param);
1355
1356
  }
1356
1357
  }
1357
- result = gvl_PQprepare(conn, StringValueCStr(name), StringValueCStr(command),
1358
- nParams, paramTypes);
1358
+ result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1359
1359
 
1360
1360
  xfree(paramTypes);
1361
1361
 
@@ -1408,11 +1408,10 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1408
1408
  VALUE name, in_res_fmt;
1409
1409
  int nParams;
1410
1410
  int resultFormat;
1411
- struct query_params_data paramsData;
1411
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1412
1412
 
1413
1413
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1414
1414
  paramsData.with_types = 0;
1415
- Check_Type(name, T_STRING);
1416
1415
 
1417
1416
  if(NIL_P(paramsData.params)) {
1418
1417
  paramsData.params = rb_ary_new2(0);
@@ -1422,7 +1421,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1422
1421
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1423
1422
  nParams = alloc_query_params( &paramsData );
1424
1423
 
1425
- result = gvl_PQexecPrepared(conn, StringValueCStr(name), nParams,
1424
+ result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1426
1425
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1427
1426
  resultFormat);
1428
1427
 
@@ -1450,13 +1449,12 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1450
1449
  PGresult *result;
1451
1450
  VALUE rb_pgresult;
1452
1451
  PGconn *conn = pg_get_pgconn(self);
1453
- char *stmt;
1454
- if(stmt_name == Qnil) {
1452
+ const char *stmt;
1453
+ if(NIL_P(stmt_name)) {
1455
1454
  stmt = NULL;
1456
1455
  }
1457
1456
  else {
1458
- Check_Type(stmt_name, T_STRING);
1459
- stmt = StringValueCStr(stmt_name);
1457
+ stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1460
1458
  }
1461
1459
  result = gvl_PQdescribePrepared(conn, stmt);
1462
1460
  rb_pgresult = pg_new_result(result, self);
@@ -1478,13 +1476,12 @@ pgconn_describe_portal(self, stmt_name)
1478
1476
  PGresult *result;
1479
1477
  VALUE rb_pgresult;
1480
1478
  PGconn *conn = pg_get_pgconn(self);
1481
- char *stmt;
1482
- if(stmt_name == Qnil) {
1479
+ const char *stmt;
1480
+ if(NIL_P(stmt_name)) {
1483
1481
  stmt = NULL;
1484
1482
  }
1485
1483
  else {
1486
- Check_Type(stmt_name, T_STRING);
1487
- stmt = StringValueCStr(stmt_name);
1484
+ stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1488
1485
  }
1489
1486
  result = gvl_PQdescribePortal(conn, stmt);
1490
1487
  rb_pgresult = pg_new_result(result, self);
@@ -1526,10 +1523,6 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1526
1523
  * call-seq:
1527
1524
  * conn.escape_string( str ) -> String
1528
1525
  *
1529
- * Connection instance method for versions of 8.1 and higher of libpq
1530
- * uses PQescapeStringConn, which is safer. Avoid calling as a class method,
1531
- * the class method uses the deprecated PQescapeString() API function.
1532
- *
1533
1526
  * Returns a SQL-safe version of the String _str_.
1534
1527
  * This is the preferred way to make strings safe for inclusion in
1535
1528
  * SQL queries.
@@ -1538,32 +1531,41 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1538
1531
  * inside of SQL commands.
1539
1532
  *
1540
1533
  * Encoding of escaped string will be equal to client encoding of connection.
1534
+ *
1535
+ * NOTE: This class version of this method can only be used safely in client
1536
+ * programs that use a single PostgreSQL connection at a time (in this case it can
1537
+ * find out what it needs to know "behind the scenes"). It might give the wrong
1538
+ * results if used in programs that use multiple database connections; use the
1539
+ * same method on the connection object in such cases.
1541
1540
  */
1542
1541
  static VALUE
1543
1542
  pgconn_s_escape(VALUE self, VALUE string)
1544
1543
  {
1545
- char *escaped;
1546
1544
  size_t size;
1547
1545
  int error;
1548
1546
  VALUE result;
1547
+ int enc_idx;
1548
+ int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1549
1549
 
1550
1550
  Check_Type(string, T_STRING);
1551
+ enc_idx = ENCODING_GET( singleton ? string : self );
1552
+ if( ENCODING_GET(string) != enc_idx ){
1553
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1554
+ }
1551
1555
 
1552
- escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
1553
- if(rb_obj_class(self) == rb_cPGconn) {
1554
- size = PQescapeStringConn(pg_get_pgconn(self), escaped,
1556
+ result = rb_str_new(NULL, RSTRING_LEN(string) * 2 + 1);
1557
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1558
+ if( !singleton ) {
1559
+ size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1555
1560
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1556
1561
  if(error) {
1557
- xfree(escaped);
1558
1562
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1559
1563
  }
1560
1564
  } else {
1561
- size = PQescapeString(escaped, RSTRING_PTR(string), RSTRING_LENINT(string));
1565
+ size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1562
1566
  }
1563
- result = rb_str_new(escaped, size);
1564
- xfree(escaped);
1567
+ rb_str_set_len(result, size);
1565
1568
  OBJ_INFECT(result, string);
1566
- PG_ENCODING_SET_NOCHECK(result, ENCODING_GET( rb_obj_class(self) == rb_cPGconn ? self : string ));
1567
1569
 
1568
1570
  return result;
1569
1571
  }
@@ -1572,13 +1574,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1572
1574
  * call-seq:
1573
1575
  * conn.escape_bytea( string ) -> String
1574
1576
  *
1575
- * Connection instance method for versions of 8.1 and higher of libpq
1576
- * uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
1577
- * the class method uses the deprecated PQescapeBytea() API function.
1578
- *
1579
- * Use the instance method version of this function, it is safer than the
1580
- * class method.
1581
- *
1582
1577
  * Escapes binary data for use within an SQL command with the type +bytea+.
1583
1578
  *
1584
1579
  * Certain byte values must be escaped (but all byte values may be escaped)
@@ -1591,6 +1586,12 @@ pgconn_s_escape(VALUE self, VALUE string)
1591
1586
  *
1592
1587
  * Consider using exec_params, which avoids the need for passing values inside of
1593
1588
  * SQL commands.
1589
+ *
1590
+ * NOTE: This class version of this method can only be used safely in client
1591
+ * programs that use a single PostgreSQL connection at a time (in this case it can
1592
+ * find out what it needs to know "behind the scenes"). It might give the wrong
1593
+ * results if used in programs that use multiple database connections; use the
1594
+ * same method on the connection object in such cases.
1594
1595
  */
1595
1596
  static VALUE
1596
1597
  pgconn_s_escape_bytea(VALUE self, VALUE str)
@@ -1603,7 +1604,7 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1603
1604
  from = (unsigned char*)RSTRING_PTR(str);
1604
1605
  from_len = RSTRING_LEN(str);
1605
1606
 
1606
- if(rb_obj_class(self) == rb_cPGconn) {
1607
+ if ( rb_obj_is_kind_of(self, rb_cPGconn) ) {
1607
1608
  to = PQescapeByteaConn(pg_get_pgconn(self), from, from_len, &to_len);
1608
1609
  } else {
1609
1610
  to = PQescapeBytea( from, from_len, &to_len);
@@ -1659,8 +1660,12 @@ pgconn_escape_literal(VALUE self, VALUE string)
1659
1660
  char *escaped = NULL;
1660
1661
  VALUE error;
1661
1662
  VALUE result = Qnil;
1663
+ int enc_idx = ENCODING_GET(self);
1662
1664
 
1663
1665
  Check_Type(string, T_STRING);
1666
+ if( ENCODING_GET(string) != enc_idx ){
1667
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1668
+ }
1664
1669
 
1665
1670
  escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1666
1671
  if (escaped == NULL)
@@ -1673,7 +1678,7 @@ pgconn_escape_literal(VALUE self, VALUE string)
1673
1678
  result = rb_str_new2(escaped);
1674
1679
  PQfreemem(escaped);
1675
1680
  OBJ_INFECT(result, string);
1676
- PG_ENCODING_SET_NOCHECK(result, ENCODING_GET(self));
1681
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1677
1682
 
1678
1683
  return result;
1679
1684
  }
@@ -1686,8 +1691,9 @@ pgconn_escape_literal(VALUE self, VALUE string)
1686
1691
  *
1687
1692
  * Escape an arbitrary String +str+ as an identifier.
1688
1693
  *
1689
- * This method does the same as #quote_ident, but uses libpq to
1690
- * process the string.
1694
+ * This method does the same as #quote_ident with a String argument,
1695
+ * but it doesn't support an Array argument and it makes use of libpq
1696
+ * to process the string.
1691
1697
  */
1692
1698
  static VALUE
1693
1699
  pgconn_escape_identifier(VALUE self, VALUE string)
@@ -1696,8 +1702,12 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1696
1702
  char *escaped = NULL;
1697
1703
  VALUE error;
1698
1704
  VALUE result = Qnil;
1705
+ int enc_idx = ENCODING_GET(self);
1699
1706
 
1700
1707
  Check_Type(string, T_STRING);
1708
+ if( ENCODING_GET(string) != enc_idx ){
1709
+ string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1710
+ }
1701
1711
 
1702
1712
  escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1703
1713
  if (escaped == NULL)
@@ -1710,7 +1720,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1710
1720
  result = rb_str_new2(escaped);
1711
1721
  PQfreemem(escaped);
1712
1722
  OBJ_INFECT(result, string);
1713
- PG_ENCODING_SET_NOCHECK(result, ENCODING_GET(self));
1723
+ PG_ENCODING_SET_NOCHECK(result, enc_idx);
1714
1724
 
1715
1725
  return result;
1716
1726
  }
@@ -1818,15 +1828,14 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1818
1828
  VALUE error;
1819
1829
  int nParams;
1820
1830
  int resultFormat;
1821
- struct query_params_data paramsData;
1831
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1822
1832
 
1823
1833
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1824
1834
  paramsData.with_types = 1;
1825
- Check_Type(command, T_STRING);
1826
1835
 
1827
1836
  /* If called with no parameters, use PQsendQuery */
1828
1837
  if(NIL_P(paramsData.params)) {
1829
- if(gvl_PQsendQuery(conn,StringValueCStr(command)) == 0) {
1838
+ if(gvl_PQsendQuery(conn, pg_cstr_enc(command, paramsData.enc_idx)) == 0) {
1830
1839
  error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1831
1840
  rb_iv_set(error, "@connection", self);
1832
1841
  rb_exc_raise(error);
@@ -1842,7 +1851,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1842
1851
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1843
1852
  nParams = alloc_query_params( &paramsData );
1844
1853
 
1845
- result = gvl_PQsendQueryParams(conn, StringValueCStr(command), nParams, paramsData.types,
1854
+ result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1846
1855
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1847
1856
 
1848
1857
  free_query_params( &paramsData );
@@ -1886,10 +1895,13 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1886
1895
  int i = 0;
1887
1896
  int nParams = 0;
1888
1897
  Oid *paramTypes = NULL;
1898
+ const char *name_cstr;
1899
+ const char *command_cstr;
1900
+ int enc_idx = ENCODING_GET(self);
1889
1901
 
1890
1902
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1891
- Check_Type(name, T_STRING);
1892
- Check_Type(command, T_STRING);
1903
+ name_cstr = pg_cstr_enc(name, enc_idx);
1904
+ command_cstr = pg_cstr_enc(command, enc_idx);
1893
1905
 
1894
1906
  if(! NIL_P(in_paramtypes)) {
1895
1907
  Check_Type(in_paramtypes, T_ARRAY);
@@ -1903,8 +1915,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1903
1915
  paramTypes[i] = NUM2UINT(param);
1904
1916
  }
1905
1917
  }
1906
- result = gvl_PQsendPrepare(conn, StringValueCStr(name), StringValueCStr(command),
1907
- nParams, paramTypes);
1918
+ result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1908
1919
 
1909
1920
  xfree(paramTypes);
1910
1921
 
@@ -1957,11 +1968,10 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1957
1968
  VALUE error;
1958
1969
  int nParams;
1959
1970
  int resultFormat;
1960
- struct query_params_data paramsData;
1971
+ struct query_params_data paramsData = { ENCODING_GET(self) };
1961
1972
 
1962
1973
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1963
1974
  paramsData.with_types = 0;
1964
- Check_Type(name, T_STRING);
1965
1975
 
1966
1976
  if(NIL_P(paramsData.params)) {
1967
1977
  paramsData.params = rb_ary_new2(0);
@@ -1972,7 +1982,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1972
1982
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1973
1983
  nParams = alloc_query_params( &paramsData );
1974
1984
 
1975
- result = gvl_PQsendQueryPrepared(conn, StringValueCStr(name), nParams,
1985
+ result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1976
1986
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1977
1987
  resultFormat);
1978
1988
 
@@ -1999,7 +2009,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
1999
2009
  VALUE error;
2000
2010
  PGconn *conn = pg_get_pgconn(self);
2001
2011
  /* returns 0 on failure */
2002
- if(gvl_PQsendDescribePrepared(conn,StringValueCStr(stmt_name)) == 0) {
2012
+ if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
2003
2013
  error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2004
2014
  rb_iv_set(error, "@connection", self);
2005
2015
  rb_exc_raise(error);
@@ -2021,7 +2031,7 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
2021
2031
  VALUE error;
2022
2032
  PGconn *conn = pg_get_pgconn(self);
2023
2033
  /* returns 0 on failure */
2024
- if(gvl_PQsendDescribePortal(conn,StringValueCStr(portal)) == 0) {
2034
+ if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
2025
2035
  error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2026
2036
  rb_iv_set(error, "@connection", self);
2027
2037
  rb_exc_raise(error);
@@ -2581,16 +2591,17 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2581
2591
 
2582
2592
  if( p_coder ){
2583
2593
  t_pg_coder_enc_func enc_func;
2594
+ int enc_idx = ENCODING_GET(self);
2584
2595
 
2585
2596
  enc_func = pg_coder_enc_func( p_coder );
2586
- len = enc_func( p_coder, value, NULL, &intermediate );
2597
+ len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
2587
2598
 
2588
2599
  if( len == -1 ){
2589
2600
  /* The intermediate value is a String that can be used directly. */
2590
2601
  buffer = intermediate;
2591
2602
  } else {
2592
2603
  buffer = rb_str_new(NULL, len);
2593
- len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate);
2604
+ len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate, enc_idx);
2594
2605
  rb_str_set_len( buffer, len );
2595
2606
  }
2596
2607
  }
@@ -2629,13 +2640,13 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2629
2640
  VALUE str;
2630
2641
  VALUE error;
2631
2642
  int ret;
2632
- char *error_message = NULL;
2643
+ const char *error_message = NULL;
2633
2644
  PGconn *conn = pg_get_pgconn(self);
2634
2645
 
2635
2646
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2636
2647
  error_message = NULL;
2637
2648
  else
2638
- error_message = StringValueCStr(str);
2649
+ error_message = pg_cstr_enc(str, ENCODING_GET(self));
2639
2650
 
2640
2651
  ret = gvl_PQputCopyEnd(conn, error_message);
2641
2652
  if(ret == -1) {
@@ -2956,7 +2967,7 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
2956
2967
 
2957
2968
  Check_Type(str, T_STRING);
2958
2969
 
2959
- if ( (PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2970
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2960
2971
  rb_raise(rb_ePGerror, "invalid encoding name: %s",StringValueCStr(str));
2961
2972
  }
2962
2973
  #ifdef M17N_SUPPORTED
@@ -3012,8 +3023,10 @@ pgconn_transaction(VALUE self)
3012
3023
 
3013
3024
  /*
3014
3025
  * call-seq:
3015
- * PG::Connection.quote_ident( str ) -> String
3016
3026
  * conn.quote_ident( str ) -> String
3027
+ * conn.quote_ident( array ) -> String
3028
+ * PG::Connection.quote_ident( str ) -> String
3029
+ * PG::Connection.quote_ident( array ) -> String
3017
3030
  *
3018
3031
  * Returns a string that is safe for inclusion in a SQL query as an
3019
3032
  * identifier. Note: this is not a quote function for values, but for
@@ -3023,40 +3036,41 @@ pgconn_transaction(VALUE self)
3023
3036
  * The identifier <tt>FOO</tt> is folded to lower case, so it actually
3024
3037
  * means <tt>foo</tt>. If you really want to access the case-sensitive
3025
3038
  * field name <tt>FOO</tt>, use this function like
3026
- * <tt>PG::Connection.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
3039
+ * <tt>conn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
3027
3040
  * (with double-quotes). PostgreSQL will see the double-quotes, and
3028
3041
  * it will not fold to lower case.
3029
3042
  *
3030
3043
  * Similarly, this function also protects against special characters,
3031
3044
  * and other things that might allow SQL injection if the identifier
3032
3045
  * comes from an untrusted source.
3046
+ *
3047
+ * If the parameter is an Array, then all it's values are separately quoted
3048
+ * and then joined by a "." character. This can be used for identifiers in
3049
+ * the form "schema"."table"."column" .
3050
+ *
3051
+ * This method is functional identical to the encoder PG::TextEncoder::Identifier .
3052
+ *
3053
+ * If the instance method form is used and the input string character encoding
3054
+ * is different to the connection encoding, then the string is converted to this
3055
+ * encoding, so that the returned string is always encoded as PG::Connection#internal_encoding .
3056
+ *
3057
+ * In the singleton form (PG::Connection.quote_ident) the character encoding
3058
+ * of the result string is set to the character encoding of the input string.
3033
3059
  */
3034
3060
  static VALUE
3035
- pgconn_s_quote_ident(VALUE self, VALUE in_str)
3061
+ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3036
3062
  {
3037
3063
  VALUE ret;
3038
- char *str = StringValuePtr(in_str);
3039
- /* result size at most NAMEDATALEN*2 plus surrounding
3040
- * double-quotes. */
3041
- char buffer[NAMEDATALEN*2+2];
3042
- unsigned int i=0,j=0;
3043
- unsigned int str_len = RSTRING_LENINT(in_str);
3044
-
3045
- if(str_len >= NAMEDATALEN) {
3046
- rb_raise(rb_eArgError,
3047
- "Input string is longer than NAMEDATALEN-1 (%d)",
3048
- NAMEDATALEN-1);
3049
- }
3050
- buffer[j++] = '"';
3051
- for(i = 0; i < str_len && str[i]; i++) {
3052
- if(str[i] == '"')
3053
- buffer[j++] = '"';
3054
- buffer[j++] = str[i];
3055
- }
3056
- buffer[j++] = '"';
3057
- ret = rb_str_new(buffer,j);
3058
- OBJ_INFECT(ret, in_str);
3059
- PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET( rb_obj_class(self) == rb_cPGconn ? self : in_str ));
3064
+ int enc_idx;
3065
+
3066
+ if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3067
+ enc_idx = ENCODING_GET( self );
3068
+ }else{
3069
+ enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3070
+ }
3071
+ pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3072
+
3073
+ OBJ_INFECT(ret, str_or_array);
3060
3074
 
3061
3075
  return ret;
3062
3076
  }
@@ -3182,6 +3196,84 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3182
3196
  return rb_pgresult;
3183
3197
  }
3184
3198
 
3199
+
3200
+ #ifdef HAVE_PQSSLATTRIBUTE
3201
+ /* Since PostgreSQL-9.5: */
3202
+
3203
+ /*
3204
+ * call-seq:
3205
+ * conn.ssl_in_use? -> Boolean
3206
+ *
3207
+ * Returns +true+ if the connection uses SSL, +false+ if not.
3208
+ *
3209
+ */
3210
+ static VALUE
3211
+ pgconn_ssl_in_use(VALUE self)
3212
+ {
3213
+ return PQsslInUse(pg_get_pgconn(self)) ? Qtrue : Qfalse;
3214
+ }
3215
+
3216
+
3217
+ /*
3218
+ * call-seq:
3219
+ * conn.ssl_attribute(attribute_name) -> String
3220
+ *
3221
+ * Returns SSL-related information about the connection.
3222
+ *
3223
+ * The list of available attributes varies depending on the SSL library being used,
3224
+ * and the type of connection. If an attribute is not available, returns nil.
3225
+ *
3226
+ * The following attributes are commonly available:
3227
+ *
3228
+ * [+library+]
3229
+ * Name of the SSL implementation in use. (Currently, only "OpenSSL" is implemented)
3230
+ * [+protocol+]
3231
+ * SSL/TLS version in use. Common values are "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" and "TLSv1.2", but an implementation may return other strings if some other protocol is used.
3232
+ * [+key_bits+]
3233
+ * Number of key bits used by the encryption algorithm.
3234
+ * [+cipher+]
3235
+ * A short name of the ciphersuite used, e.g. "DHE-RSA-DES-CBC3-SHA". The names are specific to each SSL implementation.
3236
+ * [+compression+]
3237
+ * If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
3238
+ *
3239
+ *
3240
+ * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3241
+ */
3242
+ static VALUE
3243
+ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
3244
+ {
3245
+ const char *p_attr;
3246
+
3247
+ p_attr = PQsslAttribute(pg_get_pgconn(self), StringValueCStr(attribute_name));
3248
+ return p_attr ? rb_str_new_cstr(p_attr) : Qnil;
3249
+ }
3250
+
3251
+ /*
3252
+ * call-seq:
3253
+ * conn.ssl_attribute_names -> Array<String>
3254
+ *
3255
+ * Return an array of SSL attribute names available.
3256
+ *
3257
+ * See also #ssl_attribute
3258
+ *
3259
+ */
3260
+ static VALUE
3261
+ pgconn_ssl_attribute_names(VALUE self)
3262
+ {
3263
+ int i;
3264
+ const char * const * p_list = PQsslAttributeNames(pg_get_pgconn(self));
3265
+ VALUE ary = rb_ary_new();
3266
+
3267
+ for ( i = 0; p_list[i]; i++ ) {
3268
+ rb_ary_push( ary, rb_str_new_cstr( p_list[i] ));
3269
+ }
3270
+ return ary;
3271
+ }
3272
+
3273
+
3274
+ #endif
3275
+
3276
+
3185
3277
  /**************************************************************************
3186
3278
  * LARGE OBJECT SUPPORT
3187
3279
  **************************************************************************/
@@ -3537,7 +3629,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3537
3629
  rb_encoding *rbenc = rb_to_encoding( enc );
3538
3630
  const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
3539
3631
 
3540
- if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3632
+ if ( gvl_PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3541
3633
  VALUE server_encoding = pgconn_external_encoding( self );
3542
3634
  rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
3543
3635
  rb_enc_name(rb_to_encoding(server_encoding)), name );
@@ -3579,6 +3671,34 @@ pgconn_external_encoding(VALUE self)
3579
3671
  }
3580
3672
 
3581
3673
 
3674
+ static VALUE
3675
+ pgconn_set_client_encoding_async1( VALUE args )
3676
+ {
3677
+ VALUE self = ((VALUE*)args)[0];
3678
+ VALUE encname = ((VALUE*)args)[1];
3679
+ VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3680
+ VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3681
+
3682
+ pgconn_async_exec(1, &query, self);
3683
+ return 0;
3684
+ }
3685
+
3686
+
3687
+ static VALUE
3688
+ pgconn_set_client_encoding_async2( VALUE arg )
3689
+ {
3690
+ UNUSED(arg);
3691
+ return 1;
3692
+ }
3693
+
3694
+
3695
+ static VALUE
3696
+ pgconn_set_client_encoding_async( VALUE self, const char *encname )
3697
+ {
3698
+ VALUE args[] = { self, rb_str_new_cstr(encname) };
3699
+ return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3700
+ }
3701
+
3582
3702
 
3583
3703
  /*
3584
3704
  * call-seq:
@@ -3597,7 +3717,7 @@ pgconn_set_default_encoding( VALUE self )
3597
3717
 
3598
3718
  if (( enc = rb_default_internal_encoding() )) {
3599
3719
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3600
- if ( PQsetClientEncoding(conn, encname) != 0 )
3720
+ if ( pgconn_set_client_encoding_async(self, encname) != 0 )
3601
3721
  rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
3602
3722
  encname, PQerrorMessage(conn) );
3603
3723
  pgconn_set_internal_encoding_index( self );
@@ -3729,7 +3849,7 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
3729
3849
  *
3730
3850
  * Returns either:
3731
3851
  * * a kind of PG::Coder
3732
- * * +nil+ - type encoding is disabled, returned data will be a String.
3852
+ * * +nil+ - type encoding is disabled, data must be a String.
3733
3853
  *
3734
3854
  */
3735
3855
  static VALUE
@@ -3790,6 +3910,9 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
3790
3910
  }
3791
3911
 
3792
3912
 
3913
+ /*
3914
+ * Document-class: PG::Connection
3915
+ */
3793
3916
  void
3794
3917
  init_pg_connection()
3795
3918
  {
@@ -3835,9 +3958,6 @@ init_pg_connection()
3835
3958
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
3836
3959
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
3837
3960
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
3838
- #ifdef HAVE_PQHOSTADDR
3839
- rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
3840
- #endif
3841
3961
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
3842
3962
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
3843
3963
  #ifdef HAVE_PQCONNINFO
@@ -3929,6 +4049,12 @@ init_pg_connection()
3929
4049
  rb_define_alias(rb_cPGconn, "async_query", "async_exec");
3930
4050
  rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
3931
4051
 
4052
+ #ifdef HAVE_PQSSLATTRIBUTE
4053
+ rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
4054
+ rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
4055
+ rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4056
+ #endif
4057
+
3932
4058
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
3933
4059
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
3934
4060
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");