map.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /*!
  2. * \file lib/vector/Vlib/map.c
  3. *
  4. * \brief Vector library - Manipulate with vector map
  5. *
  6. * Higher level functions for reading/writing/manipulating vectors.
  7. *
  8. * (C) 2001-2009 by the GRASS Development Team
  9. *
  10. * This program is free software under the GNU General Public License
  11. * (>=v2). Read the file COPYING that comes with GRASS for details.
  12. *
  13. * \author Original author CERL, probably Dave Gerdes or Mike
  14. * Higgins.
  15. * \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
  16. */
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <dirent.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <fcntl.h>
  25. #include <grass/glocale.h>
  26. #include <grass/vector.h>
  27. #include <grass/dbmi.h>
  28. #include <grass/glocale.h>
  29. /*!
  30. \brief Copy all alive vector features of opened vector map to
  31. another opened vector map
  32. \param In input vector map
  33. \param[out] Out output vector map
  34. \return 0 on success
  35. \return 1 on error
  36. */
  37. int Vect_copy_map_lines(struct Map_info *In, struct Map_info *Out)
  38. {
  39. return Vect_copy_map_lines_field(In, -1, Out);
  40. }
  41. /*!
  42. \brief Copy all alive vector features from given layer of opened
  43. vector map to another opened vector map
  44. Note: Try to copy on level 2 otherwise level 1 is used.
  45. \param In input vector map
  46. \param field layer number (-1 for all layers)
  47. \param[out] Out output vector map
  48. \return 0 on success
  49. \return 1 on error
  50. */
  51. int Vect_copy_map_lines_field(struct Map_info *In, int field,
  52. struct Map_info *Out)
  53. {
  54. int i, type, nlines, ret, left, rite, centroid, ogr;
  55. struct line_pnts *Points, *CPoints;
  56. struct line_cats *Cats, *CCats;
  57. Points = Vect_new_line_struct();
  58. CPoints = Vect_new_line_struct();
  59. Cats = Vect_new_cats_struct();
  60. CCats = Vect_new_cats_struct();
  61. if (Vect_level(In) < 1)
  62. G_fatal_error("Vect_copy_map_lines(): %s",
  63. _("input vector map is not open"));
  64. ogr = Vect_maptype(Out) == GV_FORMAT_OGR_DIRECT;
  65. ret = 0;
  66. /* Note: sometimes is important to copy on level 2 (pseudotopo centroids)
  67. * and sometimes on level 1 if build take too long time */
  68. if (Vect_level(In) >= 2) {
  69. nlines = Vect_get_num_lines(In);
  70. for (i = 1; i <= nlines; i++) {
  71. if (!Vect_line_alive(In, i))
  72. continue;
  73. type = Vect_read_line(In, Points, Cats, i);
  74. if (type == -1) {
  75. G_warning(_("Unable to read vector map <%s>"),
  76. Vect_get_full_name(In));
  77. ret = 1;
  78. break;
  79. }
  80. if (type == 0)
  81. continue; /* dead line */
  82. if (ogr && (type == GV_CENTROID || type == GV_BOUNDARY))
  83. /* OGR layers: centroids are stored in topo */
  84. /* polygon defined by areas (topo required) */
  85. continue;
  86. /* don't skips boundaries if field != -1 */
  87. if (field != -1) {
  88. if (type & GV_BOUNDARY) {
  89. if (Vect_cat_get(Cats, field, NULL) == 0) {
  90. int skip_bndry = 1;
  91. Vect_get_line_areas(In, i, &left, &rite);
  92. if (left < 0)
  93. left = Vect_get_isle_area(In, abs(left));
  94. if (left > 0) {
  95. if ((centroid =
  96. Vect_get_area_centroid(In, left)) > 0) {
  97. Vect_read_line(In, CPoints, CCats, centroid);
  98. if (Vect_cat_get(CCats, field, NULL) != 0)
  99. skip_bndry = 0;
  100. }
  101. }
  102. if (skip_bndry) {
  103. if (rite < 0)
  104. rite = Vect_get_isle_area(In, abs(rite));
  105. if (rite > 0) {
  106. if ((centroid =
  107. Vect_get_area_centroid(In, rite)) > 0) {
  108. Vect_read_line(In, CPoints, CCats,
  109. centroid);
  110. if (Vect_cat_get(CCats, field, NULL) != 0)
  111. skip_bndry = 0;
  112. }
  113. }
  114. }
  115. if (skip_bndry)
  116. continue;
  117. }
  118. }
  119. else if (Vect_cat_get(Cats, field, NULL) == 0)
  120. continue; /* different layer */
  121. }
  122. Vect_write_line(Out, type, Points, Cats);
  123. }
  124. if (ogr) {
  125. int area, nareas;
  126. /* copy areas/polygons */
  127. nareas = Vect_get_num_areas(In);
  128. for (area = 1; area <= nareas; area++) {
  129. G_debug(3, "area = %d", area);
  130. Vect_get_area_points(In, area, Points);
  131. centroid = Vect_get_area_centroid(In, area);
  132. if (centroid > 0)
  133. Vect_read_line(In, NULL, CCats, centroid);
  134. else
  135. Vect_reset_cats(CCats);
  136. Vect_write_line(Out, GV_BOUNDARY, Points, CCats);
  137. }
  138. }
  139. }
  140. else {
  141. /* Level 1 */
  142. if (ogr)
  143. G_warning(_("Topology not available. Polygons will be skipped."));
  144. Vect_rewind(In);
  145. while (TRUE) {
  146. type = Vect_read_next_line(In, Points, Cats);
  147. if (type == -1) {
  148. G_warning(_("Unable to read vector map <%s>"),
  149. Vect_get_full_name(In));
  150. ret = 1;
  151. break;
  152. }
  153. else if (type == -2) { /* EOF */
  154. break;
  155. }
  156. else if (type == 0) { /* dead line */
  157. continue;
  158. }
  159. /* don't skip boundaries if field != -1 */
  160. if (field != -1 && !(type & GV_BOUNDARY) &&
  161. Vect_cat_get(Cats, field, NULL) == 0)
  162. continue; /* different layer */
  163. Vect_write_line(Out, type, Points, Cats);
  164. }
  165. }
  166. Vect_destroy_line_struct(Points);
  167. Vect_destroy_line_struct(CPoints);
  168. Vect_destroy_cats_struct(Cats);
  169. Vect_destroy_cats_struct(CCats);
  170. return ret;
  171. }
  172. /*
  173. \brief Copy file
  174. \param src source file
  175. \param[out] dst destination file
  176. \return 0 OK
  177. \return 1 error
  178. */
  179. static int copy_file(const char *src, const char *dst)
  180. {
  181. char buf[1024];
  182. int fd, fd2;
  183. FILE *f2;
  184. int len, len2;
  185. if ((fd = open(src, O_RDONLY)) < 0)
  186. return 1;
  187. /* if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY)) < 0) { */
  188. if ((f2 = fopen(dst, "w")) == NULL) {
  189. close(fd);
  190. return 1;
  191. }
  192. fd2 = fileno(f2);
  193. while ((len = read(fd, buf, 1024)) > 0) {
  194. while (len && (len2 = write(fd2, buf, len)) >= 0)
  195. len -= len2;
  196. }
  197. close(fd);
  198. /* close(fd2); */
  199. fclose(f2);
  200. if (len == -1 || len2 == -1)
  201. return 1;
  202. return 0;
  203. }
  204. /*!
  205. \brief Copy a map including attribute tables
  206. Old vector is deleted
  207. \param in input vector map name
  208. \param mapset mapset name
  209. \param out output vector map name
  210. \return -1 error
  211. \return 0 success
  212. */
  213. int Vect_copy(const char *in, const char *mapset, const char *out)
  214. {
  215. int i, n, ret, type;
  216. struct Map_info In, Out;
  217. struct field_info *Fi, *Fin;
  218. char old_path[GPATH_MAX], new_path[GPATH_MAX], buf[GPATH_MAX];
  219. const char *files[] = { GV_FRMT_ELEMENT, GV_COOR_ELEMENT,
  220. GV_HEAD_ELEMENT, GV_HIST_ELEMENT,
  221. GV_TOPO_ELEMENT, GV_SIDX_ELEMENT, GV_CIDX_ELEMENT,
  222. NULL
  223. };
  224. const char *inmapset;
  225. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  226. dbDriver *driver;
  227. G_debug(2, "Copy vector '%s' in '%s' to '%s'", in, mapset, out);
  228. /* check for [A-Za-z][A-Za-z0-9_]* in name */
  229. if (Vect_legal_filename(out) < 0)
  230. G_fatal_error(_("Vector map name is not SQL compliant"));
  231. inmapset = G_find_vector2(in, mapset);
  232. if (!inmapset) {
  233. G_warning(_("Unable to find vector map <%s> in <%s>"), in, mapset);
  234. return -1;
  235. }
  236. mapset = inmapset;
  237. /* remove mapset from fully qualified name, confuses G_file_name() */
  238. if (G_name_is_fully_qualified(in, xname, xmapset)) {
  239. in = xname;
  240. }
  241. /* Delete old vector if it exists */
  242. if (G_find_vector2(out, G_mapset())) {
  243. G_warning(_("Vector map <%s> already exists and will be overwritten"),
  244. out);
  245. ret = Vect_delete(out);
  246. if (ret != 0) {
  247. G_warning(_("Unable to delete vector map <%s>"), out);
  248. return -1;
  249. }
  250. }
  251. /* Copy the directory */
  252. G__make_mapset_element(GV_DIRECTORY);
  253. sprintf(buf, "%s/%s", GV_DIRECTORY, out);
  254. G__make_mapset_element(buf);
  255. i = 0;
  256. while (files[i]) {
  257. sprintf(buf, "%s/%s", in, files[i]);
  258. G_file_name(old_path, GV_DIRECTORY, buf, mapset);
  259. sprintf(buf, "%s/%s", out, files[i]);
  260. G_file_name(new_path, GV_DIRECTORY, buf, G_mapset());
  261. if (access(old_path, F_OK) == 0) { /* file exists? */
  262. G_debug(2, "copy %s to %s", old_path, new_path);
  263. if (copy_file(old_path, new_path)) {
  264. G_warning(_("Unable to copy vector map <%s> to <%s>"),
  265. old_path, new_path);
  266. }
  267. }
  268. i++;
  269. }
  270. G_file_name(old_path, GV_DIRECTORY, in, mapset);
  271. G_file_name(new_path, GV_DIRECTORY, out, G_mapset());
  272. /* Open input */
  273. Vect_set_open_level(1);
  274. Vect_open_old_head(&In, in, mapset);
  275. if (In.format != GV_FORMAT_NATIVE) { /* Done */
  276. Vect_close(&In);
  277. return 0;
  278. }
  279. /* Open output */
  280. Vect_set_open_level(1);
  281. Vect_open_update_head(&Out, out, G_mapset());
  282. /* Copy tables */
  283. n = Vect_get_num_dblinks(&In);
  284. type = GV_1TABLE;
  285. if (n > 1)
  286. type = GV_MTABLE;
  287. for (i = 0; i < n; i++) {
  288. Fi = Vect_get_dblink(&In, i);
  289. if (Fi == NULL) {
  290. G_warning(_("Database connection not defined for layer %d"),
  291. In.dblnk->field[i].number);
  292. Vect_close(&In);
  293. Vect_close(&Out);
  294. return -1;
  295. }
  296. Fin = Vect_default_field_info(&Out, Fi->number, Fi->name, type);
  297. G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  298. Fi->driver, Fi->database, Fi->table, Fin->driver,
  299. Fin->database, Fin->table);
  300. Vect_map_add_dblink(&Out, Fi->number, Fi->name, Fin->table, Fi->key,
  301. Fin->database, Fin->driver);
  302. ret = db_copy_table(Fi->driver, Fi->database, Fi->table,
  303. Fin->driver, Vect_subst_var(Fin->database, &Out),
  304. Fin->table);
  305. if (ret == DB_FAILED) {
  306. G_warning(_("Unable to copy table <%s>"), Fin->table);
  307. Vect_close(&In);
  308. Vect_close(&Out);
  309. return -1;
  310. }
  311. driver =
  312. db_start_driver_open_database(Fin->driver,
  313. Vect_subst_var(Fin->database,
  314. &Out));
  315. if (driver == NULL) {
  316. G_warning(_("Unable to open database <%s> by driver <%s>"),
  317. Fin->database, Fin->driver);
  318. }
  319. else {
  320. if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK)
  321. G_warning(_("Unable to create index for table <%s>, key <%s>"),
  322. Fi->table, Fi->key);
  323. db_close_database_shutdown_driver(driver);
  324. }
  325. }
  326. Vect_close(&In);
  327. Vect_close(&Out);
  328. return 0;
  329. }
  330. /*!
  331. \brief Rename a map.
  332. Attribute tables are created in the same database where input tables were stored.
  333. The original format (native/OGR) is used.
  334. Old map ('out') is deleted!!!
  335. \param in input vector map name
  336. \param out output vector map name
  337. \return -1 error
  338. \return 0 success
  339. */
  340. int Vect_rename(const char *in, const char *out)
  341. {
  342. int i, n, ret, type;
  343. struct Map_info Map;
  344. struct field_info *Fin, *Fout;
  345. int *fields;
  346. dbDriver *driver;
  347. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  348. G_debug(2, "Rename vector '%s' to '%s'", in, out);
  349. /* check for [A-Za-z][A-Za-z0-9_]* in name */
  350. if (Vect_legal_filename(out) < 0)
  351. G_fatal_error(_("Vector map name is not SQL compliant"));
  352. /* Delete old vector if it exists */
  353. if (G_find_vector2(out, G_mapset())) {
  354. G_warning(_("Vector map <%s> already exists and will be overwritten"),
  355. out);
  356. Vect_delete(out);
  357. }
  358. /* remove mapset from fully qualified name */
  359. if (G_name_is_fully_qualified(in, xname, xmapset)) {
  360. in = xname;
  361. }
  362. /* Move the directory */
  363. ret = G_rename(GV_DIRECTORY, in, out);
  364. if (ret == 0) {
  365. G_warning(_("Vector map <%s> not found"), in);
  366. return -1;
  367. }
  368. else if (ret == -1) {
  369. G_warning(_("Unable to copy vector map <%s> to <%s>"), in, out);
  370. return -1;
  371. }
  372. /* Rename all tables if the format is native */
  373. Vect_set_open_level(1);
  374. Vect_open_update_head(&Map, out, G_mapset());
  375. if (Map.format != GV_FORMAT_NATIVE) { /* Done */
  376. Vect_close(&Map);
  377. return 0;
  378. }
  379. /* Copy tables */
  380. n = Vect_get_num_dblinks(&Map);
  381. type = GV_1TABLE;
  382. if (n > 1)
  383. type = GV_MTABLE;
  384. /* Make the list of fields */
  385. fields = (int *)G_malloc(n * sizeof(int));
  386. for (i = 0; i < n; i++) {
  387. Fin = Vect_get_dblink(&Map, i);
  388. fields[i] = Fin->number;
  389. }
  390. for (i = 0; i < n; i++) {
  391. G_debug(3, "field[%d] = %d", i, fields[i]);
  392. Fin = Vect_get_field(&Map, fields[i]);
  393. if (Fin == NULL) {
  394. G_warning(_("Database connection not defined for layer %d"),
  395. fields[i]);
  396. Vect_close(&Map);
  397. return -1;
  398. }
  399. Fout = Vect_default_field_info(&Map, Fin->number, Fin->name, type);
  400. G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  401. Fin->driver, Fin->database, Fin->table, Fout->driver,
  402. Fout->database, Fout->table);
  403. /* TODO: db_rename_table instead of db_copy_table */
  404. ret = db_copy_table(Fin->driver, Fin->database, Fin->table,
  405. Fout->driver, Vect_subst_var(Fout->database,
  406. &Map), Fout->table);
  407. if (ret == DB_FAILED) {
  408. G_warning(_("Unable to copy table <%s>"), Fin->table);
  409. Vect_close(&Map);
  410. return -1;
  411. }
  412. /* Change the link */
  413. Vect_map_del_dblink(&Map, Fin->number);
  414. Vect_map_add_dblink(&Map, Fout->number, Fout->name, Fout->table,
  415. Fin->key, Fout->database, Fout->driver);
  416. /* Delete old table */
  417. ret = db_delete_table(Fin->driver, Fin->database, Fin->table);
  418. if (ret == DB_FAILED) {
  419. G_warning(_("Unable to delete table <%s>"), Fin->table);
  420. Vect_close(&Map);
  421. return -1;
  422. }
  423. driver =
  424. db_start_driver_open_database(Fout->driver,
  425. Vect_subst_var(Fout->database,
  426. &Map));
  427. if (driver == NULL) {
  428. G_warning(_("Unable to open database <%s> by driver <%s>"),
  429. Fout->database, Fout->driver);
  430. }
  431. else {
  432. if (db_create_index2(driver, Fout->table, Fin->key) != DB_OK)
  433. G_warning(_("Unable to create index for table <%s>, key <%s>"),
  434. Fout->table, Fout->key);
  435. db_close_database_shutdown_driver(driver);
  436. }
  437. }
  438. Vect_close(&Map);
  439. free(fields);
  440. return 0;
  441. }
  442. /*!
  443. \brief Delete vector map including attribute tables
  444. \param map vector map name
  445. \return -1 error
  446. \return 0 success
  447. */
  448. int Vect_delete(const char *map)
  449. {
  450. int i, n, ret;
  451. struct Map_info Map;
  452. struct field_info *Fi;
  453. char buf[GPATH_MAX];
  454. DIR *dir;
  455. struct dirent *ent;
  456. const char *tmp;
  457. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  458. G_debug(3, "Delete vector '%s'", map);
  459. /* remove mapset from fully qualified name */
  460. if (G_name_is_fully_qualified(map, xname, xmapset)) {
  461. map = xname;
  462. }
  463. if (map == NULL || strlen(map) == 0) {
  464. G_warning(_("Invalid vector map name <%s>"), map ? map : "null");
  465. return -1;
  466. }
  467. sprintf(buf, "%s/%s/%s/%s/%s/%s", G_gisdbase(), G_location(),
  468. G_mapset(), GV_DIRECTORY, map, GV_DBLN_ELEMENT);
  469. G_debug(1, "dbln file: %s", buf);
  470. if (access(buf, F_OK) == 0) {
  471. /* Open input */
  472. Vect_set_open_level(1); /* Topo not needed */
  473. ret = Vect_open_old_head(&Map, map, G_mapset());
  474. if (ret < 1) {
  475. G_warning(_("Unable to open header file for vector map <%s>"),
  476. map);
  477. return -1;
  478. }
  479. /* Delete all tables, NOT external (OGR) */
  480. if (Map.format == GV_FORMAT_NATIVE) {
  481. n = Vect_get_num_dblinks(&Map);
  482. for (i = 0; i < n; i++) {
  483. Fi = Vect_get_dblink(&Map, i);
  484. if (Fi == NULL) {
  485. G_warning(_("Database connection not defined for layer %d"),
  486. Map.dblnk->field[i].number);
  487. Vect_close(&Map);
  488. return -1;
  489. }
  490. G_debug(3, "Delete drv:db:table '%s:%s:%s'", Fi->driver,
  491. Fi->database, Fi->table);
  492. ret = db_table_exists(Fi->driver, Fi->database, Fi->table);
  493. if (ret == -1) {
  494. G_warning(_("Unable to find table <%s> linked to vector map <%s>"),
  495. Fi->table, map);
  496. Vect_close(&Map);
  497. return -1;
  498. }
  499. if (ret == 1) {
  500. ret =
  501. db_delete_table(Fi->driver, Fi->database, Fi->table);
  502. if (ret == DB_FAILED) {
  503. G_warning(_("Unable to delete table <%s>"),
  504. Fi->table);
  505. Vect_close(&Map);
  506. return -1;
  507. }
  508. }
  509. else {
  510. G_warning(_("Table <%s> linked to vector map <%s> does not exist"),
  511. Fi->table, map);
  512. }
  513. }
  514. }
  515. Vect_close(&Map);
  516. }
  517. /* Delete all files from vector/name directory */
  518. sprintf(buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map);
  519. G_debug(3, "opendir '%s'", buf);
  520. dir = opendir(buf);
  521. if (dir == NULL) {
  522. G_warning(_("Unable to open directory '%s'"), buf);
  523. return -1;
  524. }
  525. while ((ent = readdir(dir))) {
  526. G_debug(3, "file = '%s'", ent->d_name);
  527. if ((strcmp(ent->d_name, ".") == 0) ||
  528. (strcmp(ent->d_name, "..") == 0))
  529. continue;
  530. sprintf(buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map,
  531. ent->d_name);
  532. G_debug(3, "delete file '%s'", buf);
  533. ret = unlink(buf);
  534. if (ret == -1) {
  535. G_warning(_("Unable to delete file '%s'"), buf);
  536. closedir(dir);
  537. return -1;
  538. }
  539. }
  540. closedir(dir);
  541. /* NFS can create .nfsxxxxxxxx files for those deleted
  542. * -> we have to move the directory to ./tmp before it is deleted */
  543. sprintf(buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map);
  544. tmp = G_tempfile();
  545. G_debug(3, "rename '%s' to '%s'", buf, tmp);
  546. ret = rename(buf, tmp);
  547. if (ret == -1) {
  548. G_warning(_("Unable to rename directory '%s' to '%s'"), buf, tmp);
  549. return -1;
  550. }
  551. G_debug(3, "remove directory '%s'", tmp);
  552. /* Warning: remove() fails on Windows */
  553. ret = rmdir(tmp);
  554. if (ret == -1) {
  555. G_warning(_("Unable to remove directory '%s'"), tmp);
  556. return -1;
  557. }
  558. return 0;
  559. }
  560. /*!
  561. \brief Copy tables linked to vector map.
  562. All if field = 0, or table defined by given field if field > 0
  563. Notice, that if input map has no tables defined, it will copy
  564. nothing and return 0 (success).
  565. \param In input vector map
  566. \param[out] Out output vector map
  567. \param field layer number
  568. \return 0 on success
  569. \return -1 on error
  570. */
  571. int Vect_copy_tables(const struct Map_info *In, struct Map_info *Out,
  572. int field)
  573. {
  574. int i, n, ret, type;
  575. struct field_info *Fi, *Fin;
  576. dbDriver *driver;
  577. n = Vect_get_num_dblinks(In);
  578. G_debug(2, "Vect_copy_tables(): copying %d tables", n);
  579. type = GV_1TABLE;
  580. if (n > 1)
  581. type = GV_MTABLE;
  582. for (i = 0; i < n; i++) {
  583. Fi = Vect_get_dblink(In, i);
  584. if (Fi == NULL) {
  585. G_warning(_("Database connection not defined for layer %d"),
  586. In->dblnk->field[i].number);
  587. return -1;
  588. }
  589. if (field > 0 && Fi->number != field)
  590. continue;
  591. Fin = Vect_default_field_info(Out, Fi->number, Fi->name, type);
  592. G_debug(2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  593. Fi->driver, Fi->database, Fi->table, Fin->driver,
  594. Fin->database, Fin->table);
  595. ret =
  596. Vect_map_add_dblink(Out, Fi->number, Fi->name, Fin->table,
  597. Fi->key, Fin->database, Fin->driver);
  598. if (ret == -1) {
  599. G_warning(_("Unable to add database link for vector map <%s>"),
  600. Out->name);
  601. return -1;
  602. }
  603. ret = db_copy_table(Fi->driver, Fi->database, Fi->table,
  604. Fin->driver, Vect_subst_var(Fin->database, Out),
  605. Fin->table);
  606. if (ret == DB_FAILED) {
  607. G_warning(_("Unable to copy table <%s>"), Fin->table);
  608. return -1;
  609. }
  610. driver =
  611. db_start_driver_open_database(Fin->driver,
  612. Vect_subst_var(Fin->database, Out));
  613. if (driver == NULL) {
  614. G_warning(_("Unable to open database <%s> by driver <%s>"),
  615. Fin->database, Fin->driver);
  616. }
  617. else {
  618. if (db_create_index2(driver, Fin->table, Fi->key) != DB_OK)
  619. G_warning(_("Unable to create index for table <%s>, key <%s>"),
  620. Fin->table, Fin->key);
  621. db_close_database_shutdown_driver(driver);
  622. }
  623. }
  624. return 0;
  625. }
  626. /*!
  627. \brief Copy table linked to vector map based on type.
  628. \param In input vector map
  629. \param[out] Out output vector map
  630. \param field_in input layer number
  631. \param field_out output layer number
  632. \param field_name layer name
  633. \param type feature type
  634. \return 0 on success
  635. \return -1 on error
  636. */
  637. int
  638. Vect_copy_table(const struct Map_info *In, struct Map_info *Out, int field_in,
  639. int field_out, const char *field_name, int type)
  640. {
  641. return Vect_copy_table_by_cats(In, Out, field_in, field_out, field_name,
  642. type, NULL, 0);
  643. }
  644. /*!
  645. \brief Copy table linked to vector map based on category numbers.
  646. \param In input vector map
  647. \param[out] Out output vector map
  648. \param field_in input layer number
  649. \param field_out output layer number
  650. \param field_name layer name
  651. \param type feature type
  652. \param cats pointer to array of cats or NULL
  653. \param ncats number of cats in 'cats'
  654. \return 0 on success
  655. \return -1 on error
  656. */
  657. int
  658. Vect_copy_table_by_cats(const struct Map_info *In, struct Map_info *Out,
  659. int field_in, int field_out, const char *field_name,
  660. int type, int *cats, int ncats)
  661. {
  662. int ret;
  663. struct field_info *Fi, *Fin;
  664. const char *name, *key;
  665. G_debug(2, "Vect_copy_table(): field_in = %d field_out = %d", field_in,
  666. field_out);
  667. Fi = Vect_get_field(In, field_in);
  668. if (Fi == NULL) {
  669. G_warning(_("Database connection not defined for layer %d"),
  670. field_in);
  671. return -1;
  672. }
  673. if (field_name != NULL)
  674. name = field_name;
  675. else
  676. name = Fi->name;
  677. Fin = Vect_default_field_info(Out, field_out, name, type);
  678. G_debug(3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  679. Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database,
  680. Fin->table);
  681. ret =
  682. Vect_map_add_dblink(Out, Fin->number, Fin->name, Fin->table, Fi->key,
  683. Fin->database, Fin->driver);
  684. if (ret == -1) {
  685. G_warning(_("Unable to add database link for vector map <%s>"),
  686. Out->name);
  687. return -1;
  688. }
  689. if (cats)
  690. key = Fi->key;
  691. else
  692. key = NULL;
  693. ret = db_copy_table_by_ints(Fi->driver, Fi->database, Fi->table,
  694. Fin->driver, Vect_subst_var(Fin->database,
  695. Out), Fin->table,
  696. key, cats, ncats);
  697. if (ret == DB_FAILED) {
  698. G_warning(_("Unable to copy table <%s>"), Fin->table);
  699. return -1;
  700. }
  701. return 0;
  702. }
  703. /*!
  704. \brief Set spatial index to be realease when vector is closed.
  705. By default, the memory occupied by spatial index is not released.
  706. \param Map vector map
  707. \return
  708. */
  709. void Vect_set_release_support(struct Map_info *Map)
  710. {
  711. Map->plus.release_support = 1;
  712. }
  713. /*!
  714. \brief By default, category index is not updated if vector is
  715. changed, this function sets category index update.
  716. WARNING: currently only category for elements is updated
  717. not for areas
  718. \param Map vector map
  719. \return
  720. */
  721. void Vect_set_category_index_update(struct Map_info *Map)
  722. {
  723. Map->plus.update_cidx = 1;
  724. }