pg 1.1.3 → 1.5.4
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/.appveyor.yml +42 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +117 -0
- data/.github/workflows/source-gem.yml +141 -0
- data/.gitignore +22 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.md +884 -0
- data/Manifest.txt +3 -3
- data/README-Windows.rdoc +4 -4
- data/README.ja.md +300 -0
- data/README.md +286 -0
- data/Rakefile +37 -137
- data/Rakefile.cross +62 -62
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +80 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +22 -2
- data/ext/extconf.rb +105 -26
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +204 -152
- data/ext/pg.h +52 -21
- data/ext/pg_binary_decoder.c +100 -17
- data/ext/pg_binary_encoder.c +238 -13
- data/ext/pg_coder.c +109 -34
- data/ext/pg_connection.c +1383 -983
- data/ext/pg_copy_coder.c +356 -35
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +522 -0
- data/ext/pg_result.c +439 -172
- data/ext/pg_text_decoder.c +42 -18
- data/ext/pg_text_encoder.c +201 -56
- data/ext/pg_tuple.c +97 -66
- data/ext/pg_type_map.c +45 -11
- data/ext/pg_type_map_all_strings.c +21 -7
- data/ext/pg_type_map_by_class.c +59 -27
- data/ext/pg_type_map_by_column.c +80 -37
- data/ext/pg_type_map_by_mri_type.c +49 -20
- data/ext/pg_type_map_by_oid.c +62 -29
- data/ext/pg_type_map_in_ruby.c +56 -22
- data/ext/{util.c → pg_util.c} +7 -7
- data/lib/pg/basic_type_map_based_on_result.rb +67 -0
- data/lib/pg/basic_type_map_for_queries.rb +198 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +299 -0
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +35 -12
- data/lib/pg/connection.rb +744 -84
- data/lib/pg/exceptions.rb +15 -1
- data/lib/pg/result.rb +13 -1
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/type_map_by_column.rb +2 -1
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +94 -39
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +34 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +102 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data/translation/.po4a-version +7 -0
- data/translation/po/all.pot +936 -0
- data/translation/po/ja.po +1036 -0
- data/translation/po4a.cfg +12 -0
- data.tar.gz.sig +0 -0
- metadata +144 -222
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +0 -485
- data/README.ja.rdoc +0 -14
- data/README.rdoc +0 -178
- data/lib/pg/basic_type_mapping.rb +0 -459
- data/lib/pg/binary_decoder.rb +0 -22
- data/lib/pg/constants.rb +0 -11
- data/lib/pg/text_decoder.rb +0 -47
- data/lib/pg/text_encoder.rb +0 -69
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -381
- data/spec/pg/basic_type_mapping_spec.rb +0 -508
- data/spec/pg/connection_spec.rb +0 -1849
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -491
- data/spec/pg/tuple_spec.rb +0 -280
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -222
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -949
- data/spec/pg_spec.rb +0 -50
- /data/ext/{util.h → pg_util.h} +0 -0
data/ext/pg.h
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include <sys/types.h>
|
|
12
12
|
#if !defined(_WIN32)
|
|
13
13
|
# include <sys/time.h>
|
|
14
|
+
# include <sys/socket.h>
|
|
14
15
|
#endif
|
|
15
16
|
#if defined(HAVE_UNISTD_H) && !defined(_WIN32)
|
|
16
17
|
# include <unistd.h>
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
#endif
|
|
57
58
|
|
|
58
59
|
/* PostgreSQL headers */
|
|
60
|
+
#include "pg_config.h"
|
|
59
61
|
#include "libpq-fe.h"
|
|
60
62
|
#include "libpq/libpq-fs.h" /* large-object interface */
|
|
61
63
|
#include "pg_config_manual.h"
|
|
@@ -74,9 +76,22 @@ typedef long suseconds_t;
|
|
|
74
76
|
#define PG_MAX_COLUMNS 4000
|
|
75
77
|
#endif
|
|
76
78
|
|
|
77
|
-
#
|
|
78
|
-
#define
|
|
79
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
|
80
|
+
#define pg_compact_callback(x) (x)
|
|
81
|
+
#define pg_gc_location(x) x = rb_gc_location(x)
|
|
82
|
+
#else
|
|
83
|
+
#define rb_gc_mark_movable(x) rb_gc_mark(x)
|
|
84
|
+
#define pg_compact_callback(x) {(x)}
|
|
85
|
+
#define pg_gc_location(x) UNUSED(x)
|
|
86
|
+
#endif
|
|
87
|
+
|
|
88
|
+
/* For compatibility with ruby < 3.0 */
|
|
89
|
+
#ifndef RUBY_TYPED_FROZEN_SHAREABLE
|
|
90
|
+
#define PG_RUBY_TYPED_FROZEN_SHAREABLE 0
|
|
91
|
+
#else
|
|
92
|
+
#define PG_RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE
|
|
79
93
|
#endif
|
|
94
|
+
#define PG_ENC_IDX_BITS 28
|
|
80
95
|
|
|
81
96
|
/* The data behind each PG::Connection object */
|
|
82
97
|
typedef struct {
|
|
@@ -84,6 +99,9 @@ typedef struct {
|
|
|
84
99
|
|
|
85
100
|
/* Cached IO object for the socket descriptor */
|
|
86
101
|
VALUE socket_io;
|
|
102
|
+
/* function pointers of the original libpq notice receivers */
|
|
103
|
+
PQnoticeReceiver default_notice_receiver;
|
|
104
|
+
PQnoticeProcessor default_notice_processor;
|
|
87
105
|
/* Proc object that receives notices as PG::Result objects */
|
|
88
106
|
VALUE notice_receiver;
|
|
89
107
|
/* Proc object that receives notices as String objects */
|
|
@@ -94,15 +112,21 @@ typedef struct {
|
|
|
94
112
|
VALUE type_map_for_results;
|
|
95
113
|
/* IO object internally used for the trace stream */
|
|
96
114
|
VALUE trace_stream;
|
|
97
|
-
/* Cached Encoding object */
|
|
98
|
-
VALUE external_encoding;
|
|
99
115
|
/* Kind of PG::Coder object for casting ruby values to COPY rows */
|
|
100
116
|
VALUE encoder_for_put_copy_data;
|
|
101
117
|
/* Kind of PG::Coder object for casting COPY rows to ruby values */
|
|
102
118
|
VALUE decoder_for_get_copy_data;
|
|
119
|
+
/* Ruby encoding index of the client/internal encoding */
|
|
120
|
+
int enc_idx : PG_ENC_IDX_BITS;
|
|
121
|
+
/* flags controlling Symbol/String field names */
|
|
122
|
+
unsigned int flags : 2;
|
|
123
|
+
/* enable automatic flushing of send data at the end of send_query calls */
|
|
124
|
+
unsigned int flush_data : 1;
|
|
103
125
|
|
|
104
|
-
|
|
105
|
-
|
|
126
|
+
#if defined(_WIN32)
|
|
127
|
+
/* File descriptor to be used for rb_w32_unwrap_io_handle() */
|
|
128
|
+
int ruby_sd;
|
|
129
|
+
#endif
|
|
106
130
|
} t_pg_connection;
|
|
107
131
|
|
|
108
132
|
typedef struct pg_coder t_pg_coder;
|
|
@@ -123,10 +147,16 @@ typedef struct {
|
|
|
123
147
|
*/
|
|
124
148
|
t_typemap *p_typemap;
|
|
125
149
|
|
|
150
|
+
/* Ruby encoding index of the client/internal encoding */
|
|
151
|
+
int enc_idx : PG_ENC_IDX_BITS;
|
|
152
|
+
|
|
126
153
|
/* 0 = PGresult is cleared by PG::Result#clear or by the GC
|
|
127
154
|
* 1 = PGresult is cleared internally by libpq
|
|
128
155
|
*/
|
|
129
|
-
int autoclear;
|
|
156
|
+
unsigned int autoclear : 1;
|
|
157
|
+
|
|
158
|
+
/* flags controlling Symbol/String field names */
|
|
159
|
+
unsigned int flags : 2;
|
|
130
160
|
|
|
131
161
|
/* Number of fields in fnames[] .
|
|
132
162
|
* Set to -1 if fnames[] is not yet initialized.
|
|
@@ -142,7 +172,7 @@ typedef struct {
|
|
|
142
172
|
/* Hash with fnames[] to field number mapping. */
|
|
143
173
|
VALUE field_map;
|
|
144
174
|
|
|
145
|
-
/* List of field names as frozen String objects.
|
|
175
|
+
/* List of field names as frozen String or Symbol objects.
|
|
146
176
|
* Only valid if nfields != -1
|
|
147
177
|
*/
|
|
148
178
|
VALUE fnames[0];
|
|
@@ -158,6 +188,10 @@ typedef VALUE (* t_pg_typecast_result)(t_typemap *, VALUE, int, int);
|
|
|
158
188
|
typedef t_pg_coder *(* t_pg_typecast_query_param)(t_typemap *, VALUE, int);
|
|
159
189
|
typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
|
|
160
190
|
|
|
191
|
+
#define PG_RESULT_FIELD_NAMES_MASK 0x03
|
|
192
|
+
#define PG_RESULT_FIELD_NAMES_SYMBOL 0x01
|
|
193
|
+
#define PG_RESULT_FIELD_NAMES_STATIC_SYMBOL 0x02
|
|
194
|
+
|
|
161
195
|
#define PG_CODER_TIMESTAMP_DB_UTC 0x0
|
|
162
196
|
#define PG_CODER_TIMESTAMP_DB_LOCAL 0x1
|
|
163
197
|
#define PG_CODER_TIMESTAMP_APP_UTC 0x0
|
|
@@ -204,6 +238,8 @@ typedef struct {
|
|
|
204
238
|
} convs[0];
|
|
205
239
|
} t_tmbc;
|
|
206
240
|
|
|
241
|
+
extern const rb_data_type_t pg_typemap_type;
|
|
242
|
+
extern const rb_data_type_t pg_coder_type;
|
|
207
243
|
|
|
208
244
|
#include "gvl_wrappers.h"
|
|
209
245
|
|
|
@@ -270,6 +306,7 @@ void init_pg_type_map_by_oid _(( void ));
|
|
|
270
306
|
void init_pg_type_map_in_ruby _(( void ));
|
|
271
307
|
void init_pg_coder _(( void ));
|
|
272
308
|
void init_pg_copycoder _(( void ));
|
|
309
|
+
void init_pg_recordcoder _(( void ));
|
|
273
310
|
void init_pg_text_encoder _(( void ));
|
|
274
311
|
void init_pg_text_decoder _(( void ));
|
|
275
312
|
void init_pg_binary_encoder _(( void ));
|
|
@@ -282,11 +319,12 @@ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, c
|
|
|
282
319
|
int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
|
|
283
320
|
t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
|
|
284
321
|
t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
|
|
285
|
-
|
|
322
|
+
VALUE pg_define_coder _(( const char *, void *, VALUE, VALUE ));
|
|
286
323
|
VALUE pg_obj_to_i _(( VALUE ));
|
|
287
324
|
VALUE pg_tmbc_allocate _(( void ));
|
|
288
325
|
void pg_coder_init_encoder _(( VALUE ));
|
|
289
326
|
void pg_coder_init_decoder _(( VALUE ));
|
|
327
|
+
void pg_coder_compact _(( void * ));
|
|
290
328
|
char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
|
|
291
329
|
|
|
292
330
|
#define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
|
|
@@ -300,20 +338,19 @@ char *pg_rb_str_ensure_capa _(( VALUE, long, char *,
|
|
|
300
338
|
(curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
|
|
301
339
|
)
|
|
302
340
|
|
|
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
341
|
VALUE pg_typemap_fit_to_result _(( VALUE, VALUE ));
|
|
309
342
|
VALUE pg_typemap_fit_to_query _(( VALUE, VALUE ));
|
|
310
343
|
int pg_typemap_fit_to_copy_get _(( VALUE ));
|
|
311
344
|
VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
|
|
312
345
|
t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
|
|
313
346
|
VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
|
|
347
|
+
void pg_typemap_mark _(( void * ));
|
|
348
|
+
size_t pg_typemap_memsize _(( const void * ));
|
|
349
|
+
void pg_typemap_compact _(( void * ));
|
|
314
350
|
|
|
315
351
|
PGconn *pg_get_pgconn _(( VALUE ));
|
|
316
352
|
t_pg_connection *pg_get_connection _(( VALUE ));
|
|
353
|
+
VALUE pgconn_block _(( int, VALUE *, VALUE ));
|
|
317
354
|
|
|
318
355
|
VALUE pg_new_result _(( PGresult *, VALUE ));
|
|
319
356
|
VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
|
|
@@ -328,16 +365,10 @@ VALUE pg_tuple_new _(( VALUE, int ));
|
|
|
328
365
|
static inline t_pg_result *
|
|
329
366
|
pgresult_get_this( VALUE self )
|
|
330
367
|
{
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
if( this == NULL )
|
|
334
|
-
rb_raise(rb_ePGerror, "result has been cleared");
|
|
335
|
-
|
|
336
|
-
return this;
|
|
368
|
+
return RTYPEDDATA_DATA(self);
|
|
337
369
|
}
|
|
338
370
|
|
|
339
371
|
|
|
340
|
-
rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
|
|
341
372
|
rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
|
|
342
373
|
const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
|
|
343
374
|
rb_encoding *pg_conn_enc_get _(( PGconn * ));
|
data/ext/pg_binary_decoder.c
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
|
3
|
-
* $Id
|
|
3
|
+
* $Id$
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
#include "ruby/version.h"
|
|
8
8
|
#include "pg.h"
|
|
9
|
-
#include "
|
|
9
|
+
#include "pg_util.h"
|
|
10
10
|
#ifdef HAVE_INTTYPES_H
|
|
11
11
|
#include <inttypes.h>
|
|
12
12
|
#endif
|
|
13
13
|
|
|
14
14
|
VALUE rb_mPG_BinaryDecoder;
|
|
15
|
+
static VALUE s_Date;
|
|
16
|
+
static ID s_id_new;
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
/*
|
|
18
20
|
* Document-class: PG::BinaryDecoder::Boolean < PG::SimpleDecoder
|
|
19
21
|
*
|
|
20
|
-
* This is a decoder class for conversion of PostgreSQL binary bool type
|
|
21
|
-
* to Ruby true or false objects.
|
|
22
|
+
* This is a decoder class for conversion of PostgreSQL binary +bool+ type
|
|
23
|
+
* to Ruby +true+ or +false+ objects.
|
|
22
24
|
*
|
|
23
25
|
*/
|
|
24
26
|
static VALUE
|
|
@@ -33,7 +35,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int fi
|
|
|
33
35
|
/*
|
|
34
36
|
* Document-class: PG::BinaryDecoder::Integer < PG::SimpleDecoder
|
|
35
37
|
*
|
|
36
|
-
* This is a decoder class for conversion of PostgreSQL binary int2
|
|
38
|
+
* This is a decoder class for conversion of PostgreSQL binary +int2+, +int4+ and +int8+ types
|
|
37
39
|
* to Ruby Integer objects.
|
|
38
40
|
*
|
|
39
41
|
*/
|
|
@@ -55,7 +57,7 @@ pg_bin_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int fi
|
|
|
55
57
|
/*
|
|
56
58
|
* Document-class: PG::BinaryDecoder::Float < PG::SimpleDecoder
|
|
57
59
|
*
|
|
58
|
-
* This is a decoder class for conversion of PostgreSQL binary float4 and float8 types
|
|
60
|
+
* This is a decoder class for conversion of PostgreSQL binary +float4+ and +float8+ types
|
|
59
61
|
* to Ruby Float objects.
|
|
60
62
|
*
|
|
61
63
|
*/
|
|
@@ -87,7 +89,7 @@ pg_bin_dec_float(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
|
|
|
87
89
|
* Document-class: PG::BinaryDecoder::Bytea < PG::SimpleDecoder
|
|
88
90
|
*
|
|
89
91
|
* This decoder class delivers the data received from the server as binary String object.
|
|
90
|
-
* It is therefore suitable for conversion of PostgreSQL bytea data as well as any other
|
|
92
|
+
* It is therefore suitable for conversion of PostgreSQL +bytea+ data as well as any other
|
|
91
93
|
* data in binary format.
|
|
92
94
|
*
|
|
93
95
|
*/
|
|
@@ -95,7 +97,7 @@ VALUE
|
|
|
95
97
|
pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
|
96
98
|
{
|
|
97
99
|
VALUE ret;
|
|
98
|
-
ret =
|
|
100
|
+
ret = rb_str_new( val, len );
|
|
99
101
|
PG_ENCODING_SET_NOCHECK( ret, rb_ascii8bit_encindex() );
|
|
100
102
|
return ret;
|
|
101
103
|
}
|
|
@@ -103,7 +105,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
|
|
|
103
105
|
/*
|
|
104
106
|
* Document-class: PG::BinaryDecoder::ToBase64 < PG::CompositeDecoder
|
|
105
107
|
*
|
|
106
|
-
* This is a decoder class for conversion of binary
|
|
108
|
+
* This is a decoder class for conversion of binary +bytea+ to base64 data.
|
|
107
109
|
*
|
|
108
110
|
*/
|
|
109
111
|
static VALUE
|
|
@@ -113,7 +115,7 @@ pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int
|
|
|
113
115
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
|
|
114
116
|
int encoded_len = BASE64_ENCODED_SIZE(len);
|
|
115
117
|
/* create a buffer of the encoded length */
|
|
116
|
-
VALUE out_value =
|
|
118
|
+
VALUE out_value = rb_str_new(NULL, encoded_len);
|
|
117
119
|
|
|
118
120
|
base64_encode( RSTRING_PTR(out_value), val, len );
|
|
119
121
|
|
|
@@ -154,7 +156,8 @@ static VALUE
|
|
|
154
156
|
pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
|
155
157
|
{
|
|
156
158
|
int64_t timestamp;
|
|
157
|
-
|
|
159
|
+
int64_t sec;
|
|
160
|
+
int64_t nsec;
|
|
158
161
|
VALUE t;
|
|
159
162
|
|
|
160
163
|
if( len != sizeof(timestamp) ){
|
|
@@ -171,14 +174,17 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
|
|
|
171
174
|
default:
|
|
172
175
|
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
|
173
176
|
* Adjust the 30 years difference. */
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
|
|
178
|
+
nsec = (timestamp % 1000000) * 1000;
|
|
176
179
|
|
|
177
|
-
#if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T)
|
|
180
|
+
#if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T) && defined(SIZEOF_TIME_T) && SIZEOF_TIME_T >= 8
|
|
178
181
|
/* Fast path for time conversion */
|
|
179
|
-
|
|
182
|
+
{
|
|
183
|
+
struct timespec ts = {sec, nsec};
|
|
184
|
+
t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
|
|
185
|
+
}
|
|
180
186
|
#else
|
|
181
|
-
t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(
|
|
187
|
+
t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(sec), LL2NUM(nsec / 1000));
|
|
182
188
|
if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
|
|
183
189
|
t = rb_funcall(t, rb_intern("utc"), 0);
|
|
184
190
|
}
|
|
@@ -191,6 +197,82 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
|
|
|
191
197
|
}
|
|
192
198
|
}
|
|
193
199
|
|
|
200
|
+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
|
|
201
|
+
#define PG_INT32_MAX (0x7FFFFFFF)
|
|
202
|
+
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
|
|
203
|
+
#define MONTHS_PER_YEAR 12
|
|
204
|
+
|
|
205
|
+
/* taken from PostgreSQL sources at src/backend/utils/adt/datetime.c */
|
|
206
|
+
void
|
|
207
|
+
j2date(int jd, int *year, int *month, int *day)
|
|
208
|
+
{
|
|
209
|
+
unsigned int julian;
|
|
210
|
+
unsigned int quad;
|
|
211
|
+
unsigned int extra;
|
|
212
|
+
int y;
|
|
213
|
+
|
|
214
|
+
julian = jd;
|
|
215
|
+
julian += 32044;
|
|
216
|
+
quad = julian / 146097;
|
|
217
|
+
extra = (julian - quad * 146097) * 4 + 3;
|
|
218
|
+
julian += 60 + quad * 3 + extra / 146097;
|
|
219
|
+
quad = julian / 1461;
|
|
220
|
+
julian -= quad * 1461;
|
|
221
|
+
y = julian * 4 / 1461;
|
|
222
|
+
julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
|
|
223
|
+
+ 123;
|
|
224
|
+
y += quad * 4;
|
|
225
|
+
*year = y - 4800;
|
|
226
|
+
quad = julian * 2141 / 65536;
|
|
227
|
+
*day = julian - 7834 * quad / 256;
|
|
228
|
+
*month = (quad + 10) % MONTHS_PER_YEAR + 1;
|
|
229
|
+
} /* j2date() */
|
|
230
|
+
|
|
231
|
+
/*
|
|
232
|
+
* Document-class: PG::BinaryDecoder::Date < PG::SimpleDecoder
|
|
233
|
+
*
|
|
234
|
+
* This is a decoder class for conversion of PostgreSQL binary date
|
|
235
|
+
* to Ruby Date objects.
|
|
236
|
+
*/
|
|
237
|
+
static VALUE
|
|
238
|
+
pg_bin_dec_date(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
|
239
|
+
{
|
|
240
|
+
int year, month, day;
|
|
241
|
+
int date;
|
|
242
|
+
|
|
243
|
+
if (len != 4) {
|
|
244
|
+
rb_raise(rb_eTypeError, "unexpected date format != 4 bytes");
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
date = read_nbo32(val);
|
|
248
|
+
switch(date){
|
|
249
|
+
case PG_INT32_MAX:
|
|
250
|
+
return rb_str_new2("infinity");
|
|
251
|
+
case PG_INT32_MIN:
|
|
252
|
+
return rb_str_new2("-infinity");
|
|
253
|
+
default:
|
|
254
|
+
j2date(date + POSTGRES_EPOCH_JDATE, &year, &month, &day);
|
|
255
|
+
|
|
256
|
+
return rb_funcall(s_Date, s_id_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* called per autoload when BinaryDecoder::Date is used */
|
|
261
|
+
static VALUE
|
|
262
|
+
init_pg_bin_decoder_date(VALUE rb_mPG_BinaryDecoder)
|
|
263
|
+
{
|
|
264
|
+
rb_require("date");
|
|
265
|
+
s_Date = rb_const_get(rb_cObject, rb_intern("Date"));
|
|
266
|
+
rb_gc_register_mark_object(s_Date);
|
|
267
|
+
s_id_new = rb_intern("new");
|
|
268
|
+
|
|
269
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Date", rb_cPG_SimpleDecoder ); */
|
|
270
|
+
pg_define_coder( "Date", pg_bin_dec_date, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
|
271
|
+
|
|
272
|
+
return Qnil;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
194
276
|
/*
|
|
195
277
|
* Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
|
|
196
278
|
*
|
|
@@ -201,10 +283,11 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
|
|
|
201
283
|
*/
|
|
202
284
|
|
|
203
285
|
void
|
|
204
|
-
init_pg_binary_decoder()
|
|
286
|
+
init_pg_binary_decoder(void)
|
|
205
287
|
{
|
|
206
288
|
/* This module encapsulates all decoder classes with binary input format */
|
|
207
289
|
rb_mPG_BinaryDecoder = rb_define_module_under( rb_mPG, "BinaryDecoder" );
|
|
290
|
+
rb_define_private_method(rb_singleton_class(rb_mPG_BinaryDecoder), "init_date", init_pg_bin_decoder_date, 0);
|
|
208
291
|
|
|
209
292
|
/* Make RDoc aware of the decoder classes... */
|
|
210
293
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Boolean", rb_cPG_SimpleDecoder ); */
|