[GRASS-SVN] r59256 - grass/trunk/vector/v.in.db

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Mar 15 06:00:33 PDT 2014


Author: martinl
Date: 2014-03-15 06:00:33 -0700 (Sat, 15 Mar 2014)
New Revision: 59256

Modified:
   grass/trunk/vector/v.in.db/main.c
   grass/trunk/vector/v.in.db/v.in.db.html
Log:
v.in.db: allow key option to be optional (currenly only supported when output DB driver is SQLite)
         update manual accordingly


Modified: grass/trunk/vector/v.in.db/main.c
===================================================================
--- grass/trunk/vector/v.in.db/main.c	2014-03-15 11:51:01 UTC (rev 59255)
+++ grass/trunk/vector/v.in.db/main.c	2014-03-15 13:00:33 UTC (rev 59256)
@@ -25,12 +25,11 @@
 
 int main(int argc, char *argv[])
 {
-    int i, cat, with_z, more, ctype, ret, nrows;
-    char buf[2000];
+    int i, cat, with_z, more, ctype, nrows;
+    char buf[DB_SQL_MAX];
     int count;
     double coor[3];
     int ncoor;
-    int coltype;
     struct Option *driver_opt, *database_opt, *table_opt;
     struct Option *xcol_opt, *ycol_opt, *zcol_opt, *keycol_opt, *where_opt,
 	*outvect;
@@ -64,11 +63,11 @@
     driver_opt = G_define_standard_option(G_OPT_DB_DRIVER);
     driver_opt->options = db_list_drivers();
     driver_opt->answer = (char *)db_get_default_driver_name();
-    driver_opt->guisection = _("Connection");
+    driver_opt->guisection = _("Input DB");
 
     database_opt = G_define_standard_option(G_OPT_DB_DATABASE);
     database_opt->answer = (char *)db_get_default_database_name();
-    database_opt->guisection = _("Connection");
+    database_opt->guisection = _("Input DB");
 
     xcol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
     xcol_opt->key = "x";
@@ -87,7 +86,7 @@
 
     keycol_opt = G_define_standard_option(G_OPT_DB_COLUMN);
     keycol_opt->key = "key";
-    keycol_opt->required = YES;
+    keycol_opt->required = NO;
     keycol_opt->label = _("Name of column containing category number");
     keycol_opt->description = _("Must refer to an integer column");
 
@@ -131,7 +130,8 @@
 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
 		      fi->database, fi->driver);
     }
-
+    db_set_error_handler_driver(driver);
+    
     /* check if target table already exists */
     G_debug(3, "Output vector table <%s>, driver: <%s>, database: <%s>",
 	    outvect->answer, db_get_default_driver_name(),
@@ -144,27 +144,42 @@
 		      db_get_default_driver_name(),
 		      db_get_default_database_name());
 
-    coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer);
+    if (keycol_opt->answer) {
+        int coltype;
+        coltype = db_column_Ctype(driver, table_opt->answer, keycol_opt->answer);
 
-    if (coltype == -1)
-	G_fatal_error(_("Missing column <%s> in table <%s>"),
-		      keycol_opt->answer, table_opt->answer);
-    if (coltype != DB_C_TYPE_INT)
-	G_fatal_error(_("Data type of key column must be integer"));
+        if (coltype == -1)
+            G_fatal_error(_("Missing column <%s> in table <%s>"),
+                          keycol_opt->answer, table_opt->answer);
+        if (coltype != DB_C_TYPE_INT)
+            G_fatal_error(_("Data type of key column must be integer"));
+    }
+    else {
+        if (same_table_flag->answer) {
+            G_fatal_error(_("Option <%s> must be specified when -%c flag is given"),
+                          keycol_opt->key, same_table_flag->key);
+        }
 
+        if (strcmp(db_get_default_driver_name(), "sqlite") != 0)
+            G_fatal_error(_("Unable to define key column. This operation is not supported "
+                            "by <%s> driver. You need to define <%s> option."),
+                          fi->driver, keycol_opt->key);
+    }
+
     /* Open select cursor */
-    sprintf(buf, "select %s, %s, %s", keycol_opt->answer, xcol_opt->answer,
-	    ycol_opt->answer);
+    sprintf(buf, "SELECT %s, %s", xcol_opt->answer, ycol_opt->answer);
     db_set_string(&sql, buf);
-
     if (with_z) {
 	sprintf(buf, ", %s", zcol_opt->answer);
 	db_append_string(&sql, buf);
     }
-
-    sprintf(buf, " from %s", table_opt->answer);
+    if (keycol_opt->answer) {
+	sprintf(buf, ", %s", keycol_opt->answer);
+	db_append_string(&sql, buf);
+    }
+    sprintf(buf, " FROM %s", table_opt->answer);
     db_append_string(&sql, buf);
-
+    
     if (where_opt->answer) {
 	sprintf(buf, " WHERE %s", where_opt->answer);
 	db_append_string(&sql, buf);
@@ -181,20 +196,26 @@
 
     G_debug(2, "%d points selected", nrows);
 
-    count = 0;
+    count = cat = 0;
     G_message(_("Writing features..."));
     while (db_fetch(&cursor, DB_NEXT, &more) == DB_OK && more) {
 	G_percent(count, nrows, 2);
 	/* key column */
-	column = db_get_table_column(table, 0);
-	ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
-	if (ctype != DB_C_TYPE_INT)
-	    G_fatal_error(_("Key column must be integer"));
-	value = db_get_column_value(column);
-	cat = db_get_value_int(value);
+        if (keycol_opt->answer) {
+            column = db_get_table_column(table, with_z ? 3 : 2);
+            ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
+            if (ctype != DB_C_TYPE_INT)
+                G_fatal_error(_("Key column must be integer"));
+            value = db_get_column_value(column);
+            cat = db_get_value_int(value);
+        }
+        else {
+            cat++;
+        }
 
+        /* coordinates */
 	for (i = 0; i < ncoor; i++) {
-	    column = db_get_table_column(table, i + 1);
+	    column = db_get_table_column(table, i);
 	    ctype = db_sqltype_to_Ctype(db_get_column_sqltype(column));
 	    if (ctype != DB_C_TYPE_INT && ctype != DB_C_TYPE_DOUBLE)
 		G_fatal_error(_("x/y/z column must be integer or double"));
@@ -218,34 +239,63 @@
     }
     G_percent(1, 1, 1);
 
+    /* close connection to input DB before copying attributes */
     db_close_database_shutdown_driver(driver);
 
     /* Copy table */
-    G_message(_("Copying attributes..."));
     if (!same_table_flag->answer) {
-	if (where_opt->answer)
-	    ret =
-		db_copy_table_where(driver_opt->answer, database_opt->answer,
-				    table_opt->answer, fi->driver,
-				    fi->database, fi->table,
-				    where_opt->answer);
-	else
-	    ret =
-		db_copy_table(driver_opt->answer, database_opt->answer,
-			      table_opt->answer, fi->driver, fi->database,
-			      fi->table);
-	if (ret == DB_FAILED) {
-	    G_warning(_("Unable to copy table"));
+        G_message(_("Copying attributes..."));
+        
+        if (DB_FAILED == db_copy_table_where(driver_opt->answer, database_opt->answer,
+                                             table_opt->answer,
+                                             fi->driver, fi->database, fi->table,
+                                             where_opt->answer)) { /* where can be NULL */
+            G_warning(_("Unable to copy table"));
 	}
 	else {
-	    Vect_map_add_dblink(&Map, 1, NULL, fi->table, keycol_opt->answer,
+	    Vect_map_add_dblink(&Map, 1, NULL, fi->table,
+                                keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
 				fi->database, fi->driver);
 	}
+
+        if (!keycol_opt->answer) {
+            /* TODO: implement for all DB drivers in generic way if
+             * possible */
+            
+            driver = db_start_driver_open_database(fi->driver, fi->database);
+            if (driver == NULL) {
+                G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
+                              fi->database, fi->driver);
+            }
+
+            /* add key column */
+            sprintf(buf, "ALTER TABLE %s ADD COLUMN %s INTEGER",
+                    fi->table, GV_KEY_COLUMN);
+            db_set_string(&sql, buf);
+            
+            if (db_execute_immediate(driver, &sql) != DB_OK) {
+                G_fatal_error(_("Unable to add key column <%s>: "
+                                "SERIAL type is not supported by <%s>"), 
+                              GV_KEY_COLUMN, fi->driver);
+            }
+
+            /* update key column */
+            sprintf(buf, "UPDATE %s SET %s = _ROWID_",
+                    fi->table, GV_KEY_COLUMN);
+            db_set_string(&sql, buf);
+            
+            if (db_execute_immediate(driver, &sql) != DB_OK) {
+                G_fatal_error(_("Failed to update key column <%s>"),
+                              GV_KEY_COLUMN);
+            }
+
+        }
     }
     else {
+        /* do not copy attributes, link original table */
 	Vect_map_add_dblink(&Map, 1, NULL, table_opt->answer,
-			    keycol_opt->answer, database_opt->answer,
-			    driver_opt->answer);
+                            keycol_opt->answer ? keycol_opt->answer : GV_KEY_COLUMN,
+                            database_opt->answer, driver_opt->answer);
     }
 
     Vect_build(&Map);

Modified: grass/trunk/vector/v.in.db/v.in.db.html
===================================================================
--- grass/trunk/vector/v.in.db/v.in.db.html	2014-03-15 11:51:01 UTC (rev 59255)
+++ grass/trunk/vector/v.in.db/v.in.db.html	2014-03-15 13:00:33 UTC (rev 59256)
@@ -1,73 +1,118 @@
 <h2>DESCRIPTION</h2>
 
-<em>v.in.db</em> 
-creates new vector (points) map from database table containing coordinates. 
+<em>v.in.db</em> creates a new vector point map from database table or file
+containing coordinates.
 
-<h2>EXAMPLE</h2>
+<h2>NOTES</h2>
 
-<h3>1) Creating a map from PostgreSQL table:</h3>
+If GRASS comes with <a href="grass-ogr.html">OGR</a> support
+than <em>v.in.db</em> allows to import data from different input
+files, eg. CSV or MS Excel (assuming that GDAL/OGR library is compiled
+with this support).
 
+<p>
+<em>v.in.db</em> creates key column "cat" automatically
+when <b>key</b> option is not given. Note that this operation is
+possible to perform only when <b>-t</b> flag is not given. Currently,
+automated creation of key column is supported only when default DB
+driver for output vector map is <a href="grass-sqlite.html">SQLite
+driver</a> otherwise <b>key</b> option must be specified by the
+user. Default DB driver is defined
+by <em><a href="db.connect.html">db.connect</a></em>.
+
+<h2>EXAMPLES</h2>
+
+<h3>Creating a map from PostgreSQL table</h3>
+
 <div class="code"><pre>
 v.in.db driver=pg database="host=myserver.itc.it,dbname=mydb" \
         table=pat_stazioni x=east y=north z=quota key=id output=pat_stazioni
 </pre></div>
-<p>If an ID column is not not present in the PostgreSQL table,
-a new column should be added. See <a href="grass-pg.html">PostgreSQL DB driver</a>
-page for details.
 
-<h3>2) Creating a map from PostGIS:</h3>
+<p>If an ID column is not not present in the PostgreSQL table, a new
+column should be added. See <a href="grass-pg.html">PostgreSQL DB
+driver</a> page for details.
 
+<h3>Creating a map from PostGIS</h3>
+
 To extract coordinate values from PostGIS, functions have to be used:
+
 <div class="code"><pre>
 v.in.db driver=pg database="host=myserver.itc.it,dbname=mydb" \
         table=station x="x(geom)" y="y(geom)" z="z(geom)" key=id out=meteostations
 </pre></div>
-<p>If an ID column is not not present in the PostgreSQL table,
-a new column should be added. See <a href="grass-pg.html">PostgreSQL DB driver</a> 
-page for details.
 
-<p>Alternatively a point vector map can be imported from PostGIS
+<p>If an ID column is not not present in the PostgreSQL table, a new
+column should be added. See <a href="grass-pg.html">PostgreSQL DB
+driver</a> page for details.
+
+<p>Alternatively a vector point map can be imported from PostGIS
 database using <em><a href="v.in.ogr.html">v.in.ogr</a></em>.
 
-<h3>3) Import of a points table (x, y, z) from DBF file to vector points map:</h3>
+<h3>Creating a map from MS Excel file</h3>
 
+A new vector point map is created from given list in MS Excel file
+file. The
+<b>database</b> option points to the file in MS Excel
+format. Option <b>table</b> is name of selected spreadsheet list.
+
 <div class="code"><pre>
-#create vector map from DBF table (here, 'idcol' contains unique row IDs, 'z' is optional):
-#the 'database' parameter is the directory where the DBF file is stored:
+v.in.db table=List1 x=long y=lat z=height output=meteodata \
+         driver=ogr datatabase=meteodata.xls
+</pre></div>
+
+Note that <b>key</b> option is omitted. In this case <em>v.in.db</em>
+tries to add key column automatically. This
+requires <a href="grass-sqlite.html">SQLite</a> to be a default DB
+driver. 
+
+<h3>Creating a map from DBF table</h3>
+
+A new 3D point vector map is created from DBF table. Column 'idcol'
+contains unique row IDs. The <b>database</b> option is the
+directory where the DBF file is stored.
+
+<div class="code"><pre>
 v.in.db driver=dbf database=/home/user/tables/ table=pointsfile x=x y=y z=z \
         key=idcol out=dtmpoints
-
-#check result:
-v.info dtmpoints
-v.info -c dtmpoints
 </pre></div>
-<p>If an ID column is missing in the DBF file, it has to be added beforehand, e.g. with OpenOffice.
-Alternatively, import the table with <em>db.in.ogr</em> into GRASS and then with <em>v.in.db</em>
-from the imported table (<em>db.in.ogr</em> optionally adds an unique ID column).
 
-<h3>4) Import of a points table (x, y, z) from SQLite file to vector points map:</h3>
+To check result:
 
 <div class="code"><pre>
-#create vector map from table in SQLITE database file (here, 'idcol' contains unique row IDs, 'z' is optional):
-#the 'database' parameter is the the SQLite database file with path:
-v.in.db driver=sqlite database=/home/user/tables/mysqlite.db table=pointsfile x=x y=y z=z \
-        key=idcol out=dtmpoints
-
-#check result:
 v.info dtmpoints
 v.info -c dtmpoints
 </pre></div>
-<p>If an ID column is missing in the table, it has to be added beforehand with 'sqlite3' or
-<em>db.execute</em>.
 
+<p>If DB driver for output vector map is different from SQLite driver
+and an ID column is missing in the DBF file, it has to be added
+beforehand, e.g. with OpenOffice.  Alternatively, import the table
+with <em><a href="db.in.ogr.html">db.in.ogr</a></em> into GRASS and
+then with <em>v.in.db</em> from the imported table
+(<em><a href="db.in.ogr.html">db.in.ogr</a></em> optionally adds an
+unique ID column).
 
-<h3>5) Import of a points table (x, y, z) from DBF file to vector points map for selected points only:</h3>
-<p>The user can import only selected vector points from a table using the <em>where</em> parameter
-(see above for general DBF handling):<p><div class="code"><pre>
+<h3>Creating a point map from DBF table for selected records only</h3>
+
+<p>The user can import only selected vector points from a table using
+the <b>where</b> parameter (see above for general DBF handling):
+
+<div class="code"><pre>
 v.in.db driver=dbf  database=/home/user/tables/ table=pointsfile x=x y=y z=z \
         key=idcol out=dtmpoints where="x NOT NULL and z > 100"
 </pre></div>
 
+<h3>Creating a map from SQLite table</h3>
+
+A new vector point map is created from table in SQLite database
+file. Column 'idcol' contains unique row IDs. The
+<b>database</b> option is the the SQLite database file.
+
+<div class="code"><pre>
+v.in.db driver=sqlite database=/home/user/tables/mysqlite.db table=pointsfile x=x y=y z=z \
+        key=idcol out=dtmpoints
+</pre></div>
+
 <h2>SEE ALSO</h2>
 
 <em>
@@ -75,13 +120,17 @@
 <a href="db.in.ogr.html">db.in.ogr</a>,
 <a href="v.info.html">v.info</a>,
 <a href="v.in.ogr.html">v.in.ogr</a>,
-<a href="v.to.db.html">v.to.db</a>,<br>
-<a href="sql.html">SQL support in GRASS GIS</a>
+<a href="v.to.db.html">v.to.db</a>
 </em>
 
+<p>
+<a href="sql.html">SQL support in GRASS GIS</a>
 
-<h2>AUTHOR</h2>
 
-Radim Blazek
+<h2>AUTHORS</h2>
 
-<p><i>Last changed: $Date$</i>
+Radim Blazek<br>
+Various updates for GRASS 7 by Martin Landa, Czech Technical University in Prague, Czech Republic
+
+<p>
+<i>Last changed: $Date$</i>



More information about the grass-commit mailing list