pg 0.17.1 → 0.18.4
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ChangeLog +2407 -2
- data/History.rdoc +68 -0
- data/Manifest.txt +29 -1
- data/README-Windows.rdoc +15 -26
- data/README.rdoc +52 -2
- data/Rakefile +56 -18
- data/Rakefile.cross +77 -49
- data/ext/extconf.rb +33 -26
- data/ext/pg.c +142 -21
- data/ext/pg.h +242 -6
- data/ext/pg_binary_decoder.c +162 -0
- data/ext/pg_binary_encoder.c +162 -0
- data/ext/pg_coder.c +479 -0
- data/ext/pg_connection.c +858 -553
- data/ext/pg_copy_coder.c +561 -0
- data/ext/pg_errors.c +6 -0
- data/ext/pg_result.c +479 -128
- data/ext/pg_text_decoder.c +421 -0
- data/ext/pg_text_encoder.c +663 -0
- data/ext/pg_type_map.c +159 -0
- data/ext/pg_type_map_all_strings.c +116 -0
- data/ext/pg_type_map_by_class.c +239 -0
- data/ext/pg_type_map_by_column.c +312 -0
- data/ext/pg_type_map_by_mri_type.c +284 -0
- data/ext/pg_type_map_by_oid.c +355 -0
- data/ext/pg_type_map_in_ruby.c +299 -0
- data/ext/util.c +149 -0
- data/ext/util.h +65 -0
- data/lib/pg/basic_type_mapping.rb +399 -0
- data/lib/pg/coder.rb +83 -0
- data/lib/pg/connection.rb +81 -29
- data/lib/pg/result.rb +13 -3
- data/lib/pg/text_decoder.rb +44 -0
- data/lib/pg/text_encoder.rb +27 -0
- data/lib/pg/type_map_by_column.rb +15 -0
- data/lib/pg.rb +12 -2
- data/spec/{lib/helpers.rb → helpers.rb} +101 -39
- data/spec/pg/basic_type_mapping_spec.rb +251 -0
- data/spec/pg/connection_spec.rb +516 -218
- data/spec/pg/result_spec.rb +216 -112
- data/spec/pg/type_map_by_class_spec.rb +138 -0
- data/spec/pg/type_map_by_column_spec.rb +222 -0
- data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
- data/spec/pg/type_map_by_oid_spec.rb +149 -0
- data/spec/pg/type_map_in_ruby_spec.rb +164 -0
- data/spec/pg/type_map_spec.rb +22 -0
- data/spec/pg/type_spec.rb +697 -0
- data/spec/pg_spec.rb +24 -18
- data.tar.gz.sig +0 -0
- metadata +111 -45
- 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
|
19
|
-
|
20
|
-
|
21
|
-
#
|
22
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
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
|
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-
|
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
|
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
|
-
|
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
|
-
|
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
|
|