map.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. /*!
  2. * \file 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-2008 by the GRASS Development Team
  9. *
  10. * This program is free software under the
  11. * GNU General Public License (>=v2).
  12. * Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. * \author Original author CERL, probably Dave Gerdes or Mike
  16. * Higgins. Update to GRASS 5.7 Radim Blazek and David D. Gray.
  17. *
  18. * \date 2001-2008
  19. */
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <dirent.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <fcntl.h>
  28. #include <grass/glocale.h>
  29. #include <grass/gis.h>
  30. #include <grass/Vect.h>
  31. #include <grass/dbmi.h>
  32. #include <grass/glocale.h>
  33. /*!
  34. \brief Copy all alive elements of opened vector map to another opened vector map
  35. \param[in] In input vector map
  36. \param[out] Out output vector map
  37. \return 0 on success
  38. \return 1 on error
  39. */
  40. int
  41. Vect_copy_map_lines ( struct Map_info *In, struct Map_info *Out )
  42. {
  43. int i, type, nlines, ret;
  44. struct line_pnts *Points;
  45. struct line_cats *Cats;
  46. Points = Vect_new_line_struct ();
  47. Cats = Vect_new_cats_struct ();
  48. if ( Vect_level ( In ) < 1 )
  49. G_fatal_error ("Vect_copy_map_lines(): %s", _("input vector map is not open"));
  50. ret = 0;
  51. /* Note: sometimes is important to copy on level 2 (pseudotopo centroids)
  52. * and sometimes on level 1 if build take too long time */
  53. if ( Vect_level ( In ) >= 2 ) {
  54. nlines = Vect_get_num_lines ( In );
  55. for ( i = 1; i <= nlines; i++ ) {
  56. type = Vect_read_line (In, Points, Cats, i);
  57. if ( type == -1 ) {
  58. G_warning (_("Unable to read vector map <%s>"), Vect_get_full_name(In));
  59. ret = 1;
  60. break;
  61. }
  62. if ( type == 0 ) continue; /* dead line */
  63. Vect_write_line ( Out, type, Points, Cats );
  64. }
  65. } else { /* Level 1 */
  66. Vect_rewind ( In );
  67. while ( 1 ) {
  68. type = Vect_read_next_line (In, Points, Cats);
  69. if ( type == -1 ) {
  70. G_warning (_("Unable to read vector map <%s>"), Vect_get_full_name(In));
  71. ret = 1;
  72. break;
  73. } else if ( type == -2 ) { /* EOF */
  74. break;
  75. } else if ( type == 0 ) { /* dead line */
  76. continue;
  77. }
  78. Vect_write_line ( Out, type, Points, Cats );
  79. }
  80. }
  81. Vect_destroy_line_struct (Points);
  82. Vect_destroy_cats_struct (Cats);
  83. return ret;
  84. }
  85. /*
  86. \brief Copy file
  87. \param[in] src source file
  88. \param[out] dst destination file
  89. \return 0 OK
  90. \return 1 error
  91. */
  92. static int
  93. copy_file(const char *src, const char *dst)
  94. {
  95. char buf[1024];
  96. int fd, fd2;
  97. FILE *f2;
  98. int len, len2;
  99. if((fd = open(src, O_RDONLY)) < 0) return 1;
  100. /* if((fd2 = open(dst, O_CREAT|O_TRUNC|O_WRONLY)) < 0) */
  101. if((f2 = fopen(dst, "w")) == NULL)
  102. {
  103. close(fd);
  104. return 1;
  105. }
  106. fd2 = fileno(f2);
  107. while((len = read(fd, buf, 1024)) > 0)
  108. {
  109. while(len && (len2 = write(fd2, buf, len)) >= 0)
  110. len -= len2;
  111. }
  112. close(fd);
  113. /* close(fd2); */
  114. fclose(f2);
  115. if ( len == -1 || len2 == -1 ) return 1;
  116. return 0;
  117. }
  118. /*!
  119. \brief Copy a map including attribute tables
  120. Old vector is deleted
  121. \param[in] in input vector map name
  122. \param[in] mapset mapset name
  123. \param[in] out output vector map name
  124. \param[in] msgout output file for messages or NULL
  125. \return -1 error
  126. \return 0 success
  127. */
  128. int
  129. Vect_copy ( const char *in, const char *mapset, const char *out, FILE *msgout )
  130. {
  131. int i, n, ret, type;
  132. struct Map_info In, Out;
  133. struct field_info *Fi, *Fin;
  134. char old_path[GPATH_MAX], new_path[GPATH_MAX], buf[GPATH_MAX];
  135. struct stat info;
  136. const char *files[] = { GRASS_VECT_FRMT_ELEMENT, GRASS_VECT_COOR_ELEMENT,
  137. GRASS_VECT_HEAD_ELEMENT, GRASS_VECT_HIST_ELEMENT,
  138. GV_TOPO_ELEMENT, GV_SIDX_ELEMENT, GV_CIDX_ELEMENT,
  139. NULL };
  140. dbDriver *driver;
  141. G_debug (2, "Copy vector '%s' in '%s' to '%s'", in, mapset, out );
  142. /* check for [A-Za-z][A-Za-z0-9_]* in name */
  143. if (Vect_legal_filename(out) < 0 )
  144. G_fatal_error ( _("Vector map name is not SQL compliant") );
  145. /* Delete old vector if it exists */
  146. if ( G_find_vector2(out, G_mapset()) ) {
  147. G_warning (_("Vector map <%s> already exists and will be overwritten"), out);
  148. ret = Vect_delete ( out );
  149. if ( ret != 0 ) {
  150. G_warning (_("Unable to delete vector map <%s>"), in);
  151. return -1;
  152. }
  153. }
  154. /* Copy the directory */
  155. G__make_mapset_element ( GRASS_VECT_DIRECTORY );
  156. sprintf ( buf, "%s/%s", GRASS_VECT_DIRECTORY, out );
  157. G__make_mapset_element ( buf );
  158. i = 0;
  159. while ( files[i] )
  160. {
  161. sprintf ( buf, "%s/%s", in, files[i] );
  162. G__file_name (old_path, GRASS_VECT_DIRECTORY, buf, mapset );
  163. sprintf ( buf, "%s/%s", out, files[i] );
  164. G__file_name (new_path, GRASS_VECT_DIRECTORY, buf, G_mapset() );
  165. if ( stat (old_path, &info) == 0) /* file exists? */
  166. {
  167. G_debug (2, "copy %s to %s", old_path, new_path );
  168. if ( copy_file ( old_path, new_path ) )
  169. {
  170. G_warning (_("Unable to copy vector map <%s> to <%s>"), old_path, new_path );
  171. }
  172. }
  173. i++;
  174. }
  175. G__file_name (old_path, GRASS_VECT_DIRECTORY, in, mapset );
  176. G__file_name (new_path, GRASS_VECT_DIRECTORY, out, G_mapset() );
  177. /* Open input */
  178. Vect_set_open_level (1);
  179. Vect_open_old_head (&In, in, mapset);
  180. if ( In.format != GV_FORMAT_NATIVE ) { /* Done */
  181. Vect_close ( &In );
  182. return 0;
  183. }
  184. /* Open output */
  185. Vect_open_update_head ( &Out, out, G_mapset() );
  186. /* Copy tables */
  187. n = Vect_get_num_dblinks ( &In );
  188. type = GV_1TABLE;
  189. if ( n > 1 ) type = GV_MTABLE;
  190. for ( i = 0; i < n; i++ ) {
  191. Fi = Vect_get_dblink ( &In, i );
  192. if ( Fi == NULL ) {
  193. G_warning (_("Database connection not defined for layer %d"),
  194. In.dblnk->field[i].number);
  195. Vect_close ( &In );
  196. Vect_close ( &Out );
  197. return -1;
  198. }
  199. Fin = Vect_default_field_info ( &Out, Fi->number, Fi->name, type );
  200. G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  201. Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
  202. Vect_map_add_dblink ( &Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver);
  203. ret = db_copy_table ( Fi->driver, Fi->database, Fi->table,
  204. Fin->driver, Vect_subst_var(Fin->database,&Out), Fin->table );
  205. if ( ret == DB_FAILED ) {
  206. G_warning (_("Unable to copy table <%s>"), Fin->table);
  207. Vect_close ( &In );
  208. Vect_close ( &Out );
  209. return -1;
  210. }
  211. driver = db_start_driver_open_database ( Fin->driver, Vect_subst_var(Fin->database,&Out) );
  212. if ( driver == NULL ) {
  213. G_warning (_("Unable to open database <%s> by driver <%s>"),
  214. Fin->database, Fin->driver);
  215. } else {
  216. if ( db_create_index2(driver, Fin->table, Fi->key ) != DB_OK )
  217. G_warning (_("Unable to create index for table <%s>, key <%s>"),
  218. Fi->table, Fi->key);
  219. db_close_database_shutdown_driver ( driver );
  220. }
  221. }
  222. Vect_close ( &In );
  223. Vect_close ( &Out );
  224. return 0;
  225. }
  226. /*!
  227. \brief Rename a map.
  228. Attribute tables are created in the same database where input tables were stored.
  229. The original format (native/OGR) is used.
  230. Old map ('out') is deleted!!!
  231. \param[in] in input vector map name
  232. \param[in] out output vector map name
  233. \param[in] msgout output file for messages or NULL
  234. \return -1 error
  235. \return 0 success
  236. */
  237. int
  238. Vect_rename ( const char *in, const char *out, FILE *msgout )
  239. {
  240. int i, n, ret, type;
  241. struct Map_info Map;
  242. struct field_info *Fin, *Fout;
  243. int *fields;
  244. dbDriver *driver;
  245. G_debug (2, "Rename vector '%s' to '%s'", in, out );
  246. /* check for [A-Za-z][A-Za-z0-9_]* in name */
  247. if (Vect_legal_filename(out) < 0 )
  248. G_fatal_error ( _("Vector map name is not SQL compliant") );
  249. /* Delete old vector if it exists */
  250. if ( G_find_vector2(out, G_mapset()) ) {
  251. G_warning (_("Vector map <%s> already exists and will be overwritten"), out);
  252. Vect_delete ( out );
  253. }
  254. /* Move the directory */
  255. ret = G_rename ( GRASS_VECT_DIRECTORY, in, out );
  256. if ( ret == 0 ) {
  257. G_warning (_("Vector map <%s> not found"), in );
  258. return -1;
  259. } else if ( ret == -1 ) {
  260. G_warning (_("Unable to copy vector map <%s> to <%s>"), in, out );
  261. return -1;
  262. }
  263. /* Rename all tables if the format is native */
  264. Vect_set_open_level (1);
  265. Vect_open_update_head ( &Map, out, G_mapset() );
  266. if ( Map.format != GV_FORMAT_NATIVE ) { /* Done */
  267. Vect_close ( &Map );
  268. return 0;
  269. }
  270. /* Copy tables */
  271. n = Vect_get_num_dblinks ( &Map );
  272. type = GV_1TABLE;
  273. if ( n > 1 ) type = GV_MTABLE;
  274. /* Make the list of fields */
  275. fields = (int *) G_malloc ( n * sizeof(int) );
  276. for ( i = 0; i < n; i++ ) {
  277. Fin = Vect_get_dblink ( &Map, i );
  278. fields[i] = Fin->number;
  279. }
  280. for ( i = 0; i < n; i++ ) {
  281. G_debug (3, "field[%d] = %d", i, fields[i] );
  282. Fin = Vect_get_field ( &Map, fields[i] );
  283. if ( Fin == NULL ) {
  284. G_warning (_("Database connection not defined for layer %d"),
  285. fields[i]);
  286. Vect_close ( &Map );
  287. return -1;
  288. }
  289. Fout = Vect_default_field_info ( &Map, Fin->number, Fin->name, type );
  290. G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  291. Fin->driver, Fin->database, Fin->table, Fout->driver, Fout->database, Fout->table );
  292. /* TODO: db_rename_table instead of db_copy_table */
  293. ret = db_copy_table ( Fin->driver, Fin->database, Fin->table,
  294. Fout->driver, Vect_subst_var(Fout->database,&Map), Fout->table );
  295. if ( ret == DB_FAILED ) {
  296. G_warning (_("Unable to copy table <%s>"), Fin->table);
  297. Vect_close ( &Map );
  298. return -1;
  299. }
  300. /* Change the link */
  301. Vect_map_del_dblink ( &Map, Fin->number );
  302. Vect_map_add_dblink ( &Map, Fout->number, Fout->name, Fout->table, Fin->key,
  303. Fout->database, Fout->driver);
  304. /* Delete old table */
  305. ret = db_delete_table ( Fin->driver, Fin->database, Fin->table );
  306. if ( ret == DB_FAILED ) {
  307. G_warning (_("Unable to delete table <%s>"), Fin->table );
  308. Vect_close ( &Map );
  309. return -1;
  310. }
  311. driver = db_start_driver_open_database ( Fout->driver, Vect_subst_var(Fout->database, &Map) );
  312. if ( driver == NULL ) {
  313. G_warning (_("Unable to open database <%s> by driver <%s>"),
  314. Fout->database, Fout->driver);
  315. } else {
  316. if ( db_create_index2(driver, Fout->table, Fin->key ) != DB_OK )
  317. G_warning (_("Unable to create index for table <%s>, key <%s>"),
  318. Fout->table, Fout->key);
  319. db_close_database_shutdown_driver ( driver );
  320. }
  321. }
  322. Vect_close ( &Map );
  323. free ( fields );
  324. return 0;
  325. }
  326. /*!
  327. \brief Delete vector map including attribute tables
  328. \param[in] map vector map name
  329. \return -1 error
  330. \return 0 success
  331. */
  332. int
  333. Vect_delete ( const char *map )
  334. {
  335. int i, n, ret;
  336. struct Map_info Map;
  337. struct field_info *Fi;
  338. char buf[GPATH_MAX];
  339. DIR *dir;
  340. struct dirent *ent;
  341. const char *tmp;
  342. G_debug (3, "Delete vector '%s'", map );
  343. if ( map == NULL || strlen ( map ) == 0 ) {
  344. G_warning (_("Invalid vector map name <%s>"), map ? map : "null");
  345. return -1;
  346. }
  347. sprintf ( buf, "%s/%s/%s/%s/%s/%s", G_gisdbase(), G_location(),
  348. G_mapset(), GRASS_VECT_DIRECTORY, map,
  349. GRASS_VECT_DBLN_ELEMENT );
  350. G_debug (1, "dbln file: %s", buf);
  351. if ( access(buf,F_OK) == 0 )
  352. {
  353. /* Open input */
  354. Vect_set_open_level (1); /* Topo not needed */
  355. ret = Vect_open_old_head (&Map, map, G_mapset());
  356. if ( ret < 1 ) {
  357. G_warning (_("Unable to open header file for vector map <%s>"), map );
  358. return -1;
  359. }
  360. /* Delete all tables, NOT external (OGR) */
  361. if ( Map.format == GV_FORMAT_NATIVE ) {
  362. n = Vect_get_num_dblinks ( &Map );
  363. for ( i = 0; i < n; i++ ) {
  364. Fi = Vect_get_dblink ( &Map, i );
  365. if ( Fi == NULL ) {
  366. G_warning (_("Database connection not defined for layer %d"),
  367. Map.dblnk->field[i].number);
  368. Vect_close ( &Map );
  369. return -1;
  370. }
  371. G_debug (3, "Delete drv:db:table '%s:%s:%s'", Fi->driver, Fi->database, Fi->table);
  372. ret = db_table_exists ( Fi->driver, Fi->database, Fi->table );
  373. if ( ret == -1 ) {
  374. G_warning (_("Unable to find table <%s> linked to vector map <%s>"),
  375. Fi->table, map );
  376. Vect_close ( &Map );
  377. return -1;
  378. }
  379. if ( ret == 1 ) {
  380. ret = db_delete_table ( Fi->driver, Fi->database, Fi->table );
  381. if ( ret == DB_FAILED ) {
  382. G_warning (_("Unable to delete table <%s>"));
  383. Vect_close ( &Map );
  384. return -1;
  385. }
  386. } else {
  387. G_warning (_("Table <%s> linked to vector map <%s> does not exist"),
  388. Fi->table, map);
  389. }
  390. }
  391. }
  392. Vect_close ( &Map );
  393. }
  394. /* Delete all files from vector/name directory */
  395. sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
  396. G_debug (3, "opendir '%s'", buf );
  397. dir = opendir( buf );
  398. if (dir == NULL) {
  399. G_warning (_("Unable to open directory '%s'"), buf );
  400. return -1;
  401. }
  402. while ( (ent = readdir (dir)) ) {
  403. G_debug (3, "file = '%s'", ent->d_name );
  404. if ( (strcmp (ent->d_name, ".") == 0) || (strcmp (ent->d_name, "..") == 0) ) continue;
  405. sprintf ( buf, "%s/%s/vector/%s/%s", G_location_path(), G_mapset(), map, ent->d_name );
  406. G_debug (3, "delete file '%s'", buf );
  407. ret = unlink ( buf );
  408. if ( ret == -1 ) {
  409. G_warning (_("Unable to delete file '%s'"), buf );
  410. closedir (dir);
  411. return -1;
  412. }
  413. }
  414. closedir (dir);
  415. /* NFS can create .nfsxxxxxxxx files for those deleted
  416. * -> we have to move the directory to ./tmp before it is deleted */
  417. sprintf ( buf, "%s/%s/vector/%s", G_location_path(), G_mapset(), map );
  418. tmp = G_tempfile();
  419. G_debug (3, "rename '%s' to '%s'", buf, tmp );
  420. ret = rename ( buf, tmp );
  421. if ( ret == -1 ) {
  422. G_warning (_("Unable to rename directory '%s' to '%s'"), buf, tmp );
  423. return -1;
  424. }
  425. G_debug (3, "remove directory '%s'", tmp );
  426. /* Warning: remove() fails on Windows */
  427. ret = rmdir ( tmp );
  428. if ( ret == -1 ) {
  429. G_warning (_("Unable to remove directory '%s'"), tmp );
  430. return -1;
  431. }
  432. return 0;
  433. }
  434. /*!
  435. \brief Copy tables linked to vector map.
  436. All if field = 0, or table defined by given field if field > 0
  437. \param[in] In input vector map
  438. \param[out] Out output vector map
  439. \param[in] field layer number
  440. \return 0 on success
  441. \return -1 on error
  442. */
  443. int
  444. Vect_copy_tables ( struct Map_info *In, struct Map_info *Out, int field )
  445. {
  446. int i, n, ret, type;
  447. struct field_info *Fi, *Fin;
  448. dbDriver *driver;
  449. G_debug (2, "Vect_copy_tables()");
  450. n = Vect_get_num_dblinks ( In );
  451. type = GV_1TABLE;
  452. if ( n > 1 ) type = GV_MTABLE;
  453. for ( i = 0; i < n; i++ ) {
  454. Fi = Vect_get_dblink ( In, i );
  455. if ( Fi == NULL ) {
  456. G_warning (_("Database connection not defined for layer %d"),
  457. In->dblnk->field[i].number);
  458. return -1;
  459. }
  460. if ( field > 0 && Fi->number != field ) continue;
  461. Fin = Vect_default_field_info ( Out, Fi->number, Fi->name, type );
  462. G_debug (2, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  463. Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
  464. ret = Vect_map_add_dblink ( Out, Fi->number, Fi->name, Fin->table, Fi->key, Fin->database, Fin->driver);
  465. if ( ret == -1 ) {
  466. G_warning (_("Unable to add database link for vector map <%s>"),
  467. Out->name);
  468. return -1;
  469. }
  470. ret = db_copy_table ( Fi->driver, Fi->database, Fi->table,
  471. Fin->driver, Vect_subst_var(Fin->database,Out), Fin->table );
  472. if ( ret == DB_FAILED ) {
  473. G_warning (_("Unable to copy table <%s>"), Fin->table);
  474. return -1;
  475. }
  476. driver = db_start_driver_open_database ( Fin->driver, Vect_subst_var(Fin->database,Out) );
  477. if ( driver == NULL ) {
  478. G_warning (_("Unable to open database <%s> by driver <%s>"),
  479. Fin->database, Fin->driver);
  480. } else {
  481. if ( db_create_index2(driver, Fin->table, Fi->key ) != DB_OK )
  482. G_warning (_("Unable to create index for table <%s>, key <%s>"),
  483. Fin->table, Fin->key);
  484. db_close_database_shutdown_driver ( driver );
  485. }
  486. }
  487. return 0;
  488. }
  489. /*!
  490. \brief Copy table linked to vector map based on type.
  491. \param[in] In input vector map
  492. \param[out] Out output vector map
  493. \param[in] field_in input layer number
  494. \param[in] field_out output layer number
  495. \param[in] field_name layer name
  496. \param[in] type feature type
  497. \return 0 on success
  498. \return -1 on error
  499. */
  500. int
  501. Vect_copy_table ( struct Map_info *In, struct Map_info *Out, int field_in,
  502. int field_out, const char *field_name, int type )
  503. {
  504. return Vect_copy_table_by_cats ( In, Out, field_in, field_out, field_name, type, NULL, 0);
  505. }
  506. /*!
  507. \brief Copy table linked to vector map based on category numbers.
  508. \param[in] In input vector map
  509. \param[out] Out output vector map
  510. \param[in] field_in input layer number
  511. \param[in] field_out output layer number
  512. \param[in] field_name layer name
  513. \param[in] type feature type
  514. \param[in] cats pointer to array of cats or NULL
  515. \param[in] ncats number of cats in 'cats'
  516. \return 0 on success
  517. \return -1 on error
  518. */
  519. int
  520. Vect_copy_table_by_cats ( struct Map_info *In, struct Map_info *Out, int field_in,
  521. int field_out, const char *field_name, int type, int *cats, int ncats )
  522. {
  523. int ret;
  524. struct field_info *Fi, *Fin;
  525. const char *name, *key;
  526. G_debug (2, "Vect_copy_table(): field_in = %d field_out = %d", field_in, field_out);
  527. Fi = Vect_get_field ( In, field_in );
  528. if ( Fi == NULL ) {
  529. G_warning (_("Database connection not defined for layer %d"),
  530. field_in);
  531. return -1;
  532. }
  533. if ( field_name != NULL ) name = field_name;
  534. else name = Fi->name;
  535. Fin = Vect_default_field_info ( Out, field_out, name, type );
  536. G_debug (3, "Copy drv:db:table '%s:%s:%s' to '%s:%s:%s'",
  537. Fi->driver, Fi->database, Fi->table, Fin->driver, Fin->database, Fin->table );
  538. ret = Vect_map_add_dblink ( Out, Fin->number, Fin->name, Fin->table, Fi->key, Fin->database, Fin->driver);
  539. if ( ret == -1 ) {
  540. G_warning (_("Unable to add database link for vector map <%s>"), Out->name);
  541. return -1;
  542. }
  543. if ( cats )
  544. key = Fi->key;
  545. else
  546. key = NULL;
  547. ret = db_copy_table_by_ints ( Fi->driver, Fi->database, Fi->table,
  548. Fin->driver, Vect_subst_var(Fin->database,Out), Fin->table, key, cats, ncats );
  549. if ( ret == DB_FAILED ) {
  550. G_warning (_("Unable to copy table <%s>"), Fin->table);
  551. return -1;
  552. }
  553. return 0;
  554. }
  555. /*!
  556. \brief Set spatial index to be realease when vector is closed.
  557. By default, the memory occupied by spatial index is not released.
  558. \param Map vector map
  559. \return
  560. */
  561. void
  562. Vect_set_release_support ( struct Map_info * Map )
  563. {
  564. Map->plus.release_support = 1;
  565. }
  566. /*!
  567. \brief By default, category index is not updated if vector is changed, this function sets category index update.
  568. WARNING: currently only category for elements is updated
  569. not for areas
  570. \param Map vector map
  571. \return
  572. */
  573. void
  574. Vect_set_category_index_update ( struct Map_info * Map )
  575. {
  576. Map->plus.update_cidx = 1;
  577. }