pg 0.9.0.pre156-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,541 @@
1
+ /************************************************
2
+
3
+ compat.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: jdavis $
12
+ $Date: 2007-12-04 14:25:44 -0800 (Tue, 04 Dec 2007) $
13
+ ************************************************/
14
+
15
+ #include <ctype.h>
16
+ #include "compat.h"
17
+
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
+
59
+ PGresult *
60
+ PQdescribePrepared(PGconn *conn, const char *stmtName)
61
+ {
62
+ rb_raise(rb_eStandardError, "PQdescribePrepared not supported by this client version.");
63
+ }
64
+
65
+ PGresult *
66
+ PQdescribePortal(PGconn *conn, const char *portalName)
67
+ {
68
+ rb_raise(rb_eStandardError, "PQdescribePortal not supported by this client version.");
69
+ }
70
+
71
+ int
72
+ PQsendDescribePrepared(PGconn *conn, const char *stmtName)
73
+ {
74
+ rb_raise(rb_eStandardError, "PQsendDescribePrepared not supported by this client version.");
75
+ }
76
+
77
+ int
78
+ PQsendDescribePortal(PGconn *conn, const char *portalName)
79
+ {
80
+ rb_raise(rb_eStandardError, "PQsendDescribePortal not supported by this client version.");
81
+ }
82
+
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
99
+ PGresult *
100
+ PQprepare(PGconn *conn, const char *stmtName, const char *query,
101
+ int nParams, const Oid *paramTypes)
102
+ {
103
+ rb_raise(rb_eStandardError, "PQprepare not supported by this client version.");
104
+ }
105
+
106
+ int
107
+ PQsendPrepare(PGconn *conn, const char *stmtName, const char *query,
108
+ int nParams, const Oid *paramTypes)
109
+ {
110
+ rb_raise(rb_eStandardError, "PQsendPrepare not supported by this client version.");
111
+ }
112
+
113
+ int
114
+ PQserverVersion(const PGconn* conn)
115
+ {
116
+ rb_raise(rb_eStandardError, "PQserverVersion not supported by this client version.");
117
+ }
118
+ #endif /* PG_BEFORE_080000 */
119
+
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)
125
+ {
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.");
139
+ }
140
+
141
+ int
142
+ PQprotocolVersion(const PGconn *conn)
143
+ {
144
+ rb_raise(rb_eStandardError, "PQprotocolVersion not supported by this client version.");
145
+ }
146
+
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)
151
+ {
152
+ rb_raise(rb_eStandardError, "PQexecPrepared not supported by this client version.");
153
+ }
154
+
155
+ int
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)
159
+ {
160
+ rb_raise(rb_eStandardError, "PQsendQueryParams not supported by this client version.");
161
+ }
162
+
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)
167
+ {
168
+ rb_raise(rb_eStandardError, "PQsendQueryPrepared not supported by this client version.");
169
+ }
170
+
171
+ int
172
+ PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
173
+ {
174
+ rb_raise(rb_eStandardError, "PQputCopyData not supported by this client version.");
175
+ }
176
+
177
+ int
178
+ PQputCopyEnd(PGconn *conn, const char *errormsg)
179
+ {
180
+ rb_raise(rb_eStandardError, "PQputCopyEnd not supported by this client version.");
181
+ }
182
+
183
+ int
184
+ PQgetCopyData(PGconn *conn, char **buffer, int async)
185
+ {
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.");
199
+ }
200
+
201
+ int
202
+ PQftablecol(const PGresult *res, int column_number)
203
+ {
204
+ rb_raise(rb_eStandardError, "PQftablecol not supported by this client version.");
205
+ }
206
+
207
+ int
208
+ PQfformat(const PGresult *res, int column_number)
209
+ {
210
+ rb_raise(rb_eStandardError, "PQfformat not supported by this client version.");
211
+ }
212
+
213
+ PQnoticeReceiver
214
+ PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
215
+ {
216
+ rb_raise(rb_eStandardError, "PQsetNoticeReceiver not supported by this client version.");
217
+ }
218
+
219
+ char *
220
+ PQresultErrorField(const PGresult *res, int fieldcode)
221
+ {
222
+ rb_raise(rb_eStandardError, "PQresultErrorField not supported by this client version.");
223
+ }
224
+ #endif /* PG_BEFORE_070400 */
225
+
226
+ #ifdef PG_BEFORE_070300
227
+ size_t
228
+ PQescapeStringConn(PGconn *conn, char *to, const char *from,
229
+ size_t length, int *error)
230
+ {
231
+ return PQescapeString(to,from,length);
232
+ }
233
+
234
+ unsigned char *
235
+ PQescapeByteaConn(PGconn *conn, const unsigned char *from,
236
+ size_t from_length, size_t *to_length)
237
+ {
238
+ return PQescapeBytea(from, from_length, to_length);
239
+ }
240
+ #endif /* PG_BEFORE_070300 */
241
+
242
+
243
+ /**************************************************************************
244
+
245
+ IF ANY CODE IS COPIED FROM POSTGRESQL, PLACE IT AFTER THIS COMMENT.
246
+
247
+ ***************************************************************************
248
+
249
+ Portions of code after this point were copied from the PostgreSQL source
250
+ distribution, available at http://www.postgresql.org
251
+
252
+ ***************************************************************************
253
+
254
+ Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
255
+
256
+ Portions Copyright (c) 1994, The Regents of the University of California
257
+
258
+ Permission to use, copy, modify, and distribute this software and its
259
+ documentation for any purpose, without fee, and without a written agreement
260
+ is hereby granted, provided that the above copyright notice and this
261
+ paragraph and the following two paragraphs appear in all copies.
262
+
263
+ IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
264
+ DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
265
+ LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
266
+ DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
267
+ POSSIBILITY OF SUCH DAMAGE.
268
+
269
+ THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
270
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
271
+ AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
272
+ ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
273
+ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
274
+
275
+ **************************************************************************/
276
+
277
+ #ifndef HAVE_PQSETCLIENTENCODING
278
+ int
279
+ PQsetClientEncoding(PGconn *conn, const char *encoding)
280
+ {
281
+ char qbuf[128];
282
+ static const char query[] = "set client_encoding to '%s'";
283
+ PGresult *res;
284
+ int status;
285
+
286
+ if (!conn || PQstatus(conn) != CONNECTION_OK)
287
+ return -1;
288
+
289
+ if (!encoding)
290
+ return -1;
291
+
292
+ /* check query buffer overflow */
293
+ if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
294
+ return -1;
295
+
296
+ /* ok, now send a query */
297
+ sprintf(qbuf, query, encoding);
298
+ res = PQexec(conn, qbuf);
299
+
300
+ if (res == NULL)
301
+ return -1;
302
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
303
+ status = -1;
304
+ else
305
+ {
306
+ /*
307
+ * In protocol 2 we have to assume the setting will stick, and adjust
308
+ * our state immediately. In protocol 3 and up we can rely on the
309
+ * backend to report the parameter value, and we'll change state at
310
+ * that time.
311
+ */
312
+ if (PQprotocolVersion(conn) < 3)
313
+ pqSaveParameterStatus(conn, "client_encoding", encoding);
314
+ status = 0; /* everything is ok */
315
+ }
316
+ PQclear(res);
317
+ return status;
318
+ }
319
+ #endif /* HAVE_PQSETCLIENTENCODING */
320
+
321
+ #ifndef HAVE_PQESCAPESTRING
322
+ /*
323
+ * Escaping arbitrary strings to get valid SQL literal strings.
324
+ *
325
+ * Replaces "\\" with "\\\\" and "'" with "''".
326
+ *
327
+ * length is the length of the source string. (Note: if a terminating NUL
328
+ * is encountered sooner, PQescapeString stops short of "length"; the behavior
329
+ * is thus rather like strncpy.)
330
+ *
331
+ * For safety the buffer at "to" must be at least 2*length + 1 bytes long.
332
+ * A terminating NUL character is added to the output string, whether the
333
+ * input is NUL-terminated or not.
334
+ *
335
+ * Returns the actual length of the output (not counting the terminating NUL).
336
+ */
337
+ size_t
338
+ PQescapeString(char *to, const char *from, size_t length)
339
+ {
340
+ const char *source = from;
341
+ char *target = to;
342
+ size_t remaining = length;
343
+
344
+ while (remaining > 0 && *source != '\0')
345
+ {
346
+ switch (*source)
347
+ {
348
+ case '\\':
349
+ *target++ = '\\';
350
+ *target++ = '\\';
351
+ break;
352
+
353
+ case '\'':
354
+ *target++ = '\'';
355
+ *target++ = '\'';
356
+ break;
357
+
358
+ default:
359
+ *target++ = *source;
360
+ break;
361
+ }
362
+ source++;
363
+ remaining--;
364
+ }
365
+
366
+ /* Write the terminating NUL character. */
367
+ *target = '\0';
368
+
369
+ return target - to;
370
+ }
371
+
372
+ /*
373
+ * PQescapeBytea - converts from binary string to the
374
+ * minimal encoding necessary to include the string in an SQL
375
+ * INSERT statement with a bytea type column as the target.
376
+ *
377
+ * The following transformations are applied
378
+ * '\0' == ASCII 0 == \\000
379
+ * '\'' == ASCII 39 == \'
380
+ * '\\' == ASCII 92 == \\\\
381
+ * anything < 0x20, or > 0x7e ---> \\ooo
382
+ * (where ooo is an octal expression)
383
+ */
384
+ unsigned char *
385
+ PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen)
386
+ {
387
+ const unsigned char *vp;
388
+ unsigned char *rp;
389
+ unsigned char *result;
390
+ size_t i;
391
+ size_t len;
392
+
393
+ /*
394
+ * empty string has 1 char ('\0')
395
+ */
396
+ len = 1;
397
+
398
+ vp = bintext;
399
+ for (i = binlen; i > 0; i--, vp++)
400
+ {
401
+ if (*vp < 0x20 || *vp > 0x7e)
402
+ len += 5; /* '5' is for '\\ooo' */
403
+ else if (*vp == '\'')
404
+ len += 2;
405
+ else if (*vp == '\\')
406
+ len += 4;
407
+ else
408
+ len++;
409
+ }
410
+
411
+ rp = result = (unsigned char *) malloc(len);
412
+ if (rp == NULL)
413
+ return NULL;
414
+
415
+ vp = bintext;
416
+ *bytealen = len;
417
+
418
+ for (i = binlen; i > 0; i--, vp++)
419
+ {
420
+ if (*vp < 0x20 || *vp > 0x7e)
421
+ {
422
+ (void) sprintf(rp, "\\\\%03o", *vp);
423
+ rp += 5;
424
+ }
425
+ else if (*vp == '\'')
426
+ {
427
+ rp[0] = '\\';
428
+ rp[1] = '\'';
429
+ rp += 2;
430
+ }
431
+ else if (*vp == '\\')
432
+ {
433
+ rp[0] = '\\';
434
+ rp[1] = '\\';
435
+ rp[2] = '\\';
436
+ rp[3] = '\\';
437
+ rp += 4;
438
+ }
439
+ else
440
+ *rp++ = *vp;
441
+ }
442
+ *rp = '\0';
443
+
444
+ return result;
445
+ }
446
+
447
+ #define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
448
+ #define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
449
+ #define OCTVAL(CH) ((CH) - '0')
450
+
451
+ /*
452
+ * PQunescapeBytea - converts the null terminated string representation
453
+ * of a bytea, strtext, into binary, filling a buffer. It returns a
454
+ * pointer to the buffer (or NULL on error), and the size of the
455
+ * buffer in retbuflen. The pointer may subsequently be used as an
456
+ * argument to the function free(3). It is the reverse of PQescapeBytea.
457
+ *
458
+ * The following transformations are made:
459
+ * \\ == ASCII 92 == \
460
+ * \ooo == a byte whose value = ooo (ooo is an octal number)
461
+ * \x == x (x is any character not matched by the above transformations)
462
+ */
463
+ unsigned char *
464
+ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
465
+ {
466
+ size_t strtextlen,
467
+ buflen;
468
+ unsigned char *buffer,
469
+ *tmpbuf;
470
+ size_t i,
471
+ j;
472
+
473
+ if (strtext == NULL)
474
+ return NULL;
475
+
476
+ strtextlen = strlen(strtext);
477
+
478
+ /*
479
+ * Length of input is max length of output, but add one to avoid
480
+ * unportable malloc(0) if input is zero-length.
481
+ */
482
+ buffer = (unsigned char *) malloc(strtextlen + 1);
483
+ if (buffer == NULL)
484
+ return NULL;
485
+
486
+ for (i = j = 0; i < strtextlen;)
487
+ {
488
+ switch (strtext[i])
489
+ {
490
+ case '\\':
491
+ i++;
492
+ if (strtext[i] == '\\')
493
+ buffer[j++] = strtext[i++];
494
+ else
495
+ {
496
+ if ((ISFIRSTOCTDIGIT(strtext[i])) &&
497
+ (ISOCTDIGIT(strtext[i + 1])) &&
498
+ (ISOCTDIGIT(strtext[i + 2])))
499
+ {
500
+ int byte;
501
+
502
+ byte = OCTVAL(strtext[i++]);
503
+ byte = (byte << 3) + OCTVAL(strtext[i++]);
504
+ byte = (byte << 3) + OCTVAL(strtext[i++]);
505
+ buffer[j++] = byte;
506
+ }
507
+ }
508
+
509
+ /*
510
+ * Note: if we see '\' followed by something that isn't a
511
+ * recognized escape sequence, we loop around having done
512
+ * nothing except advance i. Therefore the something will
513
+ * be emitted as ordinary data on the next cycle. Corner
514
+ * case: '\' at end of string will just be discarded.
515
+ */
516
+ break;
517
+
518
+ default:
519
+ buffer[j++] = strtext[i++];
520
+ break;
521
+ }
522
+ }
523
+ buflen = j; /* buflen is the length of the dequoted
524
+ * data */
525
+
526
+ /* Shrink the buffer to be no larger than necessary */
527
+ /* +1 avoids unportable behavior when buflen==0 */
528
+ tmpbuf = realloc(buffer, buflen + 1);
529
+
530
+ /* It would only be a very brain-dead realloc that could fail, but... */
531
+ if (!tmpbuf)
532
+ {
533
+ free(buffer);
534
+ return NULL;
535
+ }
536
+
537
+ *retbuflen = buflen;
538
+ return tmpbuf;
539
+ }
540
+ #endif
541
+