pg 0.9.0-x86-mingw32 → 0.11.0pre229-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -0
- data/ChangeLog +214 -1
- data/Contributors +2 -0
- data/README +2 -2
- data/README.windows +7 -4
- data/Rakefile +51 -29
- data/Rakefile.local +229 -160
- data/ext/compat.c +2 -2
- data/ext/compat.h +4 -0
- data/ext/extconf.rb +27 -94
- data/ext/pg.c +300 -121
- data/ext/pg.h +4 -0
- data/lib/1.8/pg_ext.so +0 -0
- data/lib/1.9/pg_ext.so +0 -0
- data/lib/pg.rb +11 -6
- data/rake/documentation.rb +123 -0
- data/rake/helpers.rb +375 -308
- data/rake/hg.rb +51 -6
- data/rake/manual.rb +11 -6
- data/rake/packaging.rb +7 -1
- data/rake/publishing.rb +158 -91
- data/rake/testing.rb +53 -88
- data/spec/lib/helpers.rb +40 -18
- data/spec/m17n_spec.rb +36 -24
- data/spec/pgconn_spec.rb +276 -20
- data/spec/pgresult_spec.rb +12 -6
- metadata +61 -20
- metadata.gz.sig +0 -0
- data/rake/rdoc.rb +0 -30
data/ext/compat.c
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
Author: ematsu
|
9
9
|
modified at: Wed Jan 20 16:41:51 1999
|
10
10
|
|
11
|
-
$Author:
|
12
|
-
$Date:
|
11
|
+
$Author: ged $
|
12
|
+
$Date: 2010/10/31 23:29:59 $
|
13
13
|
************************************************/
|
14
14
|
|
15
15
|
#include <ctype.h>
|
data/ext/compat.h
CHANGED
data/ext/extconf.rb
CHANGED
@@ -1,109 +1,40 @@
|
|
1
|
+
require 'pp'
|
1
2
|
require 'mkmf'
|
2
3
|
|
3
|
-
if pgdir = with_config( 'pg' )
|
4
|
-
ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPERATOR + ENV['PATH']
|
5
|
-
end
|
6
|
-
|
7
|
-
### Read the output of a command using the fork+pipe syntax so execution errors
|
8
|
-
### propagate to Ruby.
|
9
|
-
def read_cmd_output( *cmd )
|
10
|
-
output = IO.read( '|-' ) or exec( *cmd )
|
11
|
-
return output.chomp
|
12
|
-
end
|
13
|
-
|
14
|
-
### Turn a version string into a Comparable binary datastructure
|
15
|
-
def vvec( version )
|
16
|
-
version.split( '.' ).collect {|i| Integer(i) }.pack( 'N*' )
|
17
|
-
end
|
18
4
|
|
19
|
-
|
20
|
-
|
21
|
-
puts 'This library is for ruby-1.8 or higher.'
|
22
|
-
exit 1
|
23
|
-
end
|
24
|
-
|
25
|
-
pgconfig = with_config( 'pg-config' ) || 'pg_config'
|
26
|
-
if pgconfig = find_executable( pgconfig )
|
27
|
-
$CPPFLAGS << " -I%s" % [ read_cmd_output(pgconfig, '--includedir') ]
|
28
|
-
$LDFLAGS << " -L%s" % [ read_cmd_output(pgconfig, '--libdir') ]
|
5
|
+
if pgdir = with_config( 'pg' )
|
6
|
+
ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
|
29
7
|
end
|
30
8
|
|
31
|
-
|
32
|
-
|
33
|
-
puts "MacOS X build: fixing architecture flags:"
|
34
|
-
|
35
|
-
# Only keep the '-arch <a>' flags present in both the cflags reported
|
36
|
-
# by pg_config and those that Ruby specifies.
|
37
|
-
commonflags = nil
|
38
|
-
if ENV['ARCHFLAGS']
|
39
|
-
puts " using the value in ARCHFLAGS environment variable (%p)." % [ ENV['ARCHFLAGS'] ]
|
40
|
-
commonflags = ENV['ARCHFLAGS']
|
41
|
-
elsif pgconfig
|
42
|
-
puts " finding flags common to both Ruby and PostgreSQL..."
|
43
|
-
archflags = []
|
44
|
-
pgcflags = read_cmd_output( pgconfig, '--cflags' )
|
45
|
-
pgcflags.scan( /-arch\s+(\S+)/ ).each do |arch|
|
46
|
-
puts " testing for architecture: %p" % [ arch ]
|
47
|
-
archflags << "-arch #{arch}" if Config::CONFIG['CFLAGS'].index("-arch #{arch}")
|
48
|
-
end
|
49
|
-
|
50
|
-
commonflags = archflags.join(' ')
|
51
|
-
puts " common arch flags: %s" % [ commonflags ]
|
52
|
-
else
|
53
|
-
$stderr.puts %{
|
54
|
-
=========== WARNING ===========
|
55
|
-
|
56
|
-
You are building this extension on OS X without setting the
|
57
|
-
ARCHFLAGS environment variable, and pg_config wasn't found in
|
58
|
-
your PATH. If you are seeing this message, that means that the
|
59
|
-
build will probably fail.
|
9
|
+
if ENV['CROSS_COMPILING']
|
10
|
+
$LDFLAGS << " -L#{CONFIG['libdir']}"
|
60
11
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
$ export ARCHFLAGS='-arch x86_64'
|
68
|
-
(in tcsh) % set path = ( /opt/local/lib/postgresql84/bin $PATH )
|
69
|
-
% setenv ARCHFLAGS '-arch x86_64'
|
70
|
-
|
71
|
-
Then try building again.
|
72
|
-
|
73
|
-
===================================
|
74
|
-
}.gsub( /^\t+/, ' ' )
|
75
|
-
end
|
76
|
-
|
77
|
-
if commonflags
|
78
|
-
$CFLAGS.gsub!( /-arch\s+\S+ /, '' )
|
79
|
-
$LDFLAGS.gsub!( /-arch\s+\S+ /, '' )
|
80
|
-
CONFIG['LDSHARED'].gsub!( /-arch\s+\S+ /, '' )
|
81
|
-
|
82
|
-
$CFLAGS << ' ' << commonflags
|
83
|
-
$LDFLAGS << ' ' << commonflags
|
84
|
-
CONFIG['LDSHARED'] << ' ' << commonflags
|
85
|
-
end
|
12
|
+
# Link against all required libraries for static build, if they are available
|
13
|
+
have_library( 'gdi32', 'CreateDC' ) && append_library( $libs, 'gdi32' )
|
14
|
+
have_library( 'secur32' ) && append_library( $libs, 'secur32' )
|
15
|
+
have_library( 'ws2_32', 'WSASocket') && append_library( $libs, 'ws2_32' )
|
16
|
+
have_library( 'crypto', 'BIO_new' ) && append_library( $libs, 'crypto' )
|
17
|
+
have_library( 'ssl', 'SSL_new' ) && append_library( $libs, 'ssl' )
|
86
18
|
end
|
87
19
|
|
88
|
-
|
89
20
|
dir_config 'pg'
|
90
21
|
|
91
|
-
if
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
22
|
+
if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
|
23
|
+
$stderr.puts "Using config values from %s" % [ pgconfig ]
|
24
|
+
$CPPFLAGS << " -I%s" % [ `#{pgconfig} --includedir`.chomp ]
|
25
|
+
$LDFLAGS << " -L%s" % [ `#{pgconfig} --libdir`.chomp ]
|
26
|
+
else
|
27
|
+
$stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
|
28
|
+
" --with-pg-config=/path/to/pg_config"
|
97
29
|
end
|
98
30
|
|
99
|
-
|
100
|
-
abort "Can't find the 'libpq-
|
101
|
-
abort "Can't find the 'libpq/libpq-fs.h header" unless have_header('libpq/libpq-fs.h')
|
31
|
+
find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
|
32
|
+
find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
|
102
33
|
|
103
34
|
abort "Can't find the PostgreSQL client library (libpq)" unless
|
104
|
-
have_library( 'pq', 'PQconnectdb' ) ||
|
105
|
-
have_library( 'libpq', 'PQconnectdb' ) ||
|
106
|
-
have_library( 'ms/libpq', 'PQconnectdb' )
|
35
|
+
have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
|
36
|
+
have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
|
37
|
+
have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
|
107
38
|
|
108
39
|
# optional headers/functions
|
109
40
|
have_func 'PQconnectionUsedPassword'
|
@@ -112,15 +43,17 @@ have_func 'PQprepare'
|
|
112
43
|
have_func 'PQexecParams'
|
113
44
|
have_func 'PQescapeString'
|
114
45
|
have_func 'PQescapeStringConn'
|
46
|
+
have_func 'PQgetCancel'
|
115
47
|
have_func 'lo_create'
|
116
48
|
have_func 'pg_encoding_to_char'
|
117
49
|
have_func 'PQsetClientEncoding'
|
118
50
|
|
51
|
+
$defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
|
52
|
+
have_struct_member 'struct pgNotify', 'extra', 'libpq-fe.h'
|
53
|
+
|
119
54
|
# unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
|
120
55
|
have_header 'unistd.h' unless enable_config("static-build")
|
121
56
|
|
122
|
-
$CFLAGS << ' -Wall'
|
123
|
-
|
124
57
|
create_header()
|
125
58
|
create_makefile( "pg_ext" )
|
126
59
|
|
data/ext/pg.c
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
Author: ematsu
|
9
9
|
modified at: Wed Jan 20 16:41:51 1999
|
10
10
|
|
11
|
-
$Author$
|
12
|
-
$Date$
|
11
|
+
$Author: ged $
|
12
|
+
$Date: 2011/03/30 13:13:47 $
|
13
13
|
************************************************/
|
14
14
|
|
15
15
|
#include "pg.h"
|
@@ -17,13 +17,18 @@
|
|
17
17
|
# define M17N_SUPPORTED
|
18
18
|
#endif
|
19
19
|
|
20
|
+
#ifdef _WIN32
|
21
|
+
// for O_RDWR and O_BINARY
|
22
|
+
#include <fcntl.h>
|
23
|
+
#endif
|
24
|
+
|
20
25
|
#define rb_define_singleton_alias(klass,new,old) rb_define_alias(rb_singleton_class(klass),new,old)
|
21
26
|
|
22
27
|
static VALUE rb_cPGconn;
|
23
28
|
static VALUE rb_cPGresult;
|
24
29
|
static VALUE rb_ePGError;
|
25
30
|
|
26
|
-
static const char *VERSION = "0.
|
31
|
+
static const char *VERSION = "0.11.0";
|
27
32
|
|
28
33
|
|
29
34
|
/* The following functions are part of libpq, but not
|
@@ -50,21 +55,22 @@ static const char *VERSION = "0.9.0";
|
|
50
55
|
* UTILITY FUNCTIONS
|
51
56
|
**************************************************************************/
|
52
57
|
|
53
|
-
static void free_pgconn(PGconn *);
|
54
|
-
static void pgresult_check(VALUE, VALUE);
|
58
|
+
static void free_pgconn( PGconn * );
|
59
|
+
static void pgresult_check( VALUE, VALUE );
|
55
60
|
|
56
|
-
static PGconn *get_pgconn(VALUE
|
57
|
-
static VALUE pgconn_finish(VALUE
|
58
|
-
static VALUE pgresult_clear(VALUE
|
59
|
-
static VALUE pgresult_aref(VALUE
|
60
|
-
static VALUE make_column_result_array( VALUE
|
61
|
+
static PGconn *get_pgconn( VALUE );
|
62
|
+
static VALUE pgconn_finish( VALUE );
|
63
|
+
static VALUE pgresult_clear( VALUE );
|
64
|
+
static VALUE pgresult_aref( VALUE, VALUE );
|
65
|
+
static VALUE make_column_result_array( VALUE, int );
|
61
66
|
|
62
67
|
#ifdef M17N_SUPPORTED
|
63
|
-
# define ASSOCIATE_INDEX(obj, index_holder) rb_enc_associate_index((obj), enc_get_index((index_holder)))
|
64
|
-
static rb_encoding * pgconn_get_client_encoding_as_rb_encoding(PGconn*
|
65
|
-
static
|
68
|
+
# define ASSOCIATE_INDEX( obj, index_holder ) rb_enc_associate_index((obj), enc_get_index((index_holder)))
|
69
|
+
static rb_encoding * pgconn_get_client_encoding_as_rb_encoding( PGconn * );
|
70
|
+
static const char * pgconn_get_rb_encoding_as_pg_encname( rb_encoding * );
|
71
|
+
static int enc_get_index( VALUE );
|
66
72
|
#else
|
67
|
-
# define ASSOCIATE_INDEX(obj, index_holder) /* nothing */
|
73
|
+
# define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
|
68
74
|
#endif
|
69
75
|
|
70
76
|
static PQnoticeReceiver default_notice_receiver = NULL;
|
@@ -240,7 +246,7 @@ parse_connect_args(int argc, VALUE *argv, VALUE self)
|
|
240
246
|
VALUE args,arg;
|
241
247
|
VALUE conninfo_rstr = rb_str_new("",0);
|
242
248
|
char *host, *port, *opt, *tty, *dbname, *login, *pwd;
|
243
|
-
host=port=opt=tty=dbname=login=pwd=NULL;
|
249
|
+
host = port = opt = tty = dbname = login = pwd = NULL;
|
244
250
|
|
245
251
|
rb_scan_args(argc, argv, "0*", &args);
|
246
252
|
if (RARRAY_LEN(args) == 1) {
|
@@ -291,8 +297,9 @@ parse_connect_args(int argc, VALUE *argv, VALUE self)
|
|
291
297
|
build_key_value_string(conninfo_rstr, "password", rb_ary_entry(args,6));
|
292
298
|
}
|
293
299
|
else {
|
294
|
-
rb_raise(rb_eArgError,
|
295
|
-
|
300
|
+
rb_raise( rb_eArgError,
|
301
|
+
"Expected connection info string, hash, or 7 separate arguments, got a %s.",
|
302
|
+
RSTRING_PTR(rb_obj_classname( args )) );
|
296
303
|
}
|
297
304
|
|
298
305
|
return conninfo_rstr;
|
@@ -388,7 +395,10 @@ pgconn_alloc(VALUE klass)
|
|
388
395
|
* # As an Array
|
389
396
|
* PGconn.connect( nil, 5432, nil, nil, 'test', nil, nil )
|
390
397
|
*
|
391
|
-
*
|
398
|
+
* If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
|
399
|
+
* connection will have its +client_encoding+ set accordingly.
|
400
|
+
*
|
401
|
+
* @raises [PGError] if the connection fails.
|
392
402
|
*/
|
393
403
|
static VALUE
|
394
404
|
pgconn_init(int argc, VALUE *argv, VALUE self)
|
@@ -396,6 +406,10 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
396
406
|
PGconn *conn = NULL;
|
397
407
|
VALUE conninfo;
|
398
408
|
VALUE error;
|
409
|
+
#ifdef M17N_SUPPORTED
|
410
|
+
rb_encoding *enc;
|
411
|
+
const char *encname;
|
412
|
+
#endif
|
399
413
|
|
400
414
|
conninfo = parse_connect_args(argc, argv, self);
|
401
415
|
conn = PQconnectdb(StringValuePtr(conninfo));
|
@@ -412,6 +426,17 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
412
426
|
rb_exc_raise(error);
|
413
427
|
}
|
414
428
|
|
429
|
+
#ifdef M17N_SUPPORTED
|
430
|
+
/* If Ruby has its Encoding.default_internal set, set PostgreSQL's client_encoding
|
431
|
+
* to match */
|
432
|
+
if (( enc = rb_default_internal_encoding() )) {
|
433
|
+
encname = pgconn_get_rb_encoding_as_pg_encname( enc );
|
434
|
+
if ( PQsetClientEncoding(conn, encname) != 0 )
|
435
|
+
rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
|
436
|
+
encname, PQerrorMessage(conn) );
|
437
|
+
}
|
438
|
+
#endif
|
439
|
+
|
415
440
|
if (rb_block_given_p()) {
|
416
441
|
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
417
442
|
}
|
@@ -427,6 +452,12 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
427
452
|
* This is an asynchronous version of PGconn.connect().
|
428
453
|
*
|
429
454
|
* Use PGconn#connect_poll to poll the status of the connection.
|
455
|
+
*
|
456
|
+
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
457
|
+
* Encoding.default_internal is set. To set it after the connection is established,
|
458
|
+
* call PGconn#internal_encoding=. You can also set it automatically by setting
|
459
|
+
* ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
|
460
|
+
*
|
430
461
|
*/
|
431
462
|
static VALUE
|
432
463
|
pgconn_s_connect_start(int argc, VALUE *argv, VALUE self)
|
@@ -489,7 +520,7 @@ pgconn_s_conndefaults(VALUE self)
|
|
489
520
|
VALUE ary = rb_ary_new();
|
490
521
|
VALUE hash;
|
491
522
|
int i = 0;
|
492
|
-
|
523
|
+
|
493
524
|
for(i = 0; options[i].keyword != NULL; i++) {
|
494
525
|
hash = rb_hash_new();
|
495
526
|
if(options[i].keyword)
|
@@ -535,7 +566,7 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
535
566
|
{
|
536
567
|
char *encrypted = NULL;
|
537
568
|
VALUE rval = Qnil;
|
538
|
-
|
569
|
+
|
539
570
|
Check_Type(password, T_STRING);
|
540
571
|
Check_Type(username, T_STRING);
|
541
572
|
|
@@ -1065,7 +1096,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
1065
1096
|
else
|
1066
1097
|
paramFormats[i] = NUM2INT(param_format);
|
1067
1098
|
}
|
1068
|
-
|
1099
|
+
|
1069
1100
|
result = PQexecParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1070
1101
|
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1071
1102
|
|
@@ -1252,7 +1283,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1252
1283
|
else
|
1253
1284
|
paramFormats[i] = NUM2INT(param_format);
|
1254
1285
|
}
|
1255
|
-
|
1286
|
+
|
1256
1287
|
result = PQexecPrepared(conn, StringValuePtr(name), nParams,
|
1257
1288
|
(const char * const *)paramValues, paramLengths, paramFormats,
|
1258
1289
|
resultFormat);
|
@@ -1617,7 +1648,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1617
1648
|
else
|
1618
1649
|
paramFormats[i] = NUM2INT(param_format);
|
1619
1650
|
}
|
1620
|
-
|
1651
|
+
|
1621
1652
|
result = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1622
1653
|
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1623
1654
|
|
@@ -1802,7 +1833,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1802
1833
|
else
|
1803
1834
|
paramFormats[i] = NUM2INT(param_format);
|
1804
1835
|
}
|
1805
|
-
|
1836
|
+
|
1806
1837
|
result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
|
1807
1838
|
(const char * const *)paramValues, paramLengths, paramFormats,
|
1808
1839
|
resultFormat);
|
@@ -2020,7 +2051,7 @@ pgconn_flush(self)
|
|
2020
2051
|
* conn.cancel() -> String
|
2021
2052
|
*
|
2022
2053
|
* Requests cancellation of the command currently being
|
2023
|
-
* processed.
|
2054
|
+
* processed. (Only implemented in PostgreSQL >= 8.0)
|
2024
2055
|
*
|
2025
2056
|
* Returns +nil+ on success, or a string containing the
|
2026
2057
|
* error message if a failure occurs.
|
@@ -2028,6 +2059,7 @@ pgconn_flush(self)
|
|
2028
2059
|
static VALUE
|
2029
2060
|
pgconn_cancel(VALUE self)
|
2030
2061
|
{
|
2062
|
+
#ifdef HAVE_PQGETCANCEL
|
2031
2063
|
char errbuf[256];
|
2032
2064
|
PGcancel *cancel;
|
2033
2065
|
VALUE retval;
|
@@ -2038,13 +2070,16 @@ pgconn_cancel(VALUE self)
|
|
2038
2070
|
rb_raise(rb_ePGError,"Invalid connection!");
|
2039
2071
|
|
2040
2072
|
ret = PQcancel(cancel, errbuf, 256);
|
2041
|
-
if(ret == 1)
|
2073
|
+
if(ret == 1)
|
2042
2074
|
retval = Qnil;
|
2043
2075
|
else
|
2044
2076
|
retval = rb_str_new2(errbuf);
|
2045
2077
|
|
2046
2078
|
PQfreeCancel(cancel);
|
2047
2079
|
return retval;
|
2080
|
+
#else
|
2081
|
+
rb_notimplement();
|
2082
|
+
#endif
|
2048
2083
|
}
|
2049
2084
|
|
2050
2085
|
|
@@ -2052,14 +2087,14 @@ pgconn_cancel(VALUE self)
|
|
2052
2087
|
* call-seq:
|
2053
2088
|
* conn.notifies()
|
2054
2089
|
*
|
2055
|
-
* Returns a hash of the unprocessed
|
2090
|
+
* Returns a hash of the unprocessed notifications.
|
2056
2091
|
* If there is no unprocessed notifier, it returns +nil+.
|
2057
2092
|
*/
|
2058
2093
|
static VALUE
|
2059
2094
|
pgconn_notifies(VALUE self)
|
2060
2095
|
{
|
2061
2096
|
PGconn* conn = get_pgconn(self);
|
2062
|
-
PGnotify *
|
2097
|
+
PGnotify *notification;
|
2063
2098
|
VALUE hash;
|
2064
2099
|
VALUE sym_relname, sym_be_pid, sym_extra;
|
2065
2100
|
VALUE relname, be_pid, extra;
|
@@ -2068,25 +2103,60 @@ pgconn_notifies(VALUE self)
|
|
2068
2103
|
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
2069
2104
|
sym_extra = ID2SYM(rb_intern("extra"));
|
2070
2105
|
|
2071
|
-
|
2072
|
-
if (
|
2106
|
+
notification = PQnotifies(conn);
|
2107
|
+
if (notification == NULL) {
|
2073
2108
|
return Qnil;
|
2074
2109
|
}
|
2075
|
-
|
2110
|
+
|
2076
2111
|
hash = rb_hash_new();
|
2077
|
-
relname = rb_tainted_str_new2(
|
2078
|
-
be_pid = INT2NUM(
|
2079
|
-
extra = rb_tainted_str_new2(PGNOTIFY_EXTRA(
|
2080
|
-
|
2112
|
+
relname = rb_tainted_str_new2(notification->relname);
|
2113
|
+
be_pid = INT2NUM(notification->be_pid);
|
2114
|
+
extra = rb_tainted_str_new2(PGNOTIFY_EXTRA(notification));
|
2115
|
+
|
2081
2116
|
rb_hash_aset(hash, sym_relname, relname);
|
2082
2117
|
rb_hash_aset(hash, sym_be_pid, be_pid);
|
2083
2118
|
rb_hash_aset(hash, sym_extra, extra);
|
2084
2119
|
|
2085
|
-
PQfreemem(
|
2120
|
+
PQfreemem(notification);
|
2086
2121
|
return hash;
|
2087
2122
|
}
|
2088
2123
|
|
2089
2124
|
|
2125
|
+
#ifdef _WIN32
|
2126
|
+
/*
|
2127
|
+
* Duplicate the sockets from libpq and create temporary CRT FDs
|
2128
|
+
*/
|
2129
|
+
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2130
|
+
{
|
2131
|
+
int i;
|
2132
|
+
crt_set->fd_count = os_set->fd_count;
|
2133
|
+
for (i = 0; i < os_set->fd_count; i++) {
|
2134
|
+
WSAPROTOCOL_INFO wsa_pi;
|
2135
|
+
/* dupicate the SOCKET */
|
2136
|
+
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2137
|
+
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2138
|
+
/* create the CRT fd so ruby can get back to the SOCKET */
|
2139
|
+
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2140
|
+
os_set->fd_array[i] = s;
|
2141
|
+
crt_set->fd_array[i] = fd;
|
2142
|
+
}
|
2143
|
+
}
|
2144
|
+
|
2145
|
+
/*
|
2146
|
+
* Clean up the CRT FDs from create_crt_fd()
|
2147
|
+
*/
|
2148
|
+
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2149
|
+
{
|
2150
|
+
int i;
|
2151
|
+
for (i = 0; i < os_set->fd_count; i++) {
|
2152
|
+
/* cleanup the CRT fd */
|
2153
|
+
_close(crt_set->fd_array[i]);
|
2154
|
+
/* cleanup the duplicated SOCKET */
|
2155
|
+
closesocket(os_set->fd_array[i]);
|
2156
|
+
}
|
2157
|
+
}
|
2158
|
+
#endif
|
2159
|
+
|
2090
2160
|
/*
|
2091
2161
|
* call-seq:
|
2092
2162
|
* conn.wait_for_notify( [ timeout ] ) -> String
|
@@ -2104,48 +2174,67 @@ pgconn_notifies(VALUE self)
|
|
2104
2174
|
static VALUE
|
2105
2175
|
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
2106
2176
|
{
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
FD_SET(sd, &sd_rset);
|
2129
|
-
ret = rb_thread_select(sd+1, &sd_rset, NULL, NULL, ptimeout);
|
2130
|
-
if (ret == 0) {
|
2131
|
-
return Qnil;
|
2132
|
-
} else if (ret < 0) {
|
2133
|
-
rb_sys_fail(0);
|
2177
|
+
PGconn *conn = get_pgconn( self );
|
2178
|
+
PGnotify *notification;
|
2179
|
+
int sd = PQsocket( conn );
|
2180
|
+
int ret;
|
2181
|
+
struct timeval timeout;
|
2182
|
+
struct timeval *ptimeout = NULL;
|
2183
|
+
VALUE timeout_in, relname = Qnil, be_pid = Qnil, extra = Qnil;
|
2184
|
+
double timeout_sec;
|
2185
|
+
fd_set sd_rset;
|
2186
|
+
#ifdef _WIN32
|
2187
|
+
fd_set crt_sd_rset;
|
2188
|
+
#endif
|
2189
|
+
|
2190
|
+
if ( sd < 0 )
|
2191
|
+
rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
|
2192
|
+
|
2193
|
+
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2194
|
+
timeout_sec = NUM2DBL( timeout_in );
|
2195
|
+
timeout.tv_sec = (long)timeout_sec;
|
2196
|
+
timeout.tv_usec = (long)( (timeout_sec - (long)timeout_sec) * 1e6 );
|
2197
|
+
ptimeout = &timeout;
|
2134
2198
|
}
|
2135
|
-
|
2136
|
-
|
2137
|
-
|
2199
|
+
|
2200
|
+
/* Check for notifications */
|
2201
|
+
while ( (notification = PQnotifies(conn)) == NULL ) {
|
2202
|
+
FD_ZERO( &sd_rset );
|
2203
|
+
FD_SET( sd, &sd_rset );
|
2204
|
+
|
2205
|
+
#ifdef _WIN32
|
2206
|
+
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2207
|
+
#endif
|
2208
|
+
|
2209
|
+
/* Wait for the socket to become readable before checking again */
|
2210
|
+
ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2211
|
+
|
2212
|
+
#ifdef _WIN32
|
2213
|
+
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2214
|
+
#endif
|
2215
|
+
|
2216
|
+
if ( ret < 0 )
|
2217
|
+
rb_sys_fail( 0 );
|
2218
|
+
|
2219
|
+
/* Return nil if the select timed out */
|
2220
|
+
if ( ret == 0 ) return Qnil;
|
2221
|
+
|
2222
|
+
/* Read the socket */
|
2223
|
+
if ( (ret = PQconsumeInput(conn)) != 1 )
|
2224
|
+
rb_raise( rb_ePGError, "PQconsumeInput == %d: %s", ret, PQerrorMessage(conn) );
|
2138
2225
|
}
|
2139
|
-
|
2140
|
-
while ((notify = PQnotifies(conn)) != NULL) {
|
2141
|
-
relname = rb_tainted_str_new2(notify->relname);
|
2142
|
-
be_pid = INT2NUM(notify->be_pid);
|
2143
|
-
PQfreemem(notify);
|
2144
|
-
}
|
2145
2226
|
|
2146
|
-
|
2227
|
+
relname = rb_tainted_str_new2( notification->relname );
|
2228
|
+
be_pid = INT2NUM( notification->be_pid );
|
2229
|
+
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2230
|
+
extra = rb_str_new2( notification->extra );
|
2231
|
+
#endif
|
2232
|
+
PQfreemem( notification );
|
2233
|
+
|
2234
|
+
if ( rb_block_given_p() )
|
2235
|
+
rb_yield_values( 3, relname, be_pid, extra );
|
2147
2236
|
|
2148
|
-
|
2237
|
+
return relname;
|
2149
2238
|
}
|
2150
2239
|
|
2151
2240
|
|
@@ -2472,7 +2561,7 @@ pgconn_transaction(VALUE self)
|
|
2472
2561
|
PGresult *result;
|
2473
2562
|
VALUE rb_pgresult;
|
2474
2563
|
int status;
|
2475
|
-
|
2564
|
+
|
2476
2565
|
if (rb_block_given_p()) {
|
2477
2566
|
result = PQexec(conn, "BEGIN");
|
2478
2567
|
rb_pgresult = new_pgresult(result, conn);
|
@@ -2490,7 +2579,7 @@ pgconn_transaction(VALUE self)
|
|
2490
2579
|
pgresult_check(self, rb_pgresult);
|
2491
2580
|
rb_jump_tag(status);
|
2492
2581
|
}
|
2493
|
-
|
2582
|
+
|
2494
2583
|
}
|
2495
2584
|
else {
|
2496
2585
|
/* no block supplied? */
|
@@ -2529,7 +2618,7 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
|
2529
2618
|
* double-quotes. */
|
2530
2619
|
char buffer[NAMEDATALEN*2+2];
|
2531
2620
|
unsigned int i=0,j=0;
|
2532
|
-
|
2621
|
+
|
2533
2622
|
if(strlen(str) >= NAMEDATALEN) {
|
2534
2623
|
rb_raise(rb_eArgError,
|
2535
2624
|
"Input string is longer than NAMEDATALEN-1 (%d)",
|
@@ -2571,6 +2660,9 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
2571
2660
|
VALUE timeout_in;
|
2572
2661
|
double timeout_sec;
|
2573
2662
|
fd_set sd_rset;
|
2663
|
+
#ifdef _WIN32
|
2664
|
+
fd_set crt_sd_rset;
|
2665
|
+
#endif
|
2574
2666
|
|
2575
2667
|
/* Always set a timeout in WIN32, as rb_thread_select() sometimes
|
2576
2668
|
* doesn't return when a second ruby thread is running although data
|
@@ -2594,7 +2686,16 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
|
2594
2686
|
while ( PQisBusy(conn) ) {
|
2595
2687
|
FD_ZERO( &sd_rset );
|
2596
2688
|
FD_SET( sd, &sd_rset );
|
2597
|
-
|
2689
|
+
|
2690
|
+
#ifdef _WIN32
|
2691
|
+
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2692
|
+
#endif
|
2693
|
+
|
2694
|
+
ret = rb_thread_select (sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2695
|
+
|
2696
|
+
#ifdef _WIN32
|
2697
|
+
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2698
|
+
#endif
|
2598
2699
|
|
2599
2700
|
/* Return false if there was a timeout argument and the select() timed out */
|
2600
2701
|
if ( ret == 0 && argc )
|
@@ -3206,7 +3307,7 @@ pgresult_ftablecol(VALUE self, VALUE column_number)
|
|
3206
3307
|
|
3207
3308
|
if( col_number < 0 || col_number >= PQnfields(pgresult))
|
3208
3309
|
rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
|
3209
|
-
|
3310
|
+
|
3210
3311
|
n = PQftablecol(pgresult, col_number);
|
3211
3312
|
return INT2FIX(n);
|
3212
3313
|
}
|
@@ -3488,34 +3589,84 @@ pgresult_aref(VALUE self, VALUE index)
|
|
3488
3589
|
VALUE fname,val;
|
3489
3590
|
VALUE tuple;
|
3490
3591
|
|
3491
|
-
if(tuple_num < 0 || tuple_num >= PQntuples(result))
|
3492
|
-
rb_raise(rb_eIndexError, "Index %d is out of range", tuple_num);
|
3592
|
+
if ( tuple_num < 0 || tuple_num >= PQntuples(result) )
|
3593
|
+
rb_raise( rb_eIndexError, "Index %d is out of range", tuple_num );
|
3594
|
+
|
3493
3595
|
tuple = rb_hash_new();
|
3494
|
-
for(field_num = 0; field_num < PQnfields(result); field_num++) {
|
3495
|
-
fname = rb_tainted_str_new2(PQfname(result,field_num));
|
3596
|
+
for ( field_num = 0; field_num < PQnfields(result); field_num++ ) {
|
3597
|
+
fname = rb_tainted_str_new2( PQfname(result,field_num) );
|
3496
3598
|
ASSOCIATE_INDEX(fname, self);
|
3497
|
-
if(PQgetisnull(result, tuple_num, field_num)) {
|
3498
|
-
rb_hash_aset(tuple, fname, Qnil);
|
3599
|
+
if ( PQgetisnull(result, tuple_num, field_num) ) {
|
3600
|
+
rb_hash_aset( tuple, fname, Qnil );
|
3499
3601
|
}
|
3500
3602
|
else {
|
3501
|
-
val = rb_tainted_str_new(PQgetvalue(result, tuple_num, field_num),
|
3502
|
-
|
3603
|
+
val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ),
|
3604
|
+
PQgetlength(result, tuple_num, field_num) );
|
3503
3605
|
|
3504
3606
|
/* associate client encoding for text format only */
|
3505
|
-
if(0 == PQfformat(result, field_num)) {
|
3506
|
-
ASSOCIATE_INDEX(val, self);
|
3607
|
+
if ( 0 == PQfformat(result, field_num) ) {
|
3608
|
+
ASSOCIATE_INDEX( val, self );
|
3507
3609
|
} else {
|
3508
3610
|
#ifdef M17N_SUPPORTED
|
3509
|
-
rb_enc_associate(val, rb_ascii8bit_encoding());
|
3611
|
+
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3510
3612
|
#endif
|
3511
3613
|
}
|
3512
|
-
rb_hash_aset(tuple, fname, val);
|
3614
|
+
rb_hash_aset( tuple, fname, val );
|
3513
3615
|
}
|
3514
3616
|
}
|
3515
3617
|
return tuple;
|
3516
3618
|
}
|
3517
3619
|
|
3518
3620
|
|
3621
|
+
/*
|
3622
|
+
* call-seq:
|
3623
|
+
* res.values -> Array
|
3624
|
+
*
|
3625
|
+
* Returns all tuples as an array of arrays.
|
3626
|
+
*/
|
3627
|
+
static VALUE
|
3628
|
+
pgresult_values(VALUE self, VALUE index)
|
3629
|
+
{
|
3630
|
+
PGresult* result = (PGresult*) get_pgresult(self);
|
3631
|
+
int row;
|
3632
|
+
int field;
|
3633
|
+
int num_rows = PQntuples(result);
|
3634
|
+
int num_fields = PQnfields(result);
|
3635
|
+
VALUE ary = rb_ary_new2(num_rows);
|
3636
|
+
|
3637
|
+
for ( row = 0; row < num_rows; row++ ) {
|
3638
|
+
/* create new row */
|
3639
|
+
VALUE new_row = rb_ary_new2(num_fields);
|
3640
|
+
|
3641
|
+
/* add to return array */
|
3642
|
+
rb_ary_store( ary, row, new_row );
|
3643
|
+
|
3644
|
+
/* populate it */
|
3645
|
+
for ( field = 0; field < num_fields; field++ ) {
|
3646
|
+
if ( PQgetisnull(result, row, field) ) {
|
3647
|
+
rb_ary_store( new_row, field, Qnil );
|
3648
|
+
}
|
3649
|
+
else {
|
3650
|
+
VALUE val = rb_tainted_str_new( PQgetvalue(result, row, field),
|
3651
|
+
PQgetlength(result, row, field) );
|
3652
|
+
|
3653
|
+
/* associate client encoding for text format only */
|
3654
|
+
if ( 0 == PQfformat(result, field) ) {
|
3655
|
+
ASSOCIATE_INDEX( val, self );
|
3656
|
+
} else {
|
3657
|
+
#ifdef M17N_SUPPORTED
|
3658
|
+
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3659
|
+
#endif
|
3660
|
+
}
|
3661
|
+
|
3662
|
+
rb_ary_store( new_row, field, val );
|
3663
|
+
}
|
3664
|
+
}
|
3665
|
+
}
|
3666
|
+
return ary;
|
3667
|
+
}
|
3668
|
+
|
3669
|
+
|
3519
3670
|
/*
|
3520
3671
|
* call-seq:
|
3521
3672
|
* res.column_values( n ) -> array
|
@@ -3548,7 +3699,7 @@ pgresult_field_values( VALUE self, VALUE field )
|
|
3548
3699
|
|
3549
3700
|
if ( fnum < 0 )
|
3550
3701
|
rb_raise( rb_eIndexError, "no such field '%s' in result", fieldname );
|
3551
|
-
|
3702
|
+
|
3552
3703
|
return make_column_result_array( self, fnum );
|
3553
3704
|
}
|
3554
3705
|
|
@@ -3564,7 +3715,7 @@ make_column_result_array( VALUE self, int col )
|
|
3564
3715
|
int row = PQntuples( result );
|
3565
3716
|
VALUE ary = rb_ary_new2( row );
|
3566
3717
|
VALUE val = Qnil;
|
3567
|
-
|
3718
|
+
|
3568
3719
|
if ( col >= PQnfields(result) )
|
3569
3720
|
rb_raise( rb_eIndexError, "no column %d in result", col );
|
3570
3721
|
|
@@ -3583,7 +3734,7 @@ make_column_result_array( VALUE self, int col )
|
|
3583
3734
|
|
3584
3735
|
rb_ary_store( ary, row, val );
|
3585
3736
|
}
|
3586
|
-
|
3737
|
+
|
3587
3738
|
return ary;
|
3588
3739
|
}
|
3589
3740
|
|
@@ -3630,39 +3781,42 @@ pgresult_fields(VALUE self)
|
|
3630
3781
|
return ary;
|
3631
3782
|
}
|
3632
3783
|
|
3784
|
+
|
3633
3785
|
#ifdef M17N_SUPPORTED
|
3634
3786
|
/**
|
3635
3787
|
* The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
|
3636
3788
|
*/
|
3637
3789
|
static const char * const (enc_pg2ruby_mapping[][2]) = {
|
3638
|
-
{"BIG5", "Big5"
|
3639
|
-
{"EUC_CN", "GB2312"
|
3640
|
-
{"EUC_JP", "EUC-JP"
|
3641
|
-
{"EUC_JIS_2004", "EUC-JP"
|
3642
|
-
{"EUC_KR", "EUC-KR"
|
3643
|
-
{"EUC_TW", "EUC-TW"
|
3644
|
-
{"GB18030", "GB18030"
|
3645
|
-
{"GBK", "GBK"
|
3646
|
-
{"ISO_8859_5", "ISO-8859-5"
|
3647
|
-
{"ISO_8859_6", "ISO-8859-6"
|
3648
|
-
{"ISO_8859_7", "ISO-8859-7"
|
3649
|
-
{"ISO_8859_8", "ISO-8859-8"
|
3650
|
-
/* {"JOHAB", "JOHAB"
|
3651
|
-
{"KOI8", "KOI8-
|
3652
|
-
{"
|
3653
|
-
{"
|
3654
|
-
{"
|
3655
|
-
{"
|
3656
|
-
{"
|
3657
|
-
{"
|
3658
|
-
{"
|
3659
|
-
{"
|
3660
|
-
{"
|
3790
|
+
{"BIG5", "Big5" },
|
3791
|
+
{"EUC_CN", "GB2312" },
|
3792
|
+
{"EUC_JP", "EUC-JP" },
|
3793
|
+
{"EUC_JIS_2004", "EUC-JP" },
|
3794
|
+
{"EUC_KR", "EUC-KR" },
|
3795
|
+
{"EUC_TW", "EUC-TW" },
|
3796
|
+
{"GB18030", "GB18030" },
|
3797
|
+
{"GBK", "GBK" },
|
3798
|
+
{"ISO_8859_5", "ISO-8859-5" },
|
3799
|
+
{"ISO_8859_6", "ISO-8859-6" },
|
3800
|
+
{"ISO_8859_7", "ISO-8859-7" },
|
3801
|
+
{"ISO_8859_8", "ISO-8859-8" },
|
3802
|
+
/* {"JOHAB", "JOHAB" }, dummy */
|
3803
|
+
{"KOI8", "KOI8-R" },
|
3804
|
+
{"KOI8R", "KOI8-R" },
|
3805
|
+
{"KOI8U", "KOI8-U" },
|
3806
|
+
{"LATIN1", "ISO-8859-1" },
|
3807
|
+
{"LATIN2", "ISO-8859-2" },
|
3808
|
+
{"LATIN3", "ISO-8859-3" },
|
3809
|
+
{"LATIN4", "ISO-8859-4" },
|
3810
|
+
{"LATIN5", "ISO-8859-5" },
|
3811
|
+
{"LATIN6", "ISO-8859-6" },
|
3812
|
+
{"LATIN7", "ISO-8859-7" },
|
3813
|
+
{"LATIN8", "ISO-8859-8" },
|
3814
|
+
{"LATIN9", "ISO-8859-9" },
|
3661
3815
|
{"LATIN10", "ISO-8859-10" },
|
3662
|
-
{"MULE_INTERNAL", "Emacs-Mule"
|
3816
|
+
{"MULE_INTERNAL", "Emacs-Mule" },
|
3663
3817
|
{"SJIS", "Windows-31J" },
|
3664
3818
|
{"SHIFT_JIS_2004","Windows-31J" },
|
3665
|
-
/*{"SQL_ASCII", NULL
|
3819
|
+
/* {"SQL_ASCII", NULL }, special case*/
|
3666
3820
|
{"UHC", "CP949" },
|
3667
3821
|
{"UTF8", "UTF-8" },
|
3668
3822
|
{"WIN866", "IBM866" },
|
@@ -3756,6 +3910,30 @@ cache:
|
|
3756
3910
|
return enc;
|
3757
3911
|
}
|
3758
3912
|
|
3913
|
+
|
3914
|
+
/*
|
3915
|
+
* Returns the given rb_encoding as the equivalent PostgreSQL encoding string.
|
3916
|
+
*
|
3917
|
+
*/
|
3918
|
+
static const char *
|
3919
|
+
pgconn_get_rb_encoding_as_pg_encname( rb_encoding *enc )
|
3920
|
+
{
|
3921
|
+
const char *rb_encname = rb_enc_name( enc );
|
3922
|
+
const char *encname = NULL;
|
3923
|
+
int i;
|
3924
|
+
|
3925
|
+
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
3926
|
+
if (strcmp(rb_encname, enc_pg2ruby_mapping[i][1]) == 0) {
|
3927
|
+
encname = enc_pg2ruby_mapping[i][0];
|
3928
|
+
}
|
3929
|
+
}
|
3930
|
+
|
3931
|
+
if ( !encname ) encname = "SQL_ASCII";
|
3932
|
+
|
3933
|
+
return encname;
|
3934
|
+
}
|
3935
|
+
|
3936
|
+
|
3759
3937
|
/*
|
3760
3938
|
* call-seq:
|
3761
3939
|
* conn.internal_encoding() -> Encoding
|
@@ -3933,7 +4111,7 @@ Init_pg_ext()
|
|
3933
4111
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
3934
4112
|
|
3935
4113
|
/****** PGconn CLASS CONSTANTS: Connection Status ******/
|
3936
|
-
|
4114
|
+
|
3937
4115
|
/* Connection succeeded */
|
3938
4116
|
rb_define_const(rb_cPGconn, "CONNECTION_OK", INT2FIX(CONNECTION_OK));
|
3939
4117
|
/* Connection failed */
|
@@ -3966,7 +4144,7 @@ Init_pg_ext()
|
|
3966
4144
|
rb_define_const(rb_cPGconn, "PGRES_POLLING_OK", INT2FIX(PGRES_POLLING_OK));
|
3967
4145
|
|
3968
4146
|
/****** PGconn CLASS CONSTANTS: Transaction Status ******/
|
3969
|
-
|
4147
|
+
|
3970
4148
|
/* Transaction is currently idle (#transaction_status) */
|
3971
4149
|
rb_define_const(rb_cPGconn, "PQTRANS_IDLE", INT2FIX(PQTRANS_IDLE));
|
3972
4150
|
/* Transaction is currently active; query has been sent to the server, but not yet completed. (#transaction_status) */
|
@@ -4241,6 +4419,7 @@ Init_pg_ext()
|
|
4241
4419
|
rb_define_method(rb_cPGresult, "[]", pgresult_aref, 1);
|
4242
4420
|
rb_define_method(rb_cPGresult, "each", pgresult_each, 0);
|
4243
4421
|
rb_define_method(rb_cPGresult, "fields", pgresult_fields, 0);
|
4422
|
+
rb_define_method(rb_cPGresult, "values", pgresult_values, 0);
|
4244
4423
|
rb_define_method(rb_cPGresult, "column_values", pgresult_column_values, 1);
|
4245
4424
|
rb_define_method(rb_cPGresult, "field_values", pgresult_field_values, 1);
|
4246
4425
|
|