pg-ct 0.10.0

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