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