[spatialite-tools] 02/10: Imported Upstream version 4.2.1~rc1

Bas Couwenberg sebastic at xs4all.nl
Wed Nov 26 22:51:07 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-tools.

commit 74bc4844429e9f225e98666cb340a620228fb42e
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Wed Nov 26 21:38:52 2014 +0100

    Imported Upstream version 4.2.1~rc1
---
 Makefile-static-MinGW      |   33 +
 Makefile.am                |   15 +-
 Makefile.in                |   51 +-
 config.h.in                |    6 +
 configure                  |  135 +-
 configure.ac               |   18 +-
 shell.c                    |   60 +-
 spatialite_network.c       | 1063 ++++++++--
 spatialite_osm_overpass.c  | 4591 ++++++++++++++++++++++++++++++++++++++++++++
 spatialite_xml_collapse.c  |    9 +
 spatialite_xml_load.c      |    9 +
 spatialite_xml_print.c     |   11 +-
 spatialite_xml_validator.c |  718 +++++++
 13 files changed, 6516 insertions(+), 203 deletions(-)

diff --git a/Makefile-static-MinGW b/Makefile-static-MinGW
index 46685de..d278685 100644
--- a/Makefile-static-MinGW
+++ b/Makefile-static-MinGW
@@ -11,7 +11,9 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	./static_bin/spatialite_osm_map.exe ./static_bin/spatialite_gml.exe \
 	./static_bin/spatialite_osm_raw.exe ./static_bin/spatialite_osm_filter.exe \
 	./static_bin/spatialite_convert.exe ./static_bin/spatialite_dxf.exe \
+	./static_bin/spatialite_osm_overpass.exe \
 	./static_bin/spatialite_xml_collapse.exe \
+	./static_bin/spatialite_xml_validator.exe \
 	./static_bin/spatialite_xml_load.exe \
 	./static_bin/spatialite_xml_print.exe
 
@@ -217,6 +219,22 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
 	strip --strip-all ./static_bin/spatialite_osm_filter.exe
 
+./static_bin/spatialite_osm_overpass.exe: spatialite_osm_overpass.o
+	$(GG) spatialite_osm_overpass.o -o ./static_bin/spatialite_osm_overpass.exe \
+	/usr/local/lib/libspatialite.a \
+	/usr/local/lib/libsqlite3.a \
+	/usr/local/lib/liblwgeom.a \
+	/usr/local/lib/libxml2.a \
+	/usr/local/lib/liblzma.a \
+	/usr/local/lib/libproj.a \
+	/usr/local/lib/libgeos_c.a \
+	/usr/local/lib/libgeos.a \
+	/usr/local/lib/libfreexl.a \
+	/usr/local/lib/libz.a \
+	/usr/local/lib/libiconv.a \
+	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
+	strip --strip-all ./static_bin/spatialite_osm_overpass.exe
+
 ./static_bin/spatialite_xml_collapse.exe: spatialite_xml_collapse.o
 	$(GG) spatialite_xml_collapse.o -o ./static_bin/spatialite_xml_collapse.exe \
 	/usr/local/lib/libspatialite.a \
@@ -233,6 +251,15 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
 	-lm -lmsimg32 -lws2_32 -static-libstdc++ -static-libgcc 
 	strip --strip-all ./static_bin/spatialite_xml_collapse.exe
 
+./static_bin/spatialite_xml_validator.exe: spatialite_xml_validator.o
+	$(CC) spatialite_xml_validator.o -o ./static_bin/spatialite_xml_validator.exe \
+	/usr/local/lib/libxml2.a \
+	/usr/local/lib/liblzma.a \
+	/usr/local/lib/libz.a \
+	/usr/local/lib/libiconv.a \
+	-lm -lws2_32 -static-libgcc 
+	strip --strip-all ./static_bin/spatialite_xml_validator.exe
+
 ./static_bin/spatialite_xml_load.exe: spatialite_xml_load.o
 	$(GG) spatialite_xml_load.o -o ./static_bin/spatialite_xml_load.exe \
 	/usr/local/lib/libspatialite.a \
@@ -296,9 +323,15 @@ spatialite_osm_raw.o:
 spatialite_osm_filter.o:
 	$(CC) $(CFLAGS) spatialite_osm_filter.c -c
 
+spatialite_osm_overpass.o:
+	$(CC) $(CFLAGS) spatialite_osm_overpass.c -c
+
 spatialite_xml_collapse.o:
 	$(CC) $(CFLAGS) spatialite_xml_collapse.c -c
 
+spatialite_xml_validator.o:
+	$(CC) $(CFLAGS) spatialite_xml_validator.c -c
+
 spatialite_xml_load.o:
 	$(CC) $(CFLAGS) spatialite_xml_load.c -c
 
diff --git a/Makefile.am b/Makefile.am
index d9a52aa..40feb76 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,9 +10,11 @@ bin_PROGRAMS = spatialite \
 	spatialite_gml \
 	spatialite_convert \
 	spatialite_dxf \
+	spatialite_xml_validator \
 	spatialite_xml_load \
 	spatialite_xml_collapse \
-	spatialite_xml_print
+	spatialite_xml_print \
+	spatialite_osm_overpass
 else
 bin_PROGRAMS = spatialite \
 	spatialite_tool \
@@ -26,12 +28,14 @@ bin_PROGRAMS = spatialite \
 	spatialite_gml \
 	spatialite_convert \
 	spatialite_dxf \
+	spatialite_xml_validator \
 	spatialite_xml_load \
 	spatialite_xml_collapse \
-	spatialite_xml_print
+	spatialite_xml_print \
+	spatialite_osm_overpass
 endif
 
-AM_CPPFLAGS = @CFLAGS@
+AM_CPPFLAGS = @CFLAGS@ @LIBXML2_CFLAGS@
 AM_CPPFLAGS += -I$(top_srcdir)
 
 spatialite_SOURCES = shell.c
@@ -39,6 +43,7 @@ spatialite_tool_SOURCES = spatialite_tool.c
 spatialite_network_SOURCES = spatialite_network.c
 shp_doctor_SOURCES = shp_doctor.c
 exif_loader_SOURCES = exif_loader.c
+spatialite_xml_validator_SOURCES = spatialite_xml_validator.c
 spatialite_xml_load_SOURCES = spatialite_xml_load.c
 spatialite_xml_collapse_SOURCES = spatialite_xml_collapse.c
 spatialite_xml_print_SOURCES = spatialite_xml_print.c 
@@ -50,9 +55,12 @@ spatialite_osm_raw_SOURCES = spatialite_osm_raw.c
 endif
 spatialite_osm_filter_SOURCES = spatialite_osm_filter.c
 spatialite_gml_SOURCES = spatialite_gml.c
+spatialite_osm_overpass_SOURCES = spatialite_osm_overpass.c
 
 spatialite_osm_map_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ @LIBREADOSM_LIBS@ 
+spatialite_osm_overpass_LDADD = @LIBSPATIALITE_LIBS@ \
+	@LIBFREEXL_LIBS@ @LIBXML2_LIBS@ 
 spatialite_osm_raw_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ @LIBREADOSM_LIBS@
 spatialite_osm_net_LDADD = @LIBSPATIALITE_LIBS@ \
@@ -63,6 +71,7 @@ spatialite_gml_LDADD = @LIBSPATIALITE_LIBS@ \
 spatialite_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ \
 	@READLINE_LIBS@
+spatialite_xml_validator_LDADD = @LIBXML2_LIBS@
 spatialite_xml_load_LDADD = @LIBSPATIALITE_LIBS@ \
 	-lexpat
 spatialite_xml_collapse_LDADD = @LIBSPATIALITE_LIBS@
diff --git a/Makefile.in b/Makefile.in
index c5c87bf..8857f67 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -89,9 +89,11 @@ host_triplet = @host@
 @NO_READOSM_FALSE@	spatialite_gml$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_convert$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_dxf$(EXEEXT) \
+ at NO_READOSM_FALSE@	spatialite_xml_validator$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_xml_load$(EXEEXT) \
 @NO_READOSM_FALSE@	spatialite_xml_collapse$(EXEEXT) \
- at NO_READOSM_FALSE@	spatialite_xml_print$(EXEEXT)
+ at NO_READOSM_FALSE@	spatialite_xml_print$(EXEEXT) \
+ at NO_READOSM_FALSE@	spatialite_osm_overpass$(EXEEXT)
 @NO_READOSM_TRUE at bin_PROGRAMS = spatialite$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_tool$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_network$(EXEEXT) \
@@ -100,9 +102,11 @@ host_triplet = @host@
 @NO_READOSM_TRUE@	spatialite_gml$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_convert$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_dxf$(EXEEXT) \
+ at NO_READOSM_TRUE@	spatialite_xml_validator$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_xml_load$(EXEEXT) \
 @NO_READOSM_TRUE@	spatialite_xml_collapse$(EXEEXT) \
- at NO_READOSM_TRUE@	spatialite_xml_print$(EXEEXT)
+ at NO_READOSM_TRUE@	spatialite_xml_print$(EXEEXT) \
+ at NO_READOSM_TRUE@	spatialite_osm_overpass$(EXEEXT)
 subdir = .
 DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
 	$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
@@ -168,6 +172,11 @@ am__spatialite_osm_net_SOURCES_DIST = spatialite_osm_net.c
 @NO_READOSM_FALSE@	spatialite_osm_net.$(OBJEXT)
 spatialite_osm_net_OBJECTS = $(am_spatialite_osm_net_OBJECTS)
 spatialite_osm_net_DEPENDENCIES =
+am_spatialite_osm_overpass_OBJECTS =  \
+	spatialite_osm_overpass.$(OBJEXT)
+spatialite_osm_overpass_OBJECTS =  \
+	$(am_spatialite_osm_overpass_OBJECTS)
+spatialite_osm_overpass_DEPENDENCIES =
 am__spatialite_osm_raw_SOURCES_DIST = spatialite_osm_raw.c
 @NO_READOSM_FALSE at am_spatialite_osm_raw_OBJECTS =  \
 @NO_READOSM_FALSE@	spatialite_osm_raw.$(OBJEXT)
@@ -189,6 +198,11 @@ am_spatialite_xml_print_OBJECTS = spatialite_xml_print.$(OBJEXT)
 spatialite_xml_print_OBJECTS = $(am_spatialite_xml_print_OBJECTS)
 spatialite_xml_print_LDADD = $(LDADD)
 spatialite_xml_print_DEPENDENCIES =
+am_spatialite_xml_validator_OBJECTS =  \
+	spatialite_xml_validator.$(OBJEXT)
+spatialite_xml_validator_OBJECTS =  \
+	$(am_spatialite_xml_validator_OBJECTS)
+spatialite_xml_validator_DEPENDENCIES =
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -227,18 +241,23 @@ SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
 	$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
 	$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
 	$(spatialite_osm_filter_SOURCES) $(spatialite_osm_map_SOURCES) \
-	$(spatialite_osm_net_SOURCES) $(spatialite_osm_raw_SOURCES) \
-	$(spatialite_tool_SOURCES) $(spatialite_xml_collapse_SOURCES) \
-	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES)
+	$(spatialite_osm_net_SOURCES) \
+	$(spatialite_osm_overpass_SOURCES) \
+	$(spatialite_osm_raw_SOURCES) $(spatialite_tool_SOURCES) \
+	$(spatialite_xml_collapse_SOURCES) \
+	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES) \
+	$(spatialite_xml_validator_SOURCES)
 DIST_SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
 	$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
 	$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
 	$(spatialite_osm_filter_SOURCES) \
 	$(am__spatialite_osm_map_SOURCES_DIST) \
 	$(am__spatialite_osm_net_SOURCES_DIST) \
+	$(spatialite_osm_overpass_SOURCES) \
 	$(am__spatialite_osm_raw_SOURCES_DIST) \
 	$(spatialite_tool_SOURCES) $(spatialite_xml_collapse_SOURCES) \
-	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES)
+	$(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES) \
+	$(spatialite_xml_validator_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -333,6 +352,8 @@ LIBS = @LIBS@
 LIBSPATIALITE_CFLAGS = @LIBSPATIALITE_CFLAGS@
 LIBSPATIALITE_LIBS = @LIBSPATIALITE_LIBS@
 LIBTOOL = @LIBTOOL@
+LIBXML2_CFLAGS = @LIBXML2_CFLAGS@
+LIBXML2_LIBS = @LIBXML2_LIBS@
 LIPO = @LIPO@
 LN_S = @LN_S@
 LTLIBOBJS = @LTLIBOBJS@
@@ -418,12 +439,13 @@ top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 ACLOCAL_AMFLAGS = -I m4
-AM_CPPFLAGS = @CFLAGS@ -I$(top_srcdir)
+AM_CPPFLAGS = @CFLAGS@ @LIBXML2_CFLAGS@ -I$(top_srcdir)
 spatialite_SOURCES = shell.c
 spatialite_tool_SOURCES = spatialite_tool.c
 spatialite_network_SOURCES = spatialite_network.c
 shp_doctor_SOURCES = shp_doctor.c
 exif_loader_SOURCES = exif_loader.c
+spatialite_xml_validator_SOURCES = spatialite_xml_validator.c
 spatialite_xml_load_SOURCES = spatialite_xml_load.c
 spatialite_xml_collapse_SOURCES = spatialite_xml_collapse.c
 spatialite_xml_print_SOURCES = spatialite_xml_print.c 
@@ -432,9 +454,13 @@ spatialite_xml_print_SOURCES = spatialite_xml_print.c
 @NO_READOSM_FALSE at spatialite_osm_raw_SOURCES = spatialite_osm_raw.c
 spatialite_osm_filter_SOURCES = spatialite_osm_filter.c
 spatialite_gml_SOURCES = spatialite_gml.c
+spatialite_osm_overpass_SOURCES = spatialite_osm_overpass.c
 spatialite_osm_map_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ @LIBREADOSM_LIBS@ 
 
+spatialite_osm_overpass_LDADD = @LIBSPATIALITE_LIBS@ \
+	@LIBFREEXL_LIBS@ @LIBXML2_LIBS@ 
+
 spatialite_osm_raw_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ @LIBREADOSM_LIBS@
 
@@ -449,6 +475,7 @@ spatialite_LDADD = @LIBSPATIALITE_LIBS@ \
 	@LIBFREEXL_LIBS@ \
 	@READLINE_LIBS@
 
+spatialite_xml_validator_LDADD = @LIBXML2_LIBS@
 spatialite_xml_load_LDADD = @LIBSPATIALITE_LIBS@ \
 	-lexpat
 
@@ -608,6 +635,10 @@ spatialite_osm_net$(EXEEXT): $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_
 	@rm -f spatialite_osm_net$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_LDADD) $(LIBS)
 
+spatialite_osm_overpass$(EXEEXT): $(spatialite_osm_overpass_OBJECTS) $(spatialite_osm_overpass_DEPENDENCIES) $(EXTRA_spatialite_osm_overpass_DEPENDENCIES) 
+	@rm -f spatialite_osm_overpass$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(spatialite_osm_overpass_OBJECTS) $(spatialite_osm_overpass_LDADD) $(LIBS)
+
 spatialite_osm_raw$(EXEEXT): $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_DEPENDENCIES) $(EXTRA_spatialite_osm_raw_DEPENDENCIES) 
 	@rm -f spatialite_osm_raw$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_LDADD) $(LIBS)
@@ -628,6 +659,10 @@ spatialite_xml_print$(EXEEXT): $(spatialite_xml_print_OBJECTS) $(spatialite_xml_
 	@rm -f spatialite_xml_print$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(spatialite_xml_print_OBJECTS) $(spatialite_xml_print_LDADD) $(LIBS)
 
+spatialite_xml_validator$(EXEEXT): $(spatialite_xml_validator_OBJECTS) $(spatialite_xml_validator_DEPENDENCIES) $(EXTRA_spatialite_xml_validator_DEPENDENCIES) 
+	@rm -f spatialite_xml_validator$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(spatialite_xml_validator_OBJECTS) $(spatialite_xml_validator_LDADD) $(LIBS)
+
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
 
@@ -644,11 +679,13 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_filter.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_map.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_net.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_overpass.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_raw.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_tool.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_collapse.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_load.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_print.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_validator.Po at am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/config.h.in b/config.h.in
index ec16ab9..227f579 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,5 +1,8 @@
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Should be defined in order to enable LIBXML2 support. */
+#undef ENABLE_LIBXML2
+
 /* depending on SQLite library version. */
 #undef HAVE_DECL_SQLITE_CONFIG_URI
 
@@ -51,6 +54,9 @@
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
+/* Define to 1 if you have the <expat.h> header file. */
+#undef HAVE_EXPAT_H
+
 /* Define to 1 if you have the <fcntl.h> header file. */
 #undef HAVE_FCNTL_H
 
diff --git a/configure b/configure
index 65b1cd6..30a322e 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 spatialite-tools 4.2.0.
+# Generated by GNU Autoconf 2.69 for spatialite-tools 4.2.1-rc1.
 #
 # Report bugs to <a.furieri at lqt.it>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='spatialite-tools'
 PACKAGE_TARNAME='spatialite-tools'
-PACKAGE_VERSION='4.2.0'
-PACKAGE_STRING='spatialite-tools 4.2.0'
+PACKAGE_VERSION='4.2.1-rc1'
+PACKAGE_STRING='spatialite-tools 4.2.1-rc1'
 PACKAGE_BUGREPORT='a.furieri at lqt.it'
 PACKAGE_URL=''
 
@@ -634,6 +634,8 @@ ac_includes_default="\
 ac_subst_vars='am__EXEEXT_FALSE
 am__EXEEXT_TRUE
 LTLIBOBJS
+LIBXML2_LIBS
+LIBXML2_CFLAGS
 NO_READOSM_FALSE
 NO_READOSM_TRUE
 LIBREADOSM_CFLAGS
@@ -790,6 +792,7 @@ enable_readline
 with_geosconfig
 enable_freexl
 enable_readosm
+enable_libxml2
 '
       ac_precious_vars='build_alias
 host_alias
@@ -812,7 +815,9 @@ LIBSPATIALITE_LIBS
 LIBFREEXL_CFLAGS
 LIBFREEXL_LIBS
 LIBREADOSM_CFLAGS
-LIBREADOSM_LIBS'
+LIBREADOSM_LIBS
+LIBXML2_CFLAGS
+LIBXML2_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1353,7 +1358,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 spatialite-tools 4.2.0 to adapt to many kinds of systems.
+\`configure' configures spatialite-tools 4.2.1-rc1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1424,7 +1429,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of spatialite-tools 4.2.0:";;
+     short | recursive ) echo "Configuration of spatialite-tools 4.2.1-rc1:";;
    esac
   cat <<\_ACEOF
 
@@ -1449,6 +1454,7 @@ Optional Features:
   --enable-readline       use readline in shell tool (yes, no) [default=yes]
   --enable-freexl         enables FreeXL inclusion [default=yes]
   --enable-readosm        enables ReadOSM inclusion [default=yes]
+  --enable-libxml2        enables libxml2 inclusion [default=yes]
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1489,6 +1495,10 @@ Some influential environment variables:
               C compiler flags for LIBREADOSM, overriding pkg-config
   LIBREADOSM_LIBS
               linker flags for LIBREADOSM, overriding pkg-config
+  LIBXML2_CFLAGS
+              C compiler flags for LIBXML2, overriding pkg-config
+  LIBXML2_LIBS
+              linker flags for LIBXML2, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1556,7 +1566,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-spatialite-tools configure 4.2.0
+spatialite-tools configure 4.2.1-rc1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2146,7 +2156,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 spatialite-tools $as_me 4.2.0, which was
+It was created by spatialite-tools $as_me 4.2.1-rc1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3017,7 +3027,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='spatialite-tools'
- VERSION='4.2.0'
+ VERSION='4.2.1-rc1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3116,6 +3126,7 @@ ac_config_headers="$ac_config_headers config.h"
 
 
 
+
 # Checks for header files.
 DEPDIR="${am__leading_dot}deps"
 
@@ -17223,6 +17234,20 @@ done
 fi
 
 
+for ac_header in expat.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "expat.h" "ac_cv_header_expat_h" "$ac_includes_default"
+if test "x$ac_cv_header_expat_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_EXPAT_H 1
+_ACEOF
+
+else
+  as_fn_error $? "cannot find expat.h, bailing out" "$LINENO" 5
+fi
+
+done
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML_ParserCreate in -lexpat" >&5
 $as_echo_n "checking for XML_ParserCreate in -lexpat... " >&6; }
 if ${ac_cv_lib_expat_XML_ParserCreate+:} false; then :
@@ -17862,6 +17887,94 @@ else
 fi
 
 
+#-----------------------------------------------------------------------
+#   --enable-libxml2
+#
+# Check whether --enable-libxml2 was given.
+if test "${enable_libxml2+set}" = set; then :
+  enableval=$enable_libxml2;
+else
+  enable_libxml2=yes
+fi
+
+if test x"$enable_libxml2" != "xno"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBXML2" >&5
+$as_echo_n "checking for LIBXML2... " >&6; }
+
+if test -n "$LIBXML2_CFLAGS"; then
+    pkg_cv_LIBXML2_CFLAGS="$LIBXML2_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBXML2_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBXML2_LIBS"; then
+    pkg_cv_LIBXML2_LIBS="$LIBXML2_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBXML2_LIBS=`$PKG_CONFIG --libs "libxml-2.0" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        LIBXML2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxml-2.0" 2>&1`
+        else
+	        LIBXML2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxml-2.0" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$LIBXML2_PKG_ERRORS" >&5
+
+	as_fn_error $? "'libxml2' is required but it doesn't seem to be installed on this system." "$LINENO" 5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	as_fn_error $? "'libxml2' is required but it doesn't seem to be installed on this system." "$LINENO" 5
+else
+	LIBXML2_CFLAGS=$pkg_cv_LIBXML2_CFLAGS
+	LIBXML2_LIBS=$pkg_cv_LIBXML2_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+  $as_echo "#define ENABLE_LIBXML2 1" >>confdefs.h
+
+fi
+
 # checks for SQLite version-depending constants
 ac_fn_c_check_decl "$LINENO" "SQLITE_CONFIG_URI" "ac_cv_have_decl_SQLITE_CONFIG_URI" "#include <sqlite3.h>
 "
@@ -18521,7 +18634,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 spatialite-tools $as_me 4.2.0, which was
+This file was extended by spatialite-tools $as_me 4.2.1-rc1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -18587,7 +18700,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="\\
-spatialite-tools config.status 4.2.0
+spatialite-tools 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 e220aa4..e911b21 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(spatialite-tools, 4.2.0, a.furieri at lqt.it)
+AC_INIT(spatialite-tools, 4.2.1-rc1, a.furieri at lqt.it)
 AC_LANG(C)
 AC_CONFIG_MACRO_DIR([m4])
 
@@ -17,6 +17,8 @@ AH_TEMPLATE([OMIT_FREEXL],
             [Should be defined in order to disable FREEXL support.])
 AH_TEMPLATE([OMIT_READOSM],
             [Should be defined in order to disable ReadOSM support.])
+AH_TEMPLATE([ENABLE_LIBXML2],
+            [Should be defined in order to enable LIBXML2 support.])
 AH_TEMPLATE([HAVE_DECL_SQLITE_CONFIG_URI],
             [depending on SQLite library version.])
 AH_TEMPLATE([HAVE_DECL_SQLITE_DBSTATUS_LOOKASIDE_USED],
@@ -112,6 +114,7 @@ if test x"$enable_readline" != xno ; then
 fi
 AC_SUBST(READLINE_LIBS)
 
+AC_CHECK_HEADERS(expat.h,, [AC_MSG_ERROR([cannot find expat.h, bailing out])])
 AC_CHECK_LIB(expat,XML_ParserCreate,,AC_MSG_ERROR(['expat' is required but it doesn't seem to be installed on this system.]))
 AC_CHECK_LIB(proj,pj_init_plus,,AC_MSG_ERROR(['libproj' is required but it doesn't seem to be installed on this system.]),-lm)
 
@@ -196,6 +199,19 @@ fi
 
 AM_CONDITIONAL([NO_READOSM], [test "$NOREADOSM" = "true"])
 
+#-----------------------------------------------------------------------
+#   --enable-libxml2
+#
+AC_ARG_ENABLE(libxml2, [AS_HELP_STRING(
+  [--enable-libxml2], [enables libxml2 inclusion [default=yes]])],
+  [], [enable_libxml2=yes])
+if test x"$enable_libxml2" != "xno"; then
+  PKG_CHECK_MODULES([LIBXML2], [libxml-2.0], , AC_MSG_ERROR(['libxml2' is required but it doesn't seem to be installed on this system.]))
+  AC_SUBST(LIBXML2_CFLAGS)
+  AC_SUBST(LIBXML2_LIBS)
+  AC_DEFINE(ENABLE_LIBXML2)
+fi
+
 # checks for SQLite version-depending constants
 AC_CHECK_DECL([SQLITE_CONFIG_URI],
   [AC_DEFINE(HAVE_DECL_SQLITE_CONFIG_URI)],[],[[#include <sqlite3.h>]])
diff --git a/shell.c b/shell.c
index 6e70a81..0c92d9a 100644
--- a/shell.c
+++ b/shell.c
@@ -2220,7 +2220,7 @@ static char zTimerHelp[] =
     ".loadshp <args>   Loads a SHAPEFILE into a SpatiaLite table\n"
     "                  arg_list: shp_path table_name charset [SRID] [column_name]\n"
     "                      [pk_column] [geom_type] [2d | 3d] [compressed]\n"
-    "                      [with_spatial_index]\n"
+    "                      [with_spatial_index] [text_dates]\n"
     "                      geom_type={ AUTO | LINESTRING[ Z | M | ZM ]\n"
     "                                 | MULTILINESTRING[ Z | M | ZM ]\n"
     "                                 | POLYGON[ Z | M | ZM ]\n"
@@ -2229,7 +2229,7 @@ static char zTimerHelp[] =
     "                  arg_list: table_name column_name shp_path charset [geom_type]\n"
     "                      geom_type={ POINT | LINESTRING | POLYGON | MULTIPOINT }\n\n"
     ".loaddbf <args>   Loads a DBF into a SpatiaLite table\n"
-    "                  arg_list: dbf_path table_name charset [pk_column]\n\n"
+    "                  arg_list: dbf_path table_name charset [pk_column] [text_dates]\n\n"
     ".dumpdbf <args>   Dumps a SpatiaLite table into a DBF\n"
     "                  arg_list: table_name dbf_path charset\n\n"
 #ifndef OMIT_FREEXL		/* FreeXL is enabled */
@@ -2444,6 +2444,22 @@ static int do_meta_command(char *zLine, struct callback_data *p){
   n = strlen30(azArg[0]);
   c = azArg[0][0];
 
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+  if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
+    const char *zFile, *zProc;
+    char *zErrMsg = 0;
+    zFile = azArg[1];
+    zProc = nArg>=3 ? azArg[2] : 0;
+    open_db(p);
+    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
+    if( rc!=SQLITE_OK ){
+      fprintf(stderr, "Error: %s\n", zErrMsg);
+      sqlite3_free(zErrMsg);
+      rc = 1;
+    }
+  }else
+#endif
+
 /* Sandro Furieri 2008-06-20 */
     if (c == 'c' && n > 1 && strncmp (azArg[0], "charset", n) == 0 && nArg == 1)
       {
@@ -2546,7 +2562,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
       }
     else if (c == 'l' && n > 1 && strncmp (azArg[0], "loadshp", n) == 0
 	     && (nArg == 4 || nArg == 5 || nArg == 6 || nArg == 7 ||
-		 nArg == 8 || nArg == 9 || nArg == 10 || nArg == 11))
+		 nArg == 8 || nArg == 9 || nArg == 10 || nArg == 11 || nArg == 12))
       {
 	  char *shp_path = azArg[1];
 	  char *table = azArg[2];
@@ -2555,6 +2571,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
 	  int coerce2d = 0;
 	  int compressed = 0;
 	  int with_spatial_index = 0;
+	  int text_dates = 0;
 	  char *column = NULL;
 	  char *gtype = NULL;
           char *pk = NULL;
@@ -2579,23 +2596,28 @@ static int do_meta_command(char *zLine, struct callback_data *p){
 	  }
 	  if (nArg == 11)
 	      with_spatial_index = 1;
+	  if (nArg == 12)
+	      text_dates = atoi(azArg[11]);
 	  open_db (p);
-	  load_shapefile_ex (p->db, shp_path, table, inCS, srid, column, gtype, pk,
-			     coerce2d, compressed, 1, with_spatial_index, &rows,
-			     NULL);
+	  load_shapefile_ex2 (p->db, shp_path, table, inCS, srid, column, gtype, pk,
+			     coerce2d, compressed, 1, with_spatial_index, text_dates,
+			     &rows, NULL);
       }
     else if (c == 'l' && n > 1 && strncmp (azArg[0], "loaddbf", n) == 0
-	     && (nArg == 4 || nArg == 5))
+	     && (nArg == 4 || nArg == 5 || nArg == 6))
       {
 	  char *dbf_path = azArg[1];
 	  char *table = azArg[2];
 	  char *inCS = azArg[3];
-          char *pk = NULL;
+      char *pk = NULL;
+      int text_dates = 0;
 	  int rows;
-          if (nArg == 5)
-              pk = azArg[4];
+      if (nArg == 5)
+          pk = azArg[4];
+      if (nArg == 6)
+          text_dates = atoi(azArg[5]);
 	  open_db (p);
-	  load_dbf_ex (p->db, dbf_path, table, pk, inCS, 1, &rows, NULL);
+	  load_dbf_ex2 (p->db, dbf_path, table, pk, inCS, 1, text_dates, &rows, NULL);
       }
 #ifndef OMIT_FREEXL		/* FREEXL is enabled */
     else if (c == 'l' && n > 1 && strncmp (azArg[0], "loadxl", n) == 0
@@ -3213,22 +3235,6 @@ stop_dxf:
   }else
 #endif
 
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-  if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){
-    const char *zFile, *zProc;
-    char *zErrMsg = 0;
-    zFile = azArg[1];
-    zProc = nArg>=3 ? azArg[2] : 0;
-    open_db(p);
-    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
-    if( rc!=SQLITE_OK ){
-      fprintf(stderr, "Error: %s\n", zErrMsg);
-      sqlite3_free(zErrMsg);
-      rc = 1;
-    }
-  }else
-#endif
-
   if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){
     const char *zFile = azArg[1];
     output_file_close(p->pLog);
diff --git a/spatialite_network.c b/spatialite_network.c
index 784b95c..530a4ef 100644
--- a/spatialite_network.c
+++ b/spatialite_network.c
@@ -70,6 +70,7 @@
 #define ARG_ONEWAY_TOFROM	8
 #define ARG_ONEWAY_FROMTO	9
 #define ARG_OUT_TABLE		10
+#define ARG_VIRT_TABLE		11
 
 #define MAX_BLOCK	1048576
 
@@ -245,7 +246,7 @@ cmp_nodes2_id (const void *p1, const void *p2)
 }
 
 static struct node *
-find_node (struct graph *p_graph, sqlite3_int64 id, char *code)
+find_node (struct graph *p_graph, sqlite3_int64 id, const char *code)
 {
 /* searching a Node into the sorted list */
     struct node **ret;
@@ -344,7 +345,8 @@ sort_nodes (struct graph *p_graph)
 }
 
 static void
-insert_node (struct graph *p_graph, sqlite3_int64 id, char *code, int node_code)
+insert_node (struct graph *p_graph, sqlite3_int64 id, const char *code,
+	     int node_code)
 {
 /* inserts a Node into the preliminary list */
     struct pre_node *pP = malloc (sizeof (struct pre_node));
@@ -376,7 +378,7 @@ insert_node (struct graph *p_graph, sqlite3_int64 id, char *code, int node_code)
 }
 
 static void
-add_node (struct graph *p_graph, sqlite3_int64 id, char *code)
+add_node (struct graph *p_graph, sqlite3_int64 id, const char *code)
 {
 /* inserts a Node into the final list */
     int len;
@@ -411,8 +413,8 @@ add_node (struct graph *p_graph, sqlite3_int64 id, char *code)
 }
 
 static struct node *
-process_node (struct graph *p_graph, sqlite3_int64 id, char *code, double x,
-	      double y, struct node **pOther)
+process_node (struct graph *p_graph, sqlite3_int64 id, const char *code,
+	      double x, double y, struct node **pOther)
 {
 /* inserts a new node or retrieves an already defined one */
     struct node *pN = find_node (p_graph, id, code);
@@ -468,7 +470,7 @@ add_outcoming_arc (struct node *pN, struct arc *pA)
 
 static void
 add_arc (struct graph *p_graph, sqlite3_int64 rowid, sqlite3_int64 id_from,
-	 sqlite3_int64 id_to, char *code_from, char *code_to,
+	 sqlite3_int64 id_to, const char *code_from, const char *code_to,
 	 double node_from_x, double node_from_y, double node_to_x,
 	 double node_to_y, double cost)
 {
@@ -800,10 +802,12 @@ output_node (unsigned char *auxbuf, int *size, int ind, int node_code,
 }
 
 static int
-create_network_data (sqlite3 * handle, char *out_table, int force_creation,
-		     struct graph *p_graph, char *table, char *from_column,
-		     char *to_column, char *geom_column, char *name_column,
-		     int a_star_supported, double a_star_coeff)
+create_network_data (sqlite3 * handle, const char *out_table,
+		     int force_creation, struct graph *p_graph,
+		     const char *table, const char *from_column,
+		     const char *to_column, const char *geom_column,
+		     const char *name_column, int a_star_supported,
+		     double a_star_coeff)
 {
 /* creates the NETWORK-DATA table */
     int ret;
@@ -910,11 +914,15 @@ create_network_data (sqlite3 * handle, char *out_table, int force_creation,
 	  out += len;
 	  /* inserting the Geometry column name */
 	  *out++ = GAIA_NET_GEOM;
-	  len = strlen (geom_column) + 1;
+	  if (!geom_column)
+	      len = 1;
+	  else
+	      len = strlen (geom_column) + 1;
 	  gaiaExport16 (out, len, 1, endian_arch);	/* the Geometry column Name length, including last '\0' */
 	  out += 2;
 	  memset (out, '\0', len);
-	  strcpy ((char *) out, geom_column);
+	  if (geom_column)
+	      strcpy ((char *) out, geom_column);
 	  out += len;
 	  /* inserting the Name column name - may be empty */
 	  *out++ = GAIA_NET_NAME;
@@ -1037,6 +1045,40 @@ create_network_data (sqlite3 * handle, char *out_table, int force_creation,
     return 0;
 }
 
+static int
+create_virtual_network (sqlite3 * handle, const char *out_table,
+			const char *virt_table, int force_creation)
+{
+/* creates the VirtualNetwork table */
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+    if (force_creation)
+      {
+	  sprintf (sql, "DROP TABLE IF EXISTS \"%s\"", virt_table);
+	  ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
+	  if (ret != SQLITE_OK)
+	    {
+		printf ("DROP TABLE error: %s\n", err_msg);
+		sqlite3_free (err_msg);
+		goto abort;
+	    }
+      }
+/* creating the VirtualNetwork table */
+    sprintf (sql, "CREATE VIRTUAL TABLE \"%s\" USING  VirtualNetwork(\"%s\")",
+	     virt_table, out_table);
+    ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  printf ("CREATE TABLE error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto abort;
+      }
+    return 1;
+  abort:
+    return 0;
+}
+
 static void
 spatialite_autocreate (sqlite3 * db)
 {
@@ -1079,10 +1121,12 @@ spatialite_autocreate (sqlite3 * db)
 }
 
 static void
-validate (char *path, char *table, char *from_column, char *to_column,
-	  char *cost_column, char *geom_column, char *name_column,
-	  char *oneway_tofrom, char *oneway_fromto, int bidirectional,
-	  char *out_table, int force_creation, int a_star_supported)
+validate (const char *path, const char *table, const char *from_column,
+	  const char *to_column, const char *cost_column,
+	  const char *geom_column, const char *name_column,
+	  const char *oneway_tofrom, const char *oneway_fromto,
+	  int bidirectional, const char *out_table, const char *virt_table,
+	  int force_creation, int a_star_supported)
 {
 /* performs all the actual network validation */
     int ret;
@@ -1206,6 +1250,9 @@ validate (char *path, char *table, char *from_column, char *to_column,
     if (out_table)
       {
 	  printf ("\nNETWORK-DATA table creation required: '%s'\n", out_table);
+	  if (virt_table)
+	      printf ("\nVirtualNetwork table creation required: '%s'\n",
+		      virt_table);
 	  if (force_creation)
 	      printf ("Overwrite allowed if table already exists\n");
 	  else
@@ -1366,7 +1413,7 @@ validate (char *path, char *table, char *from_column, char *to_column,
 		if (type == SQLITE_INTEGER)
 		  {
 		      from_int = 1;
-		      id_from = sqlite3_column_int (stmt, 0);
+		      id_from = sqlite3_column_int64 (stmt, 0);
 		      insert_node (p_graph, id_from, "", 0);
 		  }
 		if (type == SQLITE_FLOAT)
@@ -1387,7 +1434,7 @@ validate (char *path, char *table, char *from_column, char *to_column,
 		if (type == SQLITE_INTEGER)
 		  {
 		      to_int = 1;
-		      id_to = sqlite3_column_int (stmt, 1);
+		      id_to = sqlite3_column_int64 (stmt, 1);
 		      insert_node (p_graph, id_to, "", 0);
 		  }
 		if (type == SQLITE_FLOAT)
@@ -1602,8 +1649,8 @@ validate (char *path, char *table, char *from_column, char *to_column,
 	  goto abort;
       }
     init_nodes (p_graph);
-    fprintf (stderr, "Step III - checking topologic consistency\n");
-/* checking topologic consistency */
+    fprintf (stderr, "Step III - checking topological consistency\n");
+/* checking topological consistency */
     sprintf (sql,
 	     "SELECT ROWID, \"%s\", \"%s\", X(StartPoint(\"%s\")), Y(StartPoint(\"%s\")), X(EndPoint(\"%s\")), Y(EndPoint(\"%s\"))",
 	     from_column, to_column, geom_column, geom_column, geom_column,
@@ -1819,6 +1866,17 @@ validate (char *path, char *table, char *from_column, char *to_column,
 		     out_table);
 		fprintf (stderr, "ERROR: table '%s' failure\n", out_table);
 	    }
+	  if (virt_table)
+	    {
+		ret =
+		    create_virtual_network (handle, out_table, virt_table,
+					    force_creation);
+		if (ret)
+		    fprintf (stderr, "OK: table '%s' successfully created\n",
+			     virt_table);
+		else
+		    fprintf (stderr, "ERROR: table '%s' failure\n", virt_table);
+	    }
       }
   abort:
 /* disconnecting the SpatiaLite DB */
@@ -1831,141 +1889,809 @@ validate (char *path, char *table, char *from_column, char *to_column,
 }
 
 static void
-do_help ()
-{
-/* printing the argument list */
-    fprintf (stderr, "\n\nusage: spatialite_network ARGLIST\n");
-    fprintf (stderr,
-	     "==============================================================\n");
-    fprintf (stderr,
-	     "-h or --help                      print this help message\n");
-    fprintf (stderr,
-	     "-d or --db-path pathname          the SpatiaLite db path\n");
-    fprintf (stderr,
-	     "-T or --table table_name          the db table to be validated\n");
-    fprintf (stderr,
-	     "-f or --from-column col_name      the column for FromNode\n");
-    fprintf (stderr,
-	     "-t or --to-column col_name        the column for ToNode\n");
-    fprintf (stderr,
-	     "-g or --geometry-column col_name  the column for Geometry\n");
-    fprintf (stderr, "-c or --cost-column col_name      the column for Cost\n");
-    fprintf (stderr,
-	     "                                  if omitted, GLength(g)\n");
-    fprintf (stderr,
-	     "                                  will be used by defualt\n\n");
-    fprintf (stderr, "you can specify the following options as well:\n");
-    fprintf (stderr, "----------------------------------------------\n");
-    fprintf (stderr, "--a-star-supported                *default*\n");
-    fprintf (stderr, "--a-star-excluded\n");
-    fprintf (stderr,
-	     "-n or --name-column col_name      the column for RoadName\n");
-    fprintf (stderr, "--bidirectional                   *default*\n");
-    fprintf (stderr, "--unidirectional\n\n");
-    fprintf (stderr,
-	     "if *bidirectional* each arc connecting FromNode to ToNode is\n");
-    fprintf (stderr,
-	     "implicitly connecting ToNode to FromNode as well; in this case\n");
-    fprintf (stderr, "you can select the following further options:\n");
-    fprintf (stderr, "--oneway-tofrom col_name\n");
-    fprintf (stderr, "--oneway-fromto col_name\n");
-    fprintf (stderr,
-	     "both columns are expected to contain BOOLEAN values [1-0];\n");
-    fprintf (stderr,
-	     "1 means that the arc connection in the given direction is\n");
-    fprintf (stderr, "valid, otherwise 0 means a forbidden connection\n\n");
-    fprintf (stderr, "in order to create a permanent NETWORK-DATA table\n");
-    fprintf (stderr, "you can select the following options:\n");
-    fprintf (stderr, "-o or --output-table table_name\n");
-    fprintf (stderr, "--overwrite-output\n\n");
-}
-
-int
-main (int argc, char *argv[])
+validate_no_geom (const char *path, const char *table, const char *from_column,
+		  const char *to_column, const char *cost_column,
+		  const char *name_column, const char *oneway_tofrom,
+		  const char *oneway_fromto, int bidirectional,
+		  const char *out_table, const char *virt_table,
+		  int force_creation)
 {
-/* the MAIN function simply perform arguments checking */
+/* performs all the actual network validation - NO-GEOMETRY */
+    int ret;
+    sqlite3 *handle;
+    sqlite3_stmt *stmt;
+    struct graph *p_graph = NULL;
+    char sql[1024];
+    char sql2[128];
+    char **results;
+    int n_rows;
+    int n_columns;
     int i;
-    int next_arg = ARG_NONE;
-    char *path = NULL;
-    char *table = NULL;
-    char *from_column = NULL;
-    char *to_column = NULL;
-    char *cost_column = NULL;
-    char *geom_column = NULL;
-    char *name_column = NULL;
-    char *oneway_tofrom = NULL;
-    char *oneway_fromto = NULL;
-    char *out_table = NULL;
-    int bidirectional = 1;
-    int force_creation = 0;
-    int error = 0;
-    int a_star_supported = 1;
-    for (i = 1; i < argc; i++)
+    char *err_msg = NULL;
+    char *col_name;
+    int type;
+    int ok_from_column = 0;
+    int ok_to_column = 0;
+    int ok_cost_column = 0;
+    int ok_name_column = 0;
+    int ok_oneway_tofrom = 0;
+    int ok_oneway_fromto = 0;
+    int from_null = 0;
+    int from_int = 0;
+    int from_double = 0;
+    int from_text = 0;
+    int from_blob = 0;
+    int to_null = 0;
+    int to_int = 0;
+    int to_double = 0;
+    int to_text = 0;
+    int to_blob = 0;
+    int cost_null = 0;
+    int cost_text = 0;
+    int cost_blob = 0;
+    int tofrom_null = 0;
+    int tofrom_double = 0;
+    int tofrom_text = 0;
+    int tofrom_blob = 0;
+    int fromto_null = 0;
+    int fromto_double = 0;
+    int fromto_text = 0;
+    int fromto_blob = 0;
+    int col_n;
+    int fromto_n;
+    int tofrom_n;
+    sqlite3_int64 rowid;
+    sqlite3_int64 id_from;
+    sqlite3_int64 id_to;
+    char code_from[1024];
+    char code_to[1024];
+    double cost;
+    int fromto;
+    int tofrom;
+    char xRowid[128];
+    char xIdFrom[128];
+    char xIdTo[128];
+    void *cache;
+
+/* showing the SQLite version */
+    fprintf (stderr, "SQLite version: %s\n", sqlite3_libversion ());
+/* showing the SpatiaLite version */
+    fprintf (stderr, "SpatiaLite version: %s\n", spatialite_version ());
+/* trying to connect the SpatiaLite DB  */
+    ret =
+	sqlite3_open_v2 (path, &handle,
+			 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
+    if (ret != SQLITE_OK)
       {
-	  /* parsing the invocation arguments */
-	  if (next_arg != ARG_NONE)
-	    {
-		switch (next_arg)
-		  {
-		  case ARG_DB_PATH:
-		      path = argv[i];
-		      break;
-		  case ARG_TABLE:
-		      table = argv[i];
-		      break;
-		  case ARG_OUT_TABLE:
-		      out_table = argv[i];
-		      break;
-		  case ARG_FROM_COLUMN:
-		      from_column = argv[i];
-		      break;
-		  case ARG_TO_COLUMN:
-		      to_column = argv[i];
-		      break;
-		  case ARG_COST_COLUMN:
-		      cost_column = argv[i];
-		      break;
-		  case ARG_GEOM_COLUMN:
-		      geom_column = argv[i];
-		      break;
-		  case ARG_NAME_COLUMN:
-		      name_column = argv[i];
-		      break;
-		  case ARG_ONEWAY_TOFROM:
-		      oneway_tofrom = argv[i];
-		      break;
-		  case ARG_ONEWAY_FROMTO:
-		      oneway_fromto = argv[i];
-		      break;
-		  };
-		next_arg = ARG_NONE;
-		continue;
-	    }
-	  if (strcasecmp (argv[i], "--help") == 0
-	      || strcmp (argv[i], "-h") == 0)
-	    {
-		do_help ();
-		return -1;
-	    }
-	  if (strcasecmp (argv[i], "--db-path") == 0)
-	    {
-		next_arg = ARG_DB_PATH;
-		continue;
-	    }
-	  if (strcmp (argv[i], "-d") == 0)
-	    {
-		next_arg = ARG_DB_PATH;
-		continue;
-	    }
-	  if (strcasecmp (argv[i], "--table") == 0)
+	  fprintf (stderr, "cannot open '%s': %s\n", path,
+		   sqlite3_errmsg (handle));
+	  sqlite3_close (handle);
+	  return;
+      }
+    cache = spatialite_alloc_connection ();
+    spatialite_init_ex (handle, cache, 0);
+    spatialite_autocreate (handle);
+
+    fprintf (stderr, "Step   I - checking for table and columns existence\n");
+/* reporting args */
+    printf ("\nspatialite-network\n\n");
+    printf
+	("==================================================================\n");
+    printf ("   SpatiaLite db: %s\n", path);
+    printf ("validating table: %s\n\n", table);
+    printf ("columns layout\n");
+    printf
+	("==================================================================\n");
+    printf ("FromNode: %s\n", from_column);
+    printf ("  ToNode: %s\n", to_column);
+    printf ("    Cost: %s\n", cost_column);
+    if (!name_column)
+	printf ("    Name: *unused*\n");
+    else
+	printf ("    Name: %s\n", name_column);
+    printf ("Geometry: *** unsupported ***\n\n");
+    if (bidirectional)
+      {
+	  printf ("assuming arcs to be BIDIRECTIONAL\n");
+	  if (oneway_tofrom && oneway_fromto)
 	    {
-		next_arg = ARG_TABLE;
-		continue;
+		printf ("OneWay To->From: %s\n", oneway_tofrom);
+		printf ("OneWay From->To: %s\n", oneway_fromto);
 	    }
-	  if (strcmp (argv[i], "-T") == 0)
-	    {
-		next_arg = ARG_TABLE;
-		continue;
+      }
+    else
+	printf ("assuming arcs to be UNIDIRECTIONAL\n");
+    if (out_table)
+      {
+	  printf ("\nNETWORK-DATA table creation required: '%s'\n", out_table);
+	  if (virt_table)
+	      printf ("\nVirtualNetwork table creation required: '%s'\n",
+		      virt_table);
+	  if (force_creation)
+	      printf ("Overwrite allowed if table already exists\n");
+	  else
+	      printf ("Overwrite not allowed if table already exists\n");
+      }
+    else
+	printf
+	    ("\nsimple validation required\n[NETWORK-DATA table creation is disabled]\n");
+    printf
+	("==================================================================\n\n");
+/* checking for table existence */
+    sprintf (sql,
+	     "SELECT \"tbl_name\" FROM \"sqlite_master\" WHERE Upper(\"tbl_name\") = Upper('%s') and \"type\" = 'table'",
+	     table);
+    ret =
+	sqlite3_get_table (handle, sql, &results, &n_rows, &n_columns,
+			   &err_msg);
+    if (ret != SQLITE_OK)
+      {
+/* some error occurred */
+	  fprintf (stderr, "query#1 SQL error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto abort;
+      }
+    if (n_rows == 0)
+      {
+	  /* required table does not exists */
+	  printf ("ERROR: table '%s' does not exists\n", table);
+	  goto abort;
+      }
+    else
+	sqlite3_free_table (results);
+/* checking for columns existence */
+    sprintf (sql, "PRAGMA table_info(\"%s\")", table);
+    ret =
+	sqlite3_get_table (handle, sql, &results, &n_rows, &n_columns,
+			   &err_msg);
+    if (ret != SQLITE_OK)
+      {
+/* some error occurred */
+	  fprintf (stderr, "query#2 SQL error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  goto abort;
+      }
+    if (n_rows > 1)
+      {
+	  for (i = 1; i <= n_rows; i++)
+	    {
+		col_name = results[(i * n_columns) + 1];
+		if (strcasecmp (from_column, col_name) == 0)
+		    ok_from_column = 1;
+		if (strcasecmp (to_column, col_name) == 0)
+		    ok_to_column = 1;
+		if (cost_column)
+		  {
+		      if (strcasecmp (cost_column, col_name) == 0)
+			  ok_cost_column = 1;
+		  }
+		if (name_column)
+		  {
+		      if (strcasecmp (name_column, col_name) == 0)
+			  ok_name_column = 1;
+		  }
+		if (oneway_tofrom)
+		  {
+		      if (strcasecmp (oneway_tofrom, col_name) == 0)
+			  ok_oneway_tofrom = 1;
+		  }
+		if (oneway_fromto)
+		  {
+		      if (strcasecmp (oneway_fromto, col_name) == 0)
+			  ok_oneway_fromto = 1;
+		  }
+	    }
+	  sqlite3_free_table (results);
+      }
+    if (!ok_from_column)
+	printf ("ERROR: column \"%s\".\"%s\" does not exists\n", table,
+		from_column);
+    if (!ok_to_column)
+	printf ("ERROR: column \"%s\".\"%s\" does not exists\n", table,
+		to_column);
+    if (cost_column && !ok_cost_column)
+	printf ("ERROR: column \"%s\".\"%s\" does not exists\n", table,
+		cost_column);
+    if (name_column && !ok_name_column)
+	printf ("ERROR: column \"%s\".\"%s\" does not exists\n", table,
+		name_column);
+    if (oneway_tofrom && !ok_oneway_tofrom)
+	printf ("ERROR: column \"%s\".\"%s\" does not exists\n", table,
+		oneway_tofrom);
+    if (oneway_fromto && !ok_oneway_fromto)
+	printf ("ERROR: column \"%s\".\"%s\" does not exists\n", table,
+		oneway_fromto);
+    if (!name_column)
+	ok_name_column = 1;
+    if (ok_from_column && ok_to_column && ok_name_column)
+	;
+    else
+	goto abort;
+    if (cost_column && !ok_cost_column)
+	goto abort;
+    if (oneway_tofrom && !ok_oneway_tofrom)
+	goto abort;
+    if (oneway_fromto && !ok_oneway_fromto)
+	goto abort;
+    fprintf (stderr, "Step  II - checking value types consistency\n");
+/* checking column types */
+    p_graph = graph_init ();
+    sprintf (sql, "SELECT \"%s\", \"%s\", \"%s\"", from_column, to_column,
+	     cost_column);
+    col_n = 3;
+    if (oneway_tofrom)
+      {
+	  sprintf (sql2, ", \"%s\"", oneway_tofrom);
+	  strcat (sql, sql2);
+	  tofrom_n = col_n;
+	  col_n++;
+      }
+    if (oneway_fromto)
+      {
+	  sprintf (sql2, ", \"%s\"", oneway_fromto);
+	  strcat (sql, sql2);
+	  fromto_n = col_n;
+	  col_n++;
+      }
+    sprintf (sql2, " FROM \"%s\"", table);
+    strcat (sql, sql2);
+    ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  printf ("query#4 SQL error: %s\n", sqlite3_errmsg (handle));
+	  goto abort;
+      }
+    n_columns = sqlite3_column_count (stmt);
+    while (1)
+      {
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;
+	  if (ret == SQLITE_ROW)
+	    {
+		/* the NodeFrom type */
+		type = sqlite3_column_type (stmt, 0);
+		if (type == SQLITE_NULL)
+		    from_null = 1;
+		if (type == SQLITE_INTEGER)
+		  {
+		      from_int = 1;
+		      id_from = sqlite3_column_int64 (stmt, 0);
+		      insert_node (p_graph, id_from, "", 0);
+		  }
+		if (type == SQLITE_FLOAT)
+		    from_double = 1;
+		if (type == SQLITE_TEXT)
+		  {
+		      from_text = 1;
+		      strcpy (code_from,
+			      (char *) sqlite3_column_text (stmt, 0));
+		      insert_node (p_graph, -1, code_from, 1);
+		  }
+		if (type == SQLITE_BLOB)
+		    from_blob = 1;
+		/* the NodeTo type */
+		type = sqlite3_column_type (stmt, 1);
+		if (type == SQLITE_NULL)
+		    to_null = 1;
+		if (type == SQLITE_INTEGER)
+		  {
+		      to_int = 1;
+		      id_to = sqlite3_column_int64 (stmt, 1);
+		      insert_node (p_graph, id_to, "", 0);
+		  }
+		if (type == SQLITE_FLOAT)
+		    to_double = 1;
+		if (type == SQLITE_TEXT)
+		  {
+		      to_text = 1;
+		      strcpy (code_to, (char *) sqlite3_column_text (stmt, 1));
+		      insert_node (p_graph, -1, code_to, 1);
+		  }
+		if (type == SQLITE_BLOB)
+		    to_blob = 1;
+		/* the Cost type */
+		type = sqlite3_column_type (stmt, 2);
+		if (type == SQLITE_NULL)
+		    cost_null = 1;
+		if (type == SQLITE_TEXT)
+		    cost_text = 1;
+		if (type == SQLITE_BLOB)
+		    cost_blob = 1;
+		col_n = 3;
+		if (oneway_fromto)
+		  {
+		      /* the FromTo type */
+		      type = sqlite3_column_type (stmt, col_n);
+		      col_n++;
+		      if (type == SQLITE_NULL)
+			  fromto_null = 1;
+		      if (type == SQLITE_FLOAT)
+			  fromto_double = 1;
+		      if (type == SQLITE_TEXT)
+			  fromto_text = 1;
+		      if (type == SQLITE_BLOB)
+			  fromto_blob = 1;
+		  }
+		if (oneway_tofrom)
+		  {
+		      /* the ToFrom type */
+		      type = sqlite3_column_type (stmt, col_n);
+		      col_n++;
+		      if (type == SQLITE_NULL)
+			  tofrom_null = 1;
+		      if (type == SQLITE_FLOAT)
+			  tofrom_double = 1;
+		      if (type == SQLITE_TEXT)
+			  tofrom_text = 1;
+		      if (type == SQLITE_BLOB)
+			  tofrom_blob = 1;
+		  }
+	    }
+	  else
+	    {
+		printf ("sqlite3_step() error: %s\n", sqlite3_errmsg (handle));
+		sqlite3_finalize (stmt);
+		goto abort;
+	    }
+      }
+    sqlite3_finalize (stmt);
+    ret = 1;
+    if (from_null)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains NULL values\n", table,
+		  from_column);
+	  ret = 0;
+      }
+    if (from_blob)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains BLOB values\n", table,
+		  from_column);
+	  ret = 0;
+      }
+    if (from_double)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains DOUBLE values\n", table,
+		  from_column);
+	  ret = 0;
+      }
+    if (to_null)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains NULL values\n", table,
+		  to_column);
+	  ret = 0;
+      }
+    if (to_blob)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains BLOB values\n", table,
+		  to_column);
+	  ret = 0;
+      }
+    if (to_double)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains DOUBLE values\n", table,
+		  to_column);
+	  ret = 0;
+      }
+    if (cost_null)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains NULL values\n",
+		  table, cost_column);
+	  ret = 0;
+      }
+    if (cost_blob)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains BLOB values\n",
+		  table, cost_column);
+	  ret = 0;
+      }
+    if (cost_text)
+      {
+	  printf ("ERROR: column \"%s\".\"%s\" contains TEXT values\n",
+		  table, cost_column);
+	  ret = 0;
+      }
+    if (oneway_fromto)
+      {
+	  if (fromto_null)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains NULL values\n",
+			table, oneway_fromto);
+		ret = 0;
+	    }
+	  if (fromto_blob)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains BLOB values\n",
+			table, oneway_fromto);
+		ret = 0;
+	    }
+	  if (fromto_text)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains TEXT values\n",
+			table, oneway_fromto);
+		ret = 0;
+	    }
+	  if (fromto_double)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains DOUBLE values\n",
+			table, oneway_fromto);
+		ret = 0;
+	    }
+      }
+    if (oneway_tofrom)
+      {
+	  if (tofrom_null)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains NULL values\n",
+			table, oneway_tofrom);
+		ret = 0;
+	    }
+	  if (tofrom_blob)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains BLOB values\n",
+			table, oneway_tofrom);
+		ret = 0;
+	    }
+	  if (tofrom_text)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains TEXT values\n",
+			table, oneway_tofrom);
+		ret = 0;
+	    }
+	  if (tofrom_double)
+	    {
+		printf ("ERROR: column \"%s\".\"%s\" contains DOUBLE values\n",
+			table, oneway_tofrom);
+		ret = 0;
+	    }
+      }
+    if (!ret)
+	goto abort;
+    if (from_int && to_int)
+      {
+	  /* each node is identified by an INTEGER id */
+	  p_graph->node_code = 0;
+      }
+    else if (from_text && to_text)
+      {
+	  /* each node is identified by a TEXT code */
+	  p_graph->node_code = 1;
+      }
+    else
+      {
+	  printf ("ERROR: NodeFrom / NodeTo have different value types\n");
+	  goto abort;
+      }
+    init_nodes (p_graph);
+    fprintf (stderr, "Step III - checking topological consistency\n");
+/* checking topological consistency */
+    sprintf (sql,
+	     "SELECT ROWID, \"%s\", \"%s\", \"%s\"",
+	     from_column, to_column, cost_column);
+    col_n = 4;
+    if (oneway_tofrom)
+      {
+	  sprintf (sql2, ", \"%s\"", oneway_tofrom);
+	  strcat (sql, sql2);
+	  tofrom_n = col_n;
+	  col_n++;
+      }
+    if (oneway_fromto)
+      {
+	  sprintf (sql2, ", \"%s\"", oneway_fromto);
+	  strcat (sql, sql2);
+	  fromto_n = col_n;
+	  col_n++;
+      }
+    sprintf (sql2, " FROM \"%s\"", table);
+    strcat (sql, sql2);
+    ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  printf ("query#4 SQL error: %s\n", sqlite3_errmsg (handle));
+	  goto abort;
+      }
+    n_columns = sqlite3_column_count (stmt);
+    while (1)
+      {
+	  ret = sqlite3_step (stmt);
+	  if (ret == SQLITE_DONE)
+	      break;
+	  if (ret == SQLITE_ROW)
+	    {
+		fromto = 1;
+		tofrom = 1;
+		if (p_graph->node_code)
+		  {
+		      id_from = -1;
+		      id_to = -1;
+		  }
+		else
+		  {
+		      *code_from = '\0';
+		      *code_to = '\0';
+		  }
+		/* fetching the ROWID */
+		rowid = sqlite3_column_int64 (stmt, 0);
+		/* fetching the NodeFrom value */
+		if (p_graph->node_code)
+		    strcpy (code_from, (char *) sqlite3_column_text (stmt, 1));
+		else
+		    id_from = sqlite3_column_int64 (stmt, 1);
+		/* fetching the NodeTo value */
+		if (p_graph->node_code)
+		    strcpy (code_to, (char *) sqlite3_column_text (stmt, 2));
+		else
+		    id_to = sqlite3_column_int64 (stmt, 2);
+		/* fetching the Cost value */
+		cost = sqlite3_column_double (stmt, 3);
+		if (oneway_fromto)
+		  {
+		      /* fetching the OneWay-FromTo value */
+		      fromto = sqlite3_column_int (stmt, fromto_n);
+		  }
+		if (oneway_tofrom)
+		  {
+		      /* fetching the OneWay-ToFrom value */
+		      tofrom = sqlite3_column_int (stmt, tofrom_n);
+		  }
+		sprintf (xRowid, FORMAT_64, rowid);
+		if (cost <= 0.0)
+		  {
+		      printf
+			  ("ERROR: arc ROWID=%s has NEGATIVE or NULL cost [%1.6f]\n",
+			   xRowid, cost);
+		      p_graph->error = 1;
+		  }
+		if (bidirectional)
+		  {
+		      if (!fromto && !tofrom)
+			{
+			    if (p_graph->node_code)
+				printf
+				    ("WARNING: arc forbidden in both directions; ROWID=%s From=%s To=%s\n",
+				     xRowid, code_from, code_to);
+			    else
+			      {
+				  sprintf (xIdFrom, FORMAT_64, id_from);
+				  sprintf (xIdTo, FORMAT_64, id_to);
+				  printf
+				      ("WARNING: arc forbidden in both directions; ROWID=%s From=%s To=%s\n",
+				       xRowid, xIdFrom, xIdTo);
+			      }
+			}
+		      if (fromto)
+			  add_arc (p_graph, rowid, id_from, id_to, code_from,
+				   code_to, DBL_MAX, DBL_MAX, DBL_MAX, DBL_MAX,
+				   cost);
+		      if (tofrom)
+			  add_arc (p_graph, rowid, id_to, id_from, code_to,
+				   code_from, DBL_MAX, DBL_MAX, DBL_MAX,
+				   DBL_MAX, cost);
+		  }
+		else
+		    add_arc (p_graph, rowid, id_from, id_to, code_from, code_to,
+			     DBL_MAX, DBL_MAX, DBL_MAX, DBL_MAX, cost);
+		if (p_graph->error)
+		  {
+		      printf ("\n\nERROR: network failed validation\n");
+		      printf
+			  ("\tyou cannot apply this configuration to build a valid VirtualNetwork\n");
+		      sqlite3_finalize (stmt);
+		      goto abort;
+		  }
+	    }
+	  else
+	    {
+		printf ("sqlite3_step() error: %s\n", sqlite3_errmsg (handle));
+		sqlite3_finalize (stmt);
+		goto abort;
+	    }
+      }
+    sqlite3_finalize (stmt);
+    fprintf (stderr, "Step  IV - final evaluation\n");
+/* final printout */
+    if (p_graph->error)
+      {
+	  printf ("\n\nERROR: network failed validation\n");
+	  printf
+	      ("\tyou cannot apply this configuration to build a valid VirtualNetwork\n");
+	  fprintf (stderr, "ERROR: VALIDATION FAILURE\n");
+      }
+    else
+      {
+	  print_report (p_graph);
+	  printf ("\n\nOK: network passed validation\n");
+	  printf
+	      ("\tyou can apply this configuration to build a valid VirtualNetwork\n");
+	  fprintf (stderr, "OK: validation passed\n");
+      }
+    if (out_table)
+      {
+	  ret =
+	      create_network_data (handle, out_table, force_creation, p_graph,
+				   table, from_column, to_column, NULL,
+				   name_column, 0, DBL_MAX);
+	  if (ret)
+	    {
+		printf
+		    ("\n\nOK: NETWORK-DATA table '%s' successfully created\n",
+		     out_table);
+		fprintf (stderr, "OK: table '%s' successfully created\n",
+			 out_table);
+		if (virt_table)
+		  {
+		      ret =
+			  create_virtual_network (handle, out_table, virt_table,
+						  force_creation);
+		      if (ret)
+			  fprintf (stderr,
+				   "OK: table '%s' successfully created\n",
+				   virt_table);
+		      else
+			  fprintf (stderr, "ERROR: table '%s' failure\n",
+				   virt_table);
+		  }
+	    }
+	  else
+	    {
+		printf
+		    ("\n\nERROR: creating the NETWORK-DATA table '%s' was not possible\n",
+		     out_table);
+		fprintf (stderr, "ERROR: table '%s' failure\n", out_table);
+	    }
+      }
+  abort:
+/* disconnecting the SpatiaLite DB */
+    ret = sqlite3_close (handle);
+    if (ret != SQLITE_OK)
+	fprintf (stderr, "sqlite3_close() error: %s\n",
+		 sqlite3_errmsg (handle));
+    spatialite_cleanup_ex (cache);
+    graph_free (p_graph);
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+    fprintf (stderr, "\n\nusage: spatialite_network ARGLIST\n");
+    fprintf (stderr,
+	     "==============================================================\n");
+    fprintf (stderr,
+	     "-h or --help                      print this help message\n");
+    fprintf (stderr,
+	     "-d or --db-path pathname          the SpatiaLite db path\n");
+    fprintf (stderr,
+	     "-T or --table table_name          the db table to be validated\n");
+    fprintf (stderr,
+	     "-f or --from-column col_name      the column for FromNode\n");
+    fprintf (stderr,
+	     "-t or --to-column col_name        the column for ToNode\n");
+    fprintf (stderr,
+	     "-g or --geometry-column col_name  the column for Geometry\n");
+    fprintf (stderr, "-c or --cost-column col_name      the column for Cost\n");
+    fprintf (stderr,
+	     "                                  if omitted, GLength(g)\n");
+    fprintf (stderr,
+	     "                                  will be used by default\n\n");
+    fprintf (stderr, "you can specify the following options as well:\n");
+    fprintf (stderr, "----------------------------------------------\n");
+    fprintf (stderr, "--a-star-supported                *default*\n");
+    fprintf (stderr, "--a-star-excluded\n");
+    fprintf (stderr,
+	     "-n or --name-column col_name      the column for RoadName\n");
+    fprintf (stderr, "--bidirectional                   *default*\n");
+    fprintf (stderr, "--unidirectional\n\n");
+    fprintf (stderr,
+	     "if *bidirectional* each arc connecting FromNode to ToNode is\n");
+    fprintf (stderr,
+	     "implicitly connecting ToNode to FromNode as well; in this case\n");
+    fprintf (stderr, "you can select the following further options:\n");
+    fprintf (stderr, "--oneway-tofrom col_name\n");
+    fprintf (stderr, "--oneway-fromto col_name\n");
+    fprintf (stderr,
+	     "both columns are expected to contain BOOLEAN values [1-0];\n");
+    fprintf (stderr,
+	     "1 means that the arc connection in the given direction is\n");
+    fprintf (stderr, "valid, otherwise 0 means a forbidden connection\n\n");
+    fprintf (stderr, "in order to create a permanent NETWORK-DATA table\n");
+    fprintf (stderr, "you can select the following options:\n");
+    fprintf (stderr, "-o or --output-table table_name\n");
+    fprintf (stderr, "-v or --virtual-table table_name\n");
+    fprintf (stderr, "--overwrite-output\n\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function simply perform arguments checking */
+    int i;
+    int next_arg = ARG_NONE;
+    char *path = NULL;
+    char *table = NULL;
+    char *from_column = NULL;
+    char *to_column = NULL;
+    char *cost_column = NULL;
+    char *geom_column = NULL;
+    char *name_column = NULL;
+    char *oneway_tofrom = NULL;
+    char *oneway_fromto = NULL;
+    char *out_table = NULL;
+    char *virt_table = NULL;
+    int bidirectional = 1;
+    int force_creation = 0;
+    int error = 0;
+    int a_star_supported = 1;
+    for (i = 1; i < argc; i++)
+      {
+	  /* parsing the invocation arguments */
+	  if (next_arg != ARG_NONE)
+	    {
+		switch (next_arg)
+		  {
+		  case ARG_DB_PATH:
+		      path = argv[i];
+		      break;
+		  case ARG_TABLE:
+		      table = argv[i];
+		      break;
+		  case ARG_OUT_TABLE:
+		      out_table = argv[i];
+		      break;
+		  case ARG_VIRT_TABLE:
+		      virt_table = argv[i];
+		      break;
+		  case ARG_FROM_COLUMN:
+		      from_column = argv[i];
+		      break;
+		  case ARG_TO_COLUMN:
+		      to_column = argv[i];
+		      break;
+		  case ARG_COST_COLUMN:
+		      cost_column = argv[i];
+		      break;
+		  case ARG_GEOM_COLUMN:
+		      geom_column = argv[i];
+		      break;
+		  case ARG_NAME_COLUMN:
+		      name_column = argv[i];
+		      break;
+		  case ARG_ONEWAY_TOFROM:
+		      oneway_tofrom = argv[i];
+		      break;
+		  case ARG_ONEWAY_FROMTO:
+		      oneway_fromto = argv[i];
+		      break;
+		  };
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--help") == 0
+	      || strcmp (argv[i], "-h") == 0)
+	    {
+		do_help ();
+		return -1;
+	    }
+	  if (strcasecmp (argv[i], "--db-path") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcmp (argv[i], "-d") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--table") == 0)
+	    {
+		next_arg = ARG_TABLE;
+		continue;
+	    }
+	  if (strcmp (argv[i], "-T") == 0)
+	    {
+		next_arg = ARG_TABLE;
+		continue;
 	    }
 	  if (strcasecmp (argv[i], "--output-table") == 0)
 	    {
@@ -1977,6 +2703,16 @@ main (int argc, char *argv[])
 		next_arg = ARG_OUT_TABLE;
 		continue;
 	    }
+	  if (strcasecmp (argv[i], "--virtual-table") == 0)
+	    {
+		next_arg = ARG_VIRT_TABLE;
+		continue;
+	    }
+	  if (strcmp (argv[i], "-v") == 0)
+	    {
+		next_arg = ARG_VIRT_TABLE;
+		continue;
+	    }
 	  if (strcasecmp (argv[i], "--from-column") == 0)
 	    {
 		next_arg = ARG_FROM_COLUMN;
@@ -2120,9 +2856,30 @@ main (int argc, char *argv[])
 	  do_help ();
 	  return -1;
       }
-    validate (path, table, from_column, to_column, cost_column, geom_column,
-	      name_column, oneway_tofrom, oneway_fromto, bidirectional,
-	      out_table, force_creation, a_star_supported);
+    if (strcasecmp (geom_column, "NULL") == 0
+	|| strcasecmp (geom_column, "NONE") == 0
+	|| strcasecmp (geom_column, "NO") == 0)
+      {
+	  /* NULL-Geometry has been explicitly requested */
+	  geom_column = NULL;
+	  a_star_supported = 0;
+	  fprintf (stderr, "\nWARNING: a NO-GEOMETRY graph would be processed\n"
+		   "the A* algorithm will be consequently disabled.\n\n");
+	  if (!cost_column)
+	    {
+		fprintf (stderr,
+			 "NO-GEOMETRY strictly requires to specify some --cost-column argument\n");
+		return -1;
+	    }
+      }
+    if (geom_column == NULL)
+	validate_no_geom (path, table, from_column, to_column, cost_column,
+			  name_column, oneway_tofrom, oneway_fromto,
+			  bidirectional, out_table, virt_table, force_creation);
+    else
+	validate (path, table, from_column, to_column, cost_column, geom_column,
+		  name_column, oneway_tofrom, oneway_fromto, bidirectional,
+		  out_table, virt_table, force_creation, a_star_supported);
     spatialite_shutdown ();
     return 0;
 }
diff --git a/spatialite_osm_overpass.c b/spatialite_osm_overpass.c
new file mode 100644
index 0000000..1ece7b6
--- /dev/null
+++ b/spatialite_osm_overpass.c
@@ -0,0 +1,4591 @@
+/* 
+/ spatialite_osm_overpass
+/
+/ a tool downloading OSM datasets via the Overpass wep API
+/
+/ version 1.0, 2014 November 13
+/
+/ Author: Sandro Furieri a.furieri at lqt.it
+/
+/ Copyright (C) 2014  Alessandro Furieri
+/
+/    This program is free software: you can redistribute it and/or modify
+/    it under the terms of the GNU General Public License as published by
+/    the Free Software Foundation, either version 3 of the License, or
+/    (at your option) any later version.
+/
+/    This program is distributed in the hope that it will be useful,
+/    but WITHOUT ANY WARRANTY; without even the implied warranty of
+/    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+/    GNU General Public License for more details.
+/
+/    You should have received a copy of the GNU General Public License
+/    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+
+#include <libxml/parser.h>
+#include <libxml/nanohttp.h>
+
+#include <sqlite3.h>
+#include <spatialite/gaiageo.h>
+#include <spatialite.h>
+
+#define ARG_NONE		0
+#define ARG_OSM_URL		1
+#define ARG_MINX		2
+#define ARG_MINY		3
+#define ARG_MAXX		4
+#define ARG_MAXY		5
+#define ARG_DB_PATH		6
+#define ARG_MODE		7
+#define ARG_CACHE_SIZE	8
+
+#define MODE_RAW	1
+#define MODE_MAP	2
+#define MODE_RAIL	3
+#define MODE_ROAD	4
+
+#define OBJ_NODES		1
+#define OBJ_WAYS		2
+#define OBJ_RELATIONS	3
+
+#if defined(_WIN32)
+#define atol_64		_atoi64
+#else
+#define atol_64		atoll
+#endif
+
+struct layers
+{
+    const char *name;
+    int ok_point;
+    int ok_linestring;
+    int ok_polygon;
+    int ok_multi_linestring;
+    int ok_multi_polygon;
+    sqlite3_stmt *ins_point_stmt;
+    sqlite3_stmt *ins_linestring_stmt;
+    sqlite3_stmt *ins_polygon_stmt;
+    sqlite3_stmt *ins_multi_linestring_stmt;
+    sqlite3_stmt *ins_multi_polygon_stmt;
+} base_layers[] =
+{
+    {
+    "highway", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "junction", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "traffic_calming", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "traffic_sign", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "service", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "barrier", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "cycleway", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "tracktype", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "waterway", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "railway", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "aeroway", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "aerialway", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "power", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "man_made", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "leisure", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "amenity", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "shop", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "tourism", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "historic", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "landuse", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "military", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "natural", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "geological", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "route", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "boundary", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "sport", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "abutters", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "accessories", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "properties", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "restrictions", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "place", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "building", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+    "parking", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},
+    {
+NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL},};
+
+struct download_tile
+{
+/* an helper struct corresponging to a single download tile */
+    int tile_no;
+    double minx;
+    double miny;
+    double maxx;
+    double maxy;
+    struct download_tile *next;
+};
+
+struct tiled_download
+{
+/* a tiled downloader object */
+    int count;
+    struct download_tile *first;
+    struct download_tile *last;
+};
+
+struct aux_params
+{
+/* an auxiliary struct used for XML parsing */
+    sqlite3 *db_handle;
+    void *cache;
+    sqlite3_stmt *ins_nodes_stmt;
+    sqlite3_stmt *ins_node_tags_stmt;
+    sqlite3_stmt *ins_ways_stmt;
+    sqlite3_stmt *ins_way_tags_stmt;
+    sqlite3_stmt *ins_way_refs_stmt;
+    sqlite3_stmt *ins_relations_stmt;
+    sqlite3_stmt *ins_relation_tags_stmt;
+    sqlite3_stmt *ins_relation_refs_stmt;
+    int wr_nodes;
+    int wr_node_tags;
+    int wr_ways;
+    int wr_way_tags;
+    int wr_way_refs;
+    int wr_relations;
+    int wr_rel_tags;
+    int wr_rel_refs;
+    const char *osm_url;
+    int mode;
+    sqlite3_int64 current_node_id;
+    int current_node_tag_sub;
+    sqlite3_int64 current_way_id;
+    int current_way_tag_sub;
+    int current_way_ref_sub;
+    sqlite3_int64 current_rel_id;
+    int current_rel_tag_sub;
+    int current_rel_ref_sub;
+};
+
+struct aux_arc
+{
+/* an helper struct used to build Road/Rail arcs */
+    sqlite3_int64 node_from;
+    sqlite3_int64 node_to;
+    gaiaGeomCollPtr geom_from;
+    gaiaGeomCollPtr geom_to;
+    gaiaGeomCollPtr geom;
+    struct aux_arc *next;
+};
+
+struct aux_arc_container
+{
+/* container for Road/Rail arcs */
+    struct aux_arc *first;
+    struct aux_arc *last;
+};
+
+static void
+finalize_map_stmts ()
+{
+/* finalizing all Map statements */
+    struct layers *layer;
+    int i = 0;
+
+    while (1)
+      {
+	  layer = &(base_layers[i++]);
+	  if (layer->name == NULL)
+	      break;
+	  if (layer->ins_point_stmt != NULL)
+	      sqlite3_finalize (layer->ins_point_stmt);
+	  if (layer->ins_linestring_stmt != NULL)
+	      sqlite3_finalize (layer->ins_linestring_stmt);
+	  if (layer->ins_polygon_stmt != NULL)
+	      sqlite3_finalize (layer->ins_polygon_stmt);
+	  if (layer->ins_multi_linestring_stmt != NULL)
+	      sqlite3_finalize (layer->ins_multi_linestring_stmt);
+	  if (layer->ins_multi_polygon_stmt != NULL)
+	      sqlite3_finalize (layer->ins_multi_polygon_stmt);
+      }
+}
+
+static void
+add_download_tile (struct tiled_download *obj, double minx, double miny,
+		   double maxx, double maxy)
+{
+/* inserting a further tile into the downloader object */
+    struct download_tile *tile = malloc (sizeof (struct download_tile));
+    tile->tile_no = obj->count;
+    tile->minx = minx;
+    tile->miny = miny;
+    tile->maxx = maxx;
+    tile->maxy = maxy;
+    tile->next = NULL;
+    if (obj->first == NULL)
+	obj->first = tile;
+    if (obj->last != NULL)
+	obj->last->next = tile;
+    obj->last = tile;
+    obj->count++;
+}
+
+static void
+downloader_cleanup (struct tiled_download *obj)
+{
+/* freeing the tiled downloader object */
+    struct download_tile *tile;
+    struct download_tile *tile_n;
+    tile = obj->first;
+    while (tile != NULL)
+      {
+	  tile_n = tile->next;
+	  free (tile);
+	  tile = tile_n;
+      }
+}
+
+static int
+insert_node_tag (struct aux_params *params, const char *k, const char *v)
+{
+/* inserting a raw <node><tag> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_node_tags_stmt);
+    sqlite3_clear_bindings (params->ins_node_tags_stmt);
+    sqlite3_bind_int64 (params->ins_node_tags_stmt, 1, params->current_node_id);
+    sqlite3_bind_int (params->ins_node_tags_stmt, 2,
+		      params->current_node_tag_sub);
+    sqlite3_bind_text (params->ins_node_tags_stmt, 3, k, strlen (k),
+		       SQLITE_STATIC);
+    sqlite3_bind_text (params->ins_node_tags_stmt, 4, v, strlen (v),
+		       SQLITE_STATIC);
+    ret = sqlite3_step (params->ins_node_tags_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_node_tags += 1;
+    params->current_node_tag_sub += 1;
+    return 1;
+}
+
+static int
+insert_way_ref (struct aux_params *params, sqlite3_int64 node_id)
+{
+/* inserting a raw <way><nd> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_way_refs_stmt);
+    sqlite3_clear_bindings (params->ins_way_refs_stmt);
+    sqlite3_bind_int64 (params->ins_way_refs_stmt, 1, params->current_way_id);
+    sqlite3_bind_int (params->ins_way_refs_stmt, 2,
+		      params->current_way_ref_sub);
+    sqlite3_bind_int64 (params->ins_way_refs_stmt, 3, node_id);
+    ret = sqlite3_step (params->ins_way_refs_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_way_refs += 1;
+    params->current_way_ref_sub += 1;
+    return 1;
+}
+
+static int
+insert_way_tag (struct aux_params *params, const char *k, const char *v)
+{
+/* inserting a raw <way><tag> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_way_tags_stmt);
+    sqlite3_clear_bindings (params->ins_way_tags_stmt);
+    sqlite3_bind_int64 (params->ins_way_tags_stmt, 1, params->current_way_id);
+    sqlite3_bind_int (params->ins_way_tags_stmt, 2,
+		      params->current_way_tag_sub);
+    sqlite3_bind_text (params->ins_way_tags_stmt, 3, k, strlen (k),
+		       SQLITE_STATIC);
+    sqlite3_bind_text (params->ins_way_tags_stmt, 4, v, strlen (v),
+		       SQLITE_STATIC);
+    ret = sqlite3_step (params->ins_way_tags_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_way_tags += 1;
+    params->current_way_tag_sub += 1;
+    return 1;
+}
+
+static int
+insert_relation_ref (struct aux_params *params, const char *type,
+		     sqlite3_int64 ref, const char *role)
+{
+/* inserting a raw <relation><member> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_relation_refs_stmt);
+    sqlite3_clear_bindings (params->ins_relation_refs_stmt);
+    sqlite3_bind_int64 (params->ins_relation_refs_stmt, 1,
+			params->current_rel_id);
+    sqlite3_bind_int (params->ins_relation_refs_stmt, 2,
+		      params->current_rel_ref_sub);
+    sqlite3_bind_text (params->ins_relation_refs_stmt, 3, type, strlen (type),
+		       SQLITE_STATIC);
+    sqlite3_bind_int64 (params->ins_relation_refs_stmt, 4, ref);
+    sqlite3_bind_text (params->ins_relation_refs_stmt, 5, role, strlen (role),
+		       SQLITE_STATIC);
+    ret = sqlite3_step (params->ins_relation_refs_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_rel_refs += 1;
+    params->current_rel_ref_sub += 1;
+    return 1;
+}
+
+static int
+insert_relation_tag (struct aux_params *params, const char *k, const char *v)
+{
+/* inserting a raw <relation><tag> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_relation_tags_stmt);
+    sqlite3_clear_bindings (params->ins_relation_tags_stmt);
+    sqlite3_bind_int64 (params->ins_relation_tags_stmt, 1,
+			params->current_rel_id);
+    sqlite3_bind_int (params->ins_relation_tags_stmt, 2,
+		      params->current_rel_tag_sub);
+    sqlite3_bind_text (params->ins_relation_tags_stmt, 3, k, strlen (k),
+		       SQLITE_STATIC);
+    sqlite3_bind_text (params->ins_relation_tags_stmt, 4, v, strlen (v),
+		       SQLITE_STATIC);
+    ret = sqlite3_step (params->ins_relation_tags_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_rel_tags += 1;
+    params->current_rel_tag_sub += 1;
+    return 1;
+}
+
+static int
+insert_node (struct aux_params *params, sqlite3_int64 id, double x, double y,
+	     int version, const char *timestamp, int uid, int changeset,
+	     const char *user)
+{
+/* inserting a raw <node> into the DBMS */
+    int ret;
+    unsigned char *blob;
+    int blob_size;
+    gaiaGeomCollPtr geom = gaiaAllocGeomColl ();
+    geom->Srid = 4326;
+    gaiaAddPointToGeomColl (geom, x, y);
+    sqlite3_reset (params->ins_nodes_stmt);
+    sqlite3_clear_bindings (params->ins_nodes_stmt);
+    if (params->mode == MODE_RAW)
+      {
+	  sqlite3_bind_int64 (params->ins_nodes_stmt, 1, id);
+	  sqlite3_bind_int (params->ins_nodes_stmt, 2, version);
+	  if (timestamp == NULL)
+	      sqlite3_bind_null (params->ins_nodes_stmt, 3);
+	  else
+	      sqlite3_bind_text (params->ins_nodes_stmt, 3, timestamp,
+				 strlen (timestamp), SQLITE_STATIC);
+	  sqlite3_bind_int (params->ins_nodes_stmt, 4, uid);
+	  if (user == NULL)
+	      sqlite3_bind_null (params->ins_nodes_stmt, 5);
+	  else
+	      sqlite3_bind_text (params->ins_nodes_stmt, 5, user, strlen (user),
+				 SQLITE_STATIC);
+	  sqlite3_bind_int (params->ins_nodes_stmt, 6, changeset);
+	  if (!geom)
+	      sqlite3_bind_null (params->ins_nodes_stmt, 7);
+	  else
+	    {
+		gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
+		gaiaFreeGeomColl (geom);
+		sqlite3_bind_blob (params->ins_nodes_stmt, 7, blob, blob_size,
+				   free);
+	    }
+      }
+    else
+      {
+	  sqlite3_bind_int64 (params->ins_nodes_stmt, 1, id);
+	  if (!geom)
+	      sqlite3_bind_null (params->ins_nodes_stmt, 2);
+	  else
+	    {
+		gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
+		gaiaFreeGeomColl (geom);
+		sqlite3_bind_blob (params->ins_nodes_stmt, 2, blob, blob_size,
+				   free);
+	    }
+      }
+    ret = sqlite3_step (params->ins_nodes_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_nodes += 1;
+    params->current_node_id = id;
+    params->current_node_tag_sub = 0;
+    return 1;
+}
+
+static int
+insert_way (struct aux_params *params, sqlite3_int64 id)
+{
+/* inserting a raw <way> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_ways_stmt);
+    sqlite3_clear_bindings (params->ins_ways_stmt);
+    sqlite3_bind_int64 (params->ins_ways_stmt, 1, id);
+    ret = sqlite3_step (params->ins_ways_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_ways += 1;
+    params->current_way_id = id;
+    params->current_way_ref_sub = 0;
+    params->current_way_tag_sub = 0;
+    return 1;
+}
+
+static int
+insert_relation (struct aux_params *params, sqlite3_int64 id)
+{
+/* inserting a raw <relation> into the DBMS */
+    int ret;
+    sqlite3_reset (params->ins_relations_stmt);
+    sqlite3_clear_bindings (params->ins_relations_stmt);
+    sqlite3_bind_int64 (params->ins_relations_stmt, 1, id);
+    ret = sqlite3_step (params->ins_relations_stmt);
+    if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	params->wr_relations += 1;
+    params->current_rel_id = id;
+    params->current_rel_ref_sub = 0;
+    params->current_rel_tag_sub = 0;
+    return 1;
+}
+
+const char *
+parse_attribute_value (xmlNodePtr node)
+{
+/* parsing a string argument */
+    if (node != NULL)
+      {
+	  if (node->type == XML_TEXT_NODE)
+	      return (const char *) (node->content);
+      }
+    return NULL;
+}
+
+static int
+parse_osm_nd_ref (struct _xmlAttr *attr, sqlite3_int64 * node_id)
+{
+/* parsing the OSM <node> attributes */
+    const char *attr_ref = NULL;
+    while (attr != NULL)
+      {
+	  if (attr->name != NULL)
+	    {
+		if (strcmp ((const char *) (attr->name), "ref") == 0)
+		    attr_ref = parse_attribute_value (attr->children);
+	    }
+	  attr = attr->next;
+      }
+    if (attr_ref == NULL)
+      {
+	  fprintf (stderr, "Invalid OSM <nd>: ref=%s\n", attr_ref);
+	  return 0;
+      }
+    *node_id = atol_64 (attr_ref);
+    return 1;
+}
+
+static int
+parse_osm_member (struct _xmlAttr *attr, const char **type, sqlite3_int64 * ref,
+		  const char **role)
+{
+/* parsing the OSM <member> attributes */
+    const char *attr_type = NULL;
+    const char *attr_ref = NULL;
+    const char *attr_role = NULL;
+    while (attr != NULL)
+      {
+	  if (attr->name != NULL)
+	    {
+		if (strcmp ((const char *) (attr->name), "type") == 0)
+		    attr_type = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "ref") == 0)
+		    attr_ref = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "role") == 0)
+		    attr_role = parse_attribute_value (attr->children);
+	    }
+	  attr = attr->next;
+      }
+    if (attr_type == NULL || attr_ref == NULL || attr_role == NULL)
+      {
+	  fprintf (stderr, "Invalid OSM <member>: type=%s ref=%s role=%s\n",
+		   attr_type, attr_ref, attr_role);
+	  return 0;
+      }
+    *type = attr_type;
+    *ref = atol_64 (attr_ref);
+    *role = attr_role;
+    return 1;
+}
+
+static int
+parse_osm_tag (struct _xmlAttr *attr, const char **k, const char **v)
+{
+/* parsing the OSM <tag> attributes */
+    const char *attr_k = NULL;
+    const char *attr_v = NULL;
+    while (attr != NULL)
+      {
+	  if (attr->name != NULL)
+	    {
+		if (strcmp ((const char *) (attr->name), "k") == 0)
+		    attr_k = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "v") == 0)
+		    attr_v = parse_attribute_value (attr->children);
+	    }
+	  attr = attr->next;
+      }
+    if (attr_k == NULL || attr_v == NULL)
+      {
+	  fprintf (stderr, "Invalid OSM <tag>: k=%s v=%s\n", attr_k, attr_v);
+	  return 0;
+      }
+    *k = attr_k;
+    *v = attr_v;
+    return 1;
+}
+
+static int
+parse_osm_node_attributes (struct _xmlAttr *attr, sqlite3_int64 * id, double *x,
+			   double *y, int *version, const char **timestamp,
+			   int *uid, int *changeset, const char **user)
+{
+/* parsing the OSM <node> attributes */
+    const char *attr_id = NULL;
+    const char *attr_lon = NULL;
+    const char *attr_lat = NULL;
+    const char *attr_version = NULL;
+    const char *attr_timestamp = NULL;
+    const char *attr_uid = NULL;
+    const char *attr_changeset = NULL;
+    const char *attr_user = NULL;
+    while (attr != NULL)
+      {
+	  if (attr->name != NULL)
+	    {
+		if (strcmp ((const char *) (attr->name), "id") == 0)
+		    attr_id = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "lon") == 0)
+		    attr_lon = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "lat") == 0)
+		    attr_lat = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "version") == 0)
+		    attr_version = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "timestamp") == 0)
+		    attr_timestamp = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "uid") == 0)
+		    attr_uid = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "changeset") == 0)
+		    attr_changeset = parse_attribute_value (attr->children);
+		if (strcmp ((const char *) (attr->name), "user") == 0)
+		    attr_user = parse_attribute_value (attr->children);
+	    }
+	  attr = attr->next;
+      }
+    if (attr_id == NULL || attr_lon == NULL || attr_lat == NULL)
+      {
+	  fprintf (stderr, "Invalid OSM <node>: id=%s lat=%s lon=%s\n", attr_id,
+		   attr_lon, attr_lat);
+	  return 0;
+      }
+    *id = atol_64 (attr_id);
+    *x = atof (attr_lon);
+    *y = atof (attr_lat);
+    if (attr_version == NULL)
+	*version = -1;
+    else
+	*version = atoi (attr_version);
+    *timestamp = attr_timestamp;
+    if (attr_uid == NULL)
+	*uid = -1;
+    else
+	*uid = atoi (attr_uid);
+    if (attr_changeset == NULL)
+	*changeset = -1;
+    else
+	*changeset = atoi (attr_changeset);
+    *user = attr_user;
+    return 1;
+}
+
+static int
+parse_osm_way_attributes (struct _xmlAttr *attr, sqlite3_int64 * id)
+{
+/* parsing the OSM <way> attributes */
+    const char *attr_id = NULL;
+    while (attr != NULL)
+      {
+	  if (attr->name != NULL)
+	    {
+		if (strcmp ((const char *) (attr->name), "id") == 0)
+		    attr_id = parse_attribute_value (attr->children);
+	    }
+	  attr = attr->next;
+      }
+    if (attr_id == NULL)
+      {
+	  fprintf (stderr, "Invalid OSM <way>: id=%s\n", attr_id);
+	  return 0;
+      }
+    *id = atol_64 (attr_id);
+    return 1;
+}
+
+static int
+parse_osm_relation_attributes (struct _xmlAttr *attr, sqlite3_int64 * id)
+{
+/* parsing the OSM <relation> attributes */
+    const char *attr_id = NULL;
+    while (attr != NULL)
+      {
+	  if (attr->name != NULL)
+	    {
+		if (strcmp ((const char *) (attr->name), "id") == 0)
+		    attr_id = parse_attribute_value (attr->children);
+	    }
+	  attr = attr->next;
+      }
+    if (attr_id == NULL)
+      {
+	  fprintf (stderr, "Invalid OSM <relation>: id=%s\n", attr_id);
+	  return 0;
+      }
+    *id = atol_64 (attr_id);
+    return 1;
+}
+
+static int
+parse_osm_node_tag (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <node><tag> item */
+    const char *k;
+    const char *v;
+    if (!parse_osm_tag (node->properties, &k, &v))
+	return 0;
+    if (!insert_node_tag (params, k, v))
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_way_tag (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <way><tag> item */
+    const char *k;
+    const char *v;
+    if (!parse_osm_tag (node->properties, &k, &v))
+	return 0;
+    if (!insert_way_tag (params, k, v))
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_relation_tag (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <relation><tag> item */
+    const char *k;
+    const char *v;
+    if (!parse_osm_tag (node->properties, &k, &v))
+	return 0;
+    if (!insert_relation_tag (params, k, v))
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_way_ref (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <way><nd> item */
+    sqlite3_int64 node_id;
+    if (!parse_osm_nd_ref (node->properties, &node_id))
+	return 0;
+    if (!insert_way_ref (params, node_id))
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_relation_member (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <relation><member> item */
+    const char *type;
+    sqlite3_int64 ref;
+    const char *role;
+    if (!parse_osm_member (node->properties, &type, &ref, &role))
+	return 0;
+    if (!insert_relation_ref (params, type, ref, role))
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_node (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <node> item */
+    xmlNodePtr child;
+    sqlite3_int64 id;
+    double x;
+    double y;
+    int version;
+    const char *timestamp;
+    int uid;
+    int changeset;
+    const char *user;
+    int error = 0;
+
+    if (!parse_osm_node_attributes
+	(node->properties, &id, &x, &y, &version, &timestamp, &uid, &changeset,
+	 &user))
+	return 0;
+    if (!insert_node
+	(params, id, x, y, version, timestamp, uid, changeset, user))
+	return 0;
+    for (child = node->children; child; child = child->next)
+      {
+	  if (child->type == XML_ELEMENT_NODE)
+	    {
+		const char *name = (const char *) (child->name);
+		if (name != NULL)
+		  {
+		      int ret = 1;
+		      if (strcmp (name, "tag") == 0)
+			  ret = parse_osm_node_tag (child, params);
+		      if (!ret)
+			  error = 1;
+		  }
+	    }
+      }
+    if (error)
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_way (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <way> item */
+    xmlNodePtr child;
+    sqlite3_int64 id;
+    int error = 0;
+
+    if (!parse_osm_way_attributes (node->properties, &id))
+	return 0;
+    if (!insert_way (params, id))
+	return 0;
+    for (child = node->children; child; child = child->next)
+      {
+	  if (child->type == XML_ELEMENT_NODE)
+	    {
+		const char *name = (const char *) (child->name);
+		if (name != NULL)
+		  {
+		      int ret = 1;
+		      if (strcmp (name, "nd") == 0)
+			  ret = parse_osm_way_ref (child, params);
+		      if (strcmp (name, "tag") == 0)
+			  ret = parse_osm_way_tag (child, params);
+		      if (!ret)
+			  error = 1;
+		  }
+	    }
+      }
+    if (error)
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_relation (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing an OSM <relation> item */
+    xmlNodePtr child;
+    sqlite3_int64 id;
+    int error = 0;
+
+    if (!parse_osm_relation_attributes (node->properties, &id))
+	return 0;
+    if (!insert_relation (params, id))
+	return 0;
+    for (child = node->children; child; child = child->next)
+      {
+	  if (child->type == XML_ELEMENT_NODE)
+	    {
+		const char *name = (const char *) (child->name);
+		if (name != NULL)
+		  {
+		      int ret = 1;
+		      if (strcmp (name, "member") == 0)
+			  ret = parse_osm_relation_member (child, params);
+		      if (strcmp (name, "tag") == 0)
+			  ret = parse_osm_relation_tag (child, params);
+		      if (!ret)
+			  error = 1;
+		  }
+	    }
+      }
+    if (error)
+	return 0;
+    return 1;
+}
+
+static int
+parse_osm_items (xmlNodePtr node, struct aux_params *params)
+{
+/* recursively parsing the OSM payload */
+    int error = 0;
+    xmlNodePtr cur_node = NULL;
+
+    for (cur_node = node; cur_node; cur_node = cur_node->next)
+      {
+	  if (cur_node->type == XML_ELEMENT_NODE)
+	    {
+		xmlNodePtr child;
+		for (child = cur_node->children; child; child = child->next)
+		  {
+		      if (child->type == XML_ELEMENT_NODE)
+			{
+			    const char *name = (const char *) (child->name);
+			    if (name != NULL)
+			      {
+				  int ret = 1;
+				  if (strcmp (name, "node") == 0)
+				      ret = parse_osm_node (child, params);
+				  if (strcmp (name, "way") == 0)
+				      ret = parse_osm_way (child, params);
+				  if (strcmp (name, "relation") == 0)
+				      ret = parse_osm_relation (child, params);
+				  if (!ret)
+				      error = 1;
+			      }
+			}
+		  }
+	    }
+      }
+    if (error)
+	return 0;
+    return 1;
+}
+
+static int
+osm_parse (struct aux_params *params, struct download_tile *tile, int object)
+{
+    xmlDocPtr xml_doc = NULL;
+    xmlNodePtr root;
+    char *url;
+    int error = 0;
+
+    if (params->mode == MODE_ROAD)
+      {
+	  /* downloading only the ROAD network */
+	  url =
+	      sqlite3_mprintf
+	      ("%s/interpreter?data=[timeout:600];(way[highway](%1.12f,%1.12f,%1.12f,%1.12f);>;);out body;",
+	       params->osm_url, tile->miny, tile->minx, tile->maxy, tile->maxx);
+      }
+    else if (params->mode == MODE_RAIL)
+      {
+	  /* downloading only the RAILWAY network */
+	  url =
+	      sqlite3_mprintf
+	      ("%s/interpreter?data=[timeout:600];(way[railway](%1.12f,%1.12f,%1.12f,%1.12f);>;);out body;",
+	       params->osm_url, tile->miny, tile->minx, tile->maxy, tile->maxx);
+      }
+    else if (params->mode == MODE_MAP)
+      {
+	  /* downloading a full MAP */
+	  if (object == OBJ_NODES)
+	      url =
+		  sqlite3_mprintf
+		  ("%s/interpreter?data=[timeout:600];(node(%1.12f,%1.12f,%1.12f,%1.12f););out body;",
+		   params->osm_url, tile->miny, tile->minx, tile->maxy,
+		   tile->maxx);
+	  else if (object == OBJ_WAYS)
+	      url =
+		  sqlite3_mprintf
+		  ("%s/interpreter?data=[timeout:600];(way(%1.12f,%1.12f,%1.12f,%1.12f););out body;",
+		   params->osm_url, tile->miny, tile->minx, tile->maxy,
+		   tile->maxx);
+	  else
+	      url =
+		  sqlite3_mprintf
+		  ("%s/interpreter?data=[timeout:600];(relation(%1.12f,%1.12f,%1.12f,%1.12f););out body;",
+		   params->osm_url, tile->miny, tile->minx, tile->maxy,
+		   tile->maxx);
+      }
+    else
+      {
+	  /* downloading a full MAP - raw mode */
+	  if (object == OBJ_NODES)
+	      url =
+		  sqlite3_mprintf
+		  ("%s/interpreter?data=[timeout:600];(node(%1.12f,%1.12f,%1.12f,%1.12f););out meta;",
+		   params->osm_url, tile->miny, tile->minx, tile->maxy,
+		   tile->maxx);
+	  else if (object == OBJ_WAYS)
+	      url =
+		  sqlite3_mprintf
+		  ("%s/interpreter?data=[timeout:600];(way(%1.12f,%1.12f,%1.12f,%1.12f););out meta;",
+		   params->osm_url, tile->miny, tile->minx, tile->maxy,
+		   tile->maxx);
+	  else
+	      url =
+		  sqlite3_mprintf
+		  ("%s/interpreter?data=[timeout:600];(relation(%1.12f,%1.12f,%1.12f,%1.12f););out meta;",
+		   params->osm_url, tile->miny, tile->minx, tile->maxy,
+		   tile->maxx);
+      }
+
+    xml_doc = xmlReadFile (url, NULL, 0);
+    if (xml_doc == NULL)
+      {
+	  /* parsing error; not a well-formed XML */
+	  fprintf (stderr, "ERROR: unable to download the OSM dataset\n");
+	  error = 1;
+	  goto end;
+      }
+
+/* parsing the OSM payload */
+    root = xmlDocGetRootElement (xml_doc);
+    if (!parse_osm_items (root, params))
+	error = 1;
+
+  end:
+    sqlite3_free (url);
+    if (xml_doc != NULL)
+	xmlFreeDoc (xml_doc);
+    if (error)
+	return 0;
+    return 1;
+}
+
+static void
+finalize_sql_stmts (struct aux_params *params)
+{
+    int ret;
+    char *sql_err = NULL;
+
+    if (params->ins_nodes_stmt != NULL)
+	sqlite3_finalize (params->ins_nodes_stmt);
+    if (params->ins_node_tags_stmt != NULL)
+	sqlite3_finalize (params->ins_node_tags_stmt);
+    if (params->ins_ways_stmt != NULL)
+	sqlite3_finalize (params->ins_ways_stmt);
+    if (params->ins_way_tags_stmt != NULL)
+	sqlite3_finalize (params->ins_way_tags_stmt);
+    if (params->ins_way_refs_stmt != NULL)
+	sqlite3_finalize (params->ins_way_refs_stmt);
+    if (params->ins_relations_stmt != NULL)
+	sqlite3_finalize (params->ins_relations_stmt);
+    if (params->ins_relation_tags_stmt != NULL)
+	sqlite3_finalize (params->ins_relation_tags_stmt);
+    if (params->ins_relation_refs_stmt != NULL)
+	sqlite3_finalize (params->ins_relation_refs_stmt);
+
+/* committing the still pending SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "COMMIT", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  return;
+      }
+}
+
+static void
+create_sql_stmts (struct aux_params *params, int journal_off)
+{
+    sqlite3_stmt *ins_nodes_stmt;
+    sqlite3_stmt *ins_node_tags_stmt;
+    sqlite3_stmt *ins_ways_stmt;
+    sqlite3_stmt *ins_way_tags_stmt;
+    sqlite3_stmt *ins_way_refs_stmt;
+    sqlite3_stmt *ins_relations_stmt;
+    sqlite3_stmt *ins_relation_tags_stmt;
+    sqlite3_stmt *ins_relation_refs_stmt;
+    char sql[1024];
+    int ret;
+    char *sql_err = NULL;
+
+    if (journal_off)
+      {
+	  /* disabling the journal: unsafe but faster */
+	  ret =
+	      sqlite3_exec (params->db_handle, "PRAGMA journal_mode = OFF",
+			    NULL, NULL, &sql_err);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "PRAGMA journal_mode=OFF error: %s\n",
+			 sql_err);
+		sqlite3_free (sql_err);
+		return;
+	    }
+      }
+
+/* the complete operation is handled as an unique SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "BEGIN", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  return;
+      }
+    if (params->mode == MODE_RAW)
+      {
+	  strcpy (sql,
+		  "INSERT INTO osm_nodes (node_id, version, timestamp, uid, user, changeset, Geometry) ");
+	  strcat (sql, "VALUES (?, ?, ?, ?, ?, ?, ?)");
+      }
+    else
+	strcpy (sql, "INSERT INTO osm_nodes (node_id, Geometry) VALUES (?, ?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql, "INSERT INTO osm_node_tags (node_id, sub, k, v) ");
+    strcat (sql, "VALUES (?, ?, ?, ?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_node_tags_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql, "INSERT INTO osm_ways (way_id) VALUES (?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_ways_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql, "INSERT INTO osm_way_tags (way_id, sub, k, v) ");
+    strcat (sql, "VALUES (?, ?, ?, ?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_way_tags_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql, "INSERT INTO osm_way_refs (way_id, sub, node_id) ");
+    strcat (sql, "VALUES (?, ?, ?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_way_refs_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql, "INSERT INTO osm_relations (rel_id) VALUES (?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_relations_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql, "INSERT INTO osm_relation_tags (rel_id, sub, k, v) ");
+    strcat (sql, "VALUES (?, ?, ?, ?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_relation_tags_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+    strcpy (sql,
+	    "INSERT INTO osm_relation_refs (rel_id, sub, type, ref, role) ");
+    strcat (sql, "VALUES (?, ?, ?, ?, ?)");
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_relation_refs_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  finalize_sql_stmts (params);
+	  return;
+      }
+
+    params->ins_nodes_stmt = ins_nodes_stmt;
+    params->ins_node_tags_stmt = ins_node_tags_stmt;
+    params->ins_ways_stmt = ins_ways_stmt;
+    params->ins_way_tags_stmt = ins_way_tags_stmt;
+    params->ins_way_refs_stmt = ins_way_refs_stmt;
+    params->ins_relations_stmt = ins_relations_stmt;
+    params->ins_relation_tags_stmt = ins_relation_tags_stmt;
+    params->ins_relation_refs_stmt = ins_relation_refs_stmt;
+}
+
+static void
+spatialite_autocreate (sqlite3 * db)
+{
+/* attempting to perform self-initialization for a newly created DB */
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+    int count;
+    int i;
+    char **results;
+    int rows;
+    int columns;
+
+/* checking if this DB is really empty */
+    strcpy (sql, "SELECT Count(*) from sqlite_master");
+    ret = sqlite3_get_table (db, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+	return;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	      count = atoi (results[(i * columns) + 0]);
+      }
+    sqlite3_free_table (results);
+
+    if (count > 0)
+	return;
+
+/* all right, it's empty: proceding to initialize */
+    strcpy (sql, "SELECT InitSpatialMetadata(1)");
+    ret = sqlite3_exec (db, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "InitSpatialMetadata() error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+}
+
+static int
+create_road_tables (struct aux_params *params)
+{
+/* creating the ROAD tables */
+    sqlite3 *db_handle = params->db_handle;
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+
+/* creating OSM helper nodes */
+    strcpy (sql, "CREATE TABLE osm_helper_nodes (\n");
+    strcat (sql, "node_id INTEGER NOT NULL PRIMARY KEY,\n");
+    strcat (sql, "way_count INTEGER NOT NULL)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_helper_nodes' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* populating OSM helper nodes */
+    strcpy (sql, "INSERT INTO osm_helper_nodes (node_id, way_count) ");
+    strcat (sql, "SELECT n.node_id, Count(*) FROM osm_nodes AS n ");
+    strcat (sql, "JOIN osm_way_refs AS w ON (w.node_id = n.node_id) ");
+    strcat (sql, "GROUP BY n.node_id");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "INSERT INTO 'osm_helper_nodes' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* creating ROAD nodes */
+    strcpy (sql, "CREATE TABLE road_nodes (\n");
+    strcat (sql, "node_id INTEGER NOT NULL PRIMARY KEY)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'road_nodes' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql,
+	    "SELECT AddGeometryColumn('road_nodes', 'Geometry', 4326, 'POINT', 'XY')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'road_nodes' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating ROAD arcs */
+    strcpy (sql, "CREATE TABLE road_arcs (\n");
+    strcat (sql, "arc_id INTEGER PRIMARY KEY AUTOINCREMENT,\n");
+    strcat (sql, "osm_id INTEGER NOT NULL,\n");
+    strcat (sql, "node_from INTEGER NOT NULL,\n");
+    strcat (sql, "node_to INTEGER NOT NULL,\n");
+    strcat (sql, "type TEXT,\n");
+    strcat (sql, "name TEXT,\n");
+    strcat (sql, "lanes INTEGER,\n");
+    strcat (sql, "maxspeed INTEGER,\n");
+    strcat (sql, "oneway_ft INTEGER,\n");
+    strcat (sql, "oneway_tf INTEGER,\n");
+    strcat (sql, "CONSTRAINT fk_arc_from FOREIGN KEY (node_from)\n");
+    strcat (sql, "REFERENCES road_nodes (node_id),\n");
+    strcat (sql, "CONSTRAINT fk_arc_to FOREIGN KEY (node_to)\n");
+    strcat (sql, "REFERENCES road_nodes (node_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'road_arcs' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql,
+	    "SELECT AddGeometryColumn('road_arcs', 'Geometry', 4326, 'LINESTRING', 'XY')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'road_arcs' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating an index supporting road_arcs.node_from */
+    strcpy (sql, "CREATE INDEX idx_roads_from ON road_arcs (node_from)");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'idx_roads_from' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating an index supporting road_arcs.node_to */
+    strcpy (sql, "CREATE INDEX idx_roads_to ON road_arcs (node_to)");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'idx_roads_to' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    return 1;
+}
+
+static int
+create_road_rtrees (struct aux_params *params)
+{
+/* creating the ROAD rtrees */
+    sqlite3 *db_handle = params->db_handle;
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+
+    strcpy (sql, "SELECT CreateSpatialIndex('road_nodes', 'Geometry')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE SPATIAL INDEX 'road_nodes' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql, "SELECT CreateSpatialIndex('road_arcs', 'Geometry')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE SPATIAL INDEX 'road_arcs' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    return 1;
+}
+
+static void
+add_arc (struct aux_arc_container *arcs, sqlite3_int64 nd_first,
+	 sqlite3_int64 nd_last, double x_ini, double y_ini, double x_end,
+	 double y_end, gaiaDynamicLinePtr dyn_line, int count)
+{
+/* adding a further Arc to the container */
+    int iv;
+    gaiaGeomCollPtr g;
+    gaiaPointPtr pt;
+    gaiaLinestringPtr ln;
+    struct aux_arc *arc = malloc (sizeof (struct aux_arc));
+    arc->node_from = nd_first;
+    arc->node_to = nd_last;
+    g = gaiaAllocGeomColl ();
+    gaiaAddPointToGeomColl (g, x_ini, y_ini);
+    g->Srid = 4326;
+    arc->geom_from = g;
+    g = gaiaAllocGeomColl ();
+    gaiaAddPointToGeomColl (g, x_end, y_end);
+    g->Srid = 4326;
+    arc->geom_to = g;
+    g = gaiaAllocGeomColl ();
+    ln = gaiaAddLinestringToGeomColl (g, count);
+    iv = 0;
+    pt = dyn_line->First;
+    while (pt)
+      {
+	  /* inserting any POINT into LINESTRING */
+	  gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y);
+	  iv++;
+	  pt = pt->Next;
+      }
+    g->Srid = 4326;
+    arc->geom = g;
+    arc->next = NULL;
+    if (arcs->first == NULL)
+	arcs->first = arc;
+    if (arcs->last != NULL)
+	arcs->last->next = arc;
+    arcs->last = arc;
+}
+
+static int
+build_arc (sqlite3 * sqlite, sqlite3_stmt * query_nodes_stmt, sqlite3_int64 id,
+	   struct aux_arc_container *arcs)
+{
+/* building an Arc */
+    int ret;
+    sqlite3_int64 nd_first;
+    sqlite3_int64 nd_last;
+    int count = 0;
+    double x_ini;
+    double y_ini;
+    double x_end;
+    double y_end;
+    gaiaDynamicLinePtr dyn_line = gaiaAllocDynamicLine ();
+
+    sqlite3_reset (query_nodes_stmt);
+    sqlite3_clear_bindings (query_nodes_stmt);
+    sqlite3_bind_int64 (query_nodes_stmt, 1, id);
+    while (1)
+      {
+	  /* scrolling the main result set */
+	  ret = sqlite3_step (query_nodes_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		sqlite3_int64 node_id =
+		    sqlite3_column_int64 (query_nodes_stmt, 0);
+		double x = sqlite3_column_double (query_nodes_stmt, 1);
+		double y = sqlite3_column_double (query_nodes_stmt, 2);
+		int way_count = sqlite3_column_int (query_nodes_stmt, 3);
+		if (count == 0)
+		  {
+		      nd_first = node_id;
+		      x_ini = x;
+		      y_ini = y;
+		      count++;
+		      gaiaAppendPointToDynamicLine (dyn_line, x, y);
+		  }
+		else
+		  {
+		      nd_last = node_id;
+		      x_end = x;
+		      y_end = y;
+		      count++;
+		      gaiaAppendPointToDynamicLine (dyn_line, x, y);
+		      if (way_count > 1)
+			{
+			    /* break: splitting the current arc on some junction */
+			    add_arc (arcs, nd_first, nd_last, x_ini, y_ini,
+				     x_end, y_end, dyn_line, count);
+			    /* beginning a new arc */
+			    gaiaFreeDynamicLine (dyn_line);
+			    dyn_line = gaiaAllocDynamicLine ();
+			    count = 1;
+			    nd_first = node_id;
+			    x_ini = x;
+			    y_ini = y;
+			    gaiaAppendPointToDynamicLine (dyn_line, x, y);
+			}
+		  }
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (sqlite));
+		return 0;
+	    }
+      }
+    if (count > 1)
+	add_arc (arcs, nd_first, nd_last, x_ini, y_ini, x_end, y_end, dyn_line,
+		 count);
+    gaiaFreeDynamicLine (dyn_line);
+    return 1;
+}
+
+static int
+populate_road_network (struct aux_params *params, int *cnt_nodes, int *cnt_arcs)
+{
+/* populating the ROAD tables */
+    int ret;
+    sqlite3_stmt *query_main_stmt = NULL;
+    sqlite3_stmt *query_nodes_stmt = NULL;
+    sqlite3_stmt *ins_nodes_stmt = NULL;
+    sqlite3_stmt *ins_arcs_stmt = NULL;
+    const char *sql;
+    char *sql_err = NULL;
+
+/* main SQL query extracting all Arcs */
+    sql = "SELECT w1.way_id AS osm_id, w1.v AS class, w2.v AS name, "
+	"w3.v AS lanes, w4.v AS maxspeed, w5.v AS onewway, w6.v AS roundabout "
+	"FROM osm_way_tags AS w1 "
+	"LEFT JOIN osm_way_tags AS w2 ON (w2.way_id = w1.way_id AND w2.k = 'name') "
+	"LEFT JOIN osm_way_tags AS w3 ON (w3.way_id = w1.way_id AND w3.k = 'lanes') "
+	"LEFT JOIN osm_way_tags AS w4 ON (w4.way_id = w1.way_id AND w4.k = 'maxspeed') "
+	"LEFT JOIN osm_way_tags AS w5 ON (w5.way_id = w1.way_id AND w5.k = 'oneway') "
+	"LEFT JOIN osm_way_tags AS w6 ON (w6.way_id = w1.way_id AND w6.k = 'junction') "
+	"WHERE w1.k = 'highway'";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_main_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* aux SQL query extracting Node refs */
+    sql = "SELECT w.node_id, ST_X(n.geometry), ST_Y(n.geometry), h.way_count "
+	"FROM osm_way_refs AS w "
+	"JOIN osm_nodes AS n ON (n.node_id = w.node_id) "
+	"JOIN osm_helper_nodes AS h ON (n.node_id = h.node_id) "
+	"WHERE w.way_id = ? ORDER BY w.sub";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* INSERT INTO nodes statement */
+    sql = "INSERT INTO road_nodes (node_id, geometry) VALUES (?, ?)";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* INSERT INTO arcs statement */
+    sql =
+	"INSERT INTO road_arcs (arc_id, osm_id, node_from, node_to, type, name, lanes, "
+	"maxspeed, oneway_ft, oneway_tf, geometry) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_arcs_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* the complete operation is handled as an unique SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "BEGIN", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  goto error;
+      }
+
+    while (1)
+      {
+	  /* scrolling the main result set */
+	  ret = sqlite3_step (query_main_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		struct aux_arc_container arcs;
+		struct aux_arc *arc;
+		struct aux_arc *arc_n;
+		unsigned char *blob;
+		int blob_size;
+		sqlite3_int64 id = sqlite3_column_int64 (query_main_stmt, 0);
+		arcs.first = NULL;
+		arcs.last = NULL;
+		if (!build_arc (params->db_handle, query_nodes_stmt, id, &arcs))
+		  {
+#if defined(_WIN32) || defined(__MINGW32__)
+		      /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+		      fprintf (stderr,
+			       "ERROR: unable to resolve ROAD id=%I64d\n", id);
+#else
+		      fprintf (stderr,
+			       "ERROR: unable to resolve ROAD id=%lld\n", id);
+#endif
+		      goto error;
+		  }
+		arc = arcs.first;
+		while (arc != NULL)
+		  {
+		      int oneway_ft = 1;
+		      int oneway_tf = 1;
+		      const char *p_oneway = "";
+		      const char *p_roundabout = "";
+		      const char *p_motorway = "";
+		      /* looping on split arcs */
+		      arc_n = arc->next;
+		      /* inserting NODE From */
+		      sqlite3_reset (ins_nodes_stmt);
+		      sqlite3_clear_bindings (ins_nodes_stmt);
+		      sqlite3_bind_int64 (ins_nodes_stmt, 1, arc->node_from);
+		      gaiaToSpatiaLiteBlobWkb (arc->geom_from, &blob,
+					       &blob_size);
+		      gaiaFreeGeomColl (arc->geom_from);
+		      sqlite3_bind_blob (ins_nodes_stmt, 2, blob, blob_size,
+					 free);
+		      ret = sqlite3_step (ins_nodes_stmt);
+		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+			  *cnt_nodes += 1;
+		      /* inserting NODE To */
+		      sqlite3_reset (ins_nodes_stmt);
+		      sqlite3_clear_bindings (ins_nodes_stmt);
+		      sqlite3_bind_int64 (ins_nodes_stmt, 1, arc->node_to);
+		      gaiaToSpatiaLiteBlobWkb (arc->geom_to, &blob, &blob_size);
+		      gaiaFreeGeomColl (arc->geom_to);
+		      sqlite3_bind_blob (ins_nodes_stmt, 2, blob, blob_size,
+					 free);
+		      ret = sqlite3_step (ins_nodes_stmt);
+		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+			  *cnt_nodes += 1;
+		      /* inserting the Arc itself */
+		      sqlite3_reset (ins_arcs_stmt);
+		      sqlite3_clear_bindings (ins_arcs_stmt);
+		      sqlite3_bind_int64 (ins_arcs_stmt, 1, id);
+		      sqlite3_bind_int64 (ins_arcs_stmt, 2, arc->node_from);
+		      sqlite3_bind_int64 (ins_arcs_stmt, 3, arc->node_to);
+		      if (sqlite3_column_type (query_main_stmt, 1) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 4);
+		      else
+			  sqlite3_bind_text (ins_arcs_stmt, 4,
+					     (const char *)
+					     sqlite3_column_text
+					     (query_main_stmt, 1),
+					     sqlite3_column_bytes
+					     (query_main_stmt, 1),
+					     SQLITE_STATIC);
+		      if (sqlite3_column_type (query_main_stmt, 2) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 5);
+		      else
+			  sqlite3_bind_text (ins_arcs_stmt, 5,
+					     (const char *)
+					     sqlite3_column_text
+					     (query_main_stmt, 2),
+					     sqlite3_column_bytes
+					     (query_main_stmt, 2),
+					     SQLITE_STATIC);
+		      if (sqlite3_column_type (query_main_stmt, 3) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 6);
+		      else
+			  sqlite3_bind_int (ins_arcs_stmt, 6,
+					    sqlite3_column_int (query_main_stmt,
+								3));
+		      if (sqlite3_column_type (query_main_stmt, 4) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 7);
+		      else
+			  sqlite3_bind_int (ins_arcs_stmt, 7,
+					    sqlite3_column_int (query_main_stmt,
+								4));
+		      if (sqlite3_column_type (query_main_stmt, 5) !=
+			  SQLITE_NULL)
+			  p_oneway =
+			      (const char *)
+			      sqlite3_column_text (query_main_stmt, 5);
+		      if (sqlite3_column_type (query_main_stmt, 6) !=
+			  SQLITE_NULL)
+			  p_roundabout =
+			      (const char *)
+			      sqlite3_column_text (query_main_stmt, 6);
+		      if (sqlite3_column_type (query_main_stmt, 1) !=
+			  SQLITE_NULL)
+			  p_motorway =
+			      (const char *)
+			      sqlite3_column_text (query_main_stmt, 1);
+		      if (strcmp (p_roundabout, "roundabout") == 0)
+			{
+			    /* all roundabouts are always implicitly oneway */
+			    oneway_ft = 1;
+			    oneway_tf = 0;
+			}
+		      if (strcmp (p_motorway, "motorway") == 0)
+			{
+			    /* all motorways are always implicitly oneway */
+			    oneway_ft = 1;
+			    oneway_tf = 0;
+			}
+		      if (strcmp (p_oneway, "1") == 0
+			  || strcmp (p_oneway, "yes") == 0)
+			{
+			    /* declared to be oneway From -> To */
+			    oneway_ft = 1;
+			    oneway_tf = 0;
+			}
+		      if (strcmp (p_oneway, "-1") == 0
+			  || strcmp (p_oneway, "reverse") == 0)
+			{
+			    /* declared to be oneway To -> From */
+			    oneway_ft = 0;
+			    oneway_tf = 1;
+			}
+		      sqlite3_bind_int (ins_arcs_stmt, 8, oneway_ft);
+		      sqlite3_bind_int (ins_arcs_stmt, 9, oneway_tf);
+		      gaiaToSpatiaLiteBlobWkb (arc->geom, &blob, &blob_size);
+		      gaiaFreeGeomColl (arc->geom);
+		      sqlite3_bind_blob (ins_arcs_stmt, 10, blob, blob_size,
+					 free);
+		      ret = sqlite3_step (ins_arcs_stmt);
+		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+			  *cnt_arcs += 1;
+		      else
+			{
+#if defined(_WIN32) || defined(__MINGW32__)
+			    /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+			    fprintf (stderr,
+				     "ERROR: unable to insert ROAD id=%I64d: %s\n",
+				     id, sqlite3_errmsg (params->db_handle));
+#else
+			    fprintf (stderr,
+				     "ERROR: unable to insert ROAD id=%lld: %s\n",
+				     id, sqlite3_errmsg (params->db_handle));
+#endif
+			}
+		      free (arc);
+		      arc = arc_n;
+		  }
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (params->db_handle));
+		/* ROLLBACK */
+		ret =
+		    sqlite3_exec (params->db_handle, "ROLLBACK", NULL, NULL,
+				  &sql_err);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n",
+			       sql_err);
+		      sqlite3_free (sql_err);
+		      goto error;
+		  }
+		goto error;
+	    }
+      }
+
+/* committing the still pending SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "COMMIT", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  goto error;
+      }
+
+    sqlite3_finalize (query_main_stmt);
+    sqlite3_finalize (query_nodes_stmt);
+    sqlite3_finalize (ins_nodes_stmt);
+    sqlite3_finalize (ins_arcs_stmt);
+
+    return 1;
+
+  error:
+    if (query_main_stmt != NULL)
+	sqlite3_finalize (query_main_stmt);
+    if (query_nodes_stmt != NULL)
+	sqlite3_finalize (query_nodes_stmt);
+    if (ins_nodes_stmt != NULL)
+	sqlite3_finalize (ins_nodes_stmt);
+    if (ins_arcs_stmt != NULL)
+	sqlite3_finalize (ins_arcs_stmt);
+    return 0;
+}
+
+static int
+create_rail_tables (struct aux_params *params)
+{
+/* creating the RAIL tables */
+    sqlite3 *db_handle = params->db_handle;
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+
+/* creating OSM helper nodes */
+    strcpy (sql, "CREATE TABLE osm_helper_nodes (\n");
+    strcat (sql, "node_id INTEGER NOT NULL PRIMARY KEY,\n");
+    strcat (sql, "way_count INTEGER NOT NULL)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_helper_nodes' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* populating OSM helper nodes */
+    strcpy (sql, "INSERT INTO osm_helper_nodes (node_id, way_count) ");
+    strcat (sql, "SELECT n.node_id, Count(*) FROM osm_nodes AS n ");
+    strcat (sql, "JOIN osm_way_refs AS w ON (w.node_id = n.node_id) ");
+    strcat (sql, "GROUP BY n.node_id");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "INSERT INTO 'osm_helper_nodes' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* creating RAIL nodes */
+    strcpy (sql, "CREATE TABLE rail_nodes (\n");
+    strcat (sql, "node_id INTEGER NOT NULL PRIMARY KEY)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'rail_nodes' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql,
+	    "SELECT AddGeometryColumn('rail_nodes', 'Geometry', 4326, 'POINT', 'XY')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'rail_nodes' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating RAIL arcs */
+    strcpy (sql, "CREATE TABLE rail_arcs (\n");
+    strcat (sql, "arc_id INTEGER PRIMARY KEY AUTOINCREMENT,\n");
+    strcat (sql, "osm_id INTEGER NOT NULL,\n");
+    strcat (sql, "node_from INTEGER NOT NULL,\n");
+    strcat (sql, "node_to INTEGER NOT NULL,\n");
+    strcat (sql, "type TEXT,\n");
+    strcat (sql, "name TEXT,\n");
+    strcat (sql, "gauge INTEGER,\n");
+    strcat (sql, "tracks INTEGER,\n");
+    strcat (sql, "electrified INTEGER,\n");
+    strcat (sql, "voltage INTEGER,\n");
+    strcat (sql, "operator TEXT,\n");
+    strcat (sql, "CONSTRAINT fk_arc_from FOREIGN KEY (node_from)\n");
+    strcat (sql, "REFERENCES rail_nodes (node_id),\n");
+    strcat (sql, "CONSTRAINT fk_arc_to FOREIGN KEY (node_to)\n");
+    strcat (sql, "REFERENCES rail_nodes (node_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'rail_arcs' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql,
+	    "SELECT AddGeometryColumn('rail_arcs', 'Geometry', 4326, 'LINESTRING', 'XY')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'rail_arcs' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating an index supporting rail_arcs.node_from */
+    strcpy (sql, "CREATE INDEX idx_rails_from ON rail_arcs (node_from)");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'idx_rails_from' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating an index supporting rail_arcs.node_to */
+    strcpy (sql, "CREATE INDEX idx_rails_to ON rail_arcs (node_to)");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'idx_rails_to' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* creating RAIL stations */
+    strcpy (sql, "CREATE TABLE rail_stations (\n");
+    strcat (sql, "station_id INTEGER NOT NULL PRIMARY KEY,\n");
+    strcat (sql, "name TEXT\n,");
+    strcat (sql, "operator TEXT)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'rail_stations' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql,
+	    "SELECT AddGeometryColumn('rail_stations', 'Geometry', 4326, 'POINT', 'XY')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'rail_stations' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    return 1;
+}
+
+static int
+create_rail_rtrees (struct aux_params *params)
+{
+/* creating the RAIL rtrees */
+    sqlite3 *db_handle = params->db_handle;
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+
+    strcpy (sql, "SELECT CreateSpatialIndex('rail_nodes', 'Geometry')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE SPATIAL INDEX 'rail_nodes' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql, "SELECT CreateSpatialIndex('rail_arcs', 'Geometry')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE SPATIAL INDEX 'rail_arcs' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql, "SELECT CreateSpatialIndex('rail_stations', 'Geometry')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE SPATIAL INDEX 'rail_stations' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    return 1;
+}
+
+static int
+populate_rail_network (struct aux_params *params, int *cnt_nodes, int *cnt_arcs,
+		       int *cnt_stations)
+{
+/* populating the RAIL tables */
+    int ret;
+    sqlite3_stmt *query_main_stmt = NULL;
+    sqlite3_stmt *query_nodes_stmt = NULL;
+    sqlite3_stmt *query_stations_stmt = NULL;
+    sqlite3_stmt *ins_nodes_stmt = NULL;
+    sqlite3_stmt *ins_arcs_stmt = NULL;
+    sqlite3_stmt *ins_stations_stmt = NULL;
+    const char *sql;
+    char *sql_err = NULL;
+
+/* main SQL query extracting all Arcs */
+    sql =
+	"SELECT w1.way_id AS osm_id, w1.v AS class, w2.v AS name, w3.v AS gauge, "
+	"w4.v AS tracks, w5.v AS electrified, w6.v AS voltage, w7.v AS operator "
+	"FROM osm_way_tags AS w1 "
+	"LEFT JOIN osm_way_tags AS w2 ON (w2.way_id = w1.way_id AND w2.k = 'name') "
+	"LEFT JOIN osm_way_tags AS w3 ON (w3.way_id = w1.way_id AND w3.k = 'gauge') "
+	"LEFT JOIN osm_way_tags AS w4 ON (w4.way_id = w1.way_id AND w4.k = 'tracks') "
+	"LEFT JOIN osm_way_tags AS w5 ON (w5.way_id = w1.way_id AND w5.k = 'electrified') "
+	"LEFT JOIN osm_way_tags AS w6 ON (w6.way_id = w1.way_id AND w6.k = 'voltage') "
+	"LEFT JOIN osm_way_tags AS w7 ON (w7.way_id = w1.way_id AND w7.k = 'operator') "
+	"WHERE w1.k = 'railway'";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_main_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* aux SQL query extracting Node refs */
+    sql = "SELECT w.node_id, ST_X(n.geometry), ST_Y(n.geometry), h.way_count "
+	"FROM osm_way_refs AS w "
+	"JOIN osm_nodes AS n ON (n.node_id = w.node_id) "
+	"JOIN osm_helper_nodes AS h ON (n.node_id = h.node_id) "
+	"WHERE w.way_id = ? ORDER BY w.sub";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* main SQL query extracting all Stations */
+    sql =
+	"SELECT n1.node_id AS osm_id, n2.v AS name, n3.v AS operator, g.geometry "
+	"FROM osm_node_tags AS n1 "
+	"JOIN osm_nodes AS g ON (g.node_id = n1.node_id) "
+	"LEFT JOIN osm_node_tags AS n2 ON (n2.node_id = n1.node_id AND n2.k = 'name') "
+	"LEFT JOIN osm_node_tags AS n3 ON (n3.node_id = n1.node_id AND n3.k = 'operator') "
+	"WHERE n1.k = 'railway' AND n1.v = 'station'";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_stations_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* INSERT INTO nodes statement */
+    sql = "INSERT INTO rail_nodes (node_id, geometry) VALUES (?, ?)";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* INSERT INTO arcs statement */
+    sql =
+	"INSERT INTO rail_arcs (arc_id, osm_id, node_from, node_to, type, name, "
+	"gauge, tracks, electrified, voltage, operator, geometry) VALUES "
+	"(NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_arcs_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* INSERT INTO stations statement */
+    sql =
+	"INSERT INTO rail_stations (station_id, name, operator, geometry) VALUES (?, ?, ?, ?)";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &ins_stations_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* the complete operation is handled as an unique SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "BEGIN", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  goto error;
+      }
+
+    while (1)
+      {
+	  /* scrolling the main result set */
+	  ret = sqlite3_step (query_main_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		struct aux_arc_container arcs;
+		struct aux_arc *arc;
+		struct aux_arc *arc_n;
+		unsigned char *blob;
+		int blob_size;
+		sqlite3_int64 id = sqlite3_column_int64 (query_main_stmt, 0);
+		arcs.first = NULL;
+		arcs.last = NULL;
+		if (!build_arc (params->db_handle, query_nodes_stmt, id, &arcs))
+		  {
+#if defined(_WIN32) || defined(__MINGW32__)
+		      /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+		      fprintf (stderr,
+			       "ERROR: unable to resolve RAIL id=%I64d\n", id);
+#else
+		      fprintf (stderr,
+			       "ERROR: unable to resolve RAIL id=%lld\n", id);
+#endif
+		      goto error;
+		  }
+		arc = arcs.first;
+		while (arc != NULL)
+		  {
+		      /* looping on split arcs */
+		      arc_n = arc->next;
+		      /* inserting NODE From */
+		      sqlite3_reset (ins_nodes_stmt);
+		      sqlite3_clear_bindings (ins_nodes_stmt);
+		      sqlite3_bind_int64 (ins_nodes_stmt, 1, arc->node_from);
+		      gaiaToSpatiaLiteBlobWkb (arc->geom_from, &blob,
+					       &blob_size);
+		      gaiaFreeGeomColl (arc->geom_from);
+		      sqlite3_bind_blob (ins_nodes_stmt, 2, blob, blob_size,
+					 free);
+		      ret = sqlite3_step (ins_nodes_stmt);
+		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+			  *cnt_nodes += 1;
+		      /* inserting NODE To */
+		      sqlite3_reset (ins_nodes_stmt);
+		      sqlite3_clear_bindings (ins_nodes_stmt);
+		      sqlite3_bind_int64 (ins_nodes_stmt, 1, arc->node_to);
+		      gaiaToSpatiaLiteBlobWkb (arc->geom_to, &blob, &blob_size);
+		      gaiaFreeGeomColl (arc->geom_to);
+		      sqlite3_bind_blob (ins_nodes_stmt, 2, blob, blob_size,
+					 free);
+		      ret = sqlite3_step (ins_nodes_stmt);
+		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+			  *cnt_nodes += 1;
+		      /* inserting the Arc itself */
+		      sqlite3_reset (ins_arcs_stmt);
+		      sqlite3_clear_bindings (ins_arcs_stmt);
+		      sqlite3_bind_int64 (ins_arcs_stmt, 1, id);
+		      sqlite3_bind_int64 (ins_arcs_stmt, 2, arc->node_from);
+		      sqlite3_bind_int64 (ins_arcs_stmt, 3, arc->node_to);
+		      if (sqlite3_column_type (query_main_stmt, 1) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 4);
+		      else
+			  sqlite3_bind_text (ins_arcs_stmt, 4,
+					     (const char *)
+					     sqlite3_column_text
+					     (query_main_stmt, 1),
+					     sqlite3_column_bytes
+					     (query_main_stmt, 1),
+					     SQLITE_STATIC);
+		      if (sqlite3_column_type (query_main_stmt, 2) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 5);
+		      else
+			  sqlite3_bind_text (ins_arcs_stmt, 5,
+					     (const char *)
+					     sqlite3_column_text
+					     (query_main_stmt, 2),
+					     sqlite3_column_bytes
+					     (query_main_stmt, 2),
+					     SQLITE_STATIC);
+		      if (sqlite3_column_type (query_main_stmt, 3) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 6);
+		      else
+			  sqlite3_bind_int (ins_arcs_stmt, 6,
+					    sqlite3_column_int (query_main_stmt,
+								3));
+		      if (sqlite3_column_type (query_main_stmt, 4) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 7);
+		      else
+			  sqlite3_bind_int (ins_arcs_stmt, 7,
+					    sqlite3_column_int (query_main_stmt,
+								4));
+		      if (sqlite3_column_type (query_main_stmt, 5) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 8);
+		      else
+			  sqlite3_bind_text (ins_arcs_stmt, 8,
+					     (const char *)
+					     sqlite3_column_text
+					     (query_main_stmt, 5),
+					     sqlite3_column_bytes
+					     (query_main_stmt, 5),
+					     SQLITE_STATIC);
+		      if (sqlite3_column_type (query_main_stmt, 6) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 9);
+		      else
+			  sqlite3_bind_int (ins_arcs_stmt, 9,
+					    sqlite3_column_int (query_main_stmt,
+								6));
+		      if (sqlite3_column_type (query_main_stmt, 6) ==
+			  SQLITE_NULL)
+			  sqlite3_bind_null (ins_arcs_stmt, 10);
+		      else
+			  sqlite3_bind_text (ins_arcs_stmt, 10,
+					     (const char *)
+					     sqlite3_column_text
+					     (query_main_stmt, 7),
+					     sqlite3_column_bytes
+					     (query_main_stmt, 7),
+					     SQLITE_STATIC);
+		      gaiaToSpatiaLiteBlobWkb (arc->geom, &blob, &blob_size);
+		      gaiaFreeGeomColl (arc->geom);
+		      sqlite3_bind_blob (ins_arcs_stmt, 11, blob, blob_size,
+					 free);
+		      ret = sqlite3_step (ins_arcs_stmt);
+		      if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+			  *cnt_arcs += 1;
+		      else
+			{
+#if defined(_WIN32) || defined(__MINGW32__)
+			    /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+			    fprintf (stderr,
+				     "ERROR: unable to insert RAIL id=%I64d: %s\n",
+				     id, sqlite3_errmsg (params->db_handle));
+#else
+			    fprintf (stderr,
+				     "ERROR: unable to insert RAIL id=%lld: %s\n",
+				     id, sqlite3_errmsg (params->db_handle));
+#endif
+			}
+		      free (arc);
+		      arc = arc_n;
+		  }
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (params->db_handle));
+		/* ROLLBACK */
+		ret =
+		    sqlite3_exec (params->db_handle, "ROLLBACK", NULL, NULL,
+				  &sql_err);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n",
+			       sql_err);
+		      sqlite3_free (sql_err);
+		      goto error;
+		  }
+		goto error;
+	    }
+      }
+
+    while (1)
+      {
+	  /* scrolling the stations result set */
+	  ret = sqlite3_step (query_stations_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		sqlite3_int64 id =
+		    sqlite3_column_int64 (query_stations_stmt, 0);
+		sqlite3_reset (ins_stations_stmt);
+		sqlite3_clear_bindings (ins_stations_stmt);
+		sqlite3_bind_int64 (ins_stations_stmt, 1, id);
+		if (sqlite3_column_type (query_stations_stmt, 1) == SQLITE_NULL)
+		    sqlite3_bind_null (ins_stations_stmt, 2);
+		else
+		    sqlite3_bind_text (ins_stations_stmt, 2,
+				       (const char *)
+				       sqlite3_column_text (query_stations_stmt,
+							    1),
+				       sqlite3_column_bytes
+				       (query_stations_stmt, 1), SQLITE_STATIC);
+		if (sqlite3_column_type (query_stations_stmt, 2) == SQLITE_NULL)
+		    sqlite3_bind_null (ins_stations_stmt, 3);
+		else
+		    sqlite3_bind_text (ins_stations_stmt, 3,
+				       (const char *)
+				       sqlite3_column_text (query_stations_stmt,
+							    2),
+				       sqlite3_column_bytes
+				       (query_stations_stmt, 2), SQLITE_STATIC);
+		if (sqlite3_column_type (query_stations_stmt, 3) == SQLITE_NULL)
+		    sqlite3_bind_null (ins_stations_stmt, 4);
+		else
+		    sqlite3_bind_blob (ins_stations_stmt, 4,
+				       sqlite3_column_blob (query_stations_stmt,
+							    3),
+				       sqlite3_column_bytes
+				       (query_stations_stmt, 3), SQLITE_STATIC);
+		ret = sqlite3_step (ins_stations_stmt);
+		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+		    *cnt_stations += 1;
+		else
+		  {
+#if defined(_WIN32) || defined(__MINGW32__)
+		      /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+		      fprintf (stderr,
+			       "ERROR: unable to insert RAIL station id=%I64d: %s\n",
+			       id, sqlite3_errmsg (params->db_handle));
+#else
+		      fprintf (stderr,
+			       "ERROR: unable to insert RAIL station id=%lld: %s\n",
+			       id, sqlite3_errmsg (params->db_handle));
+#endif
+		  }
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (params->db_handle));
+		/* ROLLBACK */
+		ret =
+		    sqlite3_exec (params->db_handle, "ROLLBACK", NULL, NULL,
+				  &sql_err);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n",
+			       sql_err);
+		      sqlite3_free (sql_err);
+		      goto error;
+		  }
+		goto error;
+	    }
+      }
+
+/* committing the still pending SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "COMMIT", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  goto error;
+      }
+
+    sqlite3_finalize (query_main_stmt);
+    sqlite3_finalize (query_nodes_stmt);
+    sqlite3_finalize (ins_nodes_stmt);
+    sqlite3_finalize (ins_arcs_stmt);
+
+    return 1;
+
+  error:
+    if (query_main_stmt != NULL)
+	sqlite3_finalize (query_main_stmt);
+    if (query_nodes_stmt != NULL)
+	sqlite3_finalize (query_nodes_stmt);
+    if (query_stations_stmt != NULL)
+	sqlite3_finalize (query_stations_stmt);
+    if (ins_nodes_stmt != NULL)
+	sqlite3_finalize (ins_nodes_stmt);
+    if (ins_arcs_stmt != NULL)
+	sqlite3_finalize (ins_arcs_stmt);
+    if (ins_stations_stmt != NULL)
+	sqlite3_finalize (ins_stations_stmt);
+    return 0;
+}
+
+static int
+create_map_indices (struct aux_params *params)
+{
+/* creating the MAP helper indices */
+    sqlite3 *db_handle = params->db_handle;
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+
+/* creating OSM helper idx_node_tags */
+    strcpy (sql, "CREATE INDEX idx_node_tags ON osm_node_tags (k)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'osm_node_tags' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* creating OSM helper idx_way_tags */
+    strcpy (sql, "CREATE INDEX idx_way_tags ON osm_node_tags (k)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'osm_way_tags' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+
+/* creating OSM helper idx_relation_tags */
+    strcpy (sql, "CREATE INDEX idx_relation_tags ON osm_node_tags (k)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'osm_relation_tags' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    return 1;
+}
+
+static void
+do_create_point_table (struct aux_params *params, struct layers *layer)
+{
+/* creating a Point table */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    sqlite3_stmt *stmt;
+
+    sql = sqlite3_mprintf ("CREATE TABLE pt_%s (\n"
+			   "osm_id INTEGER NOT NULL PRIMARY KEY,\n"
+			   "type TEXT,\nname TEXT)\n", layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'pt_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+    sql =
+	sqlite3_mprintf
+	("SELECT AddGeometryColumn('pt_%s', 'Geometry', 4326, 'POINT', 'XY')",
+	 layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'pt_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+
+/* creating the insert SQL statement */
+    sql = sqlite3_mprintf ("INSERT INTO pt_%s (osm_id, type, name, Geometry) "
+			   "VALUES (?, ?, ?, ?)", layer->name);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  return;
+      }
+    layer->ok_point = 1;
+    layer->ins_point_stmt = stmt;
+}
+
+static int
+do_insert_point (struct aux_params *params, sqlite3_int64 id,
+		 const char *layer_name, const char *type, const char *name,
+		 const unsigned char *blob, int blob_size)
+{
+/* inserting a Point Geometry */
+    struct layers *p_layer;
+    struct layers *layer;
+    int i = 0;
+    int ret;
+
+    layer = NULL;
+    while (1)
+      {
+	  p_layer = &(base_layers[i++]);
+	  if (p_layer->name == NULL)
+	      break;
+	  if (strcmp (p_layer->name, layer_name) == 0)
+	    {
+		layer = p_layer;
+		break;
+	    }
+      }
+    if (layer == NULL)
+      {
+	  fprintf (stderr, "Unknown Point Layer: %s\n", layer_name);
+	  return 0;
+      }
+
+    if (layer->ok_point == 0)
+	do_create_point_table (params, layer);
+
+    if (layer->ok_point && layer->ins_point_stmt != NULL)
+      {
+	  sqlite3_reset (layer->ins_point_stmt);
+	  sqlite3_clear_bindings (layer->ins_point_stmt);
+	  sqlite3_bind_int64 (layer->ins_point_stmt, 1, id);
+	  if (type == NULL)
+	      sqlite3_bind_null (layer->ins_point_stmt, 2);
+	  else
+	      sqlite3_bind_text (layer->ins_point_stmt, 2, type, strlen (type),
+				 SQLITE_STATIC);
+	  if (name == NULL)
+	      sqlite3_bind_null (layer->ins_point_stmt, 3);
+	  else
+	      sqlite3_bind_text (layer->ins_point_stmt, 3, name, strlen (name),
+				 SQLITE_STATIC);
+	  if (blob == NULL)
+	      sqlite3_bind_null (layer->ins_point_stmt, 4);
+	  else
+	      sqlite3_bind_blob (layer->ins_point_stmt, 4, blob, blob_size,
+				 SQLITE_STATIC);
+	  ret = sqlite3_step (layer->ins_point_stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      return 1;
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+      }
+    return 0;
+}
+
+static void
+do_create_linestring_table (struct aux_params *params, struct layers *layer)
+{
+/* creating a Linestring table */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    sqlite3_stmt *stmt;
+
+    sql = sqlite3_mprintf ("CREATE TABLE ln_%s (\n"
+			   "osm_id INTEGER NOT NULL PRIMARY KEY,\n"
+			   "type TEXT,\nname TEXT)\n", layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'ln_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+    sql =
+	sqlite3_mprintf
+	("SELECT AddGeometryColumn('ln_%s', 'Geometry', 4326, 'LINESTRING', 'XY')",
+	 layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'ln_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+
+/* creating the insert SQL statement */
+    sql = sqlite3_mprintf ("INSERT INTO ln_%s (osm_id, type, name, Geometry) "
+			   "VALUES (?, ?, ?, ?)", layer->name);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  return;
+      }
+    layer->ok_linestring = 1;
+    layer->ins_linestring_stmt = stmt;
+}
+
+static int
+do_insert_linestring (struct aux_params *params, sqlite3_int64 id,
+		      const char *layer_name, const char *type,
+		      const char *name, gaiaGeomCollPtr geom)
+{
+/* inserting a Linestring Geometry */
+    struct layers *p_layer;
+    struct layers *layer;
+    int i = 0;
+    int ret;
+
+    layer = NULL;
+    while (1)
+      {
+	  p_layer = &(base_layers[i++]);
+	  if (p_layer->name == NULL)
+	      break;
+	  if (strcmp (p_layer->name, layer_name) == 0)
+	    {
+		layer = p_layer;
+		break;
+	    }
+      }
+    if (layer == NULL)
+      {
+	  fprintf (stderr, "Unknown Linestring Layer: %s\n", layer_name);
+	  return 0;
+      }
+
+    if (layer->ok_linestring == 0)
+	do_create_linestring_table (params, layer);
+
+    if (layer->ok_linestring && layer->ins_linestring_stmt != NULL)
+      {
+	  unsigned char *blob;
+	  int blob_size;
+	  sqlite3_reset (layer->ins_linestring_stmt);
+	  sqlite3_clear_bindings (layer->ins_linestring_stmt);
+	  sqlite3_bind_int64 (layer->ins_linestring_stmt, 1, id);
+	  if (type == NULL)
+	      sqlite3_bind_null (layer->ins_linestring_stmt, 2);
+	  else
+	      sqlite3_bind_text (layer->ins_linestring_stmt, 2, type,
+				 strlen (type), SQLITE_STATIC);
+	  if (name == NULL)
+	      sqlite3_bind_null (layer->ins_linestring_stmt, 3);
+	  else
+	      sqlite3_bind_text (layer->ins_linestring_stmt, 3, name,
+				 strlen (name), SQLITE_STATIC);
+	  gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
+	  if (blob == NULL)
+	      sqlite3_bind_null (layer->ins_linestring_stmt, 4);
+	  else
+	      sqlite3_bind_blob (layer->ins_linestring_stmt, 4, blob, blob_size,
+				 free);
+	  ret = sqlite3_step (layer->ins_linestring_stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      return 1;
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+      }
+    return 0;
+}
+
+static void
+do_create_polygon_table (struct aux_params *params, struct layers *layer)
+{
+/* creating a Polygon table */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    sqlite3_stmt *stmt;
+
+    sql = sqlite3_mprintf ("CREATE TABLE pg_%s (\n"
+			   "osm_id INTEGER NOT NULL PRIMARY KEY,\n"
+			   "type TEXT,\nname TEXT)\n", layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'pg_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+    sql =
+	sqlite3_mprintf
+	("SELECT AddGeometryColumn('pg_%s', 'Geometry', 4326, 'POLYGON', 'XY')",
+	 layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'pg_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+
+/* creating the insert SQL statement */
+    sql = sqlite3_mprintf ("INSERT INTO pg_%s (osm_id, type, name, Geometry) "
+			   "VALUES (?, ?, ?, ?)", layer->name);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  return;
+      }
+    layer->ok_polygon = 1;
+    layer->ins_polygon_stmt = stmt;
+}
+
+static int
+do_insert_polygon (struct aux_params *params, sqlite3_int64 id,
+		   const char *layer_name, const char *type, const char *name,
+		   gaiaGeomCollPtr geom)
+{
+/* inserting a Polygon Geometry */
+    struct layers *p_layer;
+    struct layers *layer;
+    int i = 0;
+    int ret;
+
+    layer = NULL;
+    while (1)
+      {
+	  p_layer = &(base_layers[i++]);
+	  if (p_layer->name == NULL)
+	      break;
+	  if (strcmp (p_layer->name, layer_name) == 0)
+	    {
+		layer = p_layer;
+		break;
+	    }
+      }
+    if (layer == NULL)
+      {
+	  fprintf (stderr, "Unknown Polygon Layer: %s\n", layer_name);
+	  return 0;
+      }
+
+    if (layer->ok_polygon == 0)
+	do_create_polygon_table (params, layer);
+
+    if (layer->ok_polygon && layer->ins_polygon_stmt != NULL)
+      {
+	  unsigned char *blob;
+	  int blob_size;
+	  sqlite3_reset (layer->ins_polygon_stmt);
+	  sqlite3_clear_bindings (layer->ins_polygon_stmt);
+	  sqlite3_bind_int64 (layer->ins_polygon_stmt, 1, id);
+	  if (type == NULL)
+	      sqlite3_bind_null (layer->ins_polygon_stmt, 2);
+	  else
+	      sqlite3_bind_text (layer->ins_polygon_stmt, 2, type,
+				 strlen (type), SQLITE_STATIC);
+	  if (name == NULL)
+	      sqlite3_bind_null (layer->ins_polygon_stmt, 3);
+	  else
+	      sqlite3_bind_text (layer->ins_polygon_stmt, 3, name,
+				 strlen (name), SQLITE_STATIC);
+	  gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
+	  if (blob == NULL)
+	      sqlite3_bind_null (layer->ins_polygon_stmt, 4);
+	  else
+	      sqlite3_bind_blob (layer->ins_polygon_stmt, 4, blob, blob_size,
+				 free);
+	  ret = sqlite3_step (layer->ins_polygon_stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      return 1;
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+      }
+    return 0;
+}
+
+static void
+do_create_multi_linestring_table (struct aux_params *params,
+				  struct layers *layer)
+{
+/* creating a MultiLinestring table */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    sqlite3_stmt *stmt;
+
+    sql = sqlite3_mprintf ("CREATE TABLE mln_%s (\n"
+			   "node_id INTEGER NOT NULL PRIMARY KEY,\n"
+			   "type TEXT,\nname TEXT)\n", layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'mln_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+    sql =
+	sqlite3_mprintf
+	("SELECT AddGeometryColumn('mln_%s', 'Geometry', 4326, 'MULTILINESTRING', 'XY')",
+	 layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'mln_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+
+/* creating the insert SQL statement */
+    sql = sqlite3_mprintf ("INSERT INTO mln_%s (node_id, type, name, Geometry) "
+			   "VALUES (?, ?, ?, ?)", layer->name);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  return;
+      }
+    layer->ok_multi_linestring = 1;
+    layer->ins_multi_linestring_stmt = stmt;
+}
+
+static int
+do_insert_multi_linestring (struct aux_params *params, sqlite3_int64 id,
+			    const char *layer_name, const char *type,
+			    const char *name, gaiaGeomCollPtr geom)
+{
+/* inserting a MultiLinestring Geometry */
+    struct layers *p_layer;
+    struct layers *layer;
+    int i = 0;
+    int ret;
+
+    layer = NULL;
+    while (1)
+      {
+	  p_layer = &(base_layers[i++]);
+	  if (p_layer->name == NULL)
+	      break;
+	  if (strcmp (p_layer->name, layer_name) == 0)
+	    {
+		layer = p_layer;
+		break;
+	    }
+      }
+    if (layer == NULL)
+      {
+	  fprintf (stderr, "Unknown MultiLinestring Layer: %s\n", layer_name);
+	  return 0;
+      }
+
+    if (layer->ok_multi_linestring == 0)
+	do_create_multi_linestring_table (params, layer);
+
+    if (layer->ok_multi_linestring && layer->ins_multi_linestring_stmt != NULL)
+      {
+	  unsigned char *blob;
+	  int blob_size;
+	  sqlite3_reset (layer->ins_multi_linestring_stmt);
+	  sqlite3_clear_bindings (layer->ins_multi_linestring_stmt);
+	  sqlite3_bind_int64 (layer->ins_multi_linestring_stmt, 1, id);
+	  if (type == NULL)
+	      sqlite3_bind_null (layer->ins_multi_linestring_stmt, 2);
+	  else
+	      sqlite3_bind_text (layer->ins_multi_linestring_stmt, 2, type,
+				 strlen (type), SQLITE_STATIC);
+	  if (name == NULL)
+	      sqlite3_bind_null (layer->ins_multi_linestring_stmt, 3);
+	  else
+	      sqlite3_bind_text (layer->ins_multi_linestring_stmt, 3, name,
+				 strlen (name), SQLITE_STATIC);
+	  gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
+	  if (blob == NULL)
+	      sqlite3_bind_null (layer->ins_multi_linestring_stmt, 4);
+	  else
+	      sqlite3_bind_blob (layer->ins_multi_linestring_stmt, 4, blob,
+				 blob_size, free);
+	  ret = sqlite3_step (layer->ins_multi_linestring_stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      return 1;
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+      }
+    return 0;
+}
+
+static void
+do_create_multi_polygon_table (struct aux_params *params, struct layers *layer)
+{
+/* creating a MultiPolygon table */
+    int ret;
+    char *err_msg = NULL;
+    char *sql;
+    sqlite3_stmt *stmt;
+
+    sql = sqlite3_mprintf ("CREATE TABLE mpg_%s (\n"
+			   "node_id INTEGER NOT NULL PRIMARY KEY,\n"
+			   "type TEXT,\nname TEXT)\n", layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'mpg_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+    sql =
+	sqlite3_mprintf
+	("SELECT AddGeometryColumn('mpg_%s', 'Geometry', 4326, 'MULTIPOLYGON', 'XY')",
+	 layer->name);
+    ret = sqlite3_exec (params->db_handle, sql, NULL, NULL, &err_msg);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'mpg_%s' error: %s\n", layer->name,
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return;
+      }
+
+/* creating the insert SQL statement */
+    sql = sqlite3_mprintf ("INSERT INTO mpg_%s (node_id, type, name, Geometry) "
+			   "VALUES (?, ?, ?, ?)", layer->name);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql), &stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n%s\n", sql,
+		   sqlite3_errmsg (params->db_handle));
+	  return;
+      }
+    layer->ok_multi_polygon = 1;
+    layer->ins_multi_polygon_stmt = stmt;
+}
+
+static int
+do_insert_multi_polygon (struct aux_params *params, sqlite3_int64 id,
+			 const char *layer_name, const char *type,
+			 const char *name, gaiaGeomCollPtr geom)
+{
+/* inserting a MultiPolygon Geometry */
+    struct layers *p_layer;
+    struct layers *layer;
+    int i = 0;
+    int ret;
+
+    layer = NULL;
+    while (1)
+      {
+	  p_layer = &(base_layers[i++]);
+	  if (p_layer->name == NULL)
+	      break;
+	  if (strcmp (p_layer->name, layer_name) == 0)
+	    {
+		layer = p_layer;
+		break;
+	    }
+      }
+    if (layer == NULL)
+      {
+	  fprintf (stderr, "Unknown MultiPolygon Layer: %s\n", layer_name);
+	  return 0;
+      }
+
+    if (layer->ok_multi_polygon == 0)
+	do_create_multi_polygon_table (params, layer);
+
+    if (layer->ok_multi_polygon && layer->ins_multi_polygon_stmt != NULL)
+      {
+	  unsigned char *blob;
+	  int blob_size;
+	  sqlite3_reset (layer->ins_multi_polygon_stmt);
+	  sqlite3_clear_bindings (layer->ins_multi_polygon_stmt);
+	  sqlite3_bind_int64 (layer->ins_multi_polygon_stmt, 1, id);
+	  if (type == NULL)
+	      sqlite3_bind_null (layer->ins_multi_polygon_stmt, 2);
+	  else
+	      sqlite3_bind_text (layer->ins_multi_polygon_stmt, 2, type,
+				 strlen (type), SQLITE_STATIC);
+	  if (name == NULL)
+	      sqlite3_bind_null (layer->ins_multi_polygon_stmt, 3);
+	  else
+	      sqlite3_bind_text (layer->ins_multi_polygon_stmt, 3, name,
+				 strlen (name), SQLITE_STATIC);
+	  gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_size);
+	  if (blob == NULL)
+	      sqlite3_bind_null (layer->ins_multi_polygon_stmt, 4);
+	  else
+	      sqlite3_bind_blob (layer->ins_multi_polygon_stmt, 4, blob,
+				 blob_size, free);
+	  ret = sqlite3_step (layer->ins_multi_polygon_stmt);
+	  if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+	      return 1;
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+      }
+    return 0;
+}
+
+static int
+build_way_geom (sqlite3 * sqlite, sqlite3_stmt * query_nodes_stmt,
+		sqlite3_int64 id, const char *layer_name, int polygon,
+		gaiaGeomCollPtr * p_geom)
+{
+/* building a Way Geometry */
+    int ret;
+    int areal_layer = 0;
+    int is_closed = 0;
+    int count = 0;
+    double x0;
+    double y0;
+    double xN;
+    double yN;
+    gaiaPointPtr pt;
+    gaiaLinestringPtr ln;
+    gaiaPolygonPtr pg;
+    gaiaRingPtr rng;
+    int iv;
+    gaiaGeomCollPtr geom;
+    gaiaDynamicLinePtr dyn_line = gaiaAllocDynamicLine ();
+
+    if (layer_name)
+      {
+	  /* possible "areal" layers */
+	  if (strcmp (layer_name, "amenity") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "building") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "historic") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "landuse") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "leisure") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "natural") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "parking") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "place") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "shop") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "sport") == 0)
+	      areal_layer = 1;
+	  if (strcmp (layer_name, "tourism") == 0)
+	      areal_layer = 1;
+      }
+
+    sqlite3_reset (query_nodes_stmt);
+    sqlite3_clear_bindings (query_nodes_stmt);
+    sqlite3_bind_int64 (query_nodes_stmt, 1, id);
+    while (1)
+      {
+	  /* scrolling the main result set */
+	  ret = sqlite3_step (query_nodes_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		double x = sqlite3_column_double (query_nodes_stmt, 0);
+		double y = sqlite3_column_double (query_nodes_stmt, 1);
+		gaiaAppendPointToDynamicLine (dyn_line, x, y);
+		if (count == 0)
+		  {
+		      x0 = x;
+		      y0 = y;
+		  }
+		else
+		  {
+		      xN = x;
+		      yN = y;
+		  }
+		count++;
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (sqlite));
+		return 0;
+	    }
+      }
+
+/* testing for a closed ring */
+    if (x0 == xN && y0 == yN)
+	is_closed = 1;
+
+    geom = gaiaAllocGeomColl ();
+    if (is_closed && (polygon || areal_layer))
+      {
+	  /* building a Polygon Geometry */
+	  pg = gaiaAddPolygonToGeomColl (geom, count, 0);
+	  rng = pg->Exterior;
+	  iv = 0;
+	  pt = dyn_line->First;
+	  while (pt)
+	    {
+		/* inserting any POINT into LINESTRING */
+		gaiaSetPoint (rng->Coords, iv, pt->X, pt->Y);
+		iv++;
+		pt = pt->Next;
+	    }
+	  geom->DeclaredType = GAIA_POLYGON;
+      }
+    else
+      {
+	  /* building a Linestring Geometry */
+	  ln = gaiaAddLinestringToGeomColl (geom, count);
+	  iv = 0;
+	  pt = dyn_line->First;
+	  while (pt)
+	    {
+		/* inserting any POINT into LINESTRING */
+		gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y);
+		iv++;
+		pt = pt->Next;
+	    }
+	  geom->DeclaredType = GAIA_LINESTRING;
+      }
+    geom->Srid = 4326;
+    gaiaFreeDynamicLine (dyn_line);
+    *p_geom = geom;
+    return 1;
+}
+
+static int
+build_rel_way_geom (void *cache, sqlite3 * sqlite,
+		    sqlite3_stmt * query_nodes_stmt, sqlite3_int64 id,
+		    gaiaGeomCollPtr * p_geom)
+{
+/* building a complex Relation-Way Geometry */
+    int ret;
+    int count = 0;
+    gaiaPointPtr pt;
+    gaiaLinestringPtr ln;
+    int iv;
+    int first = 1;
+    sqlite3_int64 current_id;
+    gaiaGeomCollPtr geom;
+    gaiaDynamicLinePtr dyn_line = gaiaAllocDynamicLine ();
+    gaiaGeomCollPtr aggregate_geom = gaiaAllocGeomColl ();
+    aggregate_geom->Srid = 4326;
+
+    sqlite3_reset (query_nodes_stmt);
+    sqlite3_clear_bindings (query_nodes_stmt);
+    sqlite3_bind_int64 (query_nodes_stmt, 1, id);
+    while (1)
+      {
+	  /* scrolling the main result set */
+	  ret = sqlite3_step (query_nodes_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		sqlite3_int64 way_id =
+		    sqlite3_column_int64 (query_nodes_stmt, 0);
+		double x = sqlite3_column_double (query_nodes_stmt, 1);
+		double y = sqlite3_column_double (query_nodes_stmt, 2);
+		if (first)
+		  {
+		      current_id = way_id;
+		      first = 0;
+		  }
+		if (way_id != current_id)
+		  {
+		      /* saving the current Way Linestring */
+		      ln = gaiaAddLinestringToGeomColl (aggregate_geom, count);
+		      iv = 0;
+		      pt = dyn_line->First;
+		      while (pt)
+			{
+			    /* inserting any POINT into LINESTRING */
+			    gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y);
+			    iv++;
+			    pt = pt->Next;
+			}
+		      gaiaFreeDynamicLine (dyn_line);
+		      dyn_line = gaiaAllocDynamicLine ();
+		      count = 0;
+		      current_id = way_id;
+		  }
+		gaiaAppendPointToDynamicLine (dyn_line, x, y);
+		count++;
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (sqlite));
+		return 0;
+	    }
+      }
+
+/* saving the last Way Linestring */
+    ln = gaiaAddLinestringToGeomColl (aggregate_geom, count);
+    iv = 0;
+    pt = dyn_line->First;
+    while (pt)
+      {
+	  /* inserting any POINT into LINESTRING */
+	  gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y);
+	  iv++;
+	  pt = pt->Next;
+      }
+    gaiaFreeDynamicLine (dyn_line);
+
+/* attempting to build a MultiPolygon */
+    geom = gaiaPolygonize_r (cache, aggregate_geom, 1);
+    if (geom != NULL)
+      {
+	  geom->Srid = 4326;
+	  geom->DeclaredType = GAIA_MULTIPOLYGON;
+	  gaiaFreeGeomColl (aggregate_geom);
+	  *p_geom = geom;
+	  return 1;
+      }
+
+/* attempting to build a MultiLinestring */
+    geom = gaiaLineMerge_r (cache, aggregate_geom);
+    if (geom != NULL)
+      {
+	  geom->Srid = 4326;
+	  geom->DeclaredType = GAIA_MULTILINESTRING;
+	  gaiaFreeGeomColl (aggregate_geom);
+	  *p_geom = geom;
+	  return 1;
+      }
+
+/* returning the aggregate geom as is */
+    aggregate_geom->DeclaredType = GAIA_MULTILINESTRING;
+    *p_geom = aggregate_geom;
+    return 1;
+}
+
+static int
+populate_map_layers (struct aux_params *params, int *points, int *linestrings,
+		     int *polygons, int *multi_linestrings, int *multi_polygons)
+{
+/* populating the MAP layers aka tables */
+    int ret;
+    sqlite3_stmt *query_nodes_stmt = NULL;
+    sqlite3_stmt *query_ways_stmt = NULL;
+    sqlite3_stmt *query_rel_ways_stmt = NULL;
+    sqlite3_stmt *query_way_nodes_stmt = NULL;
+    sqlite3_stmt *query_rel_way_nodes_stmt = NULL;
+    char *layers;
+    char *sql;
+    char *sql_err = NULL;
+    struct layers *layer;
+    int i = 0;
+
+/* preparing the list of well known layers */
+    while (1)
+      {
+	  layer = &(base_layers[i++]);
+	  if (layer->name == NULL)
+	      break;
+	  if (i == 1)
+	      layers = sqlite3_mprintf ("%Q", layer->name);
+	  else
+	    {
+		char *prev = layers;
+		layers = sqlite3_mprintf ("%s, %Q", prev, layer->name);
+		sqlite3_free (prev);
+	    }
+      }
+
+/* main SQL query extracting all relevant Nodes */
+    sql =
+	sqlite3_mprintf ("SELECT n1.node_id, n1.k AS class, n1.v AS subclass, "
+			 "n2.v AS name, g.geometry AS geometry "
+			 "FROM osm_node_tags AS n1 "
+			 "JOIN osm_nodes AS g ON (g.node_id = n1.node_id) "
+			 "LEFT JOIN osm_node_tags AS n2 ON (n2.node_id = n1.node_id AND n2.k = 'name') "
+			 "WHERE n1.k IN (%s)", layers);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_nodes_stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* main SQL query extracting all relevant Ways */
+    sql = sqlite3_mprintf ("SELECT w1.way_id, w1.k AS class, w1.v AS subclass, "
+			   "w2.v AS name, w3.v AS polygon "
+			   "FROM osm_way_tags AS w1 "
+			   "LEFT JOIN osm_way_tags AS w2 ON (w2.way_id = w1.way_id AND w2.k = 'name') "
+			   "LEFT JOIN osm_way_tags AS w3 ON (w3.way_id = w1.way_id AND w3.k = 'area') "
+			   "WHERE w1.k IN (%s)", layers);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_ways_stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* main SQL query extracting all relevant Relations-Ways */
+    sql = sqlite3_mprintf ("SELECT r1.rel_id, r1.k AS class, r1.v AS subclass, "
+			   "r2.v AS name, count(rr.ref) AS cnt FROM osm_relation_tags AS r1 "
+			   "LEFT JOIN osm_relation_tags AS r2 ON (r2.rel_id = r1.rel_id AND r2.k = 'name') "
+			   "LEFT JOIN osm_relation_refs AS rr ON (rr.rel_id = r1.rel_id AND rr.type = 'way') "
+			   "WHERE r1.k IN (%s) GROUP BY r1.rel_id", layers);
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_rel_ways_stmt, NULL);
+    sqlite3_free (sql);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+    sqlite3_free (layers);
+
+/* aux SQL query extracting Way-Node refs */
+    sql = "SELECT ST_X(n.geometry), ST_Y(n.geometry) "
+	"FROM osm_way_refs AS w "
+	"JOIN osm_nodes AS n ON (n.node_id = w.node_id) "
+	"WHERE w.way_id = ? ORDER BY w.sub";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_way_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* aux SQL query extracting Relation-Way-Node refs */
+    sql = "SELECT w.way_id, ST_X(n.geometry), ST_Y(n.geometry) "
+	"FROM osm_way_refs AS w "
+	"JOIN osm_nodes AS n ON (n.node_id = w.node_id) "
+	"WHERE w.way_id IN (SELECT ref FROM osm_relation_refs "
+	"WHERE rel_id = ? AND type = 'way') " "ORDER BY w.way_id, w.sub";
+    ret =
+	sqlite3_prepare_v2 (params->db_handle, sql, strlen (sql),
+			    &query_rel_way_nodes_stmt, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "SQL error: %s\n",
+		   sqlite3_errmsg (params->db_handle));
+	  goto error;
+      }
+
+/* the complete operation is handled as an unique SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "BEGIN", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  goto error;
+      }
+
+    while (1)
+      {
+	  /* scrolling the Nodes result set */
+	  ret = sqlite3_step (query_nodes_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		const char *layer = NULL;
+		const char *type = NULL;
+		const char *name = NULL;
+		const unsigned char *blob = NULL;
+		int blob_size;
+		sqlite3_int64 id = sqlite3_column_int64 (query_nodes_stmt, 0);
+		if (sqlite3_column_type (query_nodes_stmt, 1) != SQLITE_NULL)
+		    layer =
+			(const char *) sqlite3_column_text (query_nodes_stmt,
+							    1);
+		if (sqlite3_column_type (query_nodes_stmt, 2) != SQLITE_NULL)
+		    type =
+			(const char *) sqlite3_column_text (query_nodes_stmt,
+							    2);
+		if (sqlite3_column_type (query_nodes_stmt, 3) != SQLITE_NULL)
+		    name =
+			(const char *) sqlite3_column_text (query_nodes_stmt,
+							    3);
+		if (sqlite3_column_type (query_nodes_stmt, 4) == SQLITE_BLOB)
+		  {
+		      blob =
+			  (const unsigned char *)
+			  sqlite3_column_blob (query_nodes_stmt, 4);
+		      blob_size = sqlite3_column_bytes (query_nodes_stmt, 4);
+		  }
+		if (do_insert_point
+		    (params, id, layer, type, name, blob, blob_size))
+		    *points += 1;
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (params->db_handle));
+		/* ROLLBACK */
+		ret =
+		    sqlite3_exec (params->db_handle, "ROLLBACK", NULL, NULL,
+				  &sql_err);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n",
+			       sql_err);
+		      sqlite3_free (sql_err);
+		      goto error;
+		  }
+		goto error;
+	    }
+      }
+
+    while (1)
+      {
+	  /* scrolling the Ways result set */
+	  ret = sqlite3_step (query_ways_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		const char *layer = NULL;
+		const char *type = NULL;
+		const char *name = NULL;
+		int polygon = 0;
+		gaiaGeomCollPtr geom = NULL;
+		sqlite3_int64 id = sqlite3_column_int64 (query_ways_stmt, 0);
+		if (sqlite3_column_type (query_ways_stmt, 1) != SQLITE_NULL)
+		    layer =
+			(const char *) sqlite3_column_text (query_ways_stmt, 1);
+		if (sqlite3_column_type (query_ways_stmt, 2) != SQLITE_NULL)
+		    type =
+			(const char *) sqlite3_column_text (query_ways_stmt, 2);
+		if (sqlite3_column_type (query_ways_stmt, 3) != SQLITE_NULL)
+		    name =
+			(const char *) sqlite3_column_text (query_ways_stmt, 3);
+		if (sqlite3_column_type (query_ways_stmt, 4) != SQLITE_NULL)
+		  {
+		      if (strcmp
+			  ((const char *)
+			   sqlite3_column_text (query_ways_stmt, 4),
+			   "yes") == 0)
+			  polygon = 1;
+		  }
+		if (!build_way_geom
+		    (params->db_handle, query_way_nodes_stmt, id, layer,
+		     polygon, &geom))
+		  {
+#if defined(_WIN32) || defined(__MINGW32__)
+		      /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+		      fprintf (stderr,
+			       "ERROR: unable to resolve WAY id=%I64d\n", id);
+#else
+		      fprintf (stderr,
+			       "ERROR: unable to resolve WAY id=%lld\n", id);
+#endif
+		      goto error;
+		  }
+		if (geom->DeclaredType == GAIA_LINESTRING)
+		  {
+		      if (do_insert_linestring
+			  (params, id, layer, type, name, geom))
+			  *linestrings += 1;
+		  }
+		else
+		  {
+		      if (do_insert_polygon
+			  (params, id, layer, type, name, geom))
+			  *polygons += 1;
+		  }
+		gaiaFreeGeomColl (geom);
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (params->db_handle));
+		/* ROLLBACK */
+		ret =
+		    sqlite3_exec (params->db_handle, "ROLLBACK", NULL, NULL,
+				  &sql_err);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n",
+			       sql_err);
+		      sqlite3_free (sql_err);
+		      goto error;
+		  }
+		goto error;
+	    }
+      }
+    while (1)
+      {
+	  /* scrolling the Relations-Ways result set */
+	  ret = sqlite3_step (query_rel_ways_stmt);
+	  if (ret == SQLITE_DONE)
+	    {
+		/* there are no more rows to fetch - we can stop looping */
+		break;
+	    }
+	  if (ret == SQLITE_ROW)
+	    {
+		/* ok, we've just fetched a valid row */
+		const char *layer = NULL;
+		const char *type = NULL;
+		const char *name = NULL;
+		gaiaGeomCollPtr geom = NULL;
+		sqlite3_int64 id =
+		    sqlite3_column_int64 (query_rel_ways_stmt, 0);
+		if (sqlite3_column_type (query_rel_ways_stmt, 1) != SQLITE_NULL)
+		    layer =
+			(const char *) sqlite3_column_text (query_rel_ways_stmt,
+							    1);
+		if (sqlite3_column_type (query_rel_ways_stmt, 2) != SQLITE_NULL)
+		    type =
+			(const char *) sqlite3_column_text (query_rel_ways_stmt,
+							    2);
+		if (sqlite3_column_type (query_rel_ways_stmt, 3) != SQLITE_NULL)
+		    name =
+			(const char *) sqlite3_column_text (query_rel_ways_stmt,
+							    3);
+		if (!build_rel_way_geom
+		    (params->cache, params->db_handle, query_rel_way_nodes_stmt,
+		     id, &geom))
+		  {
+#if defined(_WIN32) || defined(__MINGW32__)
+		      /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
+		      fprintf (stderr,
+			       "ERROR: unable to resolve RELATION-WAY id=%I64d\n",
+			       id);
+#else
+		      fprintf (stderr,
+			       "ERROR: unable to resolve RELATION-WAY id=%lld\n",
+			       id);
+#endif
+		      goto error;
+		  }
+		if (geom->DeclaredType == GAIA_MULTILINESTRING)
+		  {
+		      if (do_insert_multi_linestring
+			  (params, id, layer, type, name, geom))
+			  *multi_linestrings += 1;
+		  }
+		else
+		  {
+		      if (do_insert_multi_polygon
+			  (params, id, layer, type, name, geom))
+			  *multi_polygons += 1;
+		  }
+		gaiaFreeGeomColl (geom);
+	    }
+	  else
+	    {
+		/* some unexpected error occurred */
+		fprintf (stderr, "sqlite3_step() error: %s\n",
+			 sqlite3_errmsg (params->db_handle));
+		/* ROLLBACK */
+		ret =
+		    sqlite3_exec (params->db_handle, "ROLLBACK", NULL, NULL,
+				  &sql_err);
+		if (ret != SQLITE_OK)
+		  {
+		      fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n",
+			       sql_err);
+		      sqlite3_free (sql_err);
+		      goto error;
+		  }
+		goto error;
+	    }
+      }
+
+/* committing the still pending SQL Transaction */
+    ret = sqlite3_exec (params->db_handle, "COMMIT", NULL, NULL, &sql_err);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
+	  sqlite3_free (sql_err);
+	  goto error;
+      }
+
+    sqlite3_finalize (query_nodes_stmt);
+    sqlite3_finalize (query_ways_stmt);
+    sqlite3_finalize (query_way_nodes_stmt);
+    sqlite3_finalize (query_rel_way_nodes_stmt);
+
+    return 1;
+
+  error:
+    if (query_nodes_stmt != NULL)
+	sqlite3_finalize (query_nodes_stmt);
+    if (query_ways_stmt != NULL)
+	sqlite3_finalize (query_ways_stmt);
+    if (query_way_nodes_stmt != NULL)
+	sqlite3_finalize (query_way_nodes_stmt);
+    if (query_rel_way_nodes_stmt != NULL)
+	sqlite3_finalize (query_rel_way_nodes_stmt);
+    return 0;
+}
+
+static void
+do_clean_roads (struct aux_params *params)
+{
+/* ROAD post-processing: DB cleanup */
+    sqlite3 *db_handle = params->db_handle;
+    printf ("\nFinal DBMS cleanup\n");
+    sqlite3_exec (db_handle, "DROP TABLE osm_helper_nodes", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relation_refs", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relation_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relations", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_way_refs", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_way_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_ways", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_node_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle,
+		  "DELETE FROM geometry_columns WHERE f_table_name = 'osm_nodes'",
+		  NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_nodes", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "VACUUM", NULL, NULL, NULL);
+    printf ("All done\n");
+}
+
+static void
+do_clean_rails (struct aux_params *params)
+{
+/* ROAD post-processing: DB cleanup */
+    sqlite3 *db_handle = params->db_handle;
+    printf ("\nFinal DBMS cleanup\n");
+    sqlite3_exec (db_handle, "DROP TABLE osm_helper_nodes", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relation_refs", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relation_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relations", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_way_refs", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_way_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_ways", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_node_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle,
+		  "DELETE FROM geometry_columns WHERE f_table_name = 'osm_nodes'",
+		  NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_nodes", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "VACUUM", NULL, NULL, NULL);
+    printf ("All done\n");
+}
+
+static void
+do_clean_map (struct aux_params *params)
+{
+/* MAP post-processing: DB cleanup */
+    sqlite3 *db_handle = params->db_handle;
+    printf ("\nFinal DBMS cleanup\n");
+    sqlite3_exec (db_handle, "DROP TABLE osm_relation_refs", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relation_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_relations", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_way_refs", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_way_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_ways", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_node_tags", NULL, NULL, NULL);
+    sqlite3_exec (db_handle,
+		  "DELETE FROM geometry_columns WHERE f_table_name = 'osm_nodes'",
+		  NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "DROP TABLE osm_nodes", NULL, NULL, NULL);
+    sqlite3_exec (db_handle, "VACUUM", NULL, NULL, NULL);
+    printf ("All done\n");
+}
+
+static int
+create_osm_raw_tables (struct aux_params *params)
+{
+/* creating the raw OSM tables */
+    sqlite3 *db_handle = params->db_handle;
+    int ret;
+    char sql[1024];
+    char *err_msg = NULL;
+
+/* creating the OSM "raw" nodes */
+    if (params->mode == MODE_RAW)
+      {
+	  strcpy (sql, "CREATE TABLE osm_nodes (\n");
+	  strcat (sql, "node_id INTEGER NOT NULL PRIMARY KEY,\n");
+	  strcat (sql, "version INTEGER,\n");
+	  strcat (sql, "timestamp TEXT,\n");
+	  strcat (sql, "uid INTEGER,\n");
+	  strcat (sql, "user TEXT,\n");
+	  strcat (sql, "changeset INTEGER)\n");
+      }
+    else
+      {
+	  strcpy (sql, "CREATE TABLE osm_nodes (\n");
+	  strcat (sql, "node_id INTEGER NOT NULL PRIMARY KEY)\n");
+      }
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_nodes' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    strcpy (sql,
+	    "SELECT AddGeometryColumn('osm_nodes', 'Geometry', 4326, 'POINT', 'XY')");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_nodes' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" node tags */
+    strcpy (sql, "CREATE TABLE osm_node_tags (\n");
+    strcat (sql, "node_id INTEGER NOT NULL,\n");
+    strcat (sql, "sub INTEGER NOT NULL,\n");
+    strcat (sql, "k TEXT,\n");
+    strcat (sql, "v TEXT,\n");
+    strcat (sql, "CONSTRAINT pk_osm_nodetags PRIMARY KEY (node_id, sub),\n");
+    strcat (sql, "CONSTRAINT fk_osm_nodetags FOREIGN KEY (node_id) ");
+    strcat (sql, "REFERENCES osm_nodes (node_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_node_tags' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" ways */
+    strcpy (sql, "CREATE TABLE osm_ways (\n");
+    strcat (sql, "way_id INTEGER NOT NULL PRIMARY KEY)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_ways' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" way tags */
+    strcpy (sql, "CREATE TABLE osm_way_tags (\n");
+    strcat (sql, "way_id INTEGER NOT NULL,\n");
+    strcat (sql, "sub INTEGER NOT NULL,\n");
+    strcat (sql, "k TEXT,\n");
+    strcat (sql, "v TEXT,\n");
+    strcat (sql, "CONSTRAINT pk_osm_waytags PRIMARY KEY (way_id, sub),\n");
+    strcat (sql, "CONSTRAINT fk_osm_waytags FOREIGN KEY (way_id) ");
+    strcat (sql, "REFERENCES osm_ways (way_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_way_tags' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" way-node refs */
+    strcpy (sql, "CREATE TABLE osm_way_refs (\n");
+    strcat (sql, "way_id INTEGER NOT NULL,\n");
+    strcat (sql, "sub INTEGER NOT NULL,\n");
+    strcat (sql, "node_id INTEGER NOT NULL,\n");
+    strcat (sql, "CONSTRAINT pk_osm_waynoderefs PRIMARY KEY (way_id, sub),\n");
+    strcat (sql, "CONSTRAINT fk_osm_waynoderefs FOREIGN KEY (way_id) ");
+    strcat (sql, "REFERENCES osm_ways (way_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_way_refs' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating an index supporting osm_way_refs.node_id */
+    strcpy (sql, "CREATE INDEX idx_osm_ref_way ON osm_way_refs (node_id)");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'idx_osm_node_way' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" relations */
+    strcpy (sql, "CREATE TABLE osm_relations (\n");
+    strcat (sql, "rel_id INTEGER NOT NULL PRIMARY KEY)\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_relations' error: %s\n", err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" relation tags */
+    strcpy (sql, "CREATE TABLE osm_relation_tags (\n");
+    strcat (sql, "rel_id INTEGER NOT NULL,\n");
+    strcat (sql, "sub INTEGER NOT NULL,\n");
+    strcat (sql, "k TEXT,\n");
+    strcat (sql, "v TEXT,\n");
+    strcat (sql, "CONSTRAINT pk_osm_reltags PRIMARY KEY (rel_id, sub),\n");
+    strcat (sql, "CONSTRAINT fk_osm_reltags FOREIGN KEY (rel_id) ");
+    strcat (sql, "REFERENCES osm_relations (rel_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_relation_tags' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating the OSM "raw" relation-node refs */
+    strcpy (sql, "CREATE TABLE osm_relation_refs (\n");
+    strcat (sql, "rel_id INTEGER NOT NULL,\n");
+    strcat (sql, "sub INTEGER NOT NULL,\n");
+    strcat (sql, "type TEXT NOT NULL,\n");
+    strcat (sql, "ref INTEGER NOT NULL,\n");
+    strcat (sql, "role TEXT,");
+    strcat (sql, "CONSTRAINT pk_osm_relnoderefs PRIMARY KEY (rel_id, sub),\n");
+    strcat (sql, "CONSTRAINT fk_osm_relnoderefs FOREIGN KEY (rel_id) ");
+    strcat (sql, "REFERENCES osm_relations (rel_id))\n");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE TABLE 'osm_relation_refs' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+/* creating an index supporting osm_relation_refs.ref */
+    strcpy (sql,
+	    "CREATE INDEX idx_osm_ref_relation ON osm_relation_refs (type, ref)");
+    ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "CREATE INDEX 'idx_osm_relation' error: %s\n",
+		   err_msg);
+	  sqlite3_free (err_msg);
+	  return 0;
+      }
+    return 1;
+}
+
+static void
+open_db (const char *path, sqlite3 ** handle, int cache_size, void *cache)
+{
+/* opening the DB */
+    sqlite3 *db_handle;
+    int ret;
+    char sql[1024];
+    int spatialite_rs = 0;
+    int spatialite_gc = 0;
+    int rs_srid = 0;
+    int auth_name = 0;
+    int auth_srid = 0;
+    int ref_sys_name = 0;
+    int proj4text = 0;
+    int f_table_name = 0;
+    int f_geometry_column = 0;
+    int coord_dimension = 0;
+    int gc_srid = 0;
+    int type = 0;
+    int geometry_type = 0;
+    int spatial_index_enabled = 0;
+    const char *name;
+    int i;
+    char **results;
+    int rows;
+    int columns;
+
+    *handle = NULL;
+    printf ("SQLite version: %s\n", sqlite3_libversion ());
+    printf ("SpatiaLite version: %s\n\n", spatialite_version ());
+
+    ret =
+	sqlite3_open_v2 (path, &db_handle,
+			 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
+    if (ret != SQLITE_OK)
+      {
+	  fprintf (stderr, "cannot open '%s': %s\n", path,
+		   sqlite3_errmsg (db_handle));
+	  sqlite3_close (db_handle);
+	  return;
+      }
+    spatialite_init_ex (db_handle, cache, 0);
+    spatialite_autocreate (db_handle);
+    if (cache_size > 0)
+      {
+	  /* setting the CACHE-SIZE */
+	  sprintf (sql, "PRAGMA cache_size=%d", cache_size);
+	  sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
+      }
+    /* enforcing PK/FK constraints */
+    sprintf (sql, "PRAGMA foreign_keys=1");
+    sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
+
+/* checking the GEOMETRY_COLUMNS table */
+    strcpy (sql, "PRAGMA table_info(geometry_columns)");
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+	goto unknown;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		name = results[(i * columns) + 1];
+		if (strcasecmp (name, "f_table_name") == 0)
+		    f_table_name = 1;
+		if (strcasecmp (name, "f_geometry_column") == 0)
+		    f_geometry_column = 1;
+		if (strcasecmp (name, "coord_dimension") == 0)
+		    coord_dimension = 1;
+		if (strcasecmp (name, "srid") == 0)
+		    gc_srid = 1;
+		if (strcasecmp (name, "type") == 0)
+		    type = 1;
+		if (strcasecmp (name, "geometry_type") == 0)
+		    geometry_type = 1;
+		if (strcasecmp (name, "spatial_index_enabled") == 0)
+		    spatial_index_enabled = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (f_table_name && f_geometry_column && type && coord_dimension
+	&& gc_srid && spatial_index_enabled)
+	spatialite_gc = 1;
+    if (f_table_name && f_geometry_column && geometry_type && coord_dimension
+	&& gc_srid && spatial_index_enabled)
+	spatialite_gc = 3;
+
+/* checking the SPATIAL_REF_SYS table */
+    strcpy (sql, "PRAGMA table_info(spatial_ref_sys)");
+    ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+    if (ret != SQLITE_OK)
+	goto unknown;
+    if (rows < 1)
+	;
+    else
+      {
+	  for (i = 1; i <= rows; i++)
+	    {
+		name = results[(i * columns) + 1];
+		if (strcasecmp (name, "srid") == 0)
+		    rs_srid = 1;
+		if (strcasecmp (name, "auth_name") == 0)
+		    auth_name = 1;
+		if (strcasecmp (name, "auth_srid") == 0)
+		    auth_srid = 1;
+		if (strcasecmp (name, "ref_sys_name") == 0)
+		    ref_sys_name = 1;
+		if (strcasecmp (name, "proj4text") == 0)
+		    proj4text = 1;
+	    }
+      }
+    sqlite3_free_table (results);
+    if (rs_srid && auth_name && auth_srid && ref_sys_name && proj4text)
+	spatialite_rs = 1;
+/* verifying the MetaData format */
+    if (spatialite_gc && spatialite_rs)
+	;
+    else
+	goto unknown;
+
+    *handle = db_handle;
+    return;
+
+  unknown:
+    if (db_handle)
+	sqlite3_close (db_handle);
+    fprintf (stderr, "DB '%s'\n", path);
+    fprintf (stderr, "doesn't seems to contain valid Spatial Metadata ...\n\n");
+    fprintf (stderr, "Please, initialize Spatial Metadata\n\n");
+    return;
+}
+
+static int
+check_bbox (double *minx, double *miny, double *maxx, double *maxy)
+{
+/* checking the BoundingBox for validity */
+    double save;
+    int ret = 1;
+    if (*minx < -180.0)
+      {
+	  *minx = -180.0;
+	  ret = 0;
+      }
+    if (*maxx > 180.0)
+      {
+	  *maxx = 180.0;
+	  ret = 0;
+      }
+    if (*miny < -90.0)
+      {
+	  *miny = -90.0;
+	  ret = 0;
+      }
+    if (*maxy > 90.0)
+      {
+	  *maxy = 90.0;
+	  ret = 0;
+      }
+    if (*minx > *maxx)
+      {
+	  save = *minx;
+	  *minx = *maxx;
+	  *maxx = save;
+	  ret = 0;
+      }
+    if (*miny > *maxy)
+      {
+	  save = *miny;
+	  *miny = *maxy;
+	  *maxy = save;
+	  ret = 0;
+      }
+    return ret;
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+    fprintf (stderr, "\n\nusage: spatialite_osm_overpass ARGLIST\n");
+    fprintf (stderr,
+	     "==============================================================\n");
+    fprintf (stderr,
+	     "-h or --help                    print this help message\n");
+    fprintf (stderr,
+	     "-d or --db-path     pathname    the SpatiaLite DB path\n");
+    fprintf (stderr,
+	     "-minx or --bbox-minx  coord     BoundingBox - west longitude\n");
+    fprintf (stderr,
+	     "-maxx or --bbox-maxx  coord     BoundingBox - east longitude\n");
+    fprintf (stderr,
+	     "-miny or --bbox-miny  coord     BoundingBox - south latitude\n");
+    fprintf (stderr,
+	     "-maxy or --bbox-maxy  coord     BoundingBox - north latitude\n\n");
+    fprintf (stderr, "you can specify the following options as well\n");
+    fprintf (stderr,
+	     "-o or --osm-service   URL       URL of OSM Overpass service:\n");
+    fprintf (stderr,
+	     "                                http://overpass-api.de/api (default)\n");
+    fprintf (stderr,
+	     "                                http://overpass.osm.rambler.ru/cgi\n");
+    fprintf (stderr,
+	     "                                http://api.openstreetmap.fr/oapi\n");
+    fprintf (stderr,
+	     "-mode or --mode       mode      one of: RAW / MAP (default) / ROAD / RAIL\n");
+    fprintf (stderr,
+	     "-cs or --cache-size   num       DB cache size (how many pages)\n");
+    fprintf (stderr,
+	     "-m or --in-memory               using IN-MEMORY database\n");
+    fprintf (stderr,
+	     "-jo or --journal-off            unsafe [but faster] mode\n");
+    fprintf (stderr,
+	     "-p or --preserve                skipping final cleanup (preserving OSM tables)\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function simply perform arguments checking */
+    sqlite3 *handle;
+    int i;
+    int next_arg = ARG_NONE;
+    const char *osm_url = "http://overpass-api.de/api";
+    const char *db_path = NULL;
+    int in_memory = 0;
+    int cache_size = 0;
+    int journal_off = 0;
+    int error = 0;
+    void *cache;
+    double minx;
+    int ok_minx = 0;
+    double miny;
+    int ok_miny = 0;
+    double maxx;
+    int ok_maxx = 0;
+    double maxy;
+    int ok_maxy = 0;
+    int bbox = 1;
+    int mode = MODE_MAP;
+    int preserve_osm_tables = 0;
+    struct aux_params params;
+    struct tiled_download downloader;
+    struct download_tile *tile;
+    double extent_h;
+    double extent_v;
+    double step_v;
+    double step_h;
+    double factor;
+    double base_x;
+    double base_y;
+    double right_x;
+    double top_y;
+
+/* initializing the tiled downloader object */
+    downloader.first = NULL;
+    downloader.last = NULL;
+    downloader.count = 0;
+
+/* initializing the aux-structs */
+    params.db_handle = NULL;
+    params.ins_nodes_stmt = NULL;
+    params.ins_node_tags_stmt = NULL;
+    params.ins_ways_stmt = NULL;
+    params.ins_way_tags_stmt = NULL;
+    params.ins_way_refs_stmt = NULL;
+    params.ins_relations_stmt = NULL;
+    params.ins_relation_tags_stmt = NULL;
+    params.ins_relation_refs_stmt = NULL;
+    params.wr_nodes = 0;
+    params.wr_node_tags = 0;
+    params.wr_ways = 0;
+    params.wr_way_tags = 0;
+    params.wr_way_refs = 0;
+    params.wr_relations = 0;
+    params.wr_rel_tags = 0;
+    params.wr_rel_refs = 0;
+    params.osm_url = NULL;
+
+    for (i = 1; i < argc; i++)
+      {
+	  /* parsing the invocation arguments */
+	  if (next_arg != ARG_NONE)
+	    {
+		switch (next_arg)
+		  {
+		  case ARG_DB_PATH:
+		      db_path = argv[i];
+		      break;
+		  case ARG_OSM_URL:
+		      osm_url = argv[i];
+		      break;
+		  case ARG_CACHE_SIZE:
+		      cache_size = atoi (argv[i]);
+		      break;
+		  case ARG_MINX:
+		      minx = atof (argv[i]);
+		      ok_minx = 1;
+		      break;
+		  case ARG_MINY:
+		      miny = atof (argv[i]);
+		      ok_miny = 1;
+		      break;
+		  case ARG_MAXX:
+		      maxx = atof (argv[i]);
+		      ok_maxx = 1;
+		      break;
+		  case ARG_MAXY:
+		      maxy = atof (argv[i]);
+		      ok_maxy = 1;
+		      break;
+		  case ARG_MODE:
+		      if (strcmp (argv[i], "RAW") == 0)
+			  mode = MODE_RAW;
+		      if (strcmp (argv[i], "MAP") == 0)
+			  mode = MODE_MAP;
+		      if (strcmp (argv[i], "ROAD") == 0)
+			  mode = MODE_ROAD;
+		      if (strcmp (argv[i], "RAIL") == 0)
+			  mode = MODE_RAIL;
+		      break;
+		  };
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--help") == 0
+	      || strcmp (argv[i], "-h") == 0)
+	    {
+		do_help ();
+		return -1;
+	    }
+	  if (strcmp (argv[i], "-d") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--db-path") == 0)
+	    {
+		next_arg = ARG_DB_PATH;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--osm-service") == 0
+	      || strcmp (argv[i], "-o") == 0)
+	    {
+		next_arg = ARG_OSM_URL;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--bbox-minx") == 0
+	      || strcmp (argv[i], "-minx") == 0)
+	    {
+		next_arg = ARG_MINX;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--bbox-miny") == 0
+	      || strcmp (argv[i], "-miny") == 0)
+	    {
+		next_arg = ARG_MINY;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--bbox-maxx") == 0
+	      || strcmp (argv[i], "-maxx") == 0)
+	    {
+		next_arg = ARG_MAXX;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--bbox-maxy") == 0
+	      || strcmp (argv[i], "-maxy") == 0)
+	    {
+		next_arg = ARG_MAXY;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--mode") == 0
+	      || strcmp (argv[i], "-mode") == 0)
+	    {
+		next_arg = ARG_MODE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--preserve") == 0
+	      || strcmp (argv[i], "-p") == 0)
+	    {
+		preserve_osm_tables = 1;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--cache-size") == 0
+	      || strcmp (argv[i], "-cs") == 0)
+	    {
+		next_arg = ARG_CACHE_SIZE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-m") == 0)
+	    {
+		in_memory = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--in-memory") == 0)
+	    {
+		in_memory = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "-jo") == 0)
+	    {
+		journal_off = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  if (strcasecmp (argv[i], "--journal-off") == 0)
+	    {
+		journal_off = 1;
+		next_arg = ARG_NONE;
+		continue;
+	    }
+	  fprintf (stderr, "unknown argument: %s\n", argv[i]);
+	  error = 1;
+      }
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* checking the arguments */
+    if (!db_path)
+      {
+	  fprintf (stderr, "did you forget setting the --db-path argument ?\n");
+	  error = 1;
+      }
+    if (!ok_minx)
+      {
+	  fprintf (stderr,
+		   "did you forget setting the --bbox-minx argument ?\n");
+	  error = 1;
+	  bbox = 0;
+      }
+    if (!ok_miny)
+      {
+	  fprintf (stderr,
+		   "did you forget setting the --bbox-miny argument ?\n");
+	  error = 1;
+	  bbox = 0;
+      }
+    if (!ok_maxx)
+      {
+	  fprintf (stderr,
+		   "did you forget setting the --bbox-maxx argument ?\n");
+	  error = 1;
+	  bbox = 0;
+      }
+    if (!ok_maxy)
+      {
+	  fprintf (stderr,
+		   "did you forget setting the --bbox-maxy argument ?\n");
+	  error = 1;
+	  bbox = 0;
+      }
+    if (bbox)
+      {
+	  if (!check_bbox (&minx, &miny, &maxx, &maxy))
+	    {
+		fprintf (stderr,
+			 "invalid BoundingBox; did you possibly intended\n"
+			 "\t-minx %1.6f -miny %1.6f -maxx %1.6f -maxy %1.6f ?\n",
+			 minx, miny, maxx, maxy);
+		error = 1;
+	    }
+      }
+
+    if (error)
+      {
+	  do_help ();
+	  return -1;
+      }
+
+/* preparing individual download tiles */
+    extent_h = maxx - minx;
+    extent_v = maxy - miny;
+    step_h = extent_h;
+    factor = 1.0;
+    while (step_h > 0.35)
+      {
+	  factor += 1.0;
+	  step_h = extent_h / factor;
+      }
+    step_v = extent_v;
+    factor = 1.0;
+    while (step_v > 0.35)
+      {
+	  factor += 1.0;
+	  step_v = extent_v / factor;
+      }
+    base_y = miny;
+    while (base_y < maxy)
+      {
+	  top_y = base_y + step_v + 0.01;
+	  if (top_y > maxy)
+	      top_y = maxy;
+	  base_x = minx;
+	  while (base_x < maxx)
+	    {
+		right_x = base_x + step_h + 0.01;
+		if (right_x > maxx)
+		    right_x = maxx;
+		add_download_tile (&downloader, base_x, base_y, right_x, top_y);
+		base_x += step_h;
+	    }
+	  base_y += step_v;
+      }
+
+/* opening the DB */
+    if (in_memory)
+	cache_size = 0;
+    cache = spatialite_alloc_connection ();
+    open_db (db_path, &handle, cache_size, cache);
+    if (!handle)
+	return -1;
+    if (in_memory)
+      {
+	  /* loading the DB in-memory */
+	  sqlite3 *mem_db_handle;
+	  sqlite3_backup *backup;
+	  int ret;
+	  ret =
+	      sqlite3_open_v2 (":memory:", &mem_db_handle,
+			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			       NULL);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "cannot open 'MEMORY-DB': %s\n",
+			 sqlite3_errmsg (mem_db_handle));
+		sqlite3_close (mem_db_handle);
+		return -1;
+	    }
+	  backup = sqlite3_backup_init (mem_db_handle, "main", handle, "main");
+	  if (!backup)
+	    {
+		fprintf (stderr, "cannot load 'MEMORY-DB'\n");
+		sqlite3_close (handle);
+		sqlite3_close (mem_db_handle);
+		return -1;
+	    }
+	  while (1)
+	    {
+		ret = sqlite3_backup_step (backup, 1024);
+		if (ret == SQLITE_DONE)
+		    break;
+	    }
+	  ret = sqlite3_backup_finish (backup);
+	  sqlite3_close (handle);
+	  handle = mem_db_handle;
+	  printf ("\nusing IN-MEMORY database\n");
+	  spatialite_cleanup_ex (cache);
+	  cache = spatialite_alloc_connection ();
+	  spatialite_init_ex (handle, cache, 0);
+      }
+    params.db_handle = handle;
+    params.cache = cache;
+    params.osm_url = osm_url;
+    params.mode = mode;
+
+/* creating the OSM raw tables */
+    if (!create_osm_raw_tables (&params))
+      {
+	  sqlite3_close (handle);
+	  return -1;
+      }
+/* creating the  SQL prepared statements */
+    create_sql_stmts (&params, journal_off);
+
+    tile = downloader.first;
+    while (tile != NULL)
+      {
+	  /* downloading and parsing an input OSM dataset (tiled) */
+	  if (mode == MODE_ROAD || mode == MODE_RAIL)
+	    {
+		printf ("Downloading and parsing OSM tile %d of %d\r",
+			tile->tile_no, downloader.count);
+		if (!osm_parse (&params, tile, 0))
+		  {
+		      fprintf (stderr,
+			       "\noperation aborted due to unrecoverable errors\n\n");
+		      finalize_sql_stmts (&params);
+		      sqlite3_close (handle);
+		      return -1;
+		  }
+	    }
+	  else
+	    {
+		printf
+		    ("Downloading and parsing OSM tile %d of %d - Nodes        \r",
+		     tile->tile_no, downloader.count);
+		if (!osm_parse (&params, tile, OBJ_NODES))
+		  {
+		      fprintf (stderr,
+			       "\noperation aborted due to unrecoverable errors\n\n");
+		      finalize_sql_stmts (&params);
+		      sqlite3_close (handle);
+		      return -1;
+		  }
+		printf
+		    ("Downloading and parsing OSM tile %d of %d - Ways          \r",
+		     tile->tile_no, downloader.count);
+		if (!osm_parse (&params, tile, OBJ_WAYS))
+		  {
+		      fprintf (stderr,
+			       "\noperation aborted due to unrecoverable errors\n\n");
+		      finalize_sql_stmts (&params);
+		      sqlite3_close (handle);
+		      return -1;
+		  }
+		printf
+		    ("Downloading and parsing OSM tile %d of %d - Relations     \r",
+		     tile->tile_no, downloader.count);
+		if (!osm_parse (&params, tile, OBJ_RELATIONS))
+		  {
+		      fprintf (stderr,
+			       "\noperation aborted due to unrecoverable errors\n\n");
+		      finalize_sql_stmts (&params);
+		      sqlite3_close (handle);
+		      return -1;
+		  }
+	    }
+	  tile = tile->next;
+      }
+    printf ("Download completed                                        \n");
+
+/* finalizing SQL prepared statements */
+    finalize_sql_stmts (&params);
+
+/* printing out statistics */
+    printf ("inserted %d nodes\n", params.wr_nodes);
+    printf ("\t%d tags\n", params.wr_node_tags);
+    printf ("inserted %d ways\n", params.wr_ways);
+    printf ("\t%d tags\n", params.wr_way_tags);
+    printf ("\t%d node-refs\n", params.wr_way_refs);
+    printf ("inserted %d relations\n", params.wr_relations);
+    printf ("\t%d tags\n", params.wr_rel_tags);
+    printf ("\t%d refs\n", params.wr_rel_refs);
+
+    if (mode == MODE_ROAD)
+      {
+	  /* building the Road Network */
+	  int cnt_nodes = 0;
+	  int cnt_arcs = 0;
+	  if (!create_road_tables (&params))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  if (!populate_road_network (&params, &cnt_nodes, &cnt_arcs))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  if (!create_road_rtrees (&params))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  printf ("inserted %d ROAD nodes\n", cnt_nodes);
+	  printf ("inserted %d ROAD arcs\n", cnt_arcs);
+	  if (!preserve_osm_tables)
+	      do_clean_roads (&params);
+      }
+    else if (mode == MODE_RAIL)
+      {
+	  /* building the Rail Network */
+	  int cnt_nodes = 0;
+	  int cnt_arcs = 0;
+	  int cnt_stations = 0;
+	  if (!create_rail_tables (&params))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  if (!populate_rail_network
+	      (&params, &cnt_nodes, &cnt_arcs, &cnt_stations))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  if (!create_rail_rtrees (&params))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  printf ("inserted %d RAIL nodes\n", cnt_nodes);
+	  printf ("inserted %d RAIL arcs\n", cnt_arcs);
+	  printf ("inserted %d RAIL stations\n", cnt_stations);
+	  if (!preserve_osm_tables)
+	      do_clean_rails (&params);
+      }
+    else if (mode == MODE_MAP)
+      {
+	  /* building a full MAP */
+	  int points = 0;
+	  int linestrings = 0;
+	  int polygons = 0;
+	  int multi_linestrings = 0;
+	  int multi_polygons = 0;
+	  if (!create_map_indices (&params))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  if (!populate_map_layers
+	      (&params, &points, &linestrings, &polygons, &multi_linestrings,
+	       &multi_polygons))
+	    {
+		sqlite3_close (handle);
+		return -1;
+	    }
+	  finalize_map_stmts ();
+	  printf ("inserted %d Point Features\n", points);
+	  printf ("inserted %d Linestring Features\n", linestrings);
+	  printf ("inserted %d Polygon Features\n", polygons);
+	  printf ("inserted %d MultiLinestring Features\n", multi_linestrings);
+	  printf ("inserted %d MultiPolygon Features\n", multi_polygons);
+	  if (!preserve_osm_tables)
+	      do_clean_map (&params);
+      }
+
+    if (in_memory)
+      {
+	  /* exporting the in-memory DB to filesystem */
+	  sqlite3 *disk_db_handle;
+	  sqlite3_backup *backup;
+	  int ret;
+	  printf ("\nexporting IN_MEMORY database ... wait please ...\n");
+	  ret =
+	      sqlite3_open_v2 (db_path, &disk_db_handle,
+			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+			       NULL);
+	  if (ret != SQLITE_OK)
+	    {
+		fprintf (stderr, "cannot open '%s': %s\n", db_path,
+			 sqlite3_errmsg (disk_db_handle));
+		sqlite3_close (disk_db_handle);
+		return -1;
+	    }
+	  backup = sqlite3_backup_init (disk_db_handle, "main", handle, "main");
+	  if (!backup)
+	    {
+		fprintf (stderr, "Backup failure: 'MEMORY-DB' wasn't saved\n");
+		sqlite3_close (handle);
+		sqlite3_close (disk_db_handle);
+		return -1;
+	    }
+	  while (1)
+	    {
+		ret = sqlite3_backup_step (backup, 1024);
+		if (ret == SQLITE_DONE)
+		    break;
+	    }
+	  ret = sqlite3_backup_finish (backup);
+	  sqlite3_close (handle);
+	  handle = disk_db_handle;
+	  printf ("\tIN_MEMORY database succesfully exported\n");
+      }
+
+/* closing the DB connection */
+    sqlite3_close (handle);
+    spatialite_cleanup_ex (cache);
+    spatialite_shutdown ();
+    downloader_cleanup (&downloader);
+    return 0;
+}
diff --git a/spatialite_xml_collapse.c b/spatialite_xml_collapse.c
index b94b76f..69b5102 100644
--- a/spatialite_xml_collapse.c
+++ b/spatialite_xml_collapse.c
@@ -25,6 +25,15 @@
 /
 */
 
+/*
+ 
+CREDITS:
+
+inital development of the XML tools has been funded by:
+Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
+
+*/
+
 #if defined(_WIN32) && !defined(__MINGW32__)
 /* MSVC strictly requires this include [off_t] */
 #include <sys/types.h>
diff --git a/spatialite_xml_load.c b/spatialite_xml_load.c
index 247d95a..9967510 100644
--- a/spatialite_xml_load.c
+++ b/spatialite_xml_load.c
@@ -24,6 +24,15 @@
 /
 */
 
+/*
+ 
+CREDITS:
+
+inital development of the XML tools has been funded by:
+Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
+
+*/
+
 #include <sys/time.h>
 
 #if defined(_WIN32) && !defined(__MINGW32__)
diff --git a/spatialite_xml_print.c b/spatialite_xml_print.c
index 8c155a0..75c4e49 100644
--- a/spatialite_xml_print.c
+++ b/spatialite_xml_print.c
@@ -24,6 +24,15 @@
 /
 */
 
+/*
+ 
+CREDITS:
+
+inital development of the XML tools has been funded by:
+Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
+
+*/
+
 #include <sys/time.h>
 
 #if defined(_WIN32) && !defined(__MINGW32__)
@@ -926,7 +935,7 @@ do_help ()
     fprintf (stderr,
 	     "-d or --db-path     pathname    the SpatiaLite DB [INPUT] path\n\n");
     fprintf (stderr,
-	     "-x or --xml-path pathname       the XML file [OUUPUT] path\n");
+	     "-x or --xml-path    pathname    the XML file [OUTPUT] path\n");
     fprintf (stderr,
 	     "-cs or --cache-size    num      DB cache size (how many pages)\n");
     fprintf (stderr,
diff --git a/spatialite_xml_validator.c b/spatialite_xml_validator.c
new file mode 100644
index 0000000..77e1593
--- /dev/null
+++ b/spatialite_xml_validator.c
@@ -0,0 +1,718 @@
+/* 
+/ spatialite_xml_validator
+/
+/ a tool performing XML schema validation 
+/
+/ version 1.0, 2014 October 28
+/
+/ Author: Sandro Furieri a.furieri at lqt.it
+/
+/ Copyright (C) 2013  Alessandro Furieri
+/
+/    This program is free software: you can redistribute it and/or modify
+/    it under the terms of the GNU General Public License as published by
+/    the Free Software Foundation, either version 3 of the License, or
+/    (at your option) any later version.
+/
+/    This program is distributed in the hope that it will be useful,
+/    but WITHOUT ANY WARRANTY; without even the implied warranty of
+/    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+/    GNU General Public License for more details.
+/
+/    You should have received a copy of the GNU General Public License
+/    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#include <libxml/parser.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+struct list_item
+{
+/* a file path to be validated */
+    char *path;
+    struct list_item *next;
+};
+
+struct list_of_files
+{
+/* a list of files */
+    struct list_item *first;
+    struct list_item *last;
+};
+
+struct schema_cached_item
+{
+/* a cached XSD item */
+    char *schemaURI;
+    xmlDocPtr schema_doc;
+    xmlSchemaParserCtxtPtr parser_ctxt;
+    xmlSchemaPtr schema;
+    struct schema_cached_item *next;
+};
+
+struct schema_cache
+{
+/* a cache storing XSD schemata */
+    struct schema_cached_item *first;
+    struct schema_cached_item *last;
+};
+
+struct ns_vxpath
+{
+/* a Namespace definition */
+    char *Prefix;
+    char *Href;
+    struct ns_vxpath *Next;
+};
+
+struct namespaces_vxpath
+{
+/* Namespace container */
+    struct ns_vxpath *First;
+    struct ns_vxpath *Last;
+};
+
+static void
+add_cached_xsd (struct schema_cache *cache, const char *schemaURI,
+		xmlDocPtr schema_doc, xmlSchemaParserCtxtPtr parser_ctxt,
+		xmlSchemaPtr schema)
+{
+/* adding an XSD item to the cache */
+    int len;
+    struct schema_cached_item *p = malloc (sizeof (struct schema_cached_item));
+    len = strlen (schemaURI);
+    p->schemaURI = malloc (len + 1);
+    strcpy (p->schemaURI, schemaURI);
+    p->schema_doc = schema_doc;
+    p->parser_ctxt = parser_ctxt;
+    p->schema = schema;
+    p->next = NULL;
+    if (cache->first == NULL)
+	cache->first = p;
+    if (cache->last != NULL)
+	cache->last->next = p;
+    cache->last = p;
+}
+
+static void
+cache_cleanup (struct schema_cache *cache)
+{
+/* memory cleanup - freeing the XSD cache */
+    struct schema_cached_item *p;
+    struct schema_cached_item *pn;
+    p = cache->first;
+    while (p != NULL)
+      {
+	  pn = p->next;
+	  free (p->schemaURI);
+	  xmlSchemaFreeParserCtxt (p->parser_ctxt);
+	  xmlSchemaFree (p->schema);
+	  xmlFreeDoc (p->schema_doc);
+	  free (p);
+	  p = pn;
+      }
+}
+
+static struct schema_cached_item *
+find_cached_schema (struct schema_cache *cache, const char *schemaURI)
+{
+/* attempting to retrieve a cached XSD */
+    struct schema_cached_item *p = cache->first;
+    while (p != NULL)
+      {
+	  if (strcmp (p->schemaURI, schemaURI) == 0)
+	      return p;
+	  p = p->next;
+      }
+    return NULL;
+}
+
+static void
+list_cleanup (struct list_of_files *list)
+{
+/* memory cleanup - freeing the list */
+    struct list_item *item;
+    struct list_item *item_n;
+    item = list->first;
+    while (item != NULL)
+      {
+	  item_n = item->next;
+	  free (item->path);
+	  free (item);
+	  item = item_n;
+      }
+    free (list);
+}
+
+static void
+clean_cr (char *path)
+{
+/* removing trailing CR/LF characters */
+    int len = strlen (path);
+    char *p = path + len - 1;
+    while (p > path)
+      {
+	  if (*p == '\r' || *p == '\n')
+	      *p-- = '\0';
+	  else
+	      break;
+      }
+}
+
+static char *
+my_getline (FILE * in)
+{
+/* reading a whole line */
+    int c;
+    char *buf = malloc (1024 * 1024);
+    char *p = buf;
+    while ((c = getc (in)) != EOF)
+      {
+	  *p++ = c;
+	  if (c == '\n')
+	      break;
+      }
+    if (p == buf)
+      {
+	  free (buf);
+	  return NULL;
+      }
+    *p = '\0';
+    return buf;
+}
+
+static struct list_of_files *
+parse_list (const char *path)
+{
+/* parsing a file containing a list of file-paths */
+    char *line = NULL;
+    int count = 0;
+    struct list_item *item;
+    struct list_of_files *list = malloc (sizeof (struct list_of_files));
+    FILE *in = fopen (path, "rb");
+    if (in == NULL)
+	return NULL;
+    list->first = NULL;
+    list->last = NULL;
+
+    while ((line = my_getline (in)) != NULL)
+      {
+	  int len;
+	  item = malloc (sizeof (struct list_item));
+	  clean_cr (line);
+	  len = strlen (line);
+	  item->path = malloc (len + 1);
+	  strcpy (item->path, line);
+	  item->next = NULL;
+	  if (list->first == NULL)
+	      list->first = item;
+	  if (list->last != NULL)
+	      list->last->next = item;
+	  list->last = item;
+	  free (line);
+	  line = NULL;
+      }
+
+/* final check */
+    item = list->first;
+    while (item != NULL)
+      {
+	  count++;
+	  item = item->next;
+      }
+    if (count == 0)
+      {
+	  list_cleanup (list);
+	  return NULL;
+      }
+    return list;
+}
+
+static void
+free_vxpath_ns (struct ns_vxpath *ns)
+{
+/* memory cleanup - destroying a Namespace item */
+    if (!ns)
+	return;
+    if (ns->Prefix)
+	free (ns->Prefix);
+    if (ns->Href)
+	free (ns->Href);
+    free (ns);
+}
+
+static void
+free_vxpath_namespaces (struct namespaces_vxpath *ns_list)
+{
+/* memory cleanup - destroying the Namespaces list */
+    struct ns_vxpath *ns;
+    struct ns_vxpath *nns;
+    if (!ns_list)
+	return;
+    ns = ns_list->First;
+    while (ns)
+      {
+	  nns = ns->Next;
+	  free_vxpath_ns (ns);
+	  ns = nns;
+      }
+    free (ns_list);
+}
+
+static void
+add_vxpath_ns (struct namespaces_vxpath *ns_list, const char *prefix,
+	       const char *href)
+{
+/* inserting a further Namespace into the list */
+    int len;
+    struct ns_vxpath *ns = ns_list->First;
+    while (ns)
+      {
+	  /* checking if it's already defined */
+	  if (ns->Prefix == NULL || prefix == NULL)
+	    {
+		if (ns->Prefix == NULL && prefix == NULL
+		    && strcmp (ns->Href, href) == 0)
+		  {
+		      /* ok, already defined (default Namespace) */
+		      return;
+		  }
+	    }
+	  else
+	    {
+		if (strcmp (ns->Prefix, prefix) == 0
+		    && strcmp (ns->Href, href) == 0)
+		  {
+		      /* ok, already defined */
+		      return;
+		  }
+	    }
+	  ns = ns->Next;
+      }
+
+/* inserting a new Namespace */
+    ns = malloc (sizeof (struct ns_vxpath));
+    if (prefix == NULL)
+	ns->Prefix = NULL;
+    else
+      {
+	  len = strlen (prefix);
+	  ns->Prefix = malloc (len + 1);
+	  strcpy (ns->Prefix, prefix);
+      }
+    len = strlen (href);
+    ns->Href = malloc (len + 1);
+    strcpy (ns->Href, href);
+    ns->Next = NULL;
+    if (ns_list->First == NULL)
+	ns_list->First = ns;
+    if (ns_list->Last != NULL)
+	ns_list->Last->Next = ns;
+    ns_list->Last = ns;
+}
+
+static void
+feed_vxpath_ns (struct namespaces_vxpath *ns_list, xmlNodePtr start)
+{
+/* recursively searching for Namespaces */
+    xmlNodePtr node = start;
+    while (node)
+      {
+	  if (node->ns != NULL)
+	    {
+		/* a Namespace is defined */
+		add_vxpath_ns (ns_list, (const char *) (node->ns->prefix),
+			       (const char *) (node->ns->href));
+	    }
+	  if (node->properties != NULL)
+	    {
+		/* exploring the Attribute list */
+		struct _xmlAttr *attr = node->properties;
+		while (attr)
+		  {
+		      if (attr->type == XML_ATTRIBUTE_NODE)
+			{
+			    if (attr->ns != NULL)
+			      {
+				  /* a Namespace is defined */
+				  add_vxpath_ns (ns_list,
+						 (const char *) (attr->
+								 ns->prefix),
+						 (const char *) (attr->
+								 ns->href));
+			      }
+			}
+		      attr = attr->next;
+		  }
+	    }
+	  feed_vxpath_ns (ns_list, node->children);
+	  node = node->next;
+      }
+}
+
+static struct namespaces_vxpath *
+get_vxpath_namespaces (void *p_xml_doc)
+{
+/* creating and populating the Namespaces list */
+    xmlDocPtr xml_doc = (xmlDocPtr) p_xml_doc;
+    xmlNodePtr root = xmlDocGetRootElement (xml_doc);
+    struct namespaces_vxpath *ns_list;
+    ns_list = malloc (sizeof (struct namespaces_vxpath));
+    ns_list->First = NULL;
+    ns_list->Last = NULL;
+    feed_vxpath_ns (ns_list, root);
+    return ns_list;
+}
+
+static int
+eval_vxpath_expr (xmlDocPtr xml_doc, const char *xpath_expr,
+		  xmlXPathContextPtr * p_xpathCtx,
+		  xmlXPathObjectPtr * p_xpathObj)
+{
+/* evaluating an XPath expression */
+    xmlXPathObjectPtr xpathObj;
+    xmlXPathContextPtr xpathCtx;
+/* attempting to identify all required Namespaces */
+    struct ns_vxpath *ns;
+    struct namespaces_vxpath *ns_list = get_vxpath_namespaces (xml_doc);
+/* creating an XPath context */
+    xpathCtx = xmlXPathNewContext (xml_doc);
+    if (xpathCtx == NULL)
+	return 0;
+/* registering all Namespaces */
+    if (xpathCtx != NULL && ns_list != NULL)
+      {
+	  ns = ns_list->First;
+	  while (ns)
+	    {
+		if (ns->Prefix == NULL)
+		  {
+		      /* the default Namespace always is "dflt:xx" */
+		      xmlXPathRegisterNs (xpathCtx, (xmlChar *) "dflt",
+					  (xmlChar *) ns->Href);
+		  }
+		else
+		  {
+		      /* a fully qualified Namespace */
+		      xmlXPathRegisterNs (xpathCtx, (xmlChar *) ns->Prefix,
+					  (xmlChar *) ns->Href);
+		  }
+		ns = ns->Next;
+	    }
+      }
+    free_vxpath_namespaces (ns_list);
+/* evaluating the XPath expression */
+    xpathObj = xmlXPathEvalExpression ((const xmlChar *) xpath_expr, xpathCtx);
+    if (xpathObj != NULL)
+      {
+	  xmlNodeSetPtr nodes = xpathObj->nodesetval;
+	  int num_nodes = (nodes) ? nodes->nodeNr : 0;
+	  if (num_nodes >= 1)
+	    {
+		/* OK: match found */
+		*p_xpathCtx = xpathCtx;
+		*p_xpathObj = xpathObj;
+		xmlSetGenericErrorFunc ((void *) stderr, NULL);
+		return 1;
+	    }
+	  /* invalid: empty nodeset */
+	  xmlXPathFreeObject (xpathObj);
+      }
+    xmlXPathFreeContext (xpathCtx);
+    xmlSetGenericErrorFunc ((void *) stderr, NULL);
+    return 0;
+}
+
+static char *
+get_schema_uri (xmlDocPtr xml_doc)
+{
+/* Return the internally defined SchemaURI from a valid XmlDocument */
+    char *uri = NULL;
+    xmlXPathContextPtr xpathCtx;
+    xmlXPathObjectPtr xpathObj;
+/* retrieving the XMLDocument internal SchemaURI (if any) */
+    if (eval_vxpath_expr
+	(xml_doc, "/*/@xsi:schemaLocation", &xpathCtx, &xpathObj))
+      {
+	  /* attempting first to extract xsi:schemaLocation */
+	  xmlNodeSetPtr nodeset = xpathObj->nodesetval;
+	  xmlNodePtr node;
+	  int num_nodes = (nodeset) ? nodeset->nodeNr : 0;
+	  if (num_nodes == 1)
+	    {
+		node = nodeset->nodeTab[0];
+		if (node->type == XML_ATTRIBUTE_NODE)
+		  {
+		      if (node->children != NULL)
+			{
+			    if (node->children->content != NULL)
+			      {
+				  const char *str =
+				      (const char *) (node->children->content);
+				  const char *ptr = str;
+				  int i;
+				  int len = strlen (str);
+				  for (i = len - 1; i >= 0; i--)
+				    {
+					if (*(str + i) == ' ')
+					  {
+					      /* last occurrence of SPACE [namespace/schema separator] */
+					      ptr = str + i + 1;
+					      break;
+					  }
+				    }
+				  len = strlen (ptr);
+				  uri = malloc (len + 1);
+				  strcpy (uri, ptr);
+			      }
+			}
+		  }
+	    }
+	  if (uri != NULL)
+	      xmlXPathFreeContext (xpathCtx);
+	  xmlXPathFreeObject (xpathObj);
+      }
+    if (uri == NULL)
+      {
+	  /* checking for xsi:noNamespaceSchemaLocation */
+	  if (eval_vxpath_expr
+	      (xml_doc, "/*/@xsi:noNamespaceSchemaLocation", &xpathCtx,
+	       &xpathObj))
+	    {
+		xmlNodeSetPtr nodeset = xpathObj->nodesetval;
+		xmlNodePtr node;
+		int num_nodes = (nodeset) ? nodeset->nodeNr : 0;
+		if (num_nodes == 1)
+		  {
+		      node = nodeset->nodeTab[0];
+		      if (node->type == XML_ATTRIBUTE_NODE)
+			{
+			    if (node->children != NULL)
+			      {
+				  if (node->children->content != NULL)
+				    {
+					int len =
+					    strlen ((const char *)
+						    node->children->content);
+					uri = malloc (len + 1);
+					strcpy (uri,
+						(const char *) node->
+						children->content);
+				    }
+			      }
+			}
+		  }
+		xmlXPathFreeContext (xpathCtx);
+		xmlXPathFreeObject (xpathObj);
+	    }
+      }
+
+    return uri;
+}
+
+static int
+validate_xml_document (struct schema_cache *cache, const char *path)
+{
+/* validating a single XML document */
+    char *schemaURI = NULL;
+    xmlDocPtr xml_doc = NULL;
+    xmlSchemaPtr schema = NULL;
+    xmlSchemaValidCtxtPtr valid_ctxt = NULL;
+    xmlDocPtr xschema_doc = NULL;
+    xmlSchemaPtr xschema = NULL;
+    xmlSchemaParserCtxtPtr xparser_ctxt = NULL;
+    struct schema_cached_item *saved;
+    int new_schema;
+    fprintf (stderr, "validating %s\n", path);
+    fprintf (stderr, "----------------------------------------------------\n");
+    fprintf (stderr, "step #1) checking if the XML document is well formed\n");
+/* testing if the XMLDocument is well-formed */
+    xml_doc = xmlReadFile (path, NULL, XML_PARSE_BIG_LINES);
+    if (xml_doc == NULL)
+      {
+	  /* parsing error; not a well-formed XML */
+	  fprintf (stderr, "XML parsing error\n");
+	  goto error;
+      }
+    fprintf (stderr, "\tYES: well-formedness confirmed\n");
+    fprintf (stderr,
+	     "step #2) attempting to identify the Schema Definition URI\n");
+/* attempting to extract the Schema URI from the XML document itself */
+    schemaURI = get_schema_uri (xml_doc);
+    if (schemaURI == NULL)
+      {
+	  fprintf (stderr,
+		   "the XML Document does not contains any Schema declaration\n");
+	  goto error;
+      }
+    fprintf (stderr, "\tXSD-URI: %s\n", schemaURI);
+    saved = find_cached_schema (cache, schemaURI);
+    if (saved == NULL)
+      {
+	  /* not already cache XSD */
+	  new_schema = 1;
+	  fprintf (stderr,
+		   "step #3) attempting to load and parse the XML Schema Definition (XSD)\n");
+/* preparing the XML Schema */
+	  xschema_doc = xmlReadFile (schemaURI, NULL, XML_PARSE_BIG_LINES);
+	  if (xschema_doc == NULL)
+	    {
+		fprintf (stderr, "unable to load the XML Schema\n");
+		goto error;
+	    }
+	  xparser_ctxt = xmlSchemaNewDocParserCtxt (xschema_doc);
+	  if (xparser_ctxt == NULL)
+	    {
+		fprintf (stderr, "unable to prepare the XML Schema Context\n");
+		goto error;
+	    }
+	  xschema = xmlSchemaParse (xparser_ctxt);
+	  if (xschema == NULL)
+	    {
+		fprintf (stderr, "invalid XML Schema\n");
+		goto error;
+	    }
+	  fprintf (stderr, "\tXSD ready\n");
+	  if (new_schema)
+	    {
+		/* saving the schema into the cache */
+		add_cached_xsd (cache, schemaURI, xschema_doc, xparser_ctxt,
+				xschema);
+		xschema_doc = NULL;
+		xparser_ctxt = NULL;
+		schema = xschema;
+		xschema = NULL;
+	    }
+      }
+    else
+      {
+	  /* already cached XSD */
+	  fprintf (stderr, "step #3) already cached XSD\n");
+	  schema = saved->schema;
+      }
+
+    fprintf (stderr,
+	     "step #4) attempting to validate for Schema conformance\n");
+/* Schema validation */
+    valid_ctxt = xmlSchemaNewValidCtxt (schema);
+    if (valid_ctxt == NULL)
+      {
+	  fprintf (stderr, "unable to prepare a validation context\n");
+	  goto error;
+      }
+    if (xmlSchemaValidateDoc (valid_ctxt, xml_doc) != 0)
+      {
+	  fprintf (stderr, "Schema validation failed\n");
+	  goto error;
+      }
+    fprintf (stderr, "\tOK: XML Schema validation successfully verified\n\n");
+    xmlSchemaFreeValidCtxt (valid_ctxt);
+    xmlFreeDoc (xml_doc);
+    free (schemaURI);
+    return 1;
+  error:
+    if (valid_ctxt != NULL)
+	xmlSchemaFreeValidCtxt (valid_ctxt);
+    if (xparser_ctxt != NULL)
+	xmlSchemaFreeParserCtxt (xparser_ctxt);
+    if (xschema != NULL)
+	xmlSchemaFree (xschema);
+    if (xschema_doc != NULL)
+	xmlFreeDoc (xschema_doc);
+    if (xml_doc != NULL)
+	xmlFreeDoc (xml_doc);
+    if (schemaURI != NULL)
+	free (schemaURI);
+    fprintf (stderr, "ERROR - invalid XML: %s\n\n", path);
+    return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+    const char *xml_path = NULL;
+    const char *list_path = NULL;
+    int single = 0;
+    int list = 0;
+    int err = 1;
+    int valids = 0;
+    int invalids = 0;
+    struct schema_cache cache;
+    cache.first = NULL;
+    cache.last = NULL;
+    if (argc == 3)
+      {
+	  if (strcmp (argv[1], "-f") == 0)
+	    {
+		single = 1;
+		xml_path = argv[2];
+		err = 0;
+	    }
+	  else if (strcmp (argv[1], "-l") == 0)
+	    {
+		list = 1;
+		list_path = argv[2];
+		err = 0;
+	    }
+      }
+    if (err)
+      {
+	  /* printing the argument list and quitting */
+	  fprintf (stderr, "\n\nusage: spatialite_xml_validate -f xml-path\n");
+	  fprintf (stderr,
+		   "   or: spatialite_xml_validate -l list-of-paths-file\n");
+	  goto error;
+      }
+
+    fprintf (stderr, "libxml2 version: %s\n\n", LIBXML_DOTTED_VERSION);
+    if (single)
+      {
+	  int ret = validate_xml_document (&cache, xml_path);
+	  if (ret)
+	      valids++;
+	  else
+	      invalids++;
+      }
+    if (list)
+      {
+	  struct list_item *item;
+	  struct list_of_files *xml_list = parse_list (list_path);
+	  if (xml_list == NULL)
+	    {
+		fprintf (stderr, "Invalid list-file: %s\n", list_path);
+		goto error;
+	    }
+	  item = xml_list->first;
+	  while (item != NULL)
+	    {
+		int ret = validate_xml_document (&cache, item->path);
+		if (ret)
+		    valids++;
+		else
+		    invalids++;
+		item = item->next;
+	    }
+	  list_cleanup (xml_list);
+      }
+
+    fprintf (stderr,
+	     "====================\n  Valid XML documents: %d\nInvalid XML documents: %d\n\n",
+	     valids, invalids);
+    cache_cleanup (&cache);
+    xmlCleanupParser ();
+    return 0;
+  error:
+    cache_cleanup (&cache);
+    xmlCleanupParser ();
+    return -1;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/spatialite-tools.git



More information about the Pkg-grass-devel mailing list