pg 0.18.0 → 1.1.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.
Files changed (80) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/BSDL +2 -2
  4. data/ChangeLog +1221 -4
  5. data/History.rdoc +200 -0
  6. data/Manifest.txt +5 -18
  7. data/README-Windows.rdoc +15 -26
  8. data/README.rdoc +27 -10
  9. data/Rakefile +33 -24
  10. data/Rakefile.cross +57 -39
  11. data/ext/errorcodes.def +37 -0
  12. data/ext/errorcodes.rb +1 -1
  13. data/ext/errorcodes.txt +16 -1
  14. data/ext/extconf.rb +29 -35
  15. data/ext/gvl_wrappers.c +4 -0
  16. data/ext/gvl_wrappers.h +27 -39
  17. data/ext/pg.c +27 -53
  18. data/ext/pg.h +66 -83
  19. data/ext/pg_binary_decoder.c +75 -6
  20. data/ext/pg_binary_encoder.c +14 -12
  21. data/ext/pg_coder.c +83 -13
  22. data/ext/pg_connection.c +627 -351
  23. data/ext/pg_copy_coder.c +44 -9
  24. data/ext/pg_result.c +364 -134
  25. data/ext/pg_text_decoder.c +605 -46
  26. data/ext/pg_text_encoder.c +95 -76
  27. data/ext/pg_tuple.c +541 -0
  28. data/ext/pg_type_map.c +20 -13
  29. data/ext/pg_type_map_by_column.c +7 -7
  30. data/ext/pg_type_map_by_mri_type.c +2 -2
  31. data/ext/pg_type_map_in_ruby.c +4 -7
  32. data/ext/util.c +7 -7
  33. data/ext/util.h +3 -3
  34. data/lib/pg/basic_type_mapping.rb +105 -45
  35. data/lib/pg/binary_decoder.rb +22 -0
  36. data/lib/pg/coder.rb +1 -1
  37. data/lib/pg/connection.rb +109 -39
  38. data/lib/pg/constants.rb +1 -1
  39. data/lib/pg/exceptions.rb +1 -1
  40. data/lib/pg/result.rb +11 -6
  41. data/lib/pg/text_decoder.rb +25 -20
  42. data/lib/pg/text_encoder.rb +43 -1
  43. data/lib/pg/tuple.rb +30 -0
  44. data/lib/pg/type_map_by_column.rb +1 -1
  45. data/lib/pg.rb +21 -11
  46. data/spec/helpers.rb +50 -25
  47. data/spec/pg/basic_type_mapping_spec.rb +287 -30
  48. data/spec/pg/connection_spec.rb +695 -282
  49. data/spec/pg/connection_sync_spec.rb +41 -0
  50. data/spec/pg/result_spec.rb +59 -17
  51. data/spec/pg/tuple_spec.rb +280 -0
  52. data/spec/pg/type_map_by_class_spec.rb +3 -3
  53. data/spec/pg/type_map_by_column_spec.rb +1 -1
  54. data/spec/pg/type_map_by_mri_type_spec.rb +2 -2
  55. data/spec/pg/type_map_by_oid_spec.rb +1 -1
  56. data/spec/pg/type_map_in_ruby_spec.rb +1 -1
  57. data/spec/pg/type_map_spec.rb +1 -1
  58. data/spec/pg/type_spec.rb +319 -35
  59. data/spec/pg_spec.rb +2 -2
  60. data.tar.gz.sig +0 -0
  61. metadata +68 -68
  62. metadata.gz.sig +0 -0
  63. data/sample/array_insert.rb +0 -20
  64. data/sample/async_api.rb +0 -106
  65. data/sample/async_copyto.rb +0 -39
  66. data/sample/async_mixed.rb +0 -56
  67. data/sample/check_conn.rb +0 -21
  68. data/sample/copyfrom.rb +0 -81
  69. data/sample/copyto.rb +0 -19
  70. data/sample/cursor.rb +0 -21
  71. data/sample/disk_usage_report.rb +0 -186
  72. data/sample/issue-119.rb +0 -94
  73. data/sample/losample.rb +0 -69
  74. data/sample/minimal-testcase.rb +0 -17
  75. data/sample/notify_wait.rb +0 -72
  76. data/sample/pg_statistics.rb +0 -294
  77. data/sample/replication_monitor.rb +0 -231
  78. data/sample/test_binary_values.rb +0 -33
  79. data/sample/wal_shipper.rb +0 -434
  80. data/sample/warehouse_partitions.rb +0 -320
data/ext/pg.c CHANGED
@@ -1,12 +1,13 @@
1
1
  /*
2
2
  * pg.c - Toplevel extension
3
- * $Id: pg.c,v a9724aef9116 2014/12/12 21:03:27 lars $
3
+ * $Id: pg.c,v 2d334508484a 2018/08/27 11:33:43 lars $
4
4
  *
5
5
  * Author/s:
6
6
  *
7
7
  * - Jeff Davis <ruby-pg@j-davis.com>
8
8
  * - Guy Decoux (ts) <decoux@moulon.inra.fr>
9
9
  * - Michael Granger <ged@FaerieMUD.org>
10
+ * - Lars Kanis <lars@greiz-reinsdorf.de>
10
11
  * - Dave Lee
11
12
  * - Eiji Matsumoto <usagi@ruby.club.or.jp>
12
13
  * - Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -15,10 +16,10 @@
15
16
  * See Contributors.rdoc for the many additional fine people that have contributed
16
17
  * to this library over the years.
17
18
  *
18
- * Copyright (c) 1997-2012 by the authors.
19
+ * Copyright (c) 1997-2016 by the authors.
19
20
  *
20
21
  * You may redistribute this software under the same terms as Ruby itself; see
21
- * http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
22
+ * https://www.ruby-lang.org/en/about/license.txt or the BSDL file in the source
22
23
  * for details.
23
24
  *
24
25
  * Portions of the code are from the PostgreSQL project, and are distributed
@@ -47,6 +48,7 @@
47
48
 
48
49
  #include "pg.h"
49
50
 
51
+ int pg_skip_deprecation_warning;
50
52
  VALUE rb_mPG;
51
53
  VALUE rb_mPGconstants;
52
54
 
@@ -68,7 +70,6 @@ VALUE rb_mPGconstants;
68
70
  * M17n functions
69
71
  */
70
72
 
71
- #ifdef M17N_SUPPORTED
72
73
  /**
73
74
  * The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
74
75
  */
@@ -142,9 +143,6 @@ pg_find_or_create_johab(void)
142
143
  }
143
144
 
144
145
  enc_index = rb_define_dummy_encoding(aliases[0]);
145
- for (i = 1; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
146
- ENC_ALIAS(aliases[i], aliases[0]);
147
- }
148
146
  return rb_enc_from_index(enc_index);
149
147
  }
150
148
 
@@ -228,8 +226,6 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
228
226
  return encname;
229
227
  }
230
228
 
231
- #endif /* M17N_SUPPORTED */
232
-
233
229
 
234
230
  /*
235
231
  * Ensures that the given string has enough capacity to take expand_len
@@ -252,52 +248,33 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
252
248
  * char *current_out, *end_capa;
253
249
  * PG_RB_STR_NEW( string, current_out, end_capa );
254
250
  * while( data_is_going_to_be_processed ){
255
- * PG_RB_STR_ENSURE_CAPA( string, 2 current_out, end_capa );
251
+ * PG_RB_STR_ENSURE_CAPA( string, 2, current_out, end_capa );
256
252
  * *current_out++ = databyte1;
257
253
  * *current_out++ = databyte2;
258
254
  * }
259
255
  * rb_str_set_len( string, current_out - RSTRING_PTR(string) );
260
256
  *
261
257
  */
262
- #ifdef HAVE_RB_STR_MODIFY_EXPAND
263
- /* Use somewhat faster version with access to string capacity on MRI */
264
- char *
265
- pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
266
- {
267
- long curr_len = curr_ptr - RSTRING_PTR(str);
268
- long curr_capa = rb_str_capacity( str );
269
- if( curr_capa < curr_len + expand_len ){
270
- rb_str_set_len( str, curr_len );
271
- rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa );
272
- curr_ptr = RSTRING_PTR(str) + curr_len;
273
- }
274
- if( end_ptr )
275
- *end_ptr = RSTRING_PTR(str) + rb_str_capacity( str );
276
- return curr_ptr;
277
- }
278
- #else
279
- /* Use the more portable version */
280
- char *
281
- pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
282
- {
283
- long curr_len = curr_ptr - RSTRING_PTR(str);
284
- long curr_capa = RSTRING_LEN( str );
285
- if( curr_capa < curr_len + expand_len ){
286
- rb_str_resize( str, (curr_len + expand_len) * 2 - curr_capa );
287
- curr_ptr = RSTRING_PTR(str) + curr_len;
288
- }
289
- if( end_ptr )
290
- *end_ptr = RSTRING_PTR(str) + RSTRING_LEN(str);
291
- return curr_ptr;
258
+ char *
259
+ pg_rb_str_ensure_capa( VALUE str, long expand_len, char *curr_ptr, char **end_ptr )
260
+ {
261
+ long curr_len = curr_ptr - RSTRING_PTR(str);
262
+ long curr_capa = rb_str_capacity( str );
263
+ if( curr_capa < curr_len + expand_len ){
264
+ rb_str_set_len( str, curr_len );
265
+ rb_str_modify_expand( str, (curr_len + expand_len) * 2 - curr_capa );
266
+ curr_ptr = RSTRING_PTR(str) + curr_len;
292
267
  }
293
- #endif
268
+ if( end_ptr )
269
+ *end_ptr = RSTRING_PTR(str) + rb_str_capacity( str );
270
+ return curr_ptr;
271
+ }
294
272
 
295
273
 
296
274
  /**************************************************************************
297
275
  * Module Methods
298
276
  **************************************************************************/
299
277
 
300
- #ifdef HAVE_PQLIBVERSION
301
278
  /*
302
279
  * call-seq:
303
280
  * PG.library_version -> Integer
@@ -315,7 +292,6 @@ pg_s_library_version(VALUE self)
315
292
  UNUSED( self );
316
293
  return INT2NUM(PQlibVersion());
317
294
  }
318
- #endif
319
295
 
320
296
 
321
297
  /*
@@ -403,15 +379,20 @@ pg_s_init_ssl(VALUE self, VALUE do_ssl)
403
379
  void
404
380
  Init_pg_ext()
405
381
  {
382
+ if( RTEST(rb_eval_string("ENV['PG_SKIP_DEPRECATION_WARNING']")) ){
383
+ /* Set all bits to disable all deprecation warnings. */
384
+ pg_skip_deprecation_warning = 0xFFFF;
385
+ } else {
386
+ pg_skip_deprecation_warning = 0;
387
+ }
388
+
406
389
  rb_mPG = rb_define_module( "PG" );
407
390
  rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" );
408
391
 
409
392
  /*************************
410
393
  * PG module methods
411
394
  *************************/
412
- #ifdef HAVE_PQLIBVERSION
413
395
  rb_define_singleton_method( rb_mPG, "library_version", pg_s_library_version, 0 );
414
- #endif
415
396
  rb_define_singleton_method( rb_mPG, "isthreadsafe", pg_s_threadsafe_p, 0 );
416
397
  SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
417
398
  SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
@@ -477,7 +458,6 @@ Init_pg_ext()
477
458
  /* Verbose error verbosity level (#set_error_verbosity) */
478
459
  rb_define_const(rb_mPGconstants, "PQERRORS_VERBOSE", INT2FIX(PQERRORS_VERBOSE));
479
460
 
480
- #ifdef HAVE_PQPING
481
461
  /****** PG::Connection CLASS CONSTANTS: Check Server Status ******/
482
462
 
483
463
  /* Server is accepting connections. */
@@ -488,7 +468,6 @@ Init_pg_ext()
488
468
  rb_define_const(rb_mPGconstants, "PQPING_NO_RESPONSE", INT2FIX(PQPING_NO_RESPONSE));
489
469
  /* Connection not attempted (bad params). */
490
470
  rb_define_const(rb_mPGconstants, "PQPING_NO_ATTEMPT", INT2FIX(PQPING_NO_ATTEMPT));
491
- #endif
492
471
 
493
472
  /****** PG::Connection CLASS CONSTANTS: Large Objects ******/
494
473
 
@@ -523,13 +502,9 @@ Init_pg_ext()
523
502
  /* #result_status constant: A fatal error occurred. */
524
503
  rb_define_const(rb_mPGconstants, "PGRES_FATAL_ERROR", INT2FIX(PGRES_FATAL_ERROR));
525
504
  /* #result_status constant: Copy In/Out data transfer in progress. */
526
- #ifdef HAVE_CONST_PGRES_COPY_BOTH
527
505
  rb_define_const(rb_mPGconstants, "PGRES_COPY_BOTH", INT2FIX(PGRES_COPY_BOTH));
528
- #endif
529
506
  /* #result_status constant: Single tuple from larger resultset. */
530
- #ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
531
507
  rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
532
- #endif
533
508
 
534
509
  /****** Result CONSTANTS: result error field codes ******/
535
510
 
@@ -641,9 +616,7 @@ Init_pg_ext()
641
616
  /* Add the constants to the toplevel namespace */
642
617
  rb_include_module( rb_mPG, rb_mPGconstants );
643
618
 
644
- #ifdef M17N_SUPPORTED
645
619
  enc_pg2ruby = st_init_numtable();
646
- #endif
647
620
 
648
621
  /* Initialize the main extension classes */
649
622
  init_pg_connection();
@@ -662,5 +635,6 @@ Init_pg_ext()
662
635
  init_pg_binary_encoder();
663
636
  init_pg_binary_decoder();
664
637
  init_pg_copycoder();
638
+ init_pg_tuple();
665
639
  }
666
640
 
data/ext/pg.h CHANGED
@@ -9,95 +9,27 @@
9
9
  #include <stdio.h>
10
10
  #include <stdlib.h>
11
11
  #include <sys/types.h>
12
+ #if !defined(_WIN32)
13
+ # include <sys/time.h>
14
+ #endif
12
15
  #if defined(HAVE_UNISTD_H) && !defined(_WIN32)
13
16
  # include <unistd.h>
14
17
  #endif /* HAVE_UNISTD_H */
15
18
 
16
19
  /* Ruby headers */
17
20
  #include "ruby.h"
18
- #ifdef HAVE_RUBY_ST_H
19
- # include "ruby/st.h"
20
- #elif HAVE_ST_H
21
- # include "st.h"
22
- #endif
21
+ #include "ruby/st.h"
22
+ #include "ruby/encoding.h"
23
23
 
24
- #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
25
- # include "ruby/encoding.h"
26
- # define M17N_SUPPORTED
27
- # ifdef HAVE_RB_ENCDB_ALIAS
28
- extern int rb_encdb_alias(const char *, const char *);
29
- # define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
30
- # elif HAVE_RB_ENC_ALIAS
31
- extern int rb_enc_alias(const char *, const char *);
32
- # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
33
- # else
34
- extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
35
- # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
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) \
24
+ #define PG_ENCODING_SET_NOCHECK(obj,i) \
49
25
  do { \
50
26
  if ((i) < ENCODING_INLINE_MAX) \
51
27
  ENCODING_SET_INLINED((obj), (i)); \
52
28
  else \
53
29
  rb_enc_set_index((obj), (i)); \
54
30
  } while(0)
55
- # endif
56
-
57
- #else
58
- # define PG_ENCODING_SET_NOCHECK(obj,i) /* nothing */
59
- #endif
60
-
61
- #if RUBY_VM != 1
62
- # define RUBY_18_COMPAT
63
- #endif
64
31
 
65
- #ifndef RARRAY_LEN
66
- # define RARRAY_LEN(x) RARRAY((x))->len
67
- #endif /* RARRAY_LEN */
68
-
69
- #ifndef RSTRING_LEN
70
- # define RSTRING_LEN(x) RSTRING((x))->len
71
- #endif /* RSTRING_LEN */
72
-
73
- #ifndef RSTRING_PTR
74
- # define RSTRING_PTR(x) RSTRING((x))->ptr
75
- #endif /* RSTRING_PTR */
76
-
77
- #ifndef StringValuePtr
78
- # define StringValuePtr(x) STR2CSTR(x)
79
- #endif /* StringValuePtr */
80
-
81
- #ifdef RUBY_18_COMPAT
82
- # define rb_io_stdio_file GetWriteFile
83
- # include "rubyio.h"
84
- #else
85
- # include "ruby/io.h"
86
- #endif
87
-
88
- #ifdef RUBINIUS
89
- /* Workaround for wrong FIXNUM_MAX definition */
90
- typedef intptr_t native_int;
91
- #endif
92
-
93
- #ifndef RETURN_SIZED_ENUMERATOR
94
- #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) RETURN_ENUMERATOR((obj), (argc), (argv))
95
- #endif
96
-
97
- #ifndef HAVE_RB_HASH_DUP
98
- /* Rubinius doesn't define rb_hash_dup() */
99
- #define rb_hash_dup(tuple) rb_funcall((tuple), rb_intern("dup"), 0)
100
- #endif
32
+ #include "ruby/io.h"
101
33
 
102
34
  #ifndef timeradd
103
35
  #define timeradd(a, b, result) \
@@ -133,6 +65,19 @@
133
65
  typedef long suseconds_t;
134
66
  #endif
135
67
 
68
+ #if defined(HAVE_VARIABLE_LENGTH_ARRAYS)
69
+ #define PG_VARIABLE_LENGTH_ARRAY(type, name, len, maxlen) type name[(len)];
70
+ #else
71
+ #define PG_VARIABLE_LENGTH_ARRAY(type, name, len, maxlen) \
72
+ type name[(maxlen)] = {(len)>(maxlen) ? (rb_raise(rb_eArgError, "Number of " #name " (%d) exceeds allowed maximum of " #maxlen, (len) ), (type)1) : (type)0};
73
+
74
+ #define PG_MAX_COLUMNS 4000
75
+ #endif
76
+
77
+ #ifndef RARRAY_AREF
78
+ #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
79
+ #endif
80
+
136
81
  /* The data behind each PG::Connection object */
137
82
  typedef struct {
138
83
  PGconn *pgconn;
@@ -156,6 +101,13 @@ typedef struct {
156
101
  /* Kind of PG::Coder object for casting COPY rows to ruby values */
157
102
  VALUE decoder_for_get_copy_data;
158
103
 
104
+ /* enable/disable guessing size of PGresult's allocated memory */
105
+ int guess_result_memsize;
106
+
107
+ #if defined(_WIN32)
108
+ /* File descriptor to be used for rb_w32_unwrap_io_handle() */
109
+ int ruby_sd;
110
+ #endif
159
111
  } t_pg_connection;
160
112
 
161
113
  typedef struct pg_coder t_pg_coder;
@@ -186,9 +138,15 @@ typedef struct {
186
138
  */
187
139
  int nfields;
188
140
 
141
+ /* Size of PGresult as published to ruby memory management. */
142
+ ssize_t result_size;
143
+
189
144
  /* Prefilled tuple Hash with fnames[] as keys. */
190
145
  VALUE tuple_hash;
191
146
 
147
+ /* Hash with fnames[] to field number mapping. */
148
+ VALUE field_map;
149
+
192
150
  /* List of field names as frozen String objects.
193
151
  * Only valid if nfields != -1
194
152
  */
@@ -196,8 +154,8 @@ typedef struct {
196
154
  } t_pg_result;
197
155
 
198
156
 
199
- typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
200
- typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
157
+ typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *, int);
158
+ typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, const char *, int, int, int, int);
201
159
  typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
202
160
  typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
203
161
  typedef int (* t_pg_fit_to_copy_get)(VALUE);
@@ -205,12 +163,23 @@ typedef VALUE (* t_pg_typecast_result)(t_typemap *, VALUE, int, int);
205
163
  typedef t_pg_coder *(* t_pg_typecast_query_param)(t_typemap *, VALUE, int);
206
164
  typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
207
165
 
166
+ #define PG_CODER_TIMESTAMP_DB_UTC 0x0
167
+ #define PG_CODER_TIMESTAMP_DB_LOCAL 0x1
168
+ #define PG_CODER_TIMESTAMP_APP_UTC 0x0
169
+ #define PG_CODER_TIMESTAMP_APP_LOCAL 0x2
170
+ #define PG_CODER_FORMAT_ERROR_MASK 0xc
171
+ #define PG_CODER_FORMAT_ERROR_TO_RAISE 0x4
172
+ #define PG_CODER_FORMAT_ERROR_TO_STRING 0x8
173
+ #define PG_CODER_FORMAT_ERROR_TO_PARTIAL 0xc
174
+
208
175
  struct pg_coder {
209
176
  t_pg_coder_enc_func enc_func;
210
177
  t_pg_coder_dec_func dec_func;
211
178
  VALUE coder_obj;
212
179
  Oid oid;
213
180
  int format;
181
+ /* OR-ed values out of PG_CODER_* */
182
+ int flags;
214
183
  };
215
184
 
216
185
  typedef struct {
@@ -247,6 +216,7 @@ typedef struct {
247
216
  * Globals
248
217
  **************************************************************************/
249
218
 
219
+ extern int pg_skip_deprecation_warning;
250
220
  extern VALUE rb_mPG;
251
221
  extern VALUE rb_ePGerror;
252
222
  extern VALUE rb_eServerError;
@@ -309,10 +279,12 @@ void init_pg_text_encoder _(( void ));
309
279
  void init_pg_text_decoder _(( void ));
310
280
  void init_pg_binary_encoder _(( void ));
311
281
  void init_pg_binary_decoder _(( void ));
282
+ void init_pg_tuple _(( void ));
312
283
  VALUE lookup_error_class _(( const char * ));
313
- VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
314
- VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
315
- int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *));
284
+ VALUE pg_bin_dec_bytea _(( t_pg_coder*, const char *, int, int, int, int ));
285
+ VALUE pg_text_dec_string _(( t_pg_coder*, const char *, int, int, int, int ));
286
+ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *, int));
287
+ int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
316
288
  t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
317
289
  t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
318
290
  void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
@@ -353,6 +325,7 @@ VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
353
325
  PGresult* pgresult_get _(( VALUE ));
354
326
  VALUE pg_result_check _(( VALUE ));
355
327
  VALUE pg_result_clear _(( VALUE ));
328
+ VALUE pg_tuple_new _(( VALUE, int ));
356
329
 
357
330
  /*
358
331
  * Fetch the data pointer for the result object
@@ -360,7 +333,7 @@ VALUE pg_result_clear _(( VALUE ));
360
333
  static inline t_pg_result *
361
334
  pgresult_get_this( VALUE self )
362
335
  {
363
- t_pg_result *this = DATA_PTR(self);
336
+ t_pg_result *this = RTYPEDDATA_DATA(self);
364
337
 
365
338
  if( this == NULL )
366
339
  rb_raise(rb_ePGerror, "result has been cleared");
@@ -369,14 +342,24 @@ pgresult_get_this( VALUE self )
369
342
  }
370
343
 
371
344
 
372
- #ifdef M17N_SUPPORTED
373
345
  rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
374
346
  rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
375
347
  const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
376
348
  rb_encoding *pg_conn_enc_get _(( PGconn * ));
377
- #endif /* M17N_SUPPORTED */
378
349
 
379
350
  void notice_receiver_proxy(void *arg, const PGresult *result);
380
351
  void notice_processor_proxy(void *arg, const char *message);
381
352
 
353
+ /* reports if `-W' specified and PG_SKIP_DEPRECATION_WARNING environment variable isn't set
354
+ *
355
+ * message_id identifies the warning, so that it's reported only once.
356
+ */
357
+ #define pg_deprecated(message_id, format_args) \
358
+ do { \
359
+ if( !(pg_skip_deprecation_warning & (1 << message_id)) ){ \
360
+ pg_skip_deprecation_warning |= 1 << message_id; \
361
+ rb_warning format_args; \
362
+ } \
363
+ } while(0);
364
+
382
365
  #endif /* end __pg_h */
@@ -1,12 +1,15 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_decoder.c,v 185638b52684 2014/11/08 20:43:53 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
7
+ #include "ruby/version.h"
7
8
  #include "pg.h"
8
9
  #include "util.h"
10
+ #ifdef HAVE_INTTYPES_H
9
11
  #include <inttypes.h>
12
+ #endif
10
13
 
11
14
  VALUE rb_mPG_BinaryDecoder;
12
15
 
@@ -19,7 +22,7 @@ VALUE rb_mPG_BinaryDecoder;
19
22
  *
20
23
  */
21
24
  static VALUE
22
- 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)
23
26
  {
24
27
  if (len < 1) {
25
28
  rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
@@ -35,7 +38,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, i
35
38
  *
36
39
  */
37
40
  static VALUE
38
- 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)
39
42
  {
40
43
  switch( len ){
41
44
  case 2:
@@ -57,7 +60,7 @@ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, i
57
60
  *
58
61
  */
59
62
  static VALUE
60
- 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)
61
64
  {
62
65
  union {
63
66
  float f;
@@ -89,7 +92,7 @@ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int
89
92
  *
90
93
  */
91
94
  VALUE
92
- 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)
93
96
  {
94
97
  VALUE ret;
95
98
  ret = rb_tainted_str_new( val, len );
@@ -104,7 +107,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int
104
107
  *
105
108
  */
106
109
  static VALUE
107
- 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)
108
111
  {
109
112
  t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
110
113
  t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
@@ -128,6 +131,70 @@ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field,
128
131
  return out_value;
129
132
  }
130
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
+ int64_t sec;
158
+ int64_t nsec;
159
+ VALUE t;
160
+
161
+ if( len != sizeof(timestamp) ){
162
+ rb_raise( rb_eTypeError, "wrong data for timestamp converter in tuple %d field %d length %d", tuple, field, len);
163
+ }
164
+
165
+ timestamp = read_nbo64(val);
166
+
167
+ switch(timestamp){
168
+ case PG_INT64_MAX:
169
+ return rb_str_new2("infinity");
170
+ case PG_INT64_MIN:
171
+ return rb_str_new2("-infinity");
172
+ default:
173
+ /* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
174
+ * Adjust the 30 years difference. */
175
+ sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
176
+ nsec = (timestamp % 1000000) * 1000;
177
+
178
+ #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
179
+ /* Fast path for time conversion */
180
+ {
181
+ struct timespec ts = {sec, nsec};
182
+ t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
183
+ }
184
+ #else
185
+ t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(sec), LL2NUM(nsec / 1000));
186
+ if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
187
+ t = rb_funcall(t, rb_intern("utc"), 0);
188
+ }
189
+ #endif
190
+ if( conv->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
191
+ /* interpret it as local time */
192
+ t = rb_funcall(t, rb_intern("-"), 1, rb_funcall(t, rb_intern("utc_offset"), 0));
193
+ }
194
+ return t;
195
+ }
196
+ }
197
+
131
198
  /*
132
199
  * Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
133
200
  *
@@ -154,6 +221,8 @@ init_pg_binary_decoder()
154
221
  pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
155
222
  /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
156
223
  pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
224
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */
225
+ pg_define_coder( "Timestamp", pg_bin_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
157
226
 
158
227
  /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
159
228
  pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
@@ -1,12 +1,14 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_encoder.c,v ac23631c96d9 2014/10/14 11:50:21 lars $
3
+ * $Id: pg_binary_encoder.c,v e61a06f1f5ed 2015/12/25 21:14:21 lars $
4
4
  *
5
5
  */
6
6
 
7
7
  #include "pg.h"
8
8
  #include "util.h"
9
+ #ifdef HAVE_INTTYPES_H
9
10
  #include <inttypes.h>
11
+ #endif
10
12
 
11
13
  VALUE rb_mPG_BinaryEncoder;
12
14
 
@@ -20,16 +22,16 @@ VALUE rb_mPG_BinaryEncoder;
20
22
  *
21
23
  */
22
24
  static int
23
- pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
25
+ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
24
26
  {
25
- char bool;
27
+ char mybool;
26
28
  switch(value){
27
- case Qtrue : bool = 1; break;
28
- case Qfalse : bool = 0; break;
29
+ case Qtrue : mybool = 1; break;
30
+ case Qfalse : mybool = 0; break;
29
31
  default :
30
32
  rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
31
33
  }
32
- if(out) *out = bool;
34
+ if(out) *out = mybool;
33
35
  return 1;
34
36
  }
35
37
 
@@ -42,7 +44,7 @@ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
42
44
  *
43
45
  */
44
46
  static int
45
- pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
47
+ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
46
48
  {
47
49
  if(out){
48
50
  write_nbo16(NUM2INT(*intermediate), out);
@@ -61,7 +63,7 @@ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
61
63
  *
62
64
  */
63
65
  static int
64
- pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
66
+ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
65
67
  {
66
68
  if(out){
67
69
  write_nbo32(NUM2LONG(*intermediate), out);
@@ -80,7 +82,7 @@ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
80
82
  *
81
83
  */
82
84
  static int
83
- pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
85
+ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
84
86
  {
85
87
  if(out){
86
88
  write_nbo64(NUM2LL(*intermediate), out);
@@ -98,7 +100,7 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
98
100
  *
99
101
  */
100
102
  static int
101
- pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
103
+ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
102
104
  {
103
105
  int strlen;
104
106
  VALUE subint;
@@ -107,13 +109,13 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
107
109
 
108
110
  if(out){
109
111
  /* Second encoder pass, if required */
110
- strlen = enc_func(this->elem, value, out, intermediate);
112
+ strlen = enc_func(this->elem, value, out, intermediate, enc_idx);
111
113
  strlen = base64_decode( out, out, strlen );
112
114
 
113
115
  return strlen;
114
116
  } else {
115
117
  /* First encoder pass */
116
- strlen = enc_func(this->elem, value, NULL, &subint);
118
+ strlen = enc_func(this->elem, value, NULL, &subint, enc_idx);
117
119
 
118
120
  if( strlen == -1 ){
119
121
  /* Encoded string is returned in subint */