pg 0.9.0.pre156-x86-mingw32

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