pg 0.18.2 → 1.4.5

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 (119) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +86 -0
  6. data/.github/workflows/source-gem.yml +131 -0
  7. data/.gitignore +13 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/BSDL +2 -2
  15. data/Gemfile +14 -0
  16. data/History.rdoc +480 -4
  17. data/Manifest.txt +8 -21
  18. data/README-Windows.rdoc +17 -28
  19. data/README.ja.rdoc +1 -2
  20. data/README.rdoc +92 -20
  21. data/Rakefile +33 -133
  22. data/Rakefile.cross +89 -67
  23. data/certs/ged.pem +24 -0
  24. data/certs/larskanis-2022.pem +26 -0
  25. data/ext/errorcodes.def +113 -0
  26. data/ext/errorcodes.rb +1 -1
  27. data/ext/errorcodes.txt +36 -2
  28. data/ext/extconf.rb +120 -54
  29. data/ext/gvl_wrappers.c +8 -0
  30. data/ext/gvl_wrappers.h +44 -33
  31. data/ext/pg.c +216 -172
  32. data/ext/pg.h +93 -98
  33. data/ext/pg_binary_decoder.c +85 -16
  34. data/ext/pg_binary_encoder.c +25 -22
  35. data/ext/pg_coder.c +176 -40
  36. data/ext/pg_connection.c +1735 -1138
  37. data/ext/pg_copy_coder.c +95 -28
  38. data/ext/pg_errors.c +1 -1
  39. data/ext/pg_record_coder.c +521 -0
  40. data/ext/pg_result.c +642 -221
  41. data/ext/pg_text_decoder.c +609 -41
  42. data/ext/pg_text_encoder.c +254 -100
  43. data/ext/pg_tuple.c +569 -0
  44. data/ext/pg_type_map.c +62 -22
  45. data/ext/pg_type_map_all_strings.c +20 -6
  46. data/ext/pg_type_map_by_class.c +55 -25
  47. data/ext/pg_type_map_by_column.c +81 -42
  48. data/ext/pg_type_map_by_mri_type.c +49 -20
  49. data/ext/pg_type_map_by_oid.c +56 -26
  50. data/ext/pg_type_map_in_ruby.c +52 -21
  51. data/ext/{util.c → pg_util.c} +12 -12
  52. data/ext/{util.h → pg_util.h} +2 -2
  53. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  54. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  55. data/lib/pg/basic_type_map_for_results.rb +81 -0
  56. data/lib/pg/basic_type_registry.rb +301 -0
  57. data/lib/pg/binary_decoder.rb +23 -0
  58. data/lib/pg/coder.rb +24 -3
  59. data/lib/pg/connection.rb +711 -64
  60. data/lib/pg/constants.rb +2 -1
  61. data/lib/pg/exceptions.rb +9 -2
  62. data/lib/pg/result.rb +24 -7
  63. data/lib/pg/text_decoder.rb +27 -23
  64. data/lib/pg/text_encoder.rb +40 -8
  65. data/lib/pg/tuple.rb +30 -0
  66. data/lib/pg/type_map_by_column.rb +3 -2
  67. data/lib/pg/version.rb +4 -0
  68. data/lib/pg.rb +61 -36
  69. data/misc/openssl-pg-segfault.rb +31 -0
  70. data/misc/postgres/History.txt +9 -0
  71. data/misc/postgres/Manifest.txt +5 -0
  72. data/misc/postgres/README.txt +21 -0
  73. data/misc/postgres/Rakefile +21 -0
  74. data/misc/postgres/lib/postgres.rb +16 -0
  75. data/misc/ruby-pg/History.txt +9 -0
  76. data/misc/ruby-pg/Manifest.txt +5 -0
  77. data/misc/ruby-pg/README.txt +21 -0
  78. data/misc/ruby-pg/Rakefile +21 -0
  79. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  80. data/pg.gemspec +32 -0
  81. data/rakelib/task_extension.rb +46 -0
  82. data/sample/array_insert.rb +1 -1
  83. data/sample/async_api.rb +4 -8
  84. data/sample/async_copyto.rb +1 -1
  85. data/sample/async_mixed.rb +1 -1
  86. data/sample/check_conn.rb +1 -1
  87. data/sample/copydata.rb +71 -0
  88. data/sample/copyfrom.rb +1 -1
  89. data/sample/copyto.rb +1 -1
  90. data/sample/cursor.rb +1 -1
  91. data/sample/disk_usage_report.rb +6 -15
  92. data/sample/issue-119.rb +2 -2
  93. data/sample/losample.rb +1 -1
  94. data/sample/minimal-testcase.rb +2 -2
  95. data/sample/notify_wait.rb +1 -1
  96. data/sample/pg_statistics.rb +6 -15
  97. data/sample/replication_monitor.rb +9 -18
  98. data/sample/test_binary_values.rb +1 -1
  99. data/sample/wal_shipper.rb +2 -2
  100. data/sample/warehouse_partitions.rb +8 -17
  101. data.tar.gz.sig +0 -0
  102. metadata +74 -216
  103. metadata.gz.sig +0 -0
  104. data/ChangeLog +0 -5545
  105. data/lib/pg/basic_type_mapping.rb +0 -399
  106. data/spec/data/expected_trace.out +0 -26
  107. data/spec/data/random_binary_data +0 -0
  108. data/spec/helpers.rb +0 -355
  109. data/spec/pg/basic_type_mapping_spec.rb +0 -251
  110. data/spec/pg/connection_spec.rb +0 -1535
  111. data/spec/pg/result_spec.rb +0 -449
  112. data/spec/pg/type_map_by_class_spec.rb +0 -138
  113. data/spec/pg/type_map_by_column_spec.rb +0 -222
  114. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  115. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  116. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  117. data/spec/pg/type_map_spec.rb +0 -22
  118. data/spec/pg/type_spec.rb +0 -688
  119. data/spec/pg_spec.rb +0 -50
data/ext/pg_copy_coder.c CHANGED
@@ -21,17 +21,47 @@ typedef struct {
21
21
 
22
22
 
23
23
  static void
24
- pg_copycoder_mark( t_pg_copycoder *this )
24
+ pg_copycoder_mark( void *_this )
25
25
  {
26
- rb_gc_mark(this->typemap);
27
- rb_gc_mark(this->null_string);
26
+ t_pg_copycoder *this = (t_pg_copycoder *)_this;
27
+ rb_gc_mark_movable(this->typemap);
28
+ rb_gc_mark_movable(this->null_string);
28
29
  }
29
30
 
31
+ static size_t
32
+ pg_copycoder_memsize( const void *_this )
33
+ {
34
+ const t_pg_copycoder *this = (const t_pg_copycoder *)_this;
35
+ return sizeof(*this);
36
+ }
37
+
38
+ static void
39
+ pg_copycoder_compact( void *_this )
40
+ {
41
+ t_pg_copycoder *this = (t_pg_copycoder *)_this;
42
+ pg_coder_compact(&this->comp);
43
+ pg_gc_location(this->typemap);
44
+ pg_gc_location(this->null_string);
45
+ }
46
+
47
+ static const rb_data_type_t pg_copycoder_type = {
48
+ "PG::CopyCoder",
49
+ {
50
+ pg_copycoder_mark,
51
+ RUBY_TYPED_DEFAULT_FREE,
52
+ pg_copycoder_memsize,
53
+ pg_compact_callback(pg_copycoder_compact),
54
+ },
55
+ &pg_coder_type,
56
+ 0,
57
+ RUBY_TYPED_FREE_IMMEDIATELY,
58
+ };
59
+
30
60
  static VALUE
31
61
  pg_copycoder_encoder_allocate( VALUE klass )
32
62
  {
33
63
  t_pg_copycoder *this;
34
- VALUE self = Data_Make_Struct( klass, t_pg_copycoder, pg_copycoder_mark, -1, this );
64
+ VALUE self = TypedData_Make_Struct( klass, t_pg_copycoder, &pg_copycoder_type, this );
35
65
  pg_coder_init_encoder( self );
36
66
  this->typemap = pg_typemap_all_strings;
37
67
  this->delimiter = '\t';
@@ -43,7 +73,7 @@ static VALUE
43
73
  pg_copycoder_decoder_allocate( VALUE klass )
44
74
  {
45
75
  t_pg_copycoder *this;
46
- VALUE self = Data_Make_Struct( klass, t_pg_copycoder, pg_copycoder_mark, -1, this );
76
+ VALUE self = TypedData_Make_Struct( klass, t_pg_copycoder, &pg_copycoder_type, this );
47
77
  pg_coder_init_decoder( self );
48
78
  this->typemap = pg_typemap_all_strings;
49
79
  this->delimiter = '\t';
@@ -62,7 +92,7 @@ pg_copycoder_decoder_allocate( VALUE klass )
62
92
  static VALUE
63
93
  pg_copycoder_delimiter_set(VALUE self, VALUE delimiter)
64
94
  {
65
- t_pg_copycoder *this = DATA_PTR(self);
95
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
66
96
  StringValue(delimiter);
67
97
  if(RSTRING_LEN(delimiter) != 1)
68
98
  rb_raise( rb_eArgError, "delimiter size must be one byte");
@@ -79,7 +109,7 @@ pg_copycoder_delimiter_set(VALUE self, VALUE delimiter)
79
109
  static VALUE
80
110
  pg_copycoder_delimiter_get(VALUE self)
81
111
  {
82
- t_pg_copycoder *this = DATA_PTR(self);
112
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
83
113
  return rb_str_new(&this->delimiter, 1);
84
114
  }
85
115
 
@@ -92,7 +122,7 @@ pg_copycoder_delimiter_get(VALUE self)
92
122
  static VALUE
93
123
  pg_copycoder_null_string_set(VALUE self, VALUE null_string)
94
124
  {
95
- t_pg_copycoder *this = DATA_PTR(self);
125
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
96
126
  StringValue(null_string);
97
127
  this->null_string = null_string;
98
128
  return null_string;
@@ -104,7 +134,7 @@ pg_copycoder_null_string_set(VALUE self, VALUE null_string)
104
134
  static VALUE
105
135
  pg_copycoder_null_string_get(VALUE self)
106
136
  {
107
- t_pg_copycoder *this = DATA_PTR(self);
137
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
108
138
  return this->null_string;
109
139
  }
110
140
 
@@ -112,16 +142,17 @@ pg_copycoder_null_string_get(VALUE self)
112
142
  * call-seq:
113
143
  * coder.type_map = map
114
144
  *
145
+ * Defines how single columns are encoded or decoded.
115
146
  * +map+ must be a kind of PG::TypeMap .
116
147
  *
117
148
  * Defaults to a PG::TypeMapAllStrings , so that PG::TextEncoder::String respectively
118
- * PG::TextDecoder::String is used for encoding/decoding of all columns.
149
+ * PG::TextDecoder::String is used for encoding/decoding of each column.
119
150
  *
120
151
  */
121
152
  static VALUE
122
153
  pg_copycoder_type_map_set(VALUE self, VALUE type_map)
123
154
  {
124
- t_pg_copycoder *this = DATA_PTR( self );
155
+ t_pg_copycoder *this = RTYPEDDATA_DATA( self );
125
156
 
126
157
  if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
127
158
  rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
@@ -136,11 +167,12 @@ pg_copycoder_type_map_set(VALUE self, VALUE type_map)
136
167
  * call-seq:
137
168
  * coder.type_map -> PG::TypeMap
138
169
  *
170
+ * The PG::TypeMap that will be used for encoding and decoding of columns.
139
171
  */
140
172
  static VALUE
141
173
  pg_copycoder_type_map_get(VALUE self)
142
174
  {
143
- t_pg_copycoder *this = DATA_PTR( self );
175
+ t_pg_copycoder *this = RTYPEDDATA_DATA( self );
144
176
 
145
177
  return this->typemap;
146
178
  }
@@ -167,9 +199,15 @@ pg_copycoder_type_map_get(VALUE self)
167
199
  * conn.put_copy_data ["string2", 42, true]
168
200
  * end
169
201
  * This creates +my_table+ and inserts two rows.
202
+ *
203
+ * It is possible to manually assign a type encoder for each column per PG::TypeMapByColumn,
204
+ * or to make use of PG::BasicTypeMapBasedOnResult to assign them based on the table OIDs.
205
+ *
206
+ * See also PG::TextDecoder::CopyRow for the decoding direction with
207
+ * PG::Connection#get_copy_data .
170
208
  */
171
209
  static int
172
- pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
210
+ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
173
211
  {
174
212
  t_pg_copycoder *this = (t_pg_copycoder *)conv;
175
213
  t_pg_coder_enc_func enc_func;
@@ -179,11 +217,12 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
179
217
  char *current_out;
180
218
  char *end_capa_ptr;
181
219
 
182
- p_typemap = DATA_PTR( this->typemap );
220
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
183
221
  p_typemap->funcs.fit_to_query( this->typemap, value );
184
222
 
185
223
  /* Allocate a new string with embedded capacity and realloc exponential when needed. */
186
224
  PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
225
+ PG_ENCODING_SET_NOCHECK(*intermediate, enc_idx);
187
226
 
188
227
  for( i=0; i<RARRAY_LEN(value); i++){
189
228
  char *ptr1;
@@ -211,11 +250,11 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
211
250
  enc_func = pg_coder_enc_func(p_elem_coder);
212
251
 
213
252
  /* 1st pass for retiving the required memory space */
214
- strlen = enc_func(p_elem_coder, entry, NULL, &subint);
253
+ strlen = enc_func(p_elem_coder, entry, NULL, &subint, enc_idx);
215
254
 
216
255
  if( strlen == -1 ){
217
256
  /* we can directly use String value in subint */
218
- strlen = RSTRING_LEN(subint);
257
+ strlen = RSTRING_LENINT(subint);
219
258
 
220
259
  /* size of string assuming the worst case, that every character must be escaped. */
221
260
  PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
@@ -234,7 +273,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
234
273
  PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
235
274
 
236
275
  /* Place the unescaped string at current output position. */
237
- strlen = enc_func(p_elem_coder, entry, current_out, &subint);
276
+ strlen = enc_func(p_elem_coder, entry, current_out, &subint, enc_idx);
238
277
 
239
278
  ptr1 = current_out;
240
279
  ptr2 = current_out + strlen;
@@ -301,15 +340,38 @@ GetDecimalFromHex(char hex)
301
340
  * strings by PG::TextDecoder::String.
302
341
  *
303
342
  * Example with default type map ( TypeMapAllStrings ):
343
+ * conn.exec("CREATE TABLE my_table AS VALUES('astring', 7, FALSE), ('string2', 42, TRUE) ")
344
+ *
304
345
  * deco = PG::TextDecoder::CopyRow.new
305
346
  * conn.copy_data "COPY my_table TO STDOUT", deco do
306
347
  * while row=conn.get_copy_data
307
348
  * p row
308
349
  * end
309
350
  * end
310
- * This prints all rows of +my_table+ to stdout:
351
+ * This prints all rows of +my_table+ :
311
352
  * ["astring", "7", "f"]
312
353
  * ["string2", "42", "t"]
354
+ *
355
+ * Example with column based type map:
356
+ * tm = PG::TypeMapByColumn.new( [
357
+ * PG::TextDecoder::String.new,
358
+ * PG::TextDecoder::Integer.new,
359
+ * PG::TextDecoder::Boolean.new] )
360
+ * deco = PG::TextDecoder::CopyRow.new( type_map: tm )
361
+ * conn.copy_data "COPY my_table TO STDOUT", deco do
362
+ * while row=conn.get_copy_data
363
+ * p row
364
+ * end
365
+ * end
366
+ * This prints the rows with type casted columns:
367
+ * ["astring", 7, false]
368
+ * ["string2", 42, true]
369
+ *
370
+ * Instead of manually assigning a type decoder for each column, PG::BasicTypeMapForResults
371
+ * can be used to assign them based on the table OIDs.
372
+ *
373
+ * See also PG::TextEncoder::CopyRow for the encoding direction with
374
+ * PG::Connection#put_copy_data .
313
375
  */
314
376
  /*
315
377
  * Parse the current line into separate attributes (fields),
@@ -324,7 +386,7 @@ GetDecimalFromHex(char hex)
324
386
  * src/backend/commands/copy.c
325
387
  */
326
388
  static VALUE
327
- pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, int _field, int enc_idx)
389
+ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tuple, int _field, int enc_idx)
328
390
  {
329
391
  t_pg_copycoder *this = (t_pg_copycoder *)conv;
330
392
 
@@ -338,12 +400,12 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
338
400
  int fieldno;
339
401
  int expected_fields;
340
402
  char *output_ptr;
341
- char *cur_ptr;
342
- char *line_end_ptr;
403
+ const char *cur_ptr;
404
+ const char *line_end_ptr;
343
405
  char *end_capa_ptr;
344
406
  t_typemap *p_typemap;
345
407
 
346
- p_typemap = DATA_PTR( this->typemap );
408
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
347
409
  expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
348
410
 
349
411
  /* The received input string will probably have this->nfields fields. */
@@ -351,7 +413,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
351
413
 
352
414
  /* Allocate a new string with embedded capacity and realloc later with
353
415
  * exponential growing size when needed. */
354
- PG_RB_TAINTED_STR_NEW( field_str, output_ptr, end_capa_ptr );
416
+ PG_RB_STR_NEW( field_str, output_ptr, end_capa_ptr );
355
417
 
356
418
  /* set pointer variables for loop */
357
419
  cur_ptr = input_line;
@@ -362,9 +424,9 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
362
424
  for (;;)
363
425
  {
364
426
  int found_delim = 0;
365
- char *start_ptr;
366
- char *end_ptr;
367
- int input_len;
427
+ const char *start_ptr;
428
+ const char *end_ptr;
429
+ long input_len;
368
430
 
369
431
  /* Remember start of field on input side */
370
432
  start_ptr = cur_ptr;
@@ -513,7 +575,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
513
575
  if( field_value == field_str ){
514
576
  /* Our output string will be send to the user, so we can not reuse
515
577
  * it for the next field. */
516
- PG_RB_TAINTED_STR_NEW( field_str, output_ptr, end_capa_ptr );
578
+ PG_RB_STR_NEW( field_str, output_ptr, end_capa_ptr );
517
579
  }
518
580
  }
519
581
  /* Reset the pointer to the start of the output/buffer string. */
@@ -530,7 +592,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
530
592
 
531
593
 
532
594
  void
533
- init_pg_copycoder()
595
+ init_pg_copycoder(void)
534
596
  {
535
597
  /* Document-class: PG::CopyCoder < PG::Coder
536
598
  *
@@ -555,7 +617,12 @@ init_pg_copycoder()
555
617
  /* rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" ); */
556
618
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "CopyRow", rb_cPG_CopyEncoder ); */
557
619
  pg_define_coder( "CopyRow", pg_text_enc_copy_row, rb_cPG_CopyEncoder, rb_mPG_TextEncoder );
620
+ rb_include_module( rb_cPG_CopyEncoder, rb_mPG_BinaryFormatting );
621
+
558
622
  /* rb_mPG_TextDecoder = rb_define_module_under( rb_mPG, "TextDecoder" ); */
559
623
  /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "CopyRow", rb_cPG_CopyDecoder ); */
560
624
  pg_define_coder( "CopyRow", pg_text_dec_copy_row, rb_cPG_CopyDecoder, rb_mPG_TextDecoder );
625
+ /* Although CopyRow is a text decoder, data can contain zero bytes and are not zero terminated.
626
+ * They are handled like binaries. So format is set to 1 (binary). */
627
+ rb_include_module( rb_cPG_CopyDecoder, rb_mPG_BinaryFormatting );
561
628
  }
data/ext/pg_errors.c CHANGED
@@ -70,7 +70,7 @@ lookup_error_class(const char *sqlstate)
70
70
  }
71
71
 
72
72
  void
73
- init_pg_errors()
73
+ init_pg_errors(void)
74
74
  {
75
75
  rb_hErrors = rb_hash_new();
76
76
  rb_define_const( rb_mPG, "ERROR_CLASSES", rb_hErrors );