pg 0.19.0 → 1.1.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/ChangeLog +218 -1
- data/History.rdoc +106 -0
- data/Manifest.txt +5 -18
- data/README.rdoc +15 -5
- data/Rakefile +8 -9
- data/Rakefile.cross +19 -22
- data/ext/errorcodes.def +17 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +11 -1
- data/ext/extconf.rb +14 -32
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -39
- data/ext/pg.c +19 -48
- data/ext/pg.h +46 -81
- data/ext/pg_binary_decoder.c +69 -6
- data/ext/pg_coder.c +53 -4
- data/ext/pg_connection.c +401 -253
- data/ext/pg_copy_coder.c +10 -5
- data/ext/pg_result.c +359 -131
- data/ext/pg_text_decoder.c +597 -37
- data/ext/pg_text_encoder.c +6 -7
- data/ext/pg_tuple.c +541 -0
- data/ext/pg_type_map.c +14 -7
- data/ext/util.c +6 -6
- data/ext/util.h +2 -2
- data/lib/pg/basic_type_mapping.rb +40 -7
- data/lib/pg/binary_decoder.rb +22 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +27 -7
- data/lib/pg/constants.rb +1 -1
- data/lib/pg/exceptions.rb +1 -1
- data/lib/pg/result.rb +6 -5
- data/lib/pg/text_decoder.rb +19 -23
- data/lib/pg/text_encoder.rb +36 -2
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +1 -1
- data/lib/pg.rb +21 -11
- data/spec/helpers.rb +47 -19
- data/spec/pg/basic_type_mapping_spec.rb +230 -27
- data/spec/pg/connection_spec.rb +402 -275
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +59 -17
- data/spec/pg/tuple_spec.rb +280 -0
- data/spec/pg/type_map_by_class_spec.rb +2 -2
- data/spec/pg/type_map_by_column_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_map_by_oid_spec.rb +1 -1
- data/spec/pg/type_map_in_ruby_spec.rb +1 -1
- data/spec/pg/type_map_spec.rb +1 -1
- data/spec/pg/type_spec.rb +184 -12
- data/spec/pg_spec.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +47 -53
- 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_binary_decoder.c
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
/*
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
3
|
-
* $Id: pg_binary_decoder.c,v
|
3
|
+
* $Id: pg_binary_decoder.c,v 5d166a4d0441 2018/07/29 12:03:00 lars $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
7
|
+
#include "ruby/version.h"
|
7
8
|
#include "pg.h"
|
8
9
|
#include "util.h"
|
9
10
|
#ifdef HAVE_INTTYPES_H
|
@@ -21,7 +22,7 @@ VALUE rb_mPG_BinaryDecoder;
|
|
21
22
|
*
|
22
23
|
*/
|
23
24
|
static VALUE
|
24
|
-
pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
25
|
+
pg_bin_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
25
26
|
{
|
26
27
|
if (len < 1) {
|
27
28
|
rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
|
@@ -37,7 +38,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, i
|
|
37
38
|
*
|
38
39
|
*/
|
39
40
|
static VALUE
|
40
|
-
pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
41
|
+
pg_bin_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
41
42
|
{
|
42
43
|
switch( len ){
|
43
44
|
case 2:
|
@@ -59,7 +60,7 @@ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, i
|
|
59
60
|
*
|
60
61
|
*/
|
61
62
|
static VALUE
|
62
|
-
pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
63
|
+
pg_bin_dec_float(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
63
64
|
{
|
64
65
|
union {
|
65
66
|
float f;
|
@@ -91,7 +92,7 @@ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int
|
|
91
92
|
*
|
92
93
|
*/
|
93
94
|
VALUE
|
94
|
-
pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
95
|
+
pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
95
96
|
{
|
96
97
|
VALUE ret;
|
97
98
|
ret = rb_tainted_str_new( val, len );
|
@@ -106,7 +107,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int
|
|
106
107
|
*
|
107
108
|
*/
|
108
109
|
static VALUE
|
109
|
-
pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
110
|
+
pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
110
111
|
{
|
111
112
|
t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
|
112
113
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
|
@@ -130,6 +131,66 @@ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field,
|
|
130
131
|
return out_value;
|
131
132
|
}
|
132
133
|
|
134
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
135
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Document-class: PG::BinaryDecoder::Timestamp < PG::SimpleDecoder
|
139
|
+
*
|
140
|
+
* This is a decoder class for conversion of PostgreSQL binary timestamps
|
141
|
+
* to Ruby Time objects.
|
142
|
+
*
|
143
|
+
* The following flags can be used to specify timezone interpretation:
|
144
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Interpret timestamp as UTC time (default)
|
145
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Interpret timestamp as local time
|
146
|
+
* * +PG::Coder::TIMESTAMP_APP_UTC+ : Return timestamp as UTC time (default)
|
147
|
+
* * +PG::Coder::TIMESTAMP_APP_LOCAL+ : Return timestamp as local time
|
148
|
+
*
|
149
|
+
* Example:
|
150
|
+
* deco = PG::BinaryDecoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL)
|
151
|
+
* deco.decode("\0"*8) # => 2000-01-01 01:00:00 +0100
|
152
|
+
*/
|
153
|
+
static VALUE
|
154
|
+
pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
155
|
+
{
|
156
|
+
int64_t timestamp;
|
157
|
+
struct timespec ts;
|
158
|
+
VALUE t;
|
159
|
+
|
160
|
+
if( len != sizeof(timestamp) ){
|
161
|
+
rb_raise( rb_eTypeError, "wrong data for timestamp converter in tuple %d field %d length %d", tuple, field, len);
|
162
|
+
}
|
163
|
+
|
164
|
+
timestamp = read_nbo64(val);
|
165
|
+
|
166
|
+
switch(timestamp){
|
167
|
+
case PG_INT64_MAX:
|
168
|
+
return rb_str_new2("infinity");
|
169
|
+
case PG_INT64_MIN:
|
170
|
+
return rb_str_new2("-infinity");
|
171
|
+
default:
|
172
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
173
|
+
* Adjust the 30 years difference. */
|
174
|
+
ts.tv_sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
|
175
|
+
ts.tv_nsec = (timestamp % 1000000) * 1000;
|
176
|
+
|
177
|
+
#if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T)
|
178
|
+
/* Fast path for time conversion */
|
179
|
+
t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
|
180
|
+
#else
|
181
|
+
t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(ts.tv_sec), LL2NUM(ts.tv_nsec / 1000));
|
182
|
+
if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
|
183
|
+
t = rb_funcall(t, rb_intern("utc"), 0);
|
184
|
+
}
|
185
|
+
#endif
|
186
|
+
if( conv->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
187
|
+
/* interpret it as local time */
|
188
|
+
t = rb_funcall(t, rb_intern("-"), 1, rb_funcall(t, rb_intern("utc_offset"), 0));
|
189
|
+
}
|
190
|
+
return t;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
133
194
|
/*
|
134
195
|
* Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
|
135
196
|
*
|
@@ -156,6 +217,8 @@ init_pg_binary_decoder()
|
|
156
217
|
pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
157
218
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
|
158
219
|
pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
220
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */
|
221
|
+
pg_define_coder( "Timestamp", pg_bin_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
159
222
|
|
160
223
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
|
161
224
|
pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
|
data/ext/pg_coder.c
CHANGED
@@ -38,6 +38,7 @@ pg_coder_init_encoder( VALUE self )
|
|
38
38
|
this->coder_obj = self;
|
39
39
|
this->oid = 0;
|
40
40
|
this->format = 0;
|
41
|
+
this->flags = 0;
|
41
42
|
rb_iv_set( self, "@name", Qnil );
|
42
43
|
}
|
43
44
|
|
@@ -56,6 +57,7 @@ pg_coder_init_decoder( VALUE self )
|
|
56
57
|
this->coder_obj = self;
|
57
58
|
this->oid = 0;
|
58
59
|
this->format = 0;
|
60
|
+
this->flags = 0;
|
59
61
|
rb_iv_set( self, "@name", Qnil );
|
60
62
|
}
|
61
63
|
|
@@ -105,7 +107,7 @@ pg_composite_decoder_allocate( VALUE klass )
|
|
105
107
|
|
106
108
|
/*
|
107
109
|
* call-seq:
|
108
|
-
* coder.encode( value )
|
110
|
+
* coder.encode( value [, encoding] )
|
109
111
|
*
|
110
112
|
* Encodes the given Ruby object into string representation, without
|
111
113
|
* sending data to/from the database server.
|
@@ -192,7 +194,11 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
192
194
|
if( NIL_P(argv[0]) )
|
193
195
|
return Qnil;
|
194
196
|
|
195
|
-
|
197
|
+
if( this->format == 0 ){
|
198
|
+
val = StringValueCStr(argv[0]);
|
199
|
+
}else{
|
200
|
+
val = StringValuePtr(argv[0]);
|
201
|
+
}
|
196
202
|
if( !this->dec_func ){
|
197
203
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
198
204
|
}
|
@@ -265,6 +271,36 @@ pg_coder_format_get(VALUE self)
|
|
265
271
|
return INT2NUM(this->format);
|
266
272
|
}
|
267
273
|
|
274
|
+
/*
|
275
|
+
* call-seq:
|
276
|
+
* coder.flags = Integer
|
277
|
+
*
|
278
|
+
* Set coder specific bitwise OR-ed flags.
|
279
|
+
* See the particular en- or decoder description for available flags.
|
280
|
+
*
|
281
|
+
* The default is +0+.
|
282
|
+
*/
|
283
|
+
static VALUE
|
284
|
+
pg_coder_flags_set(VALUE self, VALUE flags)
|
285
|
+
{
|
286
|
+
t_pg_coder *this = DATA_PTR(self);
|
287
|
+
this->flags = NUM2INT(flags);
|
288
|
+
return flags;
|
289
|
+
}
|
290
|
+
|
291
|
+
/*
|
292
|
+
* call-seq:
|
293
|
+
* coder.flags -> Integer
|
294
|
+
*
|
295
|
+
* Get current bitwise OR-ed coder flags.
|
296
|
+
*/
|
297
|
+
static VALUE
|
298
|
+
pg_coder_flags_get(VALUE self)
|
299
|
+
{
|
300
|
+
t_pg_coder *this = DATA_PTR(self);
|
301
|
+
return INT2NUM(this->flags);
|
302
|
+
}
|
303
|
+
|
268
304
|
/*
|
269
305
|
* call-seq:
|
270
306
|
* coder.needs_quotation = Boolean
|
@@ -403,14 +439,14 @@ pg_coder_enc_func(t_pg_coder *this)
|
|
403
439
|
}
|
404
440
|
|
405
441
|
static VALUE
|
406
|
-
pg_text_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
442
|
+
pg_text_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
407
443
|
{
|
408
444
|
VALUE string = pg_text_dec_string(this, val, len, tuple, field, enc_idx);
|
409
445
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
410
446
|
}
|
411
447
|
|
412
448
|
static VALUE
|
413
|
-
pg_bin_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
449
|
+
pg_bin_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
414
450
|
{
|
415
451
|
VALUE string = pg_bin_dec_bytea(this, val, len, tuple, field, enc_idx);
|
416
452
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
@@ -457,6 +493,19 @@ init_pg_coder()
|
|
457
493
|
rb_define_method( rb_cPG_Coder, "oid", pg_coder_oid_get, 0 );
|
458
494
|
rb_define_method( rb_cPG_Coder, "format=", pg_coder_format_set, 1 );
|
459
495
|
rb_define_method( rb_cPG_Coder, "format", pg_coder_format_get, 0 );
|
496
|
+
rb_define_method( rb_cPG_Coder, "flags=", pg_coder_flags_set, 1 );
|
497
|
+
rb_define_method( rb_cPG_Coder, "flags", pg_coder_flags_get, 0 );
|
498
|
+
|
499
|
+
/* define flags to be used with PG::Coder#flags= */
|
500
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_UTC", INT2NUM(PG_CODER_TIMESTAMP_DB_UTC));
|
501
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_DB_LOCAL));
|
502
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_UTC", INT2NUM(PG_CODER_TIMESTAMP_APP_UTC));
|
503
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_APP_LOCAL));
|
504
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_MASK", INT2NUM(PG_CODER_FORMAT_ERROR_MASK));
|
505
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_RAISE", INT2NUM(PG_CODER_FORMAT_ERROR_TO_RAISE));
|
506
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_STRING", INT2NUM(PG_CODER_FORMAT_ERROR_TO_STRING));
|
507
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_PARTIAL", INT2NUM(PG_CODER_FORMAT_ERROR_TO_PARTIAL));
|
508
|
+
|
460
509
|
/*
|
461
510
|
* Name of the coder or the corresponding data type.
|
462
511
|
*
|