00001
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <grass/glocale.h>
00028 #include <grass/gis.h>
00029 #include <grass/dbmi.h>
00030 #include <grass/Vect.h>
00031
00032 #include <gdal_version.h>
00033
00041 struct dblinks *Vect_new_dblinks_struct(void)
00042 {
00043 struct dblinks *p;
00044
00045 p = (struct dblinks *)G_malloc(sizeof(struct dblinks));
00046
00047 if (p) {
00048 p->alloc_fields = p->n_fields = 0;
00049 p->field = NULL;
00050 }
00051
00052 return p;
00053 }
00054
00062 void Vect_reset_dblinks(struct dblinks *p)
00063 {
00064 p->n_fields = 0;
00065 }
00066
00081 int
00082 Vect_map_add_dblink(struct Map_info *Map, int number, const char *name,
00083 const char *table, const char *key, const char *db,
00084 const char *driver)
00085 {
00086 int ret;
00087
00088 if (number == 0) {
00089 G_warning(_("Layer number must be 1 or greater"));
00090 return -1;
00091 }
00092
00093 if (Map->mode != GV_MODE_WRITE && Map->mode != GV_MODE_RW) {
00094 G_warning(_("Unable to add database link, map is not opened in WRITE mode"));
00095 return -1;
00096 }
00097
00098 ret = Vect_add_dblink(Map->dblnk, number, name, table, key, db, driver);
00099 if (ret == -1) {
00100 G_warning(_("Unable to add database link"));
00101 return -1;
00102 }
00103
00104 ret = Vect_write_dblinks(Map);
00105 if (ret == -1) {
00106 G_warning(_("Unable to write database links"));
00107 return -1;
00108 }
00109 return 0;
00110 }
00111
00121 int Vect_map_del_dblink(struct Map_info *Map, int field)
00122 {
00123 int i, j, ret;
00124 struct dblinks *links;
00125
00126 G_debug(4, "Vect_map_del_dblink() field = %d", field);
00127 links = Map->dblnk;
00128
00129 ret = -1;
00130 for (i = 0; i < links->n_fields; i++) {
00131 if (links->field[i].number == field) {
00132 for (j = i; j < links->n_fields - 1; j++) {
00133 links->field[j].number = links->field[j + 1].number;
00134 links->field[j].name = links->field[j + 1].name;
00135 links->field[j].table = links->field[j + 1].table;
00136 links->field[j].key = links->field[j + 1].key;
00137 links->field[j].database = links->field[j + 1].database;
00138 links->field[j].driver = links->field[j + 1].driver;
00139 }
00140 ret = 0;
00141 links->n_fields--;
00142 }
00143 }
00144
00145 if (ret == -1)
00146 return -1;
00147
00148
00149 ret = Vect_write_dblinks(Map);
00150 if (ret == -1) {
00151 G_warning(_("Unable to write database links"));
00152 return -1;
00153 }
00154
00155 return 0;
00156 }
00157
00167 int Vect_map_check_dblink(struct Map_info *Map, int field)
00168 {
00169 return Vect_check_dblink(Map->dblnk, field);
00170 }
00171
00181 int Vect_check_dblink(struct dblinks *p, int field)
00182 {
00183 int i;
00184
00185 G_debug(3, "Vect_check_dblink: field %d", field);
00186
00187 for (i = 0; i < p->n_fields; i++) {
00188 if (p->field[i].number == field) {
00189 return 1;
00190 }
00191 }
00192 return 0;
00193 }
00194
00195
00209 int
00210 Vect_add_dblink(struct dblinks *p, int number, const char *name,
00211 const char *table, const char *key, const char *db,
00212 const char *driver)
00213 {
00214 int ret;
00215
00216 G_debug(3, "Field number <%d>, name <%s>", number, name);
00217 ret = Vect_check_dblink(p, number);
00218 if (ret == 1) {
00219 G_warning(_("Layer number %d or name <%s> already exists"), number,
00220 name);
00221 return -1;
00222 }
00223
00224 if (p->n_fields == p->alloc_fields) {
00225 p->alloc_fields += 10;
00226 p->field = (struct field_info *)G_realloc((void *)p->field,
00227 p->alloc_fields *
00228 sizeof(struct field_info));
00229 }
00230
00231 p->field[p->n_fields].number = number;
00232
00233 if (name != NULL)
00234 p->field[p->n_fields].name = G_store(name);
00235 else
00236 p->field[p->n_fields].name = NULL;
00237
00238 if (table != NULL)
00239 p->field[p->n_fields].table = G_store(table);
00240 else
00241 p->field[p->n_fields].table = NULL;
00242
00243 if (key != NULL)
00244 p->field[p->n_fields].key = G_store(key);
00245 else
00246 p->field[p->n_fields].key = NULL;
00247
00248 if (db != NULL)
00249 p->field[p->n_fields].database = G_store(db);
00250 else
00251 p->field[p->n_fields].database = NULL;
00252
00253 if (driver != NULL)
00254 p->field[p->n_fields].driver = G_store(driver);
00255 else
00256 p->field[p->n_fields].driver = NULL;
00257
00258 p->n_fields++;
00259
00260 return 0;
00261 }
00262
00273 struct field_info
00274 *Vect_default_field_info(struct Map_info *Map,
00275 int field, const char *field_name, int type)
00276 {
00277 struct field_info *fi;
00278 char buf[1000], buf2[1000];
00279 const char *schema;
00280 const char *drv, *db;
00281 dbConnection connection;
00282
00283 G_debug(1, "Vect_default_field_info(): map = %s field = %d", Map->name,
00284 field);
00285
00286 db_get_connection(&connection);
00287 drv = G__getenv2("DB_DRIVER", G_VAR_MAPSET);
00288 db = G__getenv2("DB_DATABASE", G_VAR_MAPSET);
00289
00290 G_debug(2, "drv = %s db = %s", drv, db);
00291
00292
00293 if (!connection.driverName && !connection.databaseName) {
00294
00295 db_set_default_connection();
00296 db_get_connection(&connection);
00297
00298 G_warning(_("Default driver / database set to:\n"
00299 "driver: %s\ndatabase: %s"), connection.driverName,
00300 connection.databaseName);
00301 }
00302
00303
00304 else if (!connection.driverName) {
00305 G_fatal_error(_("Default driver is not set"));
00306 }
00307 else if (!connection.databaseName) {
00308 G_fatal_error(_("Default database is not set"));
00309 }
00310
00311 drv = connection.driverName;
00312 db = connection.databaseName;
00313
00314 fi = (struct field_info *)G_malloc(sizeof(struct field_info));
00315
00316 fi->number = field;
00317 if (field_name != NULL)
00318 fi->name = G_store(field_name);
00319 else
00320 fi->name = NULL;
00321
00322
00323 if (type == GV_1TABLE) {
00324 sprintf(buf, "%s", Map->name);
00325 }
00326 else {
00327 if (field_name != NULL && strlen(field_name) > 0)
00328 sprintf(buf, "%s_%s", Map->name, field_name);
00329 else
00330 sprintf(buf, "%s_%d", Map->name, field);
00331 }
00332
00333 schema = connection.schemaName;
00334 if (schema && strlen(schema) > 0) {
00335 sprintf(buf2, "%s.%s", schema, buf);
00336 fi->table = G_store(buf2);
00337 }
00338 else {
00339 fi->table = G_store(buf);
00340 }
00341
00342 fi->key = G_store("cat");
00343 fi->database = G_store(db);
00344 fi->driver = G_store(drv);
00345
00346 return (fi);
00347 }
00348
00360 struct field_info *Vect_get_dblink(struct Map_info *Map, int link)
00361 {
00362 struct field_info *fi;
00363
00364 G_debug(1, "Vect_get_dblink(): link = %d", link);
00365
00366 if (link >= Map->dblnk->n_fields) {
00367 G_warning(_("Requested dblink %d, maximum link number %d"), link,
00368 Map->dblnk->n_fields - 1);
00369 return NULL;
00370 }
00371
00372 fi = (struct field_info *)malloc(sizeof(struct field_info));
00373 fi->number = Map->dblnk->field[link].number;
00374
00375 if (Map->dblnk->field[link].name != NULL)
00376 fi->name = G_store(Map->dblnk->field[link].name);
00377 else
00378 fi->name = NULL;
00379
00380 fi->table = G_store(Map->dblnk->field[link].table);
00381 fi->key = G_store(Map->dblnk->field[link].key);
00382 fi->database = Vect_subst_var(Map->dblnk->field[link].database, Map);
00383 fi->driver = G_store(Map->dblnk->field[link].driver);
00384
00385 return fi;
00386 }
00387
00400 struct field_info *Vect_get_field(struct Map_info *Map, int field)
00401 {
00402 int i;
00403 struct field_info *fi = NULL;
00404
00405 G_debug(1, "Vect_get_field(): field = %d", field);
00406
00407 for (i = 0; i < Map->dblnk->n_fields; i++) {
00408 if (Map->dblnk->field[i].number == field) {
00409 fi = Vect_get_dblink(Map, i);
00410 break;
00411 }
00412 }
00413
00414 return fi;
00415 }
00416
00427 int Vect_read_dblinks(struct Map_info *Map)
00428 {
00429 int ndef;
00430 FILE *fd;
00431 char file[1024], buf[2001];
00432 char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
00433 int fld;
00434 char *c;
00435 int row, rule;
00436 struct dblinks *dbl;
00437
00438 G_debug(1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name,
00439 Map->mapset);
00440
00441 dbl = Map->dblnk;
00442 Vect_reset_dblinks(dbl);
00443
00444 G_debug(3, "Searching for FID column in OGR DB");
00445 if (Map->format == GV_FORMAT_OGR) {
00446
00447 #if GDAL_VERSION_NUM > 1320
00448 int layer, nLayers;
00449 OGRDataSourceH Ogr_ds;
00450 OGRLayerH Ogr_layer = NULL;
00451 OGRFeatureDefnH Ogr_featuredefn;
00452 char ogr_fid_col[1024];
00453
00454
00455 G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
00456
00457
00458 OGRRegisterAll();
00459
00460
00461 Ogr_ds = OGROpen(Map->fInfo.ogr.dsn, FALSE, NULL);
00462 if (Ogr_ds == NULL)
00463 G_fatal_error("Cannot open OGR data source '%s'",
00464 Map->fInfo.ogr.dsn);
00465 Map->fInfo.ogr.ds = Ogr_ds;
00466
00467
00468 layer = -1;
00469 nLayers = OGR_DS_GetLayerCount(Ogr_ds);
00470
00471 G_debug(3, "%d layers (maps) found in data source", nLayers);
00472
00473 G_debug(3, "Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
00474 Ogr_layer = OGR_DS_GetLayerByName(Ogr_ds, Map->fInfo.ogr.layer_name);
00475 if (Ogr_layer == NULL) {
00476 OGR_DS_Destroy(Ogr_ds);
00477 G_fatal_error("Cannot open layer '%s'",
00478 Map->fInfo.ogr.layer_name);
00479 }
00480 Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
00481 G_debug(3, "layer %s, FID col name: %s",
00482 OGR_FD_GetName(Ogr_featuredefn),
00483 OGR_L_GetFIDColumn(Ogr_layer));
00484 Map->fInfo.ogr.layer = Ogr_layer;
00485 G_debug(3, "OGR Map->fInfo.ogr.layer %p opened",
00486 Map->fInfo.ogr.layer);
00487
00488
00489 sprintf(ogr_fid_col, "%s", OGR_L_GetFIDColumn(Map->fInfo.ogr.layer));
00490 G_debug(3, "Using FID column <%s> in OGR DB", ogr_fid_col);
00491 Vect_add_dblink(dbl, 1, NULL, Map->fInfo.ogr.layer_name, ogr_fid_col,
00492 Map->fInfo.ogr.dsn, "ogr");
00493 #else
00494 dbDriver *driver;
00495 dbCursor cursor;
00496 dbString sql;
00497 int FID = 0, OGC_FID = 0, OGR_FID = 0, GID = 0;
00498
00499 G_debug(3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
00500
00501
00502 db_init_string(&sql);
00503
00504 driver = db_start_driver_open_database("ogr", Map->fInfo.ogr.dsn);
00505
00506 if (driver == NULL) {
00507 G_warning(_("Unable to open OGR DBMI driver"));
00508 return -1;
00509 }
00510
00511
00512 db_auto_print_errors(0);
00513 sprintf(buf, "select FID from %s where FID > 0",
00514 Map->fInfo.ogr.layer_name);
00515 db_set_string(&sql, buf);
00516
00517 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
00518 DB_OK) {
00519
00520 G_debug(3, "Failed. Now searching for ogc_fid column in OGR DB");
00521 sprintf(buf, "select ogc_fid from %s where ogc_fid > 0",
00522 Map->fInfo.ogr.layer_name);
00523 db_set_string(&sql, buf);
00524
00525 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
00526 DB_OK) {
00527
00528 G_debug(3,
00529 "Failed. Now searching for ogr_fid column in OGR DB");
00530 sprintf(buf, "select ogr_fid from %s where ogr_fid > 0",
00531 Map->fInfo.ogr.layer_name);
00532 db_set_string(&sql, buf);
00533
00534 if (db_open_select_cursor
00535 (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00536
00537 G_debug(3,
00538 "Failed. Now searching for gid column in OGR DB");
00539 sprintf(buf, "select gid from %s where gid > 0",
00540 Map->fInfo.ogr.layer_name);
00541 db_set_string(&sql, buf);
00542
00543 if (db_open_select_cursor
00544 (driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00545
00546 G_warning(_("All FID tests failed. Neither 'FID' nor 'ogc_fid' "
00547 "nor 'ogr_fid' nor 'gid' available in OGR DB table"));
00548 db_close_database_shutdown_driver(driver);
00549 return 0;
00550 }
00551 else
00552 GID = 1;
00553 }
00554 else
00555 OGR_FID = 1;
00556 }
00557 else
00558 OGC_FID = 1;
00559 }
00560 else
00561 FID = 1;
00562
00563 G_debug(3, "FID: %d, OGC_FID: %d, OGR_FID: %d, GID: %d", FID, OGC_FID,
00564 OGR_FID, GID);
00565
00566 db_close_cursor(&cursor);
00567 db_close_database_shutdown_driver(driver);
00568 db_auto_print_errors(1);
00569
00570 if (FID) {
00571 G_debug(3, "Using FID column in OGR DB");
00572 Vect_add_dblink(dbl, 1, NULL, Map->fInfo.ogr.layer_name, "FID",
00573 Map->fInfo.ogr.dsn, "ogr");
00574 }
00575 else {
00576 if (OGC_FID) {
00577 G_debug(3, "Using ogc_fid column in OGR DB");
00578 Vect_add_dblink(dbl, 1, NULL, Map->fInfo.ogr.layer_name,
00579 "ogc_fid", Map->fInfo.ogr.dsn, "ogr");
00580 }
00581 else {
00582 if (OGR_FID) {
00583 G_debug(3, "Using ogr_fid column in OGR DB");
00584 Vect_add_dblink(dbl, 1, NULL, Map->fInfo.ogr.layer_name,
00585 "ogr_fid", Map->fInfo.ogr.dsn, "ogr");
00586 }
00587 else {
00588 if (GID) {
00589 G_debug(3, "Using gid column in OGR DB");
00590 Vect_add_dblink(dbl, 1, NULL,
00591 Map->fInfo.ogr.layer_name, "gid",
00592 Map->fInfo.ogr.dsn, "ogr");
00593 }
00594 }
00595 }
00596 }
00597 #endif
00598 return (1);
00599 }
00600 else if (Map->format != GV_FORMAT_NATIVE) {
00601 G_fatal_error(_("Don't know how to read links for format %d"),
00602 Map->format);
00603 }
00604
00605 sprintf(file, "%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location,
00606 Map->mapset, GRASS_VECT_DIRECTORY, Map->name,
00607 GRASS_VECT_DBLN_ELEMENT);
00608 G_debug(1, "dbln file: %s", file);
00609
00610 fd = fopen(file, "r");
00611 if (fd == NULL) {
00612 G_debug(1, "Cannot open vector database definition file");
00613 return (-1);
00614 }
00615
00616 row = 0;
00617 rule = 0;
00618 while (G_getl2(buf, 2000, fd)) {
00619 row++;
00620 G_chop(buf);
00621 G_debug(1, "dbln: %s", buf);
00622
00623 c = (char *)strchr(buf, '#');
00624 if (c != NULL)
00625 *c = '\0';
00626
00627 if (strlen(buf) == 0)
00628 continue;
00629
00630 ndef = sscanf(buf, "%s %s %s %s %s", fldstr, tab, col, db, drv);
00631
00632 if (ndef < 2 || (ndef < 5 && rule < 1)) {
00633 G_warning(_("Error in rule on row %d in %s"), row, file);
00634 continue;
00635 }
00636
00637
00638 fldname = strchr(fldstr, '/');
00639 if (fldname != NULL) {
00640 fldname[0] = 0;
00641 fldname++;
00642 }
00643 fld = atoi(fldstr);
00644
00645 Vect_add_dblink(dbl, fld, fldname, tab, col, db, drv);
00646
00647 G_debug(1,
00648 "field = %d name = %s, table = %s, key = %s, database = %s, driver = %s",
00649 fld, fldname, tab, col, db, drv);
00650
00651 rule++;
00652 }
00653 fclose(fd);
00654
00655 G_debug(1, "Dblinks read");
00656 return (rule);
00657 }
00658
00667 int Vect_write_dblinks(struct Map_info *Map)
00668 {
00669 int i;
00670 FILE *fd;
00671 char file[GPATH_MAX], buf[GPATH_MAX];
00672 struct dblinks *dbl;
00673
00674 G_debug(1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name,
00675 Map->mapset);
00676
00677 dbl = Map->dblnk;
00678
00679 sprintf(file, "%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location,
00680 Map->mapset, GRASS_VECT_DIRECTORY, Map->name,
00681 GRASS_VECT_DBLN_ELEMENT);
00682 G_debug(1, "dbln file: %s", file);
00683
00684 fd = fopen(file, "w");
00685 if (fd == NULL) {
00686 G_warning(_("Unable to open vector database definition file '%s'"),
00687 file);
00688 return (-1);
00689 }
00690
00691 for (i = 0; i < dbl->n_fields; i++) {
00692 if (dbl->field[i].name != NULL)
00693 sprintf(buf, "%d/%s", dbl->field[i].number, dbl->field[i].name);
00694 else
00695 sprintf(buf, "%d", dbl->field[i].number);
00696
00697 fprintf(fd, "%s %s %s %s %s\n", buf, dbl->field[i].table,
00698 dbl->field[i].key, dbl->field[i].database,
00699 dbl->field[i].driver);
00700 G_debug(1, "%s %s %s %s %s", buf, dbl->field[i].table,
00701 dbl->field[i].key, dbl->field[i].database,
00702 dbl->field[i].driver);
00703 }
00704 fclose(fd);
00705
00706 G_debug(1, "Dblinks written");
00707 return 0;
00708 }
00709
00718 char *Vect_subst_var(const char *in, struct Map_info *Map)
00719 {
00720 char *c;
00721 char buf[1000], str[1000];
00722
00723 G_debug(3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in,
00724 Map->name, Map->mapset);
00725
00726 strcpy(str, in);
00727
00728 strcpy(buf, str);
00729 c = (char *)strstr(buf, "$GISDBASE");
00730 if (c != NULL) {
00731 *c = '\0';
00732 sprintf(str, "%s%s%s", buf, Map->gisdbase, c + 9);
00733 }
00734
00735 strcpy(buf, str);
00736 c = (char *)strstr(buf, "$LOCATION_NAME");
00737 if (c != NULL) {
00738 *c = '\0';
00739 sprintf(str, "%s%s%s", buf, Map->location, c + 14);
00740 }
00741
00742 strcpy(buf, str);
00743 c = (char *)strstr(buf, "$MAPSET");
00744 if (c != NULL) {
00745 *c = '\0';
00746 sprintf(str, "%s%s%s", buf, Map->mapset, c + 7);
00747 }
00748
00749 strcpy(buf, str);
00750 c = (char *)strstr(buf, "$MAP");
00751 if (c != NULL) {
00752 *c = '\0';
00753 sprintf(str, "%s%s%s", buf, Map->name, c + 4);
00754 }
00755
00756 G_debug(3, " -> %s", str);
00757 return (G_store(str));
00758 }
00759
00771 void Vect_set_db_updated(struct Map_info *Map)
00772 {
00773 if (strcmp(Map->mapset, G_mapset()) != 0) {
00774 G_fatal_error(_("Bug: attempt to update map which is not in current mapset"));
00775 }
00776
00777 Vect_write_dblinks(Map);
00778 }