field.c

Go to the documentation of this file.
00001 /*
00002 ****************************************************************************
00003 *
00004 * MODULE:       Vector library 
00005 *               
00006 * AUTHOR(S):    Original author CERL, probably Dave Gerdes or Mike Higgins.
00007 *               Update to GRASS 5.7 Radim Blazek and David D. Gray.
00008 *
00009 * PURPOSE:      Higher level functions for reading/writing/manipulating vectors.
00010 *
00011 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
00012 *
00013 *               This program is free software under the GNU General Public
00014 *               License (>=v2). Read the file COPYING that comes with GRASS
00015 *               for details.
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     /* write it immediately otherwise it is lost if module crashes */
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 ) { /* field found */
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     /* write it immediately otherwise it is lost if module crashes */
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,  /* pointer to map structure */               
00229     int  field,    /* category field */
00230     char *field_name, /* field name or NULL */
00231     int  type ) /* how many tables are linked to map: GV_1TABLE / GV_MTABLE */
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 ) { /* Set default values and create dbf db dir */
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     /* Table name */
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" ); /* Should be: id/fid/gfid/... ? */
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         /* FID is not available for all OGR drivers */
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             /* FID not available */
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 ) { /* This may be correct, no tables defined */
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         /* get field and field name */
00443         fldname = strchr ( fldstr, '/' );
00444         if ( fldname != NULL ) { /* field has name */
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 ) { /* This may be correct, no tables defined */
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 }

Generated on Sat Jul 22 22:05:57 2006 for GRASS by  doxygen 1.4.7