1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
/*!
\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);
}
|