86
93
"WIN", "windows-1251",
91
98
/* forward declarations of internal functions */
92
99
void _translate_postgresql_type(unsigned int oid, unsigned short *type, unsigned int *attribs);
93
100
void _get_field_info(dbi_result_t *result);
94
101
void _get_row_data(dbi_result_t *result, dbi_row_t *row, unsigned long long rowidx);
102
int _dbd_real_connect(dbi_conn_t *conn, const char *db);
96
104
/* this function is available through the PostgreSQL client library, but it
97
105
is not declared in any of their headers. I hope this won't break anything */
98
char *pg_encoding_to_char(int encoding_id);
106
const char *pg_encoding_to_char(int encoding_id);
101
109
/* real code starts here */
118
126
int dbd_connect(dbi_conn_t *conn) {
127
return _dbd_real_connect(conn, NULL);
130
int _dbd_real_connect(dbi_conn_t *conn, const char *db) {
119
131
const char *host = dbi_conn_get_option(conn, "host");
120
132
const char *username = dbi_conn_get_option(conn, "username");
121
133
const char *password = dbi_conn_get_option(conn, "password");
122
const char *dbname = dbi_conn_get_option(conn, "dbname");
135
const char *encoding = dbi_conn_get_option(conn, "encoding");
123
136
int port = dbi_conn_get_option_numeric(conn, "port");
125
138
/* pgsql specific options */
179
int dbd_fetch_row(dbi_result_t *result, unsigned long long rownum) {
214
int dbd_fetch_row(dbi_result_t *result, unsigned long long rowidx) {
180
215
dbi_row_t *row = NULL;
182
if (result->result_state == NOTHING_RETURNED) return -1;
217
if (result->result_state == NOTHING_RETURNED) return 0;
184
219
if (result->result_state == ROWS_RETURNED) {
185
220
/* get row here */
186
221
row = _dbd_row_allocate(result->numfields);
187
_get_row_data(result, row, rownum);
188
_dbd_row_finalize(result, row, rownum);
222
_get_row_data(result, row, rowidx);
223
_dbd_row_finalize(result, row, rowidx);
191
226
return 1; /* 0 on error, 1 on successful fetchrow */
214
249
const char *dbd_get_encoding(dbi_conn_t *conn){
252
const char* encodingopt;
254
dbi_result dbires = NULL;
217
255
PGconn *pgconn = (PGconn*) conn->connection;
219
257
if(!pgconn) return NULL;
221
/* this is somewhat murky as the pg_encoding_to_char()
222
function is not declared properly by the PostgreSQL client
223
library headers. This may indicate that it is not supposed
224
to be exported or that it may disappear without a trace
225
eventually. If it breaks, use a query "SHOW CLIENT_ENCODING"
227
my_enc = pg_encoding_to_char(PQclientEncoding(pgconn));
259
encodingopt = dbi_conn_get_option(conn, "encoding");
260
if (encodingopt && !strcmp(encodingopt, "auto")) {
262
/* this is somewhat murky as the pg_encoding_to_char()
263
function is not declared properly by the PostgreSQL client
264
library headers. This may indicate that it is not supposed
265
to be exported or that it may disappear without a trace
266
eventually. If it breaks, use a query "SHOW CLIENT_ENCODING"
268
my_enc = pg_encoding_to_char(PQclientEncoding(pgconn));
269
/* printf("use PQclientEncoding, auto\n"); */
271
else if (encodingopt) {
272
my_enc = pg_encoding_to_char(PQclientEncoding(pgconn));
273
/* printf("use PQclientEncoding, %s\n", encodingopt); */
276
asprintf(&sql_cmd, "SELECT encoding FROM pg_database WHERE datname='%s'", conn->current_db);
278
dbires = dbi_conn_query(conn, sql_cmd);
281
if (dbires && dbi_result_next_row(dbires)) {
282
n_encoding = dbi_result_get_int_idx(dbires, 1);
283
my_enc = pg_encoding_to_char(n_encoding);
284
/* printf("select returned encoding %d<<%s\n", n_encoding, my_enc); */
235
/* loop over all even entries in hash and compare to my_enc */
236
while (*pgsql_encoding_hash[i]) {
237
if (!strcmp(pgsql_encoding_hash[i], my_enc)) {
238
/* return corresponding odd entry */
239
return pgsql_encoding_hash[i+1];
244
/* don't know how to translate, return original string */
292
return dbd_encoding_to_iana(my_enc);
296
const char* dbd_encoding_to_iana(const char *db_encoding) {
299
/* loop over all even entries in hash and compare to penc */
300
while (*pgsql_encoding_hash[i]) {
301
if (!strcmp(pgsql_encoding_hash[i], db_encoding)) {
302
/* return corresponding odd entry */
303
return pgsql_encoding_hash[i+1];
308
/* don't know how to translate, return original encoding */
312
const char* dbd_encoding_from_iana(const char *iana_encoding) {
315
/* loop over all odd entries in hash and compare to ienc */
316
while (*pgsql_encoding_hash[i+1]) {
317
if (!strcmp(pgsql_encoding_hash[i+1], iana_encoding)) {
318
/* return corresponding even entry */
319
return pgsql_encoding_hash[i];
324
/* don't know how to translate, return original encoding */
325
return iana_encoding;
328
char *dbd_get_engine_version(dbi_conn_t *conn, char *versionstring) {
329
dbi_result_t *dbi_result;
330
const char *versioninfo = NULL;
332
/* initialize return string */
333
*versionstring = '\0';
335
dbi_result = dbd_query(conn, "SELECT VERSION()");
337
/* this query will return something like:
338
PostgreSQL 8.0.1 on i386-portbld-freebsd5.4, compiled by GCC cc (GCC) 3.4.2 [FreeBSD] 20040728
341
if (dbi_result_next_row(dbi_result)) {
345
versioninfo = dbi_result_get_string_idx(dbi_result, 1);
347
/* try to locate the version number. Look for the first dot, go
348
back where the number before the dot starts, then walk
349
forward to the last dot or number */
350
dot = strchr(versioninfo, (int)'.');
353
while (start>versioninfo && isdigit((int)(*(start-1)))) {
358
while (*(stop+1) && (isdigit((int)(*(stop+1))) || *(stop+1)=='.')) {
362
if (stop-start < VERSIONSTRING_LENGTH) {
363
strncpy(versionstring, start, stop-start+1);
364
versionstring[stop-start+1] = '\0';
368
dbi_result_free(dbi_result);
371
return versionstring;
249
374
dbi_result_t *dbd_list_dbs(dbi_conn_t *conn, const char *pattern) {
413
size_t dbd_conn_quote_string(dbi_conn_t *conn, const char *orig, char *dest) {
414
return dbd_quote_string(conn->driver, orig, dest);
417
size_t dbd_quote_binary(dbi_conn_t *conn, const unsigned char* orig, size_t from_length, unsigned char **ptr_dest) {
418
unsigned char *temp = NULL;
419
unsigned char *quoted_temp = NULL;
422
temp = PQescapeBytea(orig, from_length, &to_length);
428
if ((quoted_temp = malloc(to_length+2)) == NULL) {
429
PQfreemem((void *)temp);
433
strcpy((char *)quoted_temp, "'");
434
strcpy((char *)(quoted_temp+1), (char *)temp);
435
strcat((char *)quoted_temp, "'");
437
PQfreemem((void*)temp);
439
*ptr_dest = quoted_temp;
288
443
dbi_result_t *dbd_query(dbi_conn_t *conn, const char *statement) {
289
444
/* allocate a new dbi_result_t and fill its applicable members:
305
result = _dbd_result_create(conn, (void *)res, PQntuples(res), atol(PQcmdTuples(res)));
306
_dbd_result_set_numfields(result, PQnfields((PGresult *)result->result_handle));
460
result = _dbd_result_create(conn, (void *)res, (unsigned long long)PQntuples(res), (unsigned long long)atoll(PQcmdTuples(res)));
461
_dbd_result_set_numfields(result, (unsigned int)PQnfields((PGresult *)result->result_handle));
307
462
_get_field_info(result);
312
dbi_result_t *dbd_query_null(dbi_conn_t *conn, const unsigned char *statement, unsigned long st_length) {
467
dbi_result_t *dbd_query_null(dbi_conn_t *conn, const unsigned char *statement, size_t st_length) {
316
char *dbd_select_db(dbi_conn_t *conn, const char *db) {
471
const char *dbd_select_db(dbi_conn_t *conn, const char *db) {
317
472
/* postgresql doesn't support switching databases without reconnecting */
318
473
if (!db || !*db) {
441
600
_type = DBI_TYPE_DECIMAL;
442
601
_attribs |= DBI_DECIMAL_SIZE8;
445
_type = DBI_TYPE_DATETIME;
446
_attribs |= DBI_DATETIME_DATE;
449
_type = DBI_TYPE_DATETIME;
450
_attribs |= DBI_DATETIME_TIME;
452
case PG_TYPE_DATETIME:
453
case PG_TYPE_TIMESTAMP:
605
_type = DBI_TYPE_DATETIME;
606
_attribs |= DBI_DATETIME_DATE;
610
_type = DBI_TYPE_DATETIME;
611
_attribs |= DBI_DATETIME_TIME;
613
case PG_TYPE_TIMESTAMP:
614
case PG_TYPE_TIMESTAMPTZ:
454
615
_type = DBI_TYPE_DATETIME;
455
616
_attribs |= DBI_DATETIME_DATE;
456
617
_attribs |= DBI_DATETIME_TIME;
458
620
case PG_TYPE_NAME:
459
621
case PG_TYPE_TEXT:
460
622
case PG_TYPE_CHAR2:
497
659
void _get_row_data(dbi_result_t *result, dbi_row_t *row, unsigned long long rowidx) {
660
unsigned int curfield = 0;
499
661
char *raw = NULL;
500
unsigned long long strsize = 0;
501
unsigned long sizeattrib;
663
unsigned int sizeattrib;
502
664
dbi_data_t *data;
665
unsigned char *temp = NULL;
666
size_t unquoted_length;
504
669
while (curfield < result->numfields) {
505
670
raw = PQgetvalue((PGresult *)result->result_handle, rowidx, curfield);
506
strsize = (unsigned long long) PQfmod((PGresult *)result->result_handle, curfield);
507
671
data = &row->field_values[curfield];
509
673
row->field_sizes[curfield] = 0;
510
674
/* will be set to strlen later on for strings */
512
676
if (PQgetisnull((PGresult *)result->result_handle, rowidx, curfield) == 1) {
677
_set_field_flag( row, curfield, DBI_VALUE_NULL, 1);
517
682
switch (result->field_types[curfield]) {
518
683
case DBI_TYPE_INTEGER:
519
sizeattrib = _isolate_attrib(result->field_attribs[curfield], DBI_INTEGER_SIZE1, DBI_INTEGER_SIZE8);
520
switch (sizeattrib) {
684
switch (result->field_attribs[curfield] & DBI_INTEGER_SIZEMASK) {
521
685
case DBI_INTEGER_SIZE1:
522
686
data->d_char = (char) atol(raw); break;
523
687
case DBI_INTEGER_SIZE2:
524
688
data->d_short = (short) atol(raw); break;
525
689
case DBI_INTEGER_SIZE3:
526
690
case DBI_INTEGER_SIZE4:
527
data->d_long = (long) atol(raw); break;
691
data->d_long = (int) atol(raw); break;
528
692
case DBI_INTEGER_SIZE8:
529
693
data->d_longlong = (long long) atoll(raw); break; /* hah, wonder if that'll work */
545
708
case DBI_TYPE_STRING:
709
strsize = (size_t)PQgetlength((PGresult *)result->result_handle, rowidx, curfield);
546
710
data->d_string = strdup(raw);
547
711
row->field_sizes[curfield] = strsize;
549
case DBI_TYPE_BINARY:
550
row->field_sizes[curfield] = strsize;
551
data->d_string = malloc(strsize);
552
memcpy(data->d_string, raw, strsize);
713
case DBI_TYPE_BINARY:
714
temp = PQunescapeBytea((const unsigned char *)raw, &unquoted_length);
715
if ((data->d_string = malloc(unquoted_length)) == NULL) {
719
memmove(data->d_string, temp, unquoted_length);
721
row->field_sizes[curfield] = unquoted_length;
722
/* todo: is raw ever unescaped binary data? */
723
/* strsize = PQgetlength((PGresult *)result->result_handle, rowidx, curfield); */
724
/* row->field_sizes[curfield] = strsize; */
725
/* data->d_string = malloc(strsize); */
726
/* memcpy(data->d_string, raw, strsize); */
555
729
case DBI_TYPE_DATETIME:
556
sizeattrib = _isolate_attrib(result->field_attribs[curfield], DBI_DATETIME_DATE, DBI_DATETIME_TIME);
730
sizeattrib = result->field_attribs[curfield] & (DBI_DATETIME_DATE|DBI_DATETIME_TIME);
557
731
data->d_datetime = _dbd_parse_datetime(raw, sizeattrib);