00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <grass/glocale.h>
00023 #include <grass/gis.h>
00024 #include <grass/dbmi.h>
00025 #include <grass/Vect.h>
00026
00027 #include <gdal_version.h>
00028
00035 struct dblinks *
00036 Vect_new_dblinks_struct ( void )
00037 {
00038 struct dblinks *p;
00039
00040 p = (struct dblinks *) G_malloc (sizeof (struct dblinks));
00041
00042 if (p) {
00043 p->alloc_fields = p->n_fields = 0;
00044 p->field = NULL;
00045 }
00046
00047 return p;
00048 }
00049
00056 void
00057 Vect_reset_dblinks ( struct dblinks *p )
00058 {
00059 p->n_fields = 0;
00060 }
00061
00069 int
00070 Vect_map_add_dblink ( struct Map_info *Map, int number, char *name, char *table, char *key,
00071 char *db, char *driver )
00072 {
00073 int ret;
00074
00075 if (number == 0) {
00076 G_warning (_("Field number must be 1 or greater."));
00077 return -1;
00078 }
00079
00080 if (Map->mode != GV_MODE_WRITE && Map->mode != GV_MODE_RW) {
00081 G_warning (_("Cannot add database link, map is not opened in WRITE mode."));
00082 return -1;
00083 }
00084
00085 ret = Vect_add_dblink ( Map->dblnk, number, name, table, key, db, driver );
00086 if ( ret == -1 ) {
00087 G_warning (_("Cannot add database link."));
00088 return -1;
00089 }
00090
00091 ret = Vect_write_dblinks ( Map );
00092 if ( ret == -1 ) {
00093 G_warning (_("Cannot write database links."));
00094 return -1;
00095 }
00096 return 0;
00097 }
00098
00105 int
00106 Vect_map_del_dblink ( struct Map_info *Map, int field)
00107 {
00108 int i, j, ret;
00109 struct dblinks *links;
00110
00111 G_debug(4, "Vect_map_del_dblink() field = %d", field);
00112 links = Map->dblnk;
00113
00114 ret = -1;
00115 for (i = 0; i < links->n_fields; i++) {
00116 if ( links->field[i].number == field ) {
00117 for (j = i; j < links->n_fields - 1; j++) {
00118 links->field[j].number = links->field[j+1].number;
00119 links->field[j].name = links->field[j+1].name;
00120 links->field[j].table = links->field[j+1].table;
00121 links->field[j].key = links->field[j+1].key;
00122 links->field[j].database = links->field[j+1].database;
00123 links->field[j].driver = links->field[j+1].driver;
00124 }
00125 ret = 0;
00126 links->n_fields--;
00127 }
00128 }
00129
00130 if ( ret == -1 )
00131 return -1;
00132
00133
00134 ret = Vect_write_dblinks ( Map );
00135 if ( ret == -1 ) {
00136 G_warning (_("Cannot write database links."));
00137 return -1;
00138 }
00139
00140 return 0;
00141 }
00142
00149 int
00150 Vect_map_check_dblink ( struct Map_info *Map, int field )
00151 {
00152 return Vect_check_dblink ( Map->dblnk, field );
00153 }
00154
00161 int
00162 Vect_check_dblink ( struct dblinks *p, int field )
00163 {
00164 int i;
00165
00166 G_debug(3,"Vect_check_dblink: field %d", field);
00167
00168 for (i = 0; i < p->n_fields; i++) {
00169 if ( p->field[i].number == field ) {
00170 return 1;
00171 }
00172 }
00173 return 0;
00174 }
00175
00176
00184 int
00185 Vect_add_dblink ( struct dblinks *p, int number, char *name, char *table, char *key, char *db, char *driver )
00186 {
00187 int ret;
00188
00189 G_debug (3, "Field number <%d>, name <%s>", number, name);
00190 ret = Vect_check_dblink ( p, number );
00191 if ( ret == 1 ) {
00192 G_warning (_("Field number <%d> or name <%s> already exists"), number, name);
00193 return -1;
00194 }
00195
00196 if ( p->n_fields == p->alloc_fields ) {
00197 p->alloc_fields += 10;
00198 p->field = ( struct field_info *) G_realloc ( (void *) p->field,
00199 p->alloc_fields * sizeof (struct field_info) );
00200 }
00201
00202 p->field[p->n_fields].number = number;
00203
00204 if ( name != NULL ) p->field[p->n_fields].name = G_store ( name );
00205 else p->field[p->n_fields].name = NULL;
00206
00207 if ( table != NULL ) p->field[p->n_fields].table = G_store ( table );
00208 else p->field[p->n_fields].table = NULL;
00209
00210 if ( key != NULL ) p->field[p->n_fields].key = G_store ( key );
00211 else p->field[p->n_fields].key = NULL;
00212
00213 if ( db != NULL ) p->field[p->n_fields].database = G_store ( db );
00214 else p->field[p->n_fields].database = NULL;
00215
00216 if ( driver != NULL ) p->field[p->n_fields].driver = G_store ( driver );
00217 else p->field[p->n_fields].driver = NULL;
00218
00219 p->n_fields++;
00220
00221 return 0;
00222 }
00223
00230 struct field_info
00231 *Vect_default_field_info (
00232 struct Map_info *Map,
00233 int field,
00234 char *field_name,
00235 int type )
00236 {
00237 struct field_info *fi;
00238 char buf[1000], buf2[1000];
00239 char *schema;
00240 char *drv, *db;
00241 dbConnection connection;
00242
00243 G_debug (1, "Vect_default_field_info(): map = %s field = %d", Map->name, field);
00244
00245 db_get_connection( &connection );
00246 drv = G__getenv2 ( "DB_DRIVER", G_VAR_MAPSET );
00247 db = G__getenv2 ( "DB_DATABASE", G_VAR_MAPSET );
00248
00249 G_debug (2, "drv = %s db = %s", drv, db );
00250
00251 if ( !connection.driverName && !connection.databaseName ) {
00252 G_warning ( _("Default driver / database set to:\n"
00253 "driver: dbf\ndatabase: $GISDBASE/$LOCATION_NAME/$MAPSET/dbf/") );
00254
00255 connection.driverName = "dbf";
00256 connection.databaseName = "$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/";
00257 db_set_connection( &connection );
00258
00259 sprintf ( buf, "%s/%s/%s/dbf", Map->gisdbase, Map->location, Map->mapset );
00260 G__make_mapset_element ( "dbf" );
00261 } else if ( !connection.driverName ) {
00262 G_fatal_error ( _("Default driver is not set") );
00263 } else if ( !connection.databaseName ) {
00264 G_fatal_error ( _("Default database is not set") );
00265 }
00266 drv = connection.driverName;
00267 db = connection.databaseName;
00268
00269 fi = (struct field_info *) G_malloc( sizeof(struct field_info) );
00270
00271 fi->number = field;
00272 if ( field_name != NULL ) fi->name = G_store ( field_name );
00273 else fi->name = NULL;
00274
00275
00276 if ( type == GV_1TABLE ) {
00277 sprintf ( buf, "%s", Map->name);
00278 } else {
00279 if ( field_name != NULL && strlen ( field_name ) > 0 )
00280 sprintf ( buf, "%s_%s", Map->name, field_name );
00281 else
00282 sprintf ( buf, "%s_%d", Map->name, field );
00283 }
00284
00285 schema = connection.schemaName;
00286 if ( schema && strlen(schema) > 0 ) {
00287 sprintf ( buf2, "%s.%s", schema, buf );
00288 fi->table = G_store ( buf2 );
00289 } else {
00290 fi->table = G_store ( buf );
00291 }
00292
00293 fi->key = G_store ( "cat" );
00294 fi->database = G_store( db );
00295 fi->driver = G_store( drv );
00296
00297 return (fi);
00298 }
00299
00307 struct field_info
00308 *Vect_get_dblink ( struct Map_info *Map, int link )
00309 {
00310 struct field_info *fi;
00311
00312 G_debug (1, "Vect_get_dblink(): link = %d", link);
00313
00314 if ( link >= Map->dblnk->n_fields ) {
00315 G_warning ( _("Requested dblink %d, maximum link number %d"), link, Map->dblnk->n_fields - 1 );
00316 return NULL;
00317 }
00318
00319 fi = (struct field_info *) malloc( sizeof(struct field_info) );
00320 fi->number = Map->dblnk->field[link].number;
00321
00322 if ( Map->dblnk->field[link].name != NULL )
00323 fi->name = G_store ( Map->dblnk->field[link].name );
00324 else
00325 fi->name = NULL;
00326
00327 fi->table = G_store ( Map->dblnk->field[link].table );
00328 fi->key = G_store ( Map->dblnk->field[link].key );
00329 fi->database = Vect_subst_var ( Map->dblnk->field[link].database, Map );
00330 fi->driver = G_store ( Map->dblnk->field[link].driver );
00331
00332 return fi;
00333 }
00334
00342 struct field_info
00343 *Vect_get_field ( struct Map_info *Map, int field )
00344 {
00345 int i;
00346 struct field_info *fi = NULL;
00347
00348 G_debug (1, "Vect_get_field(): field = %d", field);
00349
00350 for ( i = 0; i < Map->dblnk->n_fields; i++ ) {
00351 if ( Map->dblnk->field[i].number == field ) {
00352 fi = Vect_get_dblink ( Map, i );
00353 break;
00354 }
00355 }
00356
00357 return fi;
00358 }
00359
00366 int
00367 Vect_read_dblinks ( struct Map_info *Map )
00368 {
00369 int ndef;
00370 FILE *fd;
00371 char file[1024], buf[2001];
00372 char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
00373 int fld;
00374 char *c;
00375 int row, rule;
00376 struct dblinks *dbl;
00377
00378 G_debug (1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name, Map->mapset);
00379
00380 dbl = Map->dblnk;
00381 Vect_reset_dblinks ( dbl );
00382
00383 G_debug (3, "Searching for FID column in OGR DB");
00384 if ( Map->format == GV_FORMAT_OGR ) {
00385
00386 #if GDAL_VERSION_NUM > 1320
00387 int i, layer, nLayers;
00388 OGRDataSourceH Ogr_ds;
00389 OGRLayerH Ogr_layer=NULL;
00390 OGRFeatureDefnH Ogr_featuredefn;
00391 char ogr_fid_col[1024];
00392
00393
00394 G_debug (3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
00395
00396
00397 OGRRegisterAll ();
00398
00399
00400 Ogr_ds = OGROpen (Map->fInfo.ogr.dsn, FALSE, NULL);
00401 if (Ogr_ds == NULL)
00402 G_fatal_error ("Cannot open OGR data source '%s'", Map->fInfo.ogr.dsn);
00403 Map->fInfo.ogr.ds = Ogr_ds;
00404
00405
00406 layer = -1;
00407 nLayers = OGR_DS_GetLayerCount (Ogr_ds);
00408
00409 G_debug (3, "%d layers (maps) found in data source", nLayers);
00410
00411 G_debug (3, "Trying to open OGR layer: %s", Map->fInfo.ogr.layer_name);
00412 Ogr_layer = OGR_DS_GetLayerByName (Ogr_ds, Map->fInfo.ogr.layer_name);
00413 if (Ogr_layer == NULL) {
00414 OGR_DS_Destroy (Ogr_ds);
00415 G_fatal_error ("Cannot open layer '%s'", Map->fInfo.ogr.layer_name);
00416 }
00417 Ogr_featuredefn = OGR_L_GetLayerDefn (Ogr_layer);
00418 G_debug (3, "layer %s, FID col name: %s", OGR_FD_GetName (Ogr_featuredefn),
00419 OGR_L_GetFIDColumn( Ogr_layer ));
00420 Map->fInfo.ogr.layer = Ogr_layer;
00421 G_debug (3, "OGR Map->fInfo.ogr.layer %p opened", Map->fInfo.ogr.layer);
00422
00423
00424 sprintf ( ogr_fid_col, "%s", OGR_L_GetFIDColumn( Map->fInfo.ogr.layer ));
00425 G_debug (3, "Using FID column <%s> in OGR DB", ogr_fid_col);
00426 Vect_add_dblink ( dbl, 1, NULL, Map->fInfo.ogr.layer_name, ogr_fid_col, Map->fInfo.ogr.dsn, "ogr") ;
00427 #else
00428 dbDriver *driver;
00429 dbCursor cursor;
00430 dbString sql;
00431 int FID=0, OGC_FID=0, OGR_FID=0, GID=0;
00432
00433 G_debug (3, "GDAL_VERSION_NUM: %d", GDAL_VERSION_NUM);
00434
00435
00436 db_init_string (&sql);
00437
00438 driver = db_start_driver_open_database ( "ogr", Map->fInfo.ogr.dsn );
00439
00440 if ( driver == NULL ) {
00441 G_warning (_("Cannot open OGR DBMI driver."));
00442 return -1;
00443 }
00444
00445
00446 db_auto_print_errors(0);
00447 sprintf ( buf, "select FID from %s where FID > 0", Map->fInfo.ogr.layer_name );
00448 db_set_string ( &sql, buf );
00449
00450 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00451
00452 G_debug (3, "Failed. Now searching for ogc_fid column in OGR DB");
00453 sprintf ( buf, "select ogc_fid from %s where ogc_fid > 0", Map->fInfo.ogr.layer_name );
00454 db_set_string ( &sql, buf );
00455
00456 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00457
00458 G_debug (3, "Failed. Now searching for ogr_fid column in OGR DB");
00459 sprintf ( buf, "select ogr_fid from %s where ogr_fid > 0", Map->fInfo.ogr.layer_name );
00460 db_set_string ( &sql, buf );
00461
00462 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00463
00464 G_debug (3, "Failed. Now searching for gid column in OGR DB");
00465 sprintf ( buf, "select gid from %s where gid > 0", Map->fInfo.ogr.layer_name );
00466 db_set_string ( &sql, buf );
00467
00468 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00469
00470 G_warning ("All FID tests failed. Neither 'FID' nor 'ogc_fid' nor 'ogr_fid' nor 'gid' available in OGR DB table");
00471 db_close_database_shutdown_driver ( driver );
00472 return 0;
00473 } else
00474 GID=1;
00475 } else
00476 OGR_FID=1;
00477 } else
00478 OGC_FID=1;
00479 } else
00480 FID=1;
00481
00482 G_debug(3,"FID: %d, OGC_FID: %d, OGR_FID: %d, GID: %d",FID, OGC_FID, OGR_FID, GID);
00483
00484 db_close_cursor(&cursor);
00485 db_close_database_shutdown_driver ( driver );
00486 db_auto_print_errors(1);
00487
00488 if (FID) {
00489 G_debug (3, "Using FID column in OGR DB");
00490 Vect_add_dblink ( dbl, 1, NULL, Map->fInfo.ogr.layer_name, "FID", Map->fInfo.ogr.dsn, "ogr" ) ;
00491 } else {
00492 if (OGC_FID) {
00493 G_debug (3, "Using ogc_fid column in OGR DB");
00494 Vect_add_dblink ( dbl, 1, NULL, Map->fInfo.ogr.layer_name, "ogc_fid", Map->fInfo.ogr.dsn, "ogr" ) ;
00495 } else {
00496 if (OGR_FID) {
00497 G_debug (3, "Using ogr_fid column in OGR DB");
00498 Vect_add_dblink ( dbl, 1, NULL, Map->fInfo.ogr.layer_name, "ogr_fid", Map->fInfo.ogr.dsn, "ogr" ) ;
00499 } else {
00500 if (GID) {
00501 G_debug (3, "Using gid column in OGR DB");
00502 Vect_add_dblink ( dbl, 1, NULL, Map->fInfo.ogr.layer_name, "gid", Map->fInfo.ogr.dsn, "ogr" ) ;
00503 }
00504 }
00505 }
00506 }
00507 #endif
00508 return ( 1 );
00509 } else if ( Map->format != GV_FORMAT_NATIVE ) {
00510 G_fatal_error (_("Don't know how to read links for format %d"), Map->format );
00511 }
00512
00513 sprintf ( file, "%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location, Map->mapset, GRASS_VECT_DIRECTORY,
00514 Map->name, GRASS_VECT_DBLN_ELEMENT );
00515 G_debug (1, "dbln file: %s", file);
00516
00517 fd = fopen ( file, "r" );
00518 if ( fd == NULL ) {
00519 G_debug ( 1, "Cannot open vector database definition file");
00520 return (-1);
00521 }
00522
00523 row = 0;
00524 rule = 0;
00525 while ( G_getl2 (buf, 2000, fd) ) {
00526 row++;
00527 G_chop ( buf );
00528 G_debug (1, "dbln: %s", buf);
00529
00530 c = (char *) strchr ( buf, '#');
00531 if ( c != NULL ) *c = '\0';
00532
00533 if ( strlen(buf) == 0 ) continue;
00534
00535 ndef = sscanf ( buf, "%s %s %s %s %s", fldstr, tab, col, db, drv);
00536
00537 if ( ndef < 2 || (ndef < 5 && rule < 1 ) ) {
00538 G_warning ( _("Error in rule on row %d in %s"), row, file);
00539 continue;
00540 }
00541
00542
00543 fldname = strchr ( fldstr, '/' );
00544 if ( fldname != NULL ) {
00545 fldname[0] = 0;
00546 fldname++;
00547 }
00548 fld = atoi ( fldstr );
00549
00550 Vect_add_dblink ( dbl, fld, fldname, tab, col, db, drv );
00551
00552 G_debug (1, "field = %d name = %s, table = %s, key = %s, database = %s, driver = %s",
00553 fld, fldname, tab, col, db, drv );
00554
00555 rule++;
00556 }
00557 fclose (fd);
00558
00559 G_debug (1, "Dblinks read");
00560 return ( rule );
00561 }
00562
00569 int
00570 Vect_write_dblinks ( struct Map_info *Map )
00571 {
00572 int i;
00573 FILE *fd;
00574 char file[1024], buf[1024];
00575 struct dblinks *dbl;
00576
00577 G_debug (1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name, Map->mapset );
00578
00579 dbl = Map->dblnk;
00580
00581 sprintf ( file, "%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location, Map->mapset, GRASS_VECT_DIRECTORY,
00582 Map->name, GRASS_VECT_DBLN_ELEMENT );
00583 G_debug (1, "dbln file: %s", file);
00584
00585 fd = fopen ( file, "w" );
00586 if ( fd == NULL ) {
00587 G_warning ( "Cannot open vector database definition file: '%s'", file);
00588 return (-1);
00589 }
00590
00591 for ( i = 0; i < dbl->n_fields; i++ ) {
00592 if ( dbl->field[i].name != NULL )
00593 sprintf ( buf , "%d/%s", dbl->field[i].number, dbl->field[i].name );
00594 else
00595 sprintf ( buf , "%d", dbl->field[i].number );
00596
00597 fprintf ( fd, "%s %s %s %s %s\n", buf, dbl->field[i].table, dbl->field[i].key,
00598 dbl->field[i].database, dbl->field[i].driver );
00599 G_debug (1, "%s %s %s %s %s", buf, dbl->field[i].table, dbl->field[i].key,
00600 dbl->field[i].database, dbl->field[i].driver );
00601 }
00602 fclose (fd);
00603
00604 G_debug (1, "Dblinks written");
00605 return 0;
00606 }
00607
00614 char *
00615 Vect_subst_var ( char *in, struct Map_info *Map )
00616 {
00617 char *c;
00618 char buf[1000], str[1000];
00619
00620 G_debug (3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in, Map->name, Map->mapset);
00621
00622 strcpy ( str, in );
00623
00624 strcpy ( buf, str );
00625 c = (char *) strstr ( buf, "$GISDBASE" );
00626 if ( c != NULL ) {
00627 *c = '\0';
00628 sprintf (str, "%s%s%s", buf, Map->gisdbase, c+9);
00629 }
00630
00631 strcpy ( buf, str );
00632 c = (char *) strstr ( buf, "$LOCATION_NAME" );
00633 if ( c != NULL ) {
00634 *c = '\0';
00635 sprintf (str, "%s%s%s", buf, Map->location, c+14);
00636 }
00637
00638 strcpy ( buf, str );
00639 c = (char *) strstr ( buf, "$MAPSET" );
00640 if ( c != NULL ) {
00641 *c = '\0';
00642 sprintf (str, "%s%s%s", buf, Map->mapset, c+7);
00643 }
00644
00645 strcpy ( buf, str );
00646 c = (char *) strstr ( buf, "$MAP" );
00647 if ( c != NULL ) {
00648 *c = '\0';
00649 sprintf (str, "%s%s%s", buf, Map->name, c+4 );
00650 }
00651
00652 G_debug (3, " -> %s", str);
00653 return ( G_store(str) );
00654 }
00655
00662 void Vect_set_db_updated ( struct Map_info *Map )
00663 {
00664 if ( strcmp(Map->mapset,G_mapset() ) != 0 ) {
00665 G_fatal_error ( _("Bug: attempt to update map which is not in current mapset." ) );
00666 }
00667
00668 Vect_write_dblinks ( Map ) ;
00669 }