ruby-pg 0.7.9.2008.01.08 → 0.7.9.2008.01.24

Sign up to get free protection for your applications and to get access to all the features.
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