[spatialite] 01/04: Imported Upstream version 4.2.1~rc1
Bas Couwenberg
sebastic at xs4all.nl
Wed Nov 26 23:20:22 UTC 2014
This is an automated email from the git hooks/post-receive script.
sebastic-guest pushed a commit to branch experimental
in repository spatialite.
commit 245d3ef15971d6dc727848930d34b7c9a607b726
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Wed Nov 26 23:51:47 2014 +0100
Imported Upstream version 4.2.1~rc1
---
configure | 20 +-
configure.ac | 2 +-
spatialite-sql-latest.html | 11 +-
src/spatialite/extra_tables.c | 110 ++--
src/spatialite/spatialite.c | 154 ++++-
src/spatialite/virtualXL.c | 12 +
src/spatialite/virtualbbox.c | 12 +
src/spatialite/virtualdbf.c | 12 +
src/spatialite/virtualelementary.c | 12 +
src/spatialite/virtualfdo.c | 12 +
src/spatialite/virtualgpkg.c | 12 +
src/spatialite/virtualnetwork.c | 940 ++++++++++++++++++++++-------
src/spatialite/virtualshape.c | 12 +
src/spatialite/virtualspatialindex.c | 12 +
src/spatialite/virtualxpath.c | 12 +
src/virtualtext/virtualtext.c | 2 +
test/sql_stmt_geos_tests/Makefile.am | 2 +
test/sql_stmt_geos_tests/Makefile.in | 2 +
test/sql_stmt_geos_tests/buffer11.testcase | 7 +
test/sql_stmt_geos_tests/buffer12.testcase | 7 +
test/sql_stmt_tests/Makefile.am | 4 +
test/sql_stmt_tests/Makefile.in | 4 +
test/sql_stmt_tests/eval1.testcase | 7 +
test/sql_stmt_tests/eval2.testcase | 7 +
test/sql_stmt_tests/eval3.testcase | 7 +
test/sql_stmt_tests/eval4.testcase | 7 +
26 files changed, 1128 insertions(+), 273 deletions(-)
diff --git a/configure b/configure
index bd40735..1a8e6e2 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libspatialite 4.2.1-rc0.
+# Generated by GNU Autoconf 2.69 for libspatialite 4.2.1-rc1.
#
# Report bugs to <a.furieri at lqt.it>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libspatialite'
PACKAGE_TARNAME='libspatialite'
-PACKAGE_VERSION='4.2.1-rc0'
-PACKAGE_STRING='libspatialite 4.2.1-rc0'
+PACKAGE_VERSION='4.2.1-rc1'
+PACKAGE_STRING='libspatialite 4.2.1-rc1'
PACKAGE_BUGREPORT='a.furieri at lqt.it'
PACKAGE_URL=''
@@ -1362,7 +1362,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures libspatialite 4.2.1-rc0 to adapt to many kinds of systems.
+\`configure' configures libspatialite 4.2.1-rc1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1432,7 +1432,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of libspatialite 4.2.1-rc0:";;
+ short | recursive ) echo "Configuration of libspatialite 4.2.1-rc1:";;
esac
cat <<\_ACEOF
@@ -1566,7 +1566,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-libspatialite configure 4.2.1-rc0
+libspatialite configure 4.2.1-rc1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2110,7 +2110,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by libspatialite $as_me 4.2.1-rc0, which was
+It was created by libspatialite $as_me 4.2.1-rc1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2981,7 +2981,7 @@ fi
# Define the identity of the package.
PACKAGE='libspatialite'
- VERSION='4.2.1-rc0'
+ VERSION='4.2.1-rc1'
cat >>confdefs.h <<_ACEOF
@@ -19000,7 +19000,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by libspatialite $as_me 4.2.1-rc0, which was
+This file was extended by libspatialite $as_me 4.2.1-rc1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -19066,7 +19066,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-libspatialite config.status 4.2.1-rc0
+libspatialite config.status 4.2.1-rc1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 21ab175..50ef69c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT(libspatialite, 4.2.1-rc0, a.furieri at lqt.it)
+AC_INIT(libspatialite, 4.2.1-rc1, a.furieri at lqt.it)
AC_LANG(C)
AC_CONFIG_MACRO_DIR([m4])
diff --git a/spatialite-sql-latest.html b/spatialite-sql-latest.html
index 62605f4..bdb7c02 100644
--- a/spatialite-sql-latest.html
+++ b/spatialite-sql-latest.html
@@ -155,6 +155,10 @@
<tr><td><b>MD5TotalChecksum</b></td>
<td>MD5TotalChecksum( BLOB | TEXT ) : <i>Text</i></td>
<td colspan="3">returns a cumulative MD5 checksum.<br><b><u>aggregate function</u></b></td></tr>
+ <tr><td><b>eval</b></td>
+ <td>eval( X <i>TEXT</i> [ , Y <i>TEXT</i> ) : <i>Text</i></td>
+ <td colspan="3">Evaluate the SQL text in <b>X</b>. Return the results, using string <b>Y</b> as the separator.<br>
+ If <b>Y</b> is omitted, use a single space character.</td></tr>
<tr><td colspan="5" align="center" bgcolor="#f0e0c0">
<h3><a name="math">SQL math functions</a></h3></td></tr>
<tr><th bgcolor="#d0d0d0">Function</th>
@@ -1789,12 +1793,13 @@ This function only supports Long/Lat coordinates, and will return NULL for any p
<td>return a geometric object that is the closure of the set symmetric difference of geom1 and geom2
(logical XOR of space)</td></tr>
<tr><td><b>Buffer</b></td>
- <td>Buffer( geom <i>Geometry</i> , dist <i>Double precision</i> ) : <i>Geometry</i><hr>
- ST_Buffer( geom <i>Geometry</i> , dist <i>Double precision</i> ) : <i>Geometry</i></td>
+ <td>Buffer( geom <i>Geometry</i> , dist <i>Double precision</i> [ , quadrantsegments <i>Integer</i> ] ) : <i>Geometry</i><hr>
+ ST_Buffer( geom <i>Geometry</i> , dist <i>Double precision</i> [ , quadrantsegments <i>Integer</i> ] ) : <i>Geometry</i></td>
<td align="center" bgcolor="#d0f0d0">X</td>
<td align="center" bgcolor="#f0d0d0">GEOS</td>
<td>return a geometric object defined by buffering a distance d around geom,
- where dist is in the distance units for the Spatial Reference of geom</td></tr>
+ where dist is in the distance units for the Spatial Reference of geom.<hr>
+ the optional <b>quadrantsegments</b> argument specifies the number of segments used to approximate a quarter circle (default is 30).</td></tr>
<tr><td><b>ConvexHull</b></td>
<td>ConvexHull( geom <i>Geometry</i> ) : <i>Geometry</i><hr>
ST_ConvexHull( geom <i>Geometry</i> ) : <i>Geometry</i></td>
diff --git a/src/spatialite/extra_tables.c b/src/spatialite/extra_tables.c
index 80bf694..23bb562 100644
--- a/src/spatialite/extra_tables.c
+++ b/src/spatialite/extra_tables.c
@@ -969,12 +969,13 @@ create_raster_coverages (sqlite3 * sqlite)
sql = "CREATE TRIGGER raster_coverages_compression_insert\n"
"BEFORE INSERT ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
- "compression must be one of ''NONE'' | ''DEFLATE'' | ''LZMA'' | "
- "''PNG'' | ''JPEG'' | ''LOSSY_WEBP'' | ''LOSSLESS_WEBP'' | "
- "''CCITTFAX4'' | ''CHARLS'' | ''LOSSY_JP2'' | ''LOSSLESS_JP2''')\n"
- "WHERE NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', "
- "'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CCITTFAX4', "
- "'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2');\nEND";
+ "compression must be one of ''NONE'' | ''DEFLATE'' | ''DEFLATE_NO'' | "
+ "''LZMA'' | ''LZMA_NO'' | ''PNG'' | ''JPEG'' | ''LOSSY_WEBP'' | "
+ "''LOSSLESS_WEBP'' | ''CCITTFAX4'' | ''CHARLS'' | ''LOSSY_JP2'' | "
+ "''LOSSLESS_JP2''')\n"
+ "WHERE NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', "
+ "'LZMA', 'LZMA_NO', 'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', "
+ "'CCITTFAX4', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -986,12 +987,13 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE UPDATE OF 'compression' ON 'raster_coverages'"
"\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
- "compression must be one of ''NONE'' | ''DEFLATE'' | ''LZMA'' | "
- "''PNG'' | ''JPEG'' | ''LOSSY_WEBP'' | ''LOSSLESS_WEBP'' | "
- "''CCITTFAX4'' | ''CHARLS'' | ''LOSSY_JP2'' | ''LOSSLESS_JP2''')\n"
- "WHERE NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', "
- "'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CCITTFAX4', "
- "'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2');\nEND";
+ "compression must be one of ''NONE'' | ''DEFLATE'' | ''DEFLATE_NO'' | "
+ "''LZMA'' | ''LZMA_NO'' | ''PNG'' | ''JPEG'' | ''LOSSY_WEBP'' | "
+ "''LOSSLESS_WEBP'' | ''CCITTFAX4'' | ''CHARLS'' | ''LOSSY_JP2'' | "
+ "''LOSSLESS_JP2''')\n"
+ "WHERE NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', "
+ "'LZMA', 'LZMA_NO', 'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', "
+ "'CCITTFAX4', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1237,7 +1239,8 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE INSERT ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
"inconsistent MONOCHROME compression')\nWHERE NEW.pixel_type = 'MONOCHROME' "
- "AND NEW.compression NOT IN ('NONE', 'PNG', 'CCITTFAX4');\nEND";
+ "AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO', 'PNG', 'CCITTFAX4');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1249,7 +1252,8 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE UPDATE ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
"inconsistent MONOCHROME compression')\nWHERE NEW.pixel_type = 'MONOCHROME' "
- "AND NEW.compression NOT IN ('NONE', 'PNG', 'CCITTFAX4');\nEND";
+ "AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO', 'PNG', 'CCITTFAX4');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1309,7 +1313,8 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE INSERT ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
"inconsistent PALETTE compression')\nWHERE NEW.pixel_type = 'PALETTE' "
- "AND NEW.compression NOT IN ('NONE', 'PNG');\nEND";
+ "AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO', 'PNG');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1321,7 +1326,8 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE UPDATE ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
"inconsistent PALETTE compression')\nWHERE NEW.pixel_type = 'PALETTE' "
- "AND NEW.compression NOT IN ('NONE', 'PNG');\nEND";
+ "AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO', 'PNG');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1405,9 +1411,9 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE INSERT ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
"inconsistent GRAYSCALE compression')\nWHERE NEW.pixel_type = "
- "'GRAYSCALE' AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', "
- "'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CHARLS', 'LOSSY_JP2', "
- "'LOSSLESS_JP2');\nEND";
+ "'GRAYSCALE' AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', "
+ "'LZMA', 'LZMA_NO', 'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CHARLS', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1419,9 +1425,9 @@ create_raster_coverages (sqlite3 * sqlite)
"BEFORE UPDATE ON 'raster_coverages'\nFOR EACH ROW BEGIN\n"
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
"inconsistent GRAYSCALE compression')\nWHERE NEW.pixel_type = "
- "'GRAYSCALE' AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', "
- "'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CHARLS', 'LOSSY_JP2', "
- "'LOSSLESS_JP2');\nEND";
+ "'GRAYSCALE' AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', "
+ "'LZMA', 'LZMA_NO', 'PNG', 'JPEG', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CHARLS', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2');\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1458,11 +1464,11 @@ create_raster_coverages (sqlite3 * sqlite)
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
"inconsistent RGB compression')\nWHERE NEW.pixel_type = 'RGB' "
"AND ((NEW.sample_type = 'UINT8' AND NEW.compression NOT IN ("
- "'NONE', 'DEFLATE', 'LZMA', 'PNG', 'JPEG', 'LOSSY_WEBP', "
- "'LOSSLESS_WEBP', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2') OR "
- "(NEW.sample_type = 'UINT16' AND NEW.compression NOT IN "
- "('NONE', 'DEFLATE', 'LZMA', 'PNG', 'CHARLS', 'LOSSY_JP2', "
- "'LOSSLESS_JP2'))));\nEND";
+ "'NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', 'JPEG', "
+ "'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2') "
+ "OR (NEW.sample_type = 'UINT16' AND NEW.compression NOT IN "
+ "('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', 'CHARLS', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2'))));\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1475,11 +1481,11 @@ create_raster_coverages (sqlite3 * sqlite)
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
"inconsistent RGB compression')\nWHERE NEW.pixel_type = 'RGB' "
"AND ((NEW.sample_type = 'UINT8' AND NEW.compression NOT IN ("
- "'NONE', 'DEFLATE', 'LZMA', 'PNG', 'JPEG', 'LOSSY_WEBP', "
- "'LOSSLESS_WEBP', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2') OR "
- "(NEW.sample_type = 'UINT16' AND NEW.compression NOT IN "
- "('NONE', 'DEFLATE', 'LZMA', 'PNG', 'CHARLS', 'LOSSY_JP2', "
- "'LOSSLESS_JP2'))));\nEND";
+ "'NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', 'JPEG', "
+ "'LOSSY_WEBP', 'LOSSLESS_WEBP', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2') "
+ "OR (NEW.sample_type = 'UINT16' AND NEW.compression NOT IN "
+ "('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', 'CHARLS', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2'))));\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1540,14 +1546,15 @@ create_raster_coverages (sqlite3 * sqlite)
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
"inconsistent MULTIBAND compression')\nWHERE NEW.pixel_type = "
"'MULTIBAND' AND ((NEW.num_bands NOT IN (3, 4) AND "
- "NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA')) OR "
+ "NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO')) OR "
"(NEW.sample_type <> 'UINT16' AND NEW.num_bands IN (3, 4) AND "
- "NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', 'PNG', "
- "'CHARLS', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'LOSSY_JP2', "
- "'LOSSLESS_JP2')) OR (NEW.sample_type = 'UINT16' AND "
+ "NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO', 'PNG', 'CHARLS', 'LOSSY_WEBP', 'LOSSLESS_WEBP', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2')) OR (NEW.sample_type = 'UINT16' AND "
"NEW.num_bands IN (3, 4) AND NEW.compression NOT IN "
- "('NONE', 'DEFLATE', 'LZMA', 'PNG', 'CHARLS', 'LOSSY_JP2', "
- "'LOSSLESS_JP2')));\nEND";
+ "('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', "
+ "'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2')));\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1560,14 +1567,15 @@ create_raster_coverages (sqlite3 * sqlite)
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
"inconsistent MULTIBAND compression')\nWHERE NEW.pixel_type = "
"'MULTIBAND' AND ((NEW.num_bands NOT IN (3, 4) AND "
- "NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA')) OR "
+ "NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO')) OR "
"(NEW.sample_type <> 'UINT16' AND NEW.num_bands IN (3, 4) AND "
- "NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', 'PNG', "
- "'CHARLS', 'LOSSY_WEBP', 'LOSSLESS_WEBP', 'LOSSY_JP2', "
- "'LOSSLESS_JP2')) OR (NEW.sample_type = 'UINT16' AND "
+ "NEW.compression NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', "
+ "'LZMA_NO', 'PNG', 'CHARLS', 'LOSSY_WEBP', 'LOSSLESS_WEBP', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2')) OR (NEW.sample_type = 'UINT16' AND "
"NEW.num_bands IN (3, 4) AND NEW.compression NOT IN "
- "('NONE', 'DEFLATE', 'LZMA', 'PNG', 'CHARLS', 'LOSSY_JP2', "
- "'LOSSLESS_JP2')));\nEND";
+ "('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', "
+ "'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2')));\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1630,9 +1638,10 @@ create_raster_coverages (sqlite3 * sqlite)
"SELECT RAISE(ABORT,'insert on raster_coverages violates constraint: "
"inconsistent DATAGRID compression')\nWHERE NEW.pixel_type = 'DATAGRID' "
"AND (((NEW.sample_type NOT IN ('UINT8', 'UINT16')) AND NEW.compression "
- "NOT IN ('NONE', 'DEFLATE', 'LZMA')) OR ((NEW.sample_type IN ('UINT8', "
- "'UINT16')) AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', "
- "'PNG', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2')));\nEND";
+ "NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO')) OR "
+ "((NEW.sample_type IN ('UINT8', 'UINT16')) AND NEW.compression NOT IN "
+ "('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', 'CHARLS', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2')));\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
@@ -1645,9 +1654,10 @@ create_raster_coverages (sqlite3 * sqlite)
"SELECT RAISE(ABORT, 'update on raster_coverages violates constraint: "
"inconsistent DATAGRID compression')\nWHERE NEW.pixel_type = 'DATAGRID' "
"AND (((NEW.sample_type NOT IN ('UINT8', 'UINT16')) AND NEW.compression "
- "NOT IN ('NONE', 'DEFLATE', 'LZMA')) OR ((NEW.sample_type IN ('UINT8', "
- "'UINT16')) AND NEW.compression NOT IN ('NONE', 'DEFLATE', 'LZMA', "
- "'PNG', 'CHARLS', 'LOSSY_JP2', 'LOSSLESS_JP2')));\nEND";
+ "NOT IN ('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO')) OR "
+ "((NEW.sample_type IN ('UINT8', 'UINT16')) AND NEW.compression NOT IN "
+ "('NONE', 'DEFLATE', 'DEFLATE_NO', 'LZMA', 'LZMA_NO', 'PNG', 'CHARLS', "
+ "'LOSSY_JP2', 'LOSSLESS_JP2')));\nEND";
ret = sqlite3_exec (sqlite, sql, NULL, NULL, &err_msg);
if (ret != SQLITE_OK)
{
diff --git a/src/spatialite/spatialite.c b/src/spatialite/spatialite.c
index 535d7b9..2b4c6ed 100644
--- a/src/spatialite/spatialite.c
+++ b/src/spatialite/spatialite.c
@@ -173,6 +173,131 @@ struct gpkg_table
struct gpkg_table *next;
};
+
+/*
+************************************************************************
+**
+** the following code has been integrally copied from SQLite's own sources:
+** -/ext/misc/eval.c
+*/
+
+/*
+** 2014-11-10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This SQLite extension implements SQL function eval() which runs
+** SQL statements recursively.
+*/
+
+struct EvalResult
+{
+/*
+** Structure used to accumulate the output
+*/
+ char *z; /* Accumulated output */
+ const char *zSep; /* Separator */
+ int szSep; /* Size of the separator string */
+ unsigned int nAlloc; /* Number of bytes allocated for z[] */
+ int nUsed; /* Number of bytes of z[] actually used */
+};
+
+static int
+eval_callback (void *pCtx, int argc, char **argv, char **colnames)
+{
+/*
+** Callback from sqlite_exec() for the eval() function.
+*/
+ struct EvalResult *p = (struct EvalResult *) pCtx;
+ int i;
+
+ if (colnames == NULL)
+ colnames = NULL; /* silencing stupid compiler warnings */
+
+ for (i = 0; i < argc; i++)
+ {
+ const char *z = argv[i] ? argv[i] : "";
+ size_t sz = strlen (z);
+ if (sz + p->nUsed + p->szSep + 1 > p->nAlloc)
+ {
+ char *zNew;
+ p->nAlloc = p->nAlloc * 2 + sz + p->szSep + 1;
+ zNew = sqlite3_realloc (p->z, p->nAlloc);
+ if (zNew == 0)
+ {
+ sqlite3_free (p->z);
+ memset (p, 0, sizeof (*p));
+ return 1;
+ }
+ p->z = zNew;
+ }
+ if (p->nUsed > 0)
+ {
+ memcpy (&p->z[p->nUsed], p->zSep, p->szSep);
+ p->nUsed += p->szSep;
+ }
+ memcpy (&p->z[p->nUsed], z, sz);
+ p->nUsed += sz;
+ }
+ return 0;
+}
+
+static void
+fnct_EvalFunc (sqlite3_context * context, int argc, sqlite3_value ** argv)
+{
+/*
+** Implementation of the eval(X) and eval(X,Y) SQL functions.
+**
+** Evaluate the SQL text in X. Return the results, using string
+** Y as the separator. If Y is omitted, use a single space character.
+*/
+ const char *zSql;
+ sqlite3 *db;
+ char *zErr = 0;
+ int rc;
+ struct EvalResult x;
+
+ memset (&x, 0, sizeof (x));
+ x.zSep = " ";
+ zSql = (const char *) sqlite3_value_text (argv[0]);
+ if (zSql == 0)
+ return;
+ if (argc > 1)
+ {
+ x.zSep = (const char *) sqlite3_value_text (argv[1]);
+ if (x.zSep == 0)
+ return;
+ }
+ x.szSep = (int) strlen (x.zSep);
+ db = sqlite3_context_db_handle (context);
+ rc = sqlite3_exec (db, zSql, eval_callback, &x, &zErr);
+ if (rc != SQLITE_OK)
+ {
+ sqlite3_result_error (context, zErr, -1);
+ sqlite3_free (zErr);
+ }
+ else if (x.zSep == 0)
+ {
+ sqlite3_result_error_nomem (context);
+ sqlite3_free (x.z);
+ }
+ else
+ {
+ sqlite3_result_text (context, x.z, x.nUsed, sqlite3_free);
+ }
+}
+
+/*
+******** end -/ext/misc/eval.c *****
+*/
+
static void
fnct_spatialite_version (sqlite3_context * context, int argc,
sqlite3_value ** argv)
@@ -18107,6 +18232,7 @@ fnct_Buffer (sqlite3_context * context, int argc, sqlite3_value ** argv)
{
/* SQL function:
/ Buffer(BLOBencoded geometry, radius)
+/ Buffer(BLOBencoded geometry, radius, quadrantsegments)
/
/ returns a new geometry representing the BUFFER for current geometry
/ or NULL if any error is encountered
@@ -18117,6 +18243,7 @@ fnct_Buffer (sqlite3_context * context, int argc, sqlite3_value ** argv)
gaiaGeomCollPtr result;
double radius;
int int_value;
+ int quadrantsegments = 30;
GAIA_UNUSED (); /* LCOV_EXCL_LINE */
if (sqlite3_value_type (argv[0]) != SQLITE_BLOB)
{
@@ -18135,6 +18262,17 @@ fnct_Buffer (sqlite3_context * context, int argc, sqlite3_value ** argv)
sqlite3_result_null (context);
return;
}
+ if (argc == 3)
+ {
+ if (sqlite3_value_type (argv[2]) != SQLITE_INTEGER)
+ {
+ sqlite3_result_null (context);
+ return;
+ }
+ quadrantsegments = sqlite3_value_int (argv[2]);
+ if (quadrantsegments <= 0)
+ quadrantsegments = 1;
+ }
p_blob = (unsigned char *) sqlite3_value_blob (argv[0]);
n_bytes = sqlite3_value_bytes (argv[0]);
geo = gaiaFromSpatiaLiteBlobWkb (p_blob, n_bytes);
@@ -18144,9 +18282,10 @@ fnct_Buffer (sqlite3_context * context, int argc, sqlite3_value ** argv)
{
void *data = sqlite3_user_data (context);
if (data != NULL)
- result = gaiaGeomCollBuffer_r (data, geo, radius, 30);
+ result =
+ gaiaGeomCollBuffer_r (data, geo, radius, quadrantsegments);
else
- result = gaiaGeomCollBuffer (geo, radius, 30);
+ result = gaiaGeomCollBuffer (geo, radius, quadrantsegments);
if (!result)
sqlite3_result_null (context);
else
@@ -30232,6 +30371,11 @@ register_spatialite_sql_functions (void *p_db, const void *p_cache)
SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
fnct_CloneTable, 0, 0, 0);
+ sqlite3_create_function_v2 (db, "eval", 1, SQLITE_UTF8, 0, fnct_EvalFunc, 0,
+ 0, 0);
+ sqlite3_create_function_v2 (db, "eval", 2, SQLITE_UTF8, 0, fnct_EvalFunc, 0,
+ 0, 0);
+
#ifndef OMIT_PROJ /* PROJ.4 is strictly required to support KML */
sqlite3_create_function_v2 (db, "AsKml", 1,
SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
@@ -31879,6 +32023,12 @@ register_spatialite_sql_functions (void *p_db, const void *p_cache)
sqlite3_create_function_v2 (db, "ST_Buffer", 2,
SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
fnct_Buffer, 0, 0, 0);
+ sqlite3_create_function_v2 (db, "Buffer", 3,
+ SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
+ fnct_Buffer, 0, 0, 0);
+ sqlite3_create_function_v2 (db, "ST_Buffer", 3,
+ SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
+ fnct_Buffer, 0, 0, 0);
sqlite3_create_function_v2 (db, "Intersection", 2,
SQLITE_UTF8 | SQLITE_DETERMINISTIC, cache,
fnct_Intersection, 0, 0, 0);
diff --git a/src/spatialite/virtualXL.c b/src/spatialite/virtualXL.c
index 9bde0f4..6470b2c 100644
--- a/src/spatialite/virtualXL.c
+++ b/src/spatialite/virtualXL.c
@@ -901,6 +901,17 @@ vXL_rollback (sqlite3_vtab * pVTab)
}
static int
+vXL_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualXLInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -923,6 +934,7 @@ spliteVirtualXLInit (sqlite3 * db)
my_XL_module.xCommit = &vXL_commit;
my_XL_module.xRollback = &vXL_rollback;
my_XL_module.xFindFunction = NULL;
+ my_XL_module.xRename = &vXL_rename;
sqlite3_create_module_v2 (db, "VirtualXL", &my_XL_module, NULL, 0);
return rc;
}
diff --git a/src/spatialite/virtualbbox.c b/src/spatialite/virtualbbox.c
index f4338c8..1014894 100644
--- a/src/spatialite/virtualbbox.c
+++ b/src/spatialite/virtualbbox.c
@@ -951,6 +951,17 @@ vbbox_rollback (sqlite3_vtab * pVTab)
}
static int
+vbox_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualBBoxInit (sqlite3 * db, void *p_cache)
{
int rc = SQLITE_OK;
@@ -973,6 +984,7 @@ spliteVirtualBBoxInit (sqlite3 * db, void *p_cache)
my_bbox_module.xCommit = &vbbox_commit;
my_bbox_module.xRollback = &vbbox_rollback;
my_bbox_module.xFindFunction = NULL;
+ my_bbox_module.xRename = &vbox_rename;
sqlite3_create_module_v2 (db, "VirtualBBox", &my_bbox_module, p_cache, 0);
return rc;
}
diff --git a/src/spatialite/virtualdbf.c b/src/spatialite/virtualdbf.c
index 2ff1f61..8b0c0a4 100644
--- a/src/spatialite/virtualdbf.c
+++ b/src/spatialite/virtualdbf.c
@@ -887,6 +887,17 @@ vdbf_rollback (sqlite3_vtab * pVTab)
}
static int
+vdbf_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualDbfInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -909,6 +920,7 @@ spliteVirtualDbfInit (sqlite3 * db)
my_dbf_module.xCommit = &vdbf_commit;
my_dbf_module.xRollback = &vdbf_rollback;
my_dbf_module.xFindFunction = NULL;
+ my_dbf_module.xRename = &vdbf_rename;
sqlite3_create_module_v2 (db, "VirtualDbf", &my_dbf_module, NULL, 0);
return rc;
}
diff --git a/src/spatialite/virtualelementary.c b/src/spatialite/virtualelementary.c
index d7872b0..78f117f 100644
--- a/src/spatialite/virtualelementary.c
+++ b/src/spatialite/virtualelementary.c
@@ -1028,6 +1028,17 @@ velem_rollback (sqlite3_vtab * pVTab)
}
static int
+velem_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualElementaryInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -1050,6 +1061,7 @@ spliteVirtualElementaryInit (sqlite3 * db)
my_elem_module.xCommit = &velem_commit;
my_elem_module.xRollback = &velem_rollback;
my_elem_module.xFindFunction = NULL;
+ my_elem_module.xRename = &velem_rename;
sqlite3_create_module_v2 (db, "VirtualElementary", &my_elem_module, NULL,
0);
return rc;
diff --git a/src/spatialite/virtualfdo.c b/src/spatialite/virtualfdo.c
index cdc8abc..d06cfd5 100644
--- a/src/spatialite/virtualfdo.c
+++ b/src/spatialite/virtualfdo.c
@@ -2162,6 +2162,17 @@ vfdo_rollback (sqlite3_vtab * pVTab)
}
static int
+vfdo_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualFDOInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -2184,6 +2195,7 @@ spliteVirtualFDOInit (sqlite3 * db)
my_fdo_module.xCommit = &vfdo_commit;
my_fdo_module.xRollback = &vfdo_rollback;
my_fdo_module.xFindFunction = NULL;
+ my_fdo_module.xRename = &vfdo_rename;
sqlite3_create_module_v2 (db, "VirtualFDO", &my_fdo_module, NULL, 0);
return rc;
}
diff --git a/src/spatialite/virtualgpkg.c b/src/spatialite/virtualgpkg.c
index d1cbe04..b8dd750 100644
--- a/src/spatialite/virtualgpkg.c
+++ b/src/spatialite/virtualgpkg.c
@@ -1041,6 +1041,17 @@ vgpkg_rollback (sqlite3_vtab * pVTab)
}
static int
+vgpkg_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualGPKGInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -1063,6 +1074,7 @@ spliteVirtualGPKGInit (sqlite3 * db)
my_gpkg_module.xCommit = &vgpkg_commit;
my_gpkg_module.xRollback = &vgpkg_rollback;
my_gpkg_module.xFindFunction = NULL;
+ my_gpkg_module.xRename = &vgpkg_rename;
sqlite3_create_module_v2 (db, "VirtualGPKG", &my_gpkg_module, NULL, 0);
return rc;
}
diff --git a/src/spatialite/virtualnetwork.c b/src/spatialite/virtualnetwork.c
index 5591e94..0b11f7f 100644
--- a/src/spatialite/virtualnetwork.c
+++ b/src/spatialite/virtualnetwork.c
@@ -68,6 +68,11 @@ static struct sqlite3_module my_net_module;
#define VNET_DIJKSTRA_ALGORITHM 1
#define VNET_A_STAR_ALGORITHM 2
+#define VNET_ROUTING_SOLUTION 0xdd
+#define VNET_RANGE_SOLUTION 0xbb
+
+#define VNET_INVALID_SRID -1234
+
#ifdef _WIN32
#define strcasecmp _stricmp
#endif /* not WIN32 */
@@ -148,16 +153,32 @@ typedef struct RowSolutionStruct
} RowSolution;
typedef RowSolution *RowSolutionPtr;
+typedef struct RowNodeSolutionStruct
+{
+/* a row into the "within Cost range" solution */
+ NetworkNodePtr Node;
+ double Cost;
+ int Srid;
+ struct RowNodeSolutionStruct *Next;
+
+} RowNodeSolution;
+typedef RowNodeSolution *RowNodeSolutionPtr;
+
typedef struct SolutionStruct
{
/* the shortest path solution */
+ unsigned char Mode;
ArcSolutionPtr FirstArc;
ArcSolutionPtr LastArc;
NetworkNodePtr From;
NetworkNodePtr To;
+ double MaxCost;
RowSolutionPtr First;
RowSolutionPtr Last;
+ RowNodeSolutionPtr FirstNode;
+ RowNodeSolutionPtr LastNode;
RowSolutionPtr CurrentRow;
+ RowNodeSolutionPtr CurrentNodeRow;
sqlite3_int64 CurrentRowId;
double TotalCost;
gaiaGeomCollPtr Geometry;
@@ -177,6 +198,7 @@ typedef struct RoutingNode
NetworkArcPtr *Link;
int DimTo;
struct RoutingNode *PreviousNode;
+ NetworkNodePtr Node;
NetworkArcPtr Arc;
double Distance;
double HeuristicDistance;
@@ -194,11 +216,17 @@ typedef struct RoutingNodes
} RoutingNodes;
typedef RoutingNodes *RoutingNodesPtr;
+typedef struct HeapNode
+{
+ RoutingNodePtr Node;
+ double Distance;
+} HeapNode;
+typedef HeapNode *HeapNodePtr;
+
typedef struct RoutingHeapStruct
{
- RoutingNodePtr *Values;
- int Head;
- int Tail;
+ HeapNodePtr Nodes;
+ int Count;
} RoutingHeap;
typedef RoutingHeap *RoutingHeapPtr;
@@ -271,6 +299,7 @@ routing_init (NetworkPtr graph)
ndn = nd->Nodes + i;
ndn->Id = nn->InternalIndex;
ndn->DimTo = nn->NumArcs;
+ ndn->Node = nn;
ndn->To = &(nd->NodesBuffer[cnt]);
ndn->Link = &(nd->ArcsBuffer[cnt]);
cnt += nn->NumArcs;
@@ -297,59 +326,101 @@ routing_free (RoutingNodes * e)
}
static RoutingHeapPtr
-routing_heap_init (int dim)
-{
-/* allocating the Nodes ordered list */
- RoutingHeapPtr h;
- h = malloc (sizeof (RoutingHeap));
- h->Values = malloc (sizeof (RoutingNodePtr) * dim);
- h->Head = 0;
- h->Tail = 0;
- return (h);
+routing_heap_init (int n)
+{
+/* allocating and initializing the Heap (min-priority queue) */
+ RoutingHeapPtr heap = malloc (sizeof (RoutingHeap));
+ heap->Count = 0;
+ heap->Nodes = malloc (sizeof (HeapNode) * (n + 1));
+ return heap;
}
static void
-routing_heap_free (RoutingHeapPtr h)
+routing_heap_free (RoutingHeapPtr heap)
{
-/* freeing the Nodes ordered list */
- free (h->Values);
- free (h);
+/* freeing the Heap (min-priority queue) */
+ if (heap->Nodes != NULL)
+ free (heap->Nodes);
+ free (heap);
}
static void
-routing_push (RoutingHeapPtr h, RoutingNodePtr n)
+dijkstra_insert (RoutingNodePtr node, HeapNodePtr heap, int size)
{
-/* inserting a Node into the list */
- h->Values[h->Tail] = n;
- h->Tail++;
+/* inserting a new Node and rearranging the heap */
+ int i;
+ HeapNode tmp;
+ i = size + 1;
+ heap[i].Node = node;
+ heap[i].Distance = node->Distance;
+ if (i / 2 < 1)
+ return;
+ while (heap[i].Distance < heap[i / 2].Distance)
+ {
+ tmp = heap[i];
+ heap[i] = heap[i / 2];
+ heap[i / 2] = tmp;
+ i /= 2;
+ if (i / 2 < 1)
+ break;
+ }
}
-static RoutingNodePtr
-dijkstra_pop (RoutingHeapPtr h)
+static void
+dijkstra_enqueue (RoutingHeapPtr heap, RoutingNodePtr node)
{
-/* fetching the minimum value */
- int i;
- RoutingNodePtr n;
- double min = DBL_MAX;
- int i_min = h->Head;
- for (i = h->Head; i < h->Tail; i++)
+/* enqueuing a Node into the heap */
+ dijkstra_insert (node, heap->Nodes, heap->Count);
+ heap->Count += 1;
+}
+
+static void
+dijkstra_shiftdown (HeapNodePtr heap, int size, int i)
+{
+/* rearranging the heap after removing */
+ int c;
+ HeapNode tmp;
+ for (;;)
{
- n = h->Values[i];
- if (n->Distance < min)
+ c = i * 2;
+ if (c > size)
+ break;
+ if (c < size)
{
- min = n->Distance;
- i_min = i;
+ if (heap[c].Distance > heap[c + 1].Distance)
+ ++c;
}
+ if (heap[c].Distance < heap[i].Distance)
+ {
+ /* swapping two Nodes */
+ tmp = heap[c];
+ heap[c] = heap[i];
+ heap[i] = tmp;
+ i = c;
+ }
+ else
+ break;
}
- if (i_min > h->Head)
- {
- n = h->Values[i_min];
- h->Values[i_min] = h->Values[h->Head];
- h->Values[h->Head] = n;
- }
- n = h->Values[h->Head];
- h->Head++;
- return (n);
+}
+
+static RoutingNodePtr
+dijkstra_remove_min (HeapNodePtr heap, int size)
+{
+/* removing the min-priority Node from the heap */
+ RoutingNodePtr node = heap[1].Node;
+ heap[1] = heap[size];
+ --size;
+ dijkstra_shiftdown (heap, size, 1);
+ return node;
+}
+
+static RoutingNodePtr
+routing_dequeue (RoutingHeapPtr heap)
+{
+/* dequeuing a Node from the heap */
+ RoutingNodePtr node = dijkstra_remove_min (heap->Nodes, heap->Count);
+ heap->Count -= 1;
+ return node;
}
static NetworkArcPtr *
@@ -366,12 +437,12 @@ dijkstra_shortest_path (RoutingNodesPtr e, NetworkNodePtr pfrom,
NetworkArcPtr p_link;
int cnt;
NetworkArcPtr *result;
- RoutingHeapPtr h;
+ RoutingHeapPtr heap;
/* setting From/To */
from = pfrom->InternalIndex;
to = pto->InternalIndex;
/* initializing the heap */
- h = routing_heap_init (e->DimLink);
+ heap = routing_heap_init (e->DimLink);
/* initializing the graph */
for (i = 0; i < e->Dim; i++)
{
@@ -381,13 +452,13 @@ dijkstra_shortest_path (RoutingNodesPtr e, NetworkNodePtr pfrom,
n->Inspected = 0;
n->Distance = DBL_MAX;
}
-/* pushes the From node into the Nodes list */
+/* queuing the From node into the heap */
e->Nodes[from].Distance = 0.0;
- routing_push (h, e->Nodes + from);
- while (h->Tail != h->Head)
+ dijkstra_enqueue (heap, e->Nodes + from);
+ while (heap->Count > 0)
{
/* Dijsktra loop */
- n = dijkstra_pop (h);
+ n = routing_dequeue (heap);
if (n->Id == to)
{
/* destination reached */
@@ -402,11 +473,11 @@ dijkstra_shortest_path (RoutingNodesPtr e, NetworkNodePtr pfrom,
{
if (p_to->Distance == DBL_MAX)
{
- /* inserting a new node into the list */
+ /* queuing a new node into the heap */
p_to->Distance = n->Distance + p_link->Cost;
p_to->PreviousNode = n;
p_to->Arc = p_link;
- routing_push (h, p_to);
+ dijkstra_enqueue (heap, p_to);
}
else if (p_to->Distance > n->Distance + p_link->Cost)
{
@@ -418,7 +489,7 @@ dijkstra_shortest_path (RoutingNodesPtr e, NetworkNodePtr pfrom,
}
}
}
- routing_heap_free (h);
+ routing_heap_free (heap);
cnt = 0;
n = e->Nodes + to;
while (n->PreviousNode != NULL)
@@ -444,42 +515,128 @@ dijkstra_shortest_path (RoutingNodesPtr e, NetworkNodePtr pfrom,
/* END of Luigi Costalli Dijkstra Shortest Path implementation */
+static RoutingNodePtr *
+dijkstra_range_analysis (RoutingNodesPtr e, NetworkNodePtr pfrom,
+ double max_cost, int *ll)
+{
+/* identifying all Nodes within a given Cost range - Dijkstra's algorithm */
+ int from;
+ int i;
+ RoutingNodePtr p_to;
+ RoutingNodePtr n;
+ NetworkArcPtr p_link;
+ int cnt;
+ RoutingNodePtr *result;
+ RoutingHeapPtr heap;
+/* setting From */
+ from = pfrom->InternalIndex;
+/* initializing the heap */
+ heap = routing_heap_init (e->DimLink);
+/* initializing the graph */
+ for (i = 0; i < e->Dim; i++)
+ {
+ n = e->Nodes + i;
+ n->PreviousNode = NULL;
+ n->Arc = NULL;
+ n->Inspected = 0;
+ n->Distance = DBL_MAX;
+ }
+/* queuing the From node into the heap */
+ e->Nodes[from].Distance = 0.0;
+ dijkstra_enqueue (heap, e->Nodes + from);
+ while (heap->Count > 0)
+ {
+ /* Dijsktra loop */
+ n = routing_dequeue (heap);
+ n->Inspected = 1;
+ for (i = 0; i < n->DimTo; i++)
+ {
+ p_to = *(n->To + i);
+ p_link = *(n->Link + i);
+ if (p_to->Inspected == 0)
+ {
+ if (p_to->Distance == DBL_MAX)
+ {
+ /* queuing a new node into the heap */
+ if (n->Distance + p_link->Cost <= max_cost)
+ {
+ p_to->Distance = n->Distance + p_link->Cost;
+ p_to->PreviousNode = n;
+ p_to->Arc = p_link;
+ dijkstra_enqueue (heap, p_to);
+ }
+ }
+ else if (p_to->Distance > n->Distance + p_link->Cost)
+ {
+ /* updating an already inserted node */
+ p_to->Distance = n->Distance + p_link->Cost;
+ p_to->PreviousNode = n;
+ p_to->Arc = p_link;
+ }
+ }
+ }
+ }
+ routing_heap_free (heap);
+ cnt = 0;
+ for (i = 0; i < e->Dim; i++)
+ {
+ /* counting how many traversed Nodes */
+ n = e->Nodes + i;
+ if (n->Inspected)
+ cnt++;
+ }
+/* allocating the solution */
+ result = malloc (sizeof (NetworkNodePtr) * cnt);
+ cnt = 0;
+ for (i = 0; i < e->Dim; i++)
+ {
+ /* populating the resultset */
+ n = e->Nodes + i;
+ if (n->Inspected)
+ result[cnt++] = n;
+ }
+ *ll = cnt;
+ return (result);
+}
+
/*
/
/ implementation of the A* Shortest Path algorithm
/
*/
-static RoutingNodePtr
-a_star_pop (RoutingHeapPtr h)
+static void
+astar_insert (RoutingNodePtr node, HeapNodePtr heap, int size)
{
-/* fetching the minimum value */
+/* inserting a new Node and rearranging the heap */
int i;
- RoutingNodePtr n;
- double min = DBL_MAX;
- int i_min = h->Head;
- for (i = h->Head; i < h->Tail; i++)
- {
- n = h->Values[i];
- if (n->HeuristicDistance < min)
- {
- min = n->HeuristicDistance;
- i_min = i;
- }
- }
- if (i_min > h->Head)
+ HeapNode tmp;
+ i = size + 1;
+ heap[i].Node = node;
+ heap[i].Distance = node->HeuristicDistance;
+ if (i / 2 < 1)
+ return;
+ while (heap[i].Distance < heap[i / 2].Distance)
{
- n = h->Values[i_min];
- h->Values[i_min] = h->Values[h->Head];
- h->Values[h->Head] = n;
+ tmp = heap[i];
+ heap[i] = heap[i / 2];
+ heap[i / 2] = tmp;
+ i /= 2;
+ if (i / 2 < 1)
+ break;
}
- n = h->Values[h->Head];
- h->Head++;
- return (n);
+}
+
+static void
+astar_enqueue (RoutingHeapPtr heap, RoutingNodePtr node)
+{
+/* enqueuing a Node into the heap */
+ astar_insert (node, heap->Nodes, heap->Count);
+ heap->Count += 1;
}
static double
-a_star_heuristic_distance (NetworkNodePtr n1, NetworkNodePtr n2, double coeff)
+astar_heuristic_distance (NetworkNodePtr n1, NetworkNodePtr n2, double coeff)
{
/* computing the euclidean distance intercurring between two nodes */
double dx = n1->CoordX - n2->CoordX;
@@ -489,9 +646,9 @@ a_star_heuristic_distance (NetworkNodePtr n1, NetworkNodePtr n2, double coeff)
}
static NetworkArcPtr *
-a_star_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
- NetworkNodePtr pfrom, NetworkNodePtr pto,
- double heuristic_coeff, int *ll)
+astar_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
+ NetworkNodePtr pfrom, NetworkNodePtr pto,
+ double heuristic_coeff, int *ll)
{
/* identifying the Shortest Path - A* algorithm */
int from;
@@ -506,7 +663,7 @@ a_star_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
NetworkArcPtr p_link;
int cnt;
NetworkArcPtr *result;
- RoutingHeapPtr h;
+ RoutingHeapPtr heap;
/* setting From/To */
from = pfrom->InternalIndex;
to = pto->InternalIndex;
@@ -515,7 +672,7 @@ a_star_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
pAux = e->Nodes + to;
pDest = nodes + pAux->Id;
/* initializing the heap */
- h = routing_heap_init (e->DimLink);
+ heap = routing_heap_init (e->DimLink);
/* initializing the graph */
for (i = 0; i < e->Dim; i++)
{
@@ -526,15 +683,15 @@ a_star_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
n->Distance = DBL_MAX;
n->HeuristicDistance = DBL_MAX;
}
-/* pushes the From node into the Nodes list */
+/* queuing the From node into the heap */
e->Nodes[from].Distance = 0.0;
e->Nodes[from].HeuristicDistance =
- a_star_heuristic_distance (pOrg, pDest, heuristic_coeff);
- routing_push (h, e->Nodes + from);
- while (h->Tail != h->Head)
+ astar_heuristic_distance (pOrg, pDest, heuristic_coeff);
+ astar_enqueue (heap, e->Nodes + from);
+ while (heap->Count > 0)
{
/* A* loop */
- n = a_star_pop (h);
+ n = routing_dequeue (heap);
if (n->Id == to)
{
/* destination reached */
@@ -549,16 +706,16 @@ a_star_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
{
if (p_to->Distance == DBL_MAX)
{
- /* inserting a new node into the list */
+ /* queuing a new node into the heap */
p_to->Distance = n->Distance + p_link->Cost;
pOrg = nodes + p_to->Id;
p_to->HeuristicDistance =
p_to->Distance +
- a_star_heuristic_distance (pOrg, pDest,
- heuristic_coeff);
+ astar_heuristic_distance (pOrg, pDest,
+ heuristic_coeff);
p_to->PreviousNode = n;
p_to->Arc = p_link;
- routing_push (h, p_to);
+ astar_enqueue (heap, p_to);
}
else if (p_to->Distance > n->Distance + p_link->Cost)
{
@@ -567,15 +724,15 @@ a_star_shortest_path (RoutingNodesPtr e, NetworkNodePtr nodes,
pOrg = nodes + p_to->Id;
p_to->HeuristicDistance =
p_to->Distance +
- a_star_heuristic_distance (pOrg, pDest,
- heuristic_coeff);
+ astar_heuristic_distance (pOrg, pDest,
+ heuristic_coeff);
p_to->PreviousNode = n;
p_to->Arc = p_link;
}
}
}
}
- routing_heap_free (h);
+ routing_heap_free (heap);
cnt = 0;
n = e->Nodes + to;
while (n->PreviousNode != NULL)
@@ -657,6 +814,8 @@ delete_solution (SolutionPtr solution)
ArcSolutionPtr pAn;
RowSolutionPtr pR;
RowSolutionPtr pRn;
+ RowNodeSolutionPtr pN;
+ RowNodeSolutionPtr pNn;
if (!solution)
return;
pA = solution->FirstArc;
@@ -683,6 +842,13 @@ delete_solution (SolutionPtr solution)
free (pR);
pR = pRn;
}
+ pN = solution->FirstNode;
+ while (pN)
+ {
+ pNn = pN->Next;
+ free (pN);
+ pN = pNn;
+ }
if (solution->Geometry)
gaiaFreeGeomColl (solution->Geometry);
free (solution);
@@ -696,6 +862,8 @@ reset_solution (SolutionPtr solution)
ArcSolutionPtr pAn;
RowSolutionPtr pR;
RowSolutionPtr pRn;
+ RowNodeSolutionPtr pN;
+ RowNodeSolutionPtr pNn;
if (!solution)
return;
pA = solution->FirstArc;
@@ -720,15 +888,24 @@ reset_solution (SolutionPtr solution)
free (pR);
pR = pRn;
}
+ pN = solution->FirstNode;
+ while (pN)
+ {
+ pNn = pN->Next;
+ free (pN);
+ pN = pNn;
+ }
if (solution->Geometry)
gaiaFreeGeomColl (solution->Geometry);
solution->FirstArc = NULL;
solution->LastArc = NULL;
solution->From = NULL;
solution->To = NULL;
+ solution->MaxCost = 0.0;
solution->First = NULL;
solution->Last = NULL;
solution->CurrentRow = NULL;
+ solution->CurrentNodeRow = NULL;
solution->CurrentRowId = 0;
solution->TotalCost = 0.0;
solution->Geometry = NULL;
@@ -743,9 +920,13 @@ alloc_solution (void)
p->LastArc = NULL;
p->From = NULL;
p->To = NULL;
+ p->MaxCost = 0.0;
p->First = NULL;
p->Last = NULL;
+ p->FirstNode = NULL;
+ p->LastNode = NULL;
p->CurrentRow = NULL;
+ p->CurrentNodeRow = NULL;
p->CurrentRowId = 0;
p->TotalCost = 0.0;
p->Geometry = NULL;
@@ -769,6 +950,43 @@ add_arc_to_solution (SolutionPtr solution, NetworkArcPtr arc)
}
static void
+add_node_to_solution (SolutionPtr solution, RoutingNodePtr node, int srid)
+{
+/* inserts a Node into the "within Cost range" solution */
+ RowNodeSolutionPtr p = malloc (sizeof (RowNodeSolution));
+ p->Node = node->Node;
+ p->Cost = node->Distance;
+ p->Srid = srid;
+ p->Next = NULL;
+ if (!(solution->FirstNode))
+ solution->FirstNode = p;
+ if (solution->LastNode)
+ solution->LastNode->Next = p;
+ solution->LastNode = p;
+}
+
+static void
+set_arc_name_into_solution (SolutionPtr solution, sqlite3_int64 arc_id,
+ const char *name)
+{
+/* sets the Name identifyin an Arc into the Solution */
+ RowSolutionPtr row = solution->First;
+ while (row != NULL)
+ {
+ if (row->Arc->ArcRowid == arc_id)
+ {
+ int len = strlen (name);
+ if (row->Name != NULL)
+ free (row->Name);
+ row->Name = malloc (len + 1);
+ strcpy (row->Name, name);
+ return;
+ }
+ row = row->Next;
+ }
+}
+
+static void
add_arc_geometry_to_solution (SolutionPtr solution, sqlite3_int64 arc_id,
const char *from_code, const char *to_code,
sqlite3_int64 from_id, sqlite3_int64 to_id,
@@ -852,6 +1070,13 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
add_arc_to_solution (solution, shortest_path[i]);
}
}
+
+ if (graph->GeometryColumn == NULL && graph->NameColumn == NULL)
+ {
+ /* completely skipping Geometry */
+ return;
+ }
+
tbd = cnt;
while (tbd > 0)
{
@@ -865,20 +1090,38 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
if (graph->NameColumn)
{
/* a Name column is defined */
- xfrom = gaiaDoubleQuotedSql (graph->FromColumn);
- xto = gaiaDoubleQuotedSql (graph->ToColumn);
- xgeom = gaiaDoubleQuotedSql (graph->GeometryColumn);
- xname = gaiaDoubleQuotedSql (graph->NameColumn);
- xtable = gaiaDoubleQuotedSql (graph->TableName);
- sql =
- sqlite3_mprintf
- ("SELECT ROWID, \"%s\", \"%s\", \"%s\", \"%s\" FROM \"%s\" WHERE ROWID IN (",
- xfrom, xto, xgeom, xname, xtable);
- free (xfrom);
- free (xto);
- free (xgeom);
- free (xname);
- free (xtable);
+ if (graph->GeometryColumn == NULL)
+ {
+ xfrom = gaiaDoubleQuotedSql (graph->FromColumn);
+ xto = gaiaDoubleQuotedSql (graph->ToColumn);
+ xname = gaiaDoubleQuotedSql (graph->NameColumn);
+ xtable = gaiaDoubleQuotedSql (graph->TableName);
+ sql =
+ sqlite3_mprintf
+ ("SELECT ROWID, \"%s\", \"%s\", NULL, \"%s\" FROM \"%s\" WHERE ROWID IN (",
+ xfrom, xto, xname, xtable);
+ free (xfrom);
+ free (xto);
+ free (xname);
+ free (xtable);
+ }
+ else
+ {
+ xfrom = gaiaDoubleQuotedSql (graph->FromColumn);
+ xto = gaiaDoubleQuotedSql (graph->ToColumn);
+ xgeom = gaiaDoubleQuotedSql (graph->GeometryColumn);
+ xname = gaiaDoubleQuotedSql (graph->NameColumn);
+ xtable = gaiaDoubleQuotedSql (graph->TableName);
+ sql =
+ sqlite3_mprintf
+ ("SELECT ROWID, \"%s\", \"%s\", \"%s\", \"%s\" FROM \"%s\" WHERE ROWID IN (",
+ xfrom, xto, xgeom, xname, xtable);
+ free (xfrom);
+ free (xto);
+ free (xgeom);
+ free (xname);
+ free (xtable);
+ }
gaiaAppendToOutBuffer (&sql_statement, sql);
sqlite3_free (sql);
}
@@ -979,15 +1222,18 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
else
err = 1;
}
- if (sqlite3_column_type (stmt, 3) == SQLITE_BLOB)
+ if (graph->GeometryColumn != NULL)
{
- blob =
- (const unsigned char *)
- sqlite3_column_blob (stmt, 3);
- size = sqlite3_column_bytes (stmt, 3);
+ if (sqlite3_column_type (stmt, 3) == SQLITE_BLOB)
+ {
+ blob =
+ (const unsigned char *)
+ sqlite3_column_blob (stmt, 3);
+ size = sqlite3_column_bytes (stmt, 3);
+ }
+ else
+ err = 1;
}
- else
- err = 1;
if (graph->NameColumn)
{
if (sqlite3_column_type (stmt, 4) == SQLITE_TEXT)
@@ -995,7 +1241,7 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
}
if (err)
error = 1;
- else
+ else if (graph->GeometryColumn != NULL)
{
/* saving the Arc geometry into the temporary struct */
gaiaGeomCollPtr geom =
@@ -1021,8 +1267,9 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
double x;
double y;
gaiaGetPoint
- (geom->FirstLinestring->
- Coords, iv, &x, &y);
+ (geom->
+ FirstLinestring->Coords, iv,
+ &x, &y);
*(coords + ((iv * 2) + 0)) = x;
*(coords + ((iv * 2) + 1)) = y;
}
@@ -1038,8 +1285,7 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
to_id,
points,
coords,
- geom->
- Srid,
+ geom->Srid,
name);
}
else
@@ -1049,6 +1295,8 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
else
error = 1;
}
+ else if (name != NULL)
+ set_arc_name_into_solution (solution, arc_id, name);
}
}
sqlite3_finalize (stmt);
@@ -1058,7 +1306,7 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
abort:
if (shortest_path)
free (shortest_path);
- if (!error)
+ if (!error && graph->GeometryColumn != NULL)
{
/* building the Geometry representing the Shortest Path Solution */
gaiaLinestringPtr ln;
@@ -1179,6 +1427,54 @@ build_solution (sqlite3 * handle, NetworkPtr graph, SolutionPtr solution,
}
}
+static int
+find_srid (sqlite3 * handle, NetworkPtr graph)
+{
+/* attempting to retrieve the appropriate Srid */
+ sqlite3_stmt *stmt;
+ int ret;
+ int srid = VNET_INVALID_SRID;
+ char *sql;
+
+ if (graph->GeometryColumn == NULL)
+ return srid;
+
+ sql = sqlite3_mprintf ("SELECT srid FROM geometry_columns WHERE "
+ "Lower(f_table_name) = Lower(%Q) AND Lower(f_geometry_column) = Lower(%Q)",
+ graph->TableName, graph->GeometryColumn);
+ ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
+ if (ret != SQLITE_OK)
+ return srid;
+ while (1)
+ {
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE)
+ break;
+ if (ret == SQLITE_ROW)
+ srid = sqlite3_column_int (stmt, 0);
+ }
+ sqlite3_finalize (stmt);
+ return srid;
+}
+
+static void
+build_range_solution (SolutionPtr solution,
+ RoutingNodePtr * range_nodes, int cnt, int srid)
+{
+/* formatting the "within Cost range" solution */
+ int i;
+ if (cnt > 0)
+ {
+ /* building the solution */
+ for (i = 0; i < cnt; i++)
+ {
+ add_node_to_solution (solution, range_nodes[i], srid);
+ }
+ }
+ if (range_nodes)
+ free (range_nodes);
+}
+
static void
dijkstra_solve (sqlite3 * handle, NetworkPtr graph, RoutingNodesPtr routing,
SolutionPtr solution)
@@ -1191,18 +1487,30 @@ dijkstra_solve (sqlite3 * handle, NetworkPtr graph, RoutingNodesPtr routing,
}
static void
-a_star_solve (sqlite3 * handle, NetworkPtr graph, RoutingNodesPtr routing,
- SolutionPtr solution)
+astar_solve (sqlite3 * handle, NetworkPtr graph, RoutingNodesPtr routing,
+ SolutionPtr solution)
{
/* computing an A* Shortest Path solution */
int cnt;
NetworkArcPtr *shortest_path =
- a_star_shortest_path (routing, graph->Nodes, solution->From,
- solution->To, graph->AStarHeuristicCoeff, &cnt);
+ astar_shortest_path (routing, graph->Nodes, solution->From,
+ solution->To, graph->AStarHeuristicCoeff, &cnt);
build_solution (handle, graph, solution, shortest_path, cnt);
}
static void
+dijkstra_within_cost_range (RoutingNodesPtr routing, SolutionPtr solution,
+ int srid)
+{
+/* computing a Dijkstra "within cost range" solution */
+ int cnt;
+ RoutingNodePtr *range_nodes =
+ dijkstra_range_analysis (routing, solution->From, solution->MaxCost,
+ &cnt);
+ build_range_solution (solution, range_nodes, cnt, srid);
+}
+
+static void
network_free (NetworkPtr p)
{
/* memory cleanup; freeing any allocation for the network struct */
@@ -1344,8 +1652,13 @@ network_init (const unsigned char *blob, int size)
graph->ToColumn = malloc (len + 1);
strcpy (graph->ToColumn, to);
len = strlen (geom);
- graph->GeometryColumn = malloc (len + 1);
- strcpy (graph->GeometryColumn, geom);
+ if (len <= 1)
+ graph->GeometryColumn = NULL;
+ else
+ {
+ graph->GeometryColumn = malloc (len + 1);
+ strcpy (graph->GeometryColumn, geom);
+ }
if (!net64)
{
/* Name column is not supported */
@@ -1771,8 +2084,10 @@ vnet_best_index (sqlite3_vtab * pVTab, sqlite3_index_info * pIdxInfo)
int err = 1;
int from = 0;
int to = 0;
+ int cost = 0;
int i_from = -1;
int i_to = -1;
+ int i_cost = -1;
if (pVTab)
pVTab = pVTab; /* unused arg warning suppression */
for (i = 0; i < pIdxInfo->nConstraint; i++)
@@ -1791,6 +2106,11 @@ vnet_best_index (sqlite3_vtab * pVTab, sqlite3_index_info * pIdxInfo)
to++;
i_to = i;
}
+ else if (p->iColumn == 4 && p->op == SQLITE_INDEX_CONSTRAINT_LE)
+ {
+ cost++;
+ i_cost = i;
+ }
else
errors++;
}
@@ -1813,6 +2133,24 @@ vnet_best_index (sqlite3_vtab * pVTab, sqlite3_index_info * pIdxInfo)
}
err = 0;
}
+ if (from == 1 && cost == 1 && errors == 0)
+ {
+ /* this one is a valid "within cost" query */
+ if (i_from < i_cost)
+ pIdxInfo->idxNum = 3; /* first arg is FROM */
+ else
+ pIdxInfo->idxNum = 4; /* first arg is COST */
+ pIdxInfo->estimatedCost = 1.0;
+ for (i = 0; i < pIdxInfo->nConstraint; i++)
+ {
+ if (pIdxInfo->aConstraint[i].usable)
+ {
+ pIdxInfo->aConstraintUsage[i].argvIndex = i + 1;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ }
+ }
+ err = 0;
+ }
if (err)
{
/* illegal query */
@@ -1845,10 +2183,20 @@ static void
vnet_read_row (VirtualNetworkCursorPtr cursor)
{
/* trying to read a "row" from Shortest Path solution */
- if (cursor->solution->CurrentRow == NULL)
- cursor->eof = 1;
+ if (cursor->solution->Mode == VNET_RANGE_SOLUTION)
+ {
+ if (cursor->solution->CurrentNodeRow == NULL)
+ cursor->eof = 1;
+ else
+ cursor->eof = 0;
+ }
else
- cursor->eof = 0;
+ {
+ if (cursor->solution->CurrentRow == NULL)
+ cursor->eof = 1;
+ else
+ cursor->eof = 0;
+ }
return;
}
@@ -1951,18 +2299,89 @@ vnet_filter (sqlite3_vtab_cursor * pCursor, int idxNum, const char *idxStr,
sqlite3_value_int (argv[1]));
}
}
+ if (idxNum == 3 && argc == 2)
+ {
+ /* retrieving the From and Cost param */
+ if (node_code)
+ {
+ /* Nodes are identified by TEXT Codes */
+ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT)
+ cursor->solution->From =
+ find_node_by_code (net->graph,
+ (char *)
+ sqlite3_value_text (argv[0]));
+ }
+ else
+ {
+ /* Nodes are identified by INT Ids */
+ if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
+ cursor->solution->From =
+ find_node_by_id (net->graph,
+ sqlite3_value_int (argv[0]));
+ }
+ if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
+ {
+ int cost = sqlite3_value_int (argv[1]);
+ cursor->solution->MaxCost = cost;
+ }
+ else if (sqlite3_value_type (argv[1]) == SQLITE_FLOAT)
+ cursor->solution->MaxCost = sqlite3_value_double (argv[1]);
+ }
+ if (idxNum == 4 && argc == 2)
+ {
+ /* retrieving the From and Cost param */
+ if (node_code)
+ {
+ /* Nodes are identified by TEXT Codes */
+ if (sqlite3_value_type (argv[1]) == SQLITE_TEXT)
+ cursor->solution->From =
+ find_node_by_code (net->graph,
+ (char *)
+ sqlite3_value_text (argv[1]));
+ }
+ else
+ {
+ /* Nodes are identified by INT Ids */
+ if (sqlite3_value_type (argv[1]) == SQLITE_INTEGER)
+ cursor->solution->From =
+ find_node_by_id (net->graph,
+ sqlite3_value_int (argv[1]));
+ }
+ if (sqlite3_value_type (argv[0]) == SQLITE_INTEGER)
+ {
+ int cost = sqlite3_value_int (argv[0]);
+ cursor->solution->MaxCost = cost;
+ }
+ else if (sqlite3_value_type (argv[0]) == SQLITE_FLOAT)
+ cursor->solution->MaxCost = sqlite3_value_double (argv[0]);
+ }
if (cursor->solution->From && cursor->solution->To)
{
cursor->eof = 0;
+ cursor->solution->Mode = VNET_ROUTING_SOLUTION;
if (net->currentAlgorithm == VNET_A_STAR_ALGORITHM)
- a_star_solve (net->db, net->graph, net->routing,
- cursor->solution);
+ astar_solve (net->db, net->graph, net->routing, cursor->solution);
else
dijkstra_solve (net->db, net->graph, net->routing,
cursor->solution);
return SQLITE_OK;
}
+ if (cursor->solution->From && cursor->solution->MaxCost > 0.0)
+ {
+ int srid = find_srid (net->db, net->graph);
+ cursor->eof = 0;
+ cursor->solution->Mode = VNET_RANGE_SOLUTION;
+ if (net->currentAlgorithm == VNET_DIJKSTRA_ALGORITHM)
+ {
+ dijkstra_within_cost_range (net->routing, cursor->solution,
+ srid);
+ cursor->solution->CurrentRowId = 0;
+ cursor->solution->CurrentNodeRow = cursor->solution->FirstNode;
+ }
+ return SQLITE_OK;
+ }
cursor->eof = 0;
+ cursor->solution->Mode = VNET_ROUTING_SOLUTION;
return SQLITE_OK;
}
@@ -1971,14 +2390,30 @@ vnet_next (sqlite3_vtab_cursor * pCursor)
{
/* fetching a next row from cursor */
VirtualNetworkCursorPtr cursor = (VirtualNetworkCursorPtr) pCursor;
- if (cursor->solution->CurrentRowId == 0)
- cursor->solution->CurrentRow = cursor->solution->First;
+ if (cursor->solution->Mode == VNET_RANGE_SOLUTION)
+ {
+ if (cursor->solution->CurrentRowId == 0)
+ cursor->solution->CurrentNodeRow = cursor->solution->FirstNode;
+ else
+ cursor->solution->CurrentNodeRow =
+ cursor->solution->CurrentNodeRow->Next;
+ if (!(cursor->solution->CurrentNodeRow))
+ {
+ cursor->eof = 1;
+ return SQLITE_OK;
+ }
+ }
else
- cursor->solution->CurrentRow = cursor->solution->CurrentRow->Next;
- if (!(cursor->solution->CurrentRow))
{
- cursor->eof = 1;
- return SQLITE_OK;
+ if (cursor->solution->CurrentRowId == 0)
+ cursor->solution->CurrentRow = cursor->solution->First;
+ else
+ cursor->solution->CurrentRow = cursor->solution->CurrentRow->Next;
+ if (!(cursor->solution->CurrentRow))
+ {
+ cursor->eof = 1;
+ return SQLITE_OK;
+ }
}
(cursor->solution->CurrentRowId)++;
vnet_read_row (cursor);
@@ -1999,31 +2434,23 @@ vnet_column (sqlite3_vtab_cursor * pCursor, sqlite3_context * pContext,
{
/* fetching value for the Nth column */
RowSolutionPtr row;
+ RowNodeSolutionPtr row_node;
int node_code = 0;
const char *algorithm;
VirtualNetworkCursorPtr cursor = (VirtualNetworkCursorPtr) pCursor;
VirtualNetworkPtr net = (VirtualNetworkPtr) cursor->pVtab;
node_code = net->graph->NodeCode;
- if (cursor->solution->CurrentRow == 0)
+ if (cursor->solution->Mode == VNET_RANGE_SOLUTION)
{
- /* special case: this one is the solution summary */
+ /* processing "within Cost range" solution */
+ row_node = cursor->solution->CurrentNodeRow;
if (column == 0)
{
/* the currently used Algorithm */
- if (net->currentAlgorithm == VNET_A_STAR_ALGORITHM)
- algorithm = "A*";
- else
- algorithm = "Dijkstra";
+ algorithm = "Dijkstra";
sqlite3_result_text (pContext, algorithm, strlen (algorithm),
SQLITE_STATIC);
}
- if (cursor->solution->From == NULL || cursor->solution->To == NULL)
- {
- /* empty [uninitialized] solution */
- if (column > 0)
- sqlite3_result_null (pContext);
- return SQLITE_OK;
- }
if (column == 1)
{
/* the ArcRowId column */
@@ -2043,30 +2470,33 @@ vnet_column (sqlite3_vtab_cursor * pCursor, sqlite3_context * pContext,
{
/* the NodeTo column */
if (node_code)
- sqlite3_result_text (pContext, cursor->solution->To->Code,
- strlen (cursor->solution->To->Code),
+ sqlite3_result_text (pContext, row_node->Node->Code,
+ strlen (row_node->Node->Code),
SQLITE_STATIC);
else
- sqlite3_result_int64 (pContext, cursor->solution->To->Id);
+ sqlite3_result_int64 (pContext, row_node->Node->Id);
}
if (column == 4)
{
/* the Cost column */
- sqlite3_result_double (pContext, cursor->solution->TotalCost);
+ sqlite3_result_double (pContext, row_node->Cost);
}
if (column == 5)
{
/* the Geometry column */
- if (!(cursor->solution->Geometry))
+ if (row_node->Srid == VNET_INVALID_SRID)
sqlite3_result_null (pContext);
else
{
- /* builds the BLOB geometry to be returned */
int len;
unsigned char *p_result = NULL;
- gaiaToSpatiaLiteBlobWkb (cursor->solution->Geometry,
- &p_result, &len);
+ gaiaGeomCollPtr geom = gaiaAllocGeomColl ();
+ geom->Srid = row_node->Srid;
+ gaiaAddPointToGeomColl (geom, row_node->Node->CoordX,
+ row_node->Node->CoordY);
+ gaiaToSpatiaLiteBlobWkb (geom, &p_result, &len);
sqlite3_result_blob (pContext, p_result, len, free);
+ gaiaFreeGeomColl (geom);
}
}
if (column == 6)
@@ -2077,61 +2507,145 @@ vnet_column (sqlite3_vtab_cursor * pCursor, sqlite3_context * pContext,
}
else
{
- /* ordinary case: this one is an Arc used by the solution */
- row = cursor->solution->CurrentRow;
- if (column == 0)
+ /* processing an ordinary Routing (Shortest Path) solution */
+ if (cursor->solution->CurrentRow == 0)
{
- /* the currently used Algorithm */
- if (net->currentAlgorithm == VNET_A_STAR_ALGORITHM)
- algorithm = "A*";
- else
- algorithm = "Dijkstra";
- sqlite3_result_text (pContext, algorithm, strlen (algorithm),
- SQLITE_STATIC);
- }
- if (column == 1)
- {
- /* the ArcRowId column */
- sqlite3_result_int64 (pContext, row->Arc->ArcRowid);
- }
- if (column == 2)
- {
- /* the NodeFrom column */
- if (node_code)
- sqlite3_result_text (pContext, row->Arc->NodeFrom->Code,
- strlen (row->Arc->NodeFrom->Code),
- SQLITE_STATIC);
- else
- sqlite3_result_int64 (pContext, row->Arc->NodeFrom->Id);
- }
- if (column == 3)
- {
- /* the NodeTo column */
- if (node_code)
- sqlite3_result_text (pContext, row->Arc->NodeTo->Code,
- strlen (row->Arc->NodeTo->Code),
- SQLITE_STATIC);
- else
- sqlite3_result_int64 (pContext, row->Arc->NodeTo->Id);
- }
- if (column == 4)
- {
- /* the Cost column */
- sqlite3_result_double (pContext, row->Arc->Cost);
- }
- if (column == 5)
- {
- /* the Geometry column */
- sqlite3_result_null (pContext);
+ /* special case: this one is the solution summary */
+ if (column == 0)
+ {
+ /* the currently used Algorithm */
+ if (net->currentAlgorithm == VNET_A_STAR_ALGORITHM)
+ algorithm = "A*";
+ else
+ algorithm = "Dijkstra";
+ sqlite3_result_text (pContext, algorithm,
+ strlen (algorithm), SQLITE_STATIC);
+ }
+ if (cursor->solution->From == NULL
+ || cursor->solution->To == NULL)
+ {
+ /* empty [uninitialized] solution */
+ if (column > 0)
+ sqlite3_result_null (pContext);
+ return SQLITE_OK;
+ }
+ if (column == 1)
+ {
+ /* the ArcRowId column */
+ sqlite3_result_null (pContext);
+ }
+ if (column == 2)
+ {
+ /* the NodeFrom column */
+ if (node_code)
+ sqlite3_result_text (pContext,
+ cursor->solution->From->Code,
+ strlen (cursor->solution->From->
+ Code), SQLITE_STATIC);
+ else
+ sqlite3_result_int64 (pContext,
+ cursor->solution->From->Id);
+ }
+ if (column == 3)
+ {
+ /* the NodeTo column */
+ if (node_code)
+ sqlite3_result_text (pContext,
+ cursor->solution->To->Code,
+ strlen (cursor->solution->To->
+ Code), SQLITE_STATIC);
+ else
+ sqlite3_result_int64 (pContext,
+ cursor->solution->To->Id);
+ }
+ if (column == 4)
+ {
+ /* the Cost column */
+ sqlite3_result_double (pContext,
+ cursor->solution->TotalCost);
+ }
+ if (column == 5)
+ {
+ /* the Geometry column */
+ if (!(cursor->solution->Geometry))
+ sqlite3_result_null (pContext);
+ else
+ {
+ /* builds the BLOB geometry to be returned */
+ int len;
+ unsigned char *p_result = NULL;
+ gaiaToSpatiaLiteBlobWkb (cursor->solution->Geometry,
+ &p_result, &len);
+ sqlite3_result_blob (pContext, p_result, len, free);
+ }
+ }
+ if (column == 6)
+ {
+ /* the [optional] Name column */
+ sqlite3_result_null (pContext);
+ }
}
- if (column == 6)
+ else
{
- /* the [optional] Name column */
- if (row->Name)
- sqlite3_result_text (pContext, row->Name,
- strlen (row->Name), SQLITE_STATIC);
- else
- sqlite3_result_null (pContext);
+ /* ordinary case: this one is an Arc used by the solution */
+ row = cursor->solution->CurrentRow;
+ if (column == 0)
+ {
+ /* the currently used Algorithm */
+ if (net->currentAlgorithm == VNET_A_STAR_ALGORITHM)
+ algorithm = "A*";
+ else
+ algorithm = "Dijkstra";
+ sqlite3_result_text (pContext, algorithm,
+ strlen (algorithm), SQLITE_STATIC);
+ }
+ if (column == 1)
+ {
+ /* the ArcRowId column */
+ sqlite3_result_int64 (pContext, row->Arc->ArcRowid);
+ }
+ if (column == 2)
+ {
+ /* the NodeFrom column */
+ if (node_code)
+ sqlite3_result_text (pContext,
+ row->Arc->NodeFrom->Code,
+ strlen (row->Arc->NodeFrom->
+ Code), SQLITE_STATIC);
+ else
+ sqlite3_result_int64 (pContext,
+ row->Arc->NodeFrom->Id);
+ }
+ if (column == 3)
+ {
+ /* the NodeTo column */
+ if (node_code)
+ sqlite3_result_text (pContext, row->Arc->NodeTo->Code,
+ strlen (row->Arc->NodeTo->Code),
+ SQLITE_STATIC);
+ else
+ sqlite3_result_int64 (pContext, row->Arc->NodeTo->Id);
+ }
+ if (column == 4)
+ {
+ /* the Cost column */
+ sqlite3_result_double (pContext, row->Arc->Cost);
+ }
+ if (column == 5)
+ {
+ /* the Geometry column */
+ sqlite3_result_null (pContext);
+ }
+ if (column == 6)
+ {
+ /* the [optional] Name column */
+ if (row->Name)
+ sqlite3_result_text (pContext, row->Name,
+ strlen (row->Name),
+ SQLITE_STATIC);
+ else
+ sqlite3_result_null (pContext);
+ }
}
}
return SQLITE_OK;
@@ -2229,6 +2743,17 @@ vnet_rollback (sqlite3_vtab * pVTab)
}
static int
+vnet_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualNetworkInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -2251,6 +2776,7 @@ spliteVirtualNetworkInit (sqlite3 * db)
my_net_module.xCommit = &vnet_commit;
my_net_module.xRollback = &vnet_rollback;
my_net_module.xFindFunction = NULL;
+ my_net_module.xRename = &vnet_rename;
sqlite3_create_module_v2 (db, "VirtualNetwork", &my_net_module, NULL, 0);
return rc;
}
diff --git a/src/spatialite/virtualshape.c b/src/spatialite/virtualshape.c
index e7be7c3..52a36ad 100644
--- a/src/spatialite/virtualshape.c
+++ b/src/spatialite/virtualshape.c
@@ -1172,6 +1172,17 @@ vshp_rollback (sqlite3_vtab * pVTab)
}
static int
+vshp_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualShapeInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -1194,6 +1205,7 @@ spliteVirtualShapeInit (sqlite3 * db)
my_shape_module.xCommit = &vshp_commit;
my_shape_module.xRollback = &vshp_rollback;
my_shape_module.xFindFunction = NULL;
+ my_shape_module.xRename = &vshp_rename;
sqlite3_create_module_v2 (db, "VirtualShape", &my_shape_module, NULL, 0);
return rc;
}
diff --git a/src/spatialite/virtualspatialindex.c b/src/spatialite/virtualspatialindex.c
index 604742d..9a3643c 100644
--- a/src/spatialite/virtualspatialindex.c
+++ b/src/spatialite/virtualspatialindex.c
@@ -895,6 +895,17 @@ vspidx_rollback (sqlite3_vtab * pVTab)
}
static int
+vspidx_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualSpatialIndexInit (sqlite3 * db)
{
int rc = SQLITE_OK;
@@ -917,6 +928,7 @@ spliteVirtualSpatialIndexInit (sqlite3 * db)
my_spidx_module.xCommit = &vspidx_commit;
my_spidx_module.xRollback = &vspidx_rollback;
my_spidx_module.xFindFunction = NULL;
+ my_spidx_module.xRename = &vspidx_rename;
sqlite3_create_module_v2 (db, "VirtualSpatialIndex", &my_spidx_module, NULL,
0);
return rc;
diff --git a/src/spatialite/virtualxpath.c b/src/spatialite/virtualxpath.c
index 5630643..7150282 100644
--- a/src/spatialite/virtualxpath.c
+++ b/src/spatialite/virtualxpath.c
@@ -1112,6 +1112,17 @@ vxpath_rollback (sqlite3_vtab * pVTab)
}
static int
+vxpath_rename (sqlite3_vtab * pVTab, const char *zNew)
+{
+/* BEGIN TRANSACTION */
+ if (pVTab)
+ pVTab = pVTab; /* unused arg warning suppression */
+ if (zNew)
+ zNew = zNew; /* unused arg warning suppression */
+ return SQLITE_ERROR;
+}
+
+static int
spliteVirtualXPathInit (sqlite3 * db, void *p_cache)
{
int rc = SQLITE_OK;
@@ -1134,6 +1145,7 @@ spliteVirtualXPathInit (sqlite3 * db, void *p_cache)
my_xpath_module.xCommit = &vxpath_commit;
my_xpath_module.xRollback = &vxpath_rollback;
my_xpath_module.xFindFunction = NULL;
+ my_xpath_module.xRename = &vxpath_rename;
sqlite3_create_module_v2 (db, "VirtualXPath", &my_xpath_module, p_cache, 0);
return rc;
}
diff --git a/src/virtualtext/virtualtext.c b/src/virtualtext/virtualtext.c
index c5f05ee..60bae0e 100644
--- a/src/virtualtext/virtualtext.c
+++ b/src/virtualtext/virtualtext.c
@@ -1237,6 +1237,8 @@ vrttxt_set_column_title (gaiaTextReaderPtr txt, int col_no, const char *name)
char *utf8text;
char *str = (char *) name;
int len = strlen (str);
+ if (len <= 0)
+ return 0;
if (str[0] == txt->text_separator && str[len - 1] == txt->text_separator)
{
/* cleaning the enclosing quotes */
diff --git a/test/sql_stmt_geos_tests/Makefile.am b/test/sql_stmt_geos_tests/Makefile.am
index ba7b130..dd83a08 100644
--- a/test/sql_stmt_geos_tests/Makefile.am
+++ b/test/sql_stmt_geos_tests/Makefile.am
@@ -73,6 +73,8 @@ EXTRA_DIST = bdmpolyfromtext10.testcase \
boundary8.testcase \
boundary9.testcase \
buffer10.testcase \
+ buffer11.testcase \
+ buffer12.testcase \
buffer1.testcase \
buffer2.testcase \
buffer3.testcase \
diff --git a/test/sql_stmt_geos_tests/Makefile.in b/test/sql_stmt_geos_tests/Makefile.in
index 9279b26..9b819fa 100644
--- a/test/sql_stmt_geos_tests/Makefile.in
+++ b/test/sql_stmt_geos_tests/Makefile.in
@@ -315,6 +315,8 @@ EXTRA_DIST = bdmpolyfromtext10.testcase \
boundary8.testcase \
boundary9.testcase \
buffer10.testcase \
+ buffer11.testcase \
+ buffer12.testcase \
buffer1.testcase \
buffer2.testcase \
buffer3.testcase \
diff --git a/test/sql_stmt_geos_tests/buffer11.testcase b/test/sql_stmt_geos_tests/buffer11.testcase
new file mode 100644
index 0000000..51ba698
--- /dev/null
+++ b/test/sql_stmt_geos_tests/buffer11.testcase
@@ -0,0 +1,7 @@
+buffer - linestring - NULL quadrantsegments
+:memory: #use in-memory database
+SELECT AsText(Buffer(GeomFromText("LINESTRING(1 2, 4 6)"), 1, NULL))
+1 # rows (not including the header row)
+1 # columns
+AsText(Buffer(GeomFromText("LINESTRING(1 2, 4 6)"), 1, NULL))
+(NULL)
diff --git a/test/sql_stmt_geos_tests/buffer12.testcase b/test/sql_stmt_geos_tests/buffer12.testcase
new file mode 100644
index 0000000..5166478
--- /dev/null
+++ b/test/sql_stmt_geos_tests/buffer12.testcase
@@ -0,0 +1,7 @@
+buffer - linestring - 10 quadrantsegments
+:memory: #use in-memory database
+SELECT AsText(Buffer(GeomFromText("LINESTRING(1 2, 4 6)"), 1, 10))
+1 # rows (not including the header row)
+1 # columns
+AsText(Buffer(GeomFromText("LINESTRING(1 2, 4 6)"), 1, 10))
+POLYGON((3.2 6.6, 3.30371 6.717761, 3.424565 6.817848, 3.559589 6.897796, 3.705458 6.955638, 3.858579 6.989949, 4.015182 6.999885, 4.171412 6.9852, 4.32342 6.946255, 4.467465 6.884011, 4.6 6.8, 4.717761 6.69629, 4.817848 6.575435, 4.897796 6.440411, 4.955638 6.294542, 4.989949 6.141421, 4.999885 5.984818, 4.9852 5.828588, 4.946255 5.67658, 4.884011 5.532535, 4.8 5.4, 1.8 1.4, 1.69629 1.282239, 1.575435 1.182152, 1.440411 1.102204, 1.294542 1.044362, 1.141421 1.010051, 0.984818 1.000115, [...]
diff --git a/test/sql_stmt_tests/Makefile.am b/test/sql_stmt_tests/Makefile.am
index 610f69b..5b05689 100644
--- a/test/sql_stmt_tests/Makefile.am
+++ b/test/sql_stmt_tests/Makefile.am
@@ -584,6 +584,10 @@ EXTRA_DIST = addpoint10.testcase \
extractmultipolygon1.testcase \
extractmultipolygon2.testcase \
extractmultipolygon3.testcase \
+ eval1.testcase \
+ eval2.testcase \
+ eval3.testcase \
+ eval4.testcase \
fath_m.testcase \
fdo_ogr1.testcase \
fdo_ogr2.testcase \
diff --git a/test/sql_stmt_tests/Makefile.in b/test/sql_stmt_tests/Makefile.in
index 411e960..7f0f9ff 100644
--- a/test/sql_stmt_tests/Makefile.in
+++ b/test/sql_stmt_tests/Makefile.in
@@ -825,6 +825,10 @@ EXTRA_DIST = addpoint10.testcase \
extractmultipolygon1.testcase \
extractmultipolygon2.testcase \
extractmultipolygon3.testcase \
+ eval1.testcase \
+ eval2.testcase \
+ eval3.testcase \
+ eval4.testcase \
fath_m.testcase \
fdo_ogr1.testcase \
fdo_ogr2.testcase \
diff --git a/test/sql_stmt_tests/eval1.testcase b/test/sql_stmt_tests/eval1.testcase
new file mode 100644
index 0000000..baf2601
--- /dev/null
+++ b/test/sql_stmt_tests/eval1.testcase
@@ -0,0 +1,7 @@
+eval(NULL)
+:memory: #use in-memory database
+SELECT eval(NULL)
+1 # rows (not including the header row)
+1 # columns
+eval(NULL)
+(NULL)
diff --git a/test/sql_stmt_tests/eval2.testcase b/test/sql_stmt_tests/eval2.testcase
new file mode 100644
index 0000000..20f3261
--- /dev/null
+++ b/test/sql_stmt_tests/eval2.testcase
@@ -0,0 +1,7 @@
+eval(NULL, NULL)
+:memory: #use in-memory database
+SELECT eval(NULL, NULL)
+1 # rows (not including the header row)
+1 # columns
+eval(NULL, NULL)
+(NULL)
diff --git a/test/sql_stmt_tests/eval3.testcase b/test/sql_stmt_tests/eval3.testcase
new file mode 100644
index 0000000..e80a363
--- /dev/null
+++ b/test/sql_stmt_tests/eval3.testcase
@@ -0,0 +1,7 @@
+eval('SELECT 1 + 10, 2 * 10, sqrt(225)')
+:memory: #use in-memory database
+SELECT eval('SELECT 1 + 10, 2 * 10, sqrt(225)')
+1 # rows (not including the header row)
+1 # columns
+eval('SELECT 1 + 10, 2 * 10, sqrt(225)')
+11 20 15.0
diff --git a/test/sql_stmt_tests/eval4.testcase b/test/sql_stmt_tests/eval4.testcase
new file mode 100644
index 0000000..2e8409a
--- /dev/null
+++ b/test/sql_stmt_tests/eval4.testcase
@@ -0,0 +1,7 @@
+eval('SELECT 1 + 10, 2 * 10, sqrt(225)', ';')
+:memory: #use in-memory database
+SELECT eval('SELECT 1 + 10, 2 * 10, sqrt(225)', ';')
+1 # rows (not including the header row)
+1 # columns
+eval('SELECT 1 + 10, 2 * 10, sqrt(225)', ';')
+11;20;15.0
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/spatialite.git
More information about the Pkg-grass-devel
mailing list