pg 0.18.0.pre20141017155815 → 0.18.0.pre20141017160319

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95311a9d99ccb8ee189f70f82db3c3246482cf5f
4
- data.tar.gz: 72e13155d8032762a39b0628b882acb55325f8a2
3
+ metadata.gz: db79067db275bd6f5d8fb5194610716de4eba838
4
+ data.tar.gz: 30aa3c6d3ea706306adc3059b16349429f2c15c6
5
5
  SHA512:
6
- metadata.gz: 2497dbc6ea9a9ea96fc6731b548b7d0c49c38be819b5b4eb927f432483e7df35603bf4247a14936cb566702ff6c90361e4e9cd815c97d75ca88b367ac8fdc184
7
- data.tar.gz: d8475aef22cda0e31655b5edb58838b83c6dafe2e2fd5f10a051901af817c80f2d569a97d096bbdbbf1ef6f67017666661acedef70364010bacdddc5bce5f640
6
+ metadata.gz: 76c17fe2bbbdcf10ffe5e6ba71fde8babc6723ff8a3673455fc647a77f8f718caecf77cab6e255a45c46db01cfaa1fde83db75a26cb39712e10e462f143629ed
7
+ data.tar.gz: 77b0e5b2993e2c1a2c5a31a7ad2ffd3bd2ed292111e07bf6fc96f85074001d9434f2a9e6614aefb5f931c0534b4ba1611de54e9f0000e558790606f88aeab5ac
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, tip]
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.
@@ -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 );
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_text_encoder.c - PG::TextEncoder module
3
- * $Id: pg_text_encoder.c,v ac23631c96d9 2014/10/14 11:50:21 lars $
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
- end_ptr = write_array(this, value, RSTRING_PTR(*intermediate), *intermediate, this->needs_quotation);
405
+ if( TYPE(value) == T_ARRAY){
406
+ *intermediate = rb_str_new(NULL, 0);
399
407
 
400
- rb_str_set_len( *intermediate, end_ptr - RSTRING_PTR(*intermediate) );
408
+ end_ptr = write_array(this, value, RSTRING_PTR(*intermediate), *intermediate, this->needs_quotation);
401
409
 
402
- return -1;
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", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
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 c8d7c26dd595 2014/10/12 17:08:46 lars $
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
@@ -60,4 +60,6 @@
60
60
  void base64_encode( char *out, char *in, int len);
61
61
  int base64_decode( char *out, char *in, unsigned int len);
62
62
 
63
+ int pg_strncasecmp(const char *s1, const char *s2, size_t n);
64
+
63
65
  #endif /* end __utils_h */
@@ -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
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0.pre20141017155815
4
+ version: 0.18.0.pre20141017160319
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
metadata.gz.sig CHANGED
Binary file