pg 0.9.0-x86-mingw32 → 0.11.0pre229-x86-mingw32
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.
- 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
|
|