pg 1.2.3 → 1.6.1

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 (135) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +986 -0
  4. data/Gemfile +23 -0
  5. data/README-Windows.rdoc +1 -1
  6. data/README.ja.md +300 -0
  7. data/README.md +327 -0
  8. data/Rakefile +123 -144
  9. data/certs/ged.pem +24 -0
  10. data/certs/kanis@comcard.de.pem +20 -0
  11. data/certs/larskanis-2022.pem +26 -0
  12. data/certs/larskanis-2023.pem +24 -0
  13. data/certs/larskanis-2024.pem +24 -0
  14. data/ext/errorcodes.def +16 -5
  15. data/ext/errorcodes.rb +0 -0
  16. data/ext/errorcodes.txt +5 -5
  17. data/ext/extconf.rb +259 -33
  18. data/ext/gvl_wrappers.c +17 -2
  19. data/ext/gvl_wrappers.h +56 -0
  20. data/ext/pg.c +89 -63
  21. data/ext/pg.h +31 -8
  22. data/ext/pg_binary_decoder.c +232 -1
  23. data/ext/pg_binary_encoder.c +428 -1
  24. data/ext/pg_cancel_connection.c +360 -0
  25. data/ext/pg_coder.c +148 -36
  26. data/ext/pg_connection.c +1365 -817
  27. data/ext/pg_copy_coder.c +360 -38
  28. data/ext/pg_errors.c +1 -1
  29. data/ext/pg_record_coder.c +56 -25
  30. data/ext/pg_result.c +187 -76
  31. data/ext/pg_text_decoder.c +32 -11
  32. data/ext/pg_text_encoder.c +65 -33
  33. data/ext/pg_tuple.c +84 -61
  34. data/ext/pg_type_map.c +44 -10
  35. data/ext/pg_type_map_all_strings.c +17 -3
  36. data/ext/pg_type_map_by_class.c +54 -27
  37. data/ext/pg_type_map_by_column.c +74 -31
  38. data/ext/pg_type_map_by_mri_type.c +48 -19
  39. data/ext/pg_type_map_by_oid.c +61 -27
  40. data/ext/pg_type_map_in_ruby.c +55 -21
  41. data/ext/pg_util.c +2 -2
  42. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  43. data/lib/pg/basic_type_map_for_queries.rb +206 -0
  44. data/lib/pg/basic_type_map_for_results.rb +104 -0
  45. data/lib/pg/basic_type_registry.rb +311 -0
  46. data/lib/pg/binary_decoder/date.rb +9 -0
  47. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  48. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  49. data/lib/pg/cancel_connection.rb +53 -0
  50. data/lib/pg/coder.rb +18 -14
  51. data/lib/pg/connection.rb +894 -91
  52. data/lib/pg/exceptions.rb +20 -1
  53. data/lib/pg/text_decoder/date.rb +21 -0
  54. data/lib/pg/text_decoder/inet.rb +9 -0
  55. data/lib/pg/text_decoder/json.rb +17 -0
  56. data/lib/pg/text_decoder/numeric.rb +9 -0
  57. data/lib/pg/text_decoder/timestamp.rb +30 -0
  58. data/lib/pg/text_encoder/date.rb +13 -0
  59. data/lib/pg/text_encoder/inet.rb +31 -0
  60. data/lib/pg/text_encoder/json.rb +17 -0
  61. data/lib/pg/text_encoder/numeric.rb +9 -0
  62. data/lib/pg/text_encoder/timestamp.rb +24 -0
  63. data/lib/pg/version.rb +4 -0
  64. data/lib/pg.rb +109 -39
  65. data/misc/openssl-pg-segfault.rb +31 -0
  66. data/misc/postgres/History.txt +9 -0
  67. data/misc/postgres/Manifest.txt +5 -0
  68. data/misc/postgres/README.txt +21 -0
  69. data/misc/postgres/Rakefile +21 -0
  70. data/misc/postgres/lib/postgres.rb +16 -0
  71. data/misc/ruby-pg/History.txt +9 -0
  72. data/misc/ruby-pg/Manifest.txt +5 -0
  73. data/misc/ruby-pg/README.txt +21 -0
  74. data/misc/ruby-pg/Rakefile +21 -0
  75. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  76. data/misc/yugabyte/Dockerfile +9 -0
  77. data/misc/yugabyte/docker-compose.yml +28 -0
  78. data/misc/yugabyte/pg-test.rb +45 -0
  79. data/pg.gemspec +38 -0
  80. data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
  81. data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
  82. data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
  83. data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
  84. data/rakelib/pg_gem_helper.rb +64 -0
  85. data/rakelib/task_extension.rb +46 -0
  86. data/sample/array_insert.rb +20 -0
  87. data/sample/async_api.rb +102 -0
  88. data/sample/async_copyto.rb +39 -0
  89. data/sample/async_mixed.rb +56 -0
  90. data/sample/check_conn.rb +21 -0
  91. data/sample/copydata.rb +71 -0
  92. data/sample/copyfrom.rb +81 -0
  93. data/sample/copyto.rb +19 -0
  94. data/sample/cursor.rb +21 -0
  95. data/sample/disk_usage_report.rb +177 -0
  96. data/sample/issue-119.rb +94 -0
  97. data/sample/losample.rb +69 -0
  98. data/sample/minimal-testcase.rb +17 -0
  99. data/sample/notify_wait.rb +72 -0
  100. data/sample/pg_statistics.rb +285 -0
  101. data/sample/replication_monitor.rb +222 -0
  102. data/sample/test_binary_values.rb +33 -0
  103. data/sample/wal_shipper.rb +434 -0
  104. data/sample/warehouse_partitions.rb +311 -0
  105. data.tar.gz.sig +0 -0
  106. metadata +139 -213
  107. metadata.gz.sig +0 -0
  108. data/.gemtest +0 -0
  109. data/ChangeLog +0 -0
  110. data/History.rdoc +0 -578
  111. data/Manifest.txt +0 -73
  112. data/README.ja.rdoc +0 -13
  113. data/README.rdoc +0 -213
  114. data/Rakefile.cross +0 -299
  115. data/lib/pg/basic_type_mapping.rb +0 -522
  116. data/lib/pg/binary_decoder.rb +0 -23
  117. data/lib/pg/constants.rb +0 -12
  118. data/lib/pg/text_decoder.rb +0 -46
  119. data/lib/pg/text_encoder.rb +0 -59
  120. data/spec/data/expected_trace.out +0 -26
  121. data/spec/data/random_binary_data +0 -0
  122. data/spec/helpers.rb +0 -380
  123. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  124. data/spec/pg/connection_spec.rb +0 -1949
  125. data/spec/pg/connection_sync_spec.rb +0 -41
  126. data/spec/pg/result_spec.rb +0 -681
  127. data/spec/pg/tuple_spec.rb +0 -333
  128. data/spec/pg/type_map_by_class_spec.rb +0 -138
  129. data/spec/pg/type_map_by_column_spec.rb +0 -226
  130. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  131. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  132. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  133. data/spec/pg/type_map_spec.rb +0 -22
  134. data/spec/pg/type_spec.rb +0 -1123
  135. data/spec/pg_spec.rb +0 -50
@@ -16,19 +16,47 @@ typedef struct {
16
16
 
17
17
 
18
18
  static void
19
- pg_recordcoder_mark( t_pg_recordcoder *this )
19
+ pg_recordcoder_mark( void *_this )
20
20
  {
21
- pg_coder_mark(&this->comp);
22
- rb_gc_mark(this->typemap);
21
+ t_pg_recordcoder *this = (t_pg_recordcoder *)_this;
22
+ rb_gc_mark_movable(this->typemap);
23
23
  }
24
24
 
25
+ static size_t
26
+ pg_recordcoder_memsize( const void *_this )
27
+ {
28
+ const t_pg_recordcoder *this = (const t_pg_recordcoder *)_this;
29
+ return sizeof(*this);
30
+ }
31
+
32
+ static void
33
+ pg_recordcoder_compact( void *_this )
34
+ {
35
+ t_pg_recordcoder *this = (t_pg_recordcoder *)_this;
36
+ pg_coder_compact(&this->comp);
37
+ pg_gc_location(this->typemap);
38
+ }
39
+
40
+ static const rb_data_type_t pg_recordcoder_type = {
41
+ "PG::RecordCoder",
42
+ {
43
+ pg_recordcoder_mark,
44
+ RUBY_TYPED_DEFAULT_FREE,
45
+ pg_recordcoder_memsize,
46
+ pg_recordcoder_compact,
47
+ },
48
+ &pg_coder_type,
49
+ 0,
50
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
51
+ };
52
+
25
53
  static VALUE
26
54
  pg_recordcoder_encoder_allocate( VALUE klass )
27
55
  {
28
56
  t_pg_recordcoder *this;
29
- VALUE self = Data_Make_Struct( klass, t_pg_recordcoder, pg_recordcoder_mark, -1, this );
57
+ VALUE self = TypedData_Make_Struct( klass, t_pg_recordcoder, &pg_recordcoder_type, this );
30
58
  pg_coder_init_encoder( self );
31
- this->typemap = pg_typemap_all_strings;
59
+ RB_OBJ_WRITE(self, &this->typemap, pg_typemap_all_strings);
32
60
  return self;
33
61
  }
34
62
 
@@ -36,9 +64,9 @@ static VALUE
36
64
  pg_recordcoder_decoder_allocate( VALUE klass )
37
65
  {
38
66
  t_pg_recordcoder *this;
39
- VALUE self = Data_Make_Struct( klass, t_pg_recordcoder, pg_recordcoder_mark, -1, this );
67
+ VALUE self = TypedData_Make_Struct( klass, t_pg_recordcoder, &pg_recordcoder_type, this );
40
68
  pg_coder_init_decoder( self );
41
- this->typemap = pg_typemap_all_strings;
69
+ RB_OBJ_WRITE(self, &this->typemap, pg_typemap_all_strings);
42
70
  return self;
43
71
  }
44
72
 
@@ -56,13 +84,14 @@ pg_recordcoder_decoder_allocate( VALUE klass )
56
84
  static VALUE
57
85
  pg_recordcoder_type_map_set(VALUE self, VALUE type_map)
58
86
  {
59
- t_pg_recordcoder *this = DATA_PTR( self );
87
+ t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
60
88
 
89
+ rb_check_frozen(self);
61
90
  if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
62
91
  rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
63
92
  rb_obj_classname( type_map ) );
64
93
  }
65
- this->typemap = type_map;
94
+ RB_OBJ_WRITE(self, &this->typemap, type_map);
66
95
 
67
96
  return type_map;
68
97
  }
@@ -76,7 +105,7 @@ pg_recordcoder_type_map_set(VALUE self, VALUE type_map)
76
105
  static VALUE
77
106
  pg_recordcoder_type_map_get(VALUE self)
78
107
  {
79
- t_pg_recordcoder *this = DATA_PTR( self );
108
+ t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
80
109
 
81
110
  return this->typemap;
82
111
  }
@@ -106,7 +135,7 @@ pg_recordcoder_type_map_get(VALUE self)
106
135
  * tm = PG::TypeMapByColumn.new([PG::TextEncoder::Float.new]*2)
107
136
  * # Use this type map to encode the record:
108
137
  * PG::TextEncoder::Record.new(type_map: tm).encode([1,2])
109
- * # => "(\"1.0000000000000000E+00\",\"2.0000000000000000E+00\")"
138
+ * # => "(\"1.0\",\"2.0\")"
110
139
  *
111
140
  * Records can also be encoded and decoded directly to and from the database.
112
141
  * This avoids intermediate string allocations and is very fast.
@@ -156,7 +185,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
156
185
  char *current_out;
157
186
  char *end_capa_ptr;
158
187
 
159
- p_typemap = DATA_PTR( this->typemap );
188
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
160
189
  p_typemap->funcs.fit_to_query( this->typemap, value );
161
190
 
162
191
  /* Allocate a new string with embedded capacity and realloc exponential when needed. */
@@ -168,8 +197,8 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
168
197
  for( i=0; i<RARRAY_LEN(value); i++){
169
198
  char *ptr1;
170
199
  char *ptr2;
171
- int strlen;
172
- int backslashs;
200
+ long strlen;
201
+ int backslashes;
173
202
  VALUE subint;
174
203
  VALUE entry;
175
204
 
@@ -220,19 +249,19 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
220
249
  ptr2 = current_out + strlen;
221
250
 
222
251
  /* count required backlashs */
223
- for(backslashs = 0; ptr1 != ptr2; ptr1++) {
252
+ for(backslashes = 0; ptr1 != ptr2; ptr1++) {
224
253
  /* Escape backslash itself, newline, carriage return, and the current delimiter character. */
225
254
  if(*ptr1 == '"' || *ptr1 == '\\'){
226
- backslashs++;
255
+ backslashes++;
227
256
  }
228
257
  }
229
258
 
230
259
  ptr1 = current_out + strlen;
231
- ptr2 = current_out + strlen + backslashs;
260
+ ptr2 = current_out + strlen + backslashes;
232
261
  current_out = ptr2;
233
262
 
234
263
  /* Then store the escaped string on the final position, walking
235
- * right to left, until all backslashs are placed. */
264
+ * right to left, until all backslashes are placed. */
236
265
  while( ptr1 != ptr2 ) {
237
266
  *--ptr2 = *--ptr1;
238
267
  if(*ptr1 == '"' || *ptr1 == '\\'){
@@ -311,15 +340,17 @@ record_isspace(char ch)
311
340
  * conn.exec("SELECT * FROM my_table").map_types!(PG::TypeMapByColumn.new([deco]*2)).to_a
312
341
  * # => [{"v1"=>[2.0, 3.0], "v2"=>[4.0, 5.0]}, {"v1"=>[6.0, 7.0], "v2"=>[8.0, 9.0]}]
313
342
  *
314
- * It's more very convenient to use the PG::BasicTypeRegistry, which is based on database OIDs.
343
+ * It's more convenient to use the PG::BasicTypeRegistry, which is based on database OIDs.
315
344
  * # Fetch a NULL record of our type to retrieve the OIDs of the two fields "r" and "i"
316
345
  * oids = conn.exec( "SELECT (NULL::complex).*" )
317
346
  * # Build a type map (PG::TypeMapByColumn) for decoding the "complex" type
318
347
  * dtm = PG::BasicTypeMapForResults.new(conn).build_column_map( oids )
319
- * # Register a record decoder for decoding our type "complex"
320
- * PG::BasicTypeRegistry.register_coder(PG::TextDecoder::Record.new(type_map: dtm, name: "complex"))
321
- * # Apply the basic type registry to all results retrieved from the server
322
- * conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
348
+ * # Build a type map and populate with basic types
349
+ * btr = PG::BasicTypeRegistry.new.register_default_types
350
+ * # Register a new record decoder for decoding our type "complex"
351
+ * btr.register_coder(PG::TextDecoder::Record.new(type_map: dtm, name: "complex"))
352
+ * # Apply our basic type registry to all results retrieved from the server
353
+ * conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn, registry: btr)
323
354
  * # Now queries decode the "complex" type (and many basic types) automatically
324
355
  * conn.exec("SELECT * FROM my_table").to_a
325
356
  * # => [{"v1"=>[2.0, 3.0], "v2"=>[4.0, 5.0]}, {"v1"=>[6.0, 7.0], "v2"=>[8.0, 9.0]}]
@@ -358,7 +389,7 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
358
389
  char *end_capa_ptr;
359
390
  t_typemap *p_typemap;
360
391
 
361
- p_typemap = DATA_PTR( this->typemap );
392
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
362
393
  expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
363
394
 
364
395
  /* The received input string will probably have this->nfields fields. */
@@ -464,7 +495,7 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
464
495
 
465
496
 
466
497
  void
467
- init_pg_recordcoder()
498
+ init_pg_recordcoder(void)
468
499
  {
469
500
  /* Document-class: PG::RecordCoder < PG::Coder
470
501
  *