fetch.c 4.4 KB

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