pg 0.18.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) 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 +130 -0
  6. data/Manifest.txt +0 -18
  7. data/README-Windows.rdoc +15 -26
  8. data/README.rdoc +16 -10
  9. data/Rakefile +32 -23
  10. data/Rakefile.cross +56 -38
  11. data/ext/errorcodes.def +33 -0
  12. data/ext/errorcodes.txt +15 -1
  13. data/ext/extconf.rb +27 -35
  14. data/ext/gvl_wrappers.c +4 -0
  15. data/ext/gvl_wrappers.h +27 -39
  16. data/ext/pg.c +19 -51
  17. data/ext/pg.h +22 -79
  18. data/ext/pg_binary_decoder.c +3 -1
  19. data/ext/pg_binary_encoder.c +14 -12
  20. data/ext/pg_coder.c +31 -10
  21. data/ext/pg_connection.c +350 -263
  22. data/ext/pg_copy_coder.c +34 -4
  23. data/ext/pg_result.c +27 -25
  24. data/ext/pg_text_decoder.c +9 -10
  25. data/ext/pg_text_encoder.c +93 -73
  26. data/ext/pg_type_map.c +20 -13
  27. data/ext/pg_type_map_by_column.c +7 -7
  28. data/ext/pg_type_map_by_mri_type.c +2 -2
  29. data/ext/pg_type_map_in_ruby.c +4 -7
  30. data/ext/util.c +3 -3
  31. data/ext/util.h +1 -1
  32. data/lib/pg/basic_type_mapping.rb +69 -42
  33. data/lib/pg/connection.rb +89 -38
  34. data/lib/pg/result.rb +10 -5
  35. data/lib/pg/text_decoder.rb +12 -3
  36. data/lib/pg/text_encoder.rb +8 -0
  37. data/lib/pg.rb +18 -10
  38. data/spec/helpers.rb +9 -16
  39. data/spec/pg/basic_type_mapping_spec.rb +58 -4
  40. data/spec/pg/connection_spec.rb +477 -217
  41. data/spec/pg/result_spec.rb +14 -7
  42. data/spec/pg/type_map_by_class_spec.rb +2 -2
  43. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  44. data/spec/pg/type_spec.rb +145 -33
  45. data/spec/pg_spec.rb +1 -1
  46. data.tar.gz.sig +0 -0
  47. metadata +67 -66
  48. metadata.gz.sig +0 -0
  49. data/sample/array_insert.rb +0 -20
  50. data/sample/async_api.rb +0 -106
  51. data/sample/async_copyto.rb +0 -39
  52. data/sample/async_mixed.rb +0 -56
  53. data/sample/check_conn.rb +0 -21
  54. data/sample/copyfrom.rb +0 -81
  55. data/sample/copyto.rb +0 -19
  56. data/sample/cursor.rb +0 -21
  57. data/sample/disk_usage_report.rb +0 -186
  58. data/sample/issue-119.rb +0 -94
  59. data/sample/losample.rb +0 -69
  60. data/sample/minimal-testcase.rb +0 -17
  61. data/sample/notify_wait.rb +0 -72
  62. data/sample/pg_statistics.rb +0 -294
  63. data/sample/replication_monitor.rb +0 -231
  64. data/sample/test_binary_values.rb +0 -33
  65. data/sample/wal_shipper.rb +0 -434
  66. data/sample/warehouse_partitions.rb +0 -320
data/ext/pg_copy_coder.c CHANGED
@@ -167,9 +167,15 @@ pg_copycoder_type_map_get(VALUE self)
167
167
  * conn.put_copy_data ["string2", 42, true]
168
168
  * end
169
169
  * This creates +my_table+ and inserts two rows.
170
+ *
171
+ * It is possible to manually assign a type encoder for each column per PG::TypeMapByColumn,
172
+ * or to make use of PG::BasicTypeMapBasedOnResult to assign them based on the table OIDs.
173
+ *
174
+ * See also PG::TextDecoder::CopyRow for the decoding direction with
175
+ * PG::Connection#get_copy_data .
170
176
  */
171
177
  static int
172
- pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
178
+ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
173
179
  {
174
180
  t_pg_copycoder *this = (t_pg_copycoder *)conv;
175
181
  t_pg_coder_enc_func enc_func;
@@ -184,6 +190,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
184
190
 
185
191
  /* Allocate a new string with embedded capacity and realloc exponential when needed. */
186
192
  PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
193
+ PG_ENCODING_SET_NOCHECK(*intermediate, enc_idx);
187
194
 
188
195
  for( i=0; i<RARRAY_LEN(value); i++){
189
196
  char *ptr1;
@@ -211,7 +218,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
211
218
  enc_func = pg_coder_enc_func(p_elem_coder);
212
219
 
213
220
  /* 1st pass for retiving the required memory space */
214
- strlen = enc_func(p_elem_coder, entry, NULL, &subint);
221
+ strlen = enc_func(p_elem_coder, entry, NULL, &subint, enc_idx);
215
222
 
216
223
  if( strlen == -1 ){
217
224
  /* we can directly use String value in subint */
@@ -234,7 +241,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
234
241
  PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
235
242
 
236
243
  /* Place the unescaped string at current output position. */
237
- strlen = enc_func(p_elem_coder, entry, current_out, &subint);
244
+ strlen = enc_func(p_elem_coder, entry, current_out, &subint, enc_idx);
238
245
 
239
246
  ptr1 = current_out;
240
247
  ptr2 = current_out + strlen;
@@ -301,15 +308,38 @@ GetDecimalFromHex(char hex)
301
308
  * strings by PG::TextDecoder::String.
302
309
  *
303
310
  * Example with default type map ( TypeMapAllStrings ):
311
+ * conn.exec("CREATE TABLE my_table AS VALUES('astring', 7, FALSE), ('string2', 42, TRUE) ")
312
+ *
304
313
  * deco = PG::TextDecoder::CopyRow.new
305
314
  * conn.copy_data "COPY my_table TO STDOUT", deco do
306
315
  * while row=conn.get_copy_data
307
316
  * p row
308
317
  * end
309
318
  * end
310
- * This prints all rows of +my_table+ to stdout:
319
+ * This prints all rows of +my_table+ :
311
320
  * ["astring", "7", "f"]
312
321
  * ["string2", "42", "t"]
322
+ *
323
+ * Example with column based type map:
324
+ * tm = PG::TypeMapByColumn.new( [
325
+ * PG::TextDecoder::String.new,
326
+ * PG::TextDecoder::Integer.new,
327
+ * PG::TextDecoder::Boolean.new] )
328
+ * deco = PG::TextDecoder::CopyRow.new( type_map: tm )
329
+ * conn.copy_data "COPY my_table TO STDOUT", deco do
330
+ * while row=conn.get_copy_data
331
+ * p row
332
+ * end
333
+ * end
334
+ * This prints the rows with type casted columns:
335
+ * ["astring", 7, false]
336
+ * ["string2", 42, true]
337
+ *
338
+ * Instead of manually assigning a type decoder for each column, PG::BasicTypeMapForResults
339
+ * can be used to assign them based on the table OIDs.
340
+ *
341
+ * See also PG::TextEncoder::CopyRow for the encoding direction with
342
+ * PG::Connection#put_copy_data .
313
343
  */
314
344
  /*
315
345
  * Parse the current line into separate attributes (fields),
data/ext/pg_result.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_result.c - PG::Result class extension
3
- * $Id: pg_result.c,v f23dd01bcb52 2014/11/17 10:47:53 kanis $
3
+ * $Id: pg_result.c,v 7c5d9608349f 2018/01/03 16:11:52 lars $
4
4
  *
5
5
  */
6
6
 
@@ -92,12 +92,8 @@ pg_result_check( VALUE self )
92
92
  case PGRES_TUPLES_OK:
93
93
  case PGRES_COPY_OUT:
94
94
  case PGRES_COPY_IN:
95
- #ifdef HAVE_CONST_PGRES_COPY_BOTH
96
95
  case PGRES_COPY_BOTH:
97
- #endif
98
- #ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
99
96
  case PGRES_SINGLE_TUPLE:
100
- #endif
101
97
  case PGRES_EMPTY_QUERY:
102
98
  case PGRES_COMMAND_OK:
103
99
  return self;
@@ -288,7 +284,7 @@ static void pgresult_init_fnames(VALUE self)
288
284
  *
289
285
  * Example:
290
286
  * require 'pg'
291
- * conn = PGconn.open(:dbname => 'test')
287
+ * conn = PG.connect(:dbname => 'test')
292
288
  * res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
293
289
  * res.getvalue(0,0) # '1'
294
290
  * res[0]['b'] # '2'
@@ -302,7 +298,7 @@ static void pgresult_init_fnames(VALUE self)
302
298
 
303
299
  /*
304
300
  * call-seq:
305
- * res.result_status() -> Fixnum
301
+ * res.result_status() -> Integer
306
302
  *
307
303
  * Returns the status of the query. The status value is one of:
308
304
  * * +PGRES_EMPTY_QUERY+
@@ -414,7 +410,7 @@ pgresult_error_field(VALUE self, VALUE field)
414
410
 
415
411
  /*
416
412
  * call-seq:
417
- * res.ntuples() -> Fixnum
413
+ * res.ntuples() -> Integer
418
414
  *
419
415
  * Returns the number of tuples in the query result.
420
416
  */
@@ -466,7 +462,7 @@ pgresult_fname(VALUE self, VALUE index)
466
462
 
467
463
  /*
468
464
  * call-seq:
469
- * res.fnumber( name ) -> Fixnum
465
+ * res.fnumber( name ) -> Integer
470
466
  *
471
467
  * Returns the index of the field specified by the string +name+.
472
468
  * The given +name+ is treated like an identifier in an SQL command, that is,
@@ -527,7 +523,7 @@ pgresult_ftable(VALUE self, VALUE column_number)
527
523
 
528
524
  /*
529
525
  * call-seq:
530
- * res.ftablecol( column_number ) -> Fixnum
526
+ * res.ftablecol( column_number ) -> Integer
531
527
  *
532
528
  * Returns the column number (within its table) of the table from
533
529
  * which the column _column_number_ is made up.
@@ -552,7 +548,7 @@ pgresult_ftablecol(VALUE self, VALUE column_number)
552
548
 
553
549
  /*
554
550
  * call-seq:
555
- * res.fformat( column_number ) -> Fixnum
551
+ * res.fformat( column_number ) -> Integer
556
552
  *
557
553
  * Returns the format (0 for text, 1 for binary) of column
558
554
  * _column_number_.
@@ -696,7 +692,7 @@ pgresult_getisnull(VALUE self, VALUE tup_num, VALUE field_num)
696
692
 
697
693
  /*
698
694
  * call-seq:
699
- * res.getlength( tup_num, field_num ) -> Fixnum
695
+ * res.getlength( tup_num, field_num ) -> Integer
700
696
  *
701
697
  * Returns the (String) length of the field in bytes.
702
698
  *
@@ -721,7 +717,7 @@ pgresult_getlength(VALUE self, VALUE tup_num, VALUE field_num)
721
717
 
722
718
  /*
723
719
  * call-seq:
724
- * res.nparams() -> Fixnum
720
+ * res.nparams() -> Integer
725
721
  *
726
722
  * Returns the number of parameters of a prepared statement.
727
723
  * Only useful for the result returned by conn.describePrepared
@@ -772,11 +768,17 @@ pgresult_cmd_status(VALUE self)
772
768
  * Returns the number of tuples (rows) affected by the SQL command.
773
769
  *
774
770
  * If the SQL command that generated the PG::Result was not one of:
775
- * * +INSERT+
776
- * * +UPDATE+
777
- * * +DELETE+
778
- * * +MOVE+
779
- * * +FETCH+
771
+ *
772
+ * * <tt>SELECT</tt>
773
+ * * <tt>CREATE TABLE AS</tt>
774
+ * * <tt>INSERT</tt>
775
+ * * <tt>UPDATE</tt>
776
+ * * <tt>DELETE</tt>
777
+ * * <tt>MOVE</tt>
778
+ * * <tt>FETCH</tt>
779
+ * * <tt>COPY</tt>
780
+ * * an +EXECUTE+ of a prepared query that contains an +INSERT+, +UPDATE+, or +DELETE+ statement
781
+ *
780
782
  * or if no tuples were affected, <tt>0</tt> is returned.
781
783
  */
782
784
  static VALUE
@@ -863,7 +865,7 @@ pgresult_each_row(VALUE self)
863
865
  num_fields = PQnfields(this->pgresult);
864
866
 
865
867
  for ( row = 0; row < num_rows; row++ ) {
866
- VALUE row_values[num_fields];
868
+ PG_VARIABLE_LENGTH_ARRAY(VALUE, row_values, num_fields, PG_MAX_COLUMNS)
867
869
 
868
870
  /* populate the row */
869
871
  for ( field = 0; field < num_fields; field++ ) {
@@ -892,7 +894,7 @@ pgresult_values(VALUE self)
892
894
  VALUE results = rb_ary_new2( num_rows );
893
895
 
894
896
  for ( row = 0; row < num_rows; row++ ) {
895
- VALUE row_values[num_fields];
897
+ PG_VARIABLE_LENGTH_ARRAY(VALUE, row_values, num_fields, PG_MAX_COLUMNS)
896
898
 
897
899
  /* populate the row */
898
900
  for ( field = 0; field < num_fields; field++ ) {
@@ -1050,7 +1052,6 @@ pgresult_type_map_get(VALUE self)
1050
1052
  return this->typemap;
1051
1053
  }
1052
1054
 
1053
- #ifdef HAVE_PQSETSINGLEROWMODE
1054
1055
  /*
1055
1056
  * call-seq:
1056
1057
  * res.stream_each{ |tuple| ... }
@@ -1081,6 +1082,8 @@ pgresult_type_map_get(VALUE self)
1081
1082
  * # do something with the received row of the second query
1082
1083
  * end
1083
1084
  * conn.get_result # => nil (no more results)
1085
+ *
1086
+ * Available since PostgreSQL-9.2
1084
1087
  */
1085
1088
  static VALUE
1086
1089
  pgresult_stream_each(VALUE self)
@@ -1144,6 +1147,8 @@ pgresult_stream_each(VALUE self)
1144
1147
  *
1145
1148
  * This method works equally to #stream_each , but yields an Array of
1146
1149
  * values.
1150
+ *
1151
+ * Available since PostgreSQL-9.2
1147
1152
  */
1148
1153
  static VALUE
1149
1154
  pgresult_stream_each_row(VALUE self)
@@ -1176,7 +1181,7 @@ pgresult_stream_each_row(VALUE self)
1176
1181
  }
1177
1182
 
1178
1183
  for ( row = 0; row < ntuples; row++ ) {
1179
- VALUE row_values[nfields];
1184
+ PG_VARIABLE_LENGTH_ARRAY(VALUE, row_values, nfields, PG_MAX_COLUMNS)
1180
1185
  int field;
1181
1186
 
1182
1187
  /* populate the row */
@@ -1204,7 +1209,6 @@ pgresult_stream_each_row(VALUE self)
1204
1209
  /* never reached */
1205
1210
  return self;
1206
1211
  }
1207
- #endif
1208
1212
 
1209
1213
 
1210
1214
  void
@@ -1261,11 +1265,9 @@ init_pg_result()
1261
1265
  rb_define_method(rb_cPGresult, "type_map=", pgresult_type_map_set, 1);
1262
1266
  rb_define_method(rb_cPGresult, "type_map", pgresult_type_map_get, 0);
1263
1267
 
1264
- #ifdef HAVE_PQSETSINGLEROWMODE
1265
1268
  /****** PG::Result INSTANCE METHODS: streaming ******/
1266
1269
  rb_define_method(rb_cPGresult, "stream_each", pgresult_stream_each, 0);
1267
1270
  rb_define_method(rb_cPGresult, "stream_each_row", pgresult_stream_each_row, 0);
1268
- #endif
1269
1271
  }
1270
1272
 
1271
1273
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_text_decoder.c - PG::TextDecoder module
3
- * $Id: pg_text_decoder.c,v b7f9daeeba29 2014/11/21 19:53:47 lars $
3
+ * $Id: pg_text_decoder.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
4
4
  *
5
5
  */
6
6
 
@@ -30,7 +30,9 @@
30
30
 
31
31
  #include "pg.h"
32
32
  #include "util.h"
33
+ #ifdef HAVE_INTTYPES_H
33
34
  #include <inttypes.h>
35
+ #endif
34
36
 
35
37
  VALUE rb_mPG_TextDecoder;
36
38
  static ID s_id_decode;
@@ -293,7 +295,7 @@ pg_text_dec_array(t_pg_coder *conv, char *val, int len, int tuple, int field, in
293
295
  }
294
296
 
295
297
  /*
296
- * Document-class: PG::TextDecoder::Identifier < PG::CompositeDecoder
298
+ * Document-class: PG::TextDecoder::Identifier < PG::SimpleDecoder
297
299
  *
298
300
  * This is the decoder class for PostgreSQL identifiers.
299
301
  *
@@ -305,16 +307,13 @@ pg_text_dec_array(t_pg_coder *conv, char *val, int len, int tuple, int field, in
305
307
  static VALUE
306
308
  pg_text_dec_identifier(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
307
309
  {
308
- t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
309
- t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, 0);
310
-
311
310
  /* Return value: array */
312
311
  VALUE array;
313
312
  VALUE elem;
314
313
  int word_index = 0;
315
314
  int index;
316
315
  /* Use a buffer of the same length, as that will be the worst case */
317
- char word[len + 1];
316
+ PG_VARIABLE_LENGTH_ARRAY(char, word, len + 1, NAMEDATALEN)
318
317
 
319
318
  /* The current character in the input string. */
320
319
  char c;
@@ -331,7 +330,7 @@ pg_text_dec_identifier(t_pg_coder *conv, char *val, int len, int tuple, int fiel
331
330
  if(c == '.' && openQuote < 2 ) {
332
331
  word[word_index] = 0;
333
332
 
334
- elem = dec_func(conv, word, word_index, tuple, field, enc_idx);
333
+ elem = pg_text_dec_string(conv, word, word_index, tuple, field, enc_idx);
335
334
  rb_ary_push(array, elem);
336
335
 
337
336
  openQuote = 0;
@@ -353,7 +352,7 @@ pg_text_dec_identifier(t_pg_coder *conv, char *val, int len, int tuple, int fiel
353
352
  }
354
353
 
355
354
  word[word_index] = 0;
356
- elem = dec_func(conv, word, word_index, tuple, field, enc_idx);
355
+ elem = pg_text_dec_string(conv, word, word_index, tuple, field, enc_idx);
357
356
  rb_ary_push(array, elem);
358
357
 
359
358
  return array;
@@ -412,11 +411,11 @@ init_pg_text_decoder()
412
411
  pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
413
412
  /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
414
413
  pg_define_coder( "Bytea", pg_text_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
414
+ /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Identifier", rb_cPG_SimpleDecoder ); */
415
+ pg_define_coder( "Identifier", pg_text_dec_identifier, rb_cPG_SimpleDecoder, rb_mPG_TextDecoder );
415
416
 
416
417
  /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Array", rb_cPG_CompositeDecoder ); */
417
418
  pg_define_coder( "Array", pg_text_dec_array, rb_cPG_CompositeDecoder, rb_mPG_TextDecoder );
418
- /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Identifier", rb_cPG_CompositeDecoder ); */
419
- pg_define_coder( "Identifier", pg_text_dec_identifier, rb_cPG_CompositeDecoder, rb_mPG_TextDecoder );
420
419
  /* dummy = rb_define_class_under( rb_mPG_TextDecoder, "FromBase64", rb_cPG_CompositeDecoder ); */
421
420
  pg_define_coder( "FromBase64", pg_text_dec_from_base64, rb_cPG_CompositeDecoder, rb_mPG_TextDecoder );
422
421
  }