[GRASS-SVN] r51946 - grass/trunk/db/db.execute

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Jun 3 04:23:32 PDT 2012


Author: martinl
Date: 2012-06-03 04:23:32 -0700 (Sun, 03 Jun 2012)
New Revision: 51946

Modified:
   grass/trunk/db/db.execute/db.execute.html
   grass/trunk/db/db.execute/main.c
Log:
db.execute: new option for single statements (sql)
            improve support for multiple sql statements
            manual updated


Modified: grass/trunk/db/db.execute/db.execute.html
===================================================================
--- grass/trunk/db/db.execute/db.execute.html	2012-06-03 11:08:06 UTC (rev 51945)
+++ grass/trunk/db/db.execute/db.execute.html	2012-06-03 11:23:32 UTC (rev 51946)
@@ -5,97 +5,107 @@
 <h2>NOTES</h2>
 
 <em>db.execute</em> only executes SQL statements and does not return 
-any data. If you need data returned from the database, use <em>db.select</em>.
-<p>If parameters for database connection are already set with 
-<a href="db.connect.html">db.connect</a>, they are taken as default values and
+any data. If you need data returned from the database, use <em><a href="db.select.html">db.select</a></em>.
+<p>
+If parameters for database connection are already set with
+<em><a href="db.connect.html">db.connect</a></em>, they are taken as default values and
 do not need to be specified each time.
-<p>If you have a large number of SQL commands to process, it is much much faster
-to place all the SQL statements into a text file and use <em>db.execute</em>'s
-<b>input</b> file parameter than it is to process each statement individually
-in a loop. If multiple instruction lines are given, each SQL line must end
-with a semicolon.
-<p>Please see the individual <a href="sql.html">sql driver</a> pages for how to create
-a new database.
+<p>
+If you have a large number of SQL commands to process, it is much much
+faster to place all the SQL statements into a text file and
+use <b>input</b> file parameter than it is to process each statement
+individually in a loop. If multiple instruction lines are given, each
+SQL line must end with a semicolon.
+<p>
+Please see the individual <em><a href="sql.html">GRASS SQL interface</a></em>
+for how to create a new database.
 
 <h2>EXAMPLES</h2>
 
-<em>Create a new table with columns 'cat' and 'soiltype':</em><br>
+Create a new table with columns 'cat' and 'soiltype':
 <div class="code"><pre>
-echo 'create table soils (cat integer, soiltype varchar(10) )' | db.execute
+db.execute sql="CREATE TABLE soils (cat integer, soiltype varchar(10))"
 </pre></div>
 
-<p><em>Create a new table using a file with SQL statements:</em><br>
+Create a new table using a file with SQL statements
 <div class="code"><pre>
 db.execute driver=odbc database=g60test input=file.sql
 </pre></div>
 
-<p><em>Insert new row into attribute table:</em><br>
+Insert new row into attribute table:
 <div class="code"><pre>
-echo "INSERT INTO nobugs (id,name,east_gb,north_gb) values (30,'Ala',1657340,5072301)" | db.execute
+db.execute sql="INSERT INTO nobugs (id,name,east_gb,north_gb) values (30,'Ala',1657340,5072301)"
 </pre></div>
 
-<p><em>Update attribute entries to new value based on SQL rule:</em><br>
+Update attribute entries to new value based on SQL rule:
 <div class="code"><pre>
-echo "UPDATE roads SET travelcost=5 WHERE cat=1" | db.execute
+db.execute sql="UPDATE roads SET travelcost=5 WHERE cat=1"
 </pre></div>
 
-<p><em>Update attribute entries to new value based on SQL rule:</em><br>
+Update attribute entries to new value based on SQL rule:
 <div class="code"><pre>
-echo "UPDATE dourokukan SET testc=50 WHERE testc is NULL" | db.execute
+db.execute sql="UPDATE dourokukan SET testc=50 WHERE testc is NULL"
 </pre></div>
 
-<p><em>Delete selected rows from attribute table:</em><br>
+Delete selected rows from attribute table:
 <div class="code"><pre>
-echo "DELETE FROM gsod_stationlist WHERE latitude < -91" | db.execute
+db.execute sql="DELETE FROM gsod_stationlist WHERE latitude < -91"
 </pre></div>
 
-<p><em>Add new column to attribute table:</em><br>
+Add new column to attribute table:
 <div class="code"><pre>
-echo "ALTER TABLE roads ADD COLUMN length double" | db.execute
+db.execute sql="ALTER TABLE roads ADD COLUMN length double"
 </pre></div>
 
-<p><em>Column type conversion - update new column from existing column (all drivers except for DBF):</em><br>
+Column type conversion - update new column from existing column (all drivers except for DBF):
 <div class="code"><pre>
 # 'z_value' is varchar and 'z' is double precision:
-echo "update geodetic_pts SET z = CAST(z_value AS numeric)" | db.execute
+echo "UPDATE geodetic_pts SET z = CAST(z_value AS numeric)" | db.execute input=-
 </pre></div>
 
-<p><em>Drop column from attribute table:</em><br>
+Drop column from attribute table:
 <div class="code"><pre>
-echo "ALTER TABLE roads DROP COLUMN length" | db.execute
+db.execute sql="ALTER TABLE roads DROP COLUMN length"
 </pre></div>
 
-<p><em>Drop table (not supported by all drivers)</em><br>
+Drop table (not supported by all drivers):
 <div class="code"><pre>
-echo "DROP TABLE fmacopy" | db.execute
+db.execute sql="DROP TABLE fmacopy"
 </pre></div>
 
-<p><em>Update attribute with multiple SQL instructions in file (e.g., file.sql,
-    instruction line must end with a semicolon):</em><br>
+Update attribute with multiple SQL instructions in file
+(e.g., <tt>file.sql</tt>, instruction line must end with a semicolon):
 <div class="code"><pre>
 UPDATE roads SET travelcost=5 WHERE cat=1;
 UPDATE roads SET travelcost=2 WHERE cat=2;
  
-cat file.sql | db.execute
+db.execute input=file.sql
 </pre></div>
 
-<p><em>Join table 'myroads' into table 'extratab' based on common 'cat' column values (not supported by DBF driver):</em><br>
+Join table 'myroads' into table 'extratab' based on common 'cat' column values (not supported by DBF driver):
 <div class="code"><pre>
-echo "UPDATE extratab SET names=(SELECT label FROM myroads WHERE extratab.cat=myroads.cat);" | db.execute
+db.execute sql="UPDATE extratab SET names=(SELECT label FROM myroads WHERE extratab.cat=myroads.cat)"
 </pre></div>
 
 <h2>SEE ALSO</h2>
-<em><a href="db.columns.html">db.columns</a>,
+<em>
+<a href="sql.html">GRASS SQL interface</a>
+<em>
+
+<p>
+<em>
+<a href="db.columns.html">db.columns</a>,
 <a href="db.describe.html">db.describe</a>,
 <a href="db.drivers.html">db.drivers</a>,
 <a href="db.droptable.html">db.droptable</a>,
 <a href="db.login.html">db.login</a>,
 <a href="db.select.html">db.select</a>,
 <a href="db.tables.html">db.tables</a>,
-<a href="sql.html">GRASS SQL interface</a></em>
+</em>
 
 <h2>AUTHOR</h2>
 
 CERL
 
-<p><i>Last changed: $Date$</i>
+<p>
+<i>Last changed: $Date$</i>

Modified: grass/trunk/db/db.execute/main.c
===================================================================
--- grass/trunk/db/db.execute/main.c	2012-06-03 11:08:06 UTC (rev 51945)
+++ grass/trunk/db/db.execute/main.c	2012-06-03 11:23:32 UTC (rev 51946)
@@ -27,7 +27,7 @@
 
 struct
 {
-    const char *driver, *database, *schema, *input;
+    const char *driver, *database, *schema, *sql, *input;
     int i;
 } parms;
 
@@ -35,6 +35,7 @@
 static void parse_command_line(int, char **);
 static int get_stmt(FILE *, dbString *);
 static int stmt_is_empty(dbString *);
+static void error_handler(void *);
 
 int main(int argc, char **argv)
 {
@@ -49,17 +50,21 @@
 
     parse_command_line(argc, argv);
 
-    if (strcmp(parms.input, "-")) {
+    /* read from file or stdin ? */
+    if (parms.input && strcmp(parms.input, "-") != 0) {
 	fd = fopen(parms.input, "r");
 	if (fd == NULL) {
-	    G_fatal_error(_("Unable to open file <%s> for reading.\n"
-			    "Details: %s"), parms.input, strerror(errno));
+	    G_fatal_error(_("Unable to open file <%s>: %s"),
+                          parms.input, strerror(errno));
 	}
     }
     else {
 	fd = stdin;
     }
     
+    /* open DB connection */
+    db_init_string(&stmt);
+    
     driver = db_start_driver(parms.driver);
     if (driver == NULL) {
 	G_fatal_error(_("Unable to start driver <%s>"), parms.driver);
@@ -69,29 +74,35 @@
     db_set_handle(&handle, parms.database, parms.schema);
     if (db_open_database(driver, &handle) != DB_OK)
 	G_fatal_error(_("Unable to open database <%s>"), parms.database);
-
-    while (get_stmt(fd, &stmt)) {
-	if (!stmt_is_empty(&stmt)) {
-	    G_debug(3, "sql: %s", db_get_string(&stmt));
-
-	    ret = db_execute_immediate(driver, &stmt);
-
-	    if (ret != DB_OK) {
-		if (parms.i) {	/* ignore SQL errors */
-		    G_warning(_("Error while executing: '%s'"),
-			      db_get_string(&stmt));
-		    error++;
-		}
-		else {
-		    db_close_database(driver);
-		    db_shutdown_driver(driver);
-		    G_fatal_error(_("Error while executing: '%s'"),
-				  db_get_string(&stmt));
-		}
-	    }
-	}
+    G_add_error_handler(error_handler, driver);
+    
+    if (parms.sql) {
+        /* parms.sql */
+        db_set_string(&stmt, parms.sql);
+        ret = db_execute_immediate(driver, &stmt);
     }
-
+    else { /* parms.input */
+        while (get_stmt(fd, &stmt)) {
+            if (stmt_is_empty(&stmt))
+                continue;
+            G_debug(3, "sql: %s", db_get_string(&stmt));
+                
+            ret = db_execute_immediate(driver, &stmt);
+            
+            if (ret != DB_OK) {
+                if (parms.i) {	/* ignore SQL errors */
+                    G_warning(_("Error while executing: '%s'"),
+                              db_get_string(&stmt));
+                    error++;
+                }
+                else {
+                    G_fatal_error(_("Error while executing: '%s'"),
+                                  db_get_string(&stmt));
+                }
+            }
+        }
+    }
+    
     db_close_database(driver);
     db_shutdown_driver(driver);
 
@@ -101,7 +112,7 @@
 
 static void parse_command_line(int argc, char **argv)
 {
-    struct Option *driver, *database, *schema, *input;
+    struct Option *driver, *database, *schema, *sql, *input;
     struct Flag *i;
     struct GModule *module;
     const char *drv, *db, *schema_name;
@@ -117,9 +128,16 @@
     module->label = _("Executes any SQL statement.");
     module->description = _("For SELECT statements use 'db.select'.");
 
+    sql = G_define_standard_option(G_OPT_DB_SQL);
+    sql->label = _("SQL statement");
+    sql->description = _("Example: update rybniky set kapri = 'hodne' where kapri = 'malo'");
+    sql->guisection = _("SQL");
+    
     input = G_define_standard_option(G_OPT_F_INPUT);
-    input->label = _("Name of file containing SQL statements");
-    input->description = _("'-' to read from standard input");
+    input->required = NO;
+    input->label = _("Name of file containing SQL statement(s)");
+    input->description = _("'-' for standard input");
+    input->guisection = _("SQL");
 
     driver = G_define_standard_option(G_OPT_DB_DRIVER);
     driver->options = db_list_drivers();
@@ -145,49 +163,53 @@
     if (G_parser(argc, argv))
 	exit(EXIT_SUCCESS);
 
+    if (!sql->answer && !input->answer) {
+        G_fatal_error(_("You must provide <%s> or <%s> option"),
+                      sql->key, input->key);
+    }
+    
     parms.driver = driver->answer;
     parms.database = database->answer;
     parms.schema = schema->answer;
+    parms.sql = sql->answer;
     parms.input = input->answer;
-    parms.i = i->answer;
+    parms.i = i->answer ? TRUE : FALSE;
 }
 
-
-static int get_stmt(FILE * fd, dbString * stmt)
+int get_stmt(FILE * fd, dbString * stmt)
 {
-    char buf[4000], buf2[4000];
-    int len, row = 0;
+    char buf[DB_SQL_MAX], buf2[DB_SQL_MAX];
+    size_t len;
 
-    db_init_string(stmt);
+    db_zero_string(stmt);
 
-    while (fgets(buf, 4000, fd) != NULL) {
-	strcpy(buf2, buf);
-	G_chop(buf2);
-	len = strlen(buf2);
-
-	if (buf2[len - 1] == ';') {	/* end of statement */
-	    buf2[len - 1] = 0;	        /* truncate ';' */
-	    /* append truncated */
-	    db_append_string(stmt, buf2);	
-	    return 1;
-	}
-	else {
-	    /* append not truncated string (\n may be part of value) */
-	    db_append_string(stmt, buf);	
-	}
-	row++;
+    if (G_getl2(buf, sizeof(buf), fd) == 0)
+        return 0;
+    
+    strcpy(buf2, buf);
+    G_chop(buf2);
+    len = strlen(buf2);
+        
+    if (buf2[len - 1] == ';') { /* end of statement */
+        buf2[len - 1] = 0;      /* truncate ';' */
     }
+    
+    db_set_string(stmt, buf2);
 
-    if (row > 0)
-	return 1;
-
-    return 0;
+    return 1;
 }
 
-
-static int stmt_is_empty(dbString * stmt)
+int stmt_is_empty(dbString * stmt)
 {
     char dummy[2];
 
     return (sscanf(db_get_string(stmt), "%1s", dummy) != 1);
 }
+
+void error_handler(void *p)
+{
+    dbDriver *driver = (dbDriver *) p;
+    
+    db_close_database(driver);
+    db_shutdown_driver(driver);
+}



More information about the grass-commit mailing list