[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