ruby-pg 0.7.9.2008.01.08 → 0.7.9.2008.01.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (6) hide show
  1. data/ext/compat.c +140 -105
  2. data/ext/compat.h +130 -102
  3. data/ext/extconf.rb +56 -28
  4. data/ext/pg.c +150 -5
  5. data/ext/pg.h +21 -0
  6. metadata +2 -2
@@ -12,189 +12,225 @@
12
12
  $Date: 2007-12-04 14:25:44 -0800 (Tue, 04 Dec 2007) $
13
13
  ************************************************/
14
14
 
15
+ #include <ctype.h>
15
16
  #include "compat.h"
16
17
 
17
- #ifndef HAVE_PQDESCRIBEPREPARED
18
+ #ifdef PG_BEFORE_080300
19
+ int
20
+ PQconnectionNeedsPassword(PGconn *conn)
21
+ {
22
+ rb_raise(rb_eStandardError,
23
+ "PQconnectionNeedsPassword not supported by this client version.");
24
+ }
25
+
26
+ int
27
+ PQconnectionUsedPassword(PGconn *conn)
28
+ {
29
+ rb_raise(rb_eStandardError,
30
+ "PQconnectionUsedPassword not supported by this client version.");
31
+ }
32
+
33
+ int
34
+ lo_truncate(PGconn *conn, int fd, size_t len)
35
+ {
36
+ rb_raise(rb_eStandardError, "lo_truncate not supported by this client version.");
37
+ }
38
+ #endif /* PG_BEFORE_080300 */
39
+
40
+ #ifdef PG_BEFORE_080200
41
+ int
42
+ PQisthreadsafe()
43
+ {
44
+ return Qfalse;
45
+ }
46
+
47
+ int
48
+ PQnparams(const PGresult *res)
49
+ {
50
+ rb_raise(rb_eStandardError, "PQnparams not supported by this client version.");
51
+ }
52
+
53
+ Oid
54
+ PQparamtype(const PGresult *res, int param_number)
55
+ {
56
+ rb_raise(rb_eStandardError, "PQparamtype not supported by this client version.");
57
+ }
58
+
18
59
  PGresult *
19
60
  PQdescribePrepared(PGconn *conn, const char *stmtName)
20
61
  {
21
62
  rb_raise(rb_eStandardError, "PQdescribePrepared not supported by this client version.");
22
63
  }
23
- #endif /* HAVE_PQDESCRIBEPREPARED */
24
64
 
25
- #ifndef HAVE_PQDESCRIBEPORTAL
26
65
  PGresult *
27
66
  PQdescribePortal(PGconn *conn, const char *portalName)
28
67
  {
29
68
  rb_raise(rb_eStandardError, "PQdescribePortal not supported by this client version.");
30
69
  }
31
- #endif /* HAVE_PQDESCRIBEPORTAL */
32
70
 
33
- #ifndef HAVE_PQESCAPESTRINGCONN
34
- size_t
35
- PQescapeStringConn(PGconn *conn, char *to, const char *from,
36
- size_t length, int *error)
71
+ int
72
+ PQsendDescribePrepared(PGconn *conn, const char *stmtName)
37
73
  {
38
- return PQescapeString(to,from,length);
74
+ rb_raise(rb_eStandardError, "PQsendDescribePrepared not supported by this client version.");
39
75
  }
40
76
 
41
- unsigned char *
42
- PQescapeByteaConn(PGconn *conn, const unsigned char *from,
43
- size_t from_length, size_t *to_length)
77
+ int
78
+ PQsendDescribePortal(PGconn *conn, const char *portalName)
44
79
  {
45
- return PQescapeBytea(from, from_length, to_length);
80
+ rb_raise(rb_eStandardError, "PQsendDescribePortal not supported by this client version.");
46
81
  }
47
- #endif /* HAVE_PQESCAPESTRINGCONN */
48
82
 
49
- #ifndef HAVE_PQPREPARE
83
+ char *
84
+ PQencryptPassword(const char *passwd, const char *user)
85
+ {
86
+ rb_raise(rb_eStandardError, "PQencryptPassword not supported by this client version.");
87
+ }
88
+ #endif /* PG_BEFORE_080200 */
89
+
90
+ #ifdef PG_BEFORE_080100
91
+ Oid
92
+ lo_create(PGconn *conn, Oid lobjId)
93
+ {
94
+ rb_raise(rb_eStandardError, "lo_create not supported by this client version.");
95
+ }
96
+ #endif /* PG_BEFORE_080100 */
97
+
98
+ #ifdef PG_BEFORE_080000
50
99
  PGresult *
51
100
  PQprepare(PGconn *conn, const char *stmtName, const char *query,
52
101
  int nParams, const Oid *paramTypes)
53
102
  {
54
103
  rb_raise(rb_eStandardError, "PQprepare not supported by this client version.");
55
104
  }
56
- #endif /* HAVE_PQPREPARE */
57
105
 
58
- #ifndef HAVE_PQCONNECTIONNEEDSPASSWORD
59
106
  int
60
- PQconnectionNeedsPassword(PGconn *conn)
107
+ PQsendPrepare(PGconn *conn, const char *stmtName, const char *query,
108
+ int nParams, const Oid *paramTypes)
61
109
  {
62
- rb_raise(rb_eStandardError,
63
- "PQconnectionNeedsPassword not supported by this client version.");
110
+ rb_raise(rb_eStandardError, "PQsendPrepare not supported by this client version.");
64
111
  }
65
- #endif /* HAVE_PQCONNECTIONUSEDPASSWORD */
66
112
 
67
- #ifndef HAVE_PQCONNECTIONUSEDPASSWORD
68
113
  int
69
- PQconnectionUsedPassword(PGconn *conn)
114
+ PQserverVersion(const PGconn* conn)
70
115
  {
71
- rb_raise(rb_eStandardError,
72
- "PQconnectionUsedPassword not supported by this client version.");
116
+ rb_raise(rb_eStandardError, "PQserverVersion not supported by this client version.");
73
117
  }
74
- #endif /* HAVE_PQCONNECTIONUSEDPASSWORD */
118
+ #endif /* PG_BEFORE_080000 */
75
119
 
76
- #ifndef HAVE_PQISTHREADSAFE
77
- int
78
- PQisthreadsafe()
120
+ #ifdef PG_BEFORE_070400
121
+ PGresult *
122
+ PQexecParams(PGconn *conn, const char *command, int nParams,
123
+ const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
124
+ const int *paramFormats, int resultFormat)
79
125
  {
80
- return Qfalse;
126
+ rb_raise(rb_eStandardError, "PQexecParams not supported by this client version.");
127
+ }
128
+
129
+ PGTransactionStatusType
130
+ PQtransactionStatus(const PGconn *conn)
131
+ {
132
+ rb_raise(rb_eStandardError, "PQtransactionStatus not supported by this client version.");
133
+ }
134
+
135
+ char *
136
+ PQparameterStatus(const PGconn *conn, const char *paramName)
137
+ {
138
+ rb_raise(rb_eStandardError, "PQparameterStatus not supported by this client version.");
81
139
  }
82
- #endif /* HAVE_PQISTHREADSAFE */
83
140
 
84
- #ifndef HAVE_LO_TRUNCATE
85
141
  int
86
- lo_truncate(PGconn *conn, int fd, size_t len)
142
+ PQprotocolVersion(const PGconn *conn)
87
143
  {
88
- rb_raise(rb_eStandardError, "lo_truncate not supported by this client version.");
144
+ rb_raise(rb_eStandardError, "PQprotocolVersion not supported by this client version.");
89
145
  }
90
- #endif /* HAVE_LO_TRUNCATE */
91
146
 
92
- #ifndef HAVE_LO_CREATE
93
- Oid
94
- lo_create(PGconn *conn, Oid lobjId)
147
+ PGresult
148
+ *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams,
149
+ const char * const *ParamValues, const int *paramLengths, const int *paramFormats,
150
+ int resultFormat)
95
151
  {
96
- rb_raise(rb_eStandardError, "lo_create not supported by this client version.");
152
+ rb_raise(rb_eStandardError, "PQexecPrepared not supported by this client version.");
97
153
  }
98
- #endif /* HAVE_LO_CREATE */
99
154
 
100
- #ifndef HAVE_PQNPARAMS
101
155
  int
102
- PQnparams(const PGresult *res)
156
+ PQsendQueryParams(PGconn *conn, const char *command, int nParams,
157
+ const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
158
+ const int *paramFormats, int resultFormat)
103
159
  {
104
- rb_raise(rb_eStandardError, "PQnparams not supported by this client version.");
160
+ rb_raise(rb_eStandardError, "PQsendQueryParams not supported by this client version.");
105
161
  }
106
- #endif /* HAVE_PQNPARAMS */
107
162
 
108
- #ifndef HAVE_PQPARAMTYPE
109
- Oid
110
- PQparamtype(const PGresult *res, int param_number)
163
+ int
164
+ PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams,
165
+ const char * const *ParamValues, const int *paramLengths, const int *paramFormats,
166
+ int resultFormat)
111
167
  {
112
- rb_raise(rb_eStandardError, "PQparamtype not supported by this client version.");
168
+ rb_raise(rb_eStandardError, "PQsendQueryPrepared not supported by this client version.");
113
169
  }
114
- #endif /* HAVE_PQPARAMTYPE */
115
170
 
116
- #ifndef HAVE_PQSERVERVERSION
117
171
  int
118
- PQserverVersion(const PGconn* conn)
172
+ PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
119
173
  {
120
- rb_raise(rb_eStandardError, "PQserverVersion not supported by this client version.");
174
+ rb_raise(rb_eStandardError, "PQputCopyData not supported by this client version.");
121
175
  }
122
- #endif /* HAVE_PQSERVERVERSION */
123
176
 
124
- #ifndef HAVE_PQSENDDESCRIBEPREPARED
125
177
  int
126
- PQsendDescribePrepared(PGconn *conn, const char *stmtName)
178
+ PQputCopyEnd(PGconn *conn, const char *errormsg)
127
179
  {
128
- rb_raise(rb_eStandardError, "PQsendDescribePrepared not supported by this client version.");
180
+ rb_raise(rb_eStandardError, "PQputCopyEnd not supported by this client version.");
129
181
  }
130
- #endif /* HAVE_PQSENDDESCRIBEPREPARED */
131
182
 
132
- #ifndef HAVE_PQSENDDESCRIBEPORTAL
133
183
  int
134
- PQsendDescribePortal(PGconn *conn, const char *portalName)
184
+ PQgetCopyData(PGconn *conn, char **buffer, int async)
135
185
  {
136
- rb_raise(rb_eStandardError, "PQsendDescribePortal not supported by this client version.");
186
+ rb_raise(rb_eStandardError, "PQgetCopyData not supported by this client version.");
187
+ }
188
+
189
+ PGVerbosity
190
+ PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity)
191
+ {
192
+ rb_raise(rb_eStandardError, "PQsetErrorVerbosity not supported by this client version.");
193
+ }
194
+
195
+ Oid
196
+ PQftable(const PGresult *res, int column_number)
197
+ {
198
+ rb_raise(rb_eStandardError, "PQftable not supported by this client version.");
137
199
  }
138
- #endif /* HAVE_PQSENDDESCRIBEPORTAL */
139
200
 
140
- #ifndef HAVE_PQSENDPREPARE
141
201
  int
142
- PQsendPrepare(PGconn *conn, const char *stmtName, const char *query,
143
- int nParams, const Oid *paramTypes)
202
+ PQftablecol(const PGresult *res, int column_number)
144
203
  {
145
- rb_raise(rb_eStandardError, "PQsendPrepare not supported by this client version.");
204
+ rb_raise(rb_eStandardError, "PQftablecol not supported by this client version.");
146
205
  }
147
- #endif /* HAVE_PQSENDPREPARE */
148
206
 
149
- #ifndef HAVE_PQENCRYPTPASSWORD
150
- char *
151
- PQencryptPassword(const char *passwd, const char *user)
207
+ int
208
+ PQfformat(const PGresult *res, int column_number)
152
209
  {
153
- rb_raise(rb_eStandardError, "PQencryptPassword not supported by this client version.");
210
+ rb_raise(rb_eStandardError, "PQfformat not supported by this client version.");
154
211
  }
155
- #endif /* HAVE_PQENCRYPTPASSWORD */
212
+ #endif /* PG_BEFORE_070400 */
156
213
 
157
- #ifndef HAVE_PQEXECPARAMS
158
- PGresult *
159
- PQexecParams(PGconn *conn, const char *command, int nParams,
160
- const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
161
- const int *paramFormats, int resultFormat)
214
+ #ifdef PG_BEFORE_070300
215
+ size_t
216
+ PQescapeStringConn(PGconn *conn, char *to, const char *from,
217
+ size_t length, int *error)
162
218
  {
163
- rb_raise(rb_eStandardError, "PQexecParams not supported by this client version.");
219
+ return PQescapeString(to,from,length);
164
220
  }
165
221
 
166
- #define BIND_PARAM_PATTERN "\\$(\\d+)"
167
- #include <ruby.h>
168
- #include <re.h>
169
- PGresult *
170
- PQexecParams_compat(PGconn *conn, VALUE command, VALUE values)
171
- {
172
- VALUE bind_param_re = rb_reg_new(BIND_PARAM_PATTERN, 7, 0);
173
- VALUE result = rb_str_buf_new(RSTRING(command)->len);
174
- char* ptr = RSTRING(command)->ptr;
175
- int scan = 0;
176
- while ((scan = rb_reg_search(bind_param_re, command, scan, 0)) > 0) {
177
- VALUE match = rb_backref_get();
178
- int pos = BindParamNumber(match);
179
- if (pos < RARRAY(values)->len) {
180
- rb_str_buf_cat(result, ptr, scan - (ptr - RSTRING(command)->ptr));
181
- ptr = RSTRING(command)->ptr + scan;
182
- rb_str_buf_append(result, RARRAY(values)->ptr[pos]);
183
- }
184
- scan += RSTRING(rb_reg_nth_match(0, match))->len;
185
- ptr += RSTRING(rb_reg_nth_match(0, match))->len;
186
- }
187
- rb_str_buf_cat(result, ptr, RSTRING(command)->len - (ptr - RSTRING(command)->ptr));
188
-
189
- return PQexec(conn, StringValuePtr(result));
190
- }
191
- #endif /* HAVE_PQEXECPARAMS */
222
+ unsigned char *
223
+ PQescapeByteaConn(PGconn *conn, const unsigned char *from,
224
+ size_t from_length, size_t *to_length)
225
+ {
226
+ return PQescapeBytea(from, from_length, to_length);
227
+ }
228
+ #endif /* PG_BEFORE_070300 */
192
229
 
193
230
 
194
231
  /**************************************************************************
195
232
 
196
233
  IF ANY CODE IS COPIED FROM POSTGRESQL, PLACE IT AFTER THIS COMMENT.
197
- THE BSD LICENSE REQUIRES THAT YOU MAINTAIN THIS COPYRIGHT NOTICE.
198
234
 
199
235
  ***************************************************************************
200
236
 
@@ -227,7 +263,6 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
227
263
  **************************************************************************/
228
264
 
229
265
  #ifndef HAVE_PQSETCLIENTENCODING
230
-
231
266
  int
232
267
  PQsetClientEncoding(PGconn *conn, const char *encoding)
233
268
  {
@@ -4,48 +4,47 @@
4
4
 
5
5
  #include <stdlib.h>
6
6
 
7
- #include "ruby.h"
8
- #include "rubyio.h"
9
7
  #include "libpq-fe.h"
10
8
  #include "libpq/libpq-fs.h" /* large-object interface */
11
9
 
10
+ #include "ruby.h"
12
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
+ */
13
16
  #ifndef HAVE_PQCONNECTIONUSEDPASSWORD
14
- #define POSTGRES_BEFORE_83
17
+ #define PG_BEFORE_080300
15
18
  #endif
16
19
 
17
- #if RUBY_VERSION_CODE < 180
18
- #define rb_check_string_type(x) rb_check_convert_type(x, T_STRING, "String", "to_str")
19
- #endif /* RUBY_VERSION_CODE < 180 */
20
+ #ifndef HAVE_PQISTHREADSAFE
21
+ #define PG_BEFORE_080200
22
+ #endif
20
23
 
21
- #ifndef RARRAY_LEN
22
- #define RARRAY_LEN(x) RARRAY((x))->len
23
- #endif /* RARRAY_LEN */
24
+ #ifndef HAVE_LOCREATE
25
+ #define PG_BEFORE_080100
26
+ #endif
24
27
 
25
- #ifndef RSTRING_LEN
26
- #define RSTRING_LEN(x) RSTRING((x))->len
27
- #endif /* RSTRING_LEN */
28
+ #ifndef HAVE_PQPREPARE
29
+ #define PG_BEFORE_080000
30
+ #endif
28
31
 
29
- #ifndef RSTRING_PTR
30
- #define RSTRING_PTR(x) RSTRING((x))->ptr
31
- #endif /* RSTRING_PTR */
32
+ #ifndef HAVE_PQEXECPARAMS
33
+ #define PG_BEFORE_070400
34
+ #endif
32
35
 
33
- #ifndef StringValuePtr
34
- #define StringValuePtr(x) STR2CSTR(x)
35
- #endif /* StringValuePtr */
36
+ #ifndef HAVE_PQESCAPESTRINGCONN
37
+ #define PG_BEFORE_070300
38
+ #error PostgreSQL client version too old, requires 7.3 or later.
39
+ #endif
36
40
 
37
- #ifdef POSTGRES_BEFORE_83
38
- #ifndef HAVE_PG_ENCODING_TO_CHAR
39
- #define pg_encoding_to_char(x) "SQL_ASCII"
40
- #else
41
- /* Some versions ofPostgreSQL prior to 8.3 define
42
- * pg_encoding_to_char but do not declare it
43
- * in a header file, so this declaration will
44
- * eliminate an unecessary warning
45
- */
46
- extern char* pg_encoding_to_char(int);
47
- #endif /* HAVE_PG_ENCODING_TO_CHAR */
48
- #endif /* POSTGRES_BEFORE_83 */
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
49
48
 
50
49
  #ifndef PG_DIAG_INTERNAL_POSITION
51
50
  #define PG_DIAG_INTERNAL_POSITION 'p'
@@ -55,94 +54,123 @@ extern char* pg_encoding_to_char(int);
55
54
  #define PG_DIAG_INTERNAL_QUERY 'q'
56
55
  #endif /* PG_DIAG_INTERNAL_QUERY */
57
56
 
58
- #ifndef HAVE_PQFREEMEM
59
- #define PQfreemem(ptr) free(ptr)
60
- #endif /* HAVE_PQFREEMEM */
57
+ #ifdef PG_BEFORE_080300
61
58
 
62
- #ifndef HAVE_PQSETCLIENTENCODING
63
- int PQsetClientEncoding(PGconn *conn, const char *encoding)
64
- #endif /* HAVE_PQSETCLIENTENCODING */
65
-
66
- #ifndef HAVE_PQESCAPESTRING
67
- size_t PQescapeString(char *to, const char *from, size_t length);
68
- unsigned char * PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen);
69
- unsigned char * PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen);
70
- #endif /* HAVE_PQESCAPESTRING */
71
-
72
- #ifndef HAVE_PQESCAPESTRINGCONN
73
- size_t PQescapeStringConn(PGconn *conn, char *to, const char *from,
74
- size_t length, int *error);
75
- unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from,
76
- size_t from_length, size_t *to_length);
77
- #endif /* HAVE_PQESCAPESTRINGCONN */
78
-
79
- #ifndef HAVE_PQPREPARE
80
- PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query,
81
- int nParams, const Oid *paramTypes);
82
- #endif /* HAVE_PQPREPARE */
83
-
84
- #ifndef HAVE_PQDESCRIBEPREPARED
85
- PGresult * PQdescribePrepared(PGconn *conn, const char *stmtName);
86
- #endif /* HAVE_PQDESCRIBEPREPARED */
87
-
88
- #ifndef HAVE_PQDESCRIBEPORTAL
89
- PGresult * PQdescribePortal(PGconn *conn, const char *portalName);
90
- #endif /* HAVE_PQDESCRIBEPORTAL */
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 */
91
68
 
92
- #ifndef HAVE_PQCONNECTIONNEEDSPASSWORD
93
69
  int PQconnectionNeedsPassword(PGconn *conn);
94
- #endif /* HAVE_PQCONNECTIONNEEDSPASSWORD */
95
-
96
- #ifndef HAVE_PQCONNECTIONUSEDPASSWORD
97
70
  int PQconnectionUsedPassword(PGconn *conn);
98
- #endif /* HAVE_PQCONNECTIONUSEDPASSWORD */
99
-
100
- #ifndef HAVE_PQISTHREADSAFE
101
- int PQisthreadsafe(void);
102
- #endif /* HAVE_PQISTHREADSAFE */
103
-
104
- #ifndef HAVE_LO_TRUNCATE
105
71
  int lo_truncate(PGconn *conn, int fd, size_t len);
106
- #endif /* HAVE_LO_TRUNCATE */
107
72
 
108
- #ifndef HAVE_LO_CREATE
109
- Oid lo_create(PGconn *conn, Oid lobjId);
110
- #endif /* HAVE_LO_CREATE */
73
+ #endif /* PG_BEFORE_080300 */
111
74
 
112
- #ifndef HAVE_PQNPARAMS
75
+ #ifdef PG_BEFORE_080200
76
+ int PQisthreadsafe(void);
113
77
  int PQnparams(const PGresult *res);
114
- #endif /* HAVE_PQNPARAMS */
115
-
116
- #ifndef HAVE_PQPARAMTYPE
117
78
  Oid PQparamtype(const PGresult *res, int param_number);
118
- #endif /* HAVE_PQPARAMTYPE */
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 */
119
89
 
120
- #ifndef HAVE_PQSERVERVERSION
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);
121
95
  int PQserverVersion(const PGconn* conn);
122
- #endif /* HAVE_PQSERVERVERSION */
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 enum
122
+ {
123
+ PQERRORS_TERSE, /* single-line error messages */
124
+ PQERRORS_DEFAULT, /* recommended style */
125
+ PQERRORS_VERBOSE /* all the facts, ma'am */
126
+ } PGVerbosity;
127
+
128
+ typedef enum
129
+ {
130
+ PQTRANS_IDLE, /* connection idle */
131
+ PQTRANS_ACTIVE, /* command in progress */
132
+ PQTRANS_INTRANS, /* idle, within transaction block */
133
+ PQTRANS_INERROR, /* idle, within failed transaction */
134
+ PQTRANS_UNKNOWN /* cannot determine status */
135
+ } PGTransactionStatusType;
123
136
 
124
- #ifndef HAVE_PQEXECPARAMS
125
137
  PGresult *PQexecParams(PGconn *conn, const char *command, int nParams,
126
138
  const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
127
139
  const int *paramFormats, int resultFormat);
128
- PGresult *PQexecParams_compat(PGconn *conn, VALUE command, VALUE values);
129
- #endif /* HAVE_PQEXECPARAMS */
130
-
131
- #ifndef HAVE_PQSENDDESCRIBEPREPARED
132
- int PQsendDescribePrepared(PGconn *conn, const char *stmtName);
133
- #endif /* HAVE_PQSENDDESCRIBEPREPARED */
134
-
135
- #ifndef HAVE_PQSENDDESCRIBEPORTAL
136
- int PQsendDescribePortal(PGconn *conn, const char *portalName);
137
- #endif /* HAVE_PQSENDDESCRIBEPORTAL */
140
+ PGTransactionStatusType PQtransactionStatus(const PGconn *conn);
141
+ char *PQparameterStatus(const PGconn *conn, const char *paramName);
142
+ int PQprotocolVersion(const PGconn *conn);
143
+ PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams,
144
+ const char * const *ParamValues, const int *paramLengths, const int *paramFormats,
145
+ int resultFormat);
146
+ int PQsendQueryParams(PGconn *conn, const char *command, int nParams,
147
+ const Oid *paramTypes, const char * const * paramValues, const int *paramLengths,
148
+ const int *paramFormats, int resultFormat);
149
+ int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams,
150
+ const char * const *ParamValues, const int *paramLengths, const int *paramFormats,
151
+ int resultFormat);
152
+ int PQputCopyData(PGconn *conn, const char *buffer, int nbytes);
153
+ int PQputCopyEnd(PGconn *conn, const char *errormsg);
154
+ int PQgetCopyData(PGconn *conn, char **buffer, int async);
155
+ PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity);
156
+ Oid PQftable(const PGresult *res, int column_number);
157
+ int PQftablecol(const PGresult *res, int column_number);
158
+ int PQfformat(const PGresult *res, int column_number);
138
159
 
139
- #ifndef HAVE_PQSENDPREPARE
140
- int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query,
141
- int nParams, const Oid *paramTypes);
142
- #endif /* HAVE_PQSENDPREPARE */
160
+ #else
161
+ #define PGNOTIFY_EXTRA(notify) ((notify)->extra)
162
+ #endif /* PG_BEFORE_070400 */
143
163
 
144
- #ifndef HAVE_PQENCRYPTPASSWORD
145
- char *PQencryptPassword(const char *passwd, const char *user);
146
- #endif /* HAVE_PQENCRYPTPASSWORD */
164
+ #ifdef PG_BEFORE_070300
165
+ #error unsupported postgresql version, requires 7.3 or later.
166
+ int PQsetClientEncoding(PGconn *conn, const char *encoding)
167
+ size_t PQescapeString(char *to, const char *from, size_t length);
168
+ unsigned char * PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen);
169
+ unsigned char * PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen);
170
+ size_t PQescapeStringConn(PGconn *conn, char *to, const char *from,
171
+ size_t length, int *error);
172
+ unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from,
173
+ size_t from_length, size_t *to_length);
174
+ #endif /* PG_BEFORE_070300 */
147
175
 
148
176
  #endif /* __compat_h */
@@ -1,52 +1,80 @@
1
- if RUBY_VERSION < '1.3'
2
- puts 'This library is for ruby-1.3 or higher.'
3
- exit 1
1
+ require 'mkmf'
2
+
3
+ # OS X compatibility
4
+ if(PLATFORM =~ /darwin/) then
5
+ # test if postgresql is probably universal
6
+ bindir = (IO.popen("pg_config --bindir").readline.chomp rescue nil)
7
+ filetype = (IO.popen("file #{bindir}/pg_config").
8
+ readline.chomp rescue nil)
9
+ # if it's not universal, ARCHFLAGS should be set
10
+ if((filetype !~ /universal binary/) && ENV['ARCHFLAGS'].nil?) then
11
+ arch = (IO.popen("uname -m").readline.chomp rescue nil)
12
+ $stderr.write %{
13
+ =========== WARNING ===========
14
+
15
+ You are building this extension on OS X without setting the
16
+ ARCHFLAGS environment variable, and PostgreSQL does not appear
17
+ to have been built as a universal binary. If you are seeing this
18
+ message, that means that the build will probably fail.
19
+
20
+ Try setting the environment variable ARCHFLAGS
21
+ to '-arch #{arch}' before building.
22
+
23
+ For example:
24
+ (in bash) $ export ARCHFLAGS='-arch #{arch}'
25
+ (in tcsh) % setenv ARCHFLAGS '-arch #{arch}'
26
+
27
+ Then try building again.
28
+
29
+ ===================================
30
+ }
31
+ # We don't exit here. Who knows? It might build.
32
+ end
4
33
  end
5
34
 
6
- require 'mkmf'
35
+ # windows compatibility, need different library name
36
+ if(PLATFORM =~ /mingw|mswin/) then
37
+ $libname = '/ms/libpq'
38
+ else
39
+ $libname = 'pq'
40
+ end
41
+
42
+ if RUBY_VERSION < '1.8'
43
+ puts 'This library is for ruby-1.8 or higher.'
44
+ exit 1
45
+ end
7
46
 
8
47
  def config_value(type)
9
- ENV["POSTGRES_#{type.upcase}"] || pg_config(type)
48
+ ENV["POSTGRES_#{type.upcase}"] || pg_config(type)
10
49
  end
11
50
 
12
51
  def pg_config(type)
13
- IO.popen("pg_config --#{type}dir").readline.chomp rescue nil
52
+ IO.popen("pg_config --#{type}dir").readline.chomp rescue nil
14
53
  end
15
54
 
16
55
  def have_build_env
17
- have_library('pq') && have_header('libpq-fe.h') && have_header('libpq/libpq-fs.h')
56
+ have_library($libname) && have_header('libpq-fe.h') && have_header('libpq/libpq-fs.h')
18
57
  end
19
58
 
20
59
  dir_config('pgsql', config_value('include'), config_value('lib'))
21
60
 
22
61
  desired_functions = %w(
23
- PQsetClientEncoding
24
- PQfreemem
25
- PQescapeStringConn
26
- PQprepare
27
- PQescapeString
28
- PQexecParams
29
62
  PQconnectionUsedPassword
30
- PQconnectionNeedsPassword
31
63
  PQisthreadsafe
32
- PQnparams
33
- PQparamtype
34
- PQsendDescribePrepared
35
- PQsendDescribePortal
36
- PQsendPrepare
37
- PQencryptPassword
38
- PQdescribePrepared
39
- PQdescribePortal
64
+ PQprepare
65
+ PQexecParams
66
+ PQescapeString
67
+ PQescapeStringConn
40
68
  lo_create
41
- lo_truncate
42
69
  pg_encoding_to_char
70
+ PQsetClientEncoding
43
71
  )
44
72
 
45
73
  if have_build_env
46
- desired_functions.each(&method(:have_func))
47
- $OBJS = ['pg.o','compat.o']
48
- $CFLAGS << ' -Wall -Wmissing-prototypes'
49
- create_makefile("pg")
74
+ desired_functions.each(&method(:have_func))
75
+ $OBJS = ['pg.o','compat.o']
76
+ create_makefile("pg")
50
77
  else
51
- puts 'Could not find PostgreSQL build environment (libraries & headers): Makefile not created'
78
+ puts 'Could not find PostgreSQL build environment (libraries & headers): Makefile not created'
52
79
  end
80
+
data/ext/pg.c CHANGED
@@ -9,7 +9,7 @@
9
9
  modified at: Wed Jan 20 16:41:51 1999
10
10
 
11
11
  $Author: jdavis $
12
- $Date: 2008-01-08 18:03:23 -0800 (Tue, 08 Jan 2008) $
12
+ $Date: 2008-01-24 10:47:02 -0800 (Thu, 24 Jan 2008) $
13
13
  ************************************************/
14
14
 
15
15
  #include "pg.h"
@@ -627,7 +627,7 @@ pgconn_error_message(self)
627
627
 
628
628
  /*
629
629
  * call-seq:
630
- * conn.backed_pid() -> Fixnum
630
+ * conn.backend_pid() -> Fixnum
631
631
  *
632
632
  * Returns the process ID of the backend server
633
633
  * process for this connection.
@@ -1690,7 +1690,7 @@ pgconn_notifies(self)
1690
1690
  hash = rb_hash_new();
1691
1691
  relname = rb_tainted_str_new2(notify->relname);
1692
1692
  be_pid = INT2NUM(notify->be_pid);
1693
- extra = rb_tainted_str_new2(notify->extra);
1693
+ extra = rb_tainted_str_new2(PGNOTIFY_EXTRA(notify));
1694
1694
 
1695
1695
  rb_hash_aset(hash, sym_relname, relname);
1696
1696
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -1788,6 +1788,7 @@ pgconn_get_copy_data( argc, argv, self )
1788
1788
  {
1789
1789
  VALUE async_in;
1790
1790
  VALUE error;
1791
+ VALUE result_str;
1791
1792
  int ret;
1792
1793
  int async;
1793
1794
  char *buffer;
@@ -1810,7 +1811,9 @@ pgconn_get_copy_data( argc, argv, self )
1810
1811
  if(ret == 0) { // would block
1811
1812
  return Qfalse;
1812
1813
  }
1813
- return rb_str_new(buffer, ret);
1814
+ result_str = rb_str_new(buffer, ret);
1815
+ PQfreemem(buffer);
1816
+ return result_str;
1814
1817
  }
1815
1818
 
1816
1819
  /*
@@ -1902,6 +1905,142 @@ pgconn_set_client_encoding(self, str)
1902
1905
  return Qnil;
1903
1906
  }
1904
1907
 
1908
+ /*
1909
+ * call-seq:
1910
+ * conn.transaction { |conn| ... } -> nil
1911
+ *
1912
+ * Executes a +BEGIN+ at the start of the block,
1913
+ * and a +COMMIT+ at the end of the block, or
1914
+ * +ROLLBACK+ if any exception occurs.
1915
+ */
1916
+ static VALUE
1917
+ pgconn_transaction(VALUE self)
1918
+ {
1919
+ PGconn *conn = get_pgconn(self);
1920
+ PGresult *result;
1921
+ VALUE rb_pgresult;
1922
+ int status;
1923
+
1924
+ if (rb_block_given_p()) {
1925
+ result = PQexec(conn, "BEGIN");
1926
+ rb_pgresult = new_pgresult(result);
1927
+ pgresult_check(self, rb_pgresult);
1928
+ fprintf(stderr,"BEGIN\n");
1929
+ rb_protect(rb_yield, self, &status);
1930
+ if(status == 0) {
1931
+ result = PQexec(conn, "COMMIT");
1932
+ rb_pgresult = new_pgresult(result);
1933
+ pgresult_check(self, rb_pgresult);
1934
+ fprintf(stderr,"COMMIT\n");
1935
+ }
1936
+ else {
1937
+ /* exception occurred, ROLLBACK and re-raise */
1938
+ result = PQexec(conn, "ROLLBACK");
1939
+ rb_pgresult = new_pgresult(result);
1940
+ pgresult_check(self, rb_pgresult);
1941
+ fprintf(stderr,"ROLLBACK\n");
1942
+ rb_jump_tag(status);
1943
+ }
1944
+
1945
+ }
1946
+ else {
1947
+ /* no block supplied? */
1948
+ rb_raise(rb_eArgError, "Must supply block for PGconn#transaction");
1949
+ }
1950
+ return Qnil;
1951
+ }
1952
+
1953
+ /*
1954
+ * call-seq:
1955
+ * PGconn.quote_ident( str ) -> String
1956
+ * conn.quote_ident( str ) -> String
1957
+ *
1958
+ * Returns a string that is safe for inclusion in a SQL query
1959
+ * as an identifier. Note: this is not a quote function for values,
1960
+ * but for identifiers.
1961
+ *
1962
+ * For example, in a typical SQL query: +SELECT FOO FROM MYTABLE+
1963
+ * The identifier +FOO+ is folded to lower case, so it actually means
1964
+ * +foo+. If you really want to access the case-sensitive field name
1965
+ * +FOO+, use this function like +PGconn.quote_ident('FOO')+, which
1966
+ * will return +"FOO"+ (with double-quotes). PostgreSQL will see the
1967
+ * double-quotes, and it will not fold to lower case.
1968
+ *
1969
+ * Similarly, this function also protects against special characters,
1970
+ * and other things that might allow SQL injection if the identifier
1971
+ * comes from an untrusted source.
1972
+ */
1973
+ static VALUE
1974
+ pgconn_s_quote_ident(VALUE self, VALUE in_str)
1975
+ {
1976
+ char *str = StringValuePtr(in_str);
1977
+ /* result size at most NAMEDATALEN*2 plus surrounding
1978
+ * double-quotes. */
1979
+ char buffer[NAMEDATALEN*2+2];
1980
+ int i=0,j=0;
1981
+
1982
+ if(strlen(str) >= NAMEDATALEN) {
1983
+ rb_raise(rb_eArgError,
1984
+ "Input string is longer than NAMEDATALEN-1 (%d)",
1985
+ NAMEDATALEN-1);
1986
+ }
1987
+ buffer[j++] = '"';
1988
+ for(i = 0; i < strlen(str) && str[i]; i++) {
1989
+ if(str[i] == '"')
1990
+ buffer[j++] = '"';
1991
+ buffer[j++] = str[i];
1992
+ }
1993
+ buffer[j++] = '"';
1994
+ return rb_str_new(buffer,j);
1995
+ }
1996
+
1997
+
1998
+ /*
1999
+ * call-seq:
2000
+ * conn.block( [ timeout ] ) -> Boolean
2001
+ *
2002
+ * Blocks until the server is no longer busy, or until the
2003
+ * optional _timeout_ is reached, whichever comes first.
2004
+ * _timeout_ is measured in seconds and can be fractional.
2005
+ *
2006
+ * Returns +false+ if _timeout_ is reached, +true+ otherwise.
2007
+ *
2008
+ * If +true+ is returned, +conn.is_busy+ will return +false+
2009
+ * and +conn.get_result+ will not block.
2010
+ */
2011
+ static VALUE
2012
+ pgconn_block(int argc, VALUE *argv, VALUE self)
2013
+ {
2014
+ PGconn *conn = get_pgconn(self);
2015
+ int sd = PQsocket(conn);
2016
+ int ret;
2017
+ struct timeval timeout;
2018
+ struct timeval *ptimeout = NULL;
2019
+ VALUE timeout_in;
2020
+ double timeout_sec;
2021
+ fd_set sd_rset;
2022
+
2023
+ if (rb_scan_args(argc, argv, "01", &timeout_in) == 1) {
2024
+ timeout_sec = NUM2DBL(timeout_in);
2025
+ timeout.tv_sec = (long)timeout_sec;
2026
+ timeout.tv_usec = (long)((timeout_sec - (long)timeout_sec) * 1e6);
2027
+ ptimeout = &timeout;
2028
+ }
2029
+
2030
+ PQconsumeInput(conn);
2031
+ while(PQisBusy(conn)) {
2032
+ FD_ZERO(&sd_rset);
2033
+ FD_SET(sd, &sd_rset);
2034
+ ret = rb_thread_select(sd+1, &sd_rset, NULL, NULL, ptimeout);
2035
+ /* if select() times out, return false */
2036
+ if(ret == 0)
2037
+ return Qfalse;
2038
+ PQconsumeInput(conn);
2039
+ }
2040
+
2041
+ return Qtrue;
2042
+ }
2043
+
1905
2044
  /*TODO */
1906
2045
  static void
1907
2046
  notice_proxy(self, message)
@@ -2839,6 +2978,7 @@ Init_pg()
2839
2978
  rb_define_singleton_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
2840
2979
  rb_define_singleton_method(rb_cPGconn, "isthreadsafe", pgconn_s_isthreadsafe, 0);
2841
2980
  rb_define_singleton_method(rb_cPGconn, "encrypt_password", pgconn_s_encrypt_password, 0);
2981
+ rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
2842
2982
 
2843
2983
  /****** PGconn CLASS CONSTANTS: Connection Status ******/
2844
2984
  rb_define_const(rb_cPGconn, "CONNECTION_OK", INT2FIX(CONNECTION_OK));
@@ -2881,6 +3021,7 @@ Init_pg()
2881
3021
  rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
2882
3022
  rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
2883
3023
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
3024
+ rb_define_alias(rb_cPGconn, "close", "finish");
2884
3025
 
2885
3026
  /****** PGconn INSTANCE METHODS: Connection Status ******/
2886
3027
  rb_define_method(rb_cPGconn, "db", pgconn_db, 0);
@@ -2904,6 +3045,7 @@ Init_pg()
2904
3045
 
2905
3046
  /****** PGconn INSTANCE METHODS: Command Execution ******/
2906
3047
  rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
3048
+ rb_define_alias(rb_cPGconn, "query", "exec");
2907
3049
  rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
2908
3050
  rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
2909
3051
  rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
@@ -2949,9 +3091,12 @@ Init_pg()
2949
3091
  //rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
2950
3092
  rb_define_method(rb_cPGconn, "set_notice_processor", pgconn_set_notice_processor, 0);
2951
3093
 
2952
- /****** PGconn INSTANCE METHODS: Other TODO ******/
3094
+ /****** PGconn INSTANCE METHODS: Other ******/
2953
3095
  rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
2954
3096
  rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
3097
+ rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
3098
+ rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
3099
+ rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
2955
3100
 
2956
3101
  /****** PGconn INSTANCE METHODS: Large Object Support ******/
2957
3102
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
data/ext/pg.h CHANGED
@@ -1,6 +1,7 @@
1
1
  #include <stdio.h>
2
2
  #include <stdlib.h>
3
3
  #include <sys/types.h>
4
+ #include <unistd.h>
4
5
 
5
6
  #include "ruby.h"
6
7
  #include "rubyio.h"
@@ -9,5 +10,25 @@
9
10
 
10
11
  #include "compat.h"
11
12
 
13
+ #if RUBY_VERSION_CODE < 180
14
+ #define rb_check_string_type(x) rb_check_convert_type(x, T_STRING, "String", "to_str")
15
+ #endif /* RUBY_VERSION_CODE < 180 */
16
+
17
+ #ifndef RARRAY_LEN
18
+ #define RARRAY_LEN(x) RARRAY((x))->len
19
+ #endif /* RARRAY_LEN */
20
+
21
+ #ifndef RSTRING_LEN
22
+ #define RSTRING_LEN(x) RSTRING((x))->len
23
+ #endif /* RSTRING_LEN */
24
+
25
+ #ifndef RSTRING_PTR
26
+ #define RSTRING_PTR(x) RSTRING((x))->ptr
27
+ #endif /* RSTRING_PTR */
28
+
29
+ #ifndef StringValuePtr
30
+ #define StringValuePtr(x) STR2CSTR(x)
31
+ #endif /* StringValuePtr */
32
+
12
33
  void Init_pg(void);
13
34
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: ruby-pg
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.7.9.2008.01.08
7
- date: 2008-01-08 00:00:00 -08:00
6
+ version: 0.7.9.2008.01.24
7
+ date: 2008-01-24 00:00:00 -08:00
8
8
  summary: Ruby extension library providing an API to PostgreSQL
9
9
  require_paths:
10
10
  - lib