pg 0.17.1-x86-mingw32 → 0.18.0.pre20141017160319-x86-mingw32

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +1885 -169
  5. data/History.rdoc +6 -0
  6. data/Manifest.txt +25 -1
  7. data/README.rdoc +47 -0
  8. data/Rakefile +21 -12
  9. data/Rakefile.cross +39 -33
  10. data/ext/extconf.rb +27 -26
  11. data/ext/pg.c +73 -19
  12. data/ext/pg.h +194 -6
  13. data/ext/pg_binary_decoder.c +160 -0
  14. data/ext/pg_binary_encoder.c +160 -0
  15. data/ext/pg_coder.c +473 -0
  16. data/ext/pg_connection.c +872 -534
  17. data/ext/pg_copy_coder.c +557 -0
  18. data/ext/pg_result.c +266 -111
  19. data/ext/pg_text_decoder.c +424 -0
  20. data/ext/pg_text_encoder.c +631 -0
  21. data/ext/pg_type_map.c +113 -0
  22. data/ext/pg_type_map_all_strings.c +113 -0
  23. data/ext/pg_type_map_by_column.c +254 -0
  24. data/ext/pg_type_map_by_mri_type.c +266 -0
  25. data/ext/pg_type_map_by_oid.c +341 -0
  26. data/ext/util.c +149 -0
  27. data/ext/util.h +65 -0
  28. data/lib/1.9/pg_ext.so +0 -0
  29. data/lib/2.0/pg_ext.so +0 -0
  30. data/lib/2.1/pg_ext.so +0 -0
  31. data/lib/i386-mingw32/libpq.dll +0 -0
  32. data/lib/pg.rb +11 -1
  33. data/lib/pg/basic_type_mapping.rb +377 -0
  34. data/lib/pg/coder.rb +74 -0
  35. data/lib/pg/connection.rb +43 -1
  36. data/lib/pg/result.rb +13 -3
  37. data/lib/pg/text_decoder.rb +42 -0
  38. data/lib/pg/text_encoder.rb +27 -0
  39. data/lib/pg/type_map_by_column.rb +15 -0
  40. data/spec/{lib/helpers.rb → helpers.rb} +95 -35
  41. data/spec/pg/basic_type_mapping_spec.rb +251 -0
  42. data/spec/pg/connection_spec.rb +416 -214
  43. data/spec/pg/result_spec.rb +146 -116
  44. data/spec/pg/type_map_by_column_spec.rb +135 -0
  45. data/spec/pg/type_map_by_mri_type_spec.rb +122 -0
  46. data/spec/pg/type_map_by_oid_spec.rb +133 -0
  47. data/spec/pg/type_map_spec.rb +39 -0
  48. data/spec/pg/type_spec.rb +649 -0
  49. data/spec/pg_spec.rb +10 -18
  50. metadata +130 -52
  51. metadata.gz.sig +0 -0
  52. data/lib/1.8/pg_ext.so +0 -0
data/ext/pg.h CHANGED
@@ -24,7 +24,6 @@
24
24
  #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
25
25
  # include "ruby/encoding.h"
26
26
  # define M17N_SUPPORTED
27
- # define ASSOCIATE_INDEX( obj, index_holder ) rb_enc_associate_index((obj), pg_enc_get_index((index_holder)))
28
27
  # ifdef HAVE_RB_ENCDB_ALIAS
29
28
  extern int rb_encdb_alias(const char *, const char *);
30
29
  # define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
@@ -35,8 +34,28 @@
35
34
  extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
36
35
  # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
37
36
  # endif
37
+
38
+
39
+ # if !defined(ENCODING_SET_INLINED)
40
+ /* Rubinius doesn't define ENCODING_SET_INLINED, so we fall back to the more
41
+ * portable version.
42
+ */
43
+ # define PG_ENCODING_SET_NOCHECK(obj,i) \
44
+ do { \
45
+ rb_enc_set_index((obj), (i)); \
46
+ } while(0)
47
+ # else
48
+ # define PG_ENCODING_SET_NOCHECK(obj,i) \
49
+ do { \
50
+ if ((i) < ENCODING_INLINE_MAX) \
51
+ ENCODING_SET_INLINED((obj), (i)); \
52
+ else \
53
+ rb_enc_set_index((obj), (i)); \
54
+ } while(0)
55
+ # endif
56
+
38
57
  #else
39
- # define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
58
+ # define PG_ENCODING_SET_NOCHECK(obj,i) /* nothing */
40
59
  #endif
41
60
 
42
61
  #if RUBY_VM != 1
@@ -66,6 +85,11 @@
66
85
  # include "ruby/io.h"
67
86
  #endif
68
87
 
88
+ #ifdef RUBINIUS
89
+ /* Workaround for wrong FIXNUM_MAX definition */
90
+ typedef intptr_t native_int;
91
+ #endif
92
+
69
93
  #ifndef timeradd
70
94
  #define timeradd(a, b, result) \
71
95
  do { \
@@ -97,10 +121,101 @@
97
121
 
98
122
  #if defined(_WIN32)
99
123
  # include <fcntl.h>
100
- __declspec(dllexport)
101
124
  typedef long suseconds_t;
102
125
  #endif
103
126
 
127
+ /* The data behind each PG::Connection object */
128
+ typedef struct {
129
+ PGconn *pgconn;
130
+
131
+ /* Cached IO object for the socket descriptor */
132
+ VALUE socket_io;
133
+ /* Proc object that receives notices as PG::Result objects */
134
+ VALUE notice_receiver;
135
+ /* Proc object that receives notices as String objects */
136
+ VALUE notice_processor;
137
+ /* Kind of PG::TypeMap object for casting query params */
138
+ VALUE type_map_for_queries;
139
+ /* Kind of PG::TypeMap object for casting result values */
140
+ VALUE type_map_for_results;
141
+ /* IO object internally used for the trace stream */
142
+ VALUE trace_stream;
143
+ /* Cached Encoding object */
144
+ VALUE external_encoding;
145
+ /* Kind of PG::Coder object for casting ruby values to COPY rows */
146
+ VALUE encoder_for_put_copy_data;
147
+ /* Kind of PG::Coder object for casting COPY rows to ruby values */
148
+ VALUE decoder_for_get_copy_data;
149
+
150
+ } t_pg_connection;
151
+
152
+ typedef struct pg_coder t_pg_coder;
153
+ typedef struct pg_typemap t_typemap;
154
+
155
+ /* The data behind each PG::Result object */
156
+ typedef struct {
157
+ PGresult *pgresult;
158
+
159
+ /* The connection object used to build this result */
160
+ VALUE connection;
161
+
162
+ /* The TypeMap used to type cast result values */
163
+ VALUE typemap;
164
+
165
+ /* Pointer to the typemap object data. This is assumed to be
166
+ * always valid.
167
+ */
168
+ t_typemap *p_typemap;
169
+
170
+ /* 0 = PGresult is cleared by PG::Result#clear or by the GC
171
+ * 1 = PGresult is cleared internally by libpq
172
+ */
173
+ int autoclear;
174
+ } t_pg_result;
175
+
176
+
177
+ typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
178
+ typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
179
+ typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
180
+ typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
181
+ typedef int (* t_pg_fit_to_copy_get)(VALUE);
182
+ typedef VALUE (* t_pg_typecast_result)(VALUE, int, int);
183
+ typedef t_pg_coder *(* t_pg_typecast_query_param)(VALUE, VALUE, int);
184
+ typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
185
+
186
+ struct pg_coder {
187
+ t_pg_coder_enc_func enc_func;
188
+ t_pg_coder_dec_func dec_func;
189
+ VALUE coder_obj;
190
+ Oid oid;
191
+ int format;
192
+ };
193
+
194
+ typedef struct {
195
+ t_pg_coder comp;
196
+ t_pg_coder *elem;
197
+ int needs_quotation;
198
+ char delimiter;
199
+ } t_pg_composite_coder;
200
+
201
+ struct pg_typemap {
202
+ t_pg_fit_to_result fit_to_result;
203
+ t_pg_fit_to_query fit_to_query;
204
+ t_pg_fit_to_copy_get fit_to_copy_get;
205
+ t_pg_typecast_result typecast_result_value;
206
+ t_pg_typecast_query_param typecast_query_param;
207
+ t_pg_typecast_copy_get typecast_copy_get;
208
+ };
209
+
210
+ typedef struct {
211
+ t_typemap typemap;
212
+ int nfields;
213
+ struct pg_tmbc_converter {
214
+ t_pg_coder *cconv;
215
+ } convs[0];
216
+ } t_tmbc;
217
+
218
+
104
219
  #include "gvl_wrappers.h"
105
220
 
106
221
  /***************************************************************************
@@ -116,7 +231,23 @@ extern VALUE rb_mPGconstants;
116
231
  extern VALUE rb_cPGconn;
117
232
  extern VALUE rb_cPGresult;
118
233
  extern VALUE rb_hErrors;
234
+ extern VALUE rb_cTypeMap;
235
+ extern VALUE rb_cTypeMapAllStrings;
236
+ extern VALUE rb_cPG_Coder;
237
+ extern VALUE rb_cPG_SimpleEncoder;
238
+ extern VALUE rb_cPG_SimpleDecoder;
239
+ extern VALUE rb_cPG_CompositeEncoder;
240
+ extern VALUE rb_cPG_CompositeDecoder;
241
+ extern VALUE rb_cPG_CopyCoder;
242
+ extern VALUE rb_cPG_CopyEncoder;
243
+ extern VALUE rb_cPG_CopyDecoder;
244
+ extern VALUE rb_mPG_TextEncoder;
245
+ extern VALUE rb_mPG_TextDecoder;
246
+ extern VALUE rb_mPG_BinaryEncoder;
247
+ extern VALUE rb_mPG_BinaryDecoder;
248
+ extern const t_typemap pg_tmbc_default_typemap;
119
249
 
250
+ extern VALUE pg_default_typemap;
120
251
 
121
252
  /***************************************************************************
122
253
  * MACROS
@@ -134,19 +265,76 @@ void Init_pg_ext _(( void ));
134
265
  void init_pg_connection _(( void ));
135
266
  void init_pg_result _(( void ));
136
267
  void init_pg_errors _(( void ));
137
- VALUE lookup_error_class _(( const char *sqlstate ));
268
+ void init_pg_type_map _(( void ));
269
+ void init_pg_type_map_all_strings _(( void ));
270
+ void init_pg_type_map_by_column _(( void ));
271
+ void init_pg_type_map_by_mri_type _(( void ));
272
+ void init_pg_type_map_by_oid _(( void ));
273
+ void init_pg_coder _(( void ));
274
+ void init_pg_copycoder _(( void ));
275
+ void init_pg_text_encoder _(( void ));
276
+ void init_pg_text_decoder _(( void ));
277
+ void init_pg_binary_encoder _(( void ));
278
+ void init_pg_binary_decoder _(( void ));
279
+ VALUE lookup_error_class _(( const char * ));
280
+ VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
281
+ VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
282
+ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *));
283
+ t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
284
+ t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
285
+ void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
286
+ VALUE pg_obj_to_i _(( VALUE ));
287
+ VALUE pg_tmbc_allocate _(( void ));
288
+ void pg_coder_init_encoder _(( VALUE ));
289
+ void pg_coder_init_decoder _(( VALUE ));
290
+ char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
138
291
 
139
- PGconn *pg_get_pgconn _(( VALUE ));
292
+ #define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
293
+ do { \
294
+ if( (curr_ptr) + (expand_len) >= (end_ptr) ) \
295
+ (curr_ptr) = pg_rb_str_ensure_capa( (str), (expand_len), (curr_ptr), &(end_ptr) ); \
296
+ } while(0);
297
+
298
+ #define PG_RB_STR_NEW( str, curr_ptr, end_ptr ) ( \
299
+ (str) = rb_str_new( NULL, 0 ), \
300
+ (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
301
+ )
302
+
303
+ #define PG_RB_TAINTED_STR_NEW( str, curr_ptr, end_ptr ) ( \
304
+ (str) = rb_tainted_str_new( NULL, 0 ), \
305
+ (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
306
+ )
307
+
308
+ VALUE pg_typemap_fit_to_result _(( VALUE, VALUE ));
309
+ VALUE pg_typemap_fit_to_query _(( VALUE, VALUE ));
310
+ int pg_typemap_fit_to_copy_get _(( VALUE ));
311
+ VALUE pg_typemap_result_value _(( VALUE, int, int ));
312
+ t_pg_coder *pg_typemap_typecast_query_param _(( VALUE, VALUE, int ));
313
+ VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
314
+
315
+ PGconn *pg_get_pgconn _(( VALUE ));
316
+ t_pg_connection *pg_get_connection _(( VALUE ));
140
317
 
141
318
  VALUE pg_new_result _(( PGresult *, VALUE ));
319
+ VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
320
+ PGresult* pgresult_get _(( VALUE ));
142
321
  VALUE pg_result_check _(( VALUE ));
143
322
  VALUE pg_result_clear _(( VALUE ));
144
323
 
324
+ /*
325
+ * Fetch the data pointer for the result object
326
+ */
327
+ static inline t_pg_result *
328
+ pgresult_get_this( VALUE self )
329
+ {
330
+ return DATA_PTR(self);
331
+ }
332
+
333
+
145
334
  #ifdef M17N_SUPPORTED
146
335
  rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
147
336
  rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
148
337
  const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
149
- int pg_enc_get_index _(( VALUE ));
150
338
  rb_encoding *pg_conn_enc_get _(( PGconn * ));
151
339
  #endif /* M17N_SUPPORTED */
152
340
 
@@ -0,0 +1,160 @@
1
+ /*
2
+ * pg_column_map.c - PG::ColumnMap class extension
3
+ * $Id$
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+ #include "util.h"
9
+ #include <inttypes.h>
10
+
11
+ VALUE rb_mPG_BinaryDecoder;
12
+
13
+
14
+ /*
15
+ * Document-class: PG::BinaryDecoder::Boolean < PG::SimpleDecoder
16
+ *
17
+ * This is a decoder class for conversion of PostgreSQL binary bool type
18
+ * to Ruby true or false objects.
19
+ *
20
+ */
21
+ static VALUE
22
+ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
23
+ {
24
+ if (len < 1) {
25
+ rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
26
+ }
27
+ return *val == 0 ? Qfalse : Qtrue;
28
+ }
29
+
30
+ /*
31
+ * Document-class: PG::BinaryDecoder::Integer < PG::SimpleDecoder
32
+ *
33
+ * This is a decoder class for conversion of PostgreSQL binary int2, int4 and int8 types
34
+ * to Ruby Integer objects.
35
+ *
36
+ */
37
+ static VALUE
38
+ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
39
+ {
40
+ switch( len ){
41
+ case 2:
42
+ return INT2NUM(read_nbo16(val));
43
+ case 4:
44
+ return LONG2NUM(read_nbo32(val));
45
+ case 8:
46
+ return LL2NUM(read_nbo64(val));
47
+ default:
48
+ rb_raise( rb_eTypeError, "wrong data for binary integer converter in tuple %d field %d length %d", tuple, field, len);
49
+ }
50
+ }
51
+
52
+ /*
53
+ * Document-class: PG::BinaryDecoder::Float < PG::SimpleDecoder
54
+ *
55
+ * This is a decoder class for conversion of PostgreSQL binary float4 and float8 types
56
+ * to Ruby Float objects.
57
+ *
58
+ */
59
+ static VALUE
60
+ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
61
+ {
62
+ union {
63
+ float f;
64
+ int32_t i;
65
+ } swap4;
66
+ union {
67
+ double f;
68
+ int64_t i;
69
+ } swap8;
70
+
71
+ switch( len ){
72
+ case 4:
73
+ swap4.i = read_nbo32(val);
74
+ return rb_float_new(swap4.f);
75
+ case 8:
76
+ swap8.i = read_nbo64(val);
77
+ return rb_float_new(swap8.f);
78
+ default:
79
+ rb_raise( rb_eTypeError, "wrong data for BinaryFloat converter in tuple %d field %d length %d", tuple, field, len);
80
+ }
81
+ }
82
+
83
+ /*
84
+ * Document-class: PG::BinaryDecoder::Bytea < PG::SimpleDecoder
85
+ *
86
+ * This is a decoder class for conversion of PostgreSQL binary data (bytea)
87
+ * to binary Ruby String objects or some other Ruby object, if a #elements_type
88
+ * decoder was defined.
89
+ *
90
+ */
91
+ VALUE
92
+ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
93
+ {
94
+ VALUE ret;
95
+ ret = rb_tainted_str_new( val, len );
96
+ PG_ENCODING_SET_NOCHECK( ret, rb_ascii8bit_encindex() );
97
+ return ret;
98
+ }
99
+
100
+ /*
101
+ * Document-class: PG::BinaryDecoder::ToBase64 < PG::CompositeDecoder
102
+ *
103
+ * This is a decoder class for conversion of binary (bytea) to base64 data.
104
+ *
105
+ */
106
+ static VALUE
107
+ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
108
+ {
109
+ t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
110
+ t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
111
+ int encoded_len = BASE64_ENCODED_SIZE(len);
112
+ /* create a buffer of the encoded length */
113
+ VALUE out_value = rb_tainted_str_new(NULL, encoded_len);
114
+
115
+ base64_encode( RSTRING_PTR(out_value), val, len );
116
+
117
+ /* Is it a pure String conversion? Then we can directly send out_value to the user. */
118
+ if( this->comp.format == 0 && dec_func == pg_text_dec_string ){
119
+ PG_ENCODING_SET_NOCHECK( out_value, enc_idx );
120
+ return out_value;
121
+ }
122
+ if( this->comp.format == 1 && dec_func == pg_bin_dec_bytea ){
123
+ PG_ENCODING_SET_NOCHECK( out_value, rb_ascii8bit_encindex() );
124
+ return out_value;
125
+ }
126
+ out_value = dec_func(this->elem, RSTRING_PTR(out_value), encoded_len, tuple, field, enc_idx);
127
+
128
+ return out_value;
129
+ }
130
+
131
+ /*
132
+ * Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
133
+ *
134
+ * This is a decoder class for conversion of PostgreSQL text output to
135
+ * to Ruby String object. The output value will have the character encoding
136
+ * set with PG::Connection#internal_encoding= .
137
+ *
138
+ */
139
+
140
+ void
141
+ init_pg_binary_decoder()
142
+ {
143
+ /* This module encapsulates all decoder classes with binary input format */
144
+ rb_mPG_BinaryDecoder = rb_define_module_under( rb_mPG, "BinaryDecoder" );
145
+
146
+ /* Make RDoc aware of the decoder classes... */
147
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Boolean", rb_cPG_SimpleDecoder ); */
148
+ pg_define_coder( "Boolean", pg_bin_dec_boolean, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
149
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Integer", rb_cPG_SimpleDecoder ); */
150
+ pg_define_coder( "Integer", pg_bin_dec_integer, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
151
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Float", rb_cPG_SimpleDecoder ); */
152
+ pg_define_coder( "Float", pg_bin_dec_float, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
153
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "String", rb_cPG_SimpleDecoder ); */
154
+ pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
155
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
156
+ pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
157
+
158
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
159
+ pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
160
+ }
@@ -0,0 +1,160 @@
1
+ /*
2
+ * pg_column_map.c - PG::ColumnMap class extension
3
+ * $Id$
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+ #include "util.h"
9
+ #include <inttypes.h>
10
+
11
+ VALUE rb_mPG_BinaryEncoder;
12
+
13
+
14
+ /*
15
+ * Document-class: PG::BinaryEncoder::Boolean < PG::SimpleEncoder
16
+ *
17
+ * This is the encoder class for the PostgreSQL boolean type.
18
+ *
19
+ * It accepts true and false. Other values will raise an exception.
20
+ *
21
+ */
22
+ static int
23
+ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
24
+ {
25
+ char bool;
26
+ switch(value){
27
+ case Qtrue : bool = 1; break;
28
+ case Qfalse : bool = 0; break;
29
+ default :
30
+ rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
31
+ }
32
+ if(out) *out = bool;
33
+ return 1;
34
+ }
35
+
36
+ /*
37
+ * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
38
+ *
39
+ * This is the encoder class for the PostgreSQL int2 type.
40
+ *
41
+ * Non-Number values are expected to have method +to_i+ defined.
42
+ *
43
+ */
44
+ static int
45
+ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
46
+ {
47
+ if(out){
48
+ write_nbo16(NUM2INT(*intermediate), out);
49
+ }else{
50
+ *intermediate = pg_obj_to_i(value);
51
+ }
52
+ return 2;
53
+ }
54
+
55
+ /*
56
+ * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
57
+ *
58
+ * This is the encoder class for the PostgreSQL int4 type.
59
+ *
60
+ * Non-Number values are expected to have method +to_i+ defined.
61
+ *
62
+ */
63
+ static int
64
+ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
65
+ {
66
+ if(out){
67
+ write_nbo32(NUM2LONG(*intermediate), out);
68
+ }else{
69
+ *intermediate = pg_obj_to_i(value);
70
+ }
71
+ return 4;
72
+ }
73
+
74
+ /*
75
+ * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
76
+ *
77
+ * This is the encoder class for the PostgreSQL int8 type.
78
+ *
79
+ * Non-Number values are expected to have method +to_i+ defined.
80
+ *
81
+ */
82
+ static int
83
+ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
84
+ {
85
+ if(out){
86
+ write_nbo64(NUM2LL(*intermediate), out);
87
+ }else{
88
+ *intermediate = pg_obj_to_i(value);
89
+ }
90
+ return 8;
91
+ }
92
+
93
+ /*
94
+ * Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
95
+ *
96
+ * This is an encoder class for conversion of base64 encoded data
97
+ * to it's binary representation.
98
+ *
99
+ */
100
+ static int
101
+ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
102
+ {
103
+ int strlen;
104
+ VALUE subint;
105
+ t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
106
+ t_pg_coder_enc_func enc_func = pg_coder_enc_func(this->elem);
107
+
108
+ if(out){
109
+ /* Second encoder pass, if required */
110
+ strlen = enc_func(this->elem, value, out, intermediate);
111
+ strlen = base64_decode( out, out, strlen );
112
+
113
+ return strlen;
114
+ } else {
115
+ /* First encoder pass */
116
+ strlen = enc_func(this->elem, value, NULL, &subint);
117
+
118
+ if( strlen == -1 ){
119
+ /* Encoded string is returned in subint */
120
+ VALUE out_str;
121
+
122
+ strlen = RSTRING_LENINT(subint);
123
+ out_str = rb_str_new(NULL, BASE64_DECODED_SIZE(strlen));
124
+
125
+ strlen = base64_decode( RSTRING_PTR(out_str), RSTRING_PTR(subint), strlen);
126
+ rb_str_set_len( out_str, strlen );
127
+ *intermediate = out_str;
128
+
129
+ return -1;
130
+ } else {
131
+ *intermediate = subint;
132
+
133
+ return BASE64_DECODED_SIZE(strlen);
134
+ }
135
+ }
136
+ }
137
+
138
+ void
139
+ init_pg_binary_encoder()
140
+ {
141
+ /* This module encapsulates all encoder classes with binary output format */
142
+ rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
143
+
144
+ /* Make RDoc aware of the encoder classes... */
145
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Boolean", rb_cPG_SimpleEncoder ); */
146
+ pg_define_coder( "Boolean", pg_bin_enc_boolean, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
147
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int2", rb_cPG_SimpleEncoder ); */
148
+ pg_define_coder( "Int2", pg_bin_enc_int2, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
149
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int4", rb_cPG_SimpleEncoder ); */
150
+ pg_define_coder( "Int4", pg_bin_enc_int4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
151
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int8", rb_cPG_SimpleEncoder ); */
152
+ pg_define_coder( "Int8", pg_bin_enc_int8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
153
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "String", rb_cPG_SimpleEncoder ); */
154
+ pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
155
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
156
+ pg_define_coder( "Bytea", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
157
+
158
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "FromBase64", rb_cPG_CompositeEncoder ); */
159
+ pg_define_coder( "FromBase64", pg_bin_enc_from_base64, rb_cPG_CompositeEncoder, rb_mPG_BinaryEncoder );
160
+ }