pg 0.18.0.pre20140820094244 → 0.18.0.pre20141017155815
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 +1573 -2
- data/History.rdoc +3 -11
- data/Manifest.txt +24 -0
- data/README.rdoc +51 -4
- data/Rakefile +20 -14
- data/Rakefile.cross +39 -32
- data/ext/extconf.rb +27 -26
- data/ext/pg.c +75 -21
- data/ext/pg.h +194 -6
- data/ext/pg_binary_decoder.c +160 -0
- data/ext/pg_binary_encoder.c +160 -0
- data/ext/pg_coder.c +454 -0
- data/ext/pg_connection.c +815 -518
- data/ext/pg_copy_coder.c +557 -0
- data/ext/pg_result.c +258 -103
- data/ext/pg_text_decoder.c +424 -0
- data/ext/pg_text_encoder.c +608 -0
- data/ext/pg_type_map.c +113 -0
- data/ext/pg_type_map_all_strings.c +113 -0
- data/ext/pg_type_map_by_column.c +254 -0
- data/ext/pg_type_map_by_mri_type.c +266 -0
- data/ext/pg_type_map_by_oid.c +341 -0
- data/ext/util.c +121 -0
- data/ext/util.h +63 -0
- data/lib/pg.rb +11 -1
- data/lib/pg/basic_type_mapping.rb +377 -0
- data/lib/pg/coder.rb +74 -0
- data/lib/pg/connection.rb +38 -5
- data/lib/pg/result.rb +13 -3
- data/lib/pg/text_decoder.rb +42 -0
- data/lib/pg/text_encoder.rb +27 -0
- data/lib/pg/type_map_by_column.rb +15 -0
- data/spec/helpers.rb +9 -1
- data/spec/pg/basic_type_mapping_spec.rb +251 -0
- data/spec/pg/connection_spec.rb +232 -13
- data/spec/pg/result_spec.rb +52 -0
- data/spec/pg/type_map_by_column_spec.rb +135 -0
- data/spec/pg/type_map_by_mri_type_spec.rb +122 -0
- data/spec/pg/type_map_by_oid_spec.rb +133 -0
- data/spec/pg/type_map_spec.rb +39 -0
- data/spec/pg/type_spec.rb +620 -0
- metadata +40 -4
- metadata.gz.sig +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
|
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
|
-
|
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
|
-
|
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: pg_binary_decoder.c,v f786006b25ff 2014/10/12 17:40:31 lars $
|
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: pg_binary_encoder.c,v ac23631c96d9 2014/10/14 11:50:21 lars $
|
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
|
+
}
|