123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- /*!
- \file db/driver/postgres/fetch.c
-
- \brief DBMI - Low Level PostgreSQL database driver - fetch data
- \todo implement time zone handling
-
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
-
- \author Radim Blazek
- */
- #include <stdlib.h>
- #include <string.h>
- #include <grass/dbmi.h>
- #include <grass/glocale.h>
- #include "globals.h"
- #include "proto.h"
- int db__driver_fetch(dbCursor * cn, int position, int *more)
- {
- cursor *c;
- dbToken token;
- dbTable *table;
- int i;
- /* get cursor token */
- token = db_get_cursor_token(cn);
- /* get the cursor by its token */
- if (!(c = (cursor *) db_find_token(token))) {
- db_d_append_error(_("Cursor not found"));
- db_d_report_error();
- return DB_FAILED;
- }
- /* fetch on position */
- switch (position) {
- case DB_NEXT:
- c->row++;
- break;
- case DB_CURRENT:
- break;
- case DB_PREVIOUS:
- c->row--;
- break;
- case DB_FIRST:
- c->row = 0;
- break;
- case DB_LAST:
- c->row = c->nrows - 1;
- break;
- };
- G_debug(3, "row = %d nrows = %d", c->row, c->nrows);
- if (c->row < 0 || c->row >= c->nrows) {
- *more = 0;
- return DB_OK;
- }
- *more = 1;
- /* get the data out of the descriptor into the table */
- table = db_get_cursor_table(cn);
- for (i = 0; i < c->ncols; i++) {
- int col, gpgtype, sqltype;
- dbColumn *column;
- dbValue *value;
- col = c->cols[i]; /* known cols */
- column = db_get_table_column(table, i);
- gpgtype = db_get_column_host_type(column);
- sqltype = db_get_column_sqltype(column);
- value = db_get_column_value(column);
- db_zero_string(&value->s);
- /* Is null? */
- if (PQgetisnull(c->res, c->row, col)) {
- value->isNull = 1;
- continue;
- }
- else {
- value->isNull = 0;
- }
- G_debug(3, "row %d, col %d, gpgtype %d, sqltype %d: val = '%s'",
- c->row, col, gpgtype, sqltype, PQgetvalue(c->res, c->row,
- col));
- switch (gpgtype) {
- int ns, tz;
- case PG_TYPE_CHAR:
- case PG_TYPE_BPCHAR:
- case PG_TYPE_VARCHAR:
- case PG_TYPE_TEXT:
- db_set_string(&(value->s), PQgetvalue(c->res, c->row, col));
- break;
- case PG_TYPE_BIT:
- case PG_TYPE_INT2:
- case PG_TYPE_INT4:
- case PG_TYPE_INT8:
- case PG_TYPE_SERIAL:
- case PG_TYPE_OID:
- value->i = atoi(PQgetvalue(c->res, c->row, col));
- break;
- case PG_TYPE_FLOAT4:
- case PG_TYPE_FLOAT8:
- case PG_TYPE_NUMERIC:
- value->d = atof(PQgetvalue(c->res, c->row, col));
- break;
- /* Note: we have set DATESTYLE TO ISO in db_driver_open_select_cursor() so datetime
- * format should be ISO */
- case PG_TYPE_DATE:
- /* Example: '1999-01-25' */
- ns = sscanf(PQgetvalue(c->res, c->row, col), "%4d-%2d-%2d",
- &(value->t.year), &(value->t.month), &(value->t.day));
- if (ns != 3) {
- db_d_append_error("%s %s",
- _("Unable to scan date:"),
- PQgetvalue(c->res, c->row, col));
- db_d_report_error();
- return DB_FAILED;
- }
- value->t.hour = 0;
- value->t.minute = 0;
- value->t.seconds = 0.0;
- break;
- case PG_TYPE_TIME:
- /* Example: '04:05:06.25', '04:05:06' */
- ns = sscanf(PQgetvalue(c->res, c->row, col), "%2d:%2d:%lf",
- &(value->t.hour), &(value->t.minute),
- &(value->t.seconds));
- if (ns != 3) {
- db_d_append_error("%s %s",
- _("Unable to scan time:"),
- PQgetvalue(c->res, c->row, col));
- db_d_report_error();
- return DB_FAILED;
- }
- value->t.year = 0;
- value->t.month = 0;
- value->t.day = 0;
- break;
- case PG_TYPE_TIMESTAMP:
- /* Example: '1999-01-25 04:05:06.25+01', '1999-01-25 04:05:06' */
- ns = sscanf(PQgetvalue(c->res, c->row, col),
- "%4d-%2d-%2d %2d:%2d:%lf%3d", &(value->t.year),
- &(value->t.month), &(value->t.day), &(value->t.hour),
- &(value->t.minute), &(value->t.seconds), &tz);
- if (ns == 7) {
- db_d_append_error("%s %s",
- _("Unable to scan timestamp "
- "(no idea how to process time zone):"),
- PQgetvalue(c->res, c->row, col));
- db_d_report_error();
- return DB_FAILED;
- }
- else if (ns < 6) {
- db_d_append_error("%s %s",
- _("Unable to scan timestamp "
- "(not enough arguments):"),
- PQgetvalue(c->res, c->row, col));
- db_d_report_error();
- return DB_FAILED;
- }
- break;
- case PG_TYPE_BOOL:
- if (strcmp(PQgetvalue(c->res, c->row, col), "t") == 0)
- db_set_string(&(value->s), "1");
- else if (strcmp(PQgetvalue(c->res, c->row, col), "f") == 0)
- db_set_string(&(value->s), "0");
- else
- G_warning(_("Unable to recognize boolean value"));
- break;
- }
- }
- G_debug(3, "Row fetched");
- return DB_OK;
- }
- int db__driver_get_num_rows(dbCursor * cn)
- {
- cursor *c;
- dbToken token;
- /* get cursor token */
- token = db_get_cursor_token(cn);
- /* get the cursor by its token */
- if (!(c = (cursor *) db_find_token(token))) {
- db_d_append_error(_("Taken not found"));
- db_d_report_error();
- return DB_FAILED;
- }
- return (c->nrows);
- }
|