fetch.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*!
  2. \file db/driver/postgres/fetch.c
  3. \brief DBMI - Low Level PostgreSQL database driver - fetch data
  4. \todo implement time zone handling
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Radim Blazek
  8. */
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <grass/dbmi.h>
  12. #include <grass/glocale.h>
  13. #include "globals.h"
  14. #include "proto.h"
  15. int db__driver_fetch(dbCursor * cn, int position, int *more)
  16. {
  17. cursor *c;
  18. dbToken token;
  19. dbTable *table;
  20. int i;
  21. /* get cursor token */
  22. token = db_get_cursor_token(cn);
  23. /* get the cursor by its token */
  24. if (!(c = (cursor *) db_find_token(token))) {
  25. db_d_append_error(_("Cursor not found"));
  26. db_d_report_error();
  27. return DB_FAILED;
  28. }
  29. /* fetch on position */
  30. switch (position) {
  31. case DB_NEXT:
  32. c->row++;
  33. break;
  34. case DB_CURRENT:
  35. break;
  36. case DB_PREVIOUS:
  37. c->row--;
  38. break;
  39. case DB_FIRST:
  40. c->row = 0;
  41. break;
  42. case DB_LAST:
  43. c->row = c->nrows - 1;
  44. break;
  45. };
  46. G_debug(3, "row = %d nrows = %d", c->row, c->nrows);
  47. if (c->row < 0 || c->row >= c->nrows) {
  48. *more = 0;
  49. return DB_OK;
  50. }
  51. *more = 1;
  52. /* get the data out of the descriptor into the table */
  53. table = db_get_cursor_table(cn);
  54. for (i = 0; i < c->ncols; i++) {
  55. int col, gpgtype, sqltype;
  56. dbColumn *column;
  57. dbValue *value;
  58. col = c->cols[i]; /* known cols */
  59. column = db_get_table_column(table, i);
  60. gpgtype = db_get_column_host_type(column);
  61. sqltype = db_get_column_sqltype(column);
  62. value = db_get_column_value(column);
  63. db_zero_string(&value->s);
  64. /* Is null? */
  65. if (PQgetisnull(c->res, c->row, col)) {
  66. value->isNull = 1;
  67. continue;
  68. }
  69. else {
  70. value->isNull = 0;
  71. }
  72. G_debug(3, "row %d, col %d, gpgtype %d, sqltype %d: val = '%s'",
  73. c->row, col, gpgtype, sqltype, PQgetvalue(c->res, c->row,
  74. col));
  75. switch (gpgtype) {
  76. int ns, tz;
  77. case PG_TYPE_CHAR:
  78. case PG_TYPE_BPCHAR:
  79. case PG_TYPE_VARCHAR:
  80. case PG_TYPE_TEXT:
  81. db_set_string(&(value->s), PQgetvalue(c->res, c->row, col));
  82. break;
  83. case PG_TYPE_BIT:
  84. case PG_TYPE_INT2:
  85. case PG_TYPE_INT4:
  86. case PG_TYPE_INT8:
  87. case PG_TYPE_SERIAL:
  88. case PG_TYPE_OID:
  89. value->i = atoi(PQgetvalue(c->res, c->row, col));
  90. break;
  91. case PG_TYPE_FLOAT4:
  92. case PG_TYPE_FLOAT8:
  93. case PG_TYPE_NUMERIC:
  94. value->d = atof(PQgetvalue(c->res, c->row, col));
  95. break;
  96. /* Note: we have set DATESTYLE TO ISO in db_driver_open_select_cursor() so datetime
  97. * format should be ISO */
  98. case PG_TYPE_DATE:
  99. /* Example: '1999-01-25' */
  100. ns = sscanf(PQgetvalue(c->res, c->row, col), "%4d-%2d-%2d",
  101. &(value->t.year), &(value->t.month), &(value->t.day));
  102. if (ns != 3) {
  103. db_d_append_error("%s %s",
  104. _("Unable to scan date:"),
  105. PQgetvalue(c->res, c->row, col));
  106. db_d_report_error();
  107. return DB_FAILED;
  108. }
  109. value->t.hour = 0;
  110. value->t.minute = 0;
  111. value->t.seconds = 0.0;
  112. break;
  113. case PG_TYPE_TIME:
  114. /* Example: '04:05:06.25', '04:05:06' */
  115. ns = sscanf(PQgetvalue(c->res, c->row, col), "%2d:%2d:%lf",
  116. &(value->t.hour), &(value->t.minute),
  117. &(value->t.seconds));
  118. if (ns != 3) {
  119. db_d_append_error("%s %s",
  120. _("Unable to scan time:"),
  121. PQgetvalue(c->res, c->row, col));
  122. db_d_report_error();
  123. return DB_FAILED;
  124. }
  125. value->t.year = 0;
  126. value->t.month = 0;
  127. value->t.day = 0;
  128. break;
  129. case PG_TYPE_TIMESTAMP:
  130. /* Example: '1999-01-25 04:05:06.25+01', '1999-01-25 04:05:06' */
  131. ns = sscanf(PQgetvalue(c->res, c->row, col),
  132. "%4d-%2d-%2d %2d:%2d:%lf%3d", &(value->t.year),
  133. &(value->t.month), &(value->t.day), &(value->t.hour),
  134. &(value->t.minute), &(value->t.seconds), &tz);
  135. if (ns == 7) {
  136. db_d_append_error("%s %s",
  137. _("Unable to scan timestamp "
  138. "(no idea how to process time zone):"),
  139. PQgetvalue(c->res, c->row, col));
  140. db_d_report_error();
  141. return DB_FAILED;
  142. }
  143. else if (ns < 6) {
  144. db_d_append_error("%s %s",
  145. _("Unable to scan timestamp "
  146. "(not enough arguments):"),
  147. PQgetvalue(c->res, c->row, col));
  148. db_d_report_error();
  149. return DB_FAILED;
  150. }
  151. break;
  152. case PG_TYPE_BOOL:
  153. if (strcmp(PQgetvalue(c->res, c->row, col), "t") == 0)
  154. db_set_string(&(value->s), "1");
  155. else if (strcmp(PQgetvalue(c->res, c->row, col), "f") == 0)
  156. db_set_string(&(value->s), "0");
  157. else
  158. G_warning(_("Unable to recognize boolean value"));
  159. break;
  160. }
  161. }
  162. G_debug(3, "Row fetched");
  163. return DB_OK;
  164. }
  165. int db__driver_get_num_rows(dbCursor * cn)
  166. {
  167. cursor *c;
  168. dbToken token;
  169. /* get cursor token */
  170. token = db_get_cursor_token(cn);
  171. /* get the cursor by its token */
  172. if (!(c = (cursor *) db_find_token(token))) {
  173. db_d_append_error(_("Taken not found"));
  174. db_d_report_error();
  175. return DB_FAILED;
  176. }
  177. return (c->nrows);
  178. }