pg 0.12.2-x86-mingw32 → 0.13.0-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/.hoerc +2 -0
- data/.tm_properties +12 -0
- data/ChangeLog +166 -59
- data/Contributors.rdoc +7 -0
- data/History.rdoc +29 -0
- data/LICENSE +12 -14
- data/Manifest.txt +15 -14
- data/{BSD → POSTGRES} +0 -0
- data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
- data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
- data/README.ja.rdoc +1 -1
- data/README.rdoc +39 -27
- data/Rakefile +1 -5
- data/Rakefile.cross +2 -2
- data/ext/extconf.rb +8 -2
- data/ext/pg.c +232 -4297
- data/ext/pg.h +88 -23
- data/ext/pg_connection.c +3288 -0
- data/ext/pg_result.c +905 -0
- data/lib/1.8/pg_ext.so +0 -0
- data/lib/1.9/pg_ext.so +0 -0
- data/lib/pg.rb +26 -43
- data/lib/pg/connection.rb +58 -0
- data/lib/pg/constants.rb +11 -0
- data/lib/pg/exceptions.rb +11 -0
- data/lib/pg/result.rb +11 -0
- data/misc/openssl-pg-segfault.rb +1 -1
- data/sample/async_api.rb +16 -21
- data/sample/async_copyto.rb +1 -1
- data/sample/async_mixed.rb +56 -0
- data/sample/copyfrom.rb +1 -1
- data/sample/copyto.rb +1 -1
- data/sample/cursor.rb +1 -1
- data/sample/losample.rb +6 -6
- data/sample/notify_wait.rb +51 -22
- data/sample/test_binary_values.rb +4 -6
- data/spec/lib/helpers.rb +14 -10
- data/spec/{pgconn_spec.rb → pg/connection_spec.rb} +228 -60
- data/spec/{pgresult_spec.rb → pg/result_spec.rb} +31 -35
- data/spec/pg_spec.rb +22 -0
- metadata +52 -41
- data/GPL +0 -340
- data/ext/compat.c +0 -541
- data/ext/compat.h +0 -184
- data/sample/psql.rb +0 -1181
- data/sample/psqlHelp.rb +0 -158
- data/sample/test1.rb +0 -60
- data/sample/test2.rb +0 -44
- data/sample/test4.rb +0 -71
- data/spec/m17n_spec.rb +0 -170
data/{BSD → POSTGRES}
RENAMED
File without changes
|
File without changes
|
File without changes
|
data/README.ja.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -6,20 +6,31 @@
|
|
6
6
|
|
7
7
|
Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
|
8
8
|
|
9
|
-
It works with PostgreSQL 8.
|
9
|
+
It works with {PostgreSQL 8.3 and later}[http://bit.ly/6AfPhm].
|
10
10
|
|
11
|
-
|
12
|
-
and later, following the
|
13
|
-
{PostgreSQL Release Support Policy}[http://bit.ly/6AfPhm].
|
11
|
+
A small example usage:
|
14
12
|
|
13
|
+
#!/usr/bin/env ruby
|
14
|
+
|
15
|
+
require 'pg'
|
16
|
+
|
17
|
+
# Output a table of current connections to the DB
|
18
|
+
conn = PG.connect( dbname: 'sales' )
|
19
|
+
conn.exec( "SELECT * FROM pg_stat_activity" ) do |result|
|
20
|
+
puts " PID | User | Query"
|
21
|
+
result.each do |row|
|
22
|
+
puts " %7d | %-16s | %s " %
|
23
|
+
row.values_at('procpid', 'usename', 'current_query')
|
24
|
+
end
|
25
|
+
end
|
15
26
|
|
16
27
|
|
17
28
|
== Requirements
|
18
29
|
|
19
|
-
* Ruby 1.8.7-p249 or
|
20
|
-
* PostgreSQL 8.
|
30
|
+
* Ruby 1.8.7-p249 or 1.9.3-p0.
|
31
|
+
* PostgreSQL 8.3.x (with headers, -dev packages, etc).
|
21
32
|
|
22
|
-
It may work with earlier versions as well, but those are not regularly tested.
|
33
|
+
It may work with earlier versions of Ruby as well, but those are not regularly tested.
|
23
34
|
|
24
35
|
|
25
36
|
== How To Install
|
@@ -33,8 +44,12 @@ Postgres:
|
|
33
44
|
|
34
45
|
gem install pg -- --with-pg-config=<path to pg_config>
|
35
46
|
|
36
|
-
See README
|
37
|
-
README.
|
47
|
+
See README-OS_X.rdoc for more information about installing under MacOS X, and
|
48
|
+
README-Windows.rdoc for Windows build/installation instructions.
|
49
|
+
|
50
|
+
There's also {a Google+ group}[http://goo.gl/TFy1U] and a
|
51
|
+
{mailing list}[http://groups.google.com/group/ruby-pg] if you get stuck, or just
|
52
|
+
want to chat about something.
|
38
53
|
|
39
54
|
|
40
55
|
== Contributing
|
@@ -50,39 +65,36 @@ After checking out the source, run:
|
|
50
65
|
This task will install any missing dependencies, run the tests/specs, and
|
51
66
|
generate the API documentation.
|
52
67
|
|
68
|
+
The current maintainer is Michael Granger <ged@FaerieMUD.org>.
|
53
69
|
|
54
|
-
== Copying
|
55
70
|
|
56
|
-
|
71
|
+
== Copying
|
57
72
|
|
58
|
-
|
73
|
+
Copyright (c) 1997-2012 by the authors.
|
59
74
|
|
60
|
-
* Yukihiro Matsumoto <matz@ruby-lang.org> - Author of Ruby.
|
61
|
-
* Eiji Matsumoto <usagi@ruby.club.or.jp> - One of users who loves Ruby.
|
62
75
|
* Jeff Davis <ruby-pg@j-davis.com>
|
63
|
-
|
64
|
-
Thanks to:
|
65
|
-
|
66
|
-
* Noboru Saitou <noborus@netlab.jp> - Past maintainer.
|
67
|
-
* Dave Lee - Past maintainer.
|
68
|
-
* Guy Decoux (ts) <decoux@moulon.inra.fr>
|
69
|
-
|
70
|
-
Maintainers:
|
71
|
-
|
76
|
+
* Guy Decoux (ts) <decoux@moulon.inra.fr>
|
72
77
|
* Michael Granger <ged@FaerieMUD.org>
|
78
|
+
* Dave Lee
|
79
|
+
* Eiji Matsumoto <usagi@ruby.club.or.jp>
|
80
|
+
* Yukihiro Matsumoto <matz@ruby-lang.org>
|
81
|
+
* Noboru Saitou <noborus@netlab.jp>
|
73
82
|
|
74
|
-
You may redistribute this software under the terms
|
75
|
-
|
76
|
-
|
83
|
+
You may redistribute this software under the same terms as Ruby itself; see
|
84
|
+
http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
|
85
|
+
for details.
|
77
86
|
|
78
87
|
Portions of the code are from the PostgreSQL project, and are distributed
|
79
|
-
under the terms of the
|
88
|
+
under the terms of the PostgreSQL license, included in the file POSTGRES.
|
80
89
|
|
81
90
|
Portions copyright LAIKA, Inc.
|
82
91
|
|
83
92
|
|
84
93
|
== Acknowledgments
|
85
94
|
|
95
|
+
See Contributors.rdoc for the many additional fine people that have contributed
|
96
|
+
to this library over the years.
|
97
|
+
|
86
98
|
We are thankful to the people at the ruby-list and ruby-dev mailing lists.
|
87
99
|
And to the people who developed PostgreSQL.
|
88
100
|
|
data/Rakefile
CHANGED
@@ -49,10 +49,9 @@ $hoespec = Hoe.spec 'pg' do
|
|
49
49
|
self.readme_file = 'README.rdoc'
|
50
50
|
self.history_file = 'History.rdoc'
|
51
51
|
self.extra_rdoc_files = Rake::FileList[ '*.rdoc' ]
|
52
|
-
self.extra_rdoc_files.include( '
|
52
|
+
self.extra_rdoc_files.include( 'POSTGRES', 'LICENSE' )
|
53
53
|
self.extra_rdoc_files.include( 'ext/*.c' )
|
54
54
|
|
55
|
-
self.developer 'Jeff Davis', 'ruby-pg@j-davis.com'
|
56
55
|
self.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
57
56
|
|
58
57
|
self.dependency 'rake-compiler', '~> 0.7', :developer
|
@@ -97,8 +96,6 @@ task :maint do
|
|
97
96
|
ENV['MAINTAINER_MODE'] = 'yes'
|
98
97
|
end
|
99
98
|
|
100
|
-
ENV['RUBY_CC_VERSION'] = '1.8.7:1.9.2'
|
101
|
-
|
102
99
|
# Rake-compiler task
|
103
100
|
Rake::ExtensionTask.new do |ext|
|
104
101
|
ext.name = 'pg_ext'
|
@@ -115,7 +112,6 @@ Rake::ExtensionTask.new do |ext|
|
|
115
112
|
"--with-opt-include=#{STATIC_POSTGRESQL_INCDIR}",
|
116
113
|
"--with-pg-lib=#{STATIC_POSTGRESQL_LIBDIR}",
|
117
114
|
"--with-opt-lib=#{STATIC_OPENSSL_BUILDDIR}",
|
118
|
-
"--enable-static-build",
|
119
115
|
]
|
120
116
|
end
|
121
117
|
|
data/Rakefile.cross
CHANGED
@@ -41,8 +41,8 @@ OPENSSL_PATCHES = Rake::FileList[ MISCDIR + "openssl-#{OPENSSL_VERSIO
|
|
41
41
|
# Static PostgreSQL build vars
|
42
42
|
STATIC_POSTGRESQL_BUILDDIR = STATIC_BUILDDIR + "postgresql-#{POSTGRESQL_VERSION}"
|
43
43
|
POSTGRESQL_SOURCE_URI = begin
|
44
|
-
uristring = "http://
|
45
|
-
|
44
|
+
uristring = "http://ftp.postgresql.org/pub/source/v%s/postgresql-%s.tar.bz2" %
|
45
|
+
[ POSTGRESQL_VERSION, POSTGRESQL_VERSION ]
|
46
46
|
URI( uristring )
|
47
47
|
end
|
48
48
|
POSTGRESQL_TARBALL = STATIC_SOURCESDIR + File.basename( POSTGRESQL_SOURCE_URI.path )
|
data/ext/extconf.rb
CHANGED
@@ -4,7 +4,11 @@ require 'mkmf'
|
|
4
4
|
|
5
5
|
if ENV['MAINTAINER_MODE']
|
6
6
|
$stderr.puts "Maintainer mode enabled."
|
7
|
-
$CFLAGS <<
|
7
|
+
$CFLAGS <<
|
8
|
+
' -Wall' <<
|
9
|
+
' -ggdb' <<
|
10
|
+
' -DDEBUG' <<
|
11
|
+
' -pedantic'
|
8
12
|
end
|
9
13
|
|
10
14
|
if pgdir = with_config( 'pg' )
|
@@ -35,6 +39,7 @@ end
|
|
35
39
|
|
36
40
|
find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
|
37
41
|
find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
|
42
|
+
find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
|
38
43
|
|
39
44
|
abort "Can't find the PostgreSQL client library (libpq)" unless
|
40
45
|
have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
|
@@ -51,6 +56,7 @@ have_func 'PQescapeStringConn'
|
|
51
56
|
have_func 'PQgetCancel'
|
52
57
|
have_func 'lo_create'
|
53
58
|
have_func 'pg_encoding_to_char'
|
59
|
+
have_func 'pg_char_to_encoding'
|
54
60
|
have_func 'PQsetClientEncoding'
|
55
61
|
|
56
62
|
have_func 'rb_encdb_alias'
|
@@ -60,7 +66,7 @@ $defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
|
|
60
66
|
have_struct_member 'struct pgNotify', 'extra', 'libpq-fe.h'
|
61
67
|
|
62
68
|
# unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
|
63
|
-
have_header 'unistd.h'
|
69
|
+
have_header 'unistd.h'
|
64
70
|
have_header 'ruby/st.h' or have_header 'st.h' or abort "pg currently requires the ruby/st.h header"
|
65
71
|
|
66
72
|
create_header()
|
data/ext/pg.c
CHANGED
@@ -1,3908 +1,122 @@
|
|
1
|
-
/************************************************
|
2
|
-
|
3
|
-
pg.c -
|
4
|
-
|
5
|
-
Author: matz
|
6
|
-
created at: Tue May 13 20:07:35 JST 1997
|
7
|
-
|
8
|
-
Author: ematsu
|
9
|
-
modified at: Wed Jan 20 16:41:51 1999
|
10
|
-
|
11
|
-
$Author$
|
12
|
-
$Date$
|
13
|
-
************************************************/
|
14
|
-
|
15
|
-
#include "pg.h"
|
16
|
-
#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
|
17
|
-
# define M17N_SUPPORTED
|
18
|
-
#endif
|
19
|
-
|
20
|
-
#ifdef _WIN32
|
21
|
-
// for O_RDWR and O_BINARY
|
22
|
-
#include <fcntl.h>
|
23
|
-
#endif
|
24
|
-
|
25
|
-
#define rb_define_singleton_alias(klass,new,old) rb_define_alias(rb_singleton_class(klass),new,old)
|
26
|
-
|
27
|
-
static VALUE rb_cPGconn;
|
28
|
-
static VALUE rb_cPGresult;
|
29
|
-
static VALUE rb_ePGError;
|
30
|
-
|
31
|
-
static const char *VERSION = "0.12.2";
|
32
|
-
|
33
|
-
|
34
|
-
/* The following functions are part of libpq, but not
|
35
|
-
* available from ruby-pg, because they are deprecated,
|
36
|
-
* obsolete, or generally not useful:
|
37
|
-
*
|
38
|
-
* * PQfreemem -- unnecessary: copied to ruby object, then
|
39
|
-
* freed. Ruby object's memory is freed when
|
40
|
-
* it is garbage collected.
|
41
|
-
* * PQbinaryTuples -- better to use PQfformat
|
42
|
-
* * PQprint -- not very useful
|
43
|
-
* * PQsetdb -- not very useful
|
44
|
-
* * PQoidStatus -- deprecated, use PQoidValue
|
45
|
-
* * PQrequestCancel -- deprecated, use PQcancel
|
46
|
-
* * PQfn -- use a prepared statement instead
|
47
|
-
* * PQgetline -- deprecated, use PQgetCopyData
|
48
|
-
* * PQgetlineAsync -- deprecated, use PQgetCopyData
|
49
|
-
* * PQputline -- deprecated, use PQputCopyData
|
50
|
-
* * PQputnbytes -- deprecated, use PQputCopyData
|
51
|
-
* * PQendcopy -- deprecated, use PQputCopyEnd
|
52
|
-
*/
|
53
|
-
|
54
|
-
/***************************************************************************
|
55
|
-
* UTILITY FUNCTIONS
|
56
|
-
**************************************************************************/
|
57
|
-
|
58
|
-
static void free_pgconn( PGconn * );
|
59
|
-
static void pgresult_check( VALUE, VALUE );
|
60
|
-
|
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 );
|
66
|
-
|
67
|
-
#ifdef M17N_SUPPORTED
|
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 );
|
72
|
-
#else
|
73
|
-
# define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
|
74
|
-
#endif
|
75
|
-
|
76
|
-
static PQnoticeReceiver default_notice_receiver = NULL;
|
77
|
-
static PQnoticeProcessor default_notice_processor = NULL;
|
78
|
-
|
79
|
-
|
80
|
-
static void
|
81
|
-
free_pgconn(PGconn *conn)
|
82
|
-
{
|
83
|
-
if(conn != NULL)
|
84
|
-
PQfinish(conn);
|
85
|
-
}
|
86
|
-
|
87
|
-
static void
|
88
|
-
free_pgresult(PGresult *result)
|
89
|
-
{
|
90
|
-
if(result != NULL)
|
91
|
-
PQclear(result);
|
92
|
-
}
|
93
|
-
|
94
|
-
static PGconn*
|
95
|
-
get_pgconn(VALUE self)
|
96
|
-
{
|
97
|
-
PGconn *conn;
|
98
|
-
Data_Get_Struct(self, PGconn, conn);
|
99
|
-
if (conn == NULL) rb_raise(rb_ePGError, "not connected");
|
100
|
-
return conn;
|
101
|
-
}
|
102
|
-
|
103
|
-
static PGresult*
|
104
|
-
get_pgresult(VALUE self)
|
105
|
-
{
|
106
|
-
PGresult *result;
|
107
|
-
Data_Get_Struct(self, PGresult, result);
|
108
|
-
if (result == NULL) rb_raise(rb_ePGError, "result has been cleared");
|
109
|
-
return result;
|
110
|
-
}
|
111
|
-
|
112
|
-
#ifdef M17N_SUPPORTED
|
113
|
-
static VALUE
|
114
|
-
new_pgresult(PGresult *result, PGconn *conn)
|
115
|
-
{
|
116
|
-
VALUE val = Data_Wrap_Struct(rb_cPGresult, NULL, free_pgresult, result);
|
117
|
-
rb_encoding *enc = pgconn_get_client_encoding_as_rb_encoding(conn);
|
118
|
-
rb_enc_set_index(val, rb_enc_to_index(enc));
|
119
|
-
return val;
|
120
|
-
}
|
121
|
-
#else
|
122
|
-
static VALUE
|
123
|
-
new_pgresult(PGresult *result)
|
124
|
-
{
|
125
|
-
return Data_Wrap_Struct(rb_cPGresult, NULL, free_pgresult, result);
|
126
|
-
}
|
127
|
-
# define new_pgresult(result, conn) new_pgresult((result))
|
128
|
-
#endif
|
129
|
-
|
130
|
-
/*
|
131
|
-
* Raises appropriate exception if PGresult is
|
132
|
-
* in a bad state.
|
133
|
-
*/
|
134
|
-
static void
|
135
|
-
pgresult_check(VALUE rb_pgconn, VALUE rb_pgresult)
|
136
|
-
{
|
137
|
-
VALUE error, exception;
|
138
|
-
PGconn *conn = get_pgconn(rb_pgconn);
|
139
|
-
PGresult *result;
|
140
|
-
Data_Get_Struct(rb_pgresult, PGresult, result);
|
141
|
-
#ifdef M17N_SUPPORTED
|
142
|
-
rb_encoding *enc = pgconn_get_client_encoding_as_rb_encoding(conn);
|
143
|
-
#endif
|
144
|
-
|
145
|
-
if(result == NULL)
|
146
|
-
{
|
147
|
-
error = rb_str_new2( PQerrorMessage(conn) );
|
148
|
-
}
|
149
|
-
else
|
150
|
-
{
|
151
|
-
switch (PQresultStatus(result))
|
152
|
-
{
|
153
|
-
case PGRES_TUPLES_OK:
|
154
|
-
case PGRES_COPY_OUT:
|
155
|
-
case PGRES_COPY_IN:
|
156
|
-
case PGRES_EMPTY_QUERY:
|
157
|
-
case PGRES_COMMAND_OK:
|
158
|
-
return;
|
159
|
-
case PGRES_BAD_RESPONSE:
|
160
|
-
case PGRES_FATAL_ERROR:
|
161
|
-
case PGRES_NONFATAL_ERROR:
|
162
|
-
error = rb_str_new2( PQresultErrorMessage(result) );
|
163
|
-
break;
|
164
|
-
default:
|
165
|
-
error = rb_str_new2( "internal error : unknown result status." );
|
166
|
-
}
|
167
|
-
}
|
168
|
-
|
169
|
-
#ifdef M17N_SUPPORTED
|
170
|
-
rb_enc_set_index( error, rb_enc_to_index(enc) );
|
171
|
-
#endif
|
172
|
-
exception = rb_exc_new3( rb_ePGError, error );
|
173
|
-
rb_iv_set( exception, "@connection", rb_pgconn );
|
174
|
-
rb_iv_set( exception, "@result", rb_pgresult );
|
175
|
-
rb_exc_raise( exception );
|
176
|
-
|
177
|
-
return;
|
178
|
-
}
|
179
|
-
|
180
|
-
static void
|
181
|
-
notice_receiver_proxy(void *arg, const PGresult *result)
|
182
|
-
{
|
183
|
-
VALUE proc;
|
184
|
-
VALUE self = (VALUE)arg;
|
185
|
-
|
186
|
-
if ((proc = rb_iv_get(self, "@notice_receiver")) != Qnil) {
|
187
|
-
rb_funcall(proc, rb_intern("call"), 1,
|
188
|
-
Data_Wrap_Struct(rb_cPGresult, NULL, NULL, (PGresult*)result));
|
189
|
-
}
|
190
|
-
return;
|
191
|
-
}
|
192
|
-
|
193
|
-
static void
|
194
|
-
notice_processor_proxy(void *arg, const char *message)
|
195
|
-
{
|
196
|
-
VALUE proc;
|
197
|
-
VALUE self = (VALUE)arg;
|
198
|
-
|
199
|
-
if ((proc = rb_iv_get(self, "@notice_processor")) != Qnil) {
|
200
|
-
rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(message));
|
201
|
-
}
|
202
|
-
return;
|
203
|
-
}
|
204
|
-
|
205
|
-
|
206
|
-
/********************************************************************
|
207
|
-
*
|
208
|
-
* Document-class: PGError
|
209
|
-
*
|
210
|
-
* This is the exception class raised when an error is returned from
|
211
|
-
* a libpq API call.
|
212
|
-
*
|
213
|
-
* The attributes +connection+ and +result+ are set to the connection
|
214
|
-
* object and result set object, respectively.
|
215
|
-
*
|
216
|
-
* If the connection object or result set object is not available from
|
217
|
-
* the context in which the error was encountered, it is +nil+.
|
218
|
-
*/
|
219
|
-
|
220
|
-
/********************************************************************
|
221
|
-
*
|
222
|
-
* Document-class: PGconn
|
223
|
-
*
|
224
|
-
* The class to access PostgreSQL RDBMS, based on the libpq interface,
|
225
|
-
* provides convenient OO methods to interact with PostgreSQL.
|
226
|
-
*
|
227
|
-
* For example, to send query to the database on the localhost:
|
228
|
-
* require 'pg'
|
229
|
-
* conn = PGconn.open(:dbname => 'test')
|
230
|
-
* res = conn.exec('SELECT $1 AS a, $2 AS b, $3 AS c',[1, 2, nil])
|
231
|
-
* # Equivalent to:
|
232
|
-
* # res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
|
233
|
-
*
|
234
|
-
* See the PGresult class for information on working with the results of a query.
|
235
|
-
*
|
236
|
-
*/
|
237
|
-
|
238
|
-
static VALUE
|
239
|
-
pgconn_alloc(VALUE klass)
|
240
|
-
{
|
241
|
-
return Data_Wrap_Struct(klass, NULL, free_pgconn, NULL);
|
242
|
-
}
|
243
|
-
|
244
|
-
/**************************************************************************
|
245
|
-
* PGconn SINGLETON METHODS
|
246
|
-
**************************************************************************/
|
247
|
-
|
248
|
-
/*
|
249
|
-
* Document-method: new
|
250
|
-
*
|
251
|
-
* call-seq:
|
252
|
-
* PGconn.new -> PGconn
|
253
|
-
* PGconn.new(connection_hash) -> PGconn
|
254
|
-
* PGconn.new(connection_string) -> PGconn
|
255
|
-
* PGconn.new(host, port, options, tty, dbname, user, password) -> PGconn
|
256
|
-
*
|
257
|
-
* Create a connection to the specified server.
|
258
|
-
*
|
259
|
-
* [+host+]
|
260
|
-
* server hostname
|
261
|
-
* [+hostaddr+]
|
262
|
-
* server address (avoids hostname lookup, overrides +host+)
|
263
|
-
* [+port+]
|
264
|
-
* server port number
|
265
|
-
* [+dbname+]
|
266
|
-
* connecting database name
|
267
|
-
* [+user+]
|
268
|
-
* login user name
|
269
|
-
* [+password+]
|
270
|
-
* login password
|
271
|
-
* [+connect_timeout+]
|
272
|
-
* maximum time to wait for connection to succeed
|
273
|
-
* [+options+]
|
274
|
-
* backend options
|
275
|
-
* [+tty+]
|
276
|
-
* (ignored in newer versions of PostgreSQL)
|
277
|
-
* [+sslmode+]
|
278
|
-
* (disable|allow|prefer|require)
|
279
|
-
* [+krbsrvname+]
|
280
|
-
* kerberos service name
|
281
|
-
* [+gsslib+]
|
282
|
-
* GSS library to use for GSSAPI authentication
|
283
|
-
* [+service+]
|
284
|
-
* service name to use for additional parameters
|
285
|
-
*
|
286
|
-
* Examples:
|
287
|
-
*
|
288
|
-
* # Connect using all defaults
|
289
|
-
* PGconn.connect
|
290
|
-
*
|
291
|
-
* # As a Hash
|
292
|
-
* PGconn.connect( :dbname => 'test', :port => 5432 )
|
293
|
-
*
|
294
|
-
* # As a String
|
295
|
-
* PGconn.connect( "dbname=test port=5432" )
|
296
|
-
*
|
297
|
-
* # As an Array
|
298
|
-
* PGconn.connect( nil, 5432, nil, nil, 'test', nil, nil )
|
299
|
-
*
|
300
|
-
* If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
|
301
|
-
* connection will have its +client_encoding+ set accordingly.
|
302
|
-
*
|
303
|
-
* Raises a PGError if the connection fails.
|
304
|
-
*/
|
305
|
-
static VALUE
|
306
|
-
pgconn_init(int argc, VALUE *argv, VALUE self)
|
307
|
-
{
|
308
|
-
PGconn *conn = NULL;
|
309
|
-
VALUE conninfo;
|
310
|
-
VALUE error;
|
311
|
-
#ifdef M17N_SUPPORTED
|
312
|
-
rb_encoding *enc;
|
313
|
-
const char *encname;
|
314
|
-
#endif
|
315
|
-
|
316
|
-
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
317
|
-
conn = PQconnectdb(StringValuePtr(conninfo));
|
318
|
-
|
319
|
-
if(conn == NULL)
|
320
|
-
rb_raise(rb_ePGError, "PQconnectStart() unable to allocate structure");
|
321
|
-
|
322
|
-
Check_Type(self, T_DATA);
|
323
|
-
DATA_PTR(self) = conn;
|
324
|
-
|
325
|
-
if (PQstatus(conn) == CONNECTION_BAD) {
|
326
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
327
|
-
rb_iv_set(error, "@connection", self);
|
328
|
-
rb_exc_raise(error);
|
329
|
-
}
|
330
|
-
|
331
|
-
#ifdef M17N_SUPPORTED
|
332
|
-
/* If Ruby has its Encoding.default_internal set, set PostgreSQL's client_encoding
|
333
|
-
* to match */
|
334
|
-
if (( enc = rb_default_internal_encoding() )) {
|
335
|
-
encname = pgconn_get_rb_encoding_as_pg_encname( enc );
|
336
|
-
if ( PQsetClientEncoding(conn, encname) != 0 )
|
337
|
-
rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
|
338
|
-
encname, PQerrorMessage(conn) );
|
339
|
-
}
|
340
|
-
#endif
|
341
|
-
|
342
|
-
if (rb_block_given_p()) {
|
343
|
-
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
344
|
-
}
|
345
|
-
return self;
|
346
|
-
}
|
347
|
-
|
348
|
-
/*
|
349
|
-
* call-seq:
|
350
|
-
* PGconn.connect_start(connection_hash) -> PGconn
|
351
|
-
* PGconn.connect_start(connection_string) -> PGconn
|
352
|
-
* PGconn.connect_start(host, port, options, tty, dbname, login, password) -> PGconn
|
353
|
-
*
|
354
|
-
* This is an asynchronous version of PGconn.connect().
|
355
|
-
*
|
356
|
-
* Use PGconn#connect_poll to poll the status of the connection.
|
357
|
-
*
|
358
|
-
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
359
|
-
* Encoding.default_internal is set. To set it after the connection is established,
|
360
|
-
* call PGconn#internal_encoding=. You can also set it automatically by setting
|
361
|
-
* ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
|
362
|
-
*
|
363
|
-
*/
|
364
|
-
static VALUE
|
365
|
-
pgconn_s_connect_start(int argc, VALUE *argv, VALUE self)
|
366
|
-
{
|
367
|
-
PGconn *conn = NULL;
|
368
|
-
VALUE rb_conn;
|
369
|
-
VALUE conninfo;
|
370
|
-
VALUE error;
|
371
|
-
|
372
|
-
/*
|
373
|
-
* PGconn.connect_start must act as both alloc() and initialize()
|
374
|
-
* because it is not invoked by calling new().
|
375
|
-
*/
|
376
|
-
rb_conn = pgconn_alloc(rb_cPGconn);
|
377
|
-
|
378
|
-
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
379
|
-
conn = PQconnectStart(StringValuePtr(conninfo));
|
380
|
-
|
381
|
-
if(conn == NULL)
|
382
|
-
rb_raise(rb_ePGError, "PQconnectStart() unable to allocate structure");
|
383
|
-
if (PQstatus(conn) == CONNECTION_BAD) {
|
384
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
385
|
-
rb_iv_set(error, "@connection", self);
|
386
|
-
rb_exc_raise(error);
|
387
|
-
}
|
388
|
-
|
389
|
-
Check_Type(rb_conn, T_DATA);
|
390
|
-
DATA_PTR(rb_conn) = conn;
|
391
|
-
|
392
|
-
if (rb_block_given_p()) {
|
393
|
-
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
394
|
-
}
|
395
|
-
return rb_conn;
|
396
|
-
}
|
397
|
-
|
398
|
-
/*
|
399
|
-
* call-seq:
|
400
|
-
* PGconn.conndefaults() -> Array
|
401
|
-
*
|
402
|
-
* Returns an array of hashes. Each hash has the keys:
|
403
|
-
* [+:keyword+]
|
404
|
-
* the name of the option
|
405
|
-
* [+:envvar+]
|
406
|
-
* the environment variable to fall back to
|
407
|
-
* [+:compiled+]
|
408
|
-
* the compiled in option as a secondary fallback
|
409
|
-
* [+:val+]
|
410
|
-
* the option's current value, or +nil+ if not known
|
411
|
-
* [+:label+]
|
412
|
-
* the label for the field
|
413
|
-
* [+:dispchar+]
|
414
|
-
* "" for normal, "D" for debug, and "*" for password
|
415
|
-
* [+:dispsize+]
|
416
|
-
* field size
|
417
|
-
*/
|
418
|
-
static VALUE
|
419
|
-
pgconn_s_conndefaults(VALUE self)
|
420
|
-
{
|
421
|
-
PQconninfoOption *options = PQconndefaults();
|
422
|
-
VALUE ary = rb_ary_new();
|
423
|
-
VALUE hash;
|
424
|
-
int i = 0;
|
425
|
-
|
426
|
-
for(i = 0; options[i].keyword != NULL; i++) {
|
427
|
-
hash = rb_hash_new();
|
428
|
-
if(options[i].keyword)
|
429
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("keyword")),
|
430
|
-
rb_str_new2(options[i].keyword));
|
431
|
-
if(options[i].envvar)
|
432
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("envvar")),
|
433
|
-
rb_str_new2(options[i].envvar));
|
434
|
-
if(options[i].compiled)
|
435
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("compiled")),
|
436
|
-
rb_str_new2(options[i].compiled));
|
437
|
-
if(options[i].val)
|
438
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("val")),
|
439
|
-
rb_str_new2(options[i].val));
|
440
|
-
if(options[i].label)
|
441
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("label")),
|
442
|
-
rb_str_new2(options[i].label));
|
443
|
-
if(options[i].dispchar)
|
444
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("dispchar")),
|
445
|
-
rb_str_new2(options[i].dispchar));
|
446
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("dispsize")),
|
447
|
-
INT2NUM(options[i].dispsize));
|
448
|
-
rb_ary_push(ary, hash);
|
449
|
-
}
|
450
|
-
PQconninfoFree(options);
|
451
|
-
return ary;
|
452
|
-
}
|
453
|
-
|
454
|
-
|
455
|
-
/*
|
456
|
-
* call-seq:
|
457
|
-
* PGconn.encrypt_password( password, username ) -> String
|
458
|
-
*
|
459
|
-
* This function is intended to be used by client applications that
|
460
|
-
* send commands like: +ALTER USER joe PASSWORD 'pwd'+.
|
461
|
-
* The arguments are the cleartext password, and the SQL name
|
462
|
-
* of the user it is for.
|
463
|
-
*
|
464
|
-
* Return value is the encrypted password.
|
465
|
-
*/
|
466
|
-
static VALUE
|
467
|
-
pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
468
|
-
{
|
469
|
-
char *encrypted = NULL;
|
470
|
-
VALUE rval = Qnil;
|
471
|
-
|
472
|
-
Check_Type(password, T_STRING);
|
473
|
-
Check_Type(username, T_STRING);
|
474
|
-
|
475
|
-
encrypted = PQencryptPassword(StringValuePtr(password), StringValuePtr(username));
|
476
|
-
rval = rb_str_new2( encrypted );
|
477
|
-
PQfreemem( encrypted );
|
478
|
-
|
479
|
-
OBJ_INFECT( rval, password );
|
480
|
-
OBJ_INFECT( rval, username );
|
481
|
-
|
482
|
-
return rval;
|
483
|
-
}
|
484
|
-
|
485
|
-
|
486
|
-
/*
|
487
|
-
* call-seq:
|
488
|
-
* PGconn.isthreadsafe() -> Boolean
|
489
|
-
*
|
490
|
-
* Returns +true+ if libpq is thread safe, +false+ otherwise.
|
491
|
-
*/
|
492
|
-
static VALUE
|
493
|
-
pgconn_s_isthreadsafe(VALUE self)
|
494
|
-
{
|
495
|
-
return PQisthreadsafe() ? Qtrue : Qfalse;
|
496
|
-
}
|
497
|
-
|
498
|
-
/**************************************************************************
|
499
|
-
* PGconn INSTANCE METHODS
|
500
|
-
**************************************************************************/
|
501
|
-
|
502
|
-
/*
|
503
|
-
* call-seq:
|
504
|
-
* conn.connect_poll() -> Fixnum
|
505
|
-
*
|
506
|
-
* Returns one of:
|
507
|
-
* [+PGRES_POLLING_READING+]
|
508
|
-
* wait until the socket is ready to read
|
509
|
-
* [+PGRES_POLLING_WRITING+]
|
510
|
-
* wait until the socket is ready to write
|
511
|
-
* [+PGRES_POLLING_FAILED+]
|
512
|
-
* the asynchronous connection has failed
|
513
|
-
* [+PGRES_POLLING_OK+]
|
514
|
-
* the asynchronous connection is ready
|
515
|
-
*
|
516
|
-
* Example:
|
517
|
-
* conn = PGconn.connect_start("dbname=mydatabase")
|
518
|
-
* socket = IO.for_fd(conn.socket)
|
519
|
-
* status = conn.connect_poll
|
520
|
-
* while(status != PGconn::PGRES_POLLING_OK) do
|
521
|
-
* # do some work while waiting for the connection to complete
|
522
|
-
* if(status == PGconn::PGRES_POLLING_READING)
|
523
|
-
* if(not select([socket], [], [], 10.0))
|
524
|
-
* raise "Asynchronous connection timed out!"
|
525
|
-
* end
|
526
|
-
* elsif(status == PGconn::PGRES_POLLING_WRITING)
|
527
|
-
* if(not select([], [socket], [], 10.0))
|
528
|
-
* raise "Asynchronous connection timed out!"
|
529
|
-
* end
|
530
|
-
* end
|
531
|
-
* status = conn.connect_poll
|
532
|
-
* end
|
533
|
-
* # now conn.status == CONNECTION_OK, and connection
|
534
|
-
* # is ready.
|
535
|
-
*/
|
536
|
-
static VALUE
|
537
|
-
pgconn_connect_poll(VALUE self)
|
538
|
-
{
|
539
|
-
PostgresPollingStatusType status;
|
540
|
-
status = PQconnectPoll(get_pgconn(self));
|
541
|
-
return INT2FIX((int)status);
|
542
|
-
}
|
543
|
-
|
544
|
-
/*
|
545
|
-
* call-seq:
|
546
|
-
* conn.finish()
|
547
|
-
*
|
548
|
-
* Closes the backend connection.
|
549
|
-
*/
|
550
|
-
static VALUE
|
551
|
-
pgconn_finish(VALUE self)
|
552
|
-
{
|
553
|
-
PQfinish(get_pgconn(self));
|
554
|
-
DATA_PTR(self) = NULL;
|
555
|
-
return Qnil;
|
556
|
-
}
|
557
|
-
|
558
|
-
/*
|
559
|
-
* call-seq:
|
560
|
-
* conn.reset()
|
561
|
-
*
|
562
|
-
* Resets the backend connection. This method closes the
|
563
|
-
* backend connection and tries to re-connect.
|
564
|
-
*/
|
565
|
-
static VALUE
|
566
|
-
pgconn_reset(VALUE self)
|
567
|
-
{
|
568
|
-
PQreset(get_pgconn(self));
|
569
|
-
return self;
|
570
|
-
}
|
571
|
-
|
572
|
-
/*
|
573
|
-
* call-seq:
|
574
|
-
* conn.reset_start() -> nil
|
575
|
-
*
|
576
|
-
* Initiate a connection reset in a nonblocking manner.
|
577
|
-
* This will close the current connection and attempt to
|
578
|
-
* reconnect using the same connection parameters.
|
579
|
-
* Use PGconn#reset_poll to check the status of the
|
580
|
-
* connection reset.
|
581
|
-
*/
|
582
|
-
static VALUE
|
583
|
-
pgconn_reset_start(VALUE self)
|
584
|
-
{
|
585
|
-
if(PQresetStart(get_pgconn(self)) == 0)
|
586
|
-
rb_raise(rb_ePGError, "reset has failed");
|
587
|
-
return Qnil;
|
588
|
-
}
|
589
|
-
|
590
|
-
/*
|
591
|
-
* call-seq:
|
592
|
-
* conn.reset_poll -> Fixnum
|
593
|
-
*
|
594
|
-
* Checks the status of a connection reset operation.
|
595
|
-
* See PGconn#connect_start and PGconn#connect_poll for
|
596
|
-
* usage information and return values.
|
597
|
-
*/
|
598
|
-
static VALUE
|
599
|
-
pgconn_reset_poll(VALUE self)
|
600
|
-
{
|
601
|
-
PostgresPollingStatusType status;
|
602
|
-
status = PQresetPoll(get_pgconn(self));
|
603
|
-
return INT2FIX((int)status);
|
604
|
-
}
|
605
|
-
|
606
|
-
/*
|
607
|
-
* call-seq:
|
608
|
-
* conn.db()
|
609
|
-
*
|
610
|
-
* Returns the connected database name.
|
611
|
-
*/
|
612
|
-
static VALUE
|
613
|
-
pgconn_db(VALUE self)
|
614
|
-
{
|
615
|
-
char *db = PQdb(get_pgconn(self));
|
616
|
-
if (!db) return Qnil;
|
617
|
-
return rb_tainted_str_new2(db);
|
618
|
-
}
|
619
|
-
|
620
|
-
/*
|
621
|
-
* call-seq:
|
622
|
-
* conn.user()
|
623
|
-
*
|
624
|
-
* Returns the authenticated user name.
|
625
|
-
*/
|
626
|
-
static VALUE
|
627
|
-
pgconn_user(VALUE self)
|
628
|
-
{
|
629
|
-
char *user = PQuser(get_pgconn(self));
|
630
|
-
if (!user) return Qnil;
|
631
|
-
return rb_tainted_str_new2(user);
|
632
|
-
}
|
633
|
-
|
634
|
-
/*
|
635
|
-
* call-seq:
|
636
|
-
* conn.pass()
|
637
|
-
*
|
638
|
-
* Returns the authenticated user name.
|
639
|
-
*/
|
640
|
-
static VALUE
|
641
|
-
pgconn_pass(VALUE self)
|
642
|
-
{
|
643
|
-
char *user = PQpass(get_pgconn(self));
|
644
|
-
if (!user) return Qnil;
|
645
|
-
return rb_tainted_str_new2(user);
|
646
|
-
}
|
647
|
-
|
648
|
-
/*
|
649
|
-
* call-seq:
|
650
|
-
* conn.host()
|
651
|
-
*
|
652
|
-
* Returns the connected server name.
|
653
|
-
*/
|
654
|
-
static VALUE
|
655
|
-
pgconn_host(VALUE self)
|
656
|
-
{
|
657
|
-
char *host = PQhost(get_pgconn(self));
|
658
|
-
if (!host) return Qnil;
|
659
|
-
return rb_tainted_str_new2(host);
|
660
|
-
}
|
661
|
-
|
662
|
-
/*
|
663
|
-
* call-seq:
|
664
|
-
* conn.port()
|
665
|
-
*
|
666
|
-
* Returns the connected server port number.
|
667
|
-
*/
|
668
|
-
static VALUE
|
669
|
-
pgconn_port(VALUE self)
|
670
|
-
{
|
671
|
-
char* port = PQport(get_pgconn(self));
|
672
|
-
return INT2NUM(atol(port));
|
673
|
-
}
|
674
|
-
|
675
|
-
/*
|
676
|
-
* call-seq:
|
677
|
-
* conn.tty()
|
678
|
-
*
|
679
|
-
* Returns the connected pgtty. (Obsolete)
|
680
|
-
*/
|
681
|
-
static VALUE
|
682
|
-
pgconn_tty(VALUE self)
|
683
|
-
{
|
684
|
-
char *tty = PQtty(get_pgconn(self));
|
685
|
-
if (!tty) return Qnil;
|
686
|
-
return rb_tainted_str_new2(tty);
|
687
|
-
}
|
688
|
-
|
689
|
-
/*
|
690
|
-
* call-seq:
|
691
|
-
* conn.options()
|
692
|
-
*
|
693
|
-
* Returns backend option string.
|
694
|
-
*/
|
695
|
-
static VALUE
|
696
|
-
pgconn_options(VALUE self)
|
697
|
-
{
|
698
|
-
char *options = PQoptions(get_pgconn(self));
|
699
|
-
if (!options) return Qnil;
|
700
|
-
return rb_tainted_str_new2(options);
|
701
|
-
}
|
702
|
-
|
703
|
-
/*
|
704
|
-
* call-seq:
|
705
|
-
* conn.status()
|
706
|
-
*
|
707
|
-
* Returns status of connection : CONNECTION_OK or CONNECTION_BAD
|
708
|
-
*/
|
709
|
-
static VALUE
|
710
|
-
pgconn_status(VALUE self)
|
711
|
-
{
|
712
|
-
return INT2NUM(PQstatus(get_pgconn(self)));
|
713
|
-
}
|
714
|
-
|
715
|
-
/*
|
716
|
-
* call-seq:
|
717
|
-
* conn.transaction_status()
|
718
|
-
*
|
719
|
-
* returns one of the following statuses:
|
720
|
-
* PQTRANS_IDLE = 0 (connection idle)
|
721
|
-
* PQTRANS_ACTIVE = 1 (command in progress)
|
722
|
-
* PQTRANS_INTRANS = 2 (idle, within transaction block)
|
723
|
-
* PQTRANS_INERROR = 3 (idle, within failed transaction)
|
724
|
-
* PQTRANS_UNKNOWN = 4 (cannot determine status)
|
725
|
-
*/
|
726
|
-
static VALUE
|
727
|
-
pgconn_transaction_status(VALUE self)
|
728
|
-
{
|
729
|
-
return INT2NUM(PQtransactionStatus(get_pgconn(self)));
|
730
|
-
}
|
731
|
-
|
732
|
-
/*
|
733
|
-
* call-seq:
|
734
|
-
* conn.parameter_status( param_name ) -> String
|
735
|
-
*
|
736
|
-
* Returns the setting of parameter _param_name_, where
|
737
|
-
* _param_name_ is one of
|
738
|
-
* * +server_version+
|
739
|
-
* * +server_encoding+
|
740
|
-
* * +client_encoding+
|
741
|
-
* * +is_superuser+
|
742
|
-
* * +session_authorization+
|
743
|
-
* * +DateStyle+
|
744
|
-
* * +TimeZone+
|
745
|
-
* * +integer_datetimes+
|
746
|
-
* * +standard_conforming_strings+
|
747
|
-
*
|
748
|
-
* Returns nil if the value of the parameter is not known.
|
749
|
-
*/
|
750
|
-
static VALUE
|
751
|
-
pgconn_parameter_status(VALUE self, VALUE param_name)
|
752
|
-
{
|
753
|
-
const char *ret = PQparameterStatus(get_pgconn(self),
|
754
|
-
StringValuePtr(param_name));
|
755
|
-
if(ret == NULL)
|
756
|
-
return Qnil;
|
757
|
-
else
|
758
|
-
return rb_tainted_str_new2(ret);
|
759
|
-
}
|
760
|
-
|
761
|
-
/*
|
762
|
-
* call-seq:
|
763
|
-
* conn.protocol_version -> Integer
|
764
|
-
*
|
765
|
-
* The 3.0 protocol will normally be used when communicating with PostgreSQL 7.4
|
766
|
-
* or later servers; pre-7.4 servers support only protocol 2.0. (Protocol 1.0 is
|
767
|
-
* obsolete and not supported by libpq.)
|
768
|
-
*/
|
769
|
-
static VALUE
|
770
|
-
pgconn_protocol_version(VALUE self)
|
771
|
-
{
|
772
|
-
return INT2NUM(PQprotocolVersion(get_pgconn(self)));
|
773
|
-
}
|
774
|
-
|
775
|
-
/*
|
776
|
-
* call-seq:
|
777
|
-
* conn.server_version -> Integer
|
778
|
-
*
|
779
|
-
* The number is formed by converting the major, minor, and revision
|
780
|
-
* numbers into two-decimal-digit numbers and appending them together.
|
781
|
-
* For example, version 7.4.2 will be returned as 70402, and version
|
782
|
-
* 8.1 will be returned as 80100 (leading zeroes are not shown). Zero
|
783
|
-
* is returned if the connection is bad.
|
784
|
-
*
|
785
|
-
*/
|
786
|
-
static VALUE
|
787
|
-
pgconn_server_version(VALUE self)
|
788
|
-
{
|
789
|
-
return INT2NUM(PQserverVersion(get_pgconn(self)));
|
790
|
-
}
|
791
|
-
|
792
|
-
/*
|
793
|
-
* call-seq:
|
794
|
-
* conn.error_message -> String
|
795
|
-
*
|
796
|
-
* Returns the error message about connection.
|
797
|
-
*/
|
798
|
-
static VALUE
|
799
|
-
pgconn_error_message(VALUE self)
|
800
|
-
{
|
801
|
-
char *error = PQerrorMessage(get_pgconn(self));
|
802
|
-
if (!error) return Qnil;
|
803
|
-
return rb_tainted_str_new2(error);
|
804
|
-
}
|
805
|
-
|
806
|
-
/*
|
807
|
-
* call-seq:
|
808
|
-
* conn.socket() -> Fixnum
|
809
|
-
*
|
810
|
-
* Returns the socket's file descriptor for this connection.
|
811
|
-
*/
|
812
|
-
static VALUE
|
813
|
-
pgconn_socket(VALUE self)
|
814
|
-
{
|
815
|
-
int sd;
|
816
|
-
if( (sd = PQsocket(get_pgconn(self))) < 0)
|
817
|
-
rb_raise(rb_ePGError, "Can't get socket descriptor");
|
818
|
-
return INT2NUM(sd);
|
819
|
-
}
|
820
|
-
|
821
|
-
|
822
|
-
/*
|
823
|
-
* call-seq:
|
824
|
-
* conn.backend_pid() -> Fixnum
|
825
|
-
*
|
826
|
-
* Returns the process ID of the backend server
|
827
|
-
* process for this connection.
|
828
|
-
* Note that this is a PID on database server host.
|
829
|
-
*/
|
830
|
-
static VALUE
|
831
|
-
pgconn_backend_pid(VALUE self)
|
832
|
-
{
|
833
|
-
return INT2NUM(PQbackendPID(get_pgconn(self)));
|
834
|
-
}
|
835
|
-
|
836
|
-
/*
|
837
|
-
* call-seq:
|
838
|
-
* conn.connection_needs_password() -> Boolean
|
839
|
-
*
|
840
|
-
* Returns +true+ if the authentication method required a
|
841
|
-
* password, but none was available. +false+ otherwise.
|
842
|
-
*/
|
843
|
-
static VALUE
|
844
|
-
pgconn_connection_needs_password(VALUE self)
|
845
|
-
{
|
846
|
-
return PQconnectionNeedsPassword(get_pgconn(self)) ? Qtrue : Qfalse;
|
847
|
-
}
|
848
|
-
|
849
|
-
/*
|
850
|
-
* call-seq:
|
851
|
-
* conn.connection_used_password() -> Boolean
|
852
|
-
*
|
853
|
-
* Returns +true+ if the authentication method used
|
854
|
-
* a caller-supplied password, +false+ otherwise.
|
855
|
-
*/
|
856
|
-
static VALUE
|
857
|
-
pgconn_connection_used_password(VALUE self)
|
858
|
-
{
|
859
|
-
return PQconnectionUsedPassword(get_pgconn(self)) ? Qtrue : Qfalse;
|
860
|
-
}
|
861
|
-
|
862
|
-
|
863
|
-
//TODO get_ssl
|
864
|
-
|
865
|
-
|
866
|
-
/*
|
867
|
-
* call-seq:
|
868
|
-
* conn.exec(sql [, params, result_format ] ) -> PGresult
|
869
|
-
* conn.exec(sql [, params, result_format ] ) {|pg_result| block }
|
870
|
-
*
|
871
|
-
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
872
|
-
* Returns a PGresult instance on success.
|
873
|
-
* On failure, it raises a PGError exception.
|
874
|
-
*
|
875
|
-
* +params+ is an optional array of the bind parameters for the SQL query.
|
876
|
-
* Each element of the +params+ array may be either:
|
877
|
-
* a hash of the form:
|
878
|
-
* {:value => String (value of bind parameter)
|
879
|
-
* :type => Fixnum (oid of type of bind parameter)
|
880
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
881
|
-
* }
|
882
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
883
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
884
|
-
*
|
885
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
886
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
887
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
888
|
-
*
|
889
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
890
|
-
* Instead of specifying type oids, it's recommended to simply add
|
891
|
-
* explicit casts in the query to ensure that the right type is used.
|
892
|
-
*
|
893
|
-
* For example: "SELECT $1::int"
|
894
|
-
*
|
895
|
-
* The optional +result_format+ should be 0 for text results, 1
|
896
|
-
* for binary.
|
897
|
-
*
|
898
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
899
|
-
* and the PGresult object will automatically be cleared when the block terminates.
|
900
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
901
|
-
*/
|
902
|
-
static VALUE
|
903
|
-
pgconn_exec(int argc, VALUE *argv, VALUE self)
|
904
|
-
{
|
905
|
-
PGconn *conn = get_pgconn(self);
|
906
|
-
PGresult *result = NULL;
|
907
|
-
VALUE rb_pgresult;
|
908
|
-
VALUE command, params, in_res_fmt;
|
909
|
-
VALUE param, param_type, param_value, param_format;
|
910
|
-
VALUE param_value_tmp;
|
911
|
-
VALUE sym_type, sym_value, sym_format;
|
912
|
-
VALUE gc_array;
|
913
|
-
int i=0;
|
914
|
-
int nParams;
|
915
|
-
Oid *paramTypes;
|
916
|
-
char ** paramValues;
|
917
|
-
int *paramLengths;
|
918
|
-
int *paramFormats;
|
919
|
-
int resultFormat;
|
920
|
-
|
921
|
-
rb_scan_args(argc, argv, "12", &command, ¶ms, &in_res_fmt);
|
922
|
-
|
923
|
-
Check_Type(command, T_STRING);
|
924
|
-
|
925
|
-
/* If called with no parameters, use PQexec */
|
926
|
-
if(NIL_P(params)) {
|
927
|
-
result = PQexec(conn, StringValuePtr(command));
|
928
|
-
rb_pgresult = new_pgresult(result, conn);
|
929
|
-
pgresult_check(self, rb_pgresult);
|
930
|
-
if (rb_block_given_p()) {
|
931
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
932
|
-
pgresult_clear, rb_pgresult);
|
933
|
-
}
|
934
|
-
return rb_pgresult;
|
935
|
-
}
|
936
|
-
|
937
|
-
/* If called with parameters, and optionally result_format,
|
938
|
-
* use PQexecParams
|
939
|
-
*/
|
940
|
-
Check_Type(params, T_ARRAY);
|
941
|
-
|
942
|
-
if(NIL_P(in_res_fmt)) {
|
943
|
-
resultFormat = 0;
|
944
|
-
}
|
945
|
-
else {
|
946
|
-
resultFormat = NUM2INT(in_res_fmt);
|
947
|
-
}
|
948
|
-
|
949
|
-
gc_array = rb_ary_new();
|
950
|
-
rb_gc_register_address(&gc_array);
|
951
|
-
sym_type = ID2SYM(rb_intern("type"));
|
952
|
-
sym_value = ID2SYM(rb_intern("value"));
|
953
|
-
sym_format = ID2SYM(rb_intern("format"));
|
954
|
-
nParams = RARRAY_LEN(params);
|
955
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
956
|
-
paramValues = ALLOC_N(char *, nParams);
|
957
|
-
paramLengths = ALLOC_N(int, nParams);
|
958
|
-
paramFormats = ALLOC_N(int, nParams);
|
959
|
-
for(i = 0; i < nParams; i++) {
|
960
|
-
param = rb_ary_entry(params, i);
|
961
|
-
if (TYPE(param) == T_HASH) {
|
962
|
-
param_type = rb_hash_aref(param, sym_type);
|
963
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
964
|
-
if(param_value_tmp == Qnil)
|
965
|
-
param_value = param_value_tmp;
|
966
|
-
else
|
967
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
968
|
-
param_format = rb_hash_aref(param, sym_format);
|
969
|
-
}
|
970
|
-
else {
|
971
|
-
param_type = Qnil;
|
972
|
-
if(param == Qnil)
|
973
|
-
param_value = param;
|
974
|
-
else
|
975
|
-
param_value = rb_obj_as_string(param);
|
976
|
-
param_format = Qnil;
|
977
|
-
}
|
978
|
-
|
979
|
-
if(param_type == Qnil)
|
980
|
-
paramTypes[i] = 0;
|
981
|
-
else
|
982
|
-
paramTypes[i] = NUM2INT(param_type);
|
983
|
-
|
984
|
-
if(param_value == Qnil) {
|
985
|
-
paramValues[i] = NULL;
|
986
|
-
paramLengths[i] = 0;
|
987
|
-
}
|
988
|
-
else {
|
989
|
-
Check_Type(param_value, T_STRING);
|
990
|
-
/* make sure param_value doesn't get freed by the GC */
|
991
|
-
rb_ary_push(gc_array, param_value);
|
992
|
-
paramValues[i] = StringValuePtr(param_value);
|
993
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
994
|
-
}
|
995
|
-
|
996
|
-
if(param_format == Qnil)
|
997
|
-
paramFormats[i] = 0;
|
998
|
-
else
|
999
|
-
paramFormats[i] = NUM2INT(param_format);
|
1000
|
-
}
|
1001
|
-
|
1002
|
-
result = PQexecParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1003
|
-
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1004
|
-
|
1005
|
-
rb_gc_unregister_address(&gc_array);
|
1006
|
-
|
1007
|
-
xfree(paramTypes);
|
1008
|
-
xfree(paramValues);
|
1009
|
-
xfree(paramLengths);
|
1010
|
-
xfree(paramFormats);
|
1011
|
-
|
1012
|
-
rb_pgresult = new_pgresult(result, conn);
|
1013
|
-
pgresult_check(self, rb_pgresult);
|
1014
|
-
if (rb_block_given_p()) {
|
1015
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1016
|
-
pgresult_clear, rb_pgresult);
|
1017
|
-
}
|
1018
|
-
return rb_pgresult;
|
1019
|
-
}
|
1020
|
-
|
1021
|
-
/*
|
1022
|
-
* call-seq:
|
1023
|
-
* conn.prepare(stmt_name, sql [, param_types ] ) -> PGresult
|
1024
|
-
*
|
1025
|
-
* Prepares statement _sql_ with name _name_ to be executed later.
|
1026
|
-
* Returns a PGresult instance on success.
|
1027
|
-
* On failure, it raises a PGError exception.
|
1028
|
-
*
|
1029
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1030
|
-
* types of the parameters.
|
1031
|
-
*
|
1032
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1033
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1034
|
-
* explicit casts in the query to ensure that the right type is used.
|
1035
|
-
*
|
1036
|
-
* For example: "SELECT $1::int"
|
1037
|
-
*
|
1038
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1039
|
-
* inside the SQL query.
|
1040
|
-
*/
|
1041
|
-
static VALUE
|
1042
|
-
pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
1043
|
-
{
|
1044
|
-
PGconn *conn = get_pgconn(self);
|
1045
|
-
PGresult *result = NULL;
|
1046
|
-
VALUE rb_pgresult;
|
1047
|
-
VALUE name, command, in_paramtypes;
|
1048
|
-
VALUE param;
|
1049
|
-
int i = 0;
|
1050
|
-
int nParams = 0;
|
1051
|
-
Oid *paramTypes = NULL;
|
1052
|
-
|
1053
|
-
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1054
|
-
Check_Type(name, T_STRING);
|
1055
|
-
Check_Type(command, T_STRING);
|
1056
|
-
|
1057
|
-
if(! NIL_P(in_paramtypes)) {
|
1058
|
-
Check_Type(in_paramtypes, T_ARRAY);
|
1059
|
-
nParams = RARRAY_LEN(in_paramtypes);
|
1060
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1061
|
-
for(i = 0; i < nParams; i++) {
|
1062
|
-
param = rb_ary_entry(in_paramtypes, i);
|
1063
|
-
Check_Type(param, T_FIXNUM);
|
1064
|
-
if(param == Qnil)
|
1065
|
-
paramTypes[i] = 0;
|
1066
|
-
else
|
1067
|
-
paramTypes[i] = NUM2INT(param);
|
1068
|
-
}
|
1069
|
-
}
|
1070
|
-
result = PQprepare(conn, StringValuePtr(name), StringValuePtr(command),
|
1071
|
-
nParams, paramTypes);
|
1072
|
-
|
1073
|
-
xfree(paramTypes);
|
1074
|
-
|
1075
|
-
rb_pgresult = new_pgresult(result, conn);
|
1076
|
-
pgresult_check(self, rb_pgresult);
|
1077
|
-
return rb_pgresult;
|
1078
|
-
}
|
1079
|
-
|
1080
|
-
/*
|
1081
|
-
* call-seq:
|
1082
|
-
* conn.exec_prepared(statement_name [, params, result_format ] ) -> PGresult
|
1083
|
-
* conn.exec_prepared(statement_name [, params, result_format ] ) {|pg_result| block }
|
1084
|
-
*
|
1085
|
-
* Execute prepared named statement specified by _statement_name_.
|
1086
|
-
* Returns a PGresult instance on success.
|
1087
|
-
* On failure, it raises a PGError exception.
|
1088
|
-
*
|
1089
|
-
* +params+ is an array of the optional bind parameters for the
|
1090
|
-
* SQL query. Each element of the +params+ array may be either:
|
1091
|
-
* a hash of the form:
|
1092
|
-
* {:value => String (value of bind parameter)
|
1093
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1094
|
-
* }
|
1095
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1096
|
-
* { :value => <string value>, :format => 0 }
|
1097
|
-
*
|
1098
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1099
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1100
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1101
|
-
*
|
1102
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1103
|
-
* for binary.
|
1104
|
-
*
|
1105
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1106
|
-
* and the PGresult object will automatically be cleared when the block terminates.
|
1107
|
-
* In this instance, <code>conn.exec_prepared</code> returns the value of the block.
|
1108
|
-
*/
|
1109
|
-
static VALUE
|
1110
|
-
pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
1111
|
-
{
|
1112
|
-
PGconn *conn = get_pgconn(self);
|
1113
|
-
PGresult *result = NULL;
|
1114
|
-
VALUE rb_pgresult;
|
1115
|
-
VALUE name, params, in_res_fmt;
|
1116
|
-
VALUE param, param_value, param_format;
|
1117
|
-
VALUE param_value_tmp;
|
1118
|
-
VALUE sym_value, sym_format;
|
1119
|
-
VALUE gc_array;
|
1120
|
-
int i = 0;
|
1121
|
-
int nParams;
|
1122
|
-
char ** paramValues;
|
1123
|
-
int *paramLengths;
|
1124
|
-
int *paramFormats;
|
1125
|
-
int resultFormat;
|
1126
|
-
|
1127
|
-
|
1128
|
-
rb_scan_args(argc, argv, "12", &name, ¶ms, &in_res_fmt);
|
1129
|
-
Check_Type(name, T_STRING);
|
1130
|
-
|
1131
|
-
if(NIL_P(params)) {
|
1132
|
-
params = rb_ary_new2(0);
|
1133
|
-
resultFormat = 0;
|
1134
|
-
}
|
1135
|
-
else {
|
1136
|
-
Check_Type(params, T_ARRAY);
|
1137
|
-
}
|
1138
|
-
|
1139
|
-
if(NIL_P(in_res_fmt)) {
|
1140
|
-
resultFormat = 0;
|
1141
|
-
}
|
1142
|
-
else {
|
1143
|
-
resultFormat = NUM2INT(in_res_fmt);
|
1144
|
-
}
|
1145
|
-
|
1146
|
-
gc_array = rb_ary_new();
|
1147
|
-
rb_gc_register_address(&gc_array);
|
1148
|
-
sym_value = ID2SYM(rb_intern("value"));
|
1149
|
-
sym_format = ID2SYM(rb_intern("format"));
|
1150
|
-
nParams = RARRAY_LEN(params);
|
1151
|
-
paramValues = ALLOC_N(char *, nParams);
|
1152
|
-
paramLengths = ALLOC_N(int, nParams);
|
1153
|
-
paramFormats = ALLOC_N(int, nParams);
|
1154
|
-
for(i = 0; i < nParams; i++) {
|
1155
|
-
param = rb_ary_entry(params, i);
|
1156
|
-
if (TYPE(param) == T_HASH) {
|
1157
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
1158
|
-
if(param_value_tmp == Qnil)
|
1159
|
-
param_value = param_value_tmp;
|
1160
|
-
else
|
1161
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
1162
|
-
param_format = rb_hash_aref(param, sym_format);
|
1163
|
-
}
|
1164
|
-
else {
|
1165
|
-
if(param == Qnil)
|
1166
|
-
param_value = param;
|
1167
|
-
else
|
1168
|
-
param_value = rb_obj_as_string(param);
|
1169
|
-
param_format = INT2NUM(0);
|
1170
|
-
}
|
1171
|
-
if(param_value == Qnil) {
|
1172
|
-
paramValues[i] = NULL;
|
1173
|
-
paramLengths[i] = 0;
|
1174
|
-
}
|
1175
|
-
else {
|
1176
|
-
Check_Type(param_value, T_STRING);
|
1177
|
-
/* make sure param_value doesn't get freed by the GC */
|
1178
|
-
rb_ary_push(gc_array, param_value);
|
1179
|
-
paramValues[i] = StringValuePtr(param_value);
|
1180
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
1181
|
-
}
|
1182
|
-
|
1183
|
-
if(param_format == Qnil)
|
1184
|
-
paramFormats[i] = 0;
|
1185
|
-
else
|
1186
|
-
paramFormats[i] = NUM2INT(param_format);
|
1187
|
-
}
|
1188
|
-
|
1189
|
-
result = PQexecPrepared(conn, StringValuePtr(name), nParams,
|
1190
|
-
(const char * const *)paramValues, paramLengths, paramFormats,
|
1191
|
-
resultFormat);
|
1192
|
-
|
1193
|
-
rb_gc_unregister_address(&gc_array);
|
1194
|
-
|
1195
|
-
xfree(paramValues);
|
1196
|
-
xfree(paramLengths);
|
1197
|
-
xfree(paramFormats);
|
1198
|
-
|
1199
|
-
rb_pgresult = new_pgresult(result, conn);
|
1200
|
-
pgresult_check(self, rb_pgresult);
|
1201
|
-
if (rb_block_given_p()) {
|
1202
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1203
|
-
pgresult_clear, rb_pgresult);
|
1204
|
-
}
|
1205
|
-
return rb_pgresult;
|
1206
|
-
}
|
1207
|
-
|
1208
|
-
/*
|
1209
|
-
* call-seq:
|
1210
|
-
* conn.describe_prepared( statement_name ) -> PGresult
|
1211
|
-
*
|
1212
|
-
* Retrieve information about the prepared statement
|
1213
|
-
* _statement_name_.
|
1214
|
-
*/
|
1215
|
-
static VALUE
|
1216
|
-
pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
1217
|
-
{
|
1218
|
-
PGresult *result;
|
1219
|
-
VALUE rb_pgresult;
|
1220
|
-
PGconn *conn = get_pgconn(self);
|
1221
|
-
char *stmt;
|
1222
|
-
if(stmt_name == Qnil) {
|
1223
|
-
stmt = NULL;
|
1224
|
-
}
|
1225
|
-
else {
|
1226
|
-
Check_Type(stmt_name, T_STRING);
|
1227
|
-
stmt = StringValuePtr(stmt_name);
|
1228
|
-
}
|
1229
|
-
result = PQdescribePrepared(conn, stmt);
|
1230
|
-
rb_pgresult = new_pgresult(result, conn);
|
1231
|
-
pgresult_check(self, rb_pgresult);
|
1232
|
-
return rb_pgresult;
|
1233
|
-
}
|
1234
|
-
|
1235
|
-
|
1236
|
-
/*
|
1237
|
-
* call-seq:
|
1238
|
-
* conn.describe_portal( portal_name ) -> PGresult
|
1239
|
-
*
|
1240
|
-
* Retrieve information about the portal _portal_name_.
|
1241
|
-
*/
|
1242
|
-
static VALUE
|
1243
|
-
pgconn_describe_portal(self, stmt_name)
|
1244
|
-
VALUE self, stmt_name;
|
1245
|
-
{
|
1246
|
-
PGresult *result;
|
1247
|
-
VALUE rb_pgresult;
|
1248
|
-
PGconn *conn = get_pgconn(self);
|
1249
|
-
char *stmt;
|
1250
|
-
if(stmt_name == Qnil) {
|
1251
|
-
stmt = NULL;
|
1252
|
-
}
|
1253
|
-
else {
|
1254
|
-
Check_Type(stmt_name, T_STRING);
|
1255
|
-
stmt = StringValuePtr(stmt_name);
|
1256
|
-
}
|
1257
|
-
result = PQdescribePortal(conn, stmt);
|
1258
|
-
rb_pgresult = new_pgresult(result, conn);
|
1259
|
-
pgresult_check(self, rb_pgresult);
|
1260
|
-
return rb_pgresult;
|
1261
|
-
}
|
1262
|
-
|
1263
|
-
|
1264
|
-
/*
|
1265
|
-
* call-seq:
|
1266
|
-
* conn.make_empty_pgresult( status ) -> PGresult
|
1267
|
-
*
|
1268
|
-
* Constructs and empty PGresult with status _status_.
|
1269
|
-
* _status_ may be one of:
|
1270
|
-
* * +PGRES_EMPTY_QUERY+
|
1271
|
-
* * +PGRES_COMMAND_OK+
|
1272
|
-
* * +PGRES_TUPLES_OK+
|
1273
|
-
* * +PGRES_COPY_OUT+
|
1274
|
-
* * +PGRES_COPY_IN+
|
1275
|
-
* * +PGRES_BAD_RESPONSE+
|
1276
|
-
* * +PGRES_NONFATAL_ERROR+
|
1277
|
-
* * +PGRES_FATAL_ERROR+
|
1278
|
-
*/
|
1279
|
-
static VALUE
|
1280
|
-
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
1281
|
-
{
|
1282
|
-
PGresult *result;
|
1283
|
-
VALUE rb_pgresult;
|
1284
|
-
PGconn *conn = get_pgconn(self);
|
1285
|
-
result = PQmakeEmptyPGresult(conn, NUM2INT(status));
|
1286
|
-
rb_pgresult = new_pgresult(result, conn);
|
1287
|
-
pgresult_check(self, rb_pgresult);
|
1288
|
-
return rb_pgresult;
|
1289
|
-
}
|
1290
|
-
|
1291
|
-
|
1292
|
-
/*
|
1293
|
-
* call-seq:
|
1294
|
-
* conn.escape_string( str ) -> String
|
1295
|
-
*
|
1296
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1297
|
-
* uses PQescapeStringConn, which is safer. Avoid calling as a class method,
|
1298
|
-
* the class method uses the deprecated PQescapeString() API function.
|
1299
|
-
*
|
1300
|
-
* Returns a SQL-safe version of the String _str_.
|
1301
|
-
* This is the preferred way to make strings safe for inclusion in
|
1302
|
-
* SQL queries.
|
1303
|
-
*
|
1304
|
-
* Consider using exec_params, which avoids the need for passing values
|
1305
|
-
* inside of SQL commands.
|
1306
|
-
*
|
1307
|
-
* Encoding of escaped string will be equal to client encoding of connection.
|
1308
|
-
*/
|
1309
|
-
static VALUE
|
1310
|
-
pgconn_s_escape(VALUE self, VALUE string)
|
1311
|
-
{
|
1312
|
-
char *escaped;
|
1313
|
-
int size,error;
|
1314
|
-
VALUE result;
|
1315
|
-
#ifdef M17N_SUPPORTED
|
1316
|
-
rb_encoding* enc;
|
1317
|
-
#endif
|
1318
|
-
|
1319
|
-
Check_Type(string, T_STRING);
|
1320
|
-
|
1321
|
-
escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
|
1322
|
-
if(rb_obj_class(self) == rb_cPGconn) {
|
1323
|
-
size = PQescapeStringConn(get_pgconn(self), escaped,
|
1324
|
-
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1325
|
-
if(error) {
|
1326
|
-
xfree(escaped);
|
1327
|
-
rb_raise(rb_ePGError, "%s", PQerrorMessage(get_pgconn(self)));
|
1328
|
-
}
|
1329
|
-
} else {
|
1330
|
-
size = PQescapeString(escaped, RSTRING_PTR(string),
|
1331
|
-
RSTRING_LEN(string));
|
1332
|
-
}
|
1333
|
-
result = rb_str_new(escaped, size);
|
1334
|
-
xfree(escaped);
|
1335
|
-
OBJ_INFECT(result, string);
|
1336
|
-
|
1337
|
-
#ifdef M17N_SUPPORTED
|
1338
|
-
if(rb_obj_class(self) == rb_cPGconn) {
|
1339
|
-
enc = pgconn_get_client_encoding_as_rb_encoding(get_pgconn(self));
|
1340
|
-
} else {
|
1341
|
-
enc = rb_enc_get(string);
|
1342
|
-
}
|
1343
|
-
rb_enc_associate(result, enc);
|
1344
|
-
#endif
|
1345
|
-
|
1346
|
-
return result;
|
1347
|
-
}
|
1348
|
-
|
1349
|
-
/*
|
1350
|
-
* call-seq:
|
1351
|
-
* conn.escape_bytea( string ) -> String
|
1352
|
-
*
|
1353
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1354
|
-
* uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
|
1355
|
-
* the class method uses the deprecated PQescapeBytea() API function.
|
1356
|
-
*
|
1357
|
-
* Use the instance method version of this function, it is safer than the
|
1358
|
-
* class method.
|
1359
|
-
*
|
1360
|
-
* Escapes binary data for use within an SQL command with the type +bytea+.
|
1361
|
-
*
|
1362
|
-
* Certain byte values must be escaped (but all byte values may be escaped)
|
1363
|
-
* when used as part of a +bytea+ literal in an SQL statement. In general, to
|
1364
|
-
* escape a byte, it is converted into the three digit octal number equal to
|
1365
|
-
* the octet value, and preceded by two backslashes. The single quote (') and
|
1366
|
-
* backslash (\) characters have special alternative escape sequences.
|
1367
|
-
* #escape_bytea performs this operation, escaping only the minimally required
|
1368
|
-
* bytes.
|
1369
|
-
*
|
1370
|
-
* Consider using exec_params, which avoids the need for passing values inside of
|
1371
|
-
* SQL commands.
|
1372
|
-
*/
|
1373
|
-
static VALUE
|
1374
|
-
pgconn_s_escape_bytea(VALUE self, VALUE str)
|
1375
|
-
{
|
1376
|
-
unsigned char *from, *to;
|
1377
|
-
size_t from_len, to_len;
|
1378
|
-
VALUE ret;
|
1379
|
-
|
1380
|
-
Check_Type(str, T_STRING);
|
1381
|
-
from = (unsigned char*)RSTRING_PTR(str);
|
1382
|
-
from_len = RSTRING_LEN(str);
|
1383
|
-
|
1384
|
-
if(rb_obj_class(self) == rb_cPGconn) {
|
1385
|
-
to = PQescapeByteaConn(get_pgconn(self), from, from_len, &to_len);
|
1386
|
-
} else {
|
1387
|
-
to = PQescapeBytea( from, from_len, &to_len);
|
1388
|
-
}
|
1389
|
-
|
1390
|
-
ret = rb_str_new((char*)to, to_len - 1);
|
1391
|
-
OBJ_INFECT(ret, str);
|
1392
|
-
PQfreemem(to);
|
1393
|
-
return ret;
|
1394
|
-
}
|
1395
|
-
|
1396
|
-
|
1397
|
-
/*
|
1398
|
-
* call-seq:
|
1399
|
-
* PGconn.unescape_bytea( string )
|
1400
|
-
*
|
1401
|
-
* Converts an escaped string representation of binary data into binary data --- the
|
1402
|
-
* reverse of #escape_bytea. This is needed when retrieving +bytea+ data in text format,
|
1403
|
-
* but not when retrieving it in binary format.
|
1404
|
-
*
|
1405
|
-
*/
|
1406
|
-
static VALUE
|
1407
|
-
pgconn_s_unescape_bytea(VALUE self, VALUE str)
|
1408
|
-
{
|
1409
|
-
unsigned char *from, *to;
|
1410
|
-
size_t to_len;
|
1411
|
-
VALUE ret;
|
1412
|
-
|
1413
|
-
Check_Type(str, T_STRING);
|
1414
|
-
from = (unsigned char*)StringValuePtr(str);
|
1415
|
-
|
1416
|
-
to = PQunescapeBytea(from, &to_len);
|
1417
|
-
|
1418
|
-
ret = rb_str_new((char*)to, to_len);
|
1419
|
-
OBJ_INFECT(ret, str);
|
1420
|
-
PQfreemem(to);
|
1421
|
-
return ret;
|
1422
|
-
}
|
1423
|
-
|
1424
|
-
/*
|
1425
|
-
* call-seq:
|
1426
|
-
* conn.send_query(sql [, params, result_format ] ) -> nil
|
1427
|
-
*
|
1428
|
-
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1429
|
-
* asynchronous processing, and immediately returns.
|
1430
|
-
* On failure, it raises a PGError exception.
|
1431
|
-
*
|
1432
|
-
* +params+ is an optional array of the bind parameters for the SQL query.
|
1433
|
-
* Each element of the +params+ array may be either:
|
1434
|
-
* a hash of the form:
|
1435
|
-
* {:value => String (value of bind parameter)
|
1436
|
-
* :type => Fixnum (oid of type of bind parameter)
|
1437
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1438
|
-
* }
|
1439
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1440
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
1441
|
-
*
|
1442
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1443
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1444
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1445
|
-
*
|
1446
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1447
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1448
|
-
* explicit casts in the query to ensure that the right type is used.
|
1449
|
-
*
|
1450
|
-
* For example: "SELECT $1::int"
|
1451
|
-
*
|
1452
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1453
|
-
* for binary.
|
1454
|
-
*/
|
1455
|
-
static VALUE
|
1456
|
-
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1457
|
-
{
|
1458
|
-
PGconn *conn = get_pgconn(self);
|
1459
|
-
int result;
|
1460
|
-
VALUE command, params, in_res_fmt;
|
1461
|
-
VALUE param, param_type, param_value, param_format;
|
1462
|
-
VALUE param_value_tmp;
|
1463
|
-
VALUE sym_type, sym_value, sym_format;
|
1464
|
-
VALUE gc_array;
|
1465
|
-
VALUE error;
|
1466
|
-
int i=0;
|
1467
|
-
int nParams;
|
1468
|
-
Oid *paramTypes;
|
1469
|
-
char ** paramValues;
|
1470
|
-
int *paramLengths;
|
1471
|
-
int *paramFormats;
|
1472
|
-
int resultFormat;
|
1473
|
-
|
1474
|
-
rb_scan_args(argc, argv, "12", &command, ¶ms, &in_res_fmt);
|
1475
|
-
Check_Type(command, T_STRING);
|
1476
|
-
|
1477
|
-
/* If called with no parameters, use PQsendQuery */
|
1478
|
-
if(NIL_P(params)) {
|
1479
|
-
if(PQsendQuery(conn,StringValuePtr(command)) == 0) {
|
1480
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1481
|
-
rb_iv_set(error, "@connection", self);
|
1482
|
-
rb_exc_raise(error);
|
1483
|
-
}
|
1484
|
-
return Qnil;
|
1485
|
-
}
|
1486
|
-
|
1487
|
-
/* If called with parameters, and optionally result_format,
|
1488
|
-
* use PQsendQueryParams
|
1489
|
-
*/
|
1490
|
-
Check_Type(params, T_ARRAY);
|
1491
|
-
|
1492
|
-
if(NIL_P(in_res_fmt)) {
|
1493
|
-
resultFormat = 0;
|
1494
|
-
}
|
1495
|
-
else {
|
1496
|
-
resultFormat = NUM2INT(in_res_fmt);
|
1497
|
-
}
|
1498
|
-
|
1499
|
-
gc_array = rb_ary_new();
|
1500
|
-
rb_gc_register_address(&gc_array);
|
1501
|
-
sym_type = ID2SYM(rb_intern("type"));
|
1502
|
-
sym_value = ID2SYM(rb_intern("value"));
|
1503
|
-
sym_format = ID2SYM(rb_intern("format"));
|
1504
|
-
nParams = RARRAY_LEN(params);
|
1505
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1506
|
-
paramValues = ALLOC_N(char *, nParams);
|
1507
|
-
paramLengths = ALLOC_N(int, nParams);
|
1508
|
-
paramFormats = ALLOC_N(int, nParams);
|
1509
|
-
for(i = 0; i < nParams; i++) {
|
1510
|
-
param = rb_ary_entry(params, i);
|
1511
|
-
if (TYPE(param) == T_HASH) {
|
1512
|
-
param_type = rb_hash_aref(param, sym_type);
|
1513
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
1514
|
-
if(param_value_tmp == Qnil)
|
1515
|
-
param_value = param_value_tmp;
|
1516
|
-
else
|
1517
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
1518
|
-
param_format = rb_hash_aref(param, sym_format);
|
1519
|
-
}
|
1520
|
-
else {
|
1521
|
-
param_type = INT2NUM(0);
|
1522
|
-
if(param == Qnil)
|
1523
|
-
param_value = param;
|
1524
|
-
else
|
1525
|
-
param_value = rb_obj_as_string(param);
|
1526
|
-
param_format = INT2NUM(0);
|
1527
|
-
}
|
1528
|
-
|
1529
|
-
if(param_type == Qnil)
|
1530
|
-
paramTypes[i] = 0;
|
1531
|
-
else
|
1532
|
-
paramTypes[i] = NUM2INT(param_type);
|
1533
|
-
|
1534
|
-
if(param_value == Qnil) {
|
1535
|
-
paramValues[i] = NULL;
|
1536
|
-
paramLengths[i] = 0;
|
1537
|
-
}
|
1538
|
-
else {
|
1539
|
-
Check_Type(param_value, T_STRING);
|
1540
|
-
/* make sure param_value doesn't get freed by the GC */
|
1541
|
-
rb_ary_push(gc_array, param_value);
|
1542
|
-
paramValues[i] = StringValuePtr(param_value);
|
1543
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
1544
|
-
}
|
1545
|
-
|
1546
|
-
if(param_format == Qnil)
|
1547
|
-
paramFormats[i] = 0;
|
1548
|
-
else
|
1549
|
-
paramFormats[i] = NUM2INT(param_format);
|
1550
|
-
}
|
1551
|
-
|
1552
|
-
result = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1553
|
-
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1554
|
-
|
1555
|
-
rb_gc_unregister_address(&gc_array);
|
1556
|
-
|
1557
|
-
xfree(paramTypes);
|
1558
|
-
xfree(paramValues);
|
1559
|
-
xfree(paramLengths);
|
1560
|
-
xfree(paramFormats);
|
1561
|
-
|
1562
|
-
if(result == 0) {
|
1563
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1564
|
-
rb_iv_set(error, "@connection", self);
|
1565
|
-
rb_exc_raise(error);
|
1566
|
-
}
|
1567
|
-
return Qnil;
|
1568
|
-
}
|
1569
|
-
|
1570
|
-
/*
|
1571
|
-
* call-seq:
|
1572
|
-
* conn.send_prepare( stmt_name, sql [, param_types ] ) -> nil
|
1573
|
-
*
|
1574
|
-
* Prepares statement _sql_ with name _name_ to be executed later.
|
1575
|
-
* Sends prepare command asynchronously, and returns immediately.
|
1576
|
-
* On failure, it raises a PGError exception.
|
1577
|
-
*
|
1578
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1579
|
-
* types of the parameters.
|
1580
|
-
*
|
1581
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1582
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1583
|
-
* explicit casts in the query to ensure that the right type is used.
|
1584
|
-
*
|
1585
|
-
* For example: "SELECT $1::int"
|
1586
|
-
*
|
1587
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1588
|
-
* inside the SQL query.
|
1589
|
-
*/
|
1590
|
-
static VALUE
|
1591
|
-
pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
1592
|
-
{
|
1593
|
-
PGconn *conn = get_pgconn(self);
|
1594
|
-
int result;
|
1595
|
-
VALUE name, command, in_paramtypes;
|
1596
|
-
VALUE param;
|
1597
|
-
VALUE error;
|
1598
|
-
int i = 0;
|
1599
|
-
int nParams = 0;
|
1600
|
-
Oid *paramTypes = NULL;
|
1601
|
-
|
1602
|
-
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1603
|
-
Check_Type(name, T_STRING);
|
1604
|
-
Check_Type(command, T_STRING);
|
1605
|
-
|
1606
|
-
if(! NIL_P(in_paramtypes)) {
|
1607
|
-
Check_Type(in_paramtypes, T_ARRAY);
|
1608
|
-
nParams = RARRAY_LEN(in_paramtypes);
|
1609
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1610
|
-
for(i = 0; i < nParams; i++) {
|
1611
|
-
param = rb_ary_entry(in_paramtypes, i);
|
1612
|
-
Check_Type(param, T_FIXNUM);
|
1613
|
-
if(param == Qnil)
|
1614
|
-
paramTypes[i] = 0;
|
1615
|
-
else
|
1616
|
-
paramTypes[i] = NUM2INT(param);
|
1617
|
-
}
|
1618
|
-
}
|
1619
|
-
result = PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
|
1620
|
-
nParams, paramTypes);
|
1621
|
-
|
1622
|
-
xfree(paramTypes);
|
1623
|
-
|
1624
|
-
if(result == 0) {
|
1625
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1626
|
-
rb_iv_set(error, "@connection", self);
|
1627
|
-
rb_exc_raise(error);
|
1628
|
-
}
|
1629
|
-
return Qnil;
|
1630
|
-
}
|
1631
|
-
|
1632
|
-
/*
|
1633
|
-
* call-seq:
|
1634
|
-
* conn.send_query_prepared( statement_name [, params, result_format ] )
|
1635
|
-
* -> nil
|
1636
|
-
*
|
1637
|
-
* Execute prepared named statement specified by _statement_name_
|
1638
|
-
* asynchronously, and returns immediately.
|
1639
|
-
* On failure, it raises a PGError exception.
|
1640
|
-
*
|
1641
|
-
* +params+ is an array of the optional bind parameters for the
|
1642
|
-
* SQL query. Each element of the +params+ array may be either:
|
1643
|
-
* a hash of the form:
|
1644
|
-
* {:value => String (value of bind parameter)
|
1645
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1646
|
-
* }
|
1647
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1648
|
-
* { :value => <string value>, :format => 0 }
|
1649
|
-
*
|
1650
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1651
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1652
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1653
|
-
*
|
1654
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1655
|
-
* for binary.
|
1656
|
-
*/
|
1657
|
-
static VALUE
|
1658
|
-
pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
1659
|
-
{
|
1660
|
-
PGconn *conn = get_pgconn(self);
|
1661
|
-
int result;
|
1662
|
-
VALUE name, params, in_res_fmt;
|
1663
|
-
VALUE param, param_value, param_format;
|
1664
|
-
VALUE param_value_tmp;
|
1665
|
-
VALUE sym_value, sym_format;
|
1666
|
-
VALUE gc_array;
|
1667
|
-
VALUE error;
|
1668
|
-
int i = 0;
|
1669
|
-
int nParams;
|
1670
|
-
char ** paramValues;
|
1671
|
-
int *paramLengths;
|
1672
|
-
int *paramFormats;
|
1673
|
-
int resultFormat;
|
1674
|
-
|
1675
|
-
rb_scan_args(argc, argv, "12", &name, ¶ms, &in_res_fmt);
|
1676
|
-
Check_Type(name, T_STRING);
|
1677
|
-
|
1678
|
-
if(NIL_P(params)) {
|
1679
|
-
params = rb_ary_new2(0);
|
1680
|
-
resultFormat = 0;
|
1681
|
-
}
|
1682
|
-
else {
|
1683
|
-
Check_Type(params, T_ARRAY);
|
1684
|
-
}
|
1685
|
-
|
1686
|
-
if(NIL_P(in_res_fmt)) {
|
1687
|
-
resultFormat = 0;
|
1688
|
-
}
|
1689
|
-
else {
|
1690
|
-
resultFormat = NUM2INT(in_res_fmt);
|
1691
|
-
}
|
1692
|
-
|
1693
|
-
gc_array = rb_ary_new();
|
1694
|
-
rb_gc_register_address(&gc_array);
|
1695
|
-
sym_value = ID2SYM(rb_intern("value"));
|
1696
|
-
sym_format = ID2SYM(rb_intern("format"));
|
1697
|
-
nParams = RARRAY_LEN(params);
|
1698
|
-
paramValues = ALLOC_N(char *, nParams);
|
1699
|
-
paramLengths = ALLOC_N(int, nParams);
|
1700
|
-
paramFormats = ALLOC_N(int, nParams);
|
1701
|
-
for(i = 0; i < nParams; i++) {
|
1702
|
-
param = rb_ary_entry(params, i);
|
1703
|
-
if (TYPE(param) == T_HASH) {
|
1704
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
1705
|
-
if(param_value_tmp == Qnil)
|
1706
|
-
param_value = param_value_tmp;
|
1707
|
-
else
|
1708
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
1709
|
-
param_format = rb_hash_aref(param, sym_format);
|
1710
|
-
}
|
1711
|
-
else {
|
1712
|
-
if(param == Qnil)
|
1713
|
-
param_value = param;
|
1714
|
-
else
|
1715
|
-
param_value = rb_obj_as_string(param);
|
1716
|
-
param_format = INT2NUM(0);
|
1717
|
-
}
|
1718
|
-
|
1719
|
-
if(param_value == Qnil) {
|
1720
|
-
paramValues[i] = NULL;
|
1721
|
-
paramLengths[i] = 0;
|
1722
|
-
}
|
1723
|
-
else {
|
1724
|
-
Check_Type(param_value, T_STRING);
|
1725
|
-
/* make sure param_value doesn't get freed by the GC */
|
1726
|
-
rb_ary_push(gc_array, param_value);
|
1727
|
-
paramValues[i] = StringValuePtr(param_value);
|
1728
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
1729
|
-
}
|
1730
|
-
|
1731
|
-
if(param_format == Qnil)
|
1732
|
-
paramFormats[i] = 0;
|
1733
|
-
else
|
1734
|
-
paramFormats[i] = NUM2INT(param_format);
|
1735
|
-
}
|
1736
|
-
|
1737
|
-
result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
|
1738
|
-
(const char * const *)paramValues, paramLengths, paramFormats,
|
1739
|
-
resultFormat);
|
1740
|
-
|
1741
|
-
rb_gc_unregister_address(&gc_array);
|
1742
|
-
|
1743
|
-
xfree(paramValues);
|
1744
|
-
xfree(paramLengths);
|
1745
|
-
xfree(paramFormats);
|
1746
|
-
|
1747
|
-
if(result == 0) {
|
1748
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1749
|
-
rb_iv_set(error, "@connection", self);
|
1750
|
-
rb_exc_raise(error);
|
1751
|
-
}
|
1752
|
-
return Qnil;
|
1753
|
-
}
|
1754
|
-
|
1755
|
-
/*
|
1756
|
-
* call-seq:
|
1757
|
-
* conn.send_describe_prepared( statement_name ) -> nil
|
1758
|
-
*
|
1759
|
-
* Asynchronously send _command_ to the server. Does not block.
|
1760
|
-
* Use in combination with +conn.get_result+.
|
1761
|
-
*/
|
1762
|
-
static VALUE
|
1763
|
-
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
1764
|
-
{
|
1765
|
-
VALUE error;
|
1766
|
-
PGconn *conn = get_pgconn(self);
|
1767
|
-
/* returns 0 on failure */
|
1768
|
-
if(PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
|
1769
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1770
|
-
rb_iv_set(error, "@connection", self);
|
1771
|
-
rb_exc_raise(error);
|
1772
|
-
}
|
1773
|
-
return Qnil;
|
1774
|
-
}
|
1775
|
-
|
1776
|
-
|
1777
|
-
/*
|
1778
|
-
* call-seq:
|
1779
|
-
* conn.send_describe_portal( portal_name ) -> nil
|
1780
|
-
*
|
1781
|
-
* Asynchronously send _command_ to the server. Does not block.
|
1782
|
-
* Use in combination with +conn.get_result+.
|
1783
|
-
*/
|
1784
|
-
static VALUE
|
1785
|
-
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
1786
|
-
{
|
1787
|
-
VALUE error;
|
1788
|
-
PGconn *conn = get_pgconn(self);
|
1789
|
-
/* returns 0 on failure */
|
1790
|
-
if(PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
|
1791
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1792
|
-
rb_iv_set(error, "@connection", self);
|
1793
|
-
rb_exc_raise(error);
|
1794
|
-
}
|
1795
|
-
return Qnil;
|
1796
|
-
}
|
1797
|
-
|
1798
|
-
|
1799
|
-
/*
|
1800
|
-
* call-seq:
|
1801
|
-
* conn.get_result() -> PGresult
|
1802
|
-
* conn.get_result() {|pg_result| block }
|
1803
|
-
*
|
1804
|
-
* Blocks waiting for the next result from a call to
|
1805
|
-
* +PGconn#send_query+ (or another asynchronous command), and returns
|
1806
|
-
* it. Returns +nil+ if no more results are available.
|
1807
|
-
*
|
1808
|
-
* Note: call this function repeatedly until it returns +nil+, or else
|
1809
|
-
* you will not be able to issue further commands.
|
1810
|
-
*
|
1811
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1812
|
-
* and the PGresult object will automatically be cleared when the block terminates.
|
1813
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
1814
|
-
*/
|
1815
|
-
static VALUE
|
1816
|
-
pgconn_get_result(VALUE self)
|
1817
|
-
{
|
1818
|
-
PGconn *conn = get_pgconn(self);
|
1819
|
-
PGresult *result;
|
1820
|
-
VALUE rb_pgresult;
|
1821
|
-
|
1822
|
-
result = PQgetResult(conn);
|
1823
|
-
if(result == NULL)
|
1824
|
-
return Qnil;
|
1825
|
-
rb_pgresult = new_pgresult(result, conn);
|
1826
|
-
if (rb_block_given_p()) {
|
1827
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1828
|
-
pgresult_clear, rb_pgresult);
|
1829
|
-
}
|
1830
|
-
return rb_pgresult;
|
1831
|
-
}
|
1832
|
-
|
1833
|
-
/*
|
1834
|
-
* call-seq:
|
1835
|
-
* conn.consume_input()
|
1836
|
-
*
|
1837
|
-
* If input is available from the server, consume it.
|
1838
|
-
* After calling +consume_input+, you can check +is_busy+
|
1839
|
-
* or *notifies* to see if the state has changed.
|
1840
|
-
*/
|
1841
|
-
static VALUE
|
1842
|
-
pgconn_consume_input(self)
|
1843
|
-
VALUE self;
|
1844
|
-
{
|
1845
|
-
VALUE error;
|
1846
|
-
PGconn *conn = get_pgconn(self);
|
1847
|
-
/* returns 0 on error */
|
1848
|
-
if(PQconsumeInput(conn) == 0) {
|
1849
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1850
|
-
rb_iv_set(error, "@connection", self);
|
1851
|
-
rb_exc_raise(error);
|
1852
|
-
}
|
1853
|
-
return Qnil;
|
1854
|
-
}
|
1855
|
-
|
1856
|
-
/*
|
1857
|
-
* call-seq:
|
1858
|
-
* conn.is_busy() -> Boolean
|
1859
|
-
*
|
1860
|
-
* Returns +true+ if a command is busy, that is, if
|
1861
|
-
* PQgetResult would block. Otherwise returns +false+.
|
1862
|
-
*/
|
1863
|
-
static VALUE
|
1864
|
-
pgconn_is_busy(self)
|
1865
|
-
VALUE self;
|
1866
|
-
{
|
1867
|
-
return PQisBusy(get_pgconn(self)) ? Qtrue : Qfalse;
|
1868
|
-
}
|
1869
|
-
|
1870
|
-
/*
|
1871
|
-
* call-seq:
|
1872
|
-
* conn.setnonblocking(Boolean) -> nil
|
1873
|
-
*
|
1874
|
-
* Sets the nonblocking status of the connection.
|
1875
|
-
* In the blocking state, calls to PGconn#send_query
|
1876
|
-
* will block until the message is sent to the server,
|
1877
|
-
* but will not wait for the query results.
|
1878
|
-
* In the nonblocking state, calls to PGconn#send_query
|
1879
|
-
* will return an error if the socket is not ready for
|
1880
|
-
* writing.
|
1881
|
-
* Note: This function does not affect PGconn#exec, because
|
1882
|
-
* that function doesn't return until the server has
|
1883
|
-
* processed the query and returned the results.
|
1884
|
-
* Returns +nil+.
|
1885
|
-
*/
|
1886
|
-
static VALUE
|
1887
|
-
pgconn_setnonblocking(self, state)
|
1888
|
-
VALUE self, state;
|
1889
|
-
{
|
1890
|
-
int arg;
|
1891
|
-
VALUE error;
|
1892
|
-
PGconn *conn = get_pgconn(self);
|
1893
|
-
if(state == Qtrue)
|
1894
|
-
arg = 1;
|
1895
|
-
else if (state == Qfalse)
|
1896
|
-
arg = 0;
|
1897
|
-
else
|
1898
|
-
rb_raise(rb_eArgError, "Boolean value expected");
|
1899
|
-
|
1900
|
-
if(PQsetnonblocking(conn, arg) == -1) {
|
1901
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1902
|
-
rb_iv_set(error, "@connection", self);
|
1903
|
-
rb_exc_raise(error);
|
1904
|
-
}
|
1905
|
-
return Qnil;
|
1906
|
-
}
|
1907
|
-
|
1908
|
-
|
1909
|
-
/*
|
1910
|
-
* call-seq:
|
1911
|
-
* conn.isnonblocking() -> Boolean
|
1912
|
-
*
|
1913
|
-
* Returns +true+ if a command is busy, that is, if
|
1914
|
-
* PQgetResult would block. Otherwise returns +false+.
|
1915
|
-
*/
|
1916
|
-
static VALUE
|
1917
|
-
pgconn_isnonblocking(self)
|
1918
|
-
VALUE self;
|
1919
|
-
{
|
1920
|
-
return PQisnonblocking(get_pgconn(self)) ? Qtrue : Qfalse;
|
1921
|
-
}
|
1922
|
-
|
1923
|
-
/*
|
1924
|
-
* call-seq:
|
1925
|
-
* conn.flush() -> Boolean
|
1926
|
-
*
|
1927
|
-
* Attempts to flush any queued output data to the server.
|
1928
|
-
* Returns +true+ if data is successfully flushed, +false+
|
1929
|
-
* if not (can only return +false+ if connection is
|
1930
|
-
* nonblocking.
|
1931
|
-
* Raises PGError exception if some other failure occurred.
|
1932
|
-
*/
|
1933
|
-
static VALUE
|
1934
|
-
pgconn_flush(self)
|
1935
|
-
VALUE self;
|
1936
|
-
{
|
1937
|
-
PGconn *conn = get_pgconn(self);
|
1938
|
-
int ret;
|
1939
|
-
VALUE error;
|
1940
|
-
ret = PQflush(conn);
|
1941
|
-
if(ret == -1) {
|
1942
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1943
|
-
rb_iv_set(error, "@connection", self);
|
1944
|
-
rb_exc_raise(error);
|
1945
|
-
}
|
1946
|
-
return (ret) ? Qfalse : Qtrue;
|
1947
|
-
}
|
1948
|
-
|
1949
|
-
/*
|
1950
|
-
* call-seq:
|
1951
|
-
* conn.cancel() -> String
|
1952
|
-
*
|
1953
|
-
* Requests cancellation of the command currently being
|
1954
|
-
* processed. (Only implemented in PostgreSQL >= 8.0)
|
1955
|
-
*
|
1956
|
-
* Returns +nil+ on success, or a string containing the
|
1957
|
-
* error message if a failure occurs.
|
1958
|
-
*/
|
1959
|
-
static VALUE
|
1960
|
-
pgconn_cancel(VALUE self)
|
1961
|
-
{
|
1962
|
-
#ifdef HAVE_PQGETCANCEL
|
1963
|
-
char errbuf[256];
|
1964
|
-
PGcancel *cancel;
|
1965
|
-
VALUE retval;
|
1966
|
-
int ret;
|
1967
|
-
|
1968
|
-
cancel = PQgetCancel(get_pgconn(self));
|
1969
|
-
if(cancel == NULL)
|
1970
|
-
rb_raise(rb_ePGError,"Invalid connection!");
|
1971
|
-
|
1972
|
-
ret = PQcancel(cancel, errbuf, 256);
|
1973
|
-
if(ret == 1)
|
1974
|
-
retval = Qnil;
|
1975
|
-
else
|
1976
|
-
retval = rb_str_new2(errbuf);
|
1977
|
-
|
1978
|
-
PQfreeCancel(cancel);
|
1979
|
-
return retval;
|
1980
|
-
#else
|
1981
|
-
rb_notimplement();
|
1982
|
-
#endif
|
1983
|
-
}
|
1984
|
-
|
1985
|
-
|
1986
|
-
/*
|
1987
|
-
* call-seq:
|
1988
|
-
* conn.notifies()
|
1989
|
-
*
|
1990
|
-
* Returns a hash of the unprocessed notifications.
|
1991
|
-
* If there is no unprocessed notifier, it returns +nil+.
|
1992
|
-
*/
|
1993
|
-
static VALUE
|
1994
|
-
pgconn_notifies(VALUE self)
|
1995
|
-
{
|
1996
|
-
PGconn* conn = get_pgconn(self);
|
1997
|
-
PGnotify *notification;
|
1998
|
-
VALUE hash;
|
1999
|
-
VALUE sym_relname, sym_be_pid, sym_extra;
|
2000
|
-
VALUE relname, be_pid, extra;
|
2001
|
-
|
2002
|
-
sym_relname = ID2SYM(rb_intern("relname"));
|
2003
|
-
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
2004
|
-
sym_extra = ID2SYM(rb_intern("extra"));
|
2005
|
-
|
2006
|
-
notification = PQnotifies(conn);
|
2007
|
-
if (notification == NULL) {
|
2008
|
-
return Qnil;
|
2009
|
-
}
|
2010
|
-
|
2011
|
-
hash = rb_hash_new();
|
2012
|
-
relname = rb_tainted_str_new2(notification->relname);
|
2013
|
-
be_pid = INT2NUM(notification->be_pid);
|
2014
|
-
extra = rb_tainted_str_new2(PGNOTIFY_EXTRA(notification));
|
2015
|
-
|
2016
|
-
rb_hash_aset(hash, sym_relname, relname);
|
2017
|
-
rb_hash_aset(hash, sym_be_pid, be_pid);
|
2018
|
-
rb_hash_aset(hash, sym_extra, extra);
|
2019
|
-
|
2020
|
-
PQfreemem(notification);
|
2021
|
-
return hash;
|
2022
|
-
}
|
2023
|
-
|
2024
|
-
|
2025
|
-
#ifdef _WIN32
|
2026
|
-
/*
|
2027
|
-
* Duplicate the sockets from libpq and create temporary CRT FDs
|
2028
|
-
*/
|
2029
|
-
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2030
|
-
{
|
2031
|
-
int i;
|
2032
|
-
crt_set->fd_count = os_set->fd_count;
|
2033
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2034
|
-
WSAPROTOCOL_INFO wsa_pi;
|
2035
|
-
/* dupicate the SOCKET */
|
2036
|
-
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2037
|
-
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2038
|
-
/* create the CRT fd so ruby can get back to the SOCKET */
|
2039
|
-
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2040
|
-
os_set->fd_array[i] = s;
|
2041
|
-
crt_set->fd_array[i] = fd;
|
2042
|
-
}
|
2043
|
-
}
|
2044
|
-
|
2045
|
-
/*
|
2046
|
-
* Clean up the CRT FDs from create_crt_fd()
|
2047
|
-
*/
|
2048
|
-
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2049
|
-
{
|
2050
|
-
int i;
|
2051
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2052
|
-
/* cleanup the CRT fd */
|
2053
|
-
_close(crt_set->fd_array[i]);
|
2054
|
-
/* cleanup the duplicated SOCKET */
|
2055
|
-
closesocket(os_set->fd_array[i]);
|
2056
|
-
}
|
2057
|
-
}
|
2058
|
-
#endif
|
2059
|
-
|
2060
|
-
/*
|
2061
|
-
* call-seq:
|
2062
|
-
* conn.wait_for_notify( [ timeout ] ) -> String
|
2063
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
|
2064
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
|
2065
|
-
*
|
2066
|
-
* Blocks while waiting for notification(s), or until the optional
|
2067
|
-
* _timeout_ is reached, whichever comes first. _timeout_ is
|
2068
|
-
* measured in seconds and can be fractional.
|
2069
|
-
*
|
2070
|
-
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2071
|
-
* event otherwise. If used in block form, passes the name of the
|
2072
|
-
* NOTIFY +event+ and the generating +pid+ into the block.
|
2073
|
-
*
|
2074
|
-
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2075
|
-
* the optional +payload+ string, it will be given to the block as the
|
2076
|
-
* third argument.
|
2077
|
-
*
|
2078
|
-
*/
|
2079
|
-
static VALUE
|
2080
|
-
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
2081
|
-
{
|
2082
|
-
PGconn *conn = get_pgconn( self );
|
2083
|
-
PGnotify *notification;
|
2084
|
-
int sd = PQsocket( conn );
|
2085
|
-
int ret;
|
2086
|
-
struct timeval timeout;
|
2087
|
-
struct timeval *ptimeout = NULL;
|
2088
|
-
VALUE timeout_in = Qnil, relname = Qnil, be_pid = Qnil, extra = Qnil;
|
2089
|
-
double timeout_sec;
|
2090
|
-
fd_set sd_rset;
|
2091
|
-
#ifdef _WIN32
|
2092
|
-
fd_set crt_sd_rset;
|
2093
|
-
#endif
|
2094
|
-
|
2095
|
-
if ( sd < 0 )
|
2096
|
-
rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
|
2097
|
-
|
2098
|
-
rb_scan_args( argc, argv, "01", &timeout_in );
|
2099
|
-
|
2100
|
-
if ( RTEST(timeout_in) ) {
|
2101
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2102
|
-
timeout.tv_sec = (long)timeout_sec;
|
2103
|
-
timeout.tv_usec = (long)( (timeout_sec - (long)timeout_sec) * 1e6 );
|
2104
|
-
ptimeout = &timeout;
|
2105
|
-
}
|
2106
|
-
|
2107
|
-
/* Check for notifications */
|
2108
|
-
while ( (notification = PQnotifies(conn)) == NULL ) {
|
2109
|
-
FD_ZERO( &sd_rset );
|
2110
|
-
FD_SET( sd, &sd_rset );
|
2111
|
-
|
2112
|
-
#ifdef _WIN32
|
2113
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2114
|
-
#endif
|
2115
|
-
|
2116
|
-
/* Wait for the socket to become readable before checking again */
|
2117
|
-
ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2118
|
-
|
2119
|
-
#ifdef _WIN32
|
2120
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2121
|
-
#endif
|
2122
|
-
|
2123
|
-
if ( ret < 0 )
|
2124
|
-
rb_sys_fail( 0 );
|
2125
|
-
|
2126
|
-
/* Return nil if the select timed out */
|
2127
|
-
if ( ret == 0 ) return Qnil;
|
2128
|
-
|
2129
|
-
/* Read the socket */
|
2130
|
-
if ( (ret = PQconsumeInput(conn)) != 1 )
|
2131
|
-
rb_raise( rb_ePGError, "PQconsumeInput == %d: %s", ret, PQerrorMessage(conn) );
|
2132
|
-
}
|
2133
|
-
|
2134
|
-
relname = rb_tainted_str_new2( notification->relname );
|
2135
|
-
ASSOCIATE_INDEX( relname, self );
|
2136
|
-
be_pid = INT2NUM( notification->be_pid );
|
2137
|
-
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2138
|
-
if ( *notification->extra ) {
|
2139
|
-
extra = rb_tainted_str_new2( notification->extra );
|
2140
|
-
ASSOCIATE_INDEX( extra, self );
|
2141
|
-
}
|
2142
|
-
#endif
|
2143
|
-
PQfreemem( notification );
|
2144
|
-
|
2145
|
-
if ( rb_block_given_p() )
|
2146
|
-
rb_yield_values( 3, relname, be_pid, extra );
|
2147
|
-
|
2148
|
-
return relname;
|
2149
|
-
}
|
2150
|
-
|
2151
|
-
|
2152
|
-
/*
|
2153
|
-
* call-seq:
|
2154
|
-
* conn.put_copy_data( buffer ) -> Boolean
|
2155
|
-
*
|
2156
|
-
* Transmits _buffer_ as copy data to the server.
|
2157
|
-
* Returns true if the data was sent, false if it was
|
2158
|
-
* not sent (false is only possible if the connection
|
2159
|
-
* is in nonblocking mode, and this command would block).
|
2160
|
-
*
|
2161
|
-
* Raises an exception if an error occurs.
|
2162
|
-
*/
|
2163
|
-
static VALUE
|
2164
|
-
pgconn_put_copy_data(self, buffer)
|
2165
|
-
VALUE self, buffer;
|
2166
|
-
{
|
2167
|
-
int ret;
|
2168
|
-
VALUE error;
|
2169
|
-
PGconn *conn = get_pgconn(self);
|
2170
|
-
Check_Type(buffer, T_STRING);
|
2171
|
-
|
2172
|
-
ret = PQputCopyData(conn, RSTRING_PTR(buffer),
|
2173
|
-
RSTRING_LEN(buffer));
|
2174
|
-
if(ret == -1) {
|
2175
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
2176
|
-
rb_iv_set(error, "@connection", self);
|
2177
|
-
rb_exc_raise(error);
|
2178
|
-
}
|
2179
|
-
return (ret) ? Qtrue : Qfalse;
|
2180
|
-
}
|
2181
|
-
|
2182
|
-
/*
|
2183
|
-
* call-seq:
|
2184
|
-
* conn.put_copy_end( [ error_message ] ) -> Boolean
|
2185
|
-
*
|
2186
|
-
* Sends end-of-data indication to the server.
|
2187
|
-
*
|
2188
|
-
* _error_message_ is an optional parameter, and if set,
|
2189
|
-
* forces the COPY command to fail with the string
|
2190
|
-
* _error_message_.
|
2191
|
-
*
|
2192
|
-
* Returns true if the end-of-data was sent, false if it was
|
2193
|
-
* not sent (false is only possible if the connection
|
2194
|
-
* is in nonblocking mode, and this command would block).
|
2195
|
-
*/
|
2196
|
-
static VALUE
|
2197
|
-
pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2198
|
-
{
|
2199
|
-
VALUE str;
|
2200
|
-
VALUE error;
|
2201
|
-
int ret;
|
2202
|
-
char *error_message = NULL;
|
2203
|
-
PGconn *conn = get_pgconn(self);
|
2204
|
-
|
2205
|
-
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
2206
|
-
error_message = NULL;
|
2207
|
-
else
|
2208
|
-
error_message = StringValuePtr(str);
|
2209
|
-
|
2210
|
-
ret = PQputCopyEnd(conn, error_message);
|
2211
|
-
if(ret == -1) {
|
2212
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
2213
|
-
rb_iv_set(error, "@connection", self);
|
2214
|
-
rb_exc_raise(error);
|
2215
|
-
}
|
2216
|
-
return (ret) ? Qtrue : Qfalse;
|
2217
|
-
}
|
2218
|
-
|
2219
|
-
/*
|
2220
|
-
* call-seq:
|
2221
|
-
* conn.get_copy_data( [ async = false ] ) -> String
|
2222
|
-
*
|
2223
|
-
* Return a string containing one row of data, +nil+
|
2224
|
-
* if the copy is done, or +false+ if the call would
|
2225
|
-
* block (only possible if _async_ is true).
|
2226
|
-
*
|
2227
|
-
*/
|
2228
|
-
static VALUE
|
2229
|
-
pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2230
|
-
{
|
2231
|
-
VALUE async_in;
|
2232
|
-
VALUE error;
|
2233
|
-
VALUE result_str;
|
2234
|
-
int ret;
|
2235
|
-
int async;
|
2236
|
-
char *buffer;
|
2237
|
-
PGconn *conn = get_pgconn(self);
|
2238
|
-
|
2239
|
-
if (rb_scan_args(argc, argv, "01", &async_in) == 0)
|
2240
|
-
async = 0;
|
2241
|
-
else
|
2242
|
-
async = (async_in == Qfalse || async_in == Qnil) ? 0 : 1;
|
2243
|
-
|
2244
|
-
ret = PQgetCopyData(conn, &buffer, async);
|
2245
|
-
if(ret == -2) { // error
|
2246
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
2247
|
-
rb_iv_set(error, "@connection", self);
|
2248
|
-
rb_exc_raise(error);
|
2249
|
-
}
|
2250
|
-
if(ret == -1) { // No data left
|
2251
|
-
return Qnil;
|
2252
|
-
}
|
2253
|
-
if(ret == 0) { // would block
|
2254
|
-
return Qfalse;
|
2255
|
-
}
|
2256
|
-
result_str = rb_tainted_str_new(buffer, ret);
|
2257
|
-
PQfreemem(buffer);
|
2258
|
-
return result_str;
|
2259
|
-
}
|
2260
|
-
|
2261
|
-
/*
|
2262
|
-
* call-seq:
|
2263
|
-
* conn.set_error_verbosity( verbosity ) -> Fixnum
|
2264
|
-
*
|
2265
|
-
* Sets connection's verbosity to _verbosity_ and returns
|
2266
|
-
* the previous setting. Available settings are:
|
2267
|
-
* * PQERRORS_TERSE
|
2268
|
-
* * PQERRORS_DEFAULT
|
2269
|
-
* * PQERRORS_VERBOSE
|
2270
|
-
*/
|
2271
|
-
static VALUE
|
2272
|
-
pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
2273
|
-
{
|
2274
|
-
PGconn *conn = get_pgconn(self);
|
2275
|
-
PGVerbosity verbosity = NUM2INT(in_verbosity);
|
2276
|
-
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
2277
|
-
}
|
2278
|
-
|
2279
|
-
/*
|
2280
|
-
* call-seq:
|
2281
|
-
* conn.trace( stream ) -> nil
|
2282
|
-
*
|
2283
|
-
* Enables tracing message passing between backend. The
|
2284
|
-
* trace message will be written to the stream _stream_,
|
2285
|
-
* which must implement a method +fileno+ that returns
|
2286
|
-
* a writable file descriptor.
|
2287
|
-
*/
|
2288
|
-
static VALUE
|
2289
|
-
pgconn_trace(VALUE self, VALUE stream)
|
2290
|
-
{
|
2291
|
-
VALUE fileno;
|
2292
|
-
FILE *new_fp;
|
2293
|
-
int old_fd, new_fd;
|
2294
|
-
VALUE new_file;
|
2295
|
-
|
2296
|
-
if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
|
2297
|
-
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2298
|
-
|
2299
|
-
fileno = rb_funcall(stream, rb_intern("fileno"), 0);
|
2300
|
-
if(fileno == Qnil)
|
2301
|
-
rb_raise(rb_eArgError, "can't get file descriptor from stream");
|
2302
|
-
|
2303
|
-
/* Duplicate the file descriptor and re-open
|
2304
|
-
* it. Then, make it into a ruby File object
|
2305
|
-
* and assign it to an instance variable.
|
2306
|
-
* This prevents a problem when the File
|
2307
|
-
* object passed to this function is closed
|
2308
|
-
* before the connection object is. */
|
2309
|
-
old_fd = NUM2INT(fileno);
|
2310
|
-
new_fd = dup(old_fd);
|
2311
|
-
new_fp = fdopen(new_fd, "w");
|
2312
|
-
|
2313
|
-
if(new_fp == NULL)
|
2314
|
-
rb_raise(rb_eArgError, "stream is not writable");
|
2315
|
-
|
2316
|
-
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2317
|
-
rb_iv_set(self, "@trace_stream", new_file);
|
2318
|
-
|
2319
|
-
PQtrace(get_pgconn(self), new_fp);
|
2320
|
-
return Qnil;
|
2321
|
-
}
|
2322
|
-
|
2323
|
-
/*
|
2324
|
-
* call-seq:
|
2325
|
-
* conn.untrace() -> nil
|
2326
|
-
*
|
2327
|
-
* Disables the message tracing.
|
2328
|
-
*/
|
2329
|
-
static VALUE
|
2330
|
-
pgconn_untrace(VALUE self)
|
2331
|
-
{
|
2332
|
-
VALUE trace_stream;
|
2333
|
-
PQuntrace(get_pgconn(self));
|
2334
|
-
trace_stream = rb_iv_get(self, "@trace_stream");
|
2335
|
-
rb_funcall(trace_stream, rb_intern("close"), 0);
|
2336
|
-
rb_iv_set(self, "@trace_stream", Qnil);
|
2337
|
-
return Qnil;
|
2338
|
-
}
|
2339
|
-
|
2340
|
-
/*
|
2341
|
-
* call-seq:
|
2342
|
-
* conn.set_notice_receiver {|result| ... } -> Proc
|
2343
|
-
*
|
2344
|
-
* Notice and warning messages generated by the server are not returned
|
2345
|
-
* by the query execution functions, since they do not imply failure of
|
2346
|
-
* the query. Instead they are passed to a notice handling function, and
|
2347
|
-
* execution continues normally after the handler returns. The default
|
2348
|
-
* notice handling function prints the message on <tt>stderr</tt>, but the
|
2349
|
-
* application can override this behavior by supplying its own handling
|
2350
|
-
* function.
|
2351
|
-
*
|
2352
|
-
* This function takes a new block to act as the handler, which should
|
2353
|
-
* accept a single parameter that will be a PGresult object, and returns
|
2354
|
-
* the Proc object previously set, or +nil+ if it was previously the default.
|
2355
|
-
*
|
2356
|
-
* If you pass no arguments, it will reset the handler to the default.
|
2357
|
-
*/
|
2358
|
-
static VALUE
|
2359
|
-
pgconn_set_notice_receiver(VALUE self)
|
2360
|
-
{
|
2361
|
-
VALUE proc, old_proc;
|
2362
|
-
PGconn *conn = get_pgconn(self);
|
2363
|
-
|
2364
|
-
/* If default_notice_receiver is unset, assume that the current
|
2365
|
-
* notice receiver is the default, and save it to a global variable.
|
2366
|
-
* This should not be a problem because the default receiver is
|
2367
|
-
* always the same, so won't vary among connections.
|
2368
|
-
*/
|
2369
|
-
if(default_notice_receiver == NULL)
|
2370
|
-
default_notice_receiver = PQsetNoticeReceiver(conn, NULL, NULL);
|
2371
|
-
|
2372
|
-
old_proc = rb_iv_get(self, "@notice_receiver");
|
2373
|
-
if( rb_block_given_p() ) {
|
2374
|
-
proc = rb_block_proc();
|
2375
|
-
PQsetNoticeReceiver(conn, notice_receiver_proxy, (void *)self);
|
2376
|
-
} else {
|
2377
|
-
/* if no block is given, set back to default */
|
2378
|
-
proc = Qnil;
|
2379
|
-
PQsetNoticeReceiver(conn, default_notice_receiver, NULL);
|
2380
|
-
}
|
2381
|
-
|
2382
|
-
rb_iv_set(self, "@notice_receiver", proc);
|
2383
|
-
return old_proc;
|
2384
|
-
}
|
2385
|
-
|
2386
|
-
/*
|
2387
|
-
* call-seq:
|
2388
|
-
* conn.set_notice_processor {|message| ... } -> Proc
|
2389
|
-
*
|
2390
|
-
* Notice and warning messages generated by the server are not returned
|
2391
|
-
* by the query execution functions, since they do not imply failure of
|
2392
|
-
* the query. Instead they are passed to a notice handling function, and
|
2393
|
-
* execution continues normally after the handler returns. The default
|
2394
|
-
* notice handling function prints the message on <tt>stderr</tt>, but the
|
2395
|
-
* application can override this behavior by supplying its own handling
|
2396
|
-
* function.
|
2397
|
-
*
|
2398
|
-
* This function takes a new block to act as the handler, which should
|
2399
|
-
* accept a single parameter that will be a PGresult object, and returns
|
2400
|
-
* the Proc object previously set, or +nil+ if it was previously the default.
|
2401
|
-
*
|
2402
|
-
* If you pass no arguments, it will reset the handler to the default.
|
2403
|
-
*/
|
2404
|
-
static VALUE
|
2405
|
-
pgconn_set_notice_processor(VALUE self)
|
2406
|
-
{
|
2407
|
-
VALUE proc, old_proc;
|
2408
|
-
PGconn *conn = get_pgconn(self);
|
2409
|
-
|
2410
|
-
/* If default_notice_processor is unset, assume that the current
|
2411
|
-
* notice processor is the default, and save it to a global variable.
|
2412
|
-
* This should not be a problem because the default processor is
|
2413
|
-
* always the same, so won't vary among connections.
|
2414
|
-
*/
|
2415
|
-
if(default_notice_processor == NULL)
|
2416
|
-
default_notice_processor = PQsetNoticeProcessor(conn, NULL, NULL);
|
2417
|
-
|
2418
|
-
old_proc = rb_iv_get(self, "@notice_processor");
|
2419
|
-
if( rb_block_given_p() ) {
|
2420
|
-
proc = rb_block_proc();
|
2421
|
-
PQsetNoticeProcessor(conn, notice_processor_proxy, (void *)self);
|
2422
|
-
} else {
|
2423
|
-
/* if no block is given, set back to default */
|
2424
|
-
proc = Qnil;
|
2425
|
-
PQsetNoticeProcessor(conn, default_notice_processor, NULL);
|
2426
|
-
}
|
2427
|
-
|
2428
|
-
rb_iv_set(self, "@notice_processor", proc);
|
2429
|
-
return old_proc;
|
2430
|
-
}
|
2431
|
-
/*
|
2432
|
-
* call-seq:
|
2433
|
-
* conn.get_client_encoding() -> String
|
2434
|
-
*
|
2435
|
-
* Returns the client encoding as a String.
|
2436
|
-
*/
|
2437
|
-
static VALUE
|
2438
|
-
pgconn_get_client_encoding(VALUE self)
|
2439
|
-
{
|
2440
|
-
char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(get_pgconn(self)));
|
2441
|
-
return rb_tainted_str_new2(encoding);
|
2442
|
-
}
|
2443
|
-
|
2444
|
-
/*
|
2445
|
-
* call-seq:
|
2446
|
-
* conn.set_client_encoding( encoding )
|
2447
|
-
*
|
2448
|
-
* Sets the client encoding to the _encoding_ String.
|
2449
|
-
*/
|
2450
|
-
static VALUE
|
2451
|
-
pgconn_set_client_encoding(VALUE self, VALUE str)
|
2452
|
-
{
|
2453
|
-
Check_Type(str, T_STRING);
|
2454
|
-
if ((PQsetClientEncoding(get_pgconn(self), StringValuePtr(str))) == -1){
|
2455
|
-
rb_raise(rb_ePGError, "invalid encoding name: %s",StringValuePtr(str));
|
2456
|
-
}
|
2457
|
-
return Qnil;
|
2458
|
-
}
|
2459
|
-
|
2460
|
-
/*
|
2461
|
-
* call-seq:
|
2462
|
-
* conn.transaction { |conn| ... } -> nil
|
2463
|
-
*
|
2464
|
-
* Executes a +BEGIN+ at the start of the block,
|
2465
|
-
* and a +COMMIT+ at the end of the block, or
|
2466
|
-
* +ROLLBACK+ if any exception occurs.
|
2467
|
-
*/
|
2468
|
-
static VALUE
|
2469
|
-
pgconn_transaction(VALUE self)
|
2470
|
-
{
|
2471
|
-
PGconn *conn = get_pgconn(self);
|
2472
|
-
PGresult *result;
|
2473
|
-
VALUE rb_pgresult;
|
2474
|
-
int status;
|
2475
|
-
|
2476
|
-
if (rb_block_given_p()) {
|
2477
|
-
result = PQexec(conn, "BEGIN");
|
2478
|
-
rb_pgresult = new_pgresult(result, conn);
|
2479
|
-
pgresult_check(self, rb_pgresult);
|
2480
|
-
rb_protect(rb_yield, self, &status);
|
2481
|
-
if(status == 0) {
|
2482
|
-
result = PQexec(conn, "COMMIT");
|
2483
|
-
rb_pgresult = new_pgresult(result, conn);
|
2484
|
-
pgresult_check(self, rb_pgresult);
|
2485
|
-
}
|
2486
|
-
else {
|
2487
|
-
/* exception occurred, ROLLBACK and re-raise */
|
2488
|
-
result = PQexec(conn, "ROLLBACK");
|
2489
|
-
rb_pgresult = new_pgresult(result, conn);
|
2490
|
-
pgresult_check(self, rb_pgresult);
|
2491
|
-
rb_jump_tag(status);
|
2492
|
-
}
|
2493
|
-
|
2494
|
-
}
|
2495
|
-
else {
|
2496
|
-
/* no block supplied? */
|
2497
|
-
rb_raise(rb_eArgError, "Must supply block for PGconn#transaction");
|
2498
|
-
}
|
2499
|
-
return Qnil;
|
2500
|
-
}
|
2501
|
-
|
2502
|
-
|
2503
|
-
/*
|
2504
|
-
* call-seq:
|
2505
|
-
* PGconn.quote_ident( str ) -> String
|
2506
|
-
* conn.quote_ident( str ) -> String
|
2507
|
-
*
|
2508
|
-
* Returns a string that is safe for inclusion in a SQL query as an
|
2509
|
-
* identifier. Note: this is not a quote function for values, but for
|
2510
|
-
* identifiers.
|
2511
|
-
*
|
2512
|
-
* For example, in a typical SQL query: <tt>SELECT FOO FROM MYTABLE</tt>
|
2513
|
-
* The identifier <tt>FOO</tt> is folded to lower case, so it actually
|
2514
|
-
* means <tt>foo</tt>. If you really want to access the case-sensitive
|
2515
|
-
* field name <tt>FOO</tt>, use this function like
|
2516
|
-
* <tt>PGconn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
|
2517
|
-
* (with double-quotes). PostgreSQL will see the double-quotes, and
|
2518
|
-
* it will not fold to lower case.
|
2519
|
-
*
|
2520
|
-
* Similarly, this function also protects against special characters,
|
2521
|
-
* and other things that might allow SQL injection if the identifier
|
2522
|
-
* comes from an untrusted source.
|
2523
|
-
*/
|
2524
|
-
static VALUE
|
2525
|
-
pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
2526
|
-
{
|
2527
|
-
VALUE ret;
|
2528
|
-
char *str = StringValuePtr(in_str);
|
2529
|
-
/* result size at most NAMEDATALEN*2 plus surrounding
|
2530
|
-
* double-quotes. */
|
2531
|
-
char buffer[NAMEDATALEN*2+2];
|
2532
|
-
unsigned int i=0,j=0;
|
2533
|
-
|
2534
|
-
if(strlen(str) >= NAMEDATALEN) {
|
2535
|
-
rb_raise(rb_eArgError,
|
2536
|
-
"Input string is longer than NAMEDATALEN-1 (%d)",
|
2537
|
-
NAMEDATALEN-1);
|
2538
|
-
}
|
2539
|
-
buffer[j++] = '"';
|
2540
|
-
for(i = 0; i < strlen(str) && str[i]; i++) {
|
2541
|
-
if(str[i] == '"')
|
2542
|
-
buffer[j++] = '"';
|
2543
|
-
buffer[j++] = str[i];
|
2544
|
-
}
|
2545
|
-
buffer[j++] = '"';
|
2546
|
-
ret = rb_str_new(buffer,j);
|
2547
|
-
OBJ_INFECT(ret, in_str);
|
2548
|
-
return ret;
|
2549
|
-
}
|
2550
|
-
|
2551
|
-
|
2552
|
-
#ifndef _WIN32
|
2553
|
-
|
2554
|
-
/*
|
2555
|
-
* call-seq:
|
2556
|
-
* conn.block( [ timeout ] ) -> Boolean
|
2557
|
-
*
|
2558
|
-
* Blocks until the server is no longer busy, or until the
|
2559
|
-
* optional _timeout_ is reached, whichever comes first.
|
2560
|
-
* _timeout_ is measured in seconds and can be fractional.
|
2561
|
-
*
|
2562
|
-
* Returns +false+ if _timeout_ is reached, +true+ otherwise.
|
2563
|
-
*
|
2564
|
-
* If +true+ is returned, +conn.is_busy+ will return +false+
|
2565
|
-
* and +conn.get_result+ will not block.
|
2566
|
-
*/
|
2567
|
-
static VALUE
|
2568
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2569
|
-
PGconn *conn = get_pgconn( self );
|
2570
|
-
int sd = PQsocket( conn );
|
2571
|
-
int ret;
|
2572
|
-
|
2573
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2574
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2575
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2576
|
-
|
2577
|
-
struct timeval timeout;
|
2578
|
-
struct timeval *ptimeout = NULL;
|
2579
|
-
fd_set sd_rset;
|
2580
|
-
VALUE timeout_in;
|
2581
|
-
double timeout_sec;
|
2582
|
-
|
2583
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2584
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2585
|
-
timeout.tv_sec = (long)timeout_sec;
|
2586
|
-
timeout.tv_usec = (long)((timeout_sec - (long)timeout_sec) * 1e6);
|
2587
|
-
ptimeout = &timeout;
|
2588
|
-
}
|
2589
|
-
|
2590
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2591
|
-
if ( PQconsumeInput(conn) == 0 )
|
2592
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2593
|
-
|
2594
|
-
while ( PQisBusy(conn) ) {
|
2595
|
-
FD_ZERO( &sd_rset );
|
2596
|
-
FD_SET( sd, &sd_rset );
|
2597
|
-
|
2598
|
-
if ( (ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout )) < 0 )
|
2599
|
-
rb_sys_fail( "rb_thread_select()" ); /* Raises */
|
2600
|
-
|
2601
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2602
|
-
if ( ret == 0 && argc )
|
2603
|
-
return Qfalse;
|
2604
|
-
|
2605
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2606
|
-
if ( PQconsumeInput(conn) == 0 )
|
2607
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2608
|
-
}
|
2609
|
-
|
2610
|
-
return Qtrue;
|
2611
|
-
}
|
2612
|
-
|
2613
|
-
|
2614
|
-
#else /* _WIN32 */
|
2615
|
-
|
2616
|
-
/*
|
2617
|
-
* Win32 PGconn#block -- on Windows, use platform-specific strategies to wait for the socket
|
2618
|
-
* instead of rb_thread_select().
|
2619
|
-
*/
|
2620
|
-
|
2621
|
-
/* Win32 + Ruby 1.9+ */
|
2622
|
-
#ifdef HAVE_RUBY_VM_H
|
2623
|
-
|
2624
|
-
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2625
|
-
|
2626
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2627
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2628
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2629
|
-
|
2630
|
-
static VALUE
|
2631
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2632
|
-
PGconn *conn = get_pgconn( self );
|
2633
|
-
int sd = PQsocket( conn );
|
2634
|
-
int ret;
|
2635
|
-
|
2636
|
-
DWORD timeout_milisec = INFINITY;
|
2637
|
-
DWORD wait_ret;
|
2638
|
-
WSAEVENT hEvent;
|
2639
|
-
VALUE timeout_in;
|
2640
|
-
double timeout_sec;
|
2641
|
-
|
2642
|
-
hEvent = WSACreateEvent();
|
2643
|
-
|
2644
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2645
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2646
|
-
timeout_milisec = (DWORD)( (timeout_sec - (DWORD)timeout_sec) * 1e3 );
|
2647
|
-
}
|
2648
|
-
|
2649
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2650
|
-
if( PQconsumeInput(conn) == 0 ) {
|
2651
|
-
WSACloseEvent( hEvent );
|
2652
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2653
|
-
}
|
2654
|
-
|
2655
|
-
while ( PQisBusy(conn) ) {
|
2656
|
-
if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
|
2657
|
-
WSACloseEvent( hEvent );
|
2658
|
-
rb_raise( rb_ePGError, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2659
|
-
}
|
2660
|
-
|
2661
|
-
wait_ret = rb_w32_wait_events( &hEvent, 1, 100 );
|
2662
|
-
|
2663
|
-
if ( wait_ret == WAIT_TIMEOUT ) {
|
2664
|
-
ret = 0;
|
2665
|
-
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2666
|
-
ret = 1;
|
2667
|
-
} else if ( wait_ret == WAIT_FAILED ) {
|
2668
|
-
WSACloseEvent( hEvent );
|
2669
|
-
rb_raise( rb_ePGError, "Wait on socket error (WaitForMultipleObjects): %d", GetLastError() );
|
2670
|
-
} else {
|
2671
|
-
WSACloseEvent( hEvent );
|
2672
|
-
rb_raise( rb_ePGError, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2673
|
-
}
|
2674
|
-
|
2675
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2676
|
-
if ( ret == 0 && argc ) {
|
2677
|
-
WSACloseEvent( hEvent );
|
2678
|
-
return Qfalse;
|
2679
|
-
}
|
2680
|
-
|
2681
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2682
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
2683
|
-
WSACloseEvent( hEvent );
|
2684
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2685
|
-
}
|
2686
|
-
}
|
2687
|
-
|
2688
|
-
WSACloseEvent( hEvent );
|
2689
|
-
|
2690
|
-
return Qtrue;
|
2691
|
-
}
|
2692
|
-
|
2693
|
-
#else /* Win32 + Ruby < 1.9 */
|
2694
|
-
|
2695
|
-
static VALUE
|
2696
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2697
|
-
PGconn *conn = get_pgconn( self );
|
2698
|
-
int sd = PQsocket( conn );
|
2699
|
-
int ret;
|
2700
|
-
|
2701
|
-
struct timeval timeout;
|
2702
|
-
struct timeval *ptimeout = NULL;
|
2703
|
-
fd_set sd_rset;
|
2704
|
-
fd_set crt_sd_rset;
|
2705
|
-
VALUE timeout_in;
|
2706
|
-
double timeout_sec;
|
2707
|
-
|
2708
|
-
/* Always set a timeout, as rb_thread_select() sometimes
|
2709
|
-
* doesn't return when a second ruby thread is running although data
|
2710
|
-
* could be read. So we use timeout-based polling instead.
|
2711
|
-
*/
|
2712
|
-
timeout.tv_sec = 0;
|
2713
|
-
timeout.tv_usec = 10000; // 10ms
|
2714
|
-
ptimeout = &timeout;
|
2715
|
-
|
2716
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2717
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2718
|
-
timeout.tv_sec = (long)timeout_sec;
|
2719
|
-
timeout.tv_usec = (long)((timeout_sec - (long)timeout_sec) * 1e6);
|
2720
|
-
ptimeout = &timeout;
|
2721
|
-
}
|
2722
|
-
|
2723
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2724
|
-
if( PQconsumeInput(conn) == 0 )
|
2725
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2726
|
-
|
2727
|
-
while ( PQisBusy(conn) ) {
|
2728
|
-
FD_ZERO( &sd_rset );
|
2729
|
-
FD_SET( sd, &sd_rset );
|
2730
|
-
|
2731
|
-
create_crt_fd( &sd_rset, &crt_sd_rset );
|
2732
|
-
ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2733
|
-
cleanup_crt_fd( &sd_rset, &crt_sd_rset );
|
2734
|
-
|
2735
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2736
|
-
if ( ret == 0 && argc )
|
2737
|
-
return Qfalse;
|
2738
|
-
|
2739
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2740
|
-
if ( PQconsumeInput(conn) == 0 )
|
2741
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2742
|
-
}
|
2743
|
-
|
2744
|
-
return Qtrue;
|
2745
|
-
}
|
2746
|
-
|
2747
|
-
#endif /* Ruby 1.9 */
|
2748
|
-
#endif /* Win32 */
|
2749
|
-
|
2750
|
-
|
2751
|
-
/*
|
2752
|
-
* call-seq:
|
2753
|
-
* conn.get_last_result( ) -> PGresult
|
2754
|
-
*
|
2755
|
-
* This function retrieves all available results
|
2756
|
-
* on the current connection (from previously issued
|
2757
|
-
* asynchronous commands like +send_query()+) and
|
2758
|
-
* returns the last non-NULL result, or +nil+ if no
|
2759
|
-
* results are available.
|
2760
|
-
*
|
2761
|
-
* This function is similar to +PGconn#get_result+
|
2762
|
-
* except that it is designed to get one and only
|
2763
|
-
* one result.
|
2764
|
-
*/
|
2765
|
-
static VALUE
|
2766
|
-
pgconn_get_last_result(VALUE self)
|
2767
|
-
{
|
2768
|
-
PGconn *conn = get_pgconn(self);
|
2769
|
-
VALUE rb_pgresult = Qnil;
|
2770
|
-
PGresult *cur, *prev;
|
2771
|
-
|
2772
|
-
|
2773
|
-
cur = prev = NULL;
|
2774
|
-
while ((cur = PQgetResult(conn)) != NULL) {
|
2775
|
-
int status;
|
2776
|
-
|
2777
|
-
if (prev) PQclear(prev);
|
2778
|
-
prev = cur;
|
2779
|
-
|
2780
|
-
status = PQresultStatus(cur);
|
2781
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
2782
|
-
break;
|
2783
|
-
}
|
2784
|
-
|
2785
|
-
if (prev) {
|
2786
|
-
rb_pgresult = new_pgresult(prev, conn);
|
2787
|
-
pgresult_check(self, rb_pgresult);
|
2788
|
-
}
|
2789
|
-
|
2790
|
-
return rb_pgresult;
|
2791
|
-
}
|
2792
|
-
|
2793
|
-
|
2794
|
-
/*
|
2795
|
-
* call-seq:
|
2796
|
-
* conn.async_exec(sql [, params, result_format ] ) -> PGresult
|
2797
|
-
* conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
|
2798
|
-
*
|
2799
|
-
* This function has the same behavior as +PGconn#exec+,
|
2800
|
-
* except that it's implemented using asynchronous command
|
2801
|
-
* processing and ruby's +rb_thread_select+ in order to
|
2802
|
-
* allow other threads to process while waiting for the
|
2803
|
-
* server to complete the request.
|
2804
|
-
*/
|
2805
|
-
static VALUE
|
2806
|
-
pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
2807
|
-
{
|
2808
|
-
VALUE rb_pgresult = Qnil;
|
2809
|
-
|
2810
|
-
/* remove any remaining results from the queue */
|
2811
|
-
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
2812
|
-
pgconn_get_last_result( self );
|
2813
|
-
|
2814
|
-
pgconn_send_query( argc, argv, self );
|
2815
|
-
pgconn_block( 0, NULL, self );
|
2816
|
-
rb_pgresult = pgconn_get_last_result( self );
|
2817
|
-
|
2818
|
-
if ( rb_block_given_p() ) {
|
2819
|
-
return rb_ensure( rb_yield, rb_pgresult, pgresult_clear, rb_pgresult );
|
2820
|
-
}
|
2821
|
-
return rb_pgresult;
|
2822
|
-
}
|
2823
|
-
|
2824
|
-
|
2825
|
-
/**************************************************************************
|
2826
|
-
* LARGE OBJECT SUPPORT
|
2827
|
-
**************************************************************************/
|
2828
|
-
|
2829
|
-
/*
|
2830
|
-
* call-seq:
|
2831
|
-
* conn.lo_creat( [mode] ) -> Fixnum
|
2832
|
-
*
|
2833
|
-
* Creates a large object with mode _mode_. Returns a large object Oid.
|
2834
|
-
* On failure, it raises PGError exception.
|
2835
|
-
*/
|
2836
|
-
static VALUE
|
2837
|
-
pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
2838
|
-
{
|
2839
|
-
Oid lo_oid;
|
2840
|
-
int mode;
|
2841
|
-
VALUE nmode;
|
2842
|
-
PGconn *conn = get_pgconn(self);
|
2843
|
-
|
2844
|
-
if (rb_scan_args(argc, argv, "01", &nmode) == 0)
|
2845
|
-
mode = INV_READ;
|
2846
|
-
else
|
2847
|
-
mode = NUM2INT(nmode);
|
2848
|
-
|
2849
|
-
lo_oid = lo_creat(conn, mode);
|
2850
|
-
if (lo_oid == 0)
|
2851
|
-
rb_raise(rb_ePGError, "lo_creat failed");
|
2852
|
-
|
2853
|
-
return INT2FIX(lo_oid);
|
2854
|
-
}
|
2855
|
-
|
2856
|
-
/*
|
2857
|
-
* call-seq:
|
2858
|
-
* conn.lo_create( oid ) -> Fixnum
|
2859
|
-
*
|
2860
|
-
* Creates a large object with oid _oid_. Returns the large object Oid.
|
2861
|
-
* On failure, it raises PGError exception.
|
2862
|
-
*/
|
2863
|
-
static VALUE
|
2864
|
-
pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
2865
|
-
{
|
2866
|
-
Oid ret, lo_oid;
|
2867
|
-
PGconn *conn = get_pgconn(self);
|
2868
|
-
lo_oid = NUM2INT(in_lo_oid);
|
2869
|
-
|
2870
|
-
ret = lo_create(conn, in_lo_oid);
|
2871
|
-
if (ret == InvalidOid)
|
2872
|
-
rb_raise(rb_ePGError, "lo_create failed");
|
2873
|
-
|
2874
|
-
return INT2FIX(ret);
|
2875
|
-
}
|
2876
|
-
|
2877
|
-
/*
|
2878
|
-
* call-seq:
|
2879
|
-
* conn.lo_import(file) -> Fixnum
|
2880
|
-
*
|
2881
|
-
* Import a file to a large object. Returns a large object Oid.
|
2882
|
-
*
|
2883
|
-
* On failure, it raises a PGError exception.
|
2884
|
-
*/
|
2885
|
-
static VALUE
|
2886
|
-
pgconn_loimport(VALUE self, VALUE filename)
|
2887
|
-
{
|
2888
|
-
Oid lo_oid;
|
2889
|
-
|
2890
|
-
PGconn *conn = get_pgconn(self);
|
2891
|
-
|
2892
|
-
Check_Type(filename, T_STRING);
|
2893
|
-
|
2894
|
-
lo_oid = lo_import(conn, StringValuePtr(filename));
|
2895
|
-
if (lo_oid == 0) {
|
2896
|
-
rb_raise(rb_ePGError, "%s", PQerrorMessage(conn));
|
2897
|
-
}
|
2898
|
-
return INT2FIX(lo_oid);
|
2899
|
-
}
|
2900
|
-
|
2901
|
-
/*
|
2902
|
-
* call-seq:
|
2903
|
-
* conn.lo_export( oid, file ) -> nil
|
2904
|
-
*
|
2905
|
-
* Saves a large object of _oid_ to a _file_.
|
2906
|
-
*/
|
2907
|
-
static VALUE
|
2908
|
-
pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
2909
|
-
{
|
2910
|
-
PGconn *conn = get_pgconn(self);
|
2911
|
-
int oid;
|
2912
|
-
Check_Type(filename, T_STRING);
|
2913
|
-
|
2914
|
-
oid = NUM2INT(lo_oid);
|
2915
|
-
if (oid < 0) {
|
2916
|
-
rb_raise(rb_ePGError, "invalid large object oid %d",oid);
|
2917
|
-
}
|
2918
|
-
|
2919
|
-
if (lo_export(conn, oid, StringValuePtr(filename)) < 0) {
|
2920
|
-
rb_raise(rb_ePGError, "%s", PQerrorMessage(conn));
|
2921
|
-
}
|
2922
|
-
return Qnil;
|
2923
|
-
}
|
2924
|
-
|
2925
|
-
/*
|
2926
|
-
* call-seq:
|
2927
|
-
* conn.lo_open( oid, [mode] ) -> Fixnum
|
2928
|
-
*
|
2929
|
-
* Open a large object of _oid_. Returns a large object descriptor
|
2930
|
-
* instance on success. The _mode_ argument specifies the mode for
|
2931
|
-
* the opened large object,which is either +INV_READ+, or +INV_WRITE+.
|
2932
|
-
*
|
2933
|
-
* If _mode_ is omitted, the default is +INV_READ+.
|
2934
|
-
*/
|
2935
|
-
static VALUE
|
2936
|
-
pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
2937
|
-
{
|
2938
|
-
Oid lo_oid;
|
2939
|
-
int fd, mode;
|
2940
|
-
VALUE nmode, selfid;
|
2941
|
-
PGconn *conn = get_pgconn(self);
|
2942
|
-
|
2943
|
-
rb_scan_args(argc, argv, "11", &selfid, &nmode);
|
2944
|
-
lo_oid = NUM2INT(selfid);
|
2945
|
-
if(NIL_P(nmode))
|
2946
|
-
mode = INV_READ;
|
2947
|
-
else
|
2948
|
-
mode = NUM2INT(nmode);
|
2949
|
-
|
2950
|
-
if((fd = lo_open(conn, lo_oid, mode)) < 0) {
|
2951
|
-
rb_raise(rb_ePGError, "can't open large object: %s", PQerrorMessage(conn));
|
2952
|
-
}
|
2953
|
-
return INT2FIX(fd);
|
2954
|
-
}
|
2955
|
-
|
2956
|
-
/*
|
2957
|
-
* call-seq:
|
2958
|
-
* conn.lo_write( lo_desc, buffer ) -> Fixnum
|
2959
|
-
*
|
2960
|
-
* Writes the string _buffer_ to the large object _lo_desc_.
|
2961
|
-
* Returns the number of bytes written.
|
2962
|
-
*/
|
2963
|
-
static VALUE
|
2964
|
-
pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
2965
|
-
{
|
2966
|
-
int n;
|
2967
|
-
PGconn *conn = get_pgconn(self);
|
2968
|
-
int fd = NUM2INT(in_lo_desc);
|
2969
|
-
|
2970
|
-
Check_Type(buffer, T_STRING);
|
2971
|
-
|
2972
|
-
if( RSTRING_LEN(buffer) < 0) {
|
2973
|
-
rb_raise(rb_ePGError, "write buffer zero string");
|
2974
|
-
}
|
2975
|
-
if((n = lo_write(conn, fd, StringValuePtr(buffer),
|
2976
|
-
RSTRING_LEN(buffer))) < 0) {
|
2977
|
-
rb_raise(rb_ePGError, "lo_write failed: %s", PQerrorMessage(conn));
|
2978
|
-
}
|
2979
|
-
|
2980
|
-
return INT2FIX(n);
|
2981
|
-
}
|
2982
|
-
|
2983
|
-
/*
|
2984
|
-
* call-seq:
|
2985
|
-
* conn.lo_read( lo_desc, len ) -> String
|
2986
|
-
*
|
2987
|
-
* Attempts to read _len_ bytes from large object _lo_desc_,
|
2988
|
-
* returns resulting data.
|
2989
|
-
*/
|
2990
|
-
static VALUE
|
2991
|
-
pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
2992
|
-
{
|
2993
|
-
int ret;
|
2994
|
-
PGconn *conn = get_pgconn(self);
|
2995
|
-
int len = NUM2INT(in_len);
|
2996
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
2997
|
-
VALUE str;
|
2998
|
-
char *buffer;
|
2999
|
-
|
3000
|
-
buffer = ALLOC_N(char, len);
|
3001
|
-
if(buffer == NULL)
|
3002
|
-
rb_raise(rb_eNoMemError, "ALLOC failed!");
|
3003
|
-
|
3004
|
-
if (len < 0){
|
3005
|
-
rb_raise(rb_ePGError,"nagative length %d given", len);
|
3006
|
-
}
|
3007
|
-
|
3008
|
-
if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
|
3009
|
-
rb_raise(rb_ePGError, "lo_read failed");
|
3010
|
-
|
3011
|
-
if(ret == 0) {
|
3012
|
-
xfree(buffer);
|
3013
|
-
return Qnil;
|
3014
|
-
}
|
3015
|
-
|
3016
|
-
str = rb_tainted_str_new(buffer, ret);
|
3017
|
-
xfree(buffer);
|
3018
|
-
|
3019
|
-
return str;
|
3020
|
-
}
|
3021
|
-
|
3022
|
-
|
3023
|
-
/*
|
3024
|
-
* call-seq:
|
3025
|
-
* conn.lo_lseek( lo_desc, offset, whence ) -> Fixnum
|
3026
|
-
*
|
3027
|
-
* Move the large object pointer _lo_desc_ to offset _offset_.
|
3028
|
-
* Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
|
3029
|
-
* (Or 0, 1, or 2.)
|
3030
|
-
*/
|
3031
|
-
static VALUE
|
3032
|
-
pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
3033
|
-
{
|
3034
|
-
PGconn *conn = get_pgconn(self);
|
3035
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3036
|
-
int ret;
|
3037
|
-
|
3038
|
-
if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
|
3039
|
-
rb_raise(rb_ePGError, "lo_lseek failed");
|
3040
|
-
}
|
3041
|
-
|
3042
|
-
return INT2FIX(ret);
|
3043
|
-
}
|
3044
|
-
|
3045
|
-
/*
|
3046
|
-
* call-seq:
|
3047
|
-
* conn.lo_tell( lo_desc ) -> Fixnum
|
3048
|
-
*
|
3049
|
-
* Returns the current position of the large object _lo_desc_.
|
3050
|
-
*/
|
3051
|
-
static VALUE
|
3052
|
-
pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
3053
|
-
{
|
3054
|
-
int position;
|
3055
|
-
PGconn *conn = get_pgconn(self);
|
3056
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3057
|
-
|
3058
|
-
if((position = lo_tell(conn, lo_desc)) < 0)
|
3059
|
-
rb_raise(rb_ePGError,"lo_tell failed");
|
3060
|
-
|
3061
|
-
return INT2FIX(position);
|
3062
|
-
}
|
3063
|
-
|
3064
|
-
/*
|
3065
|
-
* call-seq:
|
3066
|
-
* conn.lo_truncate( lo_desc, len ) -> nil
|
3067
|
-
*
|
3068
|
-
* Truncates the large object _lo_desc_ to size _len_.
|
3069
|
-
*/
|
3070
|
-
static VALUE
|
3071
|
-
pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
3072
|
-
{
|
3073
|
-
PGconn *conn = get_pgconn(self);
|
3074
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3075
|
-
size_t len = NUM2INT(in_len);
|
3076
|
-
|
3077
|
-
if(lo_truncate(conn,lo_desc,len) < 0)
|
3078
|
-
rb_raise(rb_ePGError,"lo_truncate failed");
|
3079
|
-
|
3080
|
-
return Qnil;
|
3081
|
-
}
|
3082
|
-
|
3083
|
-
/*
|
3084
|
-
* call-seq:
|
3085
|
-
* conn.lo_close( lo_desc ) -> nil
|
3086
|
-
*
|
3087
|
-
* Closes the postgres large object of _lo_desc_.
|
3088
|
-
*/
|
3089
|
-
static VALUE
|
3090
|
-
pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
3091
|
-
{
|
3092
|
-
PGconn *conn = get_pgconn(self);
|
3093
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3094
|
-
|
3095
|
-
if(lo_close(conn,lo_desc) < 0)
|
3096
|
-
rb_raise(rb_ePGError,"lo_close failed");
|
3097
|
-
|
3098
|
-
return Qnil;
|
3099
|
-
}
|
3100
|
-
|
3101
|
-
/*
|
3102
|
-
* call-seq:
|
3103
|
-
* conn.lo_unlink( oid ) -> nil
|
3104
|
-
*
|
3105
|
-
* Unlinks (deletes) the postgres large object of _oid_.
|
3106
|
-
*/
|
3107
|
-
static VALUE
|
3108
|
-
pgconn_lounlink(VALUE self, VALUE in_oid)
|
3109
|
-
{
|
3110
|
-
PGconn *conn = get_pgconn(self);
|
3111
|
-
int oid = NUM2INT(in_oid);
|
3112
|
-
|
3113
|
-
if (oid < 0)
|
3114
|
-
rb_raise(rb_ePGError, "invalid oid %d",oid);
|
3115
|
-
|
3116
|
-
if(lo_unlink(conn,oid) < 0)
|
3117
|
-
rb_raise(rb_ePGError,"lo_unlink failed");
|
3118
|
-
|
3119
|
-
return Qnil;
|
3120
|
-
}
|
3121
|
-
|
3122
|
-
/********************************************************************
|
3123
|
-
*
|
3124
|
-
* Document-class: PGresult
|
3125
|
-
*
|
3126
|
-
* The class to represent the query result tuples (rows).
|
3127
|
-
* An instance of this class is created as the result of every query.
|
3128
|
-
* You may need to invoke the #clear method of the instance when finished with
|
3129
|
-
* the result for better memory performance.
|
3130
|
-
*
|
3131
|
-
* Example:
|
3132
|
-
* require 'pg'
|
3133
|
-
* conn = PGconn.open(:dbname => 'test')
|
3134
|
-
* res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
|
3135
|
-
* res.getvalue(0,0) # '1'
|
3136
|
-
* res[0]['b'] # '2'
|
3137
|
-
* res[0]['c'] # nil
|
3138
|
-
*
|
3139
|
-
*/
|
3140
|
-
|
3141
|
-
/**************************************************************************
|
3142
|
-
* PGresult INSTANCE METHODS
|
3143
|
-
**************************************************************************/
|
3144
|
-
|
3145
|
-
/*
|
3146
|
-
* call-seq:
|
3147
|
-
* res.result_status() -> Fixnum
|
3148
|
-
*
|
3149
|
-
* Returns the status of the query. The status value is one of:
|
3150
|
-
* * +PGRES_EMPTY_QUERY+
|
3151
|
-
* * +PGRES_COMMAND_OK+
|
3152
|
-
* * +PGRES_TUPLES_OK+
|
3153
|
-
* * +PGRES_COPY_OUT+
|
3154
|
-
* * +PGRES_COPY_IN+
|
3155
|
-
* * +PGRES_BAD_RESPONSE+
|
3156
|
-
* * +PGRES_NONFATAL_ERROR+
|
3157
|
-
* * +PGRES_FATAL_ERROR+
|
3158
|
-
*/
|
3159
|
-
static VALUE
|
3160
|
-
pgresult_result_status(VALUE self)
|
3161
|
-
{
|
3162
|
-
return INT2FIX(PQresultStatus(get_pgresult(self)));
|
3163
|
-
}
|
3164
|
-
|
3165
|
-
/*
|
3166
|
-
* call-seq:
|
3167
|
-
* res.res_status( status ) -> String
|
3168
|
-
*
|
3169
|
-
* Returns the string representation of status +status+.
|
3170
|
-
*
|
3171
|
-
*/
|
3172
|
-
static VALUE
|
3173
|
-
pgresult_res_status(VALUE self, VALUE status)
|
3174
|
-
{
|
3175
|
-
VALUE ret = rb_tainted_str_new2(PQresStatus(NUM2INT(status)));
|
3176
|
-
ASSOCIATE_INDEX(ret, self);
|
3177
|
-
return ret;
|
3178
|
-
}
|
3179
|
-
|
3180
|
-
/*
|
3181
|
-
* call-seq:
|
3182
|
-
* res.error_message() -> String
|
3183
|
-
*
|
3184
|
-
* Returns the error message of the command as a string.
|
3185
|
-
*/
|
3186
|
-
static VALUE
|
3187
|
-
pgresult_error_message(VALUE self)
|
3188
|
-
{
|
3189
|
-
VALUE ret = rb_tainted_str_new2(PQresultErrorMessage(get_pgresult(self)));
|
3190
|
-
ASSOCIATE_INDEX(ret, self);
|
3191
|
-
return ret;
|
3192
|
-
}
|
3193
|
-
|
3194
|
-
/*
|
3195
|
-
* call-seq:
|
3196
|
-
* res.error_field(fieldcode) -> String
|
3197
|
-
*
|
3198
|
-
* Returns the individual field of an error.
|
3199
|
-
*
|
3200
|
-
* +fieldcode+ is one of:
|
3201
|
-
* * +PG_DIAG_SEVERITY+
|
3202
|
-
* * +PG_DIAG_SQLSTATE+
|
3203
|
-
* * +PG_DIAG_MESSAGE_PRIMARY+
|
3204
|
-
* * +PG_DIAG_MESSAGE_DETAIL+
|
3205
|
-
* * +PG_DIAG_MESSAGE_HINT+
|
3206
|
-
* * +PG_DIAG_STATEMENT_POSITION+
|
3207
|
-
* * +PG_DIAG_INTERNAL_POSITION+
|
3208
|
-
* * +PG_DIAG_INTERNAL_QUERY+
|
3209
|
-
* * +PG_DIAG_CONTEXT+
|
3210
|
-
* * +PG_DIAG_SOURCE_FILE+
|
3211
|
-
* * +PG_DIAG_SOURCE_LINE+
|
3212
|
-
* * +PG_DIAG_SOURCE_FUNCTION+
|
3213
|
-
*
|
3214
|
-
* An example:
|
3215
|
-
*
|
3216
|
-
* begin
|
3217
|
-
* conn.exec( "SELECT * FROM nonexistant_table" )
|
3218
|
-
* rescue PGError => err
|
3219
|
-
* p [
|
3220
|
-
* result.error_field( PGresult::PG_DIAG_SEVERITY ),
|
3221
|
-
* result.error_field( PGresult::PG_DIAG_SQLSTATE ),
|
3222
|
-
* result.error_field( PGresult::PG_DIAG_MESSAGE_PRIMARY ),
|
3223
|
-
* result.error_field( PGresult::PG_DIAG_MESSAGE_DETAIL ),
|
3224
|
-
* result.error_field( PGresult::PG_DIAG_MESSAGE_HINT ),
|
3225
|
-
* result.error_field( PGresult::PG_DIAG_STATEMENT_POSITION ),
|
3226
|
-
* result.error_field( PGresult::PG_DIAG_INTERNAL_POSITION ),
|
3227
|
-
* result.error_field( PGresult::PG_DIAG_INTERNAL_QUERY ),
|
3228
|
-
* result.error_field( PGresult::PG_DIAG_CONTEXT ),
|
3229
|
-
* result.error_field( PGresult::PG_DIAG_SOURCE_FILE ),
|
3230
|
-
* result.error_field( PGresult::PG_DIAG_SOURCE_LINE ),
|
3231
|
-
* result.error_field( PGresult::PG_DIAG_SOURCE_FUNCTION ),
|
3232
|
-
* ]
|
3233
|
-
* end
|
3234
|
-
*
|
3235
|
-
* Outputs:
|
3236
|
-
*
|
3237
|
-
* ["ERROR", "42P01", "relation \"nonexistant_table\" does not exist", nil, nil,
|
3238
|
-
* "15", nil, nil, nil, "path/to/parse_relation.c", "857", "parserOpenTable"]
|
3239
|
-
*/
|
3240
|
-
static VALUE
|
3241
|
-
pgresult_error_field(VALUE self, VALUE field)
|
3242
|
-
{
|
3243
|
-
PGresult *result = get_pgresult( self );
|
3244
|
-
int fieldcode = NUM2INT( field );
|
3245
|
-
char * fieldstr = PQresultErrorField( result, fieldcode );
|
3246
|
-
VALUE ret = Qnil;
|
3247
|
-
|
3248
|
-
if ( fieldstr ) {
|
3249
|
-
ret = rb_tainted_str_new2( fieldstr );
|
3250
|
-
ASSOCIATE_INDEX( ret, self );
|
3251
|
-
}
|
3252
|
-
|
3253
|
-
return ret;
|
3254
|
-
}
|
3255
|
-
|
3256
|
-
/*
|
3257
|
-
* call-seq:
|
3258
|
-
* res.clear() -> nil
|
3259
|
-
*
|
3260
|
-
* Clears the PGresult object as the result of the query.
|
3261
|
-
*/
|
3262
|
-
static VALUE
|
3263
|
-
pgresult_clear(VALUE self)
|
3264
|
-
{
|
3265
|
-
PQclear(get_pgresult(self));
|
3266
|
-
DATA_PTR(self) = NULL;
|
3267
|
-
return Qnil;
|
3268
|
-
}
|
3269
|
-
|
3270
|
-
/*
|
3271
|
-
* call-seq:
|
3272
|
-
* res.ntuples() -> Fixnum
|
3273
|
-
*
|
3274
|
-
* Returns the number of tuples in the query result.
|
3275
|
-
*/
|
3276
|
-
static VALUE
|
3277
|
-
pgresult_ntuples(VALUE self)
|
3278
|
-
{
|
3279
|
-
return INT2FIX(PQntuples(get_pgresult(self)));
|
3280
|
-
}
|
3281
|
-
|
3282
|
-
/*
|
3283
|
-
* call-seq:
|
3284
|
-
* res.nfields() -> Fixnum
|
3285
|
-
*
|
3286
|
-
* Returns the number of columns in the query result.
|
3287
|
-
*/
|
3288
|
-
static VALUE
|
3289
|
-
pgresult_nfields(VALUE self)
|
3290
|
-
{
|
3291
|
-
return INT2NUM(PQnfields(get_pgresult(self)));
|
3292
|
-
}
|
3293
|
-
|
3294
|
-
/*
|
3295
|
-
* call-seq:
|
3296
|
-
* res.fname( index ) -> String
|
3297
|
-
*
|
3298
|
-
* Returns the name of the column corresponding to _index_.
|
3299
|
-
*/
|
3300
|
-
static VALUE
|
3301
|
-
pgresult_fname(VALUE self, VALUE index)
|
3302
|
-
{
|
3303
|
-
VALUE fname;
|
3304
|
-
PGresult *result;
|
3305
|
-
int i = NUM2INT(index);
|
3306
|
-
|
3307
|
-
result = get_pgresult(self);
|
3308
|
-
if (i < 0 || i >= PQnfields(result)) {
|
3309
|
-
rb_raise(rb_eArgError,"invalid field number %d", i);
|
3310
|
-
}
|
3311
|
-
fname = rb_tainted_str_new2(PQfname(result, i));
|
3312
|
-
ASSOCIATE_INDEX(fname, self);
|
3313
|
-
return fname;
|
3314
|
-
}
|
3315
|
-
|
3316
|
-
/*
|
3317
|
-
* call-seq:
|
3318
|
-
* res.fnumber( name ) -> Fixnum
|
3319
|
-
*
|
3320
|
-
* Returns the index of the field specified by the string _name_.
|
3321
|
-
*
|
3322
|
-
* Raises an ArgumentError if the specified _name_ isn't one of the field names;
|
3323
|
-
* raises a TypeError if _name_ is not a String.
|
3324
|
-
*/
|
3325
|
-
static VALUE
|
3326
|
-
pgresult_fnumber(VALUE self, VALUE name)
|
3327
|
-
{
|
3328
|
-
int n;
|
3329
|
-
|
3330
|
-
Check_Type(name, T_STRING);
|
3331
|
-
|
3332
|
-
n = PQfnumber(get_pgresult(self), StringValuePtr(name));
|
3333
|
-
if (n == -1) {
|
3334
|
-
rb_raise(rb_eArgError,"Unknown field: %s", StringValuePtr(name));
|
3335
|
-
}
|
3336
|
-
return INT2FIX(n);
|
3337
|
-
}
|
3338
|
-
|
3339
|
-
/*
|
3340
|
-
* call-seq:
|
3341
|
-
* res.ftable( column_number ) -> Fixnum
|
3342
|
-
*
|
3343
|
-
* Returns the Oid of the table from which the column _column_number_
|
3344
|
-
* was fetched.
|
3345
|
-
*
|
3346
|
-
* Raises ArgumentError if _column_number_ is out of range or if
|
3347
|
-
* the Oid is undefined for that column.
|
3348
|
-
*/
|
3349
|
-
static VALUE
|
3350
|
-
pgresult_ftable(VALUE self, VALUE column_number)
|
3351
|
-
{
|
3352
|
-
Oid n ;
|
3353
|
-
int col_number = NUM2INT(column_number);
|
3354
|
-
PGresult *pgresult = get_pgresult(self);
|
3355
|
-
|
3356
|
-
if( col_number < 0 || col_number >= PQnfields(pgresult))
|
3357
|
-
rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
|
3358
|
-
|
3359
|
-
n = PQftable(pgresult, col_number);
|
3360
|
-
return INT2FIX(n);
|
3361
|
-
}
|
3362
|
-
|
3363
|
-
/*
|
3364
|
-
* call-seq:
|
3365
|
-
* res.ftablecol( column_number ) -> Fixnum
|
3366
|
-
*
|
3367
|
-
* Returns the column number (within its table) of the table from
|
3368
|
-
* which the column _column_number_ is made up.
|
3369
|
-
*
|
3370
|
-
* Raises ArgumentError if _column_number_ is out of range or if
|
3371
|
-
* the column number from its table is undefined for that column.
|
3372
|
-
*/
|
3373
|
-
static VALUE
|
3374
|
-
pgresult_ftablecol(VALUE self, VALUE column_number)
|
3375
|
-
{
|
3376
|
-
int col_number = NUM2INT(column_number);
|
3377
|
-
PGresult *pgresult = get_pgresult(self);
|
3378
|
-
|
3379
|
-
int n;
|
3380
|
-
|
3381
|
-
if( col_number < 0 || col_number >= PQnfields(pgresult))
|
3382
|
-
rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
|
3383
|
-
|
3384
|
-
n = PQftablecol(pgresult, col_number);
|
3385
|
-
return INT2FIX(n);
|
3386
|
-
}
|
3387
|
-
|
3388
|
-
/*
|
3389
|
-
* call-seq:
|
3390
|
-
* res.fformat( column_number ) -> Fixnum
|
3391
|
-
*
|
3392
|
-
* Returns the format (0 for text, 1 for binary) of column
|
3393
|
-
* _column_number_.
|
3394
|
-
*
|
3395
|
-
* Raises ArgumentError if _column_number_ is out of range.
|
3396
|
-
*/
|
3397
|
-
static VALUE
|
3398
|
-
pgresult_fformat(VALUE self, VALUE column_number)
|
3399
|
-
{
|
3400
|
-
PGresult *result = get_pgresult(self);
|
3401
|
-
int fnumber = NUM2INT(column_number);
|
3402
|
-
if (fnumber < 0 || fnumber >= PQnfields(result)) {
|
3403
|
-
rb_raise(rb_eArgError, "Column number is out of range: %d",
|
3404
|
-
fnumber);
|
3405
|
-
}
|
3406
|
-
return INT2FIX(PQfformat(result, fnumber));
|
3407
|
-
}
|
3408
|
-
|
3409
|
-
/*
|
3410
|
-
* call-seq:
|
3411
|
-
* res.ftype( column_number )
|
3412
|
-
*
|
3413
|
-
* Returns the data type associated with _column_number_.
|
3414
|
-
*
|
3415
|
-
* The integer returned is the internal +OID+ number (in PostgreSQL)
|
3416
|
-
* of the type. To get a human-readable value for the type, use the
|
3417
|
-
* returned OID and the field's #fmod value with the format_type() SQL
|
3418
|
-
* function:
|
3419
|
-
*
|
3420
|
-
* # Get the type of the second column of the result 'res'
|
3421
|
-
* typename = conn.
|
3422
|
-
* exec( "SELECT format_type($1,$2)", [res.ftype(1), res.fmod(1)] ).
|
3423
|
-
* getvalue( 0, 0 )
|
3424
|
-
*
|
3425
|
-
* Raises an ArgumentError if _column_number_ is out of range.
|
3426
|
-
*/
|
3427
|
-
static VALUE
|
3428
|
-
pgresult_ftype(VALUE self, VALUE index)
|
3429
|
-
{
|
3430
|
-
PGresult* result = get_pgresult(self);
|
3431
|
-
int i = NUM2INT(index);
|
3432
|
-
if (i < 0 || i >= PQnfields(result)) {
|
3433
|
-
rb_raise(rb_eArgError, "invalid field number %d", i);
|
3434
|
-
}
|
3435
|
-
return INT2NUM(PQftype(result, i));
|
3436
|
-
}
|
3437
|
-
|
3438
|
-
/*
|
3439
|
-
* call-seq:
|
3440
|
-
* res.fmod( column_number )
|
3441
|
-
*
|
3442
|
-
* Returns the type modifier associated with column _column_number_. See
|
3443
|
-
* the #ftype method for an example of how to use this.
|
3444
|
-
*
|
3445
|
-
* Raises an ArgumentError if _column_number_ is out of range.
|
3446
|
-
*/
|
3447
|
-
static VALUE
|
3448
|
-
pgresult_fmod(VALUE self, VALUE column_number)
|
3449
|
-
{
|
3450
|
-
PGresult *result = get_pgresult(self);
|
3451
|
-
int fnumber = NUM2INT(column_number);
|
3452
|
-
int modifier;
|
3453
|
-
if (fnumber < 0 || fnumber >= PQnfields(result)) {
|
3454
|
-
rb_raise(rb_eArgError, "Column number is out of range: %d",
|
3455
|
-
fnumber);
|
3456
|
-
}
|
3457
|
-
modifier = PQfmod(result,fnumber);
|
3458
|
-
|
3459
|
-
return INT2NUM(modifier);
|
3460
|
-
}
|
3461
|
-
|
3462
|
-
/*
|
3463
|
-
* call-seq:
|
3464
|
-
* res.fsize( index )
|
3465
|
-
*
|
3466
|
-
* Returns the size of the field type in bytes. Returns <tt>-1</tt> if the field is variable sized.
|
3467
|
-
*
|
3468
|
-
* res = conn.exec("SELECT myInt, myVarChar50 FROM foo")
|
3469
|
-
* res.size(0) => 4
|
3470
|
-
* res.size(1) => -1
|
3471
|
-
*/
|
3472
|
-
static VALUE
|
3473
|
-
pgresult_fsize(VALUE self, VALUE index)
|
3474
|
-
{
|
3475
|
-
PGresult *result;
|
3476
|
-
int i = NUM2INT(index);
|
3477
|
-
|
3478
|
-
result = get_pgresult(self);
|
3479
|
-
if (i < 0 || i >= PQnfields(result)) {
|
3480
|
-
rb_raise(rb_eArgError,"invalid field number %d", i);
|
3481
|
-
}
|
3482
|
-
return INT2NUM(PQfsize(result, i));
|
3483
|
-
}
|
3484
|
-
|
3485
|
-
/*
|
3486
|
-
* call-seq:
|
3487
|
-
* res.getvalue( tup_num, field_num )
|
3488
|
-
*
|
3489
|
-
* Returns the value in tuple number _tup_num_, field _field_num_,
|
3490
|
-
* or +nil+ if the field is +NULL+.
|
3491
|
-
*/
|
3492
|
-
static VALUE
|
3493
|
-
pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
|
3494
|
-
{
|
3495
|
-
VALUE ret;
|
3496
|
-
PGresult *result;
|
3497
|
-
int i = NUM2INT(tup_num);
|
3498
|
-
int j = NUM2INT(field_num);
|
3499
|
-
|
3500
|
-
result = get_pgresult(self);
|
3501
|
-
if(i < 0 || i >= PQntuples(result)) {
|
3502
|
-
rb_raise(rb_eArgError,"invalid tuple number %d", i);
|
3503
|
-
}
|
3504
|
-
if(j < 0 || j >= PQnfields(result)) {
|
3505
|
-
rb_raise(rb_eArgError,"invalid field number %d", j);
|
3506
|
-
}
|
3507
|
-
if(PQgetisnull(result, i, j))
|
3508
|
-
return Qnil;
|
3509
|
-
ret = rb_tainted_str_new(PQgetvalue(result, i, j),
|
3510
|
-
PQgetlength(result, i, j));
|
3511
|
-
ASSOCIATE_INDEX(ret, self);
|
3512
|
-
return ret;
|
3513
|
-
}
|
3514
|
-
|
3515
|
-
/*
|
3516
|
-
* call-seq:
|
3517
|
-
* res.getisnull(tuple_position, field_position) -> boolean
|
3518
|
-
*
|
3519
|
-
* Returns +true+ if the specified value is +nil+; +false+ otherwise.
|
3520
|
-
*/
|
3521
|
-
static VALUE
|
3522
|
-
pgresult_getisnull(VALUE self, VALUE tup_num, VALUE field_num)
|
3523
|
-
{
|
3524
|
-
PGresult *result;
|
3525
|
-
int i = NUM2INT(tup_num);
|
3526
|
-
int j = NUM2INT(field_num);
|
3527
|
-
|
3528
|
-
result = get_pgresult(self);
|
3529
|
-
if (i < 0 || i >= PQntuples(result)) {
|
3530
|
-
rb_raise(rb_eArgError,"invalid tuple number %d", i);
|
3531
|
-
}
|
3532
|
-
if (j < 0 || j >= PQnfields(result)) {
|
3533
|
-
rb_raise(rb_eArgError,"invalid field number %d", j);
|
3534
|
-
}
|
3535
|
-
return PQgetisnull(result, i, j) ? Qtrue : Qfalse;
|
3536
|
-
}
|
3537
|
-
|
3538
1
|
/*
|
3539
|
-
*
|
3540
|
-
*
|
2
|
+
* pg.c - Toplevel extension
|
3
|
+
* $Id$
|
3541
4
|
*
|
3542
|
-
*
|
5
|
+
* Author/s:
|
3543
6
|
*
|
3544
|
-
*
|
3545
|
-
|
3546
|
-
|
3547
|
-
|
3548
|
-
|
3549
|
-
|
3550
|
-
|
3551
|
-
int j = NUM2INT(field_num);
|
3552
|
-
|
3553
|
-
result = get_pgresult(self);
|
3554
|
-
if (i < 0 || i >= PQntuples(result)) {
|
3555
|
-
rb_raise(rb_eArgError,"invalid tuple number %d", i);
|
3556
|
-
}
|
3557
|
-
if (j < 0 || j >= PQnfields(result)) {
|
3558
|
-
rb_raise(rb_eArgError,"invalid field number %d", j);
|
3559
|
-
}
|
3560
|
-
return INT2FIX(PQgetlength(result, i, j));
|
3561
|
-
}
|
3562
|
-
|
3563
|
-
/*
|
3564
|
-
* call-seq:
|
3565
|
-
* res.nparams() -> Fixnum
|
7
|
+
* - Jeff Davis <ruby-pg@j-davis.com>
|
8
|
+
* - Guy Decoux (ts) <decoux@moulon.inra.fr>
|
9
|
+
* - Michael Granger <ged@FaerieMUD.org>
|
10
|
+
* - Dave Lee
|
11
|
+
* - Eiji Matsumoto <usagi@ruby.club.or.jp>
|
12
|
+
* - Yukihiro Matsumoto <matz@ruby-lang.org>
|
13
|
+
* - Noboru Saitou <noborus@netlab.jp>
|
3566
14
|
*
|
3567
|
-
*
|
3568
|
-
*
|
3569
|
-
*/
|
3570
|
-
static VALUE
|
3571
|
-
pgresult_nparams(VALUE self)
|
3572
|
-
{
|
3573
|
-
PGresult *result;
|
3574
|
-
|
3575
|
-
result = get_pgresult(self);
|
3576
|
-
return INT2FIX(PQnparams(result));
|
3577
|
-
}
|
3578
|
-
|
3579
|
-
/*
|
3580
|
-
* call-seq:
|
3581
|
-
* res.paramtype( param_number ) -> Oid
|
15
|
+
* See Contributors.rdoc for the many additional fine people that have contributed
|
16
|
+
* to this library over the years.
|
3582
17
|
*
|
3583
|
-
*
|
3584
|
-
* Only useful for the result returned by conn.describePrepared
|
3585
|
-
*/
|
3586
|
-
static VALUE
|
3587
|
-
pgresult_paramtype(VALUE self, VALUE param_number)
|
3588
|
-
{
|
3589
|
-
PGresult *result;
|
3590
|
-
|
3591
|
-
result = get_pgresult(self);
|
3592
|
-
return INT2FIX(PQparamtype(result,NUM2INT(param_number)));
|
3593
|
-
}
|
3594
|
-
|
3595
|
-
/*
|
3596
|
-
* call-seq:
|
3597
|
-
* res.cmd_status() -> String
|
18
|
+
* Copyright (c) 1997-2012 by the authors.
|
3598
19
|
*
|
3599
|
-
*
|
3600
|
-
|
3601
|
-
|
3602
|
-
pgresult_cmd_status(VALUE self)
|
3603
|
-
{
|
3604
|
-
VALUE ret = rb_tainted_str_new2(PQcmdStatus(get_pgresult(self)));
|
3605
|
-
ASSOCIATE_INDEX(ret, self);
|
3606
|
-
return ret;
|
3607
|
-
}
|
3608
|
-
|
3609
|
-
/*
|
3610
|
-
* call-seq:
|
3611
|
-
* res.cmd_tuples() -> Fixnum
|
20
|
+
* You may redistribute this software under the same terms as Ruby itself; see
|
21
|
+
* http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
|
22
|
+
* for details.
|
3612
23
|
*
|
3613
|
-
*
|
24
|
+
* Portions of the code are from the PostgreSQL project, and are distributed
|
25
|
+
* under the terms of the PostgreSQL license, included in the file "POSTGRES".
|
3614
26
|
*
|
3615
|
-
*
|
3616
|
-
* * +INSERT+
|
3617
|
-
* * +UPDATE+
|
3618
|
-
* * +DELETE+
|
3619
|
-
* * +MOVE+
|
3620
|
-
* * +FETCH+
|
3621
|
-
* or if no tuples were affected, <tt>0</tt> is returned.
|
3622
|
-
*/
|
3623
|
-
static VALUE
|
3624
|
-
pgresult_cmd_tuples(VALUE self)
|
3625
|
-
{
|
3626
|
-
long n;
|
3627
|
-
n = strtol(PQcmdTuples(get_pgresult(self)),NULL, 10);
|
3628
|
-
return INT2NUM(n);
|
3629
|
-
}
|
3630
|
-
|
3631
|
-
/*
|
3632
|
-
* call-seq:
|
3633
|
-
* res.oid_value() -> Fixnum
|
27
|
+
* Portions copyright LAIKA, Inc.
|
3634
28
|
*
|
3635
|
-
* Returns the +oid+ of the inserted row if applicable,
|
3636
|
-
* otherwise +nil+.
|
3637
|
-
*/
|
3638
|
-
static VALUE
|
3639
|
-
pgresult_oid_value(VALUE self)
|
3640
|
-
{
|
3641
|
-
Oid n = PQoidValue(get_pgresult(self));
|
3642
|
-
if (n == InvalidOid)
|
3643
|
-
return Qnil;
|
3644
|
-
else
|
3645
|
-
return INT2FIX(n);
|
3646
|
-
}
|
3647
|
-
|
3648
|
-
/* Utility methods not in libpq */
|
3649
|
-
|
3650
|
-
/*
|
3651
|
-
* call-seq:
|
3652
|
-
* res[ n ] -> Hash
|
3653
29
|
*
|
3654
|
-
*
|
3655
|
-
|
3656
|
-
static VALUE
|
3657
|
-
pgresult_aref(VALUE self, VALUE index)
|
3658
|
-
{
|
3659
|
-
PGresult *result = get_pgresult(self);
|
3660
|
-
int tuple_num = NUM2INT(index);
|
3661
|
-
int field_num;
|
3662
|
-
VALUE fname,val;
|
3663
|
-
VALUE tuple;
|
3664
|
-
|
3665
|
-
if ( tuple_num < 0 || tuple_num >= PQntuples(result) )
|
3666
|
-
rb_raise( rb_eIndexError, "Index %d is out of range", tuple_num );
|
3667
|
-
|
3668
|
-
tuple = rb_hash_new();
|
3669
|
-
for ( field_num = 0; field_num < PQnfields(result); field_num++ ) {
|
3670
|
-
fname = rb_tainted_str_new2( PQfname(result,field_num) );
|
3671
|
-
ASSOCIATE_INDEX(fname, self);
|
3672
|
-
if ( PQgetisnull(result, tuple_num, field_num) ) {
|
3673
|
-
rb_hash_aset( tuple, fname, Qnil );
|
3674
|
-
}
|
3675
|
-
else {
|
3676
|
-
val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ),
|
3677
|
-
PQgetlength(result, tuple_num, field_num) );
|
3678
|
-
|
3679
|
-
/* associate client encoding for text format only */
|
3680
|
-
if ( 0 == PQfformat(result, field_num) ) {
|
3681
|
-
ASSOCIATE_INDEX( val, self );
|
3682
|
-
} else {
|
3683
|
-
#ifdef M17N_SUPPORTED
|
3684
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3685
|
-
#endif
|
3686
|
-
}
|
3687
|
-
rb_hash_aset( tuple, fname, val );
|
3688
|
-
}
|
3689
|
-
}
|
3690
|
-
return tuple;
|
3691
|
-
}
|
3692
|
-
|
3693
|
-
|
3694
|
-
/*
|
3695
|
-
* call-seq:
|
3696
|
-
* res.values -> Array
|
30
|
+
* The following functions are part of libpq, but not available from ruby-pg,
|
31
|
+
* because they are deprecated, obsolete, or generally not useful:
|
3697
32
|
*
|
3698
|
-
*
|
33
|
+
* - PQfreemem -- unnecessary: copied to ruby object, then freed. Ruby object's
|
34
|
+
* memory is freed when it is garbage collected.
|
35
|
+
* - PQbinaryTuples -- better to use PQfformat
|
36
|
+
* - PQprint -- not very useful
|
37
|
+
* - PQsetdb -- not very useful
|
38
|
+
* - PQoidStatus -- deprecated, use PQoidValue
|
39
|
+
* - PQrequestCancel -- deprecated, use PQcancel
|
40
|
+
* - PQfn -- use a prepared statement instead
|
41
|
+
* - PQgetline -- deprecated, use PQgetCopyData
|
42
|
+
* - PQgetlineAsync -- deprecated, use PQgetCopyData
|
43
|
+
* - PQputline -- deprecated, use PQputCopyData
|
44
|
+
* - PQputnbytes -- deprecated, use PQputCopyData
|
45
|
+
* - PQendcopy -- deprecated, use PQputCopyEnd
|
3699
46
|
*/
|
3700
|
-
static VALUE
|
3701
|
-
pgresult_values(VALUE self, VALUE index)
|
3702
|
-
{
|
3703
|
-
PGresult* result = (PGresult*) get_pgresult(self);
|
3704
|
-
int row;
|
3705
|
-
int field;
|
3706
|
-
int num_rows = PQntuples(result);
|
3707
|
-
int num_fields = PQnfields(result);
|
3708
|
-
VALUE ary = rb_ary_new2(num_rows);
|
3709
|
-
|
3710
|
-
for ( row = 0; row < num_rows; row++ ) {
|
3711
|
-
/* create new row */
|
3712
|
-
VALUE new_row = rb_ary_new2(num_fields);
|
3713
|
-
|
3714
|
-
/* add to return array */
|
3715
|
-
rb_ary_store( ary, row, new_row );
|
3716
|
-
|
3717
|
-
/* populate it */
|
3718
|
-
for ( field = 0; field < num_fields; field++ ) {
|
3719
|
-
if ( PQgetisnull(result, row, field) ) {
|
3720
|
-
rb_ary_store( new_row, field, Qnil );
|
3721
|
-
}
|
3722
|
-
else {
|
3723
|
-
VALUE val = rb_tainted_str_new( PQgetvalue(result, row, field),
|
3724
|
-
PQgetlength(result, row, field) );
|
3725
|
-
|
3726
|
-
/* associate client encoding for text format only */
|
3727
|
-
if ( 0 == PQfformat(result, field) ) {
|
3728
|
-
ASSOCIATE_INDEX( val, self );
|
3729
|
-
} else {
|
3730
|
-
#ifdef M17N_SUPPORTED
|
3731
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3732
|
-
#endif
|
3733
|
-
}
|
3734
|
-
|
3735
|
-
rb_ary_store( new_row, field, val );
|
3736
|
-
}
|
3737
|
-
}
|
3738
|
-
}
|
3739
|
-
return ary;
|
3740
|
-
}
|
3741
47
|
|
48
|
+
#include "pg.h"
|
3742
49
|
|
3743
|
-
|
3744
|
-
|
3745
|
-
|
3746
|
-
*
|
3747
|
-
* Returns an Array of the values from the nth column of each
|
3748
|
-
* tuple in the result.
|
3749
|
-
*
|
3750
|
-
*/
|
3751
|
-
static VALUE
|
3752
|
-
pgresult_column_values(VALUE self, VALUE index)
|
3753
|
-
{
|
3754
|
-
int col = NUM2INT( index );
|
3755
|
-
return make_column_result_array( self, col );
|
3756
|
-
}
|
50
|
+
VALUE rb_mPG;
|
51
|
+
VALUE rb_ePGerror;
|
52
|
+
VALUE rb_mPGconstants;
|
3757
53
|
|
3758
54
|
|
3759
55
|
/*
|
3760
|
-
*
|
3761
|
-
* res.field_values( field ) -> array
|
56
|
+
* Document-class: PGError
|
3762
57
|
*
|
3763
|
-
*
|
58
|
+
* This is the exception class raised when an error is returned from
|
59
|
+
* a libpq API call.
|
3764
60
|
*
|
3765
|
-
|
3766
|
-
|
3767
|
-
pgresult_field_values( VALUE self, VALUE field )
|
3768
|
-
{
|
3769
|
-
PGresult *result = get_pgresult( self );
|
3770
|
-
const char *fieldname = RSTRING_PTR( field );
|
3771
|
-
int fnum = PQfnumber( result, fieldname );
|
3772
|
-
|
3773
|
-
if ( fnum < 0 )
|
3774
|
-
rb_raise( rb_eIndexError, "no such field '%s' in result", fieldname );
|
3775
|
-
|
3776
|
-
return make_column_result_array( self, fnum );
|
3777
|
-
}
|
3778
|
-
|
3779
|
-
|
3780
|
-
/*
|
3781
|
-
* Make a Ruby array out of the encoded values from the specified
|
3782
|
-
* column in the given result.
|
3783
|
-
*/
|
3784
|
-
static VALUE
|
3785
|
-
make_column_result_array( VALUE self, int col )
|
3786
|
-
{
|
3787
|
-
PGresult *result = get_pgresult( self );
|
3788
|
-
int row = PQntuples( result );
|
3789
|
-
VALUE ary = rb_ary_new2( row );
|
3790
|
-
VALUE val = Qnil;
|
3791
|
-
|
3792
|
-
if ( col >= PQnfields(result) )
|
3793
|
-
rb_raise( rb_eIndexError, "no column %d in result", col );
|
3794
|
-
|
3795
|
-
while ( row-- ) {
|
3796
|
-
val = rb_tainted_str_new( PQgetvalue(result, row, col),
|
3797
|
-
PQgetlength(result, row, col) );
|
3798
|
-
|
3799
|
-
/* associate client encoding for text format only */
|
3800
|
-
if ( 0 == PQfformat(result, col) ) {
|
3801
|
-
ASSOCIATE_INDEX( val, self );
|
3802
|
-
} else {
|
3803
|
-
#ifdef M17N_SUPPORTED
|
3804
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3805
|
-
#endif
|
3806
|
-
}
|
3807
|
-
|
3808
|
-
rb_ary_store( ary, row, val );
|
3809
|
-
}
|
3810
|
-
|
3811
|
-
return ary;
|
3812
|
-
}
|
3813
|
-
|
3814
|
-
|
3815
|
-
/*
|
3816
|
-
* call-seq:
|
3817
|
-
* res.each{ |tuple| ... }
|
61
|
+
* The attributes +connection+ and +result+ are set to the connection
|
62
|
+
* object and result set object, respectively.
|
3818
63
|
*
|
3819
|
-
*
|
64
|
+
* If the connection object or result set object is not available from
|
65
|
+
* the context in which the error was encountered, it is +nil+.
|
3820
66
|
*/
|
3821
|
-
static VALUE
|
3822
|
-
pgresult_each(VALUE self)
|
3823
|
-
{
|
3824
|
-
PGresult *result = get_pgresult(self);
|
3825
|
-
int tuple_num;
|
3826
|
-
|
3827
|
-
for(tuple_num = 0; tuple_num < PQntuples(result); tuple_num++) {
|
3828
|
-
rb_yield(pgresult_aref(self, INT2NUM(tuple_num)));
|
3829
|
-
}
|
3830
|
-
return self;
|
3831
|
-
}
|
3832
67
|
|
3833
68
|
/*
|
3834
|
-
*
|
3835
|
-
* res.fields() -> Array
|
3836
|
-
*
|
3837
|
-
* Returns an array of Strings representing the names of the fields in the result.
|
69
|
+
* M17n functions
|
3838
70
|
*/
|
3839
|
-
static VALUE
|
3840
|
-
pgresult_fields(VALUE self)
|
3841
|
-
{
|
3842
|
-
PGresult *result;
|
3843
|
-
VALUE ary;
|
3844
|
-
int n, i;
|
3845
|
-
|
3846
|
-
result = get_pgresult(self);
|
3847
|
-
n = PQnfields(result);
|
3848
|
-
ary = rb_ary_new2(n);
|
3849
|
-
for (i=0;i<n;i++) {
|
3850
|
-
VALUE val = rb_tainted_str_new2(PQfname(result, i));
|
3851
|
-
ASSOCIATE_INDEX(val, self);
|
3852
|
-
rb_ary_push(ary, val);
|
3853
|
-
}
|
3854
|
-
return ary;
|
3855
|
-
}
|
3856
|
-
|
3857
71
|
|
3858
72
|
#ifdef M17N_SUPPORTED
|
3859
73
|
/**
|
3860
74
|
* The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
|
3861
75
|
*/
|
3862
|
-
|
3863
|
-
|
3864
|
-
|
3865
|
-
|
3866
|
-
|
3867
|
-
|
3868
|
-
|
3869
|
-
|
3870
|
-
|
3871
|
-
|
3872
|
-
|
3873
|
-
|
3874
|
-
|
3875
|
-
|
3876
|
-
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
3880
|
-
|
3881
|
-
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
3885
|
-
|
3886
|
-
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
3891
|
-
|
3892
|
-
|
3893
|
-
|
3894
|
-
|
3895
|
-
|
3896
|
-
|
3897
|
-
|
3898
|
-
|
3899
|
-
|
3900
|
-
|
3901
|
-
|
3902
|
-
|
3903
|
-
|
3904
|
-
|
3905
|
-
|
76
|
+
const char * const (pg_enc_pg2ruby_mapping[][2]) = {
|
77
|
+
{"BIG5", "Big5" },
|
78
|
+
{"EUC_CN", "GB2312" },
|
79
|
+
{"EUC_JP", "EUC-JP" },
|
80
|
+
{"EUC_JIS_2004", "EUC-JP" },
|
81
|
+
{"EUC_KR", "EUC-KR" },
|
82
|
+
{"EUC_TW", "EUC-TW" },
|
83
|
+
{"GB18030", "GB18030" },
|
84
|
+
{"GBK", "GBK" },
|
85
|
+
{"ISO_8859_5", "ISO-8859-5" },
|
86
|
+
{"ISO_8859_6", "ISO-8859-6" },
|
87
|
+
{"ISO_8859_7", "ISO-8859-7" },
|
88
|
+
{"ISO_8859_8", "ISO-8859-8" },
|
89
|
+
/* {"JOHAB", "JOHAB" }, dummy */
|
90
|
+
{"KOI8", "KOI8-R" },
|
91
|
+
{"KOI8R", "KOI8-R" },
|
92
|
+
{"KOI8U", "KOI8-U" },
|
93
|
+
{"LATIN1", "ISO-8859-1" },
|
94
|
+
{"LATIN2", "ISO-8859-2" },
|
95
|
+
{"LATIN3", "ISO-8859-3" },
|
96
|
+
{"LATIN4", "ISO-8859-4" },
|
97
|
+
{"LATIN5", "ISO-8859-9" },
|
98
|
+
{"LATIN6", "ISO-8859-10" },
|
99
|
+
{"LATIN7", "ISO-8859-13" },
|
100
|
+
{"LATIN8", "ISO-8859-14" },
|
101
|
+
{"LATIN9", "ISO-8859-15" },
|
102
|
+
{"LATIN10", "ISO-8859-16" },
|
103
|
+
{"MULE_INTERNAL", "Emacs-Mule" },
|
104
|
+
{"SJIS", "Windows-31J" },
|
105
|
+
{"SHIFT_JIS_2004","Windows-31J" },
|
106
|
+
/* {"SQL_ASCII", NULL }, special case*/
|
107
|
+
{"UHC", "CP949" },
|
108
|
+
{"UTF8", "UTF-8" },
|
109
|
+
{"WIN866", "IBM866" },
|
110
|
+
{"WIN874", "Windows-874" },
|
111
|
+
{"WIN1250", "Windows-1250"},
|
112
|
+
{"WIN1251", "Windows-1251"},
|
113
|
+
{"WIN1252", "Windows-1252"},
|
114
|
+
{"WIN1253", "Windows-1253"},
|
115
|
+
{"WIN1254", "Windows-1254"},
|
116
|
+
{"WIN1255", "Windows-1255"},
|
117
|
+
{"WIN1256", "Windows-1256"},
|
118
|
+
{"WIN1257", "Windows-1257"},
|
119
|
+
{"WIN1258", "Windows-1258"}
|
3906
120
|
};
|
3907
121
|
|
3908
122
|
|
@@ -3912,7 +126,14 @@ static const char * const (enc_pg2ruby_mapping[][2]) = {
|
|
3912
126
|
static struct st_table *enc_pg2ruby;
|
3913
127
|
static ID s_id_index;
|
3914
128
|
|
3915
|
-
|
129
|
+
|
130
|
+
/*
|
131
|
+
* Get the index of encoding +val+.
|
132
|
+
* :FIXME: Look into replacing this with rb_enc_get_index() since 1.9.1 isn't really
|
133
|
+
* used anymore.
|
134
|
+
*/
|
135
|
+
int
|
136
|
+
pg_enc_get_index(VALUE val)
|
3916
137
|
{
|
3917
138
|
int i = ENCODING_GET_INLINED(val);
|
3918
139
|
if (i == ENCODING_INLINE_MAX) {
|
@@ -3922,21 +143,18 @@ static int enc_get_index(VALUE val)
|
|
3922
143
|
return i;
|
3923
144
|
}
|
3924
145
|
|
3925
|
-
#ifdef HAVE_RB_ENCDB_ALIAS
|
3926
|
-
# define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
|
3927
|
-
#elif HAVE_RB_ENC_ALIAS
|
3928
|
-
# define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
|
3929
|
-
#else
|
3930
|
-
extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
|
3931
|
-
# define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
|
3932
|
-
#endif
|
3933
146
|
|
147
|
+
/*
|
148
|
+
* Look up the JOHAB encoding, creating it as a dummy encoding if it's not
|
149
|
+
* already defined.
|
150
|
+
*/
|
3934
151
|
static rb_encoding *
|
3935
|
-
|
152
|
+
pg_find_or_create_johab(void)
|
3936
153
|
{
|
3937
154
|
static const char * const aliases[] = { "JOHAB", "Windows-1361", "CP1361" };
|
3938
155
|
int enc_index;
|
3939
|
-
|
156
|
+
size_t i;
|
157
|
+
|
3940
158
|
for (i = 0; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
|
3941
159
|
enc_index = rb_enc_find_index(aliases[i]);
|
3942
160
|
if (enc_index > 0) return rb_enc_from_index(enc_index);
|
@@ -3950,465 +168,200 @@ find_or_create_johab(void)
|
|
3950
168
|
}
|
3951
169
|
|
3952
170
|
/*
|
3953
|
-
*
|
171
|
+
* Return the given PostgreSQL encoding ID as an rb_encoding.
|
3954
172
|
*
|
3955
|
-
*
|
3956
|
-
*
|
173
|
+
* - returns NULL if the client encoding is 'SQL_ASCII'.
|
174
|
+
* - returns ASCII-8BIT if the client encoding is unknown.
|
3957
175
|
*/
|
3958
|
-
|
3959
|
-
|
176
|
+
rb_encoding *
|
177
|
+
pg_get_pg_encoding_as_rb_encoding( int enc_id )
|
3960
178
|
{
|
3961
179
|
rb_encoding *enc;
|
3962
|
-
int enc_id = PQclientEncoding(conn);
|
3963
180
|
|
3964
|
-
if
|
181
|
+
/* Use the cached value if it exists */
|
182
|
+
if ( st_lookup(enc_pg2ruby, (st_data_t)enc_id, (st_data_t*)&enc) ) {
|
3965
183
|
return enc;
|
3966
184
|
}
|
3967
185
|
else {
|
3968
|
-
|
3969
|
-
const char *name = pg_encoding_to_char(enc_id);
|
3970
|
-
if (strcmp("SQL_ASCII", name) == 0) {
|
3971
|
-
enc = NULL;
|
3972
|
-
goto cache;
|
3973
|
-
}
|
3974
|
-
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
3975
|
-
if (strcmp(name, enc_pg2ruby_mapping[i][0]) == 0) {
|
3976
|
-
enc = rb_enc_find(enc_pg2ruby_mapping[i][1]);
|
3977
|
-
goto cache;
|
3978
|
-
}
|
3979
|
-
}
|
186
|
+
const char *name = pg_encoding_to_char( enc_id );
|
3980
187
|
|
3981
|
-
|
3982
|
-
|
3983
|
-
enc = find_or_create_johab();
|
3984
|
-
goto cache;
|
3985
|
-
}
|
188
|
+
enc = pg_get_pg_encname_as_rb_encoding( name );
|
189
|
+
st_insert( enc_pg2ruby, (st_data_t)enc_id, (st_data_t)enc );
|
3986
190
|
|
3987
|
-
enc
|
191
|
+
return enc;
|
3988
192
|
}
|
3989
|
-
cache:
|
3990
|
-
st_insert(enc_pg2ruby, (st_data_t)enc_id, (st_data_t)enc);
|
3991
|
-
return enc;
|
3992
|
-
}
|
3993
193
|
|
194
|
+
}
|
3994
195
|
|
3995
|
-
/*
|
3996
|
-
*
|
3997
|
-
*
|
196
|
+
/*
|
197
|
+
* Return the given PostgreSQL encoding name as an rb_encoding.
|
3998
198
|
*/
|
3999
|
-
|
4000
|
-
|
199
|
+
rb_encoding *
|
200
|
+
pg_get_pg_encname_as_rb_encoding( const char *pg_encname )
|
4001
201
|
{
|
4002
|
-
|
4003
|
-
const char *encname = NULL;
|
4004
|
-
int i;
|
202
|
+
size_t i;
|
4005
203
|
|
4006
|
-
|
4007
|
-
|
4008
|
-
|
4009
|
-
|
204
|
+
/* Trying looking it up in the conversion table */
|
205
|
+
for ( i = 0; i < sizeof(pg_enc_pg2ruby_mapping)/sizeof(pg_enc_pg2ruby_mapping[0]); ++i ) {
|
206
|
+
if ( strcmp(pg_encname, pg_enc_pg2ruby_mapping[i][0]) == 0 )
|
207
|
+
return rb_enc_find( pg_enc_pg2ruby_mapping[i][1] );
|
4010
208
|
}
|
4011
209
|
|
4012
|
-
|
4013
|
-
|
4014
|
-
|
4015
|
-
}
|
210
|
+
/* JOHAB isn't a builtin encoding, so make up a dummy encoding if it's seen */
|
211
|
+
if ( strncmp(pg_encname, "JOHAB", 5) == 0 )
|
212
|
+
return pg_find_or_create_johab();
|
4016
213
|
|
4017
|
-
|
4018
|
-
|
4019
|
-
* call-seq:
|
4020
|
-
* conn.internal_encoding() -> Encoding
|
4021
|
-
*
|
4022
|
-
* defined in Ruby 1.9 or later.
|
4023
|
-
*
|
4024
|
-
* Returns:
|
4025
|
-
* * an Encoding - client_encoding of the connection as a Ruby Encoding object.
|
4026
|
-
* * nil - the client_encoding is 'SQL_ASCII'
|
4027
|
-
*/
|
4028
|
-
static VALUE
|
4029
|
-
pgconn_internal_encoding(VALUE self)
|
4030
|
-
{
|
4031
|
-
return rb_enc_from_encoding(pgconn_get_client_encoding_as_rb_encoding(get_pgconn(self)));
|
214
|
+
/* Fallthrough to ASCII-8BIT */
|
215
|
+
return rb_ascii8bit_encoding();
|
4032
216
|
}
|
4033
217
|
|
4034
|
-
static VALUE pgconn_external_encoding(VALUE self);
|
4035
|
-
|
4036
218
|
/*
|
4037
|
-
*
|
4038
|
-
* conn.internal_encoding = value
|
4039
|
-
*
|
4040
|
-
* A wrapper of +PGconn#set_client_encoding+.
|
4041
|
-
* defined in Ruby 1.9 or later.
|
4042
|
-
*
|
4043
|
-
* +value+ can be one of:
|
4044
|
-
* * an Encoding
|
4045
|
-
* * a String - a name of Encoding
|
4046
|
-
* * +nil+ - sets 'SQL_ASCII' to the client_encoding.
|
219
|
+
* Get the client encoding of the specified connection handle and return it as a rb_encoding.
|
4047
220
|
*/
|
4048
|
-
|
4049
|
-
|
221
|
+
rb_encoding *
|
222
|
+
pg_conn_enc_get( PGconn *conn )
|
4050
223
|
{
|
4051
|
-
|
4052
|
-
|
4053
|
-
return enc;
|
4054
|
-
}
|
4055
|
-
else if (TYPE(enc) == T_STRING && strcasecmp("JOHAB", RSTRING_PTR(enc)) == 0) {
|
4056
|
-
pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
4057
|
-
return enc;
|
4058
|
-
}
|
4059
|
-
else {
|
4060
|
-
int i;
|
4061
|
-
const char *name;
|
4062
|
-
name = rb_enc_name(rb_to_encoding(enc));
|
4063
|
-
|
4064
|
-
/* sequential search becuase rarely called */
|
4065
|
-
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
4066
|
-
if (strcmp(name, enc_pg2ruby_mapping[i][1]) == 0) {
|
4067
|
-
if (PQsetClientEncoding(get_pgconn(self), enc_pg2ruby_mapping[i][0]) == -1) {
|
4068
|
-
VALUE server_encoding = pgconn_external_encoding(self);
|
4069
|
-
rb_raise(rb_eEncCompatError, "imcompatible character encodings: %s and %s",
|
4070
|
-
rb_enc_name(rb_to_encoding(server_encoding)),
|
4071
|
-
enc_pg2ruby_mapping[i][0]);
|
4072
|
-
}
|
4073
|
-
return enc;
|
4074
|
-
}
|
4075
|
-
}
|
4076
|
-
|
4077
|
-
/* Ruby 1.9.1 does not support JOHAB */
|
4078
|
-
if (strcasecmp(name, "JOHAB") == 0) {
|
4079
|
-
pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
4080
|
-
return enc;
|
4081
|
-
}
|
4082
|
-
}
|
4083
|
-
|
4084
|
-
enc = rb_inspect(enc);
|
4085
|
-
rb_raise(rb_ePGError, "unknown encoding: %s", StringValuePtr(enc));
|
224
|
+
int enc_id = PQclientEncoding( conn );
|
225
|
+
return pg_get_pg_encoding_as_rb_encoding( enc_id );
|
4086
226
|
}
|
4087
227
|
|
4088
228
|
|
4089
|
-
|
4090
|
-
static VALUE enc_server_encoding_getvalue(VALUE pgresult)
|
4091
|
-
{
|
4092
|
-
return pgresult_getvalue(pgresult, INT2FIX(0), INT2FIX(0));
|
4093
|
-
}
|
4094
|
-
|
4095
229
|
/*
|
4096
|
-
*
|
4097
|
-
* conn.external_encoding() -> Encoding
|
4098
|
-
*
|
4099
|
-
* defined in Ruby 1.9 or later.
|
4100
|
-
* * Returns the server_encoding of the connected database as a Ruby Encoding object.
|
4101
|
-
* * Maps 'SQL_ASCII' to ASCII-8BIT.
|
230
|
+
* Returns the given rb_encoding as the equivalent PostgreSQL encoding string.
|
4102
231
|
*/
|
4103
|
-
|
4104
|
-
|
232
|
+
const char *
|
233
|
+
pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
|
4105
234
|
{
|
4106
|
-
|
4107
|
-
|
4108
|
-
|
4109
|
-
return enc;
|
4110
|
-
}
|
4111
|
-
else {
|
4112
|
-
int i;
|
4113
|
-
VALUE query = rb_usascii_str_new_cstr("SHOW server_encoding");
|
4114
|
-
VALUE pgresult = pgconn_exec(1, &query, self);
|
4115
|
-
VALUE enc_name = rb_ensure(enc_server_encoding_getvalue, pgresult, pgresult_clear, pgresult);
|
4116
|
-
|
4117
|
-
if (strcmp("SQL_ASCII", StringValuePtr(enc_name)) == 0) {
|
4118
|
-
enc = rb_enc_from_encoding(rb_ascii8bit_encoding());
|
4119
|
-
goto cache;
|
4120
|
-
}
|
4121
|
-
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
4122
|
-
if (strcmp(StringValuePtr(enc_name), enc_pg2ruby_mapping[i][0]) == 0) {
|
4123
|
-
enc = rb_enc_from_encoding(rb_enc_find(enc_pg2ruby_mapping[i][1]));
|
4124
|
-
goto cache;
|
4125
|
-
}
|
4126
|
-
}
|
235
|
+
const char *rb_encname = rb_enc_name( enc );
|
236
|
+
const char *encname = NULL;
|
237
|
+
size_t i;
|
4127
238
|
|
4128
|
-
|
4129
|
-
if (strcmp(
|
4130
|
-
|
4131
|
-
goto cache;
|
239
|
+
for (i = 0; i < sizeof(pg_enc_pg2ruby_mapping)/sizeof(pg_enc_pg2ruby_mapping[0]); ++i) {
|
240
|
+
if (strcmp(rb_encname, pg_enc_pg2ruby_mapping[i][1]) == 0) {
|
241
|
+
encname = pg_enc_pg2ruby_mapping[i][0];
|
4132
242
|
}
|
4133
|
-
|
4134
|
-
/* fallback */
|
4135
|
-
enc = rb_enc_from_encoding(rb_enc_find(StringValuePtr(enc_name)));
|
4136
243
|
}
|
4137
244
|
|
4138
|
-
|
4139
|
-
rb_iv_set(self, "@external_encoding", enc);
|
4140
|
-
return enc;
|
4141
|
-
}
|
245
|
+
if ( !encname ) encname = "SQL_ASCII";
|
4142
246
|
|
4143
|
-
|
4144
|
-
init_m17n(void)
|
4145
|
-
{
|
4146
|
-
enc_pg2ruby = st_init_numtable();
|
4147
|
-
s_id_index = rb_intern("@encoding");
|
4148
|
-
rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
|
4149
|
-
rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
|
4150
|
-
rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
|
247
|
+
return encname;
|
4151
248
|
}
|
4152
249
|
|
250
|
+
#endif /* M17N_SUPPORTED */
|
4153
251
|
|
4154
|
-
#endif
|
4155
|
-
/**************************************************************************/
|
4156
252
|
|
4157
253
|
void
|
4158
254
|
Init_pg_ext()
|
4159
255
|
{
|
4160
|
-
|
4161
|
-
|
4162
|
-
|
4163
|
-
|
4164
|
-
/* Library version */
|
4165
|
-
rb_define_const( rb_cPGconn, "VERSION", rb_str_new2(VERSION) );
|
4166
|
-
|
4167
|
-
/*************************
|
4168
|
-
* PGError
|
4169
|
-
*************************/
|
4170
|
-
rb_define_alias(rb_ePGError, "error", "message");
|
4171
|
-
rb_define_attr(rb_ePGError, "connection", 1, 0);
|
4172
|
-
rb_define_attr(rb_ePGError, "result", 1, 0);
|
256
|
+
rb_mPG = rb_define_module( "PG" );
|
257
|
+
rb_ePGerror = rb_define_class_under( rb_mPG, "Error", rb_eStandardError );
|
258
|
+
rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" );
|
4173
259
|
|
4174
260
|
/*************************
|
4175
|
-
*
|
261
|
+
* PG::Error
|
4176
262
|
*************************/
|
263
|
+
rb_define_alias( rb_ePGerror, "error", "message" );
|
264
|
+
rb_define_attr( rb_ePGerror, "connection", 1, 0 );
|
265
|
+
rb_define_attr( rb_ePGerror, "result", 1, 0 );
|
4177
266
|
|
4178
|
-
/******
|
4179
|
-
rb_define_alloc_func(rb_cPGconn, pgconn_alloc);
|
4180
|
-
rb_define_singleton_alias(rb_cPGconn, "connect", "new");
|
4181
|
-
rb_define_singleton_alias(rb_cPGconn, "open", "new");
|
4182
|
-
rb_define_singleton_alias(rb_cPGconn, "setdb", "new");
|
4183
|
-
rb_define_singleton_alias(rb_cPGconn, "setdblogin", "new");
|
4184
|
-
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
4185
|
-
rb_define_singleton_alias(rb_cPGconn, "escape", "escape_string");
|
4186
|
-
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4187
|
-
rb_define_singleton_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4188
|
-
rb_define_singleton_method(rb_cPGconn, "isthreadsafe", pgconn_s_isthreadsafe, 0);
|
4189
|
-
rb_define_singleton_method(rb_cPGconn, "encrypt_password", pgconn_s_encrypt_password, 2);
|
4190
|
-
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4191
|
-
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4192
|
-
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4193
|
-
|
4194
|
-
/****** PGconn CLASS CONSTANTS: Connection Status ******/
|
267
|
+
/****** PG::Connection CLASS CONSTANTS: Connection Status ******/
|
4195
268
|
|
4196
269
|
/* Connection succeeded */
|
4197
|
-
rb_define_const(
|
270
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_OK", INT2FIX(CONNECTION_OK));
|
4198
271
|
/* Connection failed */
|
4199
|
-
rb_define_const(
|
272
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_BAD", INT2FIX(CONNECTION_BAD));
|
4200
273
|
|
4201
|
-
/******
|
274
|
+
/****** PG::Connection CLASS CONSTANTS: Nonblocking connection status ******/
|
4202
275
|
|
4203
276
|
/* Waiting for connection to be made. */
|
4204
|
-
rb_define_const(
|
277
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_STARTED", INT2FIX(CONNECTION_STARTED));
|
4205
278
|
/* Connection OK; waiting to send. */
|
4206
|
-
rb_define_const(
|
279
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_MADE", INT2FIX(CONNECTION_MADE));
|
4207
280
|
/* Waiting for a response from the server. */
|
4208
|
-
rb_define_const(
|
281
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_AWAITING_RESPONSE", INT2FIX(CONNECTION_AWAITING_RESPONSE));
|
4209
282
|
/* Received authentication; waiting for backend start-up to finish. */
|
4210
|
-
rb_define_const(
|
283
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_AUTH_OK", INT2FIX(CONNECTION_AUTH_OK));
|
4211
284
|
/* Negotiating SSL encryption. */
|
4212
|
-
rb_define_const(
|
285
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP));
|
4213
286
|
/* Negotiating environment-driven parameter settings. */
|
4214
|
-
rb_define_const(
|
287
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
|
4215
288
|
|
4216
|
-
/******
|
289
|
+
/****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
|
4217
290
|
|
4218
291
|
/* Async connection is waiting to read */
|
4219
|
-
rb_define_const(
|
292
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_READING", INT2FIX(PGRES_POLLING_READING));
|
4220
293
|
/* Async connection is waiting to write */
|
4221
|
-
rb_define_const(
|
294
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_WRITING", INT2FIX(PGRES_POLLING_WRITING));
|
4222
295
|
/* Async connection failed or was reset */
|
4223
|
-
rb_define_const(
|
296
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_FAILED", INT2FIX(PGRES_POLLING_FAILED));
|
4224
297
|
/* Async connection succeeded */
|
4225
|
-
rb_define_const(
|
298
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_OK", INT2FIX(PGRES_POLLING_OK));
|
4226
299
|
|
4227
|
-
/******
|
300
|
+
/****** PG::Connection CLASS CONSTANTS: Transaction Status ******/
|
4228
301
|
|
4229
302
|
/* Transaction is currently idle (#transaction_status) */
|
4230
|
-
rb_define_const(
|
303
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_IDLE", INT2FIX(PQTRANS_IDLE));
|
4231
304
|
/* Transaction is currently active; query has been sent to the server, but not yet completed. (#transaction_status) */
|
4232
|
-
rb_define_const(
|
305
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_ACTIVE", INT2FIX(PQTRANS_ACTIVE));
|
4233
306
|
/* Transaction is currently idle, in a valid transaction block (#transaction_status) */
|
4234
|
-
rb_define_const(
|
307
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_INTRANS", INT2FIX(PQTRANS_INTRANS));
|
4235
308
|
/* Transaction is currently idle, in a failed transaction block (#transaction_status) */
|
4236
|
-
rb_define_const(
|
309
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_INERROR", INT2FIX(PQTRANS_INERROR));
|
4237
310
|
/* Transaction's connection is bad (#transaction_status) */
|
4238
|
-
rb_define_const(
|
311
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_UNKNOWN", INT2FIX(PQTRANS_UNKNOWN));
|
4239
312
|
|
4240
|
-
/******
|
313
|
+
/****** PG::Connection CLASS CONSTANTS: Error Verbosity ******/
|
4241
314
|
|
4242
315
|
/* Terse error verbosity level (#set_error_verbosity) */
|
4243
|
-
rb_define_const(
|
316
|
+
rb_define_const(rb_mPGconstants, "PQERRORS_TERSE", INT2FIX(PQERRORS_TERSE));
|
4244
317
|
/* Default error verbosity level (#set_error_verbosity) */
|
4245
|
-
rb_define_const(
|
318
|
+
rb_define_const(rb_mPGconstants, "PQERRORS_DEFAULT", INT2FIX(PQERRORS_DEFAULT));
|
4246
319
|
/* Verbose error verbosity level (#set_error_verbosity) */
|
4247
|
-
rb_define_const(
|
320
|
+
rb_define_const(rb_mPGconstants, "PQERRORS_VERBOSE", INT2FIX(PQERRORS_VERBOSE));
|
4248
321
|
|
4249
|
-
/******
|
322
|
+
/****** PG::Connection CLASS CONSTANTS: Large Objects ******/
|
4250
323
|
|
4251
324
|
/* Flag for #lo_creat, #lo_open -- open for writing */
|
4252
|
-
rb_define_const(
|
325
|
+
rb_define_const(rb_mPGconstants, "INV_WRITE", INT2FIX(INV_WRITE));
|
4253
326
|
/* Flag for #lo_creat, #lo_open -- open for reading */
|
4254
|
-
rb_define_const(
|
327
|
+
rb_define_const(rb_mPGconstants, "INV_READ", INT2FIX(INV_READ));
|
4255
328
|
/* Flag for #lo_lseek -- seek from object start */
|
4256
|
-
rb_define_const(
|
329
|
+
rb_define_const(rb_mPGconstants, "SEEK_SET", INT2FIX(SEEK_SET));
|
4257
330
|
/* Flag for #lo_lseek -- seek from current position */
|
4258
|
-
rb_define_const(
|
331
|
+
rb_define_const(rb_mPGconstants, "SEEK_CUR", INT2FIX(SEEK_CUR));
|
4259
332
|
/* Flag for #lo_lseek -- seek from object end */
|
4260
|
-
rb_define_const(
|
4261
|
-
|
4262
|
-
/****** PGconn INSTANCE METHODS: Connection Control ******/
|
4263
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
4264
|
-
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
4265
|
-
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
4266
|
-
rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
|
4267
|
-
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
4268
|
-
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4269
|
-
rb_define_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4270
|
-
rb_define_alias(rb_cPGconn, "close", "finish");
|
4271
|
-
|
4272
|
-
/****** PGconn INSTANCE METHODS: Connection Status ******/
|
4273
|
-
rb_define_method(rb_cPGconn, "db", pgconn_db, 0);
|
4274
|
-
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
4275
|
-
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
4276
|
-
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
4277
|
-
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
4278
|
-
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
4279
|
-
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
4280
|
-
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
4281
|
-
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
4282
|
-
rb_define_method(rb_cPGconn, "parameter_status", pgconn_parameter_status, 1);
|
4283
|
-
rb_define_method(rb_cPGconn, "protocol_version", pgconn_protocol_version, 0);
|
4284
|
-
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
4285
|
-
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
4286
|
-
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
4287
|
-
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4288
|
-
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
4289
|
-
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
4290
|
-
//rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0);
|
4291
|
-
|
4292
|
-
/****** PGconn INSTANCE METHODS: Command Execution ******/
|
4293
|
-
rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
|
4294
|
-
rb_define_alias(rb_cPGconn, "query", "exec");
|
4295
|
-
rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
|
4296
|
-
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
|
4297
|
-
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
|
4298
|
-
rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
|
4299
|
-
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
4300
|
-
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
4301
|
-
rb_define_alias(rb_cPGconn, "escape", "escape_string");
|
4302
|
-
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4303
|
-
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4304
|
-
|
4305
|
-
/****** PGconn INSTANCE METHODS: Asynchronous Command Processing ******/
|
4306
|
-
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
4307
|
-
rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
|
4308
|
-
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4309
|
-
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4310
|
-
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4311
|
-
rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
|
4312
|
-
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
4313
|
-
rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
|
4314
|
-
rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
|
4315
|
-
rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
|
4316
|
-
rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
|
4317
|
-
rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
|
4318
|
-
|
4319
|
-
/****** PGconn INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4320
|
-
rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
|
4321
|
-
|
4322
|
-
/****** PGconn INSTANCE METHODS: NOTIFY ******/
|
4323
|
-
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
4324
|
-
|
4325
|
-
/****** PGconn INSTANCE METHODS: COPY ******/
|
4326
|
-
rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, 1);
|
4327
|
-
rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
|
4328
|
-
rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
|
333
|
+
rb_define_const(rb_mPGconstants, "SEEK_END", INT2FIX(SEEK_END));
|
4329
334
|
|
4330
|
-
/****** PGconn INSTANCE METHODS: Control Functions ******/
|
4331
|
-
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4332
|
-
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
4333
|
-
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4334
335
|
|
4335
|
-
/******
|
4336
|
-
rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
|
4337
|
-
rb_define_method(rb_cPGconn, "set_notice_processor", pgconn_set_notice_processor, 0);
|
4338
|
-
|
4339
|
-
/****** PGconn INSTANCE METHODS: Other ******/
|
4340
|
-
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
4341
|
-
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
|
4342
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
4343
|
-
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
4344
|
-
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
4345
|
-
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
4346
|
-
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4347
|
-
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
4348
|
-
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
4349
|
-
rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
|
4350
|
-
|
4351
|
-
/****** PGconn INSTANCE METHODS: Large Object Support ******/
|
4352
|
-
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
4353
|
-
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|
4354
|
-
rb_define_method(rb_cPGconn, "lo_create", pgconn_locreate, 1);
|
4355
|
-
rb_define_alias(rb_cPGconn, "locreate", "lo_create");
|
4356
|
-
rb_define_method(rb_cPGconn, "lo_import", pgconn_loimport, 1);
|
4357
|
-
rb_define_alias(rb_cPGconn, "loimport", "lo_import");
|
4358
|
-
rb_define_method(rb_cPGconn, "lo_export", pgconn_loexport, 2);
|
4359
|
-
rb_define_alias(rb_cPGconn, "loexport", "lo_export");
|
4360
|
-
rb_define_method(rb_cPGconn, "lo_open", pgconn_loopen, -1);
|
4361
|
-
rb_define_alias(rb_cPGconn, "loopen", "lo_open");
|
4362
|
-
rb_define_method(rb_cPGconn, "lo_write",pgconn_lowrite, 2);
|
4363
|
-
rb_define_alias(rb_cPGconn, "lowrite", "lo_write");
|
4364
|
-
rb_define_method(rb_cPGconn, "lo_read",pgconn_loread, 2);
|
4365
|
-
rb_define_alias(rb_cPGconn, "loread", "lo_read");
|
4366
|
-
rb_define_method(rb_cPGconn, "lo_lseek",pgconn_lolseek, 3);
|
4367
|
-
rb_define_alias(rb_cPGconn, "lolseek", "lo_lseek");
|
4368
|
-
rb_define_alias(rb_cPGconn, "lo_seek", "lo_lseek");
|
4369
|
-
rb_define_alias(rb_cPGconn, "loseek", "lo_lseek");
|
4370
|
-
rb_define_method(rb_cPGconn, "lo_tell",pgconn_lotell, 1);
|
4371
|
-
rb_define_alias(rb_cPGconn, "lotell", "lo_tell");
|
4372
|
-
rb_define_method(rb_cPGconn, "lo_truncate", pgconn_lotruncate, 2);
|
4373
|
-
rb_define_alias(rb_cPGconn, "lotruncate", "lo_truncate");
|
4374
|
-
rb_define_method(rb_cPGconn, "lo_close",pgconn_loclose, 1);
|
4375
|
-
rb_define_alias(rb_cPGconn, "loclose", "lo_close");
|
4376
|
-
rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
|
4377
|
-
rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
|
4378
|
-
|
4379
|
-
/*************************
|
4380
|
-
* PGresult
|
4381
|
-
*************************/
|
4382
|
-
rb_include_module(rb_cPGresult, rb_mEnumerable);
|
4383
|
-
|
4384
|
-
/****** PGresult CONSTANTS: result status ******/
|
336
|
+
/****** PG::Result CONSTANTS: result status ******/
|
4385
337
|
|
4386
338
|
/* #result_status constant: The string sent to the server was empty. */
|
4387
|
-
rb_define_const(
|
339
|
+
rb_define_const(rb_mPGconstants, "PGRES_EMPTY_QUERY", INT2FIX(PGRES_EMPTY_QUERY));
|
4388
340
|
/* #result_status constant: Successful completion of a command returning no data. */
|
4389
|
-
rb_define_const(
|
4390
|
-
|
341
|
+
rb_define_const(rb_mPGconstants, "PGRES_COMMAND_OK", INT2FIX(PGRES_COMMAND_OK));
|
342
|
+
/* #result_status constant: Successful completion of a command returning data
|
4391
343
|
(such as a SELECT or SHOW). */
|
4392
|
-
rb_define_const(
|
344
|
+
rb_define_const(rb_mPGconstants, "PGRES_TUPLES_OK", INT2FIX(PGRES_TUPLES_OK));
|
4393
345
|
/* #result_status constant: Copy Out (from server) data transfer started. */
|
4394
|
-
rb_define_const(
|
346
|
+
rb_define_const(rb_mPGconstants, "PGRES_COPY_OUT", INT2FIX(PGRES_COPY_OUT));
|
4395
347
|
/* #result_status constant: Copy In (to server) data transfer started. */
|
4396
|
-
rb_define_const(
|
348
|
+
rb_define_const(rb_mPGconstants, "PGRES_COPY_IN", INT2FIX(PGRES_COPY_IN));
|
4397
349
|
/* #result_status constant: The server’s response was not understood. */
|
4398
|
-
rb_define_const(
|
350
|
+
rb_define_const(rb_mPGconstants, "PGRES_BAD_RESPONSE", INT2FIX(PGRES_BAD_RESPONSE));
|
4399
351
|
/* #result_status constant: A nonfatal error (a notice or warning) occurred. */
|
4400
|
-
rb_define_const(
|
352
|
+
rb_define_const(rb_mPGconstants, "PGRES_NONFATAL_ERROR",INT2FIX(PGRES_NONFATAL_ERROR));
|
4401
353
|
/* #result_status constant: A fatal error occurred. */
|
4402
|
-
rb_define_const(
|
354
|
+
rb_define_const(rb_mPGconstants, "PGRES_FATAL_ERROR", INT2FIX(PGRES_FATAL_ERROR));
|
4403
355
|
|
4404
|
-
/******
|
356
|
+
/****** Result CONSTANTS: result error field codes ******/
|
4405
357
|
|
4406
358
|
/* #result_error_field argument constant: The severity; the field contents
|
4407
359
|
* are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE,
|
4408
360
|
* DEBUG, INFO, or LOG (in a notice message), or a localized translation
|
4409
361
|
* of one of these. Always present.
|
4410
362
|
*/
|
4411
|
-
rb_define_const(
|
363
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SEVERITY", INT2FIX(PG_DIAG_SEVERITY));
|
364
|
+
|
4412
365
|
/* #result_error_field argument constant: The SQLSTATE code for the
|
4413
366
|
* error. The SQLSTATE code identies the type of error that has occurred;
|
4414
367
|
* it can be used by front-end applications to perform specic operations
|
@@ -4416,97 +369,79 @@ Init_pg_ext()
|
|
4416
369
|
* error. For a list of the possible SQLSTATE codes, see Appendix A.
|
4417
370
|
* This eld is not localizable, and is always present.
|
4418
371
|
*/
|
4419
|
-
rb_define_const(
|
372
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SQLSTATE", INT2FIX(PG_DIAG_SQLSTATE));
|
373
|
+
|
4420
374
|
/* #result_error_field argument constant: The primary human-readable
|
4421
375
|
* error message (typically one line). Always present. */
|
4422
|
-
rb_define_const(
|
376
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_PRIMARY", INT2FIX(PG_DIAG_MESSAGE_PRIMARY));
|
377
|
+
|
4423
378
|
/* #result_error_field argument constant: Detail: an optional secondary
|
4424
379
|
* error message carrying more detail about the problem. Might run to
|
4425
380
|
* multiple lines.
|
4426
381
|
*/
|
4427
|
-
rb_define_const(
|
382
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_DETAIL", INT2FIX(PG_DIAG_MESSAGE_DETAIL));
|
383
|
+
|
4428
384
|
/* #result_error_field argument constant: Hint: an optional suggestion
|
4429
385
|
* what to do about the problem. This is intended to differ from detail
|
4430
386
|
* in that it offers advice (potentially inappropriate) rather than
|
4431
387
|
* hard facts. Might run to multiple lines.
|
4432
388
|
*/
|
4433
|
-
|
389
|
+
|
390
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_HINT", INT2FIX(PG_DIAG_MESSAGE_HINT));
|
4434
391
|
/* #result_error_field argument constant: A string containing a decimal
|
4435
392
|
* integer indicating an error cursor position as an index into the
|
4436
393
|
* original statement string. The rst character has index 1, and
|
4437
394
|
* positions are measured in characters not bytes.
|
4438
395
|
*/
|
4439
|
-
|
396
|
+
|
397
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_STATEMENT_POSITION", INT2FIX(PG_DIAG_STATEMENT_POSITION));
|
4440
398
|
/* #result_error_field argument constant: This is dened the same as
|
4441
399
|
* the PG_DIAG_STATEMENT_POSITION eld, but it is used when the cursor
|
4442
400
|
* position refers to an internally generated command rather than the
|
4443
401
|
* one submitted by the client. The PG_DIAG_INTERNAL_QUERY eld will
|
4444
402
|
* always appear when this eld appears.
|
4445
403
|
*/
|
4446
|
-
|
404
|
+
|
405
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_INTERNAL_POSITION", INT2FIX(PG_DIAG_INTERNAL_POSITION));
|
4447
406
|
/* #result_error_field argument constant: The text of a failed
|
4448
407
|
* internally-generated command. This could be, for example, a SQL
|
4449
408
|
* query issued by a PL/pgSQL function.
|
4450
409
|
*/
|
4451
|
-
|
410
|
+
|
411
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_INTERNAL_QUERY", INT2FIX(PG_DIAG_INTERNAL_QUERY));
|
4452
412
|
/* #result_error_field argument constant: An indication of the context
|
4453
413
|
* in which the error occurred. Presently this includes a call stack
|
4454
414
|
* traceback of active procedural language functions and internally-generated
|
4455
415
|
* queries. The trace is one entry per line, most recent rst.
|
4456
416
|
*/
|
4457
|
-
|
417
|
+
|
418
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_CONTEXT", INT2FIX(PG_DIAG_CONTEXT));
|
4458
419
|
/* #result_error_field argument constant: The le name of the source-code
|
4459
420
|
* location where the error was reported. */
|
4460
|
-
rb_define_const(
|
421
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FILE", INT2FIX(PG_DIAG_SOURCE_FILE));
|
422
|
+
|
4461
423
|
/* #result_error_field argument constant: The line number of the
|
4462
424
|
* source-code location where the error was reported. */
|
4463
|
-
rb_define_const(
|
425
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_LINE", INT2FIX(PG_DIAG_SOURCE_LINE));
|
426
|
+
|
4464
427
|
/* #result_error_field argument constant: The name of the source-code
|
4465
428
|
* function reporting the error. */
|
4466
|
-
rb_define_const(
|
429
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FUNCTION", INT2FIX(PG_DIAG_SOURCE_FUNCTION));
|
4467
430
|
|
4468
431
|
/* Invalid OID constant */
|
4469
|
-
rb_define_const(
|
4470
|
-
|
4471
|
-
/****** PGresult INSTANCE METHODS: libpq ******/
|
4472
|
-
rb_define_method(rb_cPGresult, "result_status", pgresult_result_status, 0);
|
4473
|
-
rb_define_method(rb_cPGresult, "res_status", pgresult_res_status, 1);
|
4474
|
-
rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
|
4475
|
-
rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
|
4476
|
-
rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
|
4477
|
-
rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
|
4478
|
-
rb_define_method(rb_cPGresult, "clear", pgresult_clear, 0);
|
4479
|
-
rb_define_method(rb_cPGresult, "ntuples", pgresult_ntuples, 0);
|
4480
|
-
rb_define_alias(rb_cPGresult, "num_tuples", "ntuples");
|
4481
|
-
rb_define_method(rb_cPGresult, "nfields", pgresult_nfields, 0);
|
4482
|
-
rb_define_alias(rb_cPGresult, "num_fields", "nfields");
|
4483
|
-
rb_define_method(rb_cPGresult, "fname", pgresult_fname, 1);
|
4484
|
-
rb_define_method(rb_cPGresult, "fnumber", pgresult_fnumber, 1);
|
4485
|
-
rb_define_method(rb_cPGresult, "ftable", pgresult_ftable, 1);
|
4486
|
-
rb_define_method(rb_cPGresult, "ftablecol", pgresult_ftablecol, 1);
|
4487
|
-
rb_define_method(rb_cPGresult, "fformat", pgresult_fformat, 1);
|
4488
|
-
rb_define_method(rb_cPGresult, "ftype", pgresult_ftype, 1);
|
4489
|
-
rb_define_method(rb_cPGresult, "fmod", pgresult_fmod, 1);
|
4490
|
-
rb_define_method(rb_cPGresult, "fsize", pgresult_fsize, 1);
|
4491
|
-
rb_define_method(rb_cPGresult, "getvalue", pgresult_getvalue, 2);
|
4492
|
-
rb_define_method(rb_cPGresult, "getisnull", pgresult_getisnull, 2);
|
4493
|
-
rb_define_method(rb_cPGresult, "getlength", pgresult_getlength, 2);
|
4494
|
-
rb_define_method(rb_cPGresult, "nparams", pgresult_nparams, 0);
|
4495
|
-
rb_define_method(rb_cPGresult, "paramtype", pgresult_paramtype, 1);
|
4496
|
-
rb_define_method(rb_cPGresult, "cmd_status", pgresult_cmd_status, 0);
|
4497
|
-
rb_define_method(rb_cPGresult, "cmd_tuples", pgresult_cmd_tuples, 0);
|
4498
|
-
rb_define_alias(rb_cPGresult, "cmdtuples", "cmd_tuples");
|
4499
|
-
rb_define_method(rb_cPGresult, "oid_value", pgresult_oid_value, 0);
|
432
|
+
rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
|
433
|
+
rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
|
4500
434
|
|
4501
|
-
|
4502
|
-
|
4503
|
-
rb_define_method(rb_cPGresult, "each", pgresult_each, 0);
|
4504
|
-
rb_define_method(rb_cPGresult, "fields", pgresult_fields, 0);
|
4505
|
-
rb_define_method(rb_cPGresult, "values", pgresult_values, 0);
|
4506
|
-
rb_define_method(rb_cPGresult, "column_values", pgresult_column_values, 1);
|
4507
|
-
rb_define_method(rb_cPGresult, "field_values", pgresult_field_values, 1);
|
435
|
+
/* Add the constants to the toplevel namespace */
|
436
|
+
rb_include_module( rb_mPG, rb_mPGconstants );
|
4508
437
|
|
4509
|
-
#ifdef M17N_SUPPORTED
|
4510
|
-
|
438
|
+
#ifdef M17N_SUPPORTED
|
439
|
+
enc_pg2ruby = st_init_numtable();
|
440
|
+
s_id_index = rb_intern("@encoding");
|
4511
441
|
#endif
|
442
|
+
|
443
|
+
/* Initialize the main extension classes */
|
444
|
+
init_pg_connection();
|
445
|
+
init_pg_result();
|
4512
446
|
}
|
447
|
+
|