pg 0.18.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/BSDL +2 -2
- data/ChangeLog +798 -7
- data/History.rdoc +96 -0
- data/Manifest.txt +0 -18
- data/README.rdoc +16 -11
- data/Rakefile +31 -24
- data/Rakefile.cross +21 -24
- data/ext/errorcodes.def +33 -0
- data/ext/errorcodes.txt +15 -1
- data/ext/extconf.rb +22 -33
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +27 -39
- data/ext/pg.c +18 -50
- data/ext/pg.h +13 -80
- data/ext/pg_binary_decoder.c +3 -1
- data/ext/pg_binary_encoder.c +14 -12
- data/ext/pg_coder.c +31 -10
- data/ext/pg_connection.c +340 -225
- data/ext/pg_copy_coder.c +34 -4
- data/ext/pg_result.c +24 -22
- data/ext/pg_text_decoder.c +3 -1
- data/ext/pg_text_encoder.c +65 -42
- data/ext/pg_type_map.c +20 -13
- data/ext/pg_type_map_by_column.c +7 -7
- data/lib/pg/basic_type_mapping.rb +35 -8
- data/lib/pg/connection.rb +53 -12
- data/lib/pg/result.rb +10 -5
- data/lib/pg/text_decoder.rb +7 -0
- data/lib/pg/text_encoder.rb +8 -0
- data/lib/pg.rb +18 -10
- data/spec/helpers.rb +8 -15
- data/spec/pg/basic_type_mapping_spec.rb +54 -0
- data/spec/pg/connection_spec.rb +390 -209
- data/spec/pg/result_spec.rb +14 -7
- data/spec/pg/type_map_by_class_spec.rb +2 -2
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_spec.rb +90 -3
- data/spec/pg_spec.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +56 -69
- metadata.gz.sig +0 -0
- data/sample/array_insert.rb +0 -20
- data/sample/async_api.rb +0 -106
- data/sample/async_copyto.rb +0 -39
- data/sample/async_mixed.rb +0 -56
- data/sample/check_conn.rb +0 -21
- data/sample/copyfrom.rb +0 -81
- data/sample/copyto.rb +0 -19
- data/sample/cursor.rb +0 -21
- data/sample/disk_usage_report.rb +0 -186
- data/sample/issue-119.rb +0 -94
- data/sample/losample.rb +0 -69
- data/sample/minimal-testcase.rb +0 -17
- data/sample/notify_wait.rb +0 -72
- data/sample/pg_statistics.rb +0 -294
- data/sample/replication_monitor.rb +0 -231
- data/sample/test_binary_values.rb +0 -33
- data/sample/wal_shipper.rb +0 -434
- data/sample/warehouse_partitions.rb +0 -320
data/ext/pg_copy_coder.c
CHANGED
@@ -167,9 +167,15 @@ pg_copycoder_type_map_get(VALUE self)
|
|
167
167
|
* conn.put_copy_data ["string2", 42, true]
|
168
168
|
* end
|
169
169
|
* This creates +my_table+ and inserts two rows.
|
170
|
+
*
|
171
|
+
* It is possible to manually assign a type encoder for each column per PG::TypeMapByColumn,
|
172
|
+
* or to make use of PG::BasicTypeMapBasedOnResult to assign them based on the table OIDs.
|
173
|
+
*
|
174
|
+
* See also PG::TextDecoder::CopyRow for the decoding direction with
|
175
|
+
* PG::Connection#get_copy_data .
|
170
176
|
*/
|
171
177
|
static int
|
172
|
-
pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
178
|
+
pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
173
179
|
{
|
174
180
|
t_pg_copycoder *this = (t_pg_copycoder *)conv;
|
175
181
|
t_pg_coder_enc_func enc_func;
|
@@ -184,6 +190,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
184
190
|
|
185
191
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
186
192
|
PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
|
193
|
+
PG_ENCODING_SET_NOCHECK(*intermediate, enc_idx);
|
187
194
|
|
188
195
|
for( i=0; i<RARRAY_LEN(value); i++){
|
189
196
|
char *ptr1;
|
@@ -211,7 +218,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
211
218
|
enc_func = pg_coder_enc_func(p_elem_coder);
|
212
219
|
|
213
220
|
/* 1st pass for retiving the required memory space */
|
214
|
-
strlen = enc_func(p_elem_coder, entry, NULL, &subint);
|
221
|
+
strlen = enc_func(p_elem_coder, entry, NULL, &subint, enc_idx);
|
215
222
|
|
216
223
|
if( strlen == -1 ){
|
217
224
|
/* we can directly use String value in subint */
|
@@ -234,7 +241,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
234
241
|
PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
|
235
242
|
|
236
243
|
/* Place the unescaped string at current output position. */
|
237
|
-
strlen = enc_func(p_elem_coder, entry, current_out, &subint);
|
244
|
+
strlen = enc_func(p_elem_coder, entry, current_out, &subint, enc_idx);
|
238
245
|
|
239
246
|
ptr1 = current_out;
|
240
247
|
ptr2 = current_out + strlen;
|
@@ -301,15 +308,38 @@ GetDecimalFromHex(char hex)
|
|
301
308
|
* strings by PG::TextDecoder::String.
|
302
309
|
*
|
303
310
|
* Example with default type map ( TypeMapAllStrings ):
|
311
|
+
* conn.exec("CREATE TABLE my_table AS VALUES('astring', 7, FALSE), ('string2', 42, TRUE) ")
|
312
|
+
*
|
304
313
|
* deco = PG::TextDecoder::CopyRow.new
|
305
314
|
* conn.copy_data "COPY my_table TO STDOUT", deco do
|
306
315
|
* while row=conn.get_copy_data
|
307
316
|
* p row
|
308
317
|
* end
|
309
318
|
* end
|
310
|
-
* This prints all rows of +my_table+
|
319
|
+
* This prints all rows of +my_table+ :
|
311
320
|
* ["astring", "7", "f"]
|
312
321
|
* ["string2", "42", "t"]
|
322
|
+
*
|
323
|
+
* Example with column based type map:
|
324
|
+
* tm = PG::TypeMapByColumn.new( [
|
325
|
+
* PG::TextDecoder::String.new,
|
326
|
+
* PG::TextDecoder::Integer.new,
|
327
|
+
* PG::TextDecoder::Boolean.new] )
|
328
|
+
* deco = PG::TextDecoder::CopyRow.new( type_map: tm )
|
329
|
+
* conn.copy_data "COPY my_table TO STDOUT", deco do
|
330
|
+
* while row=conn.get_copy_data
|
331
|
+
* p row
|
332
|
+
* end
|
333
|
+
* end
|
334
|
+
* This prints the rows with type casted columns:
|
335
|
+
* ["astring", 7, false]
|
336
|
+
* ["string2", 42, true]
|
337
|
+
*
|
338
|
+
* Instead of manually assigning a type decoder for each column, PG::BasicTypeMapForResults
|
339
|
+
* can be used to assign them based on the table OIDs.
|
340
|
+
*
|
341
|
+
* See also PG::TextEncoder::CopyRow for the encoding direction with
|
342
|
+
* PG::Connection#put_copy_data .
|
313
343
|
*/
|
314
344
|
/*
|
315
345
|
* Parse the current line into separate attributes (fields),
|
data/ext/pg_result.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_result.c - PG::Result class extension
|
3
|
-
* $Id: pg_result.c,v
|
3
|
+
* $Id: pg_result.c,v 7c5d9608349f 2018/01/03 16:11:52 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -92,12 +92,8 @@ pg_result_check( VALUE self )
|
|
92
92
|
case PGRES_TUPLES_OK:
|
93
93
|
case PGRES_COPY_OUT:
|
94
94
|
case PGRES_COPY_IN:
|
95
|
-
#ifdef HAVE_CONST_PGRES_COPY_BOTH
|
96
95
|
case PGRES_COPY_BOTH:
|
97
|
-
#endif
|
98
|
-
#ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
|
99
96
|
case PGRES_SINGLE_TUPLE:
|
100
|
-
#endif
|
101
97
|
case PGRES_EMPTY_QUERY:
|
102
98
|
case PGRES_COMMAND_OK:
|
103
99
|
return self;
|
@@ -288,7 +284,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
288
284
|
*
|
289
285
|
* Example:
|
290
286
|
* require 'pg'
|
291
|
-
* conn =
|
287
|
+
* conn = PG.connect(:dbname => 'test')
|
292
288
|
* res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
|
293
289
|
* res.getvalue(0,0) # '1'
|
294
290
|
* res[0]['b'] # '2'
|
@@ -302,7 +298,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
302
298
|
|
303
299
|
/*
|
304
300
|
* call-seq:
|
305
|
-
* res.result_status() ->
|
301
|
+
* res.result_status() -> Integer
|
306
302
|
*
|
307
303
|
* Returns the status of the query. The status value is one of:
|
308
304
|
* * +PGRES_EMPTY_QUERY+
|
@@ -414,7 +410,7 @@ pgresult_error_field(VALUE self, VALUE field)
|
|
414
410
|
|
415
411
|
/*
|
416
412
|
* call-seq:
|
417
|
-
* res.ntuples() ->
|
413
|
+
* res.ntuples() -> Integer
|
418
414
|
*
|
419
415
|
* Returns the number of tuples in the query result.
|
420
416
|
*/
|
@@ -466,7 +462,7 @@ pgresult_fname(VALUE self, VALUE index)
|
|
466
462
|
|
467
463
|
/*
|
468
464
|
* call-seq:
|
469
|
-
* res.fnumber( name ) ->
|
465
|
+
* res.fnumber( name ) -> Integer
|
470
466
|
*
|
471
467
|
* Returns the index of the field specified by the string +name+.
|
472
468
|
* The given +name+ is treated like an identifier in an SQL command, that is,
|
@@ -527,7 +523,7 @@ pgresult_ftable(VALUE self, VALUE column_number)
|
|
527
523
|
|
528
524
|
/*
|
529
525
|
* call-seq:
|
530
|
-
* res.ftablecol( column_number ) ->
|
526
|
+
* res.ftablecol( column_number ) -> Integer
|
531
527
|
*
|
532
528
|
* Returns the column number (within its table) of the table from
|
533
529
|
* which the column _column_number_ is made up.
|
@@ -552,7 +548,7 @@ pgresult_ftablecol(VALUE self, VALUE column_number)
|
|
552
548
|
|
553
549
|
/*
|
554
550
|
* call-seq:
|
555
|
-
* res.fformat( column_number ) ->
|
551
|
+
* res.fformat( column_number ) -> Integer
|
556
552
|
*
|
557
553
|
* Returns the format (0 for text, 1 for binary) of column
|
558
554
|
* _column_number_.
|
@@ -696,7 +692,7 @@ pgresult_getisnull(VALUE self, VALUE tup_num, VALUE field_num)
|
|
696
692
|
|
697
693
|
/*
|
698
694
|
* call-seq:
|
699
|
-
* res.getlength( tup_num, field_num ) ->
|
695
|
+
* res.getlength( tup_num, field_num ) -> Integer
|
700
696
|
*
|
701
697
|
* Returns the (String) length of the field in bytes.
|
702
698
|
*
|
@@ -721,7 +717,7 @@ pgresult_getlength(VALUE self, VALUE tup_num, VALUE field_num)
|
|
721
717
|
|
722
718
|
/*
|
723
719
|
* call-seq:
|
724
|
-
* res.nparams() ->
|
720
|
+
* res.nparams() -> Integer
|
725
721
|
*
|
726
722
|
* Returns the number of parameters of a prepared statement.
|
727
723
|
* Only useful for the result returned by conn.describePrepared
|
@@ -772,11 +768,17 @@ pgresult_cmd_status(VALUE self)
|
|
772
768
|
* Returns the number of tuples (rows) affected by the SQL command.
|
773
769
|
*
|
774
770
|
* If the SQL command that generated the PG::Result was not one of:
|
775
|
-
*
|
776
|
-
* *
|
777
|
-
* *
|
778
|
-
* *
|
779
|
-
* *
|
771
|
+
*
|
772
|
+
* * <tt>SELECT</tt>
|
773
|
+
* * <tt>CREATE TABLE AS</tt>
|
774
|
+
* * <tt>INSERT</tt>
|
775
|
+
* * <tt>UPDATE</tt>
|
776
|
+
* * <tt>DELETE</tt>
|
777
|
+
* * <tt>MOVE</tt>
|
778
|
+
* * <tt>FETCH</tt>
|
779
|
+
* * <tt>COPY</tt>
|
780
|
+
* * an +EXECUTE+ of a prepared query that contains an +INSERT+, +UPDATE+, or +DELETE+ statement
|
781
|
+
*
|
780
782
|
* or if no tuples were affected, <tt>0</tt> is returned.
|
781
783
|
*/
|
782
784
|
static VALUE
|
@@ -1050,7 +1052,6 @@ pgresult_type_map_get(VALUE self)
|
|
1050
1052
|
return this->typemap;
|
1051
1053
|
}
|
1052
1054
|
|
1053
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1054
1055
|
/*
|
1055
1056
|
* call-seq:
|
1056
1057
|
* res.stream_each{ |tuple| ... }
|
@@ -1081,6 +1082,8 @@ pgresult_type_map_get(VALUE self)
|
|
1081
1082
|
* # do something with the received row of the second query
|
1082
1083
|
* end
|
1083
1084
|
* conn.get_result # => nil (no more results)
|
1085
|
+
*
|
1086
|
+
* Available since PostgreSQL-9.2
|
1084
1087
|
*/
|
1085
1088
|
static VALUE
|
1086
1089
|
pgresult_stream_each(VALUE self)
|
@@ -1144,6 +1147,8 @@ pgresult_stream_each(VALUE self)
|
|
1144
1147
|
*
|
1145
1148
|
* This method works equally to #stream_each , but yields an Array of
|
1146
1149
|
* values.
|
1150
|
+
*
|
1151
|
+
* Available since PostgreSQL-9.2
|
1147
1152
|
*/
|
1148
1153
|
static VALUE
|
1149
1154
|
pgresult_stream_each_row(VALUE self)
|
@@ -1204,7 +1209,6 @@ pgresult_stream_each_row(VALUE self)
|
|
1204
1209
|
/* never reached */
|
1205
1210
|
return self;
|
1206
1211
|
}
|
1207
|
-
#endif
|
1208
1212
|
|
1209
1213
|
|
1210
1214
|
void
|
@@ -1261,11 +1265,9 @@ init_pg_result()
|
|
1261
1265
|
rb_define_method(rb_cPGresult, "type_map=", pgresult_type_map_set, 1);
|
1262
1266
|
rb_define_method(rb_cPGresult, "type_map", pgresult_type_map_get, 0);
|
1263
1267
|
|
1264
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1265
1268
|
/****** PG::Result INSTANCE METHODS: streaming ******/
|
1266
1269
|
rb_define_method(rb_cPGresult, "stream_each", pgresult_stream_each, 0);
|
1267
1270
|
rb_define_method(rb_cPGresult, "stream_each_row", pgresult_stream_each_row, 0);
|
1268
|
-
#endif
|
1269
1271
|
}
|
1270
1272
|
|
1271
1273
|
|
data/ext/pg_text_decoder.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_text_decoder.c - PG::TextDecoder module
|
3
|
-
* $Id: pg_text_decoder.c,v
|
3
|
+
* $Id: pg_text_decoder.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -30,7 +30,9 @@
|
|
30
30
|
|
31
31
|
#include "pg.h"
|
32
32
|
#include "util.h"
|
33
|
+
#ifdef HAVE_INTTYPES_H
|
33
34
|
#include <inttypes.h>
|
35
|
+
#endif
|
34
36
|
|
35
37
|
VALUE rb_mPG_TextDecoder;
|
36
38
|
static ID s_id_decode;
|
data/ext/pg_text_encoder.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_text_encoder.c - PG::TextEncoder module
|
3
|
-
* $Id: pg_text_encoder.c,v
|
3
|
+
* $Id: pg_text_encoder.c,v e61a06f1f5ed 2015/12/25 21:14:21 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -28,6 +28,7 @@
|
|
28
28
|
* intermediate - Pointer to a VALUE that might be set by the encoding function to some
|
29
29
|
* value in the first call that can be retrieved later in the second call.
|
30
30
|
* This VALUE is not yet initialized by the caller.
|
31
|
+
* enc_idx - Index of the output Encoding that strings should be converted to.
|
31
32
|
*
|
32
33
|
* Returns:
|
33
34
|
* >= 0 - If out==NULL the encoder function must return the expected output buffer size.
|
@@ -41,14 +42,16 @@
|
|
41
42
|
|
42
43
|
#include "pg.h"
|
43
44
|
#include "util.h"
|
45
|
+
#ifdef HAVE_INTTYPES_H
|
44
46
|
#include <inttypes.h>
|
47
|
+
#endif
|
45
48
|
#include <math.h>
|
46
49
|
|
47
50
|
VALUE rb_mPG_TextEncoder;
|
48
51
|
static ID s_id_encode;
|
49
52
|
static ID s_id_to_i;
|
50
53
|
|
51
|
-
static int pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate);
|
54
|
+
static int pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx);
|
52
55
|
|
53
56
|
VALUE
|
54
57
|
pg_obj_to_i( VALUE value )
|
@@ -74,7 +77,7 @@ pg_obj_to_i( VALUE value )
|
|
74
77
|
*
|
75
78
|
*/
|
76
79
|
static int
|
77
|
-
pg_text_enc_boolean(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate)
|
80
|
+
pg_text_enc_boolean(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
78
81
|
{
|
79
82
|
switch( TYPE(value) ){
|
80
83
|
case T_FALSE:
|
@@ -92,10 +95,10 @@ pg_text_enc_boolean(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
92
95
|
if(out) *out = '1';
|
93
96
|
return 1;
|
94
97
|
} else {
|
95
|
-
return pg_text_enc_integer(this, value, out, intermediate);
|
98
|
+
return pg_text_enc_integer(this, value, out, intermediate, enc_idx);
|
96
99
|
}
|
97
100
|
default:
|
98
|
-
return pg_coder_enc_to_s(this, value, out, intermediate);
|
101
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
99
102
|
}
|
100
103
|
/* never reached */
|
101
104
|
return 0;
|
@@ -111,9 +114,14 @@ pg_text_enc_boolean(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
111
114
|
*
|
112
115
|
*/
|
113
116
|
int
|
114
|
-
pg_coder_enc_to_s(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate)
|
117
|
+
pg_coder_enc_to_s(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
115
118
|
{
|
116
|
-
|
119
|
+
VALUE str = rb_obj_as_string(value);
|
120
|
+
if( ENCODING_GET(str) == enc_idx ){
|
121
|
+
*intermediate = str;
|
122
|
+
}else{
|
123
|
+
*intermediate = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
|
124
|
+
}
|
117
125
|
return -1;
|
118
126
|
}
|
119
127
|
|
@@ -127,11 +135,11 @@ pg_coder_enc_to_s(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate)
|
|
127
135
|
*
|
128
136
|
*/
|
129
137
|
static int
|
130
|
-
pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate)
|
138
|
+
pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
131
139
|
{
|
132
140
|
if(out){
|
133
141
|
if(TYPE(*intermediate) == T_STRING){
|
134
|
-
return pg_coder_enc_to_s(this, value, out, intermediate);
|
142
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
135
143
|
}else{
|
136
144
|
char *start = out;
|
137
145
|
int len;
|
@@ -204,13 +212,13 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
204
212
|
if( ll < 100000000000000LL ){
|
205
213
|
len = ll < 10000000000000LL ? 13 : 14;
|
206
214
|
}else{
|
207
|
-
return pg_coder_enc_to_s(this, *intermediate, NULL, intermediate);
|
215
|
+
return pg_coder_enc_to_s(this, *intermediate, NULL, intermediate, enc_idx);
|
208
216
|
}
|
209
217
|
}
|
210
218
|
}
|
211
219
|
return sll < 0 ? len+1 : len;
|
212
220
|
}else{
|
213
|
-
return pg_coder_enc_to_s(this, *intermediate, NULL, intermediate);
|
221
|
+
return pg_coder_enc_to_s(this, *intermediate, NULL, intermediate, enc_idx);
|
214
222
|
}
|
215
223
|
}
|
216
224
|
}
|
@@ -223,7 +231,7 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
223
231
|
*
|
224
232
|
*/
|
225
233
|
static int
|
226
|
-
pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
234
|
+
pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
227
235
|
{
|
228
236
|
if(out){
|
229
237
|
double dvalue = NUM2DBL(value);
|
@@ -263,7 +271,7 @@ static const char hextab[] = {
|
|
263
271
|
*
|
264
272
|
*/
|
265
273
|
static int
|
266
|
-
pg_text_enc_bytea(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
274
|
+
pg_text_enc_bytea(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
267
275
|
{
|
268
276
|
if(out){
|
269
277
|
size_t strlen = RSTRING_LEN(*intermediate);
|
@@ -342,13 +350,13 @@ quote_array_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
342
350
|
}
|
343
351
|
|
344
352
|
static char *
|
345
|
-
quote_string(t_pg_coder *this, VALUE value, VALUE string, char *current_out, int with_quote, t_quote_func quote_buffer, void *func_data)
|
353
|
+
quote_string(t_pg_coder *this, VALUE value, VALUE string, char *current_out, int with_quote, t_quote_func quote_buffer, void *func_data, int enc_idx)
|
346
354
|
{
|
347
355
|
int strlen;
|
348
356
|
VALUE subint;
|
349
357
|
t_pg_coder_enc_func enc_func = pg_coder_enc_func(this);
|
350
358
|
|
351
|
-
strlen = enc_func(this, value, NULL, &subint);
|
359
|
+
strlen = enc_func(this, value, NULL, &subint, enc_idx);
|
352
360
|
|
353
361
|
if( strlen == -1 ){
|
354
362
|
/* we can directly use String value in subint */
|
@@ -374,20 +382,20 @@ quote_string(t_pg_coder *this, VALUE value, VALUE string, char *current_out, int
|
|
374
382
|
current_out = pg_rb_str_ensure_capa( string, 2 * strlen + 2, current_out, NULL );
|
375
383
|
|
376
384
|
/* Place the unescaped string at current output position. */
|
377
|
-
strlen = enc_func(this, value, current_out, &subint);
|
385
|
+
strlen = enc_func(this, value, current_out, &subint, enc_idx);
|
378
386
|
|
379
387
|
current_out += quote_buffer( func_data, current_out, strlen, current_out );
|
380
388
|
}else{
|
381
389
|
/* size of the unquoted string */
|
382
390
|
current_out = pg_rb_str_ensure_capa( string, strlen, current_out, NULL );
|
383
|
-
current_out += enc_func(this, value, current_out, &subint);
|
391
|
+
current_out += enc_func(this, value, current_out, &subint, enc_idx);
|
384
392
|
}
|
385
393
|
}
|
386
394
|
return current_out;
|
387
395
|
}
|
388
396
|
|
389
397
|
static char *
|
390
|
-
write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE string, int quote)
|
398
|
+
write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE string, int quote, int enc_idx)
|
391
399
|
{
|
392
400
|
int i;
|
393
401
|
|
@@ -405,7 +413,7 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
405
413
|
|
406
414
|
switch(TYPE(entry)){
|
407
415
|
case T_ARRAY:
|
408
|
-
current_out = write_array(this, entry, current_out, string, quote);
|
416
|
+
current_out = write_array(this, entry, current_out, string, quote, enc_idx);
|
409
417
|
break;
|
410
418
|
case T_NIL:
|
411
419
|
current_out = pg_rb_str_ensure_capa( string, 4, current_out, NULL );
|
@@ -415,7 +423,7 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
415
423
|
*current_out++ = 'L';
|
416
424
|
break;
|
417
425
|
default:
|
418
|
-
current_out = quote_string( this->elem, entry, string, current_out, quote, quote_array_buffer, this );
|
426
|
+
current_out = quote_string( this->elem, entry, string, current_out, quote, quote_array_buffer, this, enc_idx );
|
419
427
|
}
|
420
428
|
}
|
421
429
|
current_out = pg_rb_str_ensure_capa( string, 1, current_out, NULL );
|
@@ -437,21 +445,23 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
437
445
|
*
|
438
446
|
*/
|
439
447
|
static int
|
440
|
-
pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
448
|
+
pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
441
449
|
{
|
442
450
|
char *end_ptr;
|
443
451
|
t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
|
444
452
|
|
445
453
|
if( TYPE(value) == T_ARRAY){
|
446
|
-
|
454
|
+
VALUE out_str = rb_str_new(NULL, 0);
|
455
|
+
PG_ENCODING_SET_NOCHECK(out_str, enc_idx);
|
447
456
|
|
448
|
-
end_ptr = write_array(this, value, RSTRING_PTR(
|
457
|
+
end_ptr = write_array(this, value, RSTRING_PTR(out_str), out_str, this->needs_quotation, enc_idx);
|
449
458
|
|
450
|
-
rb_str_set_len(
|
459
|
+
rb_str_set_len( out_str, end_ptr - RSTRING_PTR(out_str) );
|
460
|
+
*intermediate = out_str;
|
451
461
|
|
452
462
|
return -1;
|
453
463
|
} else {
|
454
|
-
return pg_coder_enc_to_s( conv, value, out, intermediate );
|
464
|
+
return pg_coder_enc_to_s( conv, value, out, intermediate, enc_idx );
|
455
465
|
}
|
456
466
|
}
|
457
467
|
|
@@ -482,7 +492,7 @@ quote_identifier( VALUE value, VALUE out_string, char *current_out ){
|
|
482
492
|
}
|
483
493
|
|
484
494
|
static char *
|
485
|
-
pg_text_enc_array_identifier(VALUE value, VALUE string, char *out)
|
495
|
+
pg_text_enc_array_identifier(VALUE value, VALUE string, char *out, int enc_idx)
|
486
496
|
{
|
487
497
|
int i;
|
488
498
|
int nr_elems;
|
@@ -493,6 +503,10 @@ pg_text_enc_array_identifier(VALUE value, VALUE string, char *out)
|
|
493
503
|
for( i=0; i<nr_elems; i++){
|
494
504
|
VALUE entry = rb_ary_entry(value, i);
|
495
505
|
|
506
|
+
StringValue(entry);
|
507
|
+
if( ENCODING_GET(entry) != enc_idx ){
|
508
|
+
entry = rb_str_export_to_enc(entry, rb_enc_from_index(enc_idx));
|
509
|
+
}
|
496
510
|
out = quote_identifier(entry, string, out);
|
497
511
|
if( i < nr_elems-1 ){
|
498
512
|
out = pg_rb_str_ensure_capa( string, 1, out, NULL );
|
@@ -514,20 +528,26 @@ pg_text_enc_array_identifier(VALUE value, VALUE string, char *out)
|
|
514
528
|
* This encoder can also be used per PG::Connection#quote_ident .
|
515
529
|
*/
|
516
530
|
int
|
517
|
-
pg_text_enc_identifier(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate)
|
531
|
+
pg_text_enc_identifier(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
518
532
|
{
|
533
|
+
VALUE out_str;
|
519
534
|
UNUSED( this );
|
520
535
|
if( TYPE(value) == T_ARRAY){
|
521
|
-
|
522
|
-
out = RSTRING_PTR(
|
523
|
-
out = pg_text_enc_array_identifier(value,
|
536
|
+
out_str = rb_str_new(NULL, 0);
|
537
|
+
out = RSTRING_PTR(out_str);
|
538
|
+
out = pg_text_enc_array_identifier(value, out_str, out, enc_idx);
|
524
539
|
} else {
|
525
540
|
StringValue(value);
|
526
|
-
|
527
|
-
|
528
|
-
|
541
|
+
if( ENCODING_GET(value) != enc_idx ){
|
542
|
+
value = rb_str_export_to_enc(value, rb_enc_from_index(enc_idx));
|
543
|
+
}
|
544
|
+
out_str = rb_str_new(NULL, RSTRING_LEN(value) + 2);
|
545
|
+
out = RSTRING_PTR(out_str);
|
546
|
+
out = quote_identifier(value, out_str, out);
|
529
547
|
}
|
530
|
-
rb_str_set_len(
|
548
|
+
rb_str_set_len( out_str, out - RSTRING_PTR(out_str) );
|
549
|
+
PG_ENCODING_SET_NOCHECK(out_str, enc_idx);
|
550
|
+
*intermediate = out_str;
|
531
551
|
return -1;
|
532
552
|
}
|
533
553
|
|
@@ -573,14 +593,16 @@ quote_literal_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
573
593
|
*
|
574
594
|
*/
|
575
595
|
static int
|
576
|
-
pg_text_enc_quoted_literal(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
596
|
+
pg_text_enc_quoted_literal(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
577
597
|
{
|
578
598
|
t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
|
599
|
+
VALUE out_str = rb_str_new(NULL, 0);
|
600
|
+
PG_ENCODING_SET_NOCHECK(out_str, enc_idx);
|
579
601
|
|
580
|
-
|
581
|
-
out =
|
582
|
-
|
583
|
-
|
602
|
+
out = RSTRING_PTR(out_str);
|
603
|
+
out = quote_string(this->elem, value, out_str, out, this->needs_quotation, quote_literal_buffer, this, enc_idx);
|
604
|
+
rb_str_set_len( out_str, out - RSTRING_PTR(out_str) );
|
605
|
+
*intermediate = out_str;
|
584
606
|
return -1;
|
585
607
|
}
|
586
608
|
|
@@ -591,7 +613,7 @@ pg_text_enc_quoted_literal(t_pg_coder *conv, VALUE value, char *out, VALUE *inte
|
|
591
613
|
*
|
592
614
|
*/
|
593
615
|
static int
|
594
|
-
pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
616
|
+
pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
595
617
|
{
|
596
618
|
int strlen;
|
597
619
|
VALUE subint;
|
@@ -600,13 +622,13 @@ pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedi
|
|
600
622
|
|
601
623
|
if(out){
|
602
624
|
/* Second encoder pass, if required */
|
603
|
-
strlen = enc_func(this->elem, value, out, intermediate);
|
625
|
+
strlen = enc_func(this->elem, value, out, intermediate, enc_idx);
|
604
626
|
base64_encode( out, out, strlen );
|
605
627
|
|
606
628
|
return BASE64_ENCODED_SIZE(strlen);
|
607
629
|
} else {
|
608
630
|
/* First encoder pass */
|
609
|
-
strlen = enc_func(this->elem, value, NULL, &subint);
|
631
|
+
strlen = enc_func(this->elem, value, NULL, &subint, enc_idx);
|
610
632
|
|
611
633
|
if( strlen == -1 ){
|
612
634
|
/* Encoded string is returned in subint */
|
@@ -614,6 +636,7 @@ pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedi
|
|
614
636
|
|
615
637
|
strlen = RSTRING_LENINT(subint);
|
616
638
|
out_str = rb_str_new(NULL, BASE64_ENCODED_SIZE(strlen));
|
639
|
+
PG_ENCODING_SET_NOCHECK(out_str, enc_idx);
|
617
640
|
|
618
641
|
base64_encode( RSTRING_PTR(out_str), RSTRING_PTR(subint), strlen);
|
619
642
|
*intermediate = out_str;
|
data/ext/pg_type_map.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
3
|
-
* $Id: pg_type_map.c,v
|
3
|
+
* $Id: pg_type_map.c,v 2af122820861 2017/01/14 19:56:36 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -11,55 +11,62 @@ VALUE rb_mDefaultTypeMappable;
|
|
11
11
|
static ID s_id_fit_to_query;
|
12
12
|
static ID s_id_fit_to_result;
|
13
13
|
|
14
|
+
NORETURN( VALUE
|
15
|
+
pg_typemap_fit_to_result( VALUE self, VALUE result ));
|
16
|
+
NORETURN( VALUE
|
17
|
+
pg_typemap_fit_to_query( VALUE self, VALUE params ));
|
18
|
+
NORETURN( int
|
19
|
+
pg_typemap_fit_to_copy_get( VALUE self ));
|
20
|
+
NORETURN( VALUE
|
21
|
+
pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field ));
|
22
|
+
NORETURN( t_pg_coder *
|
23
|
+
pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field ));
|
24
|
+
NORETURN( VALUE
|
25
|
+
pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ));
|
26
|
+
|
14
27
|
VALUE
|
15
28
|
pg_typemap_fit_to_result( VALUE self, VALUE result )
|
16
29
|
{
|
17
30
|
rb_raise( rb_eNotImpError, "type map %s is not suitable to map result values", rb_obj_classname(self) );
|
18
|
-
return Qnil;
|
19
31
|
}
|
20
32
|
|
21
33
|
VALUE
|
22
34
|
pg_typemap_fit_to_query( VALUE self, VALUE params )
|
23
35
|
{
|
24
36
|
rb_raise( rb_eNotImpError, "type map %s is not suitable to map query params", rb_obj_classname(self) );
|
25
|
-
return Qnil;
|
26
37
|
}
|
27
38
|
|
28
39
|
int
|
29
40
|
pg_typemap_fit_to_copy_get( VALUE self )
|
30
41
|
{
|
31
42
|
rb_raise( rb_eNotImpError, "type map %s is not suitable to map get_copy_data results", rb_obj_classname(self) );
|
32
|
-
return Qnil;
|
33
43
|
}
|
34
44
|
|
35
45
|
VALUE
|
36
46
|
pg_typemap_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
|
37
47
|
{
|
38
48
|
rb_raise( rb_eNotImpError, "type map is not suitable to map result values" );
|
39
|
-
return Qnil;
|
40
49
|
}
|
41
50
|
|
42
51
|
t_pg_coder *
|
43
52
|
pg_typemap_typecast_query_param( t_typemap *p_typemap, VALUE param_value, int field )
|
44
53
|
{
|
45
54
|
rb_raise( rb_eNotImpError, "type map is not suitable to map query params" );
|
46
|
-
return NULL;
|
47
55
|
}
|
48
56
|
|
49
57
|
VALUE
|
50
58
|
pg_typemap_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx )
|
51
59
|
{
|
52
60
|
rb_raise( rb_eNotImpError, "type map is not suitable to map get_copy_data results" );
|
53
|
-
return Qnil;
|
54
61
|
}
|
55
62
|
|
56
63
|
const struct pg_typemap_funcs pg_typemap_funcs = {
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
64
|
+
pg_typemap_fit_to_result,
|
65
|
+
pg_typemap_fit_to_query,
|
66
|
+
pg_typemap_fit_to_copy_get,
|
67
|
+
pg_typemap_result_value,
|
68
|
+
pg_typemap_typecast_query_param,
|
69
|
+
pg_typemap_typecast_copy_get
|
63
70
|
};
|
64
71
|
|
65
72
|
static VALUE
|
data/ext/pg_type_map_by_column.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
3
|
-
* $Id: pg_type_map_by_column.c,v
|
3
|
+
* $Id: pg_type_map_by_column.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -162,12 +162,12 @@ pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, i
|
|
162
162
|
}
|
163
163
|
|
164
164
|
const struct pg_typemap_funcs pg_tmbc_funcs = {
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
165
|
+
pg_tmbc_fit_to_result,
|
166
|
+
pg_tmbc_fit_to_query,
|
167
|
+
pg_tmbc_fit_to_copy_get,
|
168
|
+
pg_tmbc_result_value,
|
169
|
+
pg_tmbc_typecast_query_param,
|
170
|
+
pg_tmbc_typecast_copy_get
|
171
171
|
};
|
172
172
|
|
173
173
|
static void
|