27 #include <grass/glocale.h>
28 #include <grass/gis.h>
29 #include <grass/dbmi.h>
30 #include <grass/Vect.h>
32 #include <gdal_version.h>
49 p = (
struct dblinks *)G_malloc(
sizeof(
struct dblinks));
52 p->alloc_fields = p->n_fields = 0;
87 const char *table,
const char *key,
const char *db,
93 G_warning(_(
"Layer number must be 1 or greater"));
97 if (Map->mode != GV_MODE_WRITE && Map->mode != GV_MODE_RW) {
98 G_warning(_(
"Unable to add database link, map is not opened in WRITE mode"));
102 ret =
Vect_add_dblink(Map->dblnk, number, name, table, key, db, driver);
104 G_warning(_(
"Unable to add database link"));
110 G_warning(_(
"Unable to write database links"));
128 struct dblinks *links;
130 G_debug(4,
"Vect_map_del_dblink() field = %d", field);
134 for (i = 0; i < links->n_fields; i++) {
135 if (links->field[i].number == field) {
136 for (j = i; j < links->n_fields - 1; j++) {
137 links->field[j].number = links->field[j + 1].number;
138 links->field[j].name = links->field[j + 1].name;
139 links->field[j].table = links->field[j + 1].table;
140 links->field[j].key = links->field[j + 1].key;
141 links->field[j].database = links->field[j + 1].database;
142 links->field[j].driver = links->field[j + 1].driver;
155 G_warning(_(
"Unable to write database links"));
189 G_debug(3,
"Vect_check_dblink: field %d", field);
191 for (i = 0; i < p->n_fields; i++) {
192 if (p->field[i].number == field) {
215 const char *table,
const char *key,
const char *db,
220 G_debug(3,
"Field number <%d>, name <%s>", number, name);
223 G_warning(_(
"Layer number %d or name <%s> already exists"), number,
228 if (p->n_fields == p->alloc_fields) {
229 p->alloc_fields += 10;
230 p->field = (
struct field_info *)G_realloc((
void *)p->field,
232 sizeof(
struct field_info));
235 p->field[p->n_fields].number = number;
238 p->field[p->n_fields].name =
G_store(name);
240 p->field[p->n_fields].name =
NULL;
243 p->field[p->n_fields].table =
G_store(table);
245 p->field[p->n_fields].table =
NULL;
248 p->field[p->n_fields].key =
G_store(key);
250 p->field[p->n_fields].key =
NULL;
253 p->field[p->n_fields].database =
G_store(db);
255 p->field[p->n_fields].database =
NULL;
258 p->field[p->n_fields].driver =
G_store(driver);
260 p->field[p->n_fields].driver =
NULL;
279 int field,
const char *field_name,
int type)
281 struct field_info *fi;
284 const char *drv, *db;
285 dbConnection connection;
287 G_debug(1,
"Vect_default_field_info(): map = %s field = %d", Map->name,
294 G_debug(2,
"drv = %s db = %s", drv, db);
297 if (!connection.driverName && !connection.databaseName) {
302 G_warning(_(
"Default driver / database set to:\n"
303 "driver: %s\ndatabase: %s"), connection.driverName,
304 connection.databaseName);
308 else if (!connection.driverName) {
311 else if (!connection.databaseName) {
315 drv = connection.driverName;
316 db = connection.databaseName;
318 fi = (
struct field_info *)G_malloc(
sizeof(
struct field_info));
321 if (field_name !=
NULL)
322 fi->name =
G_store(field_name);
327 if (type == GV_1TABLE) {
331 if (field_name !=
NULL && strlen(field_name) > 0)
332 sprintf(buf,
"%s_%s", Map->name, field_name);
334 sprintf(buf,
"%s_%d", Map->name, field);
337 schema = connection.schemaName;
338 if (schema && strlen(schema) > 0) {
339 sprintf(buf2,
"%s.%s", schema, buf);
366 struct field_info *fi;
368 G_debug(1,
"Vect_get_dblink(): link = %d", link);
370 if (link >= Map->dblnk->n_fields) {
371 G_warning(_(
"Requested dblink %d, maximum link number %d"), link,
372 Map->dblnk->n_fields - 1);
376 fi = (
struct field_info *)
malloc(
sizeof(
struct field_info));
377 fi->number = Map->dblnk->field[link].number;
379 if (Map->dblnk->field[link].name !=
NULL)
380 fi->name =
G_store(Map->dblnk->field[link].name);
384 fi->table =
G_store(Map->dblnk->field[link].table);
385 fi->key =
G_store(Map->dblnk->field[link].key);
386 fi->database =
Vect_subst_var(Map->dblnk->field[link].database, Map);
387 fi->driver =
G_store(Map->dblnk->field[link].driver);
407 struct field_info *fi =
NULL;
409 G_debug(1,
"Vect_get_field(): field = %d", field);
411 for (i = 0; i < Map->dblnk->n_fields; i++) {
412 if (Map->dblnk->field[i].number == field) {
435 char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
443 G_debug(1,
"Vect_read_dblinks(): map = %s, mapset = %s", Map->name,
449 G_debug(3,
"Searching for FID column in OGR DB");
450 if (Map->format == GV_FORMAT_OGR) {
452 #if GDAL_VERSION_NUM > 1320 && HAVE_OGR
454 OGRDataSourceH Ogr_ds;
455 OGRLayerH Ogr_layer =
NULL;
456 OGRFeatureDefnH Ogr_featuredefn;
457 char ogr_fid_col[1024];
460 G_debug(3,
"GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
466 Ogr_ds = OGROpen(Map->fInfo.ogr.dsn,
FALSE,
NULL);
470 Map->fInfo.ogr.ds = Ogr_ds;
474 nLayers = OGR_DS_GetLayerCount(Ogr_ds);
476 G_debug(3,
"%d layers (maps) found in data source", nLayers);
478 G_debug(3,
"Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
479 Ogr_layer = OGR_DS_GetLayerByName(Ogr_ds, Map->fInfo.ogr.layer_name);
480 if (Ogr_layer ==
NULL) {
481 OGR_DS_Destroy(Ogr_ds);
483 Map->fInfo.ogr.layer_name);
485 Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
486 G_debug(3,
"layer %s, FID col name: %s",
487 OGR_FD_GetName(Ogr_featuredefn),
488 OGR_L_GetFIDColumn(Ogr_layer));
489 Map->fInfo.ogr.layer = Ogr_layer;
490 G_debug(3,
"OGR Map->fInfo.ogr.layer %p opened",
491 Map->fInfo.ogr.layer);
494 sprintf(ogr_fid_col,
"%s", OGR_L_GetFIDColumn(Map->fInfo.ogr.layer));
495 G_debug(3,
"Using FID column <%s> in OGR DB", ogr_fid_col);
497 Map->fInfo.ogr.dsn,
"ogr");
502 int FID = 0, OGC_FID = 0, OGR_FID = 0, GID = 0;
504 G_debug(3,
"GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
511 if (driver ==
NULL) {
512 G_warning(_(
"Unable to open OGR DBMI driver"));
518 sprintf(buf,
"select FID from %s where FID > 0",
519 Map->fInfo.ogr.layer_name);
525 G_debug(3,
"Failed. Now searching for ogc_fid column in OGR DB");
526 sprintf(buf,
"select ogc_fid from %s where ogc_fid > 0",
527 Map->fInfo.ogr.layer_name);
534 "Failed. Now searching for ogr_fid column in OGR DB");
535 sprintf(buf,
"select ogr_fid from %s where ogr_fid > 0",
536 Map->fInfo.ogr.layer_name);
540 (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
543 "Failed. Now searching for gid column in OGR DB");
544 sprintf(buf,
"select gid from %s where gid > 0",
545 Map->fInfo.ogr.layer_name);
549 (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
551 G_warning(_(
"All FID tests failed. Neither 'FID' nor 'ogc_fid' "
552 "nor 'ogr_fid' nor 'gid' available in OGR DB table"));
568 G_debug(3,
"FID: %d, OGC_FID: %d, OGR_FID: %d, GID: %d", FID, OGC_FID,
576 G_debug(3,
"Using FID column in OGR DB");
578 Map->fInfo.ogr.dsn,
"ogr");
582 G_debug(3,
"Using ogc_fid column in OGR DB");
584 "ogc_fid", Map->fInfo.ogr.dsn,
"ogr");
588 G_debug(3,
"Using ogr_fid column in OGR DB");
590 "ogr_fid", Map->fInfo.ogr.dsn,
"ogr");
594 G_debug(3,
"Using gid column in OGR DB");
596 Map->fInfo.ogr.layer_name,
"gid",
597 Map->fInfo.ogr.dsn,
"ogr");
605 else if (Map->format != GV_FORMAT_NATIVE) {
606 G_fatal_error(_(
"Don't know how to read links for format %d"),
610 sprintf(file,
"%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location,
611 Map->mapset, GRASS_VECT_DIRECTORY, Map->name,
612 GRASS_VECT_DBLN_ELEMENT);
613 G_debug(1,
"dbln file: %s", file);
615 fd = fopen(file,
"r");
617 G_debug(1,
"Cannot open vector database definition file");
623 while (
G_getl2(buf, 2000, fd)) {
628 c = (
char *)strchr(buf,
'#');
632 if (strlen(buf) == 0)
638 if (ntok < 2 || (ntok < 5 && rule < 1)) {
639 G_warning(_(
"Error in rule on row %d in %s"), row, file);
643 strcpy(fldstr, tokens[0]);
644 strcpy(tab, tokens[1]);
646 strcpy(col, tokens[2]);
648 strcpy(db, tokens[3]);
650 for (i=4; i < ntok-1; i++) {
652 strcat(db, tokens[i]);
655 strcpy(drv, tokens[ntok-1]);
661 fldname = strchr(fldstr,
'/');
662 if (fldname !=
NULL) {
671 "field = %d name = %s, table = %s, key = %s, database = %s, driver = %s",
672 fld, fldname, tab, col, db, drv);
694 char file[GPATH_MAX],
buf[GPATH_MAX];
697 G_debug(1,
"Vect_write_dblinks(): map = %s, mapset = %s", Map->name,
702 sprintf(file,
"%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location,
703 Map->mapset, GRASS_VECT_DIRECTORY, Map->name,
704 GRASS_VECT_DBLN_ELEMENT);
705 G_debug(1,
"dbln file: %s", file);
707 fd = fopen(file,
"w");
709 G_warning(_(
"Unable to open vector database definition file '%s'"),
714 for (i = 0; i < dbl->n_fields; i++) {
715 if (dbl->field[i].name !=
NULL)
716 sprintf(buf,
"%d/%s", dbl->field[i].number, dbl->field[i].name);
718 sprintf(buf,
"%d", dbl->field[i].number);
720 fprintf(fd,
"%s %s %s %s %s\n", buf, dbl->field[i].table,
721 dbl->field[i].key, dbl->field[i].database,
722 dbl->field[i].driver);
723 G_debug(1,
"%s %s %s %s %s", buf, dbl->field[i].table,
724 dbl->field[i].key, dbl->field[i].database,
725 dbl->field[i].driver);
744 char buf[1000], str[1000];
746 G_debug(3,
"Vect_subst_var(): in = %s, map = %s, mapset = %s", in,
747 Map->name, Map->mapset);
759 c = (
char *)strstr(buf,
"$GISDBASE");
762 sprintf(str,
"%s%s%s", buf, Map->gisdbase, c + 9);
766 c = (
char *)strstr(buf,
"$LOCATION_NAME");
769 sprintf(str,
"%s%s%s", buf, Map->location, c + 14);
773 c = (
char *)strstr(buf,
"$MAPSET");
776 sprintf(str,
"%s%s%s", buf, Map->mapset, c + 7);
780 c = (
char *)strstr(buf,
"$MAP");
783 sprintf(str,
"%s%s%s", buf, Map->name, c + 4);
803 if (strcmp(Map->mapset,
G_mapset()) != 0) {
804 G_fatal_error(_(
"Bug: attempt to update map which is not in current mapset"));
dbDriver * db_start_driver_open_database(const char *drvname, const char *dbname)
Open driver/database connection.
char * G_mapset(void)
current mapset name
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
int db_close_cursor(dbCursor *cursor)
Close cursor.
void G_free(void *buf)
Free allocated memory.
struct field_info * Vect_get_field(struct Map_info *Map, int field)
Get information about link to database.
char * G_store(const char *s)
Copy string to allocated memory.
int G_free_tokens(char **tokens)
Free memory allocated to tokens.
char * Vect_subst_var(const char *in, struct Map_info *Map)
Substitute variable in string.
int db_close_database_shutdown_driver(dbDriver *driver)
Close driver/database connection.
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
void db_auto_print_errors(int flag)
char * G_chop(char *line)
Chop leading and trailing white spaces:
char * G__getenv2(const char *name, int loc)
Get environment variable from specific place.
int Vect_check_dblink(struct dblinks *p, int field)
Check if db connection exists in dblinks structure.
int db_get_connection(dbConnection *connection)
get default db connection settings
int G_number_of_tokens(char **tokens)
Return number of tokens.
int G_getl2(char *buf, int n, FILE *fd)
gets a line of text from a file of any pedigree
int Vect_add_dblink(struct dblinks *p, int number, const char *name, const char *table, const char *key, const char *db, const char *driver)
Add new db connection to dblinks structure.
int 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)
Add new db connection to Map_info structure.
char * G_str_replace(char *buffer, const char *old_str, const char *new_str)
Replace all occurencies of old_str in buffer with new_str.
int Vect_write_dblinks(struct Map_info *Map)
Write dblinks to file.
int db_set_default_connection(void)
Sets up database connection settings using GRASS default from dbmi.h.
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
struct field_info * Vect_get_dblink(struct Map_info *Map, int link)
Get information about link to database.
int Vect_map_check_dblink(struct Map_info *Map, int field)
Check if db connection exists in dblinks structure.
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
int G_debug(int level, const char *msg,...)
Print debugging message.
int db_set_string(dbString *x, const char *s)
struct field_info * Vect_default_field_info(struct Map_info *Map, int field, const char *field_name, int type)
Get default information about link to database for new dblink.
struct dblinks * Vect_new_dblinks_struct(void)
Create and init new dblinks ctructure.
int Vect_map_del_dblink(struct Map_info *Map, int field)
Delete db connection from Map_info structure.
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
int Vect_read_dblinks(struct Map_info *Map)
Read dblinks to existing structure.
void Vect_reset_dblinks(struct dblinks *p)
Reset dblinks structure.
int db_open_select_cursor(dbDriver *driver, dbString *select, dbCursor *cursor, int mode)
Open select cursor.
void Vect_set_db_updated(struct Map_info *Map)
Rewrite 'dbln' file.
void db_init_string(dbString *x)