fetch.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /**
  2. * \file fetch.c
  3. *
  4. * \brief Low level SQLite database functions.
  5. *
  6. * This program is free software under the GNU General Public License
  7. * (>=v2). Read the file COPYING that comes with GRASS for details.
  8. *
  9. * \author Radim Blazek
  10. *
  11. * \date 2005-2007
  12. */
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <grass/dbmi.h>
  16. #include <grass/glocale.h>
  17. #include "globals.h"
  18. #include "proto.h"
  19. /**
  20. * \fn int db__driver_fetch (dbCursor *cn, int position, int *more)
  21. *
  22. * \brief Low level SQLite database table record fetch.
  23. *
  24. * NOTE: <b>position</b> is one of:
  25. * DB_NEXT, DB_FIRST, DB_CURRENT, DB_PREVIOUS, DB_LAST.
  26. *
  27. * \param[in] cn open database cursor
  28. * \param[in] position database position. See NOTE.
  29. * \param[in,out] more 1 = more data; 0 = no more data
  30. * \return int
  31. */
  32. int
  33. db__driver_fetch (dbCursor *cn, int position, int *more)
  34. {
  35. cursor *c;
  36. dbToken token;
  37. dbTable *table;
  38. int i, ret;
  39. int ns;
  40. /* get cursor token */
  41. token = db_get_cursor_token(cn);
  42. /* get the cursor by its token */
  43. if (!(c = (cursor *) db_find_token(token))) {
  44. append_error ("Cursor not found");
  45. report_error();
  46. return DB_FAILED;
  47. }
  48. G_debug ( 3, "fetch row = %d", c->row );
  49. /* fetch on position */
  50. switch (position)
  51. {
  52. case DB_NEXT:
  53. case DB_FIRST:
  54. if ( position == DB_FIRST )
  55. c->row = -1;
  56. ret = sqlite3_step ( c->statement );
  57. if ( ret != SQLITE_ROW )
  58. {
  59. if ( ret != SQLITE_DONE )
  60. {
  61. append_error ("Cannot step:\n");
  62. append_error ((char *) sqlite3_errmsg (sqlite));
  63. report_error();
  64. return DB_FAILED;
  65. }
  66. sqlite3_reset ( c->statement );
  67. *more = 0;
  68. return DB_OK;
  69. }
  70. c->row++;
  71. break;
  72. case DB_CURRENT:
  73. break;
  74. case DB_PREVIOUS:
  75. append_error ("DB_PREVIOUS is not supported");
  76. report_error();
  77. return DB_FAILED;
  78. break;
  79. case DB_LAST:
  80. append_error ("DB_LAST is not supported");
  81. report_error();
  82. return DB_FAILED;
  83. break;
  84. };
  85. *more = 1;
  86. /* get the data out of the descriptor into the table */
  87. table = db_get_cursor_table(cn);
  88. for (i = 0; i < c->nkcols; i++)
  89. {
  90. int col, litetype, sqltype;
  91. dbColumn *column;
  92. dbValue *value;
  93. const char *text;
  94. dbDateTime *dt;
  95. col = c->kcols[i]; /* known cols */
  96. column = db_get_table_column (table, i);
  97. sqltype = db_get_column_sqltype(column);
  98. /* fails for dates:
  99. litetype = db_get_column_host_type(column);
  100. */
  101. litetype = sqlite3_column_type ( c->statement, col );
  102. text = (const char *) sqlite3_column_text ( c->statement, col);
  103. value = db_get_column_value (column);
  104. db_zero_string (&value->s);
  105. /* Is null? */
  106. if ( sqlite3_column_type(c->statement, col) == SQLITE_NULL ) {
  107. value->isNull = 1;
  108. continue;
  109. } else {
  110. value->isNull = 0;
  111. }
  112. G_debug (3, "col %d, litetype %d, sqltype %d: val = '%s'",
  113. col, litetype, sqltype, text );
  114. /* http://www.sqlite.org/capi3ref.html#sqlite3_column_type
  115. SQLITE_INTEGER 1
  116. SQLITE_FLOAT 2
  117. SQLITE_TEXT 3
  118. SQLITE_BLOB 4
  119. SQLITE_NULL 5
  120. lib/db/dbmi_base/sqltype.c defines:
  121. DB_SQL_TYPE_*
  122. */
  123. /* Note: we have set DATESTYLE TO ISO in db_driver_open_select_cursor() so datetime
  124. * format should be ISO */
  125. switch ( sqltype ) {
  126. case DB_SQL_TYPE_INTEGER:
  127. case DB_SQL_TYPE_SMALLINT:
  128. case DB_SQL_TYPE_SERIAL:
  129. value->i = sqlite3_column_int ( c->statement, col);
  130. break;
  131. case DB_SQL_TYPE_REAL:
  132. case DB_SQL_TYPE_DOUBLE_PRECISION:
  133. value->d = sqlite3_column_double ( c->statement, col);
  134. break;
  135. case DB_SQL_TYPE_DATE:
  136. dt = &value->t;
  137. dt->hour = 0;
  138. dt->minute = 0;
  139. dt->seconds = 0.0;
  140. G_debug(3, "sqlite fetched date: %s", text);
  141. ns = sscanf(text, "%4d-%2d-%2d",
  142. &dt->year, &dt->month, &dt->day);
  143. if ( ns != 3 ) {
  144. append_error ( "Cannot scan date:");
  145. append_error (text);
  146. report_error();
  147. return DB_FAILED;
  148. }
  149. break;
  150. case DB_SQL_TYPE_TIME:
  151. dt = &value->t;
  152. dt->year = 0;
  153. dt->month = 0;
  154. dt->day = 0;
  155. G_debug(3, "sqlite fetched date: %s", text);
  156. ns = sscanf(text, "%2d:%2d:%lf",
  157. &dt->hour, &dt->minute, &dt->seconds);
  158. if ( ns != 3 ) {
  159. append_error ( "Cannot scan time:");
  160. append_error (text);
  161. report_error();
  162. return DB_FAILED;
  163. }
  164. break;
  165. case DB_SQL_TYPE_TIMESTAMP:
  166. dt = &value->t;
  167. G_debug(3, "sqlite fetched timestamp: %s", text);
  168. ns = sscanf(text, "%4d-%2d-%2d %2d:%2d:%lf",
  169. &dt->year, &dt->month, &dt->day,
  170. &dt->hour, &dt->minute, &dt->seconds);
  171. if ( ns != 6 ) {
  172. append_error ( "Cannot scan timestamp:");
  173. append_error (text);
  174. report_error();
  175. return DB_FAILED;
  176. }
  177. break;
  178. case DB_SQL_TYPE_INTERVAL:
  179. dt = &value->t;
  180. dt->year = 0;
  181. dt->month = 0;
  182. dt->day = 0;
  183. dt->hour = 0;
  184. dt->minute = 0;
  185. G_debug(3, "sqlite fetched interval: %s", text);
  186. G_warning("SQLite driver: parsing of interval values not implemented; assuming seconds");
  187. ns = sscanf(text, "%lf", &dt->seconds);
  188. if ( ns != 1 ) {
  189. append_error ( "Cannot scan interval:");
  190. append_error (text);
  191. report_error();
  192. return DB_FAILED;
  193. }
  194. break;
  195. case DB_SQL_TYPE_DECIMAL:
  196. case DB_SQL_TYPE_NUMERIC:
  197. case DB_SQL_TYPE_CHARACTER:
  198. case DB_SQL_TYPE_TEXT:
  199. db_set_string ( &value->s, text);
  200. break;
  201. }
  202. }
  203. G_debug (3, "Row fetched" );
  204. return DB_OK;
  205. }
  206. /**
  207. * \fn int db__driver_get_num_rows (dbCursor *cn)
  208. *
  209. * \brief Gets number of rows in SQLite database table.
  210. *
  211. * \param[in] cn open database cursor
  212. * \return int number of rows in table
  213. */
  214. int
  215. db__driver_get_num_rows (dbCursor *cn)
  216. {
  217. cursor *c;
  218. dbToken token;
  219. int row;
  220. /* get cursor token */
  221. token = db_get_cursor_token(cn);
  222. /* get the cursor by its token */
  223. if (!(c = (cursor *) db_find_token(token))) {
  224. append_error("Cursor not found");
  225. report_error();
  226. return DB_FAILED;
  227. }
  228. if ( c->nrows > -1 )
  229. {
  230. return ( c->nrows );
  231. }
  232. sqlite3_reset ( c->statement );
  233. c->nrows = 0;
  234. while ( sqlite3_step ( c->statement ) == SQLITE_ROW )
  235. {
  236. c->nrows++;
  237. }
  238. sqlite3_reset ( c->statement );
  239. /* Reset cursor position */
  240. row = -1;
  241. if ( c->row > -1 )
  242. {
  243. while ( sqlite3_step ( c->statement ) == SQLITE_ROW )
  244. {
  245. if ( row == c->row )
  246. break;
  247. row++;
  248. }
  249. }
  250. return ( c->nrows );
  251. }