pg 0.18.0.pre20141017155815 → 0.18.0.pre20141017160319
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +19 -1
- data/ext/pg_coder.c +19 -0
- data/ext/pg_text_encoder.c +57 -34
- data/ext/util.c +29 -1
- data/ext/util.h +2 -0
- data/spec/pg/type_spec.rb +29 -0
- metadata +1 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db79067db275bd6f5d8fb5194610716de4eba838
|
4
|
+
data.tar.gz: 30aa3c6d3ea706306adc3059b16349429f2c15c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76c17fe2bbbdcf10ffe5e6ba71fde8babc6723ff8a3673455fc647a77f8f718caecf77cab6e255a45c46db01cfaa1fde83db75a26cb39712e10e462f143629ed
|
7
|
+
data.tar.gz: 77b0e5b2993e2c1a2c5a31a7ad2ffd3bd2ed292111e07bf6fc96f85074001d9434f2a9e6614aefb5f931c0534b4ba1611de54e9f0000e558790606f88aeab5ac
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,10 +1,28 @@
|
|
1
|
+
2014-10-15 Lars Kanis <lars@greiz-reinsdorf.de>
|
2
|
+
|
3
|
+
* ext/pg_text_encoder.c, spec/pg/type_spec.rb:
|
4
|
+
Allow non Array values as input for TextEncoder::Array.
|
5
|
+
[a4725dfca9e4] [tip]
|
6
|
+
|
7
|
+
* ext/pg_coder.c, spec/pg/type_spec.rb:
|
8
|
+
Clarify handling of nil/NULL values by PG::Coders.
|
9
|
+
[99d6acb8b66d]
|
10
|
+
|
11
|
+
* ext/pg_text_encoder.c, ext/util.c, ext/util.h:
|
12
|
+
Move pg_strncasecmp() to util.c - it better fits there.
|
13
|
+
[117fb5c5eed7]
|
14
|
+
|
1
15
|
2014-10-14 Lars Kanis <lars@greiz-reinsdorf.de>
|
2
16
|
|
17
|
+
* ext/pg_text_encoder.c, spec/pg/type_spec.rb:
|
18
|
+
Implement a more serious TestEncoder::Boolean.
|
19
|
+
[9063a84a2ff9]
|
20
|
+
|
3
21
|
* ext/pg.h, ext/pg_binary_encoder.c, ext/pg_coder.c,
|
4
22
|
ext/pg_text_encoder.c:
|
5
23
|
Fix naming and description of pg_coder_enc_to_s(). It actually uses
|
6
24
|
#to_s not #to_str.
|
7
|
-
[ac23631c96d9] [github/master
|
25
|
+
[ac23631c96d9] [github/master]
|
8
26
|
|
9
27
|
* ext/pg_text_encoder.c, spec/pg/type_spec.rb:
|
10
28
|
Use same rules for array quoting in text encoder as PostgreSQL.
|
data/ext/pg_coder.c
CHANGED
@@ -109,6 +109,8 @@ pg_composite_decoder_allocate( VALUE klass )
|
|
109
109
|
* Encodes the given Ruby object into string representation, without
|
110
110
|
* sending data to/from the database server.
|
111
111
|
*
|
112
|
+
* A nil value is passed through.
|
113
|
+
*
|
112
114
|
*/
|
113
115
|
static VALUE
|
114
116
|
pg_coder_encode(VALUE self, VALUE value)
|
@@ -118,6 +120,9 @@ pg_coder_encode(VALUE self, VALUE value)
|
|
118
120
|
int len, len2;
|
119
121
|
t_pg_coder *this = DATA_PTR(self);
|
120
122
|
|
123
|
+
if( NIL_P(value) )
|
124
|
+
return Qnil;
|
125
|
+
|
121
126
|
if( !this->enc_func ){
|
122
127
|
rb_raise(rb_eRuntimeError, "no encoder function defined");
|
123
128
|
}
|
@@ -151,6 +156,9 @@ pg_coder_encode(VALUE self, VALUE value)
|
|
151
156
|
* Decodes the given string representation into a Ruby object, without
|
152
157
|
* sending data to/from the database server.
|
153
158
|
*
|
159
|
+
* A nil value is passed through and non String values are expected to have
|
160
|
+
* #to_str defined.
|
161
|
+
*
|
154
162
|
*/
|
155
163
|
static VALUE
|
156
164
|
pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
@@ -168,6 +176,9 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
168
176
|
field = NUM2INT(argv[2]);
|
169
177
|
}
|
170
178
|
|
179
|
+
if( NIL_P(argv[0]) )
|
180
|
+
return Qnil;
|
181
|
+
|
171
182
|
val = StringValuePtr(argv[0]);
|
172
183
|
if( !this->dec_func ){
|
173
184
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
@@ -406,6 +417,14 @@ init_pg_coder()
|
|
406
417
|
/* Document-class: PG::Coder < Object
|
407
418
|
*
|
408
419
|
* This is the base class for all type cast encoder and decoder classes.
|
420
|
+
*
|
421
|
+
* It can be used for implicit type casts by a PG::TypeMap or to
|
422
|
+
* convert single values to/from their string representation by #encode
|
423
|
+
* and #decode.
|
424
|
+
*
|
425
|
+
* Ruby +nil+ values are not handled by encoders, but are always transmitted
|
426
|
+
* as SQL +NULL+ value. Vice versa SQL +NULL+ values are not handled by decoders,
|
427
|
+
* but are always returned as a +nil+ value.
|
409
428
|
*/
|
410
429
|
rb_cPG_Coder = rb_define_class_under( rb_mPG, "Coder", rb_cObject );
|
411
430
|
rb_define_alloc_func( rb_cPG_Coder, pg_coder_allocate );
|
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 a4725dfca9e4 2014/10/15 19:50:56 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -46,6 +46,7 @@
|
|
46
46
|
VALUE rb_mPG_TextEncoder;
|
47
47
|
static ID s_id_encode;
|
48
48
|
static ID s_id_to_i;
|
49
|
+
static VALUE hash_false_values;
|
49
50
|
|
50
51
|
|
51
52
|
VALUE
|
@@ -66,7 +67,39 @@ pg_obj_to_i( VALUE value )
|
|
66
67
|
*
|
67
68
|
* This is the encoder class for the PostgreSQL bool type.
|
68
69
|
*
|
70
|
+
* Ruby values false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off' and 'OFF'
|
71
|
+
* are encoded as SQL +FALSE+ value. nil is sent as SQL +NULL+.
|
72
|
+
* Any other values are encoded as SQL +TRUE+ .
|
73
|
+
*
|
69
74
|
*/
|
75
|
+
static int
|
76
|
+
pg_text_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
77
|
+
{
|
78
|
+
if(out){
|
79
|
+
switch( TYPE(value) ){
|
80
|
+
case T_FALSE:
|
81
|
+
*out = 'f';
|
82
|
+
break;
|
83
|
+
case T_FIXNUM:
|
84
|
+
case T_BIGNUM:
|
85
|
+
if( NUM2LONG(value) == 0 ){
|
86
|
+
*out = 'f';
|
87
|
+
} else {
|
88
|
+
*out = 't';
|
89
|
+
}
|
90
|
+
break;
|
91
|
+
case T_STRING:
|
92
|
+
if( rb_hash_lookup(hash_false_values, value) == Qtrue ){
|
93
|
+
*out = 'f';
|
94
|
+
break;
|
95
|
+
}
|
96
|
+
/* fall through */
|
97
|
+
default:
|
98
|
+
*out = 't';
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return 1;
|
102
|
+
}
|
70
103
|
|
71
104
|
|
72
105
|
/*
|
@@ -213,34 +246,6 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
|
213
246
|
}
|
214
247
|
}
|
215
248
|
|
216
|
-
/*
|
217
|
-
* Case-independent comparison of two not-necessarily-null-terminated strings.
|
218
|
-
* At most n bytes will be examined from each string.
|
219
|
-
*/
|
220
|
-
static int
|
221
|
-
pg_strncasecmp(const char *s1, const char *s2, size_t n)
|
222
|
-
{
|
223
|
-
while (n-- > 0)
|
224
|
-
{
|
225
|
-
unsigned char ch1 = (unsigned char) *s1++;
|
226
|
-
unsigned char ch2 = (unsigned char) *s2++;
|
227
|
-
|
228
|
-
if (ch1 != ch2){
|
229
|
-
if (ch1 >= 'A' && ch1 <= 'Z')
|
230
|
-
ch1 += 'a' - 'A';
|
231
|
-
|
232
|
-
if (ch2 >= 'A' && ch2 <= 'Z')
|
233
|
-
ch2 += 'a' - 'A';
|
234
|
-
|
235
|
-
if (ch1 != ch2)
|
236
|
-
return (int) ch1 - (int) ch2;
|
237
|
-
}
|
238
|
-
if (ch1 == 0)
|
239
|
-
break;
|
240
|
-
}
|
241
|
-
return 0;
|
242
|
-
}
|
243
|
-
|
244
249
|
typedef int (*t_quote_func)( void *_this, char *p_in, int strlen, char *p_out );
|
245
250
|
|
246
251
|
static int
|
@@ -387,19 +392,27 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
387
392
|
* All values are encoded according to the #elements_type
|
388
393
|
* accessor. Sub-arrays are encoded recursively.
|
389
394
|
*
|
395
|
+
* This encoder expects an Array of values or sub-arrays as input.
|
396
|
+
* Other values are passed through as text without interpretation.
|
397
|
+
*
|
390
398
|
*/
|
391
399
|
static int
|
392
400
|
pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
393
401
|
{
|
394
402
|
char *end_ptr;
|
395
403
|
t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
|
396
|
-
*intermediate = rb_str_new(NULL, 0);
|
397
404
|
|
398
|
-
|
405
|
+
if( TYPE(value) == T_ARRAY){
|
406
|
+
*intermediate = rb_str_new(NULL, 0);
|
399
407
|
|
400
|
-
|
408
|
+
end_ptr = write_array(this, value, RSTRING_PTR(*intermediate), *intermediate, this->needs_quotation);
|
401
409
|
|
402
|
-
|
410
|
+
rb_str_set_len( *intermediate, end_ptr - RSTRING_PTR(*intermediate) );
|
411
|
+
|
412
|
+
return -1;
|
413
|
+
} else {
|
414
|
+
return pg_coder_enc_to_s( conv, value, out, intermediate );
|
415
|
+
}
|
403
416
|
}
|
404
417
|
|
405
418
|
static int
|
@@ -584,12 +597,22 @@ init_pg_text_encoder()
|
|
584
597
|
s_id_encode = rb_intern("encode");
|
585
598
|
s_id_to_i = rb_intern("to_i");
|
586
599
|
|
600
|
+
hash_false_values = rb_hash_new();
|
601
|
+
rb_gc_register_address( &hash_false_values );
|
602
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "0" ), Qtrue );
|
603
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "f" ), Qtrue );
|
604
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "F" ), Qtrue );
|
605
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "false" ), Qtrue );
|
606
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "FALSE" ), Qtrue );
|
607
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "off" ), Qtrue );
|
608
|
+
rb_hash_aset( hash_false_values, rb_str_new2( "OFF" ), Qtrue );
|
609
|
+
|
587
610
|
/* This module encapsulates all encoder classes with text output format */
|
588
611
|
rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" );
|
589
612
|
|
590
613
|
/* Make RDoc aware of the encoder classes... */
|
591
614
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Boolean", rb_cPG_SimpleEncoder ); */
|
592
|
-
pg_define_coder( "Boolean",
|
615
|
+
pg_define_coder( "Boolean", pg_text_enc_boolean, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
|
593
616
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Integer", rb_cPG_SimpleEncoder ); */
|
594
617
|
pg_define_coder( "Integer", pg_text_enc_integer, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
|
595
618
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Float", rb_cPG_SimpleEncoder ); */
|
data/ext/util.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* util.c - Utils for ruby-pg
|
3
|
-
* $Id: util.c,v
|
3
|
+
* $Id: util.c,v 117fb5c5eed7 2014/10/15 18:36:39 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -119,3 +119,31 @@ base64_decode( char *out, char *in, unsigned int len)
|
|
119
119
|
return (char*)out_ptr - out;
|
120
120
|
}
|
121
121
|
|
122
|
+
/*
|
123
|
+
* Case-independent comparison of two not-necessarily-null-terminated strings.
|
124
|
+
* At most n bytes will be examined from each string.
|
125
|
+
*/
|
126
|
+
int
|
127
|
+
pg_strncasecmp(const char *s1, const char *s2, size_t n)
|
128
|
+
{
|
129
|
+
while (n-- > 0)
|
130
|
+
{
|
131
|
+
unsigned char ch1 = (unsigned char) *s1++;
|
132
|
+
unsigned char ch2 = (unsigned char) *s2++;
|
133
|
+
|
134
|
+
if (ch1 != ch2){
|
135
|
+
if (ch1 >= 'A' && ch1 <= 'Z')
|
136
|
+
ch1 += 'a' - 'A';
|
137
|
+
|
138
|
+
if (ch2 >= 'A' && ch2 <= 'Z')
|
139
|
+
ch2 += 'a' - 'A';
|
140
|
+
|
141
|
+
if (ch1 != ch2)
|
142
|
+
return (int) ch1 - (int) ch2;
|
143
|
+
}
|
144
|
+
if (ch1 == 0)
|
145
|
+
break;
|
146
|
+
}
|
147
|
+
return 0;
|
148
|
+
}
|
149
|
+
|
data/ext/util.h
CHANGED
data/spec/pg/type_spec.rb
CHANGED
@@ -7,6 +7,8 @@ require 'pg'
|
|
7
7
|
describe "PG::Type derivations" do
|
8
8
|
let!(:textenc_int) { PG::TextEncoder::Integer.new name: 'Integer', oid: 23 }
|
9
9
|
let!(:textdec_int) { PG::TextDecoder::Integer.new name: 'Integer', oid: 23 }
|
10
|
+
let!(:textenc_boolean) { PG::TextEncoder::Boolean.new }
|
11
|
+
let!(:textdec_boolean) { PG::TextDecoder::Boolean.new }
|
10
12
|
let!(:textenc_float) { PG::TextEncoder::Float.new }
|
11
13
|
let!(:textdec_float) { PG::TextDecoder::Float.new }
|
12
14
|
let!(:textenc_string) { PG::TextEncoder::String.new }
|
@@ -88,6 +90,11 @@ describe "PG::Type derivations" do
|
|
88
90
|
expect{ textdec_int.decode(2, 3, 4) }.to raise_error(TypeError)
|
89
91
|
expect( intdec_incrementer.decode(2, 3, 4) ).to eq( 3 )
|
90
92
|
end
|
93
|
+
|
94
|
+
it "should pass through nil values" do
|
95
|
+
expect( textdec_string.encode( nil )).to be_nil
|
96
|
+
expect( textdec_int.encode( nil )).to be_nil
|
97
|
+
end
|
91
98
|
end
|
92
99
|
|
93
100
|
describe '#encode' do
|
@@ -130,6 +137,18 @@ describe "PG::Type derivations" do
|
|
130
137
|
expect( textenc_int.encode(" 123-xyz ") ).to eq( "123" )
|
131
138
|
end
|
132
139
|
|
140
|
+
it "should encode false and 0 to SQL FALSE value" do
|
141
|
+
[false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].each do |value|
|
142
|
+
expect( textenc_boolean.encode(value) ).to eq( "f" )
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should encode true, 1 to SQL TRUE value" do
|
147
|
+
[true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].each do |value|
|
148
|
+
expect( textenc_boolean.encode(value) ).to eq( "t" )
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
133
152
|
it "should encode special floats equally to Float#to_s" do
|
134
153
|
expect( textenc_float.encode(Float::INFINITY) ).to eq( Float::INFINITY.to_s )
|
135
154
|
expect( textenc_float.encode(-Float::INFINITY) ).to eq( (-Float::INFINITY).to_s )
|
@@ -143,6 +162,11 @@ describe "PG::Type derivations" do
|
|
143
162
|
it "should return when ruby encoder returns non string values" do
|
144
163
|
expect( intenc_incrementer_with_int_result.encode(3) ).to eq( 4 )
|
145
164
|
end
|
165
|
+
|
166
|
+
it "should pass through nil values" do
|
167
|
+
expect( textenc_string.encode( nil )).to be_nil
|
168
|
+
expect( textenc_int.encode( nil )).to be_nil
|
169
|
+
end
|
146
170
|
end
|
147
171
|
|
148
172
|
it "should be possible to marshal encoders" do
|
@@ -377,6 +401,11 @@ describe "PG::Type derivations" do
|
|
377
401
|
end
|
378
402
|
end
|
379
403
|
|
404
|
+
it "should pass through non Array inputs" do
|
405
|
+
expect( textenc_float_array.encode("text") ).to eq( "text" )
|
406
|
+
expect( textenc_float_array.encode(1234) ).to eq( "1234" )
|
407
|
+
end
|
408
|
+
|
380
409
|
context 'identifier quotation' do
|
381
410
|
it 'should quote and escape identifier' do
|
382
411
|
quoted_type = PG::TextEncoder::Identifier.new elements_type: textenc_string
|
metadata
CHANGED
metadata.gz.sig
CHANGED
Binary file
|