main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /******************************************************************************
  2. * MODULE: v.in.db
  3. *
  4. * AUTHOR(S): Radim Blazek
  5. *
  6. * PURPOSE: Create new vector from db table.
  7. *
  8. * COPYRIGHT: (C) 2000-2007, 2009 by the GRASS Development Team
  9. *
  10. * This program is free software under the GNU General Public
  11. * License (>=v2). Read the file COPYING that comes with GRASS
  12. * for details.
  13. *
  14. ******************************************************************************/
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <grass/gis.h>
  21. #include <grass/dbmi.h>
  22. #include <grass/vector.h>
  23. #include <grass/glocale.h>
  24. int main(int argc, char *argv[])
  25. {
  26. int i, cat, with_z, more, ctype, nrows;
  27. char buf[DB_SQL_MAX];
  28. int count;
  29. double coor[3];
  30. int ncoor;
  31. struct Option *driver_opt, *database_opt, *table_opt;
  32. struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt,
  33. *outvect;
  34. struct Flag *same_table_flag;
  35. struct GModule *module;
  36. struct Map_info Map;
  37. struct line_pnts *Points;
  38. struct line_cats *Cats;
  39. dbString sql;
  40. dbDriver *driver;
  41. dbCursor cursor;
  42. dbTable *table;
  43. dbColumn *column;
  44. dbValue *value;
  45. struct field_info *fi;
  46. G_gisinit(argv[0]);
  47. module = G_define_module();
  48. G_add_keyword(_("vector"));
  49. G_add_keyword(_("import"));
  50. G_add_keyword(_("database"));
  51. G_add_keyword(_("points"));
  52. module->description =
  53. _("Creates new vector (points) map from database table containing coordinates.");
  54. table_opt = G_define_standard_option(G_OPT_DB_TABLE);
  55. table_opt->required = YES;
  56. table_opt->description = _("Input table name");
  57. driver_opt = G_define_standard_option(G_OPT_DB_DRIVER);
  58. driver_opt->options = db_list_drivers();
  59. driver_opt->answer = (char *)db_get_default_driver_name();
  60. driver_opt->guisection = _("Input DB");
  61. database_opt = G_define_standard_option(G_OPT_DB_DATABASE);
  62. database_opt->answer = (char *)db_get_default_database_name();
  63. database_opt->guisection = _("Input DB");
  64. xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  65. xcol_opt->key = "x";
  66. xcol_opt->required = YES;
  67. xcol_opt->description = _("Name of column containing x coordinate");
  68. ycol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  69. ycol_opt->key = "y";
  70. ycol_opt->required = YES;
  71. ycol_opt->description = _("Name of column containing y coordinate");
  72. zcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  73. zcol_opt->key = "z";
  74. zcol_opt->description = _("Name of column containing z coordinate");
  75. zcol_opt->guisection = _("3D output");
  76. keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
  77. keycol_opt->key = "key";
  78. keycol_opt->required = NO;
  79. keycol_opt->label = _("Name of column containing category number");
  80. keycol_opt->description = _("Must refer to an integer column");
  81. where_opt = G_define_standard_option(G_OPT_DB_WHERE);
  82. where_opt->guisection = _("Selection");
  83. outvect = G_define_standard_option(G_OPT_V_OUTPUT);
  84. same_table_flag = G_define_flag();
  85. same_table_flag->key = 't';
  86. same_table_flag->description =
  87. _("Use imported table as attribute table for new map");
  88. if (G_parser(argc, argv))
  89. exit(EXIT_FAILURE);
  90. if (zcol_opt->answer) {
  91. with_z = WITH_Z;
  92. ncoor = 3;
  93. }
  94. else {
  95. with_z = WITHOUT_Z;
  96. ncoor = 2;
  97. }
  98. Points = Vect_new_line_struct();
  99. Cats = Vect_new_cats_struct();
  100. db_init_string(&sql);
  101. if (G_get_overwrite()) {
  102. /* We don't want to delete the input table when overwriting the output
  103. * vector. */
  104. char name[GNAME_MAX], mapset[GMAPSET_MAX];
  105. if (!G_name_is_fully_qualified(outvect->answer, name, mapset)) {
  106. strcpy(name, outvect->answer);
  107. strcpy(mapset, G_mapset());
  108. }
  109. Vect_set_open_level(1); /* no topo needed */
  110. if (strcmp(mapset, G_mapset()) == 0 && G_find_vector2(name, mapset) &&
  111. Vect_open_old(&Map, name, mapset) >= 0) {
  112. int num_dblinks;
  113. num_dblinks = Vect_get_num_dblinks(&Map);
  114. for (i = 0; i < num_dblinks; i++) {
  115. if ((fi = Vect_get_dblink(&Map, i)) != NULL &&
  116. strcmp(fi->driver, driver_opt->answer) == 0 &&
  117. strcmp(fi->database, database_opt->answer) == 0 &&
  118. strcmp(fi->table, table_opt->answer) == 0)
  119. G_fatal_error(_("Vector map <%s> cannot be overwritten "
  120. "because input table <%s> is linked to "
  121. "this map."),
  122. outvect->answer, table_opt->answer);
  123. }
  124. Vect_close(&Map);
  125. }
  126. }
  127. if (Vect_open_new(&Map, outvect->answer, with_z) < 0)
  128. G_fatal_error(_("Unable to create vector map <%s>"),
  129. outvect->answer);
  130. Vect_set_error_handler_io(NULL, &Map);
  131. Vect_hist_command(&Map);
  132. fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE);
  133. /* Open driver */
  134. driver = db_start_driver_open_database(driver_opt->answer,
  135. database_opt->answer);
  136. if (driver == NULL) {
  137. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  138. fi->database, fi->driver);
  139. }
  140. db_set_error_handler_driver(driver);
  141. /* check if target table already exists */
  142. G_debug(3, "Output vector table <%s>, driver: <%s>, database: <%s>",
  143. outvect->answer, db_get_default_driver_name(),
  144. db_get_default_database_name());
  145. if (!same_table_flag->answer &&
  146. db_table_exists(db_get_default_driver_name(),
  147. db_get_default_database_name(), outvect->answer) == 1)
  148. G_fatal_error(_("Output vector map, table <%s> (driver: <%s>, database: <%s>) "
  149. "already exists"), outvect->answer,
  150. db_get_default_driver_name(),
  151. db_get_default_database_name());
  152. if (keycol_opt->answer) {
  153. int coltype;
  154. coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer);
  155. if (coltype == -1)
  156. G_fatal_error(_("Column <%s> not found in table <%s>"),
  157. keycol_opt->answer, table_opt->answer);
  158. if (coltype != DB_C_TYPE_INT)
  159. G_fatal_error(_("Data type of key column must be integer"));
  160. }
  161. else {
  162. if (same_table_flag->answer) {
  163. G_fatal_error(_("Option <%s> must be specified when -%c flag is given"),
  164. keycol_opt->key, same_table_flag->key);
  165. }
  166. if (strcmp(db_get_default_driver_name(), "sqlite") != 0)
  167. G_fatal_error(_("Unable to define key column. This operation is not supported "
  168. "by <%s> driver. You need to define <%s> option."),
  169. fi->driver, keycol_opt->key);
  170. }
  171. /* Open select cursor */
  172. sprintf(buf, "SELECT %s, %s", xcol_opt->answer, ycol_opt->answer);
  173. db_set_string(&sql, buf);
  174. if (with_z) {
  175. sprintf(buf, ", %s", zcol_opt->answer);
  176. db_append_string(&sql, buf);
  177. }
  178. if (keycol_opt->answer) {
  179. sprintf(buf, ", %s", keycol_opt->answer);
  180. db_append_string(&sql, buf);
  181. }
  182. sprintf(buf, " FROM %s", table_opt->answer);
  183. db_append_string(&sql, buf);
  184. if (where_opt->answer) {
  185. sprintf(buf, " WHERE %s", where_opt->answer);
  186. db_append_string(&sql, buf);
  187. }
  188. G_debug(2, "SQL: %s", db_get_string(&sql));
  189. if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
  190. G_fatal_error(_("Unable to open select cursor: '%s'"),
  191. db_get_string(&sql));
  192. }
  193. table = db_get_cursor_table(&cursor);
  194. nrows = db_get_num_rows(&cursor);
  195. G_debug(2, "%d points selected", nrows);
  196. count = cat = 0;
  197. G_message(_("Writing features..."));
  198. while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
  199. G_percent(count, nrows, 2);
  200. /* key column */
  201. if (keycol_opt->answer) {
  202. column = db_get_table_column(table, with_z ? 3 : 2);
  203. ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
  204. if (ctype != DB_C_TYPE_INT)
  205. G_fatal_error(_("Key column must be integer"));
  206. value = db_get_column_value(column);
  207. cat = db_get_value_int(value);
  208. }
  209. else {
  210. cat++;
  211. }
  212. /* coordinates */
  213. for (i = 0; i < ncoor; i++) {
  214. column = db_get_table_column(table, i);
  215. ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
  216. if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
  217. G_fatal_error(_("x/y/z column must be integer or double"));
  218. value = db_get_column_value(column);
  219. if (ctype == DB_C_TYPE_INT)
  220. coor[i] = (double)db_get_value_int(value);
  221. else
  222. coor[i] = db_get_value_double(value);
  223. }
  224. Vect_reset_line(Points);
  225. Vect_reset_cats(Cats);
  226. Vect_append_point(Points, coor[0], coor[1], coor[2]);
  227. Vect_cat_set(Cats, 1, cat);
  228. Vect_write_line(&Map, GV_POINT, Points, Cats);
  229. count++;
  230. }
  231. G_percent(1, 1, 1);
  232. /* close connection to input DB before copying attributes */
  233. db_close_database_shutdown_driver(driver);
  234. /* Copy table */
  235. if (!same_table_flag->answer) {
  236. G_message(_("Copying attributes..."));
  237. if (DB_FAILED == db_copy_table_where(driver_opt->answer, database_opt->answer,
  238. table_opt->answer,
  239. fi->driver, fi->database, fi->table,
  240. where_opt->answer)) { /* where can be NULL */
  241. G_warning(_("Unable to copy table"));
  242. }
  243. else {
  244. Vect_map_add_dblink(&Map, 1, NULL, fi->table,
  245. keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
  246. fi->database, fi->driver);
  247. }
  248. if (!keycol_opt->answer) {
  249. /* TODO: implement for all DB drivers in generic way if
  250. * possible */
  251. driver = db_start_driver_open_database(fi->driver, fi->database);
  252. if (driver == NULL) {
  253. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  254. fi->database, fi->driver);
  255. }
  256. db_set_error_handler_driver(driver);
  257. /* add key column */
  258. sprintf(buf, "ALTER TABLE %s ADD COLUMN %s INTEGER",
  259. fi->table, GV_KEY_COLUMN);
  260. db_set_string(&sql, buf);
  261. if (db_execute_immediate(driver, &sql) != DB_OK) {
  262. G_fatal_error(_("Unable to add key column <%s>: "
  263. "SERIAL type is not supported by <%s>"),
  264. GV_KEY_COLUMN, fi->driver);
  265. }
  266. /* update key column */
  267. sprintf(buf, "UPDATE %s SET %s = _ROWID_",
  268. fi->table, GV_KEY_COLUMN);
  269. db_set_string(&sql, buf);
  270. if (db_execute_immediate(driver, &sql) != DB_OK) {
  271. G_fatal_error(_("Failed to update key column <%s>"),
  272. GV_KEY_COLUMN);
  273. }
  274. }
  275. }
  276. else {
  277. /* do not copy attributes, link original table */
  278. Vect_map_add_dblink(&Map, 1, NULL, table_opt->answer,
  279. keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
  280. database_opt->answer, driver_opt->answer);
  281. }
  282. Vect_build(&Map);
  283. Vect_close(&Map);
  284. G_done_msg(n_("%d point written to vector map.",
  285. "%d points written to vector map.",
  286. count), count);
  287. return (EXIT_SUCCESS);
  288. }