fetch.c 4.6 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
  9. db__driver_fetch (dbCursor *cn, int position, int *more)
  10. {
  11. cursor *c;
  12. dbToken token;
  13. dbTable *table;
  14. int i;
  15. /* get cursor token */
  16. token = db_get_cursor_token(cn);
  17. /* get the cursor by its token */
  18. if (!(c = (cursor *) db_find_token(token))) {
  19. append_error ("Cursor not found");
  20. report_error();
  21. return DB_FAILED;
  22. }
  23. /* fetch on position */
  24. switch (position)
  25. {
  26. case DB_NEXT:
  27. c->row++;
  28. break;
  29. case DB_CURRENT:
  30. break;
  31. case DB_PREVIOUS:
  32. c->row--;
  33. break;
  34. case DB_FIRST:
  35. c->row = 0;
  36. break;
  37. case DB_LAST:
  38. c->row = c->nrows - 1;
  39. break;
  40. };
  41. G_debug ( 3, "row = %d nrows = %d", c->row, c->nrows );
  42. if ( c->row < 0 || c->row >= c->nrows ) {
  43. *more = 0;
  44. return DB_OK;
  45. }
  46. *more = 1;
  47. /* get the data out of the descriptor into the table */
  48. table = db_get_cursor_table(cn);
  49. for (i = 0; i < c->ncols; i++) {
  50. int col, gpgtype, sqltype;
  51. dbColumn *column;
  52. dbValue *value;
  53. col = c->cols[i]; /* known cols */
  54. column = db_get_table_column (table, i);
  55. gpgtype = db_get_column_host_type(column);
  56. sqltype = db_get_column_sqltype(column);
  57. value = db_get_column_value (column);
  58. db_zero_string (&value->s);
  59. /* Is null? */
  60. if ( PQgetisnull(c->res, c->row, col ) ) {
  61. value->isNull = 1;
  62. continue;
  63. } else {
  64. value->isNull = 0;
  65. }
  66. G_debug (3, "row %d, col %d, gpgtype %d, sqltype %d: val = '%s'",
  67. c->row, col, gpgtype, sqltype, PQgetvalue(c->res, c->row, 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), &(value->t.seconds) );
  109. if ( ns != 3 ) {
  110. append_error ( "Cannot scan time:");
  111. append_error ( PQgetvalue(c->res, c->row, col) );
  112. report_error();
  113. return DB_FAILED;
  114. }
  115. value->t.year = 0;
  116. value->t.month = 0;
  117. value->t.day = 0;
  118. break;
  119. case PG_TYPE_TIMESTAMP:
  120. /* Example: '1999-01-25 04:05:06.25+01', '1999-01-25 04:05:06' */
  121. ns = sscanf( PQgetvalue(c->res, c->row, col), "%4d-%2d-%2d %2d:%2d:%lf%3d",
  122. &(value->t.year), &(value->t.month), &(value->t.day),
  123. &(value->t.hour), &(value->t.minute), &(value->t.seconds), &tz );
  124. if ( ns == 7 ) {
  125. append_error ( "Cannot scan timestamp (no idea how to process time zone):");
  126. append_error ( PQgetvalue(c->res, c->row, col) );
  127. report_error();
  128. return DB_FAILED;
  129. } else if ( ns < 6 ) {
  130. append_error ( "Cannot scan timestamp (not enough arguments):");
  131. append_error ( PQgetvalue(c->res, c->row, col) );
  132. report_error();
  133. return DB_FAILED;
  134. }
  135. break;
  136. case PG_TYPE_BOOL:
  137. if ( strcmp ( PQgetvalue(c->res, c->row, col), "t") == 0 )
  138. db_set_string ( &(value->s), "1");
  139. else if ( strcmp ( PQgetvalue(c->res, c->row, col), "f") == 0 )
  140. db_set_string ( &(value->s), "0" );
  141. else
  142. G_warning (_("Cannot recognize boolean value"));
  143. break;
  144. }
  145. }
  146. G_debug (3, "Row fetched" );
  147. return DB_OK;
  148. }
  149. int
  150. db__driver_get_num_rows (dbCursor *cn)
  151. {
  152. cursor *c;
  153. dbToken token;
  154. /* get cursor token */
  155. token = db_get_cursor_token(cn);
  156. /* get the cursor by its token */
  157. if (!(c = (cursor *) db_find_token(token))) {
  158. append_error("Cursor not found");
  159. report_error();
  160. return DB_FAILED;
  161. }
  162. return ( c->nrows );
  163. }