[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, ×tamp, &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 (¶ms))
+ {
+ sqlite3_close (handle);
+ return -1;
+ }
+/* creating the SQL prepared statements */
+ create_sql_stmts (¶ms, 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 (¶ms, tile, 0))
+ {
+ fprintf (stderr,
+ "\noperation aborted due to unrecoverable errors\n\n");
+ finalize_sql_stmts (¶ms);
+ 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 (¶ms, tile, OBJ_NODES))
+ {
+ fprintf (stderr,
+ "\noperation aborted due to unrecoverable errors\n\n");
+ finalize_sql_stmts (¶ms);
+ sqlite3_close (handle);
+ return -1;
+ }
+ printf
+ ("Downloading and parsing OSM tile %d of %d - Ways \r",
+ tile->tile_no, downloader.count);
+ if (!osm_parse (¶ms, tile, OBJ_WAYS))
+ {
+ fprintf (stderr,
+ "\noperation aborted due to unrecoverable errors\n\n");
+ finalize_sql_stmts (¶ms);
+ sqlite3_close (handle);
+ return -1;
+ }
+ printf
+ ("Downloading and parsing OSM tile %d of %d - Relations \r",
+ tile->tile_no, downloader.count);
+ if (!osm_parse (¶ms, tile, OBJ_RELATIONS))
+ {
+ fprintf (stderr,
+ "\noperation aborted due to unrecoverable errors\n\n");
+ finalize_sql_stmts (¶ms);
+ sqlite3_close (handle);
+ return -1;
+ }
+ }
+ tile = tile->next;
+ }
+ printf ("Download completed \n");
+
+/* finalizing SQL prepared statements */
+ finalize_sql_stmts (¶ms);
+
+/* 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 (¶ms))
+ {
+ sqlite3_close (handle);
+ return -1;
+ }
+ if (!populate_road_network (¶ms, &cnt_nodes, &cnt_arcs))
+ {
+ sqlite3_close (handle);
+ return -1;
+ }
+ if (!create_road_rtrees (¶ms))
+ {
+ 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 (¶ms);
+ }
+ 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 (¶ms))
+ {
+ sqlite3_close (handle);
+ return -1;
+ }
+ if (!populate_rail_network
+ (¶ms, &cnt_nodes, &cnt_arcs, &cnt_stations))
+ {
+ sqlite3_close (handle);
+ return -1;
+ }
+ if (!create_rail_rtrees (¶ms))
+ {
+ 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 (¶ms);
+ }
+ 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 (¶ms))
+ {
+ sqlite3_close (handle);
+ return -1;
+ }
+ if (!populate_map_layers
+ (¶ms, &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 (¶ms);
+ }
+
+ 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