pg 0.18.0 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
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 */