00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include "glocale.h"
00022 #include "gis.h"
00023 #include "dbmi.h"
00024 #include "Vect.h"
00025
00032 struct dblinks *
00033 Vect_new_dblinks_struct ( void )
00034 {
00035 struct dblinks *p;
00036
00037 p = (struct dblinks *) G_malloc (sizeof (struct dblinks));
00038
00039 if (p) {
00040 p->alloc_fields = p->n_fields = 0;
00041 p->field = NULL;
00042 }
00043
00044 return p;
00045 }
00046
00053 void
00054 Vect_reset_dblinks ( struct dblinks *p )
00055 {
00056 p->n_fields = 0;
00057 }
00058
00066 int
00067 Vect_map_add_dblink ( struct Map_info *Map, int number, char *name, char *table, char *key,
00068 char *db, char *driver )
00069 {
00070 int ret;
00071
00072 if (number == 0) {
00073 G_warning (_("Field number must be 1 or greater."));
00074 return -1;
00075 }
00076
00077 if (Map->mode != GV_MODE_WRITE && Map->mode != GV_MODE_RW) {
00078 G_warning (_("Cannot add database link, map is not opened in WRITE mode."));
00079 return -1;
00080 }
00081
00082 ret = Vect_add_dblink ( Map->dblnk, number, name, table, key, db, driver );
00083 if ( ret == -1 ) {
00084 G_warning (_("Cannot add database link."));
00085 return -1;
00086 }
00087
00088 ret = Vect_write_dblinks ( Map );
00089 if ( ret == -1 ) {
00090 G_warning (_("Cannot write database links."));
00091 return -1;
00092 }
00093 return 0;
00094 }
00095
00102 int
00103 Vect_map_del_dblink ( struct Map_info *Map, int field)
00104 {
00105 int i, j, ret;
00106 struct dblinks *links;
00107
00108 G_debug(4, "Vect_map_del_dblink() field = %d", field);
00109 links = Map->dblnk;
00110
00111 ret = -1;
00112 for (i = 0; i < links->n_fields; i++) {
00113 if ( links->field[i].number == field ) {
00114 for (j = i; j < links->n_fields - 1; j++) {
00115 links->field[j].number = links->field[j+1].number;
00116 links->field[j].name = links->field[j+1].name;
00117 links->field[j].table = links->field[j+1].table;
00118 links->field[j].key = links->field[j+1].key;
00119 links->field[j].database = links->field[j+1].database;
00120 links->field[j].driver = links->field[j+1].driver;
00121 }
00122 ret = 0;
00123 links->n_fields--;
00124 }
00125 }
00126
00127 if ( ret == -1 )
00128 return -1;
00129
00130
00131 ret = Vect_write_dblinks ( Map );
00132 if ( ret == -1 ) {
00133 G_warning (_("Cannot write database links."));
00134 return -1;
00135 }
00136
00137 return 0;
00138 }
00139
00146 int
00147 Vect_map_check_dblink ( struct Map_info *Map, int field )
00148 {
00149 return Vect_check_dblink ( Map->dblnk, field );
00150 }
00151
00158 int
00159 Vect_check_dblink ( struct dblinks *p, int field )
00160 {
00161 int i;
00162
00163 G_debug(3,"Vect_check_dblink: field %d", field);
00164
00165 for (i = 0; i < p->n_fields; i++) {
00166 if ( p->field[i].number == field ) {
00167 return 1;
00168 }
00169 }
00170 return 0;
00171 }
00172
00173
00181 int
00182 Vect_add_dblink ( struct dblinks *p, int number, char *name, char *table, char *key, char *db, char *driver )
00183 {
00184 int ret;
00185
00186 ret = Vect_check_dblink ( p, number );
00187 if ( ret == 1 ) {
00188 G_warning (_("Field number <%d> or name <%s> already exists"), number, name);
00189 return -1;
00190 }
00191
00192 if ( p->n_fields == p->alloc_fields ) {
00193 p->alloc_fields += 10;
00194 p->field = ( struct field_info *) G_realloc ( (void *) p->field,
00195 p->alloc_fields * sizeof (struct field_info) );
00196 }
00197
00198 p->field[p->n_fields].number = number;
00199
00200 if ( name != NULL ) p->field[p->n_fields].name = G_store ( name );
00201 else p->field[p->n_fields].name = NULL;
00202
00203 if ( table != NULL ) p->field[p->n_fields].table = G_store ( table );
00204 else p->field[p->n_fields].table = NULL;
00205
00206 if ( key != NULL ) p->field[p->n_fields].key = G_store ( key );
00207 else p->field[p->n_fields].key = NULL;
00208
00209 if ( db != NULL ) p->field[p->n_fields].database = G_store ( db );
00210 else p->field[p->n_fields].database = NULL;
00211
00212 if ( driver != NULL ) p->field[p->n_fields].driver = G_store ( driver );
00213 else p->field[p->n_fields].driver = NULL;
00214
00215 p->n_fields++;
00216
00217 return 0;
00218 }
00219
00226 struct field_info
00227 *Vect_default_field_info (
00228 struct Map_info *Map,
00229 int field,
00230 char *field_name,
00231 int type )
00232 {
00233 struct field_info *fi;
00234 char buf[1000], buf2[1000];
00235 char *schema;
00236 char *drv, *db;
00237 dbConnection connection;
00238
00239 G_debug (1, "Vect_default_field_info(): map = %s field = %d", Map->name, field);
00240
00241 db_get_connection( &connection );
00242 drv = G__getenv2 ( "DB_DRIVER", G_VAR_MAPSET );
00243 db = G__getenv2 ( "DB_DATABASE", G_VAR_MAPSET );
00244
00245 G_debug (2, "drv = %s db = %s", drv, db );
00246
00247 if ( !connection.driverName && !connection.databaseName ) {
00248 G_warning ( _("Default driver / database set to:\n"
00249 "driver: dbf\ndatabase: $GISDBASE/$LOCATION_NAME/$MAPSET/dbf/") );
00250
00251 connection.driverName = "dbf";
00252 connection.databaseName = "$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/";
00253 db_set_connection( &connection );
00254
00255 sprintf ( buf, "%s/%s/%s/dbf", Map->gisdbase, Map->location, Map->mapset );
00256 G__make_mapset_element ( "dbf" );
00257 } else if ( !connection.driverName ) {
00258 G_fatal_error ( _("Default driver is not set") );
00259 } else if ( !connection.databaseName ) {
00260 G_fatal_error ( _("Default database is not set") );
00261 }
00262 drv = connection.driverName;
00263 db = connection.databaseName;
00264
00265 fi = (struct field_info *) G_malloc( sizeof(struct field_info) );
00266
00267 fi->number = field;
00268 if ( field_name != NULL ) fi->name = G_store ( field_name );
00269 else fi->name = NULL;
00270
00271
00272 if ( type == GV_1TABLE ) {
00273 sprintf ( buf, "%s", Map->name);
00274 } else {
00275 if ( field_name != NULL && strlen ( field_name ) > 0 )
00276 sprintf ( buf, "%s_%s", Map->name, field_name );
00277 else
00278 sprintf ( buf, "%s_%d", Map->name, field );
00279 }
00280
00281 schema = connection.schemaName;
00282 if ( schema && strlen(schema) > 0 ) {
00283 sprintf ( buf2, "%s.%s", schema, buf );
00284 fi->table = G_store ( buf2 );
00285 } else {
00286 fi->table = G_store ( buf );
00287 }
00288
00289 fi->key = G_store ( "cat" );
00290 fi->database = G_store( db );
00291 fi->driver = G_store( drv );
00292
00293 return (fi);
00294 }
00295
00303 struct field_info
00304 *Vect_get_dblink ( struct Map_info *Map, int link )
00305 {
00306 struct field_info *fi;
00307
00308 G_debug (1, "Vect_get_dblink(): link = %d", link);
00309
00310 if ( link >= Map->dblnk->n_fields ) {
00311 G_warning ( _("Requested dblink %d, maximum link number %d"), link, Map->dblnk->n_fields - 1 );
00312 return NULL;
00313 }
00314
00315 fi = (struct field_info *) malloc( sizeof(struct field_info) );
00316 fi->number = Map->dblnk->field[link].number;
00317
00318 if ( Map->dblnk->field[link].name != NULL )
00319 fi->name = G_store ( Map->dblnk->field[link].name );
00320 else
00321 fi->name = NULL;
00322
00323 fi->table = G_store ( Map->dblnk->field[link].table );
00324 fi->key = G_store ( Map->dblnk->field[link].key );
00325 fi->database = Vect_subst_var ( Map->dblnk->field[link].database, Map );
00326 fi->driver = G_store ( Map->dblnk->field[link].driver );
00327
00328 return fi;
00329 }
00330
00338 struct field_info
00339 *Vect_get_field ( struct Map_info *Map, int field )
00340 {
00341 int i;
00342 struct field_info *fi = NULL;
00343
00344 G_debug (1, "Vect_get_field(): field = %d", field);
00345
00346 for ( i = 0; i < Map->dblnk->n_fields; i++ ) {
00347 if ( Map->dblnk->field[i].number == field ) {
00348 fi = Vect_get_dblink ( Map, i );
00349 break;
00350 }
00351 }
00352
00353 return fi;
00354 }
00355
00362 int
00363 Vect_read_dblinks ( struct Map_info *Map )
00364 {
00365 int ndef;
00366 FILE *fd;
00367 char file[1024], buf[2001];
00368 char tab[1024], col[1024], db[1024], drv[1024], fldstr[1024], *fldname;
00369 int fld;
00370 char *c;
00371 int row, rule;
00372 struct dblinks *dbl;
00373
00374 G_debug (1, "Vect_read_dblinks(): map = %s, mapset = %s", Map->name, Map->mapset);
00375
00376 dbl = Map->dblnk;
00377 Vect_reset_dblinks ( dbl );
00378
00379 if ( Map->format == GV_FORMAT_OGR ) {
00380 dbDriver *driver;
00381 dbCursor cursor;
00382 dbString sql;
00383
00384
00385 db_init_string (&sql);
00386
00387 driver = db_start_driver_open_database ( "ogr", Map->fInfo.ogr.dsn );
00388
00389 if ( driver == NULL ) {
00390 G_warning (_("Cannot open OGR DBMI driver."));
00391 return -1;
00392 }
00393
00394 sprintf ( buf, "select FID from %s where FID = -1", Map->fInfo.ogr.layer_name );
00395 db_set_string ( &sql, buf );
00396
00397 if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) != DB_OK) {
00398
00399 db_close_database_shutdown_driver ( driver );
00400 return 0;
00401 }
00402
00403 db_close_cursor(&cursor);
00404 db_close_database_shutdown_driver ( driver );
00405
00406 Vect_add_dblink ( dbl, 1, NULL, Map->fInfo.ogr.layer_name, "FID", Map->fInfo.ogr.dsn, "ogr" ) ;
00407
00408 return ( 1 );
00409 } else if ( Map->format != GV_FORMAT_NATIVE ) {
00410 G_fatal_error (_("Don't know how to read links for format %d"), Map->format );
00411 }
00412
00413 sprintf ( file, "%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location, Map->mapset, GRASS_VECT_DIRECTORY,
00414 Map->name, GRASS_VECT_DBLN_ELEMENT );
00415 G_debug (1, "dbln file: %s", file);
00416
00417 fd = fopen ( file, "r" );
00418 if ( fd == NULL ) {
00419 G_debug ( 1, "Cannot open vector database definition file");
00420 return (-1);
00421 }
00422
00423 row = 0;
00424 rule = 0;
00425 while ( G_getl2 (buf, 2000, fd) ) {
00426 row++;
00427 G_chop ( buf );
00428 G_debug (1, "dbln: %s", buf);
00429
00430 c = (char *) strchr ( buf, '#');
00431 if ( c != NULL ) *c = '\0';
00432
00433 if ( strlen(buf) == 0 ) continue;
00434
00435 ndef = sscanf ( buf, "%s %s %s %s %s", fldstr, tab, col, db, drv);
00436
00437 if ( ndef < 2 || (ndef < 5 && rule < 1 ) ) {
00438 G_warning ( _("Error in rule on row %d in %s"), row, file);
00439 continue;
00440 }
00441
00442
00443 fldname = strchr ( fldstr, '/' );
00444 if ( fldname != NULL ) {
00445 fldname[0] = 0;
00446 fldname++;
00447 }
00448 fld = atoi ( fldstr );
00449
00450 Vect_add_dblink ( dbl, fld, fldname, tab, col, db, drv );
00451
00452 G_debug (1, "field = %d name = %s, table = %s, key = %s, database = %s, driver = %s",
00453 fld, fldname, tab, col, db, drv );
00454
00455 rule++;
00456 }
00457 fclose (fd);
00458
00459 G_debug (1, "Dblinks read");
00460 return ( rule );
00461 }
00462
00469 int
00470 Vect_write_dblinks ( struct Map_info *Map )
00471 {
00472 int i;
00473 FILE *fd;
00474 char file[1024], buf[1024];
00475 struct dblinks *dbl;
00476
00477 G_debug (1, "Vect_write_dblinks(): map = %s, mapset = %s", Map->name, Map->mapset );
00478
00479 dbl = Map->dblnk;
00480
00481 sprintf ( file, "%s/%s/%s/%s/%s/%s", Map->gisdbase, Map->location, Map->mapset, GRASS_VECT_DIRECTORY,
00482 Map->name, GRASS_VECT_DBLN_ELEMENT );
00483 G_debug (1, "dbln file: %s", file);
00484
00485 fd = fopen ( file, "w" );
00486 if ( fd == NULL ) {
00487 G_warning ( "Cannot open vector database definition file: '%s'", file);
00488 return (-1);
00489 }
00490
00491 for ( i = 0; i < dbl->n_fields; i++ ) {
00492 if ( dbl->field[i].name != NULL )
00493 sprintf ( buf , "%d/%s", dbl->field[i].number, dbl->field[i].name );
00494 else
00495 sprintf ( buf , "%d", dbl->field[i].number );
00496
00497 fprintf ( fd, "%s %s %s %s %s\n", buf, dbl->field[i].table, dbl->field[i].key,
00498 dbl->field[i].database, dbl->field[i].driver );
00499 G_debug (1, "%s %s %s %s %s", buf, dbl->field[i].table, dbl->field[i].key,
00500 dbl->field[i].database, dbl->field[i].driver );
00501 }
00502 fclose (fd);
00503
00504 G_debug (1, "Dblinks written");
00505 return 0;
00506 }
00507
00514 char *
00515 Vect_subst_var ( char *in, struct Map_info *Map )
00516 {
00517 char *c;
00518 char buf[1000], str[1000];
00519
00520 G_debug (3, "Vect_subst_var(): in = %s, map = %s, mapset = %s", in, Map->name, Map->mapset);
00521
00522 strcpy ( str, in );
00523
00524 strcpy ( buf, str );
00525 c = (char *) strstr ( buf, "$GISDBASE" );
00526 if ( c != NULL ) {
00527 *c = '\0';
00528 sprintf (str, "%s%s%s", buf, Map->gisdbase, c+9);
00529 }
00530
00531 strcpy ( buf, str );
00532 c = (char *) strstr ( buf, "$LOCATION_NAME" );
00533 if ( c != NULL ) {
00534 *c = '\0';
00535 sprintf (str, "%s%s%s", buf, Map->location, c+14);
00536 }
00537
00538 strcpy ( buf, str );
00539 c = (char *) strstr ( buf, "$MAPSET" );
00540 if ( c != NULL ) {
00541 *c = '\0';
00542 sprintf (str, "%s%s%s", buf, Map->mapset, c+7);
00543 }
00544
00545 strcpy ( buf, str );
00546 c = (char *) strstr ( buf, "$MAP" );
00547 if ( c != NULL ) {
00548 *c = '\0';
00549 sprintf (str, "%s%s%s", buf, Map->name, c+4 );
00550 }
00551
00552 G_debug (3, " -> %s", str);
00553 return ( G_store(str) );
00554 }
00555
00562 void Vect_set_db_updated ( struct Map_info *Map )
00563 {
00564 if ( strcmp(Map->mapset,G_mapset() ) != 0 ) {
00565 G_fatal_error ( _("Bug: attempt to update map which is not in current mapset." ) );
00566 }
00567
00568 Vect_write_dblinks ( Map ) ;
00569 }