Jelajahi Sumber

v.db.update: add support for extended SQLite functions

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@63238 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Neteler 10 tahun lalu
induk
melakukan
1ec8a337d2

+ 3 - 0
db/drivers/sqlite/db.c

@@ -110,6 +110,9 @@ int db__driver_open_database(dbHandle * handle)
 	return DB_FAILED;
     }
 
+    /* enable loading of extensions */
+    sqlite3_enable_load_extension(sqlite, 1);
+
     /* set the sqlite busy handler */
     sqlite3_busy_handler(sqlite, sqlite_busy_callback, NULL);
 

+ 28 - 1
scripts/v.db.update/v.db.update.html

@@ -14,6 +14,8 @@ allow easier usage.
 
 <h2>EXAMPLES</h2>
 
+<h3>Replacing of NULL values</h3>
+
 In this example, selectively display lakes without (blue) and with
 NULL (red) are shown to find out which type is undefined. In the
 original map there are lakes missing FTYPE attribute which are
@@ -37,7 +39,9 @@ v.db.update mylakes col=FTYPE value=WETLAND \
 v.db.select mylakes
 </pre></div>
 
-Spearfish example: adding new column, copying values from other table
+<h3>Updating of columns with on the fly calculation</h3>
+
+Spearfish example: adding new column, copying values from another table
 column with on the fly calculation:
 <div class="code"><pre>
 g.copy vect=fields,myfields
@@ -46,6 +50,8 @@ v.db.update myfields col=polynum qcol="cat*2"
 v.db.select myfields
 </pre></div>
 
+<h3>Type casting</h3>
+
 Type cast (type conversion) of strings to double precision
 (unsupported by DBF driver):
 <div class="code"><pre>
@@ -54,6 +60,27 @@ v.db.update mygeodetic_pts col=zval qcol="CAST(z_value AS double precision)" \
             where="z_value &lt;&gt; 'N/A'"
 </pre></div>
 
+<h3>Updating of columns with on the fly calculation (SQLite extended functions)</h3>
+
+North Carolina data set example: adding new column, copying values from
+another table column with on the fly calculation:
+
+<div class="code"><pre>
+g.copy vect=precip_30ynormals,myprecip_30ynormals
+v.db.addcolumn myprecip_30ynormals column="logjuly double precision"
+v.db.update myprecip_30ynormals column="logjuly" qcolumn="log(jul)" \
+  sqliteextra=$HOME/sqlite_extensions/libsqlitefunctions.so
+
+v.db.select myprecip_30ynormals columns=jul,logjuly
+jul|logjuly
+132.842|4.88916045210132
+127|4.84418708645859
+124.206|4.82194147751127
+104.648|4.65060233738593
+98.298|4.58800368106618
+...
+</pre></div>
+
 
 <h2>SEE ALSO</h2>
 

+ 19 - 1
scripts/v.db.update/v.db.update.py

@@ -43,6 +43,12 @@
 #%end
 #%option G_OPT_DB_WHERE
 #%end
+#%option G_OPT_F_INPUT
+#% key: sqliteextra
+#% description: Name of SQLite extension file for extra functions (SQLite backend only)
+#% gisprompt: old,bin,file
+#% required: no
+#%end
 
 import sys
 import os
@@ -55,6 +61,7 @@ def main():
     value = options['value']
     qcolumn = options['query_column']
     where = options['where']
+    sqlitefile  = options['sqliteextra']
 
     mapset = grass.gisenv()['MAPSET']
 
@@ -71,6 +78,13 @@ def main():
     database = f['database']
     driver = f['driver']
 
+    # check for SQLite backend for extra functions
+    if sqlitefile and driver != "sqlite":
+        grass.fatal(_("Use of libsqlitefunctions only with SQLite backend"))
+    if driver == "sqlite" and sqlitefile:
+        if not os.access(sqlitefile, os.R_OK):
+            grass.fatal(_("File <%s> not found") % sqlitefile)
+
     # checking column types
     try:
         coltype = grass.vector_columns(vector, layer)[column]['type']
@@ -93,8 +107,12 @@ def main():
     if where:
         cmd += " WHERE " + where
 
-    grass.verbose("SQL: \"%s\"" % cmd)
+    # SQLite: preload extra functions from extension lib if provided by user
+    if sqlitefile:
+        sqliteload = "SELECT load_extension('%s');\n" % sqlitefile
+        cmd = sqliteload + cmd
 
+    grass.verbose("SQL: \"%s\"" % cmd)
     grass.write_command('db.execute', input = '-', database = database, driver = driver, stdin = cmd)
 
     # write cmd history: