pg 0.17.1 → 0.18.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/ChangeLog +2407 -2
  4. data/History.rdoc +68 -0
  5. data/Manifest.txt +29 -1
  6. data/README-Windows.rdoc +15 -26
  7. data/README.rdoc +52 -2
  8. data/Rakefile +56 -18
  9. data/Rakefile.cross +77 -49
  10. data/ext/extconf.rb +33 -26
  11. data/ext/pg.c +142 -21
  12. data/ext/pg.h +242 -6
  13. data/ext/pg_binary_decoder.c +162 -0
  14. data/ext/pg_binary_encoder.c +162 -0
  15. data/ext/pg_coder.c +479 -0
  16. data/ext/pg_connection.c +858 -553
  17. data/ext/pg_copy_coder.c +561 -0
  18. data/ext/pg_errors.c +6 -0
  19. data/ext/pg_result.c +479 -128
  20. data/ext/pg_text_decoder.c +421 -0
  21. data/ext/pg_text_encoder.c +663 -0
  22. data/ext/pg_type_map.c +159 -0
  23. data/ext/pg_type_map_all_strings.c +116 -0
  24. data/ext/pg_type_map_by_class.c +239 -0
  25. data/ext/pg_type_map_by_column.c +312 -0
  26. data/ext/pg_type_map_by_mri_type.c +284 -0
  27. data/ext/pg_type_map_by_oid.c +355 -0
  28. data/ext/pg_type_map_in_ruby.c +299 -0
  29. data/ext/util.c +149 -0
  30. data/ext/util.h +65 -0
  31. data/lib/pg/basic_type_mapping.rb +399 -0
  32. data/lib/pg/coder.rb +83 -0
  33. data/lib/pg/connection.rb +81 -29
  34. data/lib/pg/result.rb +13 -3
  35. data/lib/pg/text_decoder.rb +44 -0
  36. data/lib/pg/text_encoder.rb +27 -0
  37. data/lib/pg/type_map_by_column.rb +15 -0
  38. data/lib/pg.rb +12 -2
  39. data/spec/{lib/helpers.rb → helpers.rb} +101 -39
  40. data/spec/pg/basic_type_mapping_spec.rb +251 -0
  41. data/spec/pg/connection_spec.rb +516 -218
  42. data/spec/pg/result_spec.rb +216 -112
  43. data/spec/pg/type_map_by_class_spec.rb +138 -0
  44. data/spec/pg/type_map_by_column_spec.rb +222 -0
  45. data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
  46. data/spec/pg/type_map_by_oid_spec.rb +149 -0
  47. data/spec/pg/type_map_in_ruby_spec.rb +164 -0
  48. data/spec/pg/type_map_spec.rb +22 -0
  49. data/spec/pg/type_spec.rb +697 -0
  50. data/spec/pg_spec.rb +24 -18
  51. data.tar.gz.sig +0 -0
  52. metadata +111 -45
  53. metadata.gz.sig +0 -0
data/ext/extconf.rb CHANGED
@@ -15,36 +15,35 @@ if pgdir = with_config( 'pg' )
15
15
  ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
16
16
  end
17
17
 
18
- if ENV['CROSS_COMPILING']
19
- $LDFLAGS << " -L#{CONFIG['libdir']}"
20
-
21
- # Link against all required libraries for static build, if they are available
22
- have_library( 'crypt32', 'CertOpenStore' ) && append_library( $libs, 'crypt32' )
23
- have_library( 'gdi32', 'CreateDC' ) && append_library( $libs, 'gdi32' )
24
- have_library( 'secur32' ) && append_library( $libs, 'secur32' )
25
- have_library( 'ws2_32', 'WSASocket') && append_library( $libs, 'ws2_32' )
26
- have_library( 'crypto', 'BIO_new' ) && append_library( $libs, 'crypto' )
27
- have_library( 'ssl', 'SSL_new' ) && append_library( $libs, 'ssl' )
28
- end
18
+ if enable_config("windows-cross")
19
+ # Avoid dependency to external libgcc.dll on x86-mingw32
20
+ $LDFLAGS << " -static-libgcc"
21
+ # Don't use pg_config for cross build, but --with-pg-* path options
22
+ dir_config 'pg'
29
23
 
30
- if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
31
- $stderr.puts "Using config values from %s" % [ pgconfig ]
32
- incdir = `"#{pgconfig}" --includedir`.chomp
33
- libdir = `"#{pgconfig}" --libdir`.chomp
34
- dir_config 'pg', incdir, libdir
35
-
36
- # Try to use runtime path linker option, even if RbConfig doesn't know about it.
37
- # The rpath option is usually set implicit by dir_config(), but so far not
38
- # on MacOS-X.
39
- if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
40
- $LDFLAGS << " -Wl,-rpath,#{libdir}"
41
- end
42
24
  else
43
- $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
44
- " --with-pg-config=/path/to/pg_config"
45
- dir_config 'pg'
25
+ # Native build
26
+
27
+ if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
28
+ $stderr.puts "Using config values from %s" % [ pgconfig ]
29
+ incdir = `"#{pgconfig}" --includedir`.chomp
30
+ libdir = `"#{pgconfig}" --libdir`.chomp
31
+ dir_config 'pg', incdir, libdir
32
+
33
+ # Try to use runtime path linker option, even if RbConfig doesn't know about it.
34
+ # The rpath option is usually set implicit by dir_config(), but so far not
35
+ # on MacOS-X.
36
+ if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
37
+ $LDFLAGS << " -Wl,-rpath,#{libdir}"
38
+ end
39
+ else
40
+ $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
41
+ " --with-pg-config=/path/to/pg_config"
42
+ dir_config 'pg'
43
+ end
46
44
  end
47
45
 
46
+
48
47
  find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
49
48
  find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
50
49
  find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
@@ -73,6 +72,7 @@ have_func 'PQsetClientEncoding'
73
72
  have_func 'PQlibVersion'
74
73
  have_func 'PQping'
75
74
  have_func 'PQsetSingleRowMode'
75
+ have_func 'PQconninfo'
76
76
 
77
77
  have_func 'rb_encdb_alias'
78
78
  have_func 'rb_enc_alias'
@@ -80,6 +80,8 @@ have_func 'rb_thread_call_without_gvl'
80
80
  have_func 'rb_thread_call_with_gvl'
81
81
  have_func 'rb_thread_fd_select'
82
82
  have_func 'rb_w32_wrap_io_handle'
83
+ have_func 'rb_str_modify_expand'
84
+ have_func 'rb_hash_dup'
83
85
 
84
86
  have_const 'PGRES_COPY_BOTH', 'libpq-fe.h'
85
87
  have_const 'PGRES_SINGLE_TUPLE', 'libpq-fe.h'
@@ -90,8 +92,13 @@ $defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
90
92
 
91
93
  # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
92
94
  have_header 'unistd.h'
95
+ have_header 'inttypes.h'
93
96
  have_header 'ruby/st.h' or have_header 'st.h' or abort "pg currently requires the ruby/st.h header"
94
97
 
98
+ checking_for "C99 variable length arrays" do
99
+ $defs.push( "-DHAVE_VARIABLE_LENGTH_ARRAYS" ) if try_compile('void test_vla(int l){ int vla[l]; }')
100
+ end
101
+
95
102
  create_header()
96
103
  create_makefile( "pg_ext" )
97
104
 
data/ext/pg.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg.c - Toplevel extension
3
- * $Id: pg.c,v 74aa9514a381 2013/05/18 17:29:19 lars $
3
+ * $Id: pg.c,v b60c89ee93c8 2015/02/11 20:59:36 lars $
4
4
  *
5
5
  * Author/s:
6
6
  *
@@ -15,7 +15,7 @@
15
15
  * See Contributors.rdoc for the many additional fine people that have contributed
16
16
  * to this library over the years.
17
17
  *
18
- * Copyright (c) 1997-2012 by the authors.
18
+ * Copyright (c) 1997-2015 by the authors.
19
19
  *
20
20
  * You may redistribute this software under the same terms as Ruby itself; see
21
21
  * http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
@@ -123,24 +123,6 @@ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
123
123
  * A cache of mapping from PostgreSQL's encoding indices to Ruby's rb_encoding*s.
124
124
  */
125
125
  static struct st_table *enc_pg2ruby;
126
- static ID s_id_index;
127
-
128
-
129
- /*
130
- * Get the index of encoding +val+.
131
- * :FIXME: Look into replacing this with rb_enc_get_index() since 1.9.1 isn't really
132
- * used anymore.
133
- */
134
- int
135
- pg_enc_get_index(VALUE val)
136
- {
137
- int i = ENCODING_GET_INLINED(val);
138
- if (i == ENCODING_INLINE_MAX) {
139
- VALUE iv = rb_ivar_get(val, s_id_index);
140
- i = NUM2INT(iv);
141
- }
142
- return i;
143
- }
144
126
 
145
127
 
146
128
  /*
@@ -249,6 +231,68 @@ pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
249
231
  #endif /* M17N_SUPPORTED */
250
232
 
251
233
 
234
+ /*
235
+ * Ensures that the given string has enough capacity to take expand_len
236
+ * more data bytes. The new data part of the String is not initialized.
237
+ *
238
+ * current_out must be a pointer within the data part of the String object.
239
+ * This pointer is returned and possibly adjusted, because the location of the data
240
+ * part of the String can change through this function.
241
+ *
242
+ * PG_RB_STR_ENSURE_CAPA can be used to do fast inline checks of the remaining capacity.
243
+ * end_capa it is then set to the first byte after the currently reserved memory,
244
+ * if not NULL.
245
+ *
246
+ * Before the String can be used with other string functions or returned to Ruby space,
247
+ * the string length has to be set with rb_str_set_len().
248
+ *
249
+ * Usage example:
250
+ *
251
+ * VALUE string;
252
+ * char *current_out, *end_capa;
253
+ * PG_RB_STR_NEW( string, current_out, end_capa );
254
+ * while( data_is_going_to_be_processed ){
255
+ * PG_RB_STR_ENSURE_CAPA( string, 2, current_out, end_capa );
256
+ * *current_out++ = databyte1;
257
+ * *current_out++ = databyte2;
258
+ * }
259
+ * rb_str_set_len( string, current_out - RSTRING_PTR(string) );
260
+ *
261
+ */
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;
292
+ }
293
+ #endif
294
+
295
+
252
296
  /**************************************************************************
253
297
  * Module Methods
254
298
  **************************************************************************/
@@ -289,6 +333,67 @@ pg_s_threadsafe_p(VALUE self)
289
333
  return PQisthreadsafe() ? Qtrue : Qfalse;
290
334
  }
291
335
 
336
+ static int
337
+ pg_to_bool_int(VALUE value)
338
+ {
339
+ switch( TYPE(value) ){
340
+ case T_FALSE:
341
+ return 0;
342
+ case T_TRUE:
343
+ return 1;
344
+ default:
345
+ return NUM2INT(value);
346
+ }
347
+ }
348
+
349
+ /*
350
+ * call-seq:
351
+ * PG.init_openssl(do_ssl, do_crypto) -> nil
352
+ *
353
+ * Allows applications to select which security libraries to initialize.
354
+ *
355
+ * If your application initializes libssl and/or libcrypto libraries and libpq is
356
+ * built with SSL support, you should call PG.init_openssl() to tell libpq that the
357
+ * libssl and/or libcrypto libraries have been initialized by your application,
358
+ * so that libpq will not also initialize those libraries. See
359
+ * http://h71000.www7.hp.com/doc/83final/BA554_90007/ch04.html for details on the SSL API.
360
+ *
361
+ * When do_ssl is +true+, libpq will initialize the OpenSSL library before first
362
+ * opening a database connection. When do_crypto is +true+, the libcrypto library
363
+ * will be initialized. By default (if PG.init_openssl() is not called), both libraries
364
+ * are initialized. When SSL support is not compiled in, this function is present but does nothing.
365
+ *
366
+ * If your application uses and initializes either OpenSSL or its underlying libcrypto library,
367
+ * you must call this function with +false+ for the appropriate parameter(s) before first opening
368
+ * a database connection. Also be sure that you have done that initialization before opening a
369
+ * database connection.
370
+ *
371
+ */
372
+ static VALUE
373
+ pg_s_init_openssl(VALUE self, VALUE do_ssl, VALUE do_crypto)
374
+ {
375
+ UNUSED( self );
376
+ PQinitOpenSSL(pg_to_bool_int(do_ssl), pg_to_bool_int(do_crypto));
377
+ return Qnil;
378
+ }
379
+
380
+
381
+ /*
382
+ * call-seq:
383
+ * PG.init_ssl(do_ssl) -> nil
384
+ *
385
+ * Allows applications to select which security libraries to initialize.
386
+ *
387
+ * This function is equivalent to <tt>PG.init_openssl(do_ssl, do_ssl)</tt> . It is sufficient for
388
+ * applications that initialize both or neither of OpenSSL and libcrypto.
389
+ */
390
+ static VALUE
391
+ pg_s_init_ssl(VALUE self, VALUE do_ssl)
392
+ {
393
+ UNUSED( self );
394
+ PQinitSSL(pg_to_bool_int(do_ssl));
395
+ return Qnil;
396
+ }
292
397
 
293
398
 
294
399
  /**************************************************************************
@@ -311,6 +416,10 @@ Init_pg_ext()
311
416
  SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
312
417
  SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
313
418
 
419
+ rb_define_singleton_method( rb_mPG, "init_openssl", pg_s_init_openssl, 2 );
420
+ rb_define_singleton_method( rb_mPG, "init_ssl", pg_s_init_ssl, 1 );
421
+
422
+
314
423
  /****** PG::Connection CLASS CONSTANTS: Connection Status ******/
315
424
 
316
425
  /* Connection succeeded */
@@ -534,12 +643,24 @@ Init_pg_ext()
534
643
 
535
644
  #ifdef M17N_SUPPORTED
536
645
  enc_pg2ruby = st_init_numtable();
537
- s_id_index = rb_intern("@encoding");
538
646
  #endif
539
647
 
540
648
  /* Initialize the main extension classes */
541
649
  init_pg_connection();
542
650
  init_pg_result();
543
651
  init_pg_errors();
652
+ init_pg_type_map();
653
+ init_pg_type_map_all_strings();
654
+ init_pg_type_map_by_class();
655
+ init_pg_type_map_by_column();
656
+ init_pg_type_map_by_mri_type();
657
+ init_pg_type_map_by_oid();
658
+ init_pg_type_map_in_ruby();
659
+ init_pg_coder();
660
+ init_pg_text_encoder();
661
+ init_pg_text_decoder();
662
+ init_pg_binary_encoder();
663
+ init_pg_binary_decoder();
664
+ init_pg_copycoder();
544
665
  }
545
666
 
data/ext/pg.h CHANGED
@@ -24,7 +24,6 @@
24
24
  #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
25
25
  # include "ruby/encoding.h"
26
26
  # define M17N_SUPPORTED
27
- # define ASSOCIATE_INDEX( obj, index_holder ) rb_enc_associate_index((obj), pg_enc_get_index((index_holder)))
28
27
  # ifdef HAVE_RB_ENCDB_ALIAS
29
28
  extern int rb_encdb_alias(const char *, const char *);
30
29
  # define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
@@ -35,8 +34,28 @@
35
34
  extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
36
35
  # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
37
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) \
49
+ do { \
50
+ if ((i) < ENCODING_INLINE_MAX) \
51
+ ENCODING_SET_INLINED((obj), (i)); \
52
+ else \
53
+ rb_enc_set_index((obj), (i)); \
54
+ } while(0)
55
+ # endif
56
+
38
57
  #else
39
- # define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
58
+ # define PG_ENCODING_SET_NOCHECK(obj,i) /* nothing */
40
59
  #endif
41
60
 
42
61
  #if RUBY_VM != 1
@@ -66,6 +85,20 @@
66
85
  # include "ruby/io.h"
67
86
  #endif
68
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
101
+
69
102
  #ifndef timeradd
70
103
  #define timeradd(a, b, result) \
71
104
  do { \
@@ -97,10 +130,126 @@
97
130
 
98
131
  #if defined(_WIN32)
99
132
  # include <fcntl.h>
100
- __declspec(dllexport)
101
133
  typedef long suseconds_t;
102
134
  #endif
103
135
 
136
+ #if defined(HAVE_VARIABLE_LENGTH_ARRAYS)
137
+ #define PG_VARIABLE_LENGTH_ARRAY(type, name, len, maxlen) type name[(len)];
138
+ #else
139
+ #define PG_VARIABLE_LENGTH_ARRAY(type, name, len, maxlen) \
140
+ type name[(maxlen)] = {(len)>(maxlen) ? (rb_raise(rb_eArgError, "Number of " #name " (%d) exceeds allowed maximum of " #maxlen, (len) ), (type)1) : (type)0};
141
+
142
+ #define PG_MAX_COLUMNS 4000
143
+ #endif
144
+
145
+ /* The data behind each PG::Connection object */
146
+ typedef struct {
147
+ PGconn *pgconn;
148
+
149
+ /* Cached IO object for the socket descriptor */
150
+ VALUE socket_io;
151
+ /* Proc object that receives notices as PG::Result objects */
152
+ VALUE notice_receiver;
153
+ /* Proc object that receives notices as String objects */
154
+ VALUE notice_processor;
155
+ /* Kind of PG::TypeMap object for casting query params */
156
+ VALUE type_map_for_queries;
157
+ /* Kind of PG::TypeMap object for casting result values */
158
+ VALUE type_map_for_results;
159
+ /* IO object internally used for the trace stream */
160
+ VALUE trace_stream;
161
+ /* Cached Encoding object */
162
+ VALUE external_encoding;
163
+ /* Kind of PG::Coder object for casting ruby values to COPY rows */
164
+ VALUE encoder_for_put_copy_data;
165
+ /* Kind of PG::Coder object for casting COPY rows to ruby values */
166
+ VALUE decoder_for_get_copy_data;
167
+
168
+ } t_pg_connection;
169
+
170
+ typedef struct pg_coder t_pg_coder;
171
+ typedef struct pg_typemap t_typemap;
172
+
173
+ /* The data behind each PG::Result object */
174
+ typedef struct {
175
+ PGresult *pgresult;
176
+
177
+ /* The connection object used to build this result */
178
+ VALUE connection;
179
+
180
+ /* The TypeMap used to type cast result values */
181
+ VALUE typemap;
182
+
183
+ /* Pointer to the typemap object data. This is assumed to be
184
+ * always valid.
185
+ */
186
+ t_typemap *p_typemap;
187
+
188
+ /* 0 = PGresult is cleared by PG::Result#clear or by the GC
189
+ * 1 = PGresult is cleared internally by libpq
190
+ */
191
+ int autoclear;
192
+
193
+ /* Number of fields in fnames[] .
194
+ * Set to -1 if fnames[] is not yet initialized.
195
+ */
196
+ int nfields;
197
+
198
+ /* Prefilled tuple Hash with fnames[] as keys. */
199
+ VALUE tuple_hash;
200
+
201
+ /* List of field names as frozen String objects.
202
+ * Only valid if nfields != -1
203
+ */
204
+ VALUE fnames[0];
205
+ } t_pg_result;
206
+
207
+
208
+ typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
209
+ typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
210
+ typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
211
+ typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
212
+ typedef int (* t_pg_fit_to_copy_get)(VALUE);
213
+ typedef VALUE (* t_pg_typecast_result)(t_typemap *, VALUE, int, int);
214
+ typedef t_pg_coder *(* t_pg_typecast_query_param)(t_typemap *, VALUE, int);
215
+ typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
216
+
217
+ struct pg_coder {
218
+ t_pg_coder_enc_func enc_func;
219
+ t_pg_coder_dec_func dec_func;
220
+ VALUE coder_obj;
221
+ Oid oid;
222
+ int format;
223
+ };
224
+
225
+ typedef struct {
226
+ t_pg_coder comp;
227
+ t_pg_coder *elem;
228
+ int needs_quotation;
229
+ char delimiter;
230
+ } t_pg_composite_coder;
231
+
232
+ struct pg_typemap {
233
+ struct pg_typemap_funcs {
234
+ t_pg_fit_to_result fit_to_result;
235
+ t_pg_fit_to_query fit_to_query;
236
+ t_pg_fit_to_copy_get fit_to_copy_get;
237
+ t_pg_typecast_result typecast_result_value;
238
+ t_pg_typecast_query_param typecast_query_param;
239
+ t_pg_typecast_copy_get typecast_copy_get;
240
+ } funcs;
241
+ VALUE default_typemap;
242
+ };
243
+
244
+ typedef struct {
245
+ t_typemap typemap;
246
+ int nfields;
247
+ struct pg_tmbc_converter {
248
+ t_pg_coder *cconv;
249
+ } convs[0];
250
+ } t_tmbc;
251
+
252
+
104
253
  #include "gvl_wrappers.h"
105
254
 
106
255
  /***************************************************************************
@@ -112,11 +261,33 @@ extern VALUE rb_ePGerror;
112
261
  extern VALUE rb_eServerError;
113
262
  extern VALUE rb_eUnableToSend;
114
263
  extern VALUE rb_eConnectionBad;
264
+ extern VALUE rb_eInvalidResultStatus;
265
+ extern VALUE rb_eNoResultError;
266
+ extern VALUE rb_eInvalidChangeOfResultFields;
115
267
  extern VALUE rb_mPGconstants;
116
268
  extern VALUE rb_cPGconn;
117
269
  extern VALUE rb_cPGresult;
118
270
  extern VALUE rb_hErrors;
271
+ extern VALUE rb_cTypeMap;
272
+ extern VALUE rb_cTypeMapAllStrings;
273
+ extern VALUE rb_mDefaultTypeMappable;
274
+ extern VALUE rb_cPG_Coder;
275
+ extern VALUE rb_cPG_SimpleEncoder;
276
+ extern VALUE rb_cPG_SimpleDecoder;
277
+ extern VALUE rb_cPG_CompositeEncoder;
278
+ extern VALUE rb_cPG_CompositeDecoder;
279
+ extern VALUE rb_cPG_CopyCoder;
280
+ extern VALUE rb_cPG_CopyEncoder;
281
+ extern VALUE rb_cPG_CopyDecoder;
282
+ extern VALUE rb_mPG_TextEncoder;
283
+ extern VALUE rb_mPG_TextDecoder;
284
+ extern VALUE rb_mPG_BinaryEncoder;
285
+ extern VALUE rb_mPG_BinaryDecoder;
286
+ extern VALUE rb_mPG_BinaryFormatting;
287
+ extern const struct pg_typemap_funcs pg_tmbc_funcs;
288
+ extern const struct pg_typemap_funcs pg_typemap_funcs;
119
289
 
290
+ extern VALUE pg_typemap_all_strings;
120
291
 
121
292
  /***************************************************************************
122
293
  * MACROS
@@ -134,19 +305,84 @@ void Init_pg_ext _(( void ));
134
305
  void init_pg_connection _(( void ));
135
306
  void init_pg_result _(( void ));
136
307
  void init_pg_errors _(( void ));
137
- VALUE lookup_error_class _(( const char *sqlstate ));
308
+ void init_pg_type_map _(( void ));
309
+ void init_pg_type_map_all_strings _(( void ));
310
+ void init_pg_type_map_by_class _(( void ));
311
+ void init_pg_type_map_by_column _(( void ));
312
+ void init_pg_type_map_by_mri_type _(( void ));
313
+ void init_pg_type_map_by_oid _(( void ));
314
+ void init_pg_type_map_in_ruby _(( void ));
315
+ void init_pg_coder _(( void ));
316
+ void init_pg_copycoder _(( void ));
317
+ void init_pg_text_encoder _(( void ));
318
+ void init_pg_text_decoder _(( void ));
319
+ void init_pg_binary_encoder _(( void ));
320
+ void init_pg_binary_decoder _(( void ));
321
+ VALUE lookup_error_class _(( const char * ));
322
+ VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
323
+ VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
324
+ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *));
325
+ int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *));
326
+ t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
327
+ t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
328
+ void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
329
+ VALUE pg_obj_to_i _(( VALUE ));
330
+ VALUE pg_tmbc_allocate _(( void ));
331
+ void pg_coder_init_encoder _(( VALUE ));
332
+ void pg_coder_init_decoder _(( VALUE ));
333
+ char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
334
+
335
+ #define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
336
+ do { \
337
+ if( (curr_ptr) + (expand_len) >= (end_ptr) ) \
338
+ (curr_ptr) = pg_rb_str_ensure_capa( (str), (expand_len), (curr_ptr), &(end_ptr) ); \
339
+ } while(0);
340
+
341
+ #define PG_RB_STR_NEW( str, curr_ptr, end_ptr ) ( \
342
+ (str) = rb_str_new( NULL, 0 ), \
343
+ (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
344
+ )
345
+
346
+ #define PG_RB_TAINTED_STR_NEW( str, curr_ptr, end_ptr ) ( \
347
+ (str) = rb_tainted_str_new( NULL, 0 ), \
348
+ (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
349
+ )
138
350
 
139
- PGconn *pg_get_pgconn _(( VALUE ));
351
+ VALUE pg_typemap_fit_to_result _(( VALUE, VALUE ));
352
+ VALUE pg_typemap_fit_to_query _(( VALUE, VALUE ));
353
+ int pg_typemap_fit_to_copy_get _(( VALUE ));
354
+ VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
355
+ t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
356
+ VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
357
+
358
+ PGconn *pg_get_pgconn _(( VALUE ));
359
+ t_pg_connection *pg_get_connection _(( VALUE ));
140
360
 
141
361
  VALUE pg_new_result _(( PGresult *, VALUE ));
362
+ VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
363
+ PGresult* pgresult_get _(( VALUE ));
142
364
  VALUE pg_result_check _(( VALUE ));
143
365
  VALUE pg_result_clear _(( VALUE ));
144
366
 
367
+ /*
368
+ * Fetch the data pointer for the result object
369
+ */
370
+ static inline t_pg_result *
371
+ pgresult_get_this( VALUE self )
372
+ {
373
+ t_pg_result *this = DATA_PTR(self);
374
+
375
+ if( this == NULL )
376
+ rb_raise(rb_ePGerror, "result has been cleared");
377
+
378
+ return this;
379
+ }
380
+
381
+
145
382
  #ifdef M17N_SUPPORTED
146
383
  rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
147
384
  rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
148
385
  const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
149
- int pg_enc_get_index _(( VALUE ));
150
386
  rb_encoding *pg_conn_enc_get _(( PGconn * ));
151
387
  #endif /* M17N_SUPPORTED */
152
388