1 /*!
2 \file lib/vector/Vlib/field.c
3
4 \brief Vector library - field (layer) related fns.
5
6 Higher level functions for reading/writing/manipulating vectors.
7
8 \todo see Vect_read_dblinks(); activate auto-FID detection once
9 OGR_L_GetFIDColumn() is working or solution found if FID not
10 available
11
12 (C) 2001-2009, 2011-2012 by the GRASS Development Team
13
14 This program is free software under the GNU General Public License
15 (>=v2). Read the file COPYING that comes with GRASS for details.
16
17 \author Original author CERL, probably Dave Gerdes or Mike Higgins.
18 \author Update to GRASS 5.7 by Radim Blazek and David D. Gray.
19 \author Various updates by Martin Landa <landa.martin gmail.com>, 2009-2011
20 */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <grass/gis.h>
26 #include <grass/glocale.h>
27 #include <grass/dbmi.h>
28 #include <grass/vector.h>
29
30 #include "local_proto.h"
31
32 #ifdef HAVE_GDAL
33 #include <gdal_version.h> /* needed for FID detection */
34 #endif /* HAVE_GDAL */
35
36 #ifdef HAVE_OGR
37 #include <ogr_api.h>
38 #endif
39
40 /*!
41 \brief Create and init new dblinks structure
42
43 \return pointer to new dblinks structure
44 \return NULL on failure
45 */
Vect_new_dblinks_struct(void)46 struct dblinks *Vect_new_dblinks_struct(void)
47 {
48 struct dblinks *p;
49
50 p = (struct dblinks *)G_malloc(sizeof(struct dblinks));
51
52 if (p) {
53 /* initialize members */
54 G_zero(p, sizeof(struct dblinks));
55 }
56
57 return p;
58 }
59
name2sql(char * name)60 static int name2sql(char *name)
61 {
62 char *s = name;
63 int ret;
64
65 if (!s)
66 return 0;
67
68 /* sql-compliant name must start with letter */
69 if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z'))) {
70 G_warning(_("Name <%s> is not SQL compliant. Must start with a letter."),
71 name);
72 return 0;
73 }
74
75 ret = 1;
76 /* convert illegal characters to underscore */
77 for (s++; *s; s++) {
78 if (!((*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') ||
79 (*s >= '0' && *s <= '9') || *s == '_')) {
80 G_debug(2, "Character '%c' not allowed.", *s);
81 *s = '_';
82 ret++;
83 }
84 }
85
86 return ret;
87 }
88
89 /*!
90 \brief Reset dblinks structure (number of fields)
91
92 \param p pointer to existing dblinks structure
93 */
Vect_reset_dblinks(struct dblinks * p)94 void Vect_reset_dblinks(struct dblinks *p)
95 {
96 p->n_fields = 0;
97 }
98
99 /*!
100 \brief Add new db connection to Map_info structure
101
102 \param Map pointer to Map_info structure
103 \param number layer number
104 \param name layer name (if not given use table name)
105 \param table table name
106 \param key key name
107 \param db database name
108 \param driver driver name
109
110 \return 0 on success
111 \return -1 on failure
112 */
Vect_map_add_dblink(struct Map_info * Map,int number,const char * name,const char * table,const char * key,const char * db,const char * driver)113 int Vect_map_add_dblink(struct Map_info *Map, int number, const char *name,
114 const char *table, const char *key, const char *db,
115 const char *driver)
116 {
117 int ret;
118
119 if (number < 1) {
120 G_warning(_("Layer number must be 1 or greater"));
121 return -1;
122 }
123
124 if (Map->mode != GV_MODE_WRITE && Map->mode != GV_MODE_RW) {
125 G_warning(_("Unable to add attribute link, vector map is "
126 "not opened in WRITE mode"));
127 return -1;
128 }
129
130 ret = Vect_add_dblink(Map->dblnk, number, name, table, key, db, driver);
131 if (ret == -1) {
132 G_warning(_("Unable to add attribute link"));
133 return -1;
134 }
135 /* write it immediately otherwise it is lost if module crashes */
136 ret = Vect_write_dblinks(Map);
137 if (ret == -1) {
138 G_warning(_("Unable to write attribute links"));
139 return -1;
140 }
141 return 0;
142 }
143
144 /*!
145 \brief Delete db connection from Map_info structure
146
147 \param Map pointer to Map_info structure
148 \param field layer number (-1 to delete all dblinks)
149
150 \return 0 deleted
151 \return -1 error
152 */
Vect_map_del_dblink(struct Map_info * Map,int field)153 int Vect_map_del_dblink(struct Map_info *Map, int field)
154 {
155 int i, j, ret;
156 struct dblinks *links;
157
158 G_debug(4, "Vect_map_del_dblink() field = %d", field);
159 links = Map->dblnk;
160
161 ret = -1;
162 for (i = 0; i < links->n_fields; i++) {
163 if (field < 0 || links->field[i].number == field) { /* field found */
164 for (j = i; j < links->n_fields - 1; j++) {
165 links->field[j].number = links->field[j + 1].number;
166 links->field[j].name = links->field[j + 1].name;
167 links->field[j].table = links->field[j + 1].table;
168 links->field[j].key = links->field[j + 1].key;
169 links->field[j].database = links->field[j + 1].database;
170 links->field[j].driver = links->field[j + 1].driver;
171 }
172 ret = 0;
173 links->n_fields--;
174 }
175 }
176
177 if (ret == -1)
178 return -1;
179
180 /* write it immediately otherwise it is lost if module crashes */
181 ret = Vect_write_dblinks(Map);
182 if (ret == -1) {
183 G_warning(_("Unable to write database links"));
184 return -1;
185 }
186
187 return 0;
188 }
189
190 /*!
191 \brief Copy DB links from input vector map to output vector map
192
193 \param In pointer to Map_info structure (input)
194 \param Out pointer to Map_info structure (output)
195 \param first_only TRUE to copy only first link otherwise all DB links are copied
196 */
Vect_copy_map_dblinks(const struct Map_info * In,struct Map_info * Out,int first_only)197 void Vect_copy_map_dblinks(const struct Map_info *In, struct Map_info *Out,
198 int first_only)
199 {
200 int i, ndblinks;
201 struct field_info *Fi;
202
203 ndblinks = Vect_get_num_dblinks(In);
204 for (i = 0; i < ndblinks; i++) {
205 Fi = Vect_get_dblink(In, 0);
206 if (!Fi) {
207 G_warning(_("Database connection not defined. Skipping."));
208 continue;
209 }
210 Vect_map_add_dblink(Out, Fi->number, Fi->name, Fi->table, Fi->key,
211 Fi->database, Fi->driver);
212
213 if (first_only && ndblinks > 1)
214 G_warning(_("More DB links defined for input vector map. "
215 "Using only first DB link for output."));
216 }
217 }
218
219 /*!
220 \brief Check if DB connection exists in dblinks structure
221
222 \param Map pointer to Map_info structure
223 \param field layer number
224 \param name layer name
225
226 \return 1 dblink for field exists
227 \return 0 dblink does not exist for field
228 */
Vect_map_check_dblink(const struct Map_info * Map,int field,const char * name)229 int Vect_map_check_dblink(const struct Map_info *Map, int field, const char *name)
230 {
231 return Vect_check_dblink(Map->dblnk, field, name);
232 }
233
234 /*!
235 \brief Check if DB connection exists in dblinks structure
236
237 \param p pointer to existing dblinks structure
238 \param field layer number
239 \param name layer name
240
241 \return 1 dblink for field exists
242 \return 0 dblink does not exist for field
243 */
Vect_check_dblink(const struct dblinks * p,int field,const char * name)244 int Vect_check_dblink(const struct dblinks *p, int field, const char *name)
245 {
246 int i;
247
248 G_debug(3, "Vect_check_dblink: field %d, name %s", field, (name != NULL ? name : "not given"));
249
250 for (i = 0; i < p->n_fields; i++) {
251 if (p->field[i].number == field) {
252 return 1;
253 }
254 if (name != NULL && p->field[i].name != NULL) {
255 if (strcmp(p->field[i].name, name) == 0)
256 return 1;
257 }
258 }
259 return 0;
260 }
261
262
263 /*!
264 \brief Add new DB connection to dblinks structure
265
266 \param[in,out] p pointer to existing dblinks structure
267 \param number layer number (1 for OGR)
268 \param name layer name (layer for OGR) - if not given use table name
269 \param table table name (layer for OGR)
270 \param key key name
271 \param db database name (datasource for OGR)
272 \param driver driver name (dbf, postgresql, ogr, ...)
273
274 \return 0 on success
275 \return -1 error
276 */
Vect_add_dblink(struct dblinks * p,int number,const char * name,const char * table,const char * key,const char * db,const char * driver)277 int Vect_add_dblink(struct dblinks *p, int number, const char *name,
278 const char *table, const char *key, const char *db,
279 const char *driver)
280 {
281 int ret;
282
283 G_debug(3, "Field number <%d>, name <%s>", number, name);
284 if (!name) {
285 /* if name is not given, use table name */
286 name = table;
287 }
288 ret = Vect_check_dblink(p, number, name);
289 if (ret == 1) {
290 G_warning(_("Layer number %d or name <%s> already exists"), number,
291 name);
292 return -1;
293 }
294
295 if (p->n_fields == p->alloc_fields) {
296 p->alloc_fields += 10;
297 p->field = (struct field_info *)G_realloc((void *)p->field,
298 p->alloc_fields *
299 sizeof(struct field_info));
300 }
301
302 p->field[p->n_fields].number = number;
303
304 if (name != NULL) {
305 p->field[p->n_fields].name = G_store(name);
306 /* replace all spaces with underscore, otherwise dbln can't be read */
307 /* G_strchg(p->field[p->n_fields].name, ' ', '_'); */
308 if (!name2sql(p->field[p->n_fields].name)) {
309 G_free(p->field[p->n_fields].name);
310 p->field[p->n_fields].name = NULL;
311 }
312 }
313 else
314 p->field[p->n_fields].name = NULL;
315
316 if (table != NULL)
317 p->field[p->n_fields].table = G_store(table);
318 else
319 p->field[p->n_fields].table = NULL;
320
321 if (key != NULL)
322 p->field[p->n_fields].key = G_store(key);
323 else
324 p->field[p->n_fields].key = NULL;
325
326 if (db != NULL)
327 p->field[p->n_fields].database = G_store(db);
328 else
329 p->field[p->n_fields].database = NULL;
330
331 if (driver != NULL)
332 p->field[p->n_fields].driver = G_store(driver);
333 else
334 p->field[p->n_fields].driver = NULL;
335
336 p->n_fields++;
337
338 return 0;
339 }
340
341 /*!
342 \brief Get default information about link to database for new dblink
343
344 \param Map pointer to Map_info structure
345 \param field layer number
346 \param field_name layer name
347 \param type how many tables are linked to map: GV_1TABLE / GV_MTABLE
348
349 \return pointer to allocated field_info structure
350 */
Vect_default_field_info(struct Map_info * Map,int field,const char * field_name,int type)351 struct field_info *Vect_default_field_info(struct Map_info *Map,
352 int field, const char *field_name, int type)
353 {
354 struct field_info *fi;
355 char buf[GNAME_MAX], buf2[GNAME_MAX];
356 const char *schema;
357 dbConnection connection;
358
359 G_debug(1, "Vect_default_field_info(): map = %s field = %d", Map->name,
360 field);
361
362 if (Map->format == GV_FORMAT_OGR_DIRECT) {
363 G_zero(&connection, sizeof(dbConnection));
364 connection.driverName = G_store("ogr");
365 connection.databaseName = G_store(Map->fInfo.ogr.dsn);
366 }
367 else {
368 db_get_connection(&connection);
369 }
370
371 G_debug(2, "drv = %s db = %s", connection.driverName, connection.databaseName);
372
373 if (!connection.driverName && !connection.databaseName) {
374 /* Set default values */
375 db_set_default_connection();
376 db_get_connection(&connection);
377
378 G_important_message(_("Default driver / database set to:\n"
379 "driver: %s\ndatabase: %s"), connection.driverName,
380 connection.databaseName);
381 }
382 /* they must be a matched pair, so if one is set but not the other
383 then give up and let the user figure it out */
384 else if (!connection.driverName) {
385 G_fatal_error(_("Default driver is not set"));
386 }
387 else if (!connection.databaseName) {
388 G_fatal_error(_("Default database is not set"));
389 }
390
391 fi = (struct field_info *)G_malloc(sizeof(struct field_info));
392
393 fi->number = field;
394
395 /* Field name */
396 fi->name = NULL;
397 if (field_name && *field_name) {
398 fi->name = G_store(field_name);
399 if (!name2sql(fi->name)) {
400 G_free(fi->name);
401 fi->name = NULL;
402 }
403 }
404
405 /* Table name */
406 if (type == GV_1TABLE) {
407 sprintf(buf, "%s", Map->name);
408 }
409 else {
410 if (fi->name != NULL && strlen(fi->name) > 0) {
411 sprintf(buf, "%s_%s", Map->name, fi->name);
412 if (!name2sql(buf)) {
413 sprintf(buf, "%s_%d", Map->name, field);
414 }
415 }
416 else
417 sprintf(buf, "%s_%d", Map->name, field);
418 }
419 schema = connection.schemaName;
420 if (schema && strlen(schema) > 0) {
421 sprintf(buf2, "%s.%s", schema, buf);
422 fi->table = G_store(buf2);
423 }
424 else {
425 fi->table = G_store(buf);
426 }
427
428 /* Field name still empty */
429 if (!fi->name)
430 fi->name = G_store(buf);
431
432 fi->key = G_store(GV_KEY_COLUMN); /* Should be: id/fid/gfid/... ? */
433 #ifdef TEMPORARY_MAP_DB
434 if (Map->temporary) {
435 Vect__get_element_path(buf, Map, NULL);
436 if (strcmp(DB_DEFAULT_DRIVER, "sqlite") == 0)
437 strcat(buf, "/sqlite.db");
438 else
439 strcat(buf, "/db.dbf");
440 fi->database = G_store(buf);
441 fi->driver = DB_DEFAULT_DRIVER;
442 }
443 else {
444 fi->database = G_store(connection.databaseName);
445 fi->driver = G_store(connection.driverName);
446 }
447 #else
448 fi->database = G_store(connection.databaseName);
449 fi->driver = G_store(connection.driverName);
450 #endif
451
452 return fi;
453 }
454
455 /*!
456 \brief Get information about link to database.
457
458 Variables are substituted by values, link is index to array of
459 dblinks.
460
461 \param Map pointer to Map_info structure
462 \param link link id
463
464 \return pointer to new field_info structure
465 */
Vect_get_dblink(const struct Map_info * Map,int link)466 struct field_info *Vect_get_dblink(const struct Map_info *Map, int link)
467 {
468 struct field_info *fi;
469
470 G_debug(1, "Vect_get_dblink(): link = %d", link);
471
472 if (link >= Map->dblnk->n_fields) {
473 G_warning(_("Requested dblink %d, maximum link number %d"), link,
474 Map->dblnk->n_fields - 1);
475 return NULL;
476 }
477
478 fi = (struct field_info *)G_malloc(sizeof(struct field_info));
479 fi->number = Map->dblnk->field[link].number;
480
481 if (Map->dblnk->field[link].name != NULL)
482 fi->name = G_store(Map->dblnk->field[link].name);
483 else
484 fi->name = NULL;
485
486 fi->table = G_store(Map->dblnk->field[link].table);
487 fi->key = G_store(Map->dblnk->field[link].key);
488 fi->database = Vect_subst_var(Map->dblnk->field[link].database, Map);
489 fi->driver = G_store(Map->dblnk->field[link].driver);
490
491 return fi;
492 }
493
494 /*!
495 \brief Get information about link to database (by layer number)
496
497 Variables are substituted by values, field is number of requested
498 field.
499
500 \param Map pointer to Map_info structure
501 \param field layer number
502
503 \return pointer to new field_info structure
504 \return NULL if not found
505 */
Vect_get_field(const struct Map_info * Map,int field)506 struct field_info *Vect_get_field(const struct Map_info *Map, int field)
507 {
508 int i;
509 struct field_info *fi = NULL;
510
511 G_debug(1, "Vect_get_field(): field = %d", field);
512
513 for (i = 0; i < Map->dblnk->n_fields; i++) {
514 if (Map->dblnk->field[i].number == field) {
515 fi = Vect_get_dblink(Map, i);
516 break;
517 }
518 }
519
520 return fi;
521 }
522
523 /*!
524 \brief Get information about link to database (by layer name)
525
526 \param Map pointer to Map_info structure
527 \param field layer name
528
529 \return pointer to new field_info structure
530 \return NULL if not found
531 */
Vect_get_field_by_name(const struct Map_info * Map,const char * field)532 struct field_info *Vect_get_field_by_name(const struct Map_info *Map, const char *field)
533 {
534 int i;
535 struct field_info *fi = NULL;
536
537 G_debug(1, "Vect_get_field_by_name(): field = %s", field);
538
539 for (i = 0; i < Map->dblnk->n_fields; i++) {
540 if (strcmp(Map->dblnk->field[i].name, field) == 0) {
541 fi = Vect_get_dblink(Map, i);
542 break;
543 }
544 }
545
546 return fi;
547 }
548
549 /*!
550 \brief Get information about link to database (by layer number or layer name)
551
552 Note: if <em>field</em> is -1 then the function returns the first
553 dblink or NULL
554
555 \param Map pointer to Map_info structure
556 \param field layer number or name
557
558 \return pointer to new field_info structure
559 \return NULL if not found
560 */
Vect_get_field2(const struct Map_info * Map,const char * field)561 struct field_info *Vect_get_field2(const struct Map_info *Map, const char *field)
562 {
563 int ifield;
564 struct field_info *fi;
565
566 G_debug(1, "Vect_get_field2(): field = %s", field);
567
568 fi = NULL;
569 ifield = atoi(field);
570
571 if (ifield > 0) {
572 fi = Vect_get_field(Map, ifield);
573 if (fi)
574 return fi;
575 }
576 else if (ifield == -1) {
577 if (Vect_get_num_dblinks(Map) > 0)
578 return Vect_get_dblink(Map, 0); /* return first */
579 else
580 return NULL;
581 }
582 else if (ifield == 0)
583 return Vect_get_field_by_name(Map, field);
584
585 return NULL;
586 }
587
588 /*!
589 \brief Get field number of given field
590
591 \param Map pointer to Map_info structure
592 \param field layer name
593
594 \return layer number
595 \return -1 for all layers
596 \return 0 if layer not found
597 */
Vect_get_field_number(const struct Map_info * Map,const char * field)598 int Vect_get_field_number(const struct Map_info *Map, const char *field)
599 {
600 struct field_info *fi;
601
602 G_debug(1, "Vect_get_field_number(): field = %s", field);
603
604 if (strcmp(field, "-1") == 0)
605 return -1;
606
607 if (Vect_get_num_dblinks(Map) == 0)
608 return atoi(field);
609
610 fi = Vect_get_field2(Map, field);
611
612 if (fi)
613 return fi->number;
614
615 return atoi(field);
616 }
617
read_dblinks_nat(struct Map_info * Map)618 static int read_dblinks_nat(struct Map_info *Map)
619 {
620 FILE *fd;
621 char file[1024], buf[2001];
622 char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
623 int fld;
624 char *c, path[GPATH_MAX];
625 int row, rule;
626 struct dblinks *dbl;
627 char **tokens;
628 int ntok, i;
629
630 dbl = Map->dblnk;
631
632 /* Read dblink for native format */
633 Vect__get_path(path, Map);
634 fd = G_fopen_old(path, GV_DBLN_ELEMENT, Map->mapset);
635 if (fd == NULL) { /* This may be correct, no tables defined */
636 G_debug(1, "Cannot open vector database definition file");
637 return -1;
638 }
639
640 row = 0;
641 rule = 0;
642 while (G_getl2(buf, 2000, fd)) {
643 row++;
644 G_chop(buf);
645 G_debug(1, "dbln: %s", buf);
646
647 c = (char *)strchr(buf, '#');
648 if (c != NULL)
649 *c = '\0';
650
651 if (strlen(buf) == 0)
652 continue;
653
654 #ifdef NOT_ABLE_TO_READ_GRASS_6
655 int ndef;
656 ndef = sscanf(buf, "%s|%s|%s|%s|%s", fldstr, tab, col, db, drv);
657
658 if (ndef < 2 || (ndef < 5 && rule < 1)) {
659 G_warning(_("Error in rule on row %d in <%s>"), row, file);
660 continue;
661 }
662 #else
663 tokens = G_tokenize(buf, " |");
664 ntok = G_number_of_tokens(tokens);
665
666 if (ntok < 2 || (ntok < 5 && rule < 1)) {
667 G_warning(_("Error in rule on row %d in <%s>"), row, file);
668 continue;
669 }
670
671 strcpy(fldstr, tokens[0]);
672 strcpy(tab, tokens[1]);
673 if (ntok > 2) {
674 strcpy(col, tokens[2]);
675 if (ntok > 3) {
676 strcpy(db, tokens[3]);
677 /* allow for spaces in path names */
678 for (i=4; i < ntok-1; i++) {
679 strcat(db, " ");
680 strcat(db, tokens[i]);
681 }
682
683 strcpy(drv, tokens[ntok-1]);
684 }
685 }
686 G_free_tokens(tokens);
687 #endif
688
689 /* get field and field name */
690 fldname = strchr(fldstr, '/');
691 if (fldname != NULL) { /* field has name */
692 fldname[0] = 0;
693 fldname++;
694 }
695 fld = atoi(fldstr);
696
697 Vect_add_dblink(dbl, fld, fldname, tab, col, db, drv);
698
699 G_debug(1,
700 "field = %d name = %s, table = %s, key = %s, database = %s, driver = %s",
701 fld, fldname, tab, col, db, drv);
702
703 rule++;
704 }
705 fclose(fd);
706
707 G_debug(1, "Dblinks read");
708
709 return rule;
710 }
711
712 /* return -1 on error */
read_dblinks_ogr(struct Map_info * Map)713 static int read_dblinks_ogr(struct Map_info *Map)
714 {
715 struct dblinks *dbl;
716
717 dbl = Map->dblnk;
718 G_debug(3, "Searching for FID column in OGR DB");
719 #ifndef HAVE_OGR
720 G_warning(_("GRASS is not compiled with OGR support"));
721 #else
722 #if GDAL_VERSION_NUM > 1320 && HAVE_OGR /* seems to be fixed after 1320 release */
723 int nLayers;
724 char *ogr_fid_col;
725
726 G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
727
728 if (Map->fInfo.ogr.ds == NULL) {
729 /* open the connection to fetch the FID column name */
730 OGRRegisterAll();
731
732 /* data source handle */
733 Map->fInfo.ogr.ds = OGROpen(Map->fInfo.ogr.dsn, FALSE, NULL);
734 if (Map->fInfo.ogr.ds == NULL) {
735 G_warning(_("Unable to open OGR data source '%s'"),
736 Map->fInfo.ogr.dsn);
737 return -1;
738 }
739 }
740 if (Map->fInfo.ogr.layer == NULL) {
741 /* get layer number */
742 nLayers = OGR_DS_GetLayerCount(Map->fInfo.ogr.ds); /* Layers = Maps in OGR DB */
743
744 G_debug(3, "%d layers (maps) found in data source", nLayers);
745
746 G_debug(3, "Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
747 if (Map->fInfo.ogr.layer_name) {
748 Map->fInfo.ogr.layer = OGR_DS_GetLayerByName(Map->fInfo.ogr.ds, Map->fInfo.ogr.layer_name);
749 if (Map->fInfo.ogr.layer == NULL) {
750 OGR_DS_Destroy(Map->fInfo.ogr.ds);
751 Map->fInfo.ogr.ds = NULL;
752 G_warning(_("Unable to open OGR layer <%s>"),
753 Map->fInfo.ogr.layer_name);
754 return -1;
755 }
756 }
757 }
758
759 /* get fid column */
760 ogr_fid_col = G_store(OGR_L_GetFIDColumn(Map->fInfo.ogr.layer));
761 G_debug(3, "Using FID column <%s> in OGR DB", ogr_fid_col);
762 Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name,
763 Map->fInfo.ogr.layer_name, ogr_fid_col,
764 Map->fInfo.ogr.dsn, "ogr");
765 #else
766 dbDriver *driver;
767 dbCursor cursor;
768 dbString sql;
769 int FID = 0, OGC_FID = 0, OGR_FID = 0, GID = 0;
770
771 G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
772
773 /* FID is not available for all OGR drivers */
774 db_init_string(&sql);
775
776 driver = db_start_driver_open_database("ogr", Map->fInfo.ogr.dsn);
777
778 if (driver == NULL) {
779 G_warning(_("Unable to open OGR DBMI driver"));
780 return -1;
781 }
782
783 /* this is a bit stupid, but above FID auto-detection doesn't work yet...: */
784 db_auto_print_errors(0);
785 sprintf(buf, "select FID from %s where FID > 0",
786 Map->fInfo.ogr.layer_name);
787 db_set_string(&sql, buf);
788
789 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
790 DB_OK) {
791 /* FID not available, so we try ogc_fid */
792 G_debug(3, "Failed. Now searching for ogc_fid column in OGR DB");
793 sprintf(buf, "select ogc_fid from %s where ogc_fid > 0",
794 Map->fInfo.ogr.layer_name);
795 db_set_string(&sql, buf);
796
797 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
798 DB_OK) {
799 /* Neither FID nor ogc_fid available, so we try ogr_fid */
800 G_debug(3,
801 "Failed. Now searching for ogr_fid column in OGR DB");
802 sprintf(buf, "select ogr_fid from %s where ogr_fid > 0",
803 Map->fInfo.ogr.layer_name);
804 db_set_string(&sql, buf);
805
806 if (db_open_select_cursor
807 (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
808 /* Neither FID nor ogc_fid available, so we try gid */
809 G_debug(3,
810 "Failed. Now searching for gid column in OGR DB");
811 sprintf(buf, "select gid from %s where gid > 0",
812 Map->fInfo.ogr.layer_name);
813 db_set_string(&sql, buf);
814
815 if (db_open_select_cursor
816 (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
817 /* neither FID nor ogc_fid nor ogr_fid nor gid available */
818 G_warning(_("All FID tests failed. Neither 'FID' nor 'ogc_fid' "
819 "nor 'ogr_fid' nor 'gid' available in OGR DB table"));
820 db_close_database_shutdown_driver(driver);
821 return 0;
822 }
823 else
824 GID = 1;
825 }
826 else
827 OGR_FID = 1;
828 }
829 else
830 OGC_FID = 1;
831 }
832 else
833 FID = 1;
834
835 G_debug(3, "FID: %d, OGC_FID: %d, OGR_FID: %d, GID: %d", FID, OGC_FID,
836 OGR_FID, GID);
837
838 db_close_cursor(&cursor);
839 db_close_database_shutdown_driver(driver);
840 db_auto_print_errors(1);
841
842 if (FID) {
843 G_debug(3, "Using FID column in OGR DB");
844 Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name, Map->fInfo.ogr.layer_name, "FID",
845 Map->fInfo.ogr.dsn, "ogr");
846 }
847 else {
848 if (OGC_FID) {
849 G_debug(3, "Using ogc_fid column in OGR DB");
850 Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name, Map->fInfo.ogr.layer_name,
851 "ogc_fid", Map->fInfo.ogr.dsn, "ogr");
852 }
853 else {
854 if (OGR_FID) {
855 G_debug(3, "Using ogr_fid column in OGR DB");
856 Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name, Map->fInfo.ogr.layer_name,
857 "ogr_fid", Map->fInfo.ogr.dsn, "ogr");
858 }
859 else {
860 if (GID) {
861 G_debug(3, "Using gid column in OGR DB");
862 Vect_add_dblink(dbl, 1, Map->fInfo.ogr.layer_name,
863 Map->fInfo.ogr.layer_name, "gid",
864 Map->fInfo.ogr.dsn, "ogr");
865 }
866 }
867 }
868 }
869 #endif /* GDAL_VERSION_NUM > 1320 && HAVE_OGR */
870 return 1;
871 #endif /* HAVE_GDAL */
872 }
873
read_dblinks_pg(struct Map_info * Map)874 static int read_dblinks_pg(struct Map_info *Map)
875 {
876 #ifdef HAVE_POSTGRES
877 char *name;
878 struct dblinks *dbl;
879 struct Format_info_pg *pg_info;
880
881 dbl = Map->dblnk;
882 pg_info = &(Map->fInfo.pg);
883
884 if (!pg_info->fid_column) {
885 G_warning(_("Feature table <%s> has no primary key defined. "
886 "Unable to define DB links."), pg_info->table_name);
887 return -1;
888 }
889 G_debug(3, "Using FID column <%s>", pg_info->fid_column);
890
891 name = NULL;
892 if (G_strcasecmp(pg_info->schema_name, "public") != 0)
893 G_asprintf(&name, "%s.%s", pg_info->schema_name,
894 pg_info->table_name);
895 else
896 name = pg_info->table_name;
897
898 Vect_add_dblink(dbl, 1, name, name,
899 pg_info->fid_column,
900 pg_info->db_name, "pg");
901 if (name != pg_info->table_name)
902 G_free(name);
903 return 1;
904 #else
905 G_warning(_("GRASS not compiled with PostgreSQL support"));
906 return -1;
907 #endif
908 }
909
910 /*!
911 \brief Read dblinks to existing structure.
912
913 Variables are not substituted by values.
914
915 \param Map pointer to Map_info structure
916
917 \return number of links read
918 \return -1 on error
919 */
Vect_read_dblinks(struct Map_info * Map)920 int Vect_read_dblinks(struct Map_info *Map)
921 {
922 G_debug(1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name,
923 Map->mapset);
924
925 Vect_reset_dblinks(Map->dblnk);
926
927 if (Map->format == GV_FORMAT_NATIVE) {
928 return read_dblinks_nat(Map);
929 }
930 else if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_OGR_DIRECT) {
931 return read_dblinks_ogr(Map);
932 }
933 else if (Map->format == GV_FORMAT_POSTGIS) {
934 return read_dblinks_pg(Map);
935 }
936 else {
937 G_fatal_error(_("Unknown vector map format"));
938 }
939
940 return -1;
941 }
942
943 /*!
944 \brief Write dblinks to file
945
946 \param Map pointer to Map_info structure
947
948 \return 0 on success
949 \return -1 on error
950 */
Vect_write_dblinks(struct Map_info * Map)951 int Vect_write_dblinks(struct Map_info *Map)
952 {
953 int i;
954 FILE *fd;
955 char path[GPATH_MAX], buf[1024];
956 struct dblinks *dbl;
957
958 if (Map->format != GV_FORMAT_NATIVE)
959 /* nothing to write for non-native formats */
960 return 0;
961
962 G_debug(1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name,
963 Map->mapset);
964
965 dbl = Map->dblnk;
966
967 Vect__get_path(path, Map);
968 fd = G_fopen_new(path, GV_DBLN_ELEMENT);
969 if (fd == NULL) { /* This may be correct, no tables defined */
970 G_warning(_("Unable to create database definition file for vector map <%s>"),
971 Vect_get_name(Map));
972 return -1;
973 }
974
975 for (i = 0; i < dbl->n_fields; i++) {
976 if (dbl->field[i].name != NULL)
977 sprintf(buf, "%d/%s", dbl->field[i].number, dbl->field[i].name);
978 else
979 sprintf(buf, "%d", dbl->field[i].number);
980
981 fprintf(fd, "%s|%s|%s|%s|%s\n", buf, dbl->field[i].table,
982 dbl->field[i].key, dbl->field[i].database,
983 dbl->field[i].driver);
984 G_debug(1, "%s|%s|%s|%s|%s", buf, dbl->field[i].table,
985 dbl->field[i].key, dbl->field[i].database,
986 dbl->field[i].driver);
987 }
988 fclose(fd);
989
990 G_debug(1, "Dblinks written");
991
992 return 0;
993 }
994
995 /*!
996 \brief Substitute variable in string
997
998 \param in current string
999 \param Map pointer to Map_info structure
1000
1001 \return pointer to new string
1002 */
Vect_subst_var(const char * in,const struct Map_info * Map)1003 char *Vect_subst_var(const char *in, const struct Map_info *Map)
1004 {
1005 char *c;
1006 char buf[1000], str[1000];
1007
1008 G_debug(3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in,
1009 Map->name, Map->mapset);
1010
1011 #ifdef __MINGW32__
1012 char *cin;
1013 cin = G_str_replace(in, "/", "\\");
1014 strcpy(str, cin);
1015 G_free(cin);
1016 #else
1017 strcpy(str, in);
1018 #endif
1019
1020 strcpy(buf, str);
1021 c = (char *)strstr(buf, "$GISDBASE");
1022 if (c != NULL) {
1023 *c = '\0';
1024 sprintf(str, "%s%s%s", buf, Map->gisdbase, c + 9);
1025 }
1026
1027 strcpy(buf, str);
1028 c = (char *)strstr(buf, "$LOCATION_NAME");
1029 if (c != NULL) {
1030 *c = '\0';
1031 sprintf(str, "%s%s%s", buf, Map->location, c + 14);
1032 }
1033
1034 strcpy(buf, str);
1035 c = (char *)strstr(buf, "$MAPSET");
1036 if (c != NULL) {
1037 *c = '\0';
1038 sprintf(str, "%s%s%s", buf, Map->mapset, c + 7);
1039 }
1040
1041 strcpy(buf, str);
1042 c = (char *)strstr(buf, "$MAP");
1043 if (c != NULL) {
1044 *c = '\0';
1045 sprintf(str, "%s%s%s", buf, Map->name, c + 4);
1046 }
1047
1048 G_debug(3, " -> %s", str);
1049 return (G_store(str));
1050 }
1051
1052 /*!
1053 \brief Rewrite 'dbln' file
1054
1055 Should be used by GRASS modules which update database tables, so
1056 that other applications know that tables were changed and can reload
1057 data.
1058
1059 \param Map pointer to Map_info structure
1060 */
Vect_set_db_updated(struct Map_info * Map)1061 void Vect_set_db_updated(struct Map_info *Map)
1062 {
1063 if (strcmp(Map->mapset, G_mapset()) != 0 &&
1064 G_strcasecmp(Map->mapset, "ogr") != 0) {
1065 G_fatal_error(_("Bug: attempt to update map which is not in current mapset"));
1066 }
1067
1068 Vect_write_dblinks(Map);
1069 }
1070