[spatialite-tools] 01/01: Imported Upstream version 4.2.0
Bas Couwenberg
sebastic at xs4all.nl
Mon Aug 4 01:35:20 UTC 2014
This is an automated email from the git hooks/post-receive script.
sebastic-guest pushed a commit to branch upstream
in repository spatialite-tools.
commit 2717972969204541096102491a55a5f0a84b0619
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Mon Aug 4 00:14:39 2014 +0200
Imported Upstream version 4.2.0
---
Makefile-static-MinGW | 63 +-
Makefile.am | 21 +-
Makefile.in | 320 +++--
aclocal.m4 | 381 +++---
configure | 82 +-
configure.ac | 2 +-
exif_loader.c | 1 +
shell.c | 111 +-
spatialite_convert.c | 85 +-
spatialite_dxf.c | 3 +-
spatialite_gml.c | 1 +
spatialite_network.c | 1 +
spatialite_osm_filter.c | 1 +
spatialite_osm_map.c | 31 +-
spatialite_osm_net.c | 1 +
spatialite_osm_raw.c | 1 +
spatialite_tool.c | 1 +
spatialite_xml_collapse.c | 2408 ++++++++++++++++++++++++++++++++++++++
spatialite_xml_load.c | 2837 +++++++++++++++++++++++++++++++++++++++++++++
spatialite_xml_print.c | 1063 +++++++++++++++++
20 files changed, 7105 insertions(+), 309 deletions(-)
diff --git a/Makefile-static-MinGW b/Makefile-static-MinGW
index b551367..46685de 100644
--- a/Makefile-static-MinGW
+++ b/Makefile-static-MinGW
@@ -10,7 +10,10 @@ all: ./static_bin/spatialite.exe ./static_bin/spatialite_tool.exe \
./static_bin/exif_loader.exe ./static_bin/spatialite_osm_net.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_convert.exe ./static_bin/spatialite_dxf.exe \
+ ./static_bin/spatialite_xml_collapse.exe \
+ ./static_bin/spatialite_xml_load.exe \
+ ./static_bin/spatialite_xml_print.exe
./static_bin/spatialite.exe: shell.o
$(GG) shell.o -o ./static_bin/spatialite.exe \
@@ -214,6 +217,55 @@ 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_xml_collapse.exe: spatialite_xml_collapse.o
+ $(GG) spatialite_xml_collapse.o -o ./static_bin/spatialite_xml_collapse.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_xml_collapse.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 \
+ /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/libexpat.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_xml_load.exe
+
+./static_bin/spatialite_xml_print.exe: spatialite_xml_print.o
+ $(GG) spatialite_xml_print.o -o ./static_bin/spatialite_xml_print.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_xml_print.exe
+
shell.o:
$(CC) $(CFLAGS) shell.c -c
@@ -243,3 +295,12 @@ spatialite_osm_raw.o:
spatialite_osm_filter.o:
$(CC) $(CFLAGS) spatialite_osm_filter.c -c
+
+spatialite_xml_collapse.o:
+ $(CC) $(CFLAGS) spatialite_xml_collapse.c -c
+
+spatialite_xml_load.o:
+ $(CC) $(CFLAGS) spatialite_xml_load.c -c
+
+spatialite_xml_print.o:
+ $(CC) $(CFLAGS) spatialite_xml_print.c -c
diff --git a/Makefile.am b/Makefile.am
index 0e719c7..d9a52aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,10 @@ bin_PROGRAMS = spatialite \
spatialite_osm_filter \
spatialite_gml \
spatialite_convert \
- spatialite_dxf
+ spatialite_dxf \
+ spatialite_xml_load \
+ spatialite_xml_collapse \
+ spatialite_xml_print
else
bin_PROGRAMS = spatialite \
spatialite_tool \
@@ -22,17 +25,23 @@ bin_PROGRAMS = spatialite \
spatialite_osm_filter \
spatialite_gml \
spatialite_convert \
- spatialite_dxf
+ spatialite_dxf \
+ spatialite_xml_load \
+ spatialite_xml_collapse \
+ spatialite_xml_print
endif
-INCLUDES = @CFLAGS@
-INCLUDES += -I$(top_srcdir)
+AM_CPPFLAGS = @CFLAGS@
+AM_CPPFLAGS += -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_load_SOURCES = spatialite_xml_load.c
+spatialite_xml_collapse_SOURCES = spatialite_xml_collapse.c
+spatialite_xml_print_SOURCES = spatialite_xml_print.c
if NO_READOSM
else
spatialite_osm_net_SOURCES = spatialite_osm_net.c
@@ -54,6 +63,10 @@ spatialite_gml_LDADD = @LIBSPATIALITE_LIBS@ \
spatialite_LDADD = @LIBSPATIALITE_LIBS@ \
@LIBFREEXL_LIBS@ \
@READLINE_LIBS@
+spatialite_xml_load_LDADD = @LIBSPATIALITE_LIBS@ \
+ -lexpat
+spatialite_xml_collapse_LDADD = @LIBSPATIALITE_LIBS@
+spatialite_xml_print_LADD = @LIBSPATIALIATE_LIBS@
LDADD = @LIBSPATIALITE_LIBS@ \
@LIBFREEXL_LIBS@
diff --git a/Makefile.in b/Makefile.in
index e91a652..c5c87bf 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -15,23 +15,51 @@
@SET_MAKE@
VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
- *) \
- for am__flg in $$MAKEFLAGS; do \
- case $$am__flg in \
- *=*|--*) ;; \
- *n*) am__dry=yes; break;; \
- esac; \
- done;; \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
esac; \
- test $$am__dry = yes; \
- }
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -60,7 +88,10 @@ host_triplet = @host@
@NO_READOSM_FALSE@ spatialite_osm_filter$(EXEEXT) \
@NO_READOSM_FALSE@ spatialite_gml$(EXEEXT) \
@NO_READOSM_FALSE@ spatialite_convert$(EXEEXT) \
- at NO_READOSM_FALSE@ spatialite_dxf$(EXEEXT)
+ at NO_READOSM_FALSE@ spatialite_dxf$(EXEEXT) \
+ at NO_READOSM_FALSE@ spatialite_xml_load$(EXEEXT) \
+ at NO_READOSM_FALSE@ spatialite_xml_collapse$(EXEEXT) \
+ at NO_READOSM_FALSE@ spatialite_xml_print$(EXEEXT)
@NO_READOSM_TRUE at bin_PROGRAMS = spatialite$(EXEEXT) \
@NO_READOSM_TRUE@ spatialite_tool$(EXEEXT) \
@NO_READOSM_TRUE@ spatialite_network$(EXEEXT) \
@@ -68,12 +99,16 @@ host_triplet = @host@
@NO_READOSM_TRUE@ spatialite_osm_filter$(EXEEXT) \
@NO_READOSM_TRUE@ spatialite_gml$(EXEEXT) \
@NO_READOSM_TRUE@ spatialite_convert$(EXEEXT) \
- at NO_READOSM_TRUE@ spatialite_dxf$(EXEEXT)
+ at NO_READOSM_TRUE@ spatialite_dxf$(EXEEXT) \
+ at NO_READOSM_TRUE@ spatialite_xml_load$(EXEEXT) \
+ at NO_READOSM_TRUE@ spatialite_xml_collapse$(EXEEXT) \
+ at NO_READOSM_TRUE@ spatialite_xml_print$(EXEEXT)
subdir = .
-DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in $(srcdir)/config.h.in \
- $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
- config.guess config.sub depcomp install-sh ltmain.sh missing
+DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
+ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/configure $(am__configure_deps) \
+ $(srcdir)/config.h.in depcomp COPYING config.guess config.sub \
+ install-sh missing ltmain.sh
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@@ -93,6 +128,10 @@ am_exif_loader_OBJECTS = exif_loader.$(OBJEXT)
exif_loader_OBJECTS = $(am_exif_loader_OBJECTS)
exif_loader_LDADD = $(LDADD)
exif_loader_DEPENDENCIES =
+AM_V_lt = $(am__v_lt_ at AM_V@)
+am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
am_shp_doctor_OBJECTS = shp_doctor.$(OBJEXT)
shp_doctor_OBJECTS = $(am_shp_doctor_OBJECTS)
shp_doctor_LDADD = $(LDADD)
@@ -138,25 +177,59 @@ am_spatialite_tool_OBJECTS = spatialite_tool.$(OBJEXT)
spatialite_tool_OBJECTS = $(am_spatialite_tool_OBJECTS)
spatialite_tool_LDADD = $(LDADD)
spatialite_tool_DEPENDENCIES =
+am_spatialite_xml_collapse_OBJECTS = \
+ spatialite_xml_collapse.$(OBJEXT)
+spatialite_xml_collapse_OBJECTS = \
+ $(am_spatialite_xml_collapse_OBJECTS)
+spatialite_xml_collapse_DEPENDENCIES =
+am_spatialite_xml_load_OBJECTS = spatialite_xml_load.$(OBJEXT)
+spatialite_xml_load_OBJECTS = $(am_spatialite_xml_load_OBJECTS)
+spatialite_xml_load_DEPENDENCIES =
+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_V_P = $(am__v_P_ at AM_V@)
+am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_ at AM_V@)
+am__v_GEN_ = $(am__v_GEN_ at AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_ at AM_V@)
+am__v_at_ = $(am__v_at_ at AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
DEFAULT_INCLUDES = -I. at am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_ at AM_V@)
+am__v_CC_ = $(am__v_CC_ at AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
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_tool_SOURCES) $(spatialite_xml_collapse_SOURCES) \
+ $(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES)
DIST_SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
$(spatialite_SOURCES) spatialite_convert.c spatialite_dxf.c \
$(spatialite_gml_SOURCES) $(spatialite_network_SOURCES) \
@@ -164,12 +237,31 @@ DIST_SOURCES = $(exif_loader_SOURCES) $(shp_doctor_SOURCES) \
$(am__spatialite_osm_map_SOURCES_DIST) \
$(am__spatialite_osm_net_SOURCES_DIST) \
$(am__spatialite_osm_raw_SOURCES_DIST) \
- $(spatialite_tool_SOURCES)
+ $(spatialite_tool_SOURCES) $(spatialite_xml_collapse_SOURCES) \
+ $(spatialite_xml_load_SOURCES) $(spatialite_xml_print_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+ $(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
@@ -193,6 +285,7 @@ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
@@ -325,12 +418,15 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I m4
-INCLUDES = @CFLAGS@ -I$(top_srcdir)
+AM_CPPFLAGS = @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_load_SOURCES = spatialite_xml_load.c
+spatialite_xml_collapse_SOURCES = spatialite_xml_collapse.c
+spatialite_xml_print_SOURCES = spatialite_xml_print.c
@NO_READOSM_FALSE at spatialite_osm_net_SOURCES = spatialite_osm_net.c
@NO_READOSM_FALSE at spatialite_osm_map_SOURCES = spatialite_osm_map.c
@NO_READOSM_FALSE at spatialite_osm_raw_SOURCES = spatialite_osm_raw.c
@@ -353,6 +449,11 @@ spatialite_LDADD = @LIBSPATIALITE_LIBS@ \
@LIBFREEXL_LIBS@ \
@READLINE_LIBS@
+spatialite_xml_load_LDADD = @LIBSPATIALITE_LIBS@ \
+ -lexpat
+
+spatialite_xml_collapse_LDADD = @LIBSPATIALITE_LIBS@
+spatialite_xml_print_LADD = @LIBSPATIALIATE_LIBS@
LDADD = @LIBSPATIALITE_LIBS@ \
@LIBFREEXL_LIBS@
@@ -426,10 +527,12 @@ install-binPROGRAMS: $(bin_PROGRAMS)
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
- while read p p1; do if test -f $$p || test -f $$p1; \
- then echo "$$p"; echo "$$p"; else :; fi; \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
- sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
@@ -450,7 +553,8 @@ uninstall-binPROGRAMS:
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
- -e 's/$$/$(EXEEXT)/' `; \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && rm -f $$files
@@ -463,42 +567,66 @@ clean-binPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
+
exif_loader$(EXEEXT): $(exif_loader_OBJECTS) $(exif_loader_DEPENDENCIES) $(EXTRA_exif_loader_DEPENDENCIES)
@rm -f exif_loader$(EXEEXT)
- $(LINK) $(exif_loader_OBJECTS) $(exif_loader_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(exif_loader_OBJECTS) $(exif_loader_LDADD) $(LIBS)
+
shp_doctor$(EXEEXT): $(shp_doctor_OBJECTS) $(shp_doctor_DEPENDENCIES) $(EXTRA_shp_doctor_DEPENDENCIES)
@rm -f shp_doctor$(EXEEXT)
- $(LINK) $(shp_doctor_OBJECTS) $(shp_doctor_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(shp_doctor_OBJECTS) $(shp_doctor_LDADD) $(LIBS)
+
spatialite$(EXEEXT): $(spatialite_OBJECTS) $(spatialite_DEPENDENCIES) $(EXTRA_spatialite_DEPENDENCIES)
@rm -f spatialite$(EXEEXT)
- $(LINK) $(spatialite_OBJECTS) $(spatialite_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_OBJECTS) $(spatialite_LDADD) $(LIBS)
+
spatialite_convert$(EXEEXT): $(spatialite_convert_OBJECTS) $(spatialite_convert_DEPENDENCIES) $(EXTRA_spatialite_convert_DEPENDENCIES)
@rm -f spatialite_convert$(EXEEXT)
- $(LINK) $(spatialite_convert_OBJECTS) $(spatialite_convert_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_convert_OBJECTS) $(spatialite_convert_LDADD) $(LIBS)
+
spatialite_dxf$(EXEEXT): $(spatialite_dxf_OBJECTS) $(spatialite_dxf_DEPENDENCIES) $(EXTRA_spatialite_dxf_DEPENDENCIES)
@rm -f spatialite_dxf$(EXEEXT)
- $(LINK) $(spatialite_dxf_OBJECTS) $(spatialite_dxf_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_dxf_OBJECTS) $(spatialite_dxf_LDADD) $(LIBS)
+
spatialite_gml$(EXEEXT): $(spatialite_gml_OBJECTS) $(spatialite_gml_DEPENDENCIES) $(EXTRA_spatialite_gml_DEPENDENCIES)
@rm -f spatialite_gml$(EXEEXT)
- $(LINK) $(spatialite_gml_OBJECTS) $(spatialite_gml_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_gml_OBJECTS) $(spatialite_gml_LDADD) $(LIBS)
+
spatialite_network$(EXEEXT): $(spatialite_network_OBJECTS) $(spatialite_network_DEPENDENCIES) $(EXTRA_spatialite_network_DEPENDENCIES)
@rm -f spatialite_network$(EXEEXT)
- $(LINK) $(spatialite_network_OBJECTS) $(spatialite_network_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_network_OBJECTS) $(spatialite_network_LDADD) $(LIBS)
+
spatialite_osm_filter$(EXEEXT): $(spatialite_osm_filter_OBJECTS) $(spatialite_osm_filter_DEPENDENCIES) $(EXTRA_spatialite_osm_filter_DEPENDENCIES)
@rm -f spatialite_osm_filter$(EXEEXT)
- $(LINK) $(spatialite_osm_filter_OBJECTS) $(spatialite_osm_filter_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_osm_filter_OBJECTS) $(spatialite_osm_filter_LDADD) $(LIBS)
+
spatialite_osm_map$(EXEEXT): $(spatialite_osm_map_OBJECTS) $(spatialite_osm_map_DEPENDENCIES) $(EXTRA_spatialite_osm_map_DEPENDENCIES)
@rm -f spatialite_osm_map$(EXEEXT)
- $(LINK) $(spatialite_osm_map_OBJECTS) $(spatialite_osm_map_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_osm_map_OBJECTS) $(spatialite_osm_map_LDADD) $(LIBS)
+
spatialite_osm_net$(EXEEXT): $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_DEPENDENCIES) $(EXTRA_spatialite_osm_net_DEPENDENCIES)
@rm -f spatialite_osm_net$(EXEEXT)
- $(LINK) $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_osm_net_OBJECTS) $(spatialite_osm_net_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)
- $(LINK) $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_osm_raw_OBJECTS) $(spatialite_osm_raw_LDADD) $(LIBS)
+
spatialite_tool$(EXEEXT): $(spatialite_tool_OBJECTS) $(spatialite_tool_DEPENDENCIES) $(EXTRA_spatialite_tool_DEPENDENCIES)
@rm -f spatialite_tool$(EXEEXT)
- $(LINK) $(spatialite_tool_OBJECTS) $(spatialite_tool_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(spatialite_tool_OBJECTS) $(spatialite_tool_LDADD) $(LIBS)
+
+spatialite_xml_collapse$(EXEEXT): $(spatialite_xml_collapse_OBJECTS) $(spatialite_xml_collapse_DEPENDENCIES) $(EXTRA_spatialite_xml_collapse_DEPENDENCIES)
+ @rm -f spatialite_xml_collapse$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(spatialite_xml_collapse_OBJECTS) $(spatialite_xml_collapse_LDADD) $(LIBS)
+
+spatialite_xml_load$(EXEEXT): $(spatialite_xml_load_OBJECTS) $(spatialite_xml_load_DEPENDENCIES) $(EXTRA_spatialite_xml_load_DEPENDENCIES)
+ @rm -f spatialite_xml_load$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(spatialite_xml_load_OBJECTS) $(spatialite_xml_load_LDADD) $(LIBS)
+
+spatialite_xml_print$(EXEEXT): $(spatialite_xml_print_OBJECTS) $(spatialite_xml_print_DEPENDENCIES) $(EXTRA_spatialite_xml_print_DEPENDENCIES)
+ @rm -f spatialite_xml_print$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(spatialite_xml_print_OBJECTS) $(spatialite_xml_print_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -518,27 +646,30 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_osm_net.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@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_collapse.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_load.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/spatialite_xml_print.Po at am__quote@
.c.o:
- at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(COMPILE) -c $<
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(COMPILE) -c $<
.c.obj:
- at am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
- at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
- at am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
- at am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+ at am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ at am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+ at am__fastdepCC_FALSE@ $(AM_V_CC at am__nodep@)$(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
@@ -549,26 +680,15 @@ clean-libtool:
distclean-libtool:
-rm -f libtool config.lt
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ $(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
@@ -580,15 +700,11 @@ TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$$unique; \
fi; \
fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
- END { if (nonempty) { for (i in files) print i; }; }'`; \
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
@@ -597,18 +713,16 @@ GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
-
cscope: cscope.files
test ! -s cscope.files \
|| $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
-
clean-cscope:
-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
-cscope.files: clean-cscope cscopelist
-
-cscopelist: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP)'; \
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
@@ -716,9 +830,9 @@ distcheck: dist
*.zip*) \
unzip $(distdir).zip ;;\
esac
- chmod -R a-w $(distdir); chmod u+w $(distdir)
- mkdir $(distdir)/_build
- mkdir $(distdir)/_inst
+ chmod -R a-w $(distdir)
+ chmod u+w $(distdir)
+ mkdir $(distdir)/_build $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
@@ -892,14 +1006,14 @@ uninstall-am: uninstall-binPROGRAMS
.MAKE: all install-am install-strip
-.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
clean-binPROGRAMS clean-cscope clean-generic clean-libtool \
- cscope cscopelist ctags dist dist-all dist-bzip2 dist-gzip \
- dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \
- distclean distclean-compile distclean-generic distclean-hdr \
- distclean-libtool distclean-tags distcleancheck distdir \
- distuninstallcheck dvi dvi-am html html-am info info-am \
- install install-am install-binPROGRAMS install-data \
+ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+ distcheck distclean distclean-compile distclean-generic \
+ distclean-hdr distclean-libtool distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-binPROGRAMS install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
@@ -907,7 +1021,7 @@ uninstall-am: uninstall-binPROGRAMS
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-binPROGRAMS
+ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/aclocal.m4 b/aclocal.m4
index 5e48e24..f209970 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.12.2 -*- Autoconf -*-
+# generated automatically by aclocal 1.13.4 -*- Autoconf -*-
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -11,6 +11,7 @@
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
@@ -219,24 +220,37 @@ m4_popdef([pkg_default])
m4_popdef([pkg_description])
]) dnl PKG_NOARCH_INSTALLDIR
-# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+
+# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# -------------------------------------------
+# Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])# PKG_CHECK_VAR
+
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 8
-
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.12'
+[am__api_version='1.13'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.12.2], [],
+m4_if([$1], [1.13.4], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -252,21 +266,19 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.12.2])dnl
+[AM_AUTOMAKE_VERSION([1.13.4])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 2
-
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
@@ -314,14 +326,12 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 10
-
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
@@ -347,13 +357,12 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 17
# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
@@ -539,19 +548,18 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 6
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[{
- # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
@@ -580,7 +588,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
+ test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
@@ -614,27 +622,14 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
-AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
-
# Do all the work for Automake. -*- Autoconf -*-
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 19
-
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
@@ -650,7 +645,7 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.62])dnl
+[AC_PREREQ([2.65])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@@ -680,8 +675,7 @@ AC_SUBST([CYGPATH_W])
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[AC_DIAGNOSE([obsolete],
-[$0: two- and three-arguments forms are deprecated. For more info, see:
-http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation])
+ [$0: two- and three-arguments forms are deprecated.])
m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
@@ -735,18 +729,15 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES([OBJC])],
[m4_define([AC_PROG_OBJC],
m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
-dnl Support for Objective C++ was only introduced in Autoconf 2.65,
-dnl but we still cater to Autoconf 2.62.
-m4_ifdef([AC_PROG_OBJCXX],
-[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[_AM_DEPENDENCIES([OBJCXX])],
[m4_define([AC_PROG_OBJCXX],
- m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
-_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
-dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the
-dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
-dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
@@ -780,14 +771,12 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 8
-
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
@@ -803,14 +792,12 @@ if test x"${install_sh}" != xset; then
fi
AC_SUBST([install_sh])])
-# Copyright (C) 2003-2012 Free Software Foundation, Inc.
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 2
-
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
@@ -827,14 +814,12 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 7
-
# AM_MAINTAINER_MODE([DEFAULT-MODE])
# ----------------------------------
# Control maintainer-specific portions of Makefiles.
@@ -862,18 +847,14 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
]
)
-AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
-
# Check to see how 'make' treats includes. -*- Autoconf -*-
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 5
-
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
@@ -918,14 +899,12 @@ rm -f confinc confmf
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 7
-
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
@@ -933,11 +912,10 @@ AC_DEFUN([AM_MISSING_PROG],
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
-
# AM_MISSING_HAS_RUN
# ------------------
-# Define MISSING if not defined so far and test if it supports --run.
-# If it does, set am_missing_run to use it, otherwise, to nothing.
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
@@ -950,24 +928,51 @@ if test x"${MISSING+set}" != xset; then
esac
fi
# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
else
am_missing_run=
AC_MSG_WARN(['missing' script is too old or missing])
fi
])
+# -*- Autoconf -*-
+# Obsolete and "removed" macros, that must however still report explicit
+# error messages when used, to smooth transition.
+#
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl
+AC_CONFIG_HEADERS($@)])
+
+AC_DEFUN([AM_PROG_CC_STDC],
+[AC_PROG_CC
+am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc
+AC_DIAGNOSE([obsolete],
+['$0': this macro is obsolete.
+You should simply use the 'AC][_PROG_CC' macro instead.
+Also, your code should no longer depend upon 'am_cv_prog_cc_stdc',
+but upon 'ac_cv_prog_cc_stdc'.])])
+
+AC_DEFUN([AM_C_PROTOTYPES],
+ [AC_FATAL([automatic de-ANSI-fication support has been removed])])
+AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES])
+
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 6
-
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
@@ -993,14 +998,12 @@ AC_DEFUN([_AM_IF_OPTION],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 9
-
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
@@ -1076,13 +1079,71 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 2
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+ [--enable-silent-rules],
+ [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+ [--disable-silent-rules],
+ [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
@@ -1106,14 +1167,12 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006-2012 Free Software Foundation, Inc.
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 3
-
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
@@ -1127,14 +1186,12 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004-2012 Free Software Foundation, Inc.
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 3
-
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
@@ -1148,76 +1205,114 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
+#
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility. Yes, it's still used
# in the wild :-( We should find a proper way to deprecate it ...
AC_SUBST([AMTAR], ['$${TAR-tar}'])
-m4_if([$1], [v7],
- [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
- [m4_case([$1], [ustar],, [pax],,
- [m4_fatal([Unknown tar format])])
-AC_MSG_CHECKING([how to create a $1 tar archive])
-# Loop over all known methods to create a tar archive until one works.
+
+# We'll loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
-_am_tools=${am_cv_prog_tar_$1-$_am_tools}
-# Do not fold the above two line into one, because Tru64 sh and
-# Solaris sh will not grok spaces in the rhs of '-'.
-for _am_tool in $_am_tools
-do
- case $_am_tool in
- gnutar)
- for _am_tar in tar gnutar gtar;
- do
- AM_RUN_LOG([$_am_tar --version]) && break
- done
- am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
- am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
- am__untar="$_am_tar -xf -"
- ;;
- plaintar)
- # Must skip GNU tar: if it does not support --format= it doesn't create
- # ustar tarball either.
- (tar --version) >/dev/null 2>&1 && continue
- am__tar='tar chf - "$$tardir"'
- am__tar_='tar chf - "$tardir"'
- am__untar='tar xf -'
- ;;
- pax)
- am__tar='pax -L -x $1 -w "$$tardir"'
- am__tar_='pax -L -x $1 -w "$tardir"'
- am__untar='pax -r'
- ;;
- cpio)
- am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
- am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
- am__untar='cpio -i -H $1 -d'
- ;;
- none)
- am__tar=false
- am__tar_=false
- am__untar=false
- ;;
- esac
- # If the value was cached, stop now. We just wanted to have am__tar
- # and am__untar set.
- test -n "${am_cv_prog_tar_$1}" && break
+m4_if([$1], [v7],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+ [m4_case([$1],
+ [ustar],
+ [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+ if test $am_uid -le $am_max_uid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi
+ AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+ if test $am_gid -le $am_max_gid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi],
+
+ [pax],
+ [],
+
+ [m4_fatal([Unknown tar format])])
+
+ AC_MSG_CHECKING([how to create a $1 tar archive])
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
- # tar/untar a dummy directory, and stop if the command works
- rm -rf conftest.dir
- mkdir conftest.dir
- echo GrepMe > conftest.dir/file
- AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ AM_RUN_LOG([cat conftest.dir/file])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
rm -rf conftest.dir
- if test -s conftest.tar; then
- AM_RUN_LOG([$am__untar <conftest.tar])
- grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
- fi
-done
-rm -rf conftest.dir
-AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
-AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
diff --git a/configure b/configure
index ef375f5..65b1cd6 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.1.1.
+# Generated by GNU Autoconf 2.69 for spatialite-tools 4.2.0.
#
# 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.1.1'
-PACKAGE_STRING='spatialite-tools 4.1.1'
+PACKAGE_VERSION='4.2.0'
+PACKAGE_STRING='spatialite-tools 4.2.0'
PACKAGE_BUGREPORT='a.furieri at lqt.it'
PACKAGE_URL=''
@@ -708,6 +708,10 @@ CC
MAINT
MAINTAINER_MODE_FALSE
MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
am__untar
am__tar
AMTAR
@@ -772,6 +776,7 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+enable_silent_rules
enable_maintainer_mode
enable_dependency_tracking
enable_shared
@@ -1348,7 +1353,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.1.1 to adapt to many kinds of systems.
+\`configure' configures spatialite-tools 4.2.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1419,7 +1424,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of spatialite-tools 4.1.1:";;
+ short | recursive ) echo "Configuration of spatialite-tools 4.2.0:";;
esac
cat <<\_ACEOF
@@ -1427,6 +1432,8 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-silent-rules less verbose build output (undo: "make V=1")
+ --disable-silent-rules verbose build output (undo: "make V=0")
--enable-maintainer-mode
enable make rules and dependencies not useful (and
sometimes confusing) to the casual installer
@@ -1549,7 +1556,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-spatialite-tools configure 4.1.1
+spatialite-tools configure 4.2.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2139,7 +2146,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.1.1, which was
+It was created by spatialite-tools $as_me 4.2.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2495,7 +2502,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
-am__api_version='1.12'
+am__api_version='1.13'
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -2708,8 +2715,8 @@ if test x"${MISSING+set}" != xset; then
esac
fi
# Use eval to expand $SHELL
-if eval "$MISSING --run true"; then
- am_missing_run="$MISSING --run "
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
else
am_missing_run=
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
@@ -2949,6 +2956,45 @@ else
fi
rmdir .tst 2>/dev/null
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
@@ -2971,7 +3017,7 @@ fi
# Define the identity of the package.
PACKAGE='spatialite-tools'
- VERSION='4.1.1'
+ VERSION='4.2.0'
cat >>confdefs.h <<_ACEOF
@@ -3011,6 +3057,10 @@ mkdir_p='$(MKDIR_P)'
# in the wild :-( We should find a proper way to deprecate it ...
AMTAR='$${TAR-tar}'
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar pax cpio none'
+
am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
@@ -3018,6 +3068,7 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
# Check whether --enable-maintainer-mode was given.
@@ -18019,7 +18070,6 @@ DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
-U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
@@ -18471,7 +18521,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.1.1, which was
+This file was extended by spatialite-tools $as_me 4.2.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -18537,7 +18587,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.1.1
+spatialite-tools config.status 4.2.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -19645,7 +19695,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
case $ac_file$ac_mode in
"depfiles":C) test x"$AMDEP_TRUE" != x"" || {
- # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # Older Autoconf quotes --file arguments for eval, but not when files
# are listed without --file. Let's play safe and only enable the eval
# if we detect the quoting.
case $CONFIG_FILES in
@@ -19696,7 +19746,7 @@ $as_echo X"$mf" |
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
- test -z "am__include" && continue
+ test -z "$am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
diff --git a/configure.ac b/configure.ac
index 19c2c05..e220aa4 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.1.1, a.furieri at lqt.it)
+AC_INIT(spatialite-tools, 4.2.0, a.furieri at lqt.it)
AC_LANG(C)
AC_CONFIG_MACRO_DIR([m4])
diff --git a/exif_loader.c b/exif_loader.c
index 1505b9c..25e2dd5 100644
--- a/exif_loader.c
+++ b/exif_loader.c
@@ -1617,5 +1617,6 @@ main (int argc, char *argv[])
fprintf (stderr,
"\n\n*** %d EXIF photo%s successfully inserted into the DB\n",
cnt, (cnt > 1) ? "s where" : " was");
+spatialite_shutdown();
return 0;
}
diff --git a/shell.c b/shell.c
index 810d4ea..6e70a81 100644
--- a/shell.c
+++ b/shell.c
@@ -119,6 +119,10 @@ extern int isatty(int);
/* True if the timer is enabled */
static int enableTimer = 0;
+/* sandro 2013-11-07 */
+void *splite_cache = NULL;
+/* end sandro 2013-11-07 */
+
/* ctype macros that work with signed characters */
#define IsSpace(X) isspace((unsigned char)X)
#define IsDigit(X) isdigit((unsigned char)X)
@@ -259,6 +263,13 @@ static int sql_log_enabled = 1;
static int bail_on_error = 0;
/*
+** sandro 2013-08-30
+** If the following flag is set, no welcome message will be
+** printed at all.
+*/
+static int splite_silent = 0;
+
+/*
** Threat stdin as an interactive input if the following variable
** is true. Otherwise, assume stdin is connected to a file or pipe.
*/
@@ -711,6 +722,40 @@ convert_to_utf8 (char *buf, int maxlen)
free (utf8buf);
}
+/* sandro 2013-11-17 */
+static void
+split_drop_name(const char *str, char **prefix, char **table)
+{
+ int len1;
+ int len2;
+ const char *pt = NULL;
+ const char *p = str;
+ *prefix = NULL;
+ *table = NULL;
+ while (*p != '\0')
+ {
+ if (*p == '.')
+ {
+ pt = p;
+ break;
+ }
+ p++;
+ }
+ if (pt == NULL)
+ return;
+ len1 = pt - str;
+ len2 = strlen(pt + 1);
+ if (len1 > 0 && len2 > 0)
+ {
+ *prefix = malloc(len1 + 1);
+ memcpy(*prefix, str, len1);
+ *(*prefix + len1) = '\0';
+ *table = malloc(len2 + 1);
+ strcpy(*table, pt + 1);
+ }
+}
+/* end sandro 2013-11-17 */
+
static void
convert_input_to_utf8 (char *buf, int maxlen)
{
@@ -2141,8 +2186,10 @@ static char zHelp[] =
" If TABLE specified, only show tables matching\n"
" LIKE pattern TABLE.\n"
".separator STRING Change separator used by output mode and .import\n"
+ ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
".show Show the current values for various settings\n"
".stats ON|OFF Turn stats on or off\n"
+ ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
".tables ?TABLE? List names of tables\n"
" If TABLE specified, only list tables matching\n"
" LIKE pattern TABLE.\n"
@@ -2242,6 +2289,7 @@ static void open_db(struct callback_data *p){
p->zDbFilename, sqlite3_errmsg(db));
exit(1);
}
+ spatialite_init_ex (p->db, splite_cache, (splite_silent == 0) ? 1 : 0);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3_enable_load_extension(p->db, 1);
#endif
@@ -2662,7 +2710,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if (dxf == NULL)
goto stop_dxf;
/* attempting to parse the DXF input file */
- if (gaiaParseDxfFile (dxf, dxf_path))
+ if (gaiaParseDxfFile_r (splite_cache, dxf, dxf_path))
{
/* loading into the DB */
if (!gaiaLoadFromDxfParser (p->db, dxf, mode, append))
@@ -2782,17 +2830,29 @@ stop_dxf:
}
else if (c == 'd' && strncmp (azArg[0], "dropgeo", n) == 0 && nArg > 1)
{
+ char *prefix;
+ char *table;
+ int ret;
int cnt0 = sqlite3_total_changes(p->db);
- if (gaiaDropTable (p->db, azArg[1]))
+ split_drop_name(azArg[1], &prefix, &table);
+ if (prefix != NULL && table != NULL)
+ ret = gaiaDropTableEx (p->db, prefix, table);
+ else
+ ret = gaiaDropTable (p->db, azArg[1]);
+ if (ret)
{
int cnt1 = sqlite3_total_changes(p->db);
if (cnt1 > cnt0)
- fprintf(stderr, "SpatialTable \"%s\" succesfully removed\n", azArg[1]);
+ fprintf(stderr, "SpatialTable %s succesfully removed\n", azArg[1]);
else
- fprintf(stderr, "SpatialTable \"%s\" seems not to exist\n", azArg[1]);
+ fprintf(stderr, "SpatialTable %s seems not to exist\n", azArg[1]);
}
else
- fprintf(stderr, "ERROR: unable to remove SpatialTable \"%s\"\n", azArg[1]);
+ fprintf(stderr, "ERROR: unable to remove SpatialTable %s\n", azArg[1]);
+ if (prefix != NULL)
+ free(prefix);
+ if (table != NULL)
+ free(table);
} else
/* end sandro 2008-06-20 */
if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){
@@ -3406,6 +3466,27 @@ stop_dxf:
"%.*s", (int)sizeof(p->separator)-1, azArg[1]);
}else
+ if( c=='s'
+ && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
+ ){
+ char *zCmd;
+ int i;
+ if( nArg<2 ){
+ fprintf(stderr, "Usage: .system COMMAND\n");
+ rc = 1;
+ }
+ else {
+ zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
+ for(i=2; i<nArg; i++){
+ zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
+ zCmd, azArg[i]);
+ }
+ (void)system(zCmd);
+ sqlite3_free(zCmd);
+ }
+ }else
+
+
if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
int i;
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
@@ -4049,6 +4130,7 @@ static const char zOptions[] =
" -interactive force interactive I/O\n"
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
+ " -silent suppress the welcome message\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
" -multiplex enable the multiplexor VFS\n"
#endif
@@ -4100,6 +4182,9 @@ int main(int argc, char **argv){
char *zFirstCmd = 0;
int i;
int rc = 0;
+
+/* initializing the SpatiaLite's internal cache */
+ splite_cache = spatialite_alloc_connection ();
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
@@ -4112,8 +4197,13 @@ int main(int argc, char **argv){
Sandro Furieri 30 May 2008
===========================
registering the SpatiaLite extension
+2013-08-30: supporting "silent mode"
*/
- spatialite_init (1);
+ for(i=1; i<argc && argv[i][0]=='-'; i++){
+ char *z = argv[i];
+ if( z[1]=='-' ){ z++; }
+ if( strcmp(z,"-silent")==0 ){ splite_silent = 1;}
+ }
stdin_is_interactive = isatty(0);
@@ -4285,6 +4375,10 @@ registering the SpatiaLite extension
data.statsOn = 1;
}else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1;
+ }else if( strcmp(z,"-silent")==0 ){
+/* sandro 2013-08-30 */
+ splite_silent = 1;
+/* end sandro */
}else if( strcmp(z,"-version")==0 ){
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
return 0;
@@ -4362,6 +4456,7 @@ registering the SpatiaLite extension
sqlite3_libversion(), sqlite3_sourceid()
);
*/
+ open_db(&data);
if (isatty (1))
printf ("SQLite version ......: %s\n",
sqlite3_libversion ());
@@ -4414,7 +4509,9 @@ Sandro Furieri 30 May 2008
===========================
memory cleanup for SpatiaLite extension
*/
- sqlite3_reset_auto_extension ();
+
+ spatialite_cleanup_ex (splite_cache);
+ spatialite_shutdown ();
return rc;
}
diff --git a/spatialite_convert.c b/spatialite_convert.c
index 09f3dcf..bc427c1 100644
--- a/spatialite_convert.c
+++ b/spatialite_convert.c
@@ -2155,6 +2155,34 @@ copy_views_geometry_columns_4_3 (sqlite3 * handle)
}
static int
+check_views_geometry_columns (sqlite3 * handle)
+{
+/* may be v2.4 - testing for views_geometry_columns */
+ const char *sql;
+ char **results;
+ int ret;
+ int rows;
+ int columns;
+ int i;
+ char *errMsg = NULL;
+ int ok = 0;
+
+/* testing for an existing VIEWS_GEOMETRY_COLUMNS */
+ sql = "SELECT Count(*) FROM sqlite_master WHERE type = 'table' "
+ "AND Lower(name) = 'views_geometry_columns'";
+ ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, &errMsg);
+ if (ret != SQLITE_OK)
+ return 0;
+ for (i = 1; i <= rows; i++)
+ {
+ if (atoi (results[(i * columns)]) > 0)
+ ok = 1;
+ }
+ sqlite3_free_table (results);
+ return ok;
+}
+
+static int
cvt_views_geometry_columns (sqlite3 * handle, int in_version, int version)
{
/* converting VIEWS_GEOMETRY_COLUMNS */
@@ -2168,13 +2196,23 @@ cvt_views_geometry_columns (sqlite3 * handle, int in_version, int version)
}
else
{
- /* if version=2 we'll simply create the table and exit */
- if (version == 3)
- ret = create_views_geometry_columns_3 (handle);
- if (version == 4)
- ret = create_views_geometry_columns_4 (handle);
- if (!ret)
- return 0;
+ if (check_views_geometry_columns (handle))
+ {
+ /* preparing the input table */
+ if (!prepare_input (handle, "views_geometry_columns"))
+ return 0;
+ }
+ else
+ {
+ /* if version=2 we'll simply create the table and exit */
+ if (version == 3)
+ ret = create_views_geometry_columns_3 (handle);
+ if (version == 4)
+ ret = create_views_geometry_columns_4 (handle);
+ if (!ret)
+ return 0;
+ return 1;
+ }
}
drop_views_geometry_columns (handle);
@@ -2191,31 +2229,26 @@ cvt_views_geometry_columns (sqlite3 * handle, int in_version, int version)
/* copying any row */
ret = 0;
- if (in_version == 2)
- ret = 1;
- if (in_version == 3)
+ if (in_version == 4)
{
if (version == 2)
ret = 1;
- if (version == 4)
- ret = copy_views_geometry_columns_3_4 (handle);
+ if (version == 3)
+ ret = copy_views_geometry_columns_4_3 (handle);
}
- if (in_version == 4)
+ else
{
if (version == 2)
ret = 1;
- if (version == 3)
- ret = copy_views_geometry_columns_4_3 (handle);
+ if (version == 4)
+ ret = copy_views_geometry_columns_3_4 (handle);
}
if (!ret)
return 0;
- if (in_version != 2)
- {
- /* dropping the temporary input table */
- if (!drop_input_table (handle))
- return 0;
- }
+ /* dropping the temporary input table */
+ if (!drop_input_table (handle))
+ return 0;
return 1;
}
@@ -3893,8 +3926,6 @@ static int
cvt_extra_stuff (sqlite3 * handle, int version)
{
/* converting extra-sfuff Tables and Views */
- int ret;
-
if (version != 3)
drop_layer_statistics (handle);
@@ -4248,6 +4279,7 @@ register_virtual (sqlite3 * sqlite, const char *table, int version)
int rows;
int columns;
int i;
+ int count = 0;
char *errMsg = NULL;
int xdims = -1;
@@ -4268,8 +4300,14 @@ register_virtual (sqlite3 * sqlite, const char *table, int version)
{
strcpy (gtype, results[(i * columns)]);
srid = atoi (results[(i * columns) + 1]);
+ count++;
}
sqlite3_free_table (results);
+ if (count == 0)
+ {
+ /* empty table */
+ return 1;
+ }
/* normalized Geometry type */
if (strcmp (gtype, "POINT") == 0)
@@ -7027,5 +7065,6 @@ main (int argc, char *argv[])
end:
sqlite3_close (handle);
spatialite_cleanup_ex (cache);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_dxf.c b/spatialite_dxf.c
index f5ba2d7..ed6d201 100644
--- a/spatialite_dxf.c
+++ b/spatialite_dxf.c
@@ -480,7 +480,7 @@ main (int argc, char *argv[])
if (dxf == NULL)
goto stop;
/* attempting to parse the DXF input file */
- if (gaiaParseDxfFile (dxf, dxf_path))
+ if (gaiaParseDxfFile_r (cache, dxf, dxf_path))
{
/* loading into the DB */
if (!gaiaLoadFromDxfParser (handle, dxf, mode, append))
@@ -541,5 +541,6 @@ main (int argc, char *argv[])
sqlite3_errmsg (handle));
}
spatialite_cleanup_ex (cache);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_gml.c b/spatialite_gml.c
index 72fc44c..dff2843 100644
--- a/spatialite_gml.c
+++ b/spatialite_gml.c
@@ -1941,5 +1941,6 @@ main (int argc, char *argv[])
sqlite3_close (handle);
spatialite_cleanup_ex (cache);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_network.c b/spatialite_network.c
index bb2f896..784b95c 100644
--- a/spatialite_network.c
+++ b/spatialite_network.c
@@ -2123,5 +2123,6 @@ main (int argc, char *argv[])
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);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_osm_filter.c b/spatialite_osm_filter.c
index a219e2c..f609090 100644
--- a/spatialite_osm_filter.c
+++ b/spatialite_osm_filter.c
@@ -1864,5 +1864,6 @@ main (int argc, char *argv[])
spatialite_cleanup_ex (cache);
if (out != NULL)
fclose (out);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_osm_map.c b/spatialite_osm_map.c
index fa757b9..71c566b 100644
--- a/spatialite_osm_map.c
+++ b/spatialite_osm_map.c
@@ -1549,22 +1549,32 @@ destroy_ring_refs (struct ring_refs *rings)
if (rings == NULL)
return;
- if (rings->id != NULL)
- free (rings->id);
- if (rings->found != NULL)
- free (rings->found);
- if (rings->outer != NULL)
- free (rings->outer);
if (rings->geom != NULL)
{
for (i = 0; i < rings->count; i++)
{
g = *(rings->geom + i);
if (g)
- gaiaFreeGeomColl (g);
+ {
+ int j;
+ sqlite3_int64 id = *(rings->id + i);
+ gaiaFreeGeomColl (g);
+ for (j = 0; j < rings->count; j++)
+ {
+ sqlite3_int64 id2 = *(rings->id + j);
+ if (id == id2)
+ *(rings->geom + j) = NULL;
+ }
+ }
}
free (rings->geom);
}
+ if (rings->id != NULL)
+ free (rings->id);
+ if (rings->found != NULL)
+ free (rings->found);
+ if (rings->outer != NULL)
+ free (rings->outer);
free (rings);
}
@@ -1806,7 +1816,7 @@ multipolygon_layer_insert (struct aux_params *params, const char *layer_name,
sqlite3_bind_text (layer->ins_polygon_stmt, 3, name,
strlen (name), SQLITE_STATIC);
sqlite3_bind_blob (layer->ins_polygon_stmt, 4, blob,
- blob_size, SQLITE_STATIC);
+ blob_size, free);
ret = sqlite3_step (layer->ins_polygon_stmt);
if (ret == SQLITE_DONE || ret == SQLITE_ROW)
return 1;
@@ -1849,7 +1859,7 @@ multiline_generic_insert (struct aux_params *params,
sqlite3_bind_text (params->ins_generic_linestring_stmt, 2, name,
strlen (name), SQLITE_STATIC);
sqlite3_bind_blob (params->ins_generic_linestring_stmt, 3, blob,
- blob_size, SQLITE_STATIC);
+ blob_size, free);
ret = sqlite3_step (params->ins_generic_linestring_stmt);
if (ret == SQLITE_DONE || ret == SQLITE_ROW)
return 1;
@@ -1889,7 +1899,7 @@ multipolygon_generic_insert (struct aux_params *params,
sqlite3_bind_text (params->ins_generic_polygon_stmt, 2, name,
strlen (name), SQLITE_STATIC);
sqlite3_bind_blob (params->ins_generic_polygon_stmt, 3, blob,
- blob_size, SQLITE_STATIC);
+ blob_size, free);
ret = sqlite3_step (params->ins_generic_polygon_stmt);
if (ret == SQLITE_DONE || ret == SQLITE_ROW)
return 1;
@@ -2832,5 +2842,6 @@ main (int argc, char *argv[])
db_vacuum (handle);
sqlite3_close (handle);
spatialite_cleanup_ex (cache);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_osm_net.c b/spatialite_osm_net.c
index f7bf0b3..bbff0b1 100644
--- a/spatialite_osm_net.c
+++ b/spatialite_osm_net.c
@@ -2747,5 +2747,6 @@ main (int argc, char *argv[])
sqlite3_close (handle);
spatialite_cleanup_ex (cache);
free_params (¶ms);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_osm_raw.c b/spatialite_osm_raw.c
index 1ef9e40..5d292ec 100644
--- a/spatialite_osm_raw.c
+++ b/spatialite_osm_raw.c
@@ -1225,5 +1225,6 @@ main (int argc, char *argv[])
/* closing the DB connection */
sqlite3_close (handle);
spatialite_cleanup_ex (cache);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_tool.c b/spatialite_tool.c
index 17f6d7e..2a73751 100644
--- a/spatialite_tool.c
+++ b/spatialite_tool.c
@@ -539,5 +539,6 @@ main (int argc, char *argv[])
coerce2d, compressed);
if (export)
do_export (db_path, shp_path, table, column, charset, type);
+ spatialite_shutdown ();
return 0;
}
diff --git a/spatialite_xml_collapse.c b/spatialite_xml_collapse.c
new file mode 100644
index 0000000..b94b76f
--- /dev/null
+++ b/spatialite_xml_collapse.c
@@ -0,0 +1,2408 @@
+/*
+/ spatialite_xml_collapse
+/
+/ a tool performing post-processing tasks after importing
+/ several XML files into SQLite tables
+/
+/ version 1.0, 2013 August 20
+/
+/ 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/>.
+/
+*/
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sqlite3.h>
+#include <spatialite.h>
+
+#define ARG_NONE 0
+#define ARG_DB_PATH 1
+#define ARG_CACHE_SIZE 2
+#define ARG_NAME_LEVEL 3
+
+struct resultset_values
+{
+/* a struct wrapping values from a resultset */
+ int type;
+ sqlite3_int64 int_value;
+ double dbl_value;
+ unsigned char *txt_blob_value;
+ int txt_blob_size;
+};
+
+struct resultset_comparator
+{
+/* object for comparing two rows of the same resultset */
+ struct resultset_values *previous;
+ struct resultset_values *current;
+ int num_columns;
+ sqlite3_int64 previous_rowid;
+ sqlite3_int64 current_rowid;
+};
+
+struct xml_attribute
+{
+/* a struct wrapping an XML attribute (column name) */
+ char *attr_name;
+ char *sql_name;
+ int main_collapsed;
+ int already_defined;
+ int datatype;
+ sqlite3_int64 int_value;
+ double double_value;
+ const unsigned char *text_value;
+ const unsigned char *blob_value;
+ int blob_size;
+ char *xml_reference;
+ struct xml_attribute *next;
+};
+
+struct new_attributes
+{
+/* containing struct for XML attributes (columns) to be added */
+ struct xml_attribute *first;
+ struct xml_attribute *last;
+ int collision;
+};
+
+struct child_reference
+{
+/* an XML child reference */
+ struct xml_table *child;
+ struct child_reference *next;
+};
+
+struct xml_table
+{
+/* a struct wrapping an XML table */
+ char *table_name;
+ char *parent_table;
+ char *tag_ns;
+ char *tag_name;
+ char *geometry;
+ struct xml_table *parent;
+ struct child_reference *first;
+ struct child_reference *last;
+ int done;
+ int level;
+ struct xml_table *next;
+};
+
+struct xml_geometry
+{
+/* a struct wrapping some BLOB geometry */
+ char *table_name;
+ char *geometry;
+ char *type;
+ int srid;
+ char *dims;
+ struct xml_geometry *next;
+};
+
+struct xml_tables_list
+{
+/* linked list of XML tables */
+ struct xml_table *first;
+ struct xml_table *last;
+ struct xml_geometry *first_geom;
+ struct xml_geometry *last_geom;
+};
+
+static struct resultset_comparator *
+create_resultset_comparator (int columns)
+{
+/* creating an empty resultset comparator object */
+ int i;
+ struct resultset_comparator *p =
+ malloc (sizeof (struct resultset_comparator));
+ p->num_columns = columns;
+ p->previous_rowid = -1;
+ p->current_rowid = -1;
+ p->previous = malloc (sizeof (struct resultset_values) * columns);
+ p->current = malloc (sizeof (struct resultset_values) * columns);
+ for (i = 0; i < columns; i++)
+ {
+ struct resultset_values *value = p->previous + i;
+ value->type = SQLITE_NULL;
+ value->txt_blob_value = NULL;
+ value = p->current + i;
+ value->type = SQLITE_NULL;
+ value->txt_blob_value = NULL;
+ }
+ return p;
+}
+
+static void
+destroy_resultset_comparator (struct resultset_comparator *ptr)
+{
+/* memory cleanup - destroying a resultset comparator object */
+ int i;
+ if (ptr == NULL)
+ return;
+ for (i = 0; i < ptr->num_columns; i++)
+ {
+ struct resultset_values *value = ptr->previous + i;
+ if (value->txt_blob_value != NULL)
+ free (value->txt_blob_value);
+ value = ptr->current + i;
+ if (value->txt_blob_value != NULL)
+ free (value->txt_blob_value);
+ }
+ if (ptr->previous != NULL)
+ free (ptr->previous);
+ if (ptr->current != NULL)
+ free (ptr->current);
+ free (ptr);
+}
+
+static void
+save_row_from_resultset (struct resultset_comparator *ptr, sqlite3_stmt * stmt)
+{
+/* saving the current row values */
+ int i;
+ int size;
+ const unsigned char *p;
+ if (ptr == NULL)
+ return;
+ ptr->current_rowid = sqlite3_column_int64 (stmt, 0);
+ for (i = 0; i < ptr->num_columns; i++)
+ {
+ struct resultset_values *value = ptr->current + i;
+ value->type = sqlite3_column_type (stmt, i + 1);
+ switch (value->type)
+ {
+ case SQLITE_INTEGER:
+ value->int_value = sqlite3_column_int64 (stmt, i + 1);
+ break;
+ case SQLITE_FLOAT:
+ value->dbl_value = sqlite3_column_double (stmt, i + 1);
+ break;
+ case SQLITE_TEXT:
+ p = sqlite3_column_text (stmt, i + 1);
+ size = strlen ((const char *) p);
+ value->txt_blob_value = malloc (size + 1);
+ strcpy ((char *) (value->txt_blob_value), (const char *) p);
+ break;
+ case SQLITE_BLOB:
+ p = sqlite3_column_blob (stmt, i + 1);
+ size = sqlite3_column_bytes (stmt, i + 1);
+ value->txt_blob_value = malloc (size);
+ memcpy (value->txt_blob_value, p, size);
+ value->txt_blob_size = size;
+ break;
+ };
+ }
+}
+
+static int
+resultset_rows_equals (struct resultset_comparator *ptr)
+{
+/* comparing the current and previous row from the resultset */
+ int i;
+ if (ptr == NULL)
+ return 0;
+ for (i = 0; i < ptr->num_columns; i++)
+ {
+ struct resultset_values *val_prev = ptr->previous + i;
+ struct resultset_values *val_curr = ptr->current + i;
+ if (val_prev->type != val_curr->type)
+ return 0;
+ switch (val_prev->type)
+ {
+ case SQLITE_INTEGER:
+ if (val_prev->int_value != val_curr->int_value)
+ return 0;
+ break;
+ case SQLITE_FLOAT:
+ if (val_prev->dbl_value != val_curr->dbl_value)
+ return 0;
+ break;
+ case SQLITE_TEXT:
+ if (strcmp
+ ((const char *) (val_prev->txt_blob_value),
+ (const char *) (val_curr->txt_blob_value)) != 0)
+ return 0;
+ break;
+ case SQLITE_BLOB:
+ if (val_prev->txt_blob_size != val_curr->txt_blob_size)
+ return 0;
+ if (memcmp
+ (val_prev->txt_blob_value, val_curr->txt_blob_value,
+ val_curr->txt_blob_size) != 0)
+ return 0;
+ break;
+ };
+ }
+ return 1;
+}
+
+static sqlite3_int64
+get_current_resultset_rowid (struct resultset_comparator *ptr)
+{
+/* returns the current ROWID */
+ if (ptr == NULL)
+ return -1;
+ return ptr->current_rowid;
+}
+
+static void
+reset_resultset_current_row (struct resultset_comparator *ptr)
+{
+/* resetting the resultset current row values */
+ int i;
+ if (ptr == NULL)
+ return;
+ ptr->current_rowid = -1;
+ for (i = 0; i < ptr->num_columns; i++)
+ {
+ struct resultset_values *value = ptr->current + i;
+ value->type = SQLITE_NULL;
+ if (value->txt_blob_value != NULL)
+ free (value->txt_blob_value);
+ value->txt_blob_value = NULL;
+ }
+}
+
+static void
+swap_resultset_rows (struct resultset_comparator *ptr)
+{
+/* resetting the resultset comparator */
+ int i;
+ if (ptr == NULL)
+ return;
+ ptr->previous_rowid = ptr->current_rowid;
+ ptr->current_rowid = -1;
+ for (i = 0; i < ptr->num_columns; i++)
+ {
+ struct resultset_values *val_prev = ptr->previous + i;
+ struct resultset_values *val_curr = ptr->current + i;
+ if (val_prev->txt_blob_value != NULL)
+ free (val_prev->txt_blob_value);
+ val_prev->type = val_curr->type;
+ val_prev->int_value = val_curr->int_value;
+ val_prev->dbl_value = val_curr->dbl_value;
+ val_prev->txt_blob_value = val_curr->txt_blob_value;
+ val_prev->txt_blob_size = val_curr->txt_blob_size;
+ val_curr->type = SQLITE_NULL;
+ val_curr->txt_blob_value = NULL;
+ }
+}
+
+static void
+destroy_child_reference (struct child_reference *p)
+{
+/* memory cleanup - destroying a child reference */
+ if (p == NULL)
+ return;
+ free (p);
+}
+
+static struct xml_table *
+alloc_xml_table (const char *table, const char *parent, const char *tag_ns,
+ const char *tag_name, const char *geometry, int level)
+{
+/* allocating and initializing an XML table */
+ int len;
+ struct xml_table *p = malloc (sizeof (struct xml_table));
+ len = strlen (table);
+ p->table_name = malloc (len + 1);
+ strcpy (p->table_name, table);
+ if (parent == NULL)
+ p->parent_table = NULL;
+ else
+ {
+ len = strlen (parent);
+ p->parent_table = malloc (len + 1);
+ strcpy (p->parent_table, parent);
+ }
+ if (tag_ns == NULL)
+ p->tag_ns = NULL;
+ else
+ {
+ len = strlen (tag_ns);
+ p->tag_ns = malloc (len + 1);
+ strcpy (p->tag_ns, tag_ns);
+ }
+ len = strlen (tag_name);
+ p->tag_name = malloc (len + 1);
+ strcpy (p->tag_name, tag_name);
+ if (geometry == NULL)
+ p->geometry = NULL;
+ else
+ {
+ len = strlen (geometry);
+ p->geometry = malloc (len + 1);
+ strcpy (p->geometry, geometry);
+ }
+ p->parent = NULL;
+ p->first = NULL;
+ p->last = NULL;
+ p->done = 0;
+ p->level = level;
+ p->next = NULL;
+ return p;
+}
+
+static void
+destroy_xml_table (struct xml_table *p)
+{
+/* memory cleanup - destroying an XML table */
+ struct child_reference *pc;
+ struct child_reference *pcn;
+ if (p == NULL)
+ return;
+ if (p->table_name)
+ free (p->table_name);
+ if (p->parent_table)
+ free (p->parent_table);
+ if (p->tag_ns)
+ free (p->tag_ns);
+ if (p->tag_name)
+ free (p->tag_name);
+ if (p->geometry)
+ free (p->geometry);
+ pc = p->first;
+ while (pc != NULL)
+ {
+ pcn = pc->next;
+ destroy_child_reference (pc);
+ pc = pcn;
+ }
+ free (p);
+}
+
+static struct xml_geometry *
+alloc_xml_geometry (const char *table, const char *geometry)
+{
+/* allocating and initializing an XML geometry */
+ int len;
+ struct xml_geometry *p = malloc (sizeof (struct xml_geometry));
+ len = strlen (table);
+ p->table_name = malloc (len + 1);
+ strcpy (p->table_name, table);
+ len = strlen (geometry);
+ p->geometry = malloc (len + 1);
+ strcpy (p->geometry, geometry);
+ p->type = NULL;
+ p->srid = -1;
+ p->dims = NULL;
+ p->next = NULL;
+ return p;
+}
+
+static void
+destroy_xml_geometry (struct xml_geometry *p)
+{
+/* memory cleanup - destroying an XML Geometry */
+ if (p == NULL)
+ return;
+ if (p->table_name)
+ free (p->table_name);
+ if (p->geometry)
+ free (p->geometry);
+ if (p->type)
+ free (p->type);
+ if (p->dims)
+ free (p->dims);
+ free (p);
+}
+
+static struct xml_tables_list *
+alloc_xml_tables (void)
+{
+/* creating an empty list */
+ struct xml_tables_list *p = malloc (sizeof (struct xml_tables_list));
+ p->first = NULL;
+ p->last = NULL;
+ p->first_geom = NULL;
+ p->last_geom = NULL;
+ return p;
+}
+
+static void
+destroy_xml_tables (struct xml_tables_list *p)
+{
+/* memory cleanup - destroying the list */
+ struct xml_table *pt;
+ struct xml_table *ptn;
+ struct xml_geometry *pg;
+ struct xml_geometry *pgn;
+ if (p == NULL)
+ return;
+ pt = p->first;
+ while (pt != NULL)
+ {
+ ptn = pt->next;
+ destroy_xml_table (pt);
+ pt = ptn;
+ }
+ pg = p->first_geom;
+ while (pg != NULL)
+ {
+ pgn = pg->next;
+ destroy_xml_geometry (pg);
+ pg = pgn;
+ }
+ free (p);
+}
+
+static void
+add_xml_table (struct xml_tables_list *list, const char *table,
+ const char *parent, const char *tag_ns, const char *tag_name,
+ const char *geometry, int level)
+{
+/* adds an XML table into the list */
+ struct xml_table *p =
+ alloc_xml_table (table, parent, tag_ns, tag_name, geometry, level);
+ if (list->first == NULL)
+ list->first = p;
+ if (list->last != NULL)
+ list->last->next = p;
+ list->last = p;
+}
+
+static void
+add_xml_geometry (struct xml_tables_list *list, const char *table,
+ const char *geometry)
+{
+/* adds an XML geometry into the list */
+ struct xml_geometry *p = alloc_xml_geometry (table, geometry);
+ if (list->first_geom == NULL)
+ list->first_geom = p;
+ if (list->last_geom != NULL)
+ list->last_geom->next = p;
+ list->last_geom = p;
+}
+
+static void
+add_child (struct xml_tables_list *list, struct xml_table *child,
+ const char *parent)
+{
+/* inserting a child into the parent */
+ struct xml_table *p = list->first;
+ while (p != NULL)
+ {
+ if (strcasecmp (p->table_name, parent) == 0)
+ {
+ struct child_reference *ref =
+ malloc (sizeof (struct child_reference));
+ ref->child = child;
+ ref->next = NULL;
+ if (p->first == NULL)
+ p->first = ref;
+ if (p->last != NULL)
+ p->last->next = ref;
+ p->last = ref;
+ child->parent = p;
+ return;
+ }
+ p = p->next;
+ }
+}
+
+static void
+identify_childs (struct xml_tables_list *list)
+{
+/* identifying parent-child relationships */
+ struct xml_table *p = list->first;
+ while (p != NULL)
+ {
+ if (p->parent_table != NULL)
+ add_child (list, p, p->parent_table);
+ p = p->next;
+ }
+}
+
+static void
+add_attribute (struct new_attributes *p, const char *name, int main)
+{
+/* adding a new XML Attribute (column) into the container */
+ int len;
+ int i;
+ struct xml_attribute *attr = malloc (sizeof (struct xml_attribute));
+ len = strlen (name);
+ attr->attr_name = malloc (len + 1);
+ strcpy (attr->attr_name, name);
+ for (i = 0; i < len; i++)
+ {
+ char c = *(attr->attr_name + i);
+ if (c >= 'A' && c <= 'Z')
+ *(attr->attr_name + i) = c - 'A' + 'a';
+ }
+ attr->main_collapsed = main;
+ attr->already_defined = 0;
+ attr->datatype = SQLITE_NULL;
+ attr->xml_reference = NULL;
+ attr->next = NULL;
+ if (p->first == NULL)
+ p->first = attr;
+ if (p->last != NULL)
+ p->last->next = attr;
+ p->last = attr;
+}
+
+static void
+destroy_attribute (struct xml_attribute *attr)
+{
+/* memory cleanup: destroying an XML Attribute (column) */
+ if (attr == NULL)
+ return;
+ if (attr->attr_name != NULL)
+ free (attr->attr_name);
+ if (attr->xml_reference != NULL)
+ free (attr->xml_reference);
+ free (attr);
+}
+
+static struct new_attributes *
+alloc_new_attributes (void)
+{
+/* creating an empty container */
+ struct new_attributes *p = malloc (sizeof (struct new_attributes));
+ p->first = NULL;
+ p->last = NULL;
+ p->collision = 0;
+ return p;
+}
+
+static void
+destroy_new_attributes (struct new_attributes *p)
+{
+/* memory cleanup: destroying a container */
+ struct xml_attribute *pa;
+ struct xml_attribute *pan;
+ if (p == NULL)
+ return;
+ pa = p->first;
+ while (pa != NULL)
+ {
+ pan = pa->next;
+ destroy_attribute (pa);
+ pa = pan;
+ }
+ free (p);
+}
+
+static void
+check_attribute (struct new_attributes *p, const char *name)
+{
+/* checks if an Attribute/Column name is already defined */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ if (strcasecmp (attr->attr_name, name) == 0)
+ {
+ attr->already_defined = 1;
+ p->collision = 1;
+ }
+ attr = attr->next;
+ }
+}
+
+static void
+reset_attribute_values (struct new_attributes *p)
+{
+/* resetting all values as NULL */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ attr->datatype = SQLITE_NULL;
+ attr = attr->next;
+ }
+}
+
+static void
+set_int_value (struct new_attributes *p, const char *name,
+ sqlite3_int64 int_value)
+{
+/* setting an INT-64 attribute value */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ if (strcasecmp (attr->attr_name, name) == 0)
+ {
+ attr->datatype = SQLITE_INTEGER;
+ attr->int_value = int_value;
+ break;
+ }
+ attr = attr->next;
+ }
+}
+
+static void
+set_double_value (struct new_attributes *p, const char *name,
+ double double_value)
+{
+/* setting a FLOATING POINT (DOUBLE) attribute value */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ if (strcasecmp (attr->attr_name, name) == 0)
+ {
+ attr->datatype = SQLITE_FLOAT;
+ attr->double_value = double_value;
+ break;
+ }
+ attr = attr->next;
+ }
+}
+
+static void
+set_text_value (struct new_attributes *p, const char *name,
+ const unsigned char *text_value)
+{
+/* setting a TEXT attribute value */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ if (strcasecmp (attr->attr_name, name) == 0)
+ {
+ attr->datatype = SQLITE_TEXT;
+ attr->text_value = text_value;
+ break;
+ }
+ attr = attr->next;
+ }
+}
+
+static void
+set_blob_value (struct new_attributes *p, const char *name,
+ const unsigned char *blob_value, int blob_size)
+{
+/* setting a BLOB attribute value */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ if (strcasecmp (attr->attr_name, name) == 0)
+ {
+ attr->datatype = SQLITE_BLOB;
+ attr->blob_value = blob_value;
+ attr->blob_size = blob_size;
+ break;
+ }
+ attr = attr->next;
+ }
+}
+
+static char *
+get_main_attribute (struct new_attributes *p)
+{
+/* return the name of the "main" attribute */
+ struct xml_attribute *attr = p->first;
+ while (attr != NULL)
+ {
+ if (attr->main_collapsed == 1)
+ return attr->attr_name;
+ attr = attr->next;
+ }
+ return NULL;
+}
+
+static int
+do_delete_duplicates2 (sqlite3 * sqlite, sqlite3_int64 rowid,
+ sqlite3_stmt * stmt1, int *count)
+{
+/* deleting duplicate rows [actual delete] */
+ int ret;
+
+ *count = 0;
+ sqlite3_reset (stmt1);
+ sqlite3_clear_bindings (stmt1);
+ sqlite3_bind_int64 (stmt1, 1, rowid);
+ ret = sqlite3_step (stmt1);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ goto error;
+ }
+ *count = 1;
+ return 1;
+
+ error:
+ *count = 0;
+
+ return 0;
+}
+
+static void
+do_delete_duplicates (sqlite3 * sqlite, const char *sql,
+ const char *sql_del, int *count)
+{
+/* deleting duplicate rows */
+ sqlite3_stmt *stmt1 = NULL;
+ sqlite3_stmt *stmt2 = NULL;
+ int ret;
+ int xcnt;
+ int cnt = 0;
+ char *sql_err = NULL;
+ struct resultset_comparator *rs_obj = NULL;
+
+ *count = 0;
+
+/* the complete operation is handled as an unique SQL Transaction */
+ ret = sqlite3_exec (sqlite, "BEGIN", NULL, NULL, &sql_err);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
+ sqlite3_free (sql_err);
+ return;
+ }
+/* preparing the main SELECT statement */
+ ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt1, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ return;
+ }
+/* preparing the DELETE statement */
+ ret = sqlite3_prepare_v2 (sqlite, sql_del, strlen (sql_del), &stmt2, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ goto error;
+ }
+
+ rs_obj = create_resultset_comparator (sqlite3_column_count (stmt1) - 1);
+ while (1)
+ {
+ /* fetching the result set rows */
+ ret = sqlite3_step (stmt1);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ {
+ /* fetching a row */
+ save_row_from_resultset (rs_obj, stmt1);
+ if (resultset_rows_equals (rs_obj))
+ {
+ if (do_delete_duplicates2
+ (sqlite, get_current_resultset_rowid (rs_obj), stmt2,
+ &xcnt))
+ {
+ cnt += xcnt;
+ reset_resultset_current_row (rs_obj);
+ continue;
+ }
+ else
+ goto error;
+ }
+ swap_resultset_rows (rs_obj);
+ }
+ else
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ goto error;
+ }
+ }
+ destroy_resultset_comparator (rs_obj);
+
+ sqlite3_finalize (stmt1);
+ sqlite3_finalize (stmt2);
+
+/* confirm the still pending Transaction */
+ ret = sqlite3_exec (sqlite, "COMMIT", NULL, NULL, &sql_err);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
+ sqlite3_free (sql_err);
+ return;
+ }
+
+ *count = cnt;
+ return;
+
+ error:
+ *count = 0;
+ if (stmt1)
+ sqlite3_finalize (stmt1);
+ if (stmt2)
+ sqlite3_finalize (stmt2);
+ if (rs_obj != NULL)
+ destroy_resultset_comparator (rs_obj);
+
+/* performing a ROLLBACK anyway */
+ ret = sqlite3_exec (sqlite, "ROLLBACK", NULL, NULL, &sql_err);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "ROLLBACK TRANSACTION error: %s\n", sql_err);
+ sqlite3_free (sql_err);
+ }
+}
+
+static char *
+eval_table (sqlite3 * db_handle, char *table)
+{
+/* preparing the column list for Delete Duplicates */
+ int ret;
+ char *sql;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ char *list = NULL;
+
+/* testing if the column/table really exists */
+ sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ goto done;
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, "node_id") == 0)
+ continue;
+ if (strcmp (name, "parent_id") == 0)
+ continue;
+ if (list == NULL)
+ list = sqlite3_mprintf ("\"%s\"", name);
+ else
+ {
+ char *tmp = sqlite3_mprintf ("%s, \"%s\"", list, name);
+ sqlite3_free (list);
+ list = tmp;
+ }
+ }
+ }
+ sqlite3_free_table (results);
+ done:
+ return list;
+}
+
+static void
+remove_duplicates (sqlite3 * db_handle, struct xml_table *table)
+{
+/* attempting to delete Duplicated rows from a table */
+ int count;
+ char *sql;
+ char *sql_del;
+ char *column_list = eval_table (db_handle, table->table_name);
+ if (column_list == NULL)
+ {
+ table->done = 1;
+ return;
+ }
+ sql = sqlite3_mprintf ("SELECT ROWID, %s FROM \"%s\" ORDER BY %s, ROWID",
+ column_list, table->table_name, column_list);
+ sqlite3_free (column_list);
+ sql_del =
+ sqlite3_mprintf ("DELETE FROM \"%s\" WHERE ROWID = ?",
+ table->table_name);
+ do_delete_duplicates (db_handle, sql, sql_del, &count);
+ if (!count)
+ printf ("No duplicated rows found in: %s\n", table->table_name);
+ else
+ printf ("%9d duplicated rows deleted from: %s\n", count,
+ table->table_name);
+ fflush (stdout);
+ sqlite3_free (sql);
+ sqlite3_free (sql_del);
+ table->done = 1;
+}
+
+static void
+recover_geometry (sqlite3 * db_handle, struct xml_geometry *geom)
+{
+/* recovering a full Geometry Column */
+ int ret;
+ char *err_msg;
+ char *sql;
+
+ printf ("Recovering Geometry: %s.%s\n", geom->table_name,
+ geom->geometry);
+ fflush (stdout);
+
+ sql = sqlite3_mprintf ("SELECT RecoverGeometryColumn(%Q, %Q, %d, %Q, %Q)",
+ geom->table_name, geom->geometry, geom->srid,
+ geom->type, geom->dims);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "RecoverGeometryColumn error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return;
+ }
+
+ fprintf (stderr, "Creating Spatial Index: %s.%s\n", geom->table_name,
+ geom->geometry);
+
+ sql = sqlite3_mprintf ("SELECT CreateSpatialIndex(%Q, %Q)",
+ geom->table_name, geom->geometry);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CreateSpatialIndex error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return;
+ }
+}
+
+static void
+check_geometry (sqlite3 * db_handle, struct xml_geometry *geom)
+{
+/* checks if a geometry could be recovered */
+ int ret;
+ char *sql;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int exists = 0;
+ int registered = 0;
+
+/* testing if the column/table really exists */
+ sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", geom->table_name);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ goto done1;
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, geom->geometry) == 0)
+ exists = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ done1:
+
+/* testing if the geometry isn't yet registered */
+ sql = sqlite3_mprintf ("SELECT f_geometry_column FROM geometry_columns "
+ "WHERE Lower(f_table_name) = Lower(%Q) AND "
+ "Lower(f_geometry_column) = Lower(%Q)",
+ geom->table_name, geom->geometry);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ registered = 1;
+ goto done2;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 0];
+ if (strcmp (name, geom->geometry) == 0)
+ registered = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ done2:
+ if (exists && !registered)
+ ;
+ else
+ return;
+
+/* testing if the geometry could really be recovered */
+ sql = sqlite3_mprintf ("SELECT DISTINCT ST_GeometryType(\"%s\"), "
+ "ST_Srid(\"%s\"), CoordDimension(\"%s\") "
+ "FROM \"%s\"", geom->geometry, geom->geometry,
+ geom->geometry, geom->table_name);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ return;
+ if (rows != 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ int len;
+ int i2;
+ const char *type = results[(i * columns) + 0];
+ const char *srid = results[(i * columns) + 1];
+ const char *dims = results[(i * columns) + 2];
+ if (geom->type != NULL)
+ free (geom->type);
+ len = strlen (type);
+ geom->type = malloc (len + 1);
+ strcpy (geom->type, type);
+ for (i2 = 0; i2 < len; i2++)
+ {
+ if (*(geom->type + i2) == ' ')
+ *(geom->type + i2) = '\0';
+ }
+ geom->srid = atoi (srid);
+ if (geom->dims != NULL)
+ free (geom->dims);
+ len = strlen (dims);
+ geom->dims = malloc (len + 1);
+ strcpy (geom->dims, dims);
+ }
+ }
+ sqlite3_free_table (results);
+}
+
+static int
+collapse_table (sqlite3 * db_handle, int journal_off,
+ struct new_attributes *list, const char *table,
+ const char *parent, struct xml_table *tbl)
+{
+/* attempting to collapse some Child table into the Parent */
+ int ret;
+ char *err_msg = NULL;
+ char *sql;
+ char *sql1;
+ struct xml_attribute *attr;
+ sqlite3_stmt *sel_stmt = NULL;
+ sqlite3_stmt *upd_stmt = NULL;
+ int error = 0;
+ sqlite3_int64 pk_value;
+ const unsigned char *main_value;
+ int i;
+ char *tag_child;
+ char *tag_parent;
+
+ if (tbl->tag_ns == NULL)
+ tag_child = sqlite3_mprintf ("<%s>", tbl->tag_name);
+ else
+ tag_child = sqlite3_mprintf ("<%s:%s>", tbl->tag_ns, tbl->tag_name);
+ if (tbl->parent->tag_ns == NULL)
+ tag_parent = sqlite3_mprintf ("<%s>", tbl->parent->tag_name);
+ else
+ tag_parent =
+ sqlite3_mprintf ("<%s:%s>", tbl->parent->tag_ns,
+ tbl->parent->tag_name);
+ printf ("Collapsing %s%s\n", tag_parent, tag_child);
+ fflush (stdout);
+ sqlite3_free (tag_child);
+ sqlite3_free (tag_parent);
+
+ sql = sqlite3_mprintf ("SELECT parent_id, node_value");
+ attr = list->first;
+ while (attr != NULL)
+ {
+ if (attr->main_collapsed)
+ {
+ /* skipping the "main" attribute (child tag name) */
+ attr = attr->next;
+ continue;
+ }
+ sql1 =
+ sqlite3_mprintf ("%s, \"%s\" AS \"%s\"", sql, attr->attr_name,
+ attr->attr_name);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ }
+ sql1 = sqlite3_mprintf ("%s FROM \"%s\"", sql, table);
+ sqlite3_free (sql);
+ sql = sql1;
+ ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &sel_stmt, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM Child error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ error = 1;
+ goto stop;
+ }
+
+ sql =
+ sqlite3_mprintf ("UPDATE \"%s\" SET \"%s\" = ?", parent,
+ get_main_attribute (list));
+ attr = list->first;
+ while (attr != NULL)
+ {
+ if (attr->main_collapsed)
+ {
+ /* skipping the "main" attribute (child tag name) */
+ attr = attr->next;
+ continue;
+ }
+ sql1 = sqlite3_mprintf ("%s, \"%s\" = ?", sql, attr->attr_name);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ }
+ sql1 = sqlite3_mprintf ("%s WHERE node_id = ?", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &upd_stmt, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "UPDATE Parent error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ error = 1;
+ goto stop;
+ }
+
+ if (journal_off)
+ {
+ /* disabling the Journal File */
+ ret =
+ sqlite3_exec (db_handle, "PRAGMA journal_mode=OFF", NULL,
+ NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "JOURNAL MODE=OFF error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto stop;
+ }
+ ret =
+ sqlite3_exec (db_handle, "PRAGMA synchronous=OFF", NULL,
+ NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SYNCHRONOUS=OFF error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto stop;
+ }
+ }
+
+/* starting a transaction */
+ ret = sqlite3_exec (db_handle, "BEGIN", NULL, NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "BEGIN error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto stop;
+ }
+
+ while (1)
+ {
+ /* scrolling the result set rows */
+ ret = sqlite3_step (sel_stmt);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ {
+ /* fetching an input row from the Child Table */
+ int main_value_null = 0;
+ pk_value = sqlite3_column_int64 (sel_stmt, 0);
+ if (sqlite3_column_type (sel_stmt, 1) == SQLITE_NULL)
+ main_value_null = 1;
+ else
+ main_value = sqlite3_column_text (sel_stmt, 1);
+ reset_attribute_values (list);
+ for (i = 2; i < sqlite3_column_count (sel_stmt); i++)
+ {
+ const char *name = sqlite3_column_name (sel_stmt, i);
+ switch (sqlite3_column_type (sel_stmt, i))
+ {
+ case SQLITE_INTEGER:
+ set_int_value (list, name,
+ sqlite3_column_int64 (sel_stmt, i));
+ break;
+ case SQLITE_FLOAT:
+ set_double_value (list, name,
+ sqlite3_column_double (sel_stmt,
+ i));
+ break;
+ case SQLITE_TEXT:
+ set_text_value (list, name,
+ sqlite3_column_text (sel_stmt, i));
+ break;
+ case SQLITE_BLOB:
+ set_blob_value (list, name,
+ sqlite3_column_blob (sel_stmt, i),
+ sqlite3_column_bytes (sel_stmt, i));
+ break;
+ };
+ }
+ /* updating the Parent Table */
+ sqlite3_reset (upd_stmt);
+ sqlite3_clear_bindings (upd_stmt);
+ if (main_value_null)
+ sqlite3_bind_null (upd_stmt, 1);
+ else
+ sqlite3_bind_text (upd_stmt, 1, (const char *) main_value,
+ strlen ((const char *) main_value),
+ SQLITE_STATIC);
+ i = 2;
+ attr = list->first;
+ while (attr != NULL)
+ {
+ if (attr->main_collapsed)
+ {
+ /* skipping the "main" attribute (child tag name) */
+ attr = attr->next;
+ continue;
+ }
+ switch (attr->datatype)
+ {
+ case SQLITE_INTEGER:
+ sqlite3_bind_int64 (upd_stmt, i, attr->int_value);
+ break;
+ case SQLITE_FLOAT:
+ sqlite3_bind_double (upd_stmt, i,
+ attr->double_value);
+ break;
+ case SQLITE_TEXT:
+ sqlite3_bind_text (upd_stmt, i,
+ (const char
+ *) (attr->text_value),
+ strlen ((const char
+ *) (attr->text_value)),
+ SQLITE_STATIC);
+ break;
+ case SQLITE_BLOB:
+ sqlite3_bind_blob (upd_stmt, i, attr->blob_value,
+ attr->blob_size, SQLITE_STATIC);
+ break;
+ default:
+ sqlite3_bind_null (upd_stmt, i);
+ break;
+ };
+ i++;
+ attr = attr->next;
+ }
+ sqlite3_bind_int64 (upd_stmt, i, pk_value);
+ /* UPDATing */
+ ret = sqlite3_step (upd_stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "sqlite3_step [WRITE] error: %s\n",
+ sqlite3_errmsg (db_handle));
+ error = 1;
+ goto stop;
+ }
+ }
+ else
+ {
+ fprintf (stderr, "sqlite3_step [READ] error: %s\n",
+ sqlite3_errmsg (db_handle));
+ error = 1;
+ goto stop;
+ }
+ }
+
+/* finally dropping the Child Table */
+ sql = sqlite3_mprintf ("DROP TABLE \"%s\"", table);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "DROP TABLE error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ error = 1;
+ goto stop;
+ }
+
+/* updating xml_metacatalog_tables (child) */
+ sql = sqlite3_mprintf ("UPDATE xml_metacatalog_tables "
+ "SET status = 'post-processed: collapsed and then dropped' "
+ "WHERE table_name = %Q", tbl->table_name);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "UPDATE xml_metacatalog_tables (child): %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ }
+
+/* updating xml_metacatalog_tables (parent) */
+ sql = sqlite3_mprintf ("UPDATE xml_metacatalog_tables "
+ "SET status = 'post-processed: receiving collapsed children' "
+ "WHERE table_name = %Q", tbl->parent_table);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "UPDATE xml_metacatalog_tables (parent): %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ }
+
+ attr = list->first;
+ while (attr != NULL)
+ {
+ /* updating xml_metacatalog_columns (parent) */
+ char *xml;
+ char *parent_tag;
+ char *geom = NULL;
+ if (tbl->parent->tag_ns == NULL)
+ parent_tag = sqlite3_mprintf ("<%s>", tbl->parent->tag_name);
+ else
+ parent_tag =
+ sqlite3_mprintf ("<%s:%s>", tbl->parent->tag_ns,
+ tbl->parent->tag_name);
+ xml =
+ sqlite3_mprintf ("%s%s%s", parent_tag, attr->xml_reference,
+ parent_tag);
+ sqlite3_free (parent_tag);
+ if (tbl->geometry != NULL)
+ {
+ if (strcmp (attr->attr_name, tbl->geometry) == 0)
+ geom =
+ sqlite3_mprintf ("GeomFromGml(\"%s\")", tbl->tag_name);
+ }
+ if (geom != NULL)
+ {
+ sql = sqlite3_mprintf ("INSERT INTO xml_metacatalog_columns "
+ "(table_name, column_name, origin, destination, xml_reference) VALUES "
+ "(%Q, %Q, %Q, NULL, %Q)",
+ tbl->parent_table, attr->attr_name, geom,
+ xml);
+ sqlite3_free (geom);
+ }
+ else
+ sql = sqlite3_mprintf ("INSERT INTO xml_metacatalog_columns "
+ "(table_name, column_name, origin, destination, xml_reference) VALUES "
+ "(%Q, %Q, %Q, NULL, %Q)",
+ tbl->parent_table, attr->attr_name,
+ "collapsed from child node", xml);
+ sqlite3_free (xml);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "INSERT INTO xml_metacatalog_columns: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ }
+ /* updating xml_metacatalog_columns (child) */
+ xml =
+ sqlite3_mprintf ("collapsed into \"%s\".\"%s\"",
+ tbl->parent_table, attr->attr_name);
+ sql =
+ sqlite3_mprintf
+ ("UPDATE xml_metacatalog_columns SET destination = %Q "
+ "WHERE table_name = %Q AND column_name = %Q", xml,
+ tbl->table_name, attr->attr_name);
+ sqlite3_free (xml);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "UPDATE xml_metacatalog_columns: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ }
+ attr = attr->next;
+ }
+
+/* committing the transaction */
+ ret = sqlite3_exec (db_handle, "COMMIT", NULL, NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "COMMIT error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ }
+
+ stop:
+ if (sel_stmt != NULL)
+ sqlite3_finalize (sel_stmt);
+ if (upd_stmt != NULL)
+ sqlite3_finalize (upd_stmt);
+ if (error)
+ return 0;
+ return 1;
+}
+
+static void
+get_xml_references (sqlite3 * db_handle, struct new_attributes *list,
+ const char *table)
+{
+/* fetching the xml_references for any column to be collapsed */
+ struct xml_attribute *attr = list->first;
+ while (attr != NULL)
+ {
+ int ret;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int len;
+ const char *name;
+ char *sql;
+ if (attr->main_collapsed)
+ sql = sqlite3_mprintf ("SELECT xml_reference "
+ "FROM xml_metacatalog_columns "
+ "WHERE table_name = %Q AND column_name = %Q",
+ table, "node_value");
+ else
+ sql = sqlite3_mprintf ("SELECT xml_reference "
+ "FROM xml_metacatalog_columns "
+ "WHERE table_name = %Q AND column_name = %Q",
+ table, attr->attr_name);
+ ret =
+ sqlite3_get_table (db_handle, sql, &results, &rows, &columns,
+ NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT xml_referemce error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto default_ref;
+ }
+ if (rows < 1)
+ {
+ sqlite3_free_table (results);
+ goto default_ref;
+ }
+ for (i = 1; i <= rows; i++)
+ {
+ name = results[(i * columns) + 0];
+ if (attr->xml_reference != NULL)
+ free (attr->xml_reference);
+ len = strlen (name);
+ attr->xml_reference = malloc (len + 1);
+ strcpy (attr->xml_reference, name);
+ }
+ sqlite3_free_table (results);
+ attr = attr->next;
+ continue;
+ default_ref:
+ name = "?unknown?";
+ if (attr->xml_reference != NULL)
+ free (attr->xml_reference);
+ len = strlen (name);
+ attr->xml_reference = malloc (len + 1);
+ strcpy (attr->xml_reference, name);
+ attr = attr->next;
+ }
+}
+
+static int
+test_index (sqlite3 * db_handle, const char *table, const char *column)
+{
+/* tests if an index exists */
+ int ret;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int ok = 0;
+
+/* checking the expected columns */
+ char *idx = sqlite3_mprintf ("idx_%s_%s", table, column);
+ char *sql = sqlite3_mprintf ("SELECT name FROM sqlite_master "
+ "WHERE type = 'index' AND tbl_name = %Q AND name = %Q",
+ table, idx);
+ sqlite3_free (idx);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM sqlite_master error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ ok = 1;
+ }
+ sqlite3_free_table (results);
+ return ok;
+}
+
+static struct new_attributes *
+upgrade_parent (sqlite3 * db_handle, const char *table, const char *parent,
+ const char *attr_name, const char *geometry_name)
+{
+/* attempting to upgrade the parent table */
+ int ret;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int error = 0;
+ struct new_attributes *list = alloc_new_attributes ();
+ char *sql;
+ struct xml_attribute *attr;
+
+/* inserting the tag name itself */
+ add_attribute (list, attr_name, 1);
+
+/* extracting the column (XML Attributes) names from the Child Table */
+ sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA table_info[Child] error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto done;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, "node_id") == 0)
+ continue;
+ if (strcmp (name, "parent_id") == 0)
+ continue;
+ if (strcmp (name, "node_value") == 0)
+ continue;
+ add_attribute (list, name, 0);
+ }
+ }
+ sqlite3_free_table (results);
+
+/* extracting the column (XML Attributes) names from the Parent Table */
+ sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", parent);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA table_info[Parent] error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto done;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ check_attribute (list, name);
+ }
+ }
+ sqlite3_free_table (results);
+
+ if (list->collision)
+ {
+ error = 1;
+ goto done;
+ }
+
+ attr = list->first;
+ while (attr != NULL)
+ {
+ /* adding the new Columns to the Parent Table */
+ const char *type = "TEXT";
+ if (geometry_name != NULL)
+ {
+ if (strcmp (geometry_name, attr->attr_name) == 0)
+ type = "BLOB";
+ }
+ sql =
+ sqlite3_mprintf ("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s",
+ parent, attr->attr_name, type);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "ALTER TABLE error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ error = 1;
+ goto done;
+ }
+ attr = attr->next;
+ }
+
+ attr = list->first;
+ while (attr != NULL)
+ {
+ if (strcmp (attr->attr_name, "gml_id") == 0)
+ {
+ if (test_index (db_handle, table, "gml_id"))
+ {
+ /* creating an Index supporting "gml_id" */
+ sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+ "\"idx_%s_gml_id\" ON \"%s\" (gml_id)",
+ parent, parent);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr,
+ "CREATE INDEX [gml_id] error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ error = 1;
+ goto done;
+ }
+ }
+ }
+ if (strcmp (attr->attr_name, "xlink_href") == 0)
+ {
+ if (test_index (db_handle, table, "xlink_href"))
+ {
+ /* creating an Index supporting "xlink_href" */
+ sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+ "\"idx_%s_xlink_href\" ON \"%s\" (xlink_href)",
+ parent, parent);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr,
+ "CREATE INDEX [xlink_href] error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ error = 1;
+ goto done;
+ }
+ }
+ }
+ attr = attr->next;
+ }
+
+ done:
+ if (error)
+ {
+ destroy_new_attributes (list);
+ return NULL;
+ }
+ return list;
+}
+
+static int
+check_collapsible (sqlite3 * db_handle, const char *table, const char *parent)
+{
+/* tests if this table could be collapsed as an XML parent Attribute */
+ char *sql;
+ int ret;
+ char *err_msg = NULL;
+ int multi = 0;
+ sqlite3_stmt *stmt;
+
+ sql = sqlite3_mprintf ("SELECT p.node_id, Count(*) AS cnt "
+ "FROM \"%s\" AS c JOIN \"%s\" AS p ON (p.node_id = c.parent_id) "
+ "GROUP BY p.node_id HAVING cnt > 1", table, parent);
+ ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT multi-values: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ while (1)
+ {
+ /* scrolling the result set rows */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ multi++;
+ }
+ sqlite3_finalize (stmt);
+ if (multi > 0)
+ return 0;
+
+ return 1;
+}
+
+static char *
+check_xml_child_table (sqlite3 * db_handle, const char *table)
+{
+/* tests if this table seems to be an XML child table */
+ int ret;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int ok_pk = 0;
+ int ok_fk = 0;
+ int ok_value = 0;
+ int error = 0;
+ char *parent = NULL;
+ int fk = 0;
+
+/* checking the expected columns */
+ char *sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", table);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA table_info error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return NULL;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, "node_id") == 0)
+ {
+ if (atoi (results[(i * columns) + 5]) == 1)
+ ok_pk = 1;
+ }
+ else if (atoi (results[(i * columns) + 5]) == 1)
+ error = 1;
+ if (strcmp (name, "parent_id") == 0)
+ ok_fk = 1;
+ if (strcmp (name, "node_value") == 0)
+ ok_value = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ if (error)
+ return NULL;
+ if (ok_pk == 0)
+ return NULL;
+ if (ok_fk == 0)
+ return NULL;
+ if (ok_value == 0)
+ return NULL;
+
+/* checking the Foreing Key */
+ sql = sqlite3_mprintf ("PRAGMA foreign_key_list(\"%s\")", table);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA foreign_key_list error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return NULL;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ int len;
+ const char *name = results[(i * columns) + 2];
+ if (parent != NULL)
+ free (parent);
+ len = strlen (name);
+ parent = malloc (len + 1);
+ strcpy (parent, name);
+ fk++;
+ if (strcmp (results[(i * columns) + 3], "parent_id") != 0
+ || strcmp (results[(i * columns) + 4], "node_id") != 0)
+ error = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ if (error || fk != 1)
+ {
+ if (parent != NULL)
+ free (parent);
+ return NULL;
+ }
+
+ return parent;
+}
+
+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
+check_xml_metacatalog (sqlite3 * db_handle)
+{
+/* checking if XML-metacatalog tables do really exist */
+ int ret;
+ const char *sql;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int ok_table_name = 0;
+ int ok_tree_level = 0;
+ int ok_xml_tag_namespace = 0;
+ int ok_xml_tag_name = 0;
+ int ok_parent_table_name = 0;
+ int ok_gml_geometry_column = 0;
+ int ok_status = 0;
+ int ok_column_name = 0;
+ int ok_origin = 0;
+ int ok_destination = 0;
+ int ok_xml_reference = 0;
+ int error = 0;
+
+/* checking xml_metacatalog_tables */
+ sql = "PRAGMA table_info(xml_metacatalog_tables)";
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA xml_metacatalog_tables error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ goto done;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, "table_name") == 0)
+ ok_table_name = 1;
+ if (strcmp (name, "tree_level") == 0)
+ ok_tree_level = 1;
+ if (strcmp (name, "xml_tag_namespace") == 0)
+ ok_xml_tag_namespace = 1;
+ if (strcmp (name, "xml_tag_name") == 0)
+ ok_xml_tag_name = 1;
+ if (strcmp (name, "parent_table_name") == 0)
+ ok_parent_table_name = 1;
+ if (strcmp (name, "gml_geometry_column") == 0)
+ ok_gml_geometry_column = 1;
+ if (strcmp (name, "status") == 0)
+ ok_status = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ if (ok_table_name && ok_tree_level && ok_xml_tag_namespace
+ && ok_xml_tag_name && ok_parent_table_name && ok_gml_geometry_column
+ && ok_status)
+ ;
+ else
+ {
+ error = 1;
+ goto done;
+ }
+ ok_table_name = 0;
+
+/* checking xml_metacatalog_columns */
+ sql = "PRAGMA table_info(xml_metacatalog_columns)";
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA xml_metacatalog_columns error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ goto done;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, "table_name") == 0)
+ ok_table_name = 1;
+ if (strcmp (name, "column_name") == 0)
+ ok_column_name = 1;
+ if (strcmp (name, "origin") == 0)
+ ok_origin = 1;
+ if (strcmp (name, "destination") == 0)
+ ok_destination = 1;
+ if (strcmp (name, "xml_reference") == 0)
+ ok_xml_reference = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ if (ok_table_name && ok_column_name && ok_origin && ok_destination
+ && ok_xml_reference)
+ ;
+ else
+ {
+ error = 1;
+ goto done;
+ }
+
+ done:
+ if (error)
+ 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];
+
+ *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);
+ db_handle = NULL;
+ return;
+ }
+
+ if (!check_xml_metacatalog (db_handle))
+ {
+ fprintf (stderr,
+ "XML-metacatalog not found or invalid ... cowardly quitting\n");
+ 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);
+ }
+
+/* enabling PK/FK constraints */
+ sqlite3_exec (db_handle, "PRAGMA foreign_keys = 1", NULL, NULL, NULL);
+ *handle = db_handle;
+ return;
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+ fprintf (stderr, "\n\nusage: spatialite_xml_collapse 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\n");
+ fprintf (stderr, "you can specify the following options as well\n");
+ fprintf (stderr,
+ "-dd or --delete-duplicates remove all duplicate rows except one\n");
+ fprintf (stderr,
+ "-nl or --nl-level num tree-level for table-names (dft: 0)\n\n");
+ fprintf (stderr,
+ "-jo or --journal-off unsafe [but faster] mode\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");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+ sqlite3 *handle;
+ char *err_msg = NULL;
+ int ret;
+ int i;
+ int error = 0;
+ int next_arg = ARG_NONE;
+ const char *db_path = NULL;
+ int delete_duplicates = 0;
+ int name_level = -1;
+ int in_memory = 0;
+ int cache_size = 0;
+ int journal_off = 0;
+ void *cache;
+ const char *sql;
+ char **results;
+ int rows;
+ int columns;
+ int loop_again = 1;
+ struct xml_geometry *geom;
+ struct xml_tables_list *catalog = alloc_xml_tables ();
+
+ 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_CACHE_SIZE:
+ cache_size = atoi (argv[i]);
+ break;
+ case ARG_NAME_LEVEL:
+ name_level = atoi (argv[i]);
+ 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], "--cache-size") == 0
+ || strcmp (argv[i], "-cs") == 0)
+ {
+ next_arg = ARG_CACHE_SIZE;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--name-level") == 0
+ || strcmp (argv[i], "-nl") == 0)
+ {
+ next_arg = ARG_NAME_LEVEL;
+ 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;
+ }
+ 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], "-dd") == 0)
+ {
+ delete_duplicates = 1;
+ next_arg = ARG_NONE;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--delete-duplicates") == 0)
+ {
+ delete_duplicates = 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 (delete_duplicates && name_level < 0)
+ {
+ fprintf (stderr, "--delete-duplicates requires --name-level\n");
+ error = 1;
+ }
+ if (error)
+ {
+ do_help ();
+ return -1;
+ }
+
+/* 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);
+ }
+
+/* identifying the tables to be (possibly) collapsed */
+ sql =
+ "SELECT table_name, parent_table_name, xml_tag_namespace, xml_tag_name, "
+ "gml_geometry_column, tree_level FROM xml_metacatalog_tables "
+ "WHERE status LIKE 'raw %'";
+ ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM xml_metacatalog_tables error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ goto abort;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *table = results[(i * columns) + 0];
+ const char *parent = results[(i * columns) + 1];
+ const char *tag_ns = results[(i * columns) + 2];
+ const char *tag_name = results[(i * columns) + 3];
+ const char *geometry = results[(i * columns) + 4];
+ int level = atoi (results[(i * columns) + 5]);
+ add_xml_table (catalog, table, parent, tag_ns, tag_name,
+ geometry, level);
+ }
+ }
+ sqlite3_free_table (results);
+
+ identify_childs (catalog);
+ while (loop_again)
+ {
+ /* iteratively attempting to collapse */
+ struct xml_table *tbl = catalog->first;
+ loop_again = 0;
+ while (tbl != NULL)
+ {
+ if (tbl->first == NULL && tbl->done == 0)
+ {
+ char *parent =
+ check_xml_child_table (handle, tbl->table_name);
+ loop_again = 1;
+ tbl->done = 1;
+ if (parent != NULL)
+ {
+ if (check_collapsible
+ (handle, tbl->table_name, parent))
+ {
+ struct new_attributes *list =
+ upgrade_parent (handle, tbl->table_name,
+ parent, tbl->tag_name,
+ tbl->geometry);
+ if (list != NULL)
+ {
+ get_xml_references (handle, list,
+ tbl->table_name);
+ ret =
+ collapse_table (handle, journal_off,
+ list,
+ tbl->table_name,
+ parent, tbl);
+ destroy_new_attributes (list);
+ if (!ret)
+ {
+ fprintf (stderr,
+ "Unable to collapse \"%s\"\n",
+ tbl->table_name);
+ free (parent);
+ goto abort;
+ }
+ }
+ }
+ free (parent);
+ }
+ }
+ tbl = tbl->next;
+ }
+ }
+
+ if (delete_duplicates)
+ {
+ /* deleting duplicates */
+ struct xml_table *tbl = catalog->first;
+ while (tbl != NULL)
+ {
+ if (tbl->level == name_level)
+ remove_duplicates (handle, tbl);
+ tbl = tbl->next;
+ }
+ }
+
+/* identifying the Geometries to be (possibly) recovered */
+ sql =
+ "SELECT table_name, column_name FROM xml_metacatalog_columns "
+ "WHERE origin LIKE 'GeomFromGml%'";
+ ret = sqlite3_get_table (handle, sql, &results, &rows, &columns, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM xml_metacatalog_columns error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ goto abort;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *table = results[(i * columns) + 0];
+ const char *geometry = results[(i * columns) + 1];
+ add_xml_geometry (catalog, table, geometry);
+ }
+ }
+ sqlite3_free_table (results);
+
+ geom = catalog->first_geom;
+ while (geom != NULL)
+ {
+ check_geometry (handle, geom);
+ if (geom->type != NULL)
+ recover_geometry (handle, geom);
+ geom = geom->next;
+ }
+
+ abort:
+ destroy_xml_tables (catalog);
+
+ 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");
+ }
+ sqlite3_close (handle);
+ spatialite_cleanup_ex (cache);
+ return 0;
+}
diff --git a/spatialite_xml_load.c b/spatialite_xml_load.c
new file mode 100644
index 0000000..247d95a
--- /dev/null
+++ b/spatialite_xml_load.c
@@ -0,0 +1,2837 @@
+/*
+/ spatialite_xml_load
+/
+/ a tool loading any XML into SQLite tables
+/
+/ version 1.0, 2013 August 14
+/
+/ 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 <sys/time.h>
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <expat.h>
+
+#include "config.h"
+
+#ifdef SPATIALITE_AMALGAMATION
+#include <spatialite/sqlite3.h>
+#else
+#include <sqlite3.h>
+#endif
+#include <spatialite.h>
+
+#define BUFFSIZE 8192
+
+#define ARG_NONE 0
+#define ARG_XML_PATH 1
+#define ARG_DB_PATH 2
+#define ARG_NAME_LEVEL 3
+#define ARG_PARENT_LEVELS 4
+#define ARG_CACHE_SIZE 5
+
+struct gmlDynBuffer
+{
+/* a struct handling a dynamically growing output buffer */
+ char *Buffer;
+ size_t WriteOffset;
+ size_t BufferSize;
+ int Error;
+};
+
+struct sql_table
+{
+/* a SQL table name */
+ char *table_name;
+ char *parent_table;
+ struct xml_tag *tag;
+ sqlite3_stmt *ins_stmt;
+ sqlite3_stmt *upd_stmt;
+ sqlite3_int64 current;
+ struct sql_table *next;
+};
+
+struct xml_attr
+{
+/* an XML attribute <tag attr="value"> */
+ char *attr_ns;
+ char *attr_name;
+ char *attr_value;
+ int exists;
+ struct xml_attr *next;
+};
+
+struct xml_tag
+{
+/* an XML node <tag name> */
+ char *tag_ns;
+ char *tag_name;
+ char *full_name;
+ char *unique_name;
+ int unique_level;
+ int has_geometry;
+ int tree_level;
+ struct xml_attr *first_attr;
+ struct xml_attr *last_attr;
+ struct xml_tag *parent;
+ struct sql_table *table;
+ struct xml_tag *next;
+};
+
+struct stack_entry
+{
+/* an entry into the tag stack */
+ char *tag_ns;
+ char *tag_name;
+ struct stack_entry *prev;
+};
+
+struct xml_params
+{
+/* an auxiliary struct used for GML parsing */
+ char *filename;
+ sqlite3 *db_handle;
+ int journal_off;
+ int collapsed_gml;
+ int xlink_href;
+ char *CharData;
+ int CharDataLen;
+ int CharDataMax;
+ int CharDataStep;
+ int parse_error;
+ int db_error;
+ struct xml_tag *first_tag;
+ struct xml_tag *last_tag;
+ struct xml_tag **sort_array;
+ int count_array;
+ struct sql_table *first_table;
+ struct sql_table *last_table;
+ struct stack_entry *stack;
+ int CollapsingGML;
+ struct gmlDynBuffer *CollapsedGML;
+ char *CollapsedGMLMarker;
+ int treeLevel;
+};
+
+static struct gmlDynBuffer *
+gmlDynBufferAlloc (void)
+{
+/* creating and initializing a dynamically growing output buffer */
+ struct gmlDynBuffer *buf = malloc (sizeof (struct gmlDynBuffer));
+ buf->Buffer = NULL;
+ buf->WriteOffset = 0;
+ buf->BufferSize = 0;
+ buf->Error = 0;
+ return buf;
+}
+
+static void
+gmlDynBufferDestroy (struct gmlDynBuffer *buf)
+{
+/* cleaning a dynamically growing output buffer */
+ if (buf == NULL)
+ return;
+ if (buf->Buffer)
+ free (buf->Buffer);
+ free (buf);
+}
+
+static void
+gmlDynBufferAppend (struct gmlDynBuffer *buf, const char *payload, size_t size)
+{
+/* appending into the buffer */
+ size_t free_size = buf->BufferSize - buf->WriteOffset;
+ if (size > free_size)
+ {
+ /* we must allocate a bigger buffer */
+ size_t new_size;
+ char *new_buf;
+ if (buf->BufferSize == 0)
+ new_size = size + 1024;
+ else if (buf->BufferSize <= 4196)
+ new_size = buf->BufferSize + size + 4196;
+ else if (buf->BufferSize <= 65536)
+ new_size = buf->BufferSize + size + 65536;
+ else
+ new_size = buf->BufferSize + size + (1024 * 1024);
+ new_buf = malloc (new_size);
+ if (!new_buf)
+ {
+ buf->Error = 1;
+ return;
+ }
+ if (buf->Buffer)
+ {
+ memcpy (new_buf, buf->Buffer, buf->WriteOffset);
+ free (buf->Buffer);
+ }
+ buf->Buffer = new_buf;
+ buf->BufferSize = new_size;
+ }
+ memcpy (buf->Buffer + buf->WriteOffset, payload, size);
+ buf->WriteOffset += size;
+}
+
+static void
+xmlCharData (void *data, const XML_Char * s, int len)
+{
+/* parsing XML char data */
+ struct xml_params *params = (struct xml_params *) data;
+ if ((params->CharDataLen + len) > params->CharDataMax)
+ {
+ /* we must increase the CharData buffer size */
+ void *new_buf;
+ int new_size = params->CharDataMax;
+ while (new_size < params->CharDataLen + len)
+ new_size += params->CharDataStep;
+ new_buf = realloc (params->CharData, new_size);
+ if (new_buf)
+ {
+ params->CharData = new_buf;
+ params->CharDataMax = new_size;
+ }
+ }
+ memcpy (params->CharData + params->CharDataLen, s, len);
+ params->CharDataLen += len;
+}
+
+static int
+valid_char_data (struct xml_params *params)
+{
+/* testing if Char Data are meaningfull */
+ int valid = 0;
+ if (params->CharDataLen > 0)
+ {
+ int i;
+ for (i = 0; i < params->CharDataLen; i++)
+ {
+ if (*(params->CharData + i) == ' ')
+ continue;
+ if (*(params->CharData + i) == '\t')
+ continue;
+ if (*(params->CharData + i) == '\r')
+ continue;
+ if (*(params->CharData + i) == '\n')
+ continue;
+ valid = 1;
+ break;
+ }
+ }
+ return valid;
+}
+
+static int
+tag_compare (const void *p1, const void *p2)
+{
+/* comparison function for QSort and BSearch*/
+ int ret;
+ struct xml_tag *tag1 = *((struct xml_tag **) p1);
+ struct xml_tag *tag2 = *((struct xml_tag **) p2);
+ ret = strcmp (tag1->full_name, tag2->full_name);
+ if (ret != 0)
+ return ret;
+ if (tag1->tag_ns == NULL && tag2->tag_ns != NULL)
+ return -1;
+ if (tag1->tag_ns != NULL && tag2->tag_ns == NULL)
+ return 1;
+ if (tag1->tag_ns != NULL && tag2->tag_ns != NULL)
+ {
+ ret = strcmp (tag1->tag_ns, tag2->tag_ns);
+ if (ret != 0)
+ return ret;
+ }
+ return strcmp (tag1->tag_name, tag2->tag_name);
+}
+
+static void
+sort_tag_array (struct xml_params *params)
+{
+/* updating the Sorted Tags Array */
+ int count = 0;
+ struct xml_tag *tag = params->first_tag;
+ while (tag != NULL)
+ {
+ /* counting how many tags are there */
+ count++;
+ tag = tag->next;
+ }
+ if (params->sort_array != NULL)
+ free (params->sort_array);
+/* allocating the array */
+ params->count_array = count;
+ params->sort_array = malloc (sizeof (struct xml_tag **) * count);
+ count = 0;
+ tag = params->first_tag;
+ while (tag != NULL)
+ {
+ /* inserting the pointers into the array */
+ *(params->sort_array + count++) = tag;
+ tag = tag->next;
+ }
+ qsort (params->sort_array, params->count_array, sizeof (struct xml_tag *),
+ tag_compare);
+}
+
+static struct xml_attr *
+alloc_attr (char *ns, char *name)
+{
+/* allocating and initializing an attribute */
+ struct xml_attr *attr = malloc (sizeof (struct xml_attr));
+ attr->attr_ns = ns;
+ attr->attr_name = name;
+ attr->attr_value = NULL;
+ attr->exists = 0;
+ attr->next = NULL;
+ return attr;
+}
+
+static void
+destroy_attr (struct xml_attr *attr)
+{
+/* memory cleanup - freeing an attribute */
+ if (attr == NULL)
+ return;
+ if (attr->attr_ns != NULL)
+ free (attr->attr_ns);
+ if (attr->attr_name != NULL)
+ free (attr->attr_name);
+ if (attr->attr_value != NULL)
+ free (attr->attr_value);
+ free (attr);
+}
+
+static struct sql_table *
+alloc_table (char *table_name, char *parent_table)
+{
+/* allocating and initializing a SQL Table */
+ int len;
+ int i;
+ struct sql_table *table = malloc (sizeof (struct sql_table));
+ table->table_name = table_name;
+ if (table_name != NULL)
+ {
+ len = strlen (table->table_name);
+ for (i = 0; i < len; i++)
+ {
+ char c = *(table->table_name + i);
+ if (c >= 'A' && c <= 'Z')
+ {
+ /* forcing to lowercase */
+ c = c - 'A' + 'a';
+ *(table->table_name + i) = c;
+ }
+ }
+ }
+ table->parent_table = parent_table;
+ if (parent_table != NULL)
+ {
+ len = strlen (table->parent_table);
+ for (i = 0; i < len; i++)
+ {
+ char c = *(table->parent_table + i);
+ if (c >= 'A' && c <= 'Z')
+ {
+ /* forcing to lowercase */
+ c = c - 'A' + 'a';
+ *(table->parent_table + i) = c;
+ }
+ }
+ }
+ table->tag = NULL;
+ table->ins_stmt = NULL;
+ table->upd_stmt = NULL;
+ table->current = 0;
+ table->next = NULL;
+ return table;
+}
+
+static void
+destroy_table (struct sql_table *table)
+{
+/* memory cleanup - freeing a SQL Table */
+ if (table == NULL)
+ return;
+ if (table->ins_stmt != NULL)
+ sqlite3_finalize (table->ins_stmt);
+ if (table->upd_stmt != NULL)
+ sqlite3_finalize (table->upd_stmt);
+ free (table);
+}
+
+static struct xml_tag *
+alloc_tag (const char *tag_ns, const char *tag_name, char *full_name,
+ struct xml_tag *parent)
+{
+/* allocating and initializing a tag */
+ int len;
+ struct xml_tag *tag = malloc (sizeof (struct xml_tag));
+ if (tag_ns == NULL)
+ tag->tag_ns = NULL;
+ else
+ {
+ len = strlen (tag_ns);
+ tag->tag_ns = malloc (len + 1);
+ strcpy (tag->tag_ns, tag_ns);
+ }
+ len = strlen (tag_name);
+ tag->tag_name = malloc (len + 1);
+ strcpy (tag->tag_name, tag_name);
+ tag->full_name = full_name;
+ tag->unique_name = NULL;
+ tag->first_attr = NULL;
+ tag->last_attr = NULL;
+ tag->parent = parent;
+ tag->unique_level = -1;
+ tag->table = NULL;
+ tag->has_geometry = 0;
+ tag->tree_level = -1;
+ tag->next = NULL;
+ return tag;
+}
+
+static void
+destroy_tag (struct xml_tag *tag)
+{
+/* memory cleanup - freeing a tag */
+ struct xml_attr *pa;
+ struct xml_attr *pan;
+ if (tag == NULL)
+ return;
+ if (tag->tag_ns != NULL)
+ free (tag->tag_ns);
+ if (tag->tag_name != NULL)
+ free (tag->tag_name);
+ if (tag->full_name != NULL)
+ sqlite3_free (tag->full_name);
+ if (tag->unique_name != NULL)
+ sqlite3_free (tag->unique_name);
+ pa = tag->first_attr;
+ while (pa != NULL)
+ {
+ pan = pa->next;
+ destroy_attr (pa);
+ pa = pan;
+ }
+ free (tag);
+}
+
+static void
+reset_tag_attributes (struct xml_tag *tag)
+{
+/* resetting XML attributes to NULL */
+ struct xml_attr *attr = tag->first_attr;
+ while (attr != NULL)
+ {
+ if (attr->attr_value != NULL)
+ free (attr->attr_value);
+ attr->attr_value = NULL;
+ attr = attr->next;
+ }
+}
+
+static struct xml_tag *
+find_tag (struct xml_params *params, const char *tag_ns, const char *tag_name,
+ const char *full_name)
+{
+/* attempts to find if some XML Node tag is already defined */
+ struct xml_tag item;
+ struct xml_tag *p_item = &item;
+ struct xml_tag *found;
+ void *x;
+ if (params->sort_array == NULL)
+ return NULL;
+ item.tag_ns = (char *) tag_ns;
+ item.tag_name = (char *) tag_name;
+ item.full_name = (char *) full_name;
+ x = bsearch (&p_item, params->sort_array, params->count_array,
+ sizeof (struct xml_tag *), tag_compare);
+ if (x == NULL)
+ return NULL;
+ found = *((struct xml_tag **) x);
+ return found;
+}
+
+static struct xml_tag *
+append_tag (struct xml_params *params, const char *tag_ns,
+ const char *tag_name, char *full_name, struct xml_tag *parent)
+{
+/* appending an XML Node tag */
+ struct xml_tag *tag = alloc_tag (tag_ns, tag_name, full_name, parent);
+ tag->tree_level = params->treeLevel;
+ if (params->first_tag == NULL)
+ params->first_tag = tag;
+ if (params->last_tag != NULL)
+ params->last_tag->next = tag;
+ params->last_tag = tag;
+ sort_tag_array (params);
+ return tag;
+}
+
+static struct xml_attr *
+find_attr (struct xml_tag *tag, const char *ns, const char *name)
+{
+/* attempts to find if some Attribute is already defined */
+ struct xml_attr *p = tag->first_attr;
+ while (p != NULL)
+ {
+ if (p->attr_ns == NULL && ns == NULL)
+ {
+ if (strcmp (p->attr_name, name) == 0)
+ return p;
+ }
+ if (p->attr_ns != NULL && ns != NULL)
+ {
+ if (strcmp (p->attr_ns, ns) == 0
+ && strcmp (p->attr_name, name) == 0)
+ return p;
+ }
+ p = p->next;
+ }
+ return NULL;
+}
+
+static void
+append_attribute (struct xml_tag *tag, char *ns, char *name)
+{
+/* appending an attribute to an XML Node */
+ struct xml_attr *attr = find_attr (tag, ns, name);
+ if (attr != NULL)
+ {
+ /* already existing */
+ if (ns != NULL)
+ free (ns);
+ if (name != NULL)
+ free (name);
+ return;
+ }
+ attr = alloc_attr (ns, name);
+ if (tag->first_attr == NULL)
+ tag->first_attr = attr;
+ if (tag->last_attr != NULL)
+ tag->last_attr->next = attr;
+ tag->last_attr = attr;
+}
+
+static void
+set_attribute_value (struct xml_tag *tag, const char *ns, const char *name,
+ const char *value)
+{
+/* setting some value to an Attribute */
+ int len;
+ struct xml_attr *attr = find_attr (tag, ns, name);
+ if (attr == NULL)
+ return;
+ len = strlen (value);
+ if (attr->attr_value != NULL)
+ free (attr->attr_value);
+ attr->attr_value = malloc (len + 1);
+ strcpy (attr->attr_value, value);
+}
+
+static void
+push_stack (struct xml_params *params, char *tag_ns, char *tag_name)
+{
+/* pushing an item into the tag stack */
+ struct stack_entry *entry = malloc (sizeof (struct stack_entry));
+ entry->tag_ns = tag_ns;
+ entry->tag_name = tag_name;
+ entry->prev = params->stack;
+ params->stack = entry;
+}
+
+static void
+pop_stack (struct xml_params *params)
+{
+/* popping an item from the tag stack */
+ struct stack_entry *entry = params->stack;
+ if (entry != NULL)
+ {
+ params->stack = entry->prev;
+ if (entry->tag_ns != NULL)
+ free (entry->tag_ns);
+ if (entry->tag_name != NULL)
+ free (entry->tag_name);
+ free (entry);
+ }
+}
+
+static void
+append_table (struct xml_params *ptr, struct xml_tag *xml, char *table_name,
+ char *parent_table)
+{
+/* appends a SQL Table definition */
+ struct sql_table *tbl = alloc_table (table_name, parent_table);
+ xml->table = tbl;
+ tbl->tag = xml;
+ if (ptr->first_table == NULL)
+ ptr->first_table = tbl;
+ if (ptr->last_table != NULL)
+ ptr->last_table->next = tbl;
+ ptr->last_table = tbl;
+}
+
+static char *
+build_unique_name (struct xml_tag *tag, int name_level, int parent_levels)
+{
+/* building a qualified tag name */
+ int i;
+ char *str = NULL;
+ struct xml_tag *parent = tag->parent;
+ if (tag->tree_level <= name_level)
+ {
+ /* above the limit: main branches of the tree -> "child_parent" */
+ if (parent == NULL)
+ str = sqlite3_mprintf ("%s", tag->tag_name);
+ else
+ str = sqlite3_mprintf ("%s_%s", parent->tag_name, tag->tag_name);
+ }
+ else
+ {
+ /* under the limit: expanding a full tree branch */
+ int cnt = 0;
+ int max = 999999;
+ if (parent_levels >= 0)
+ max = parent_levels;
+ str = sqlite3_mprintf ("%s", tag->tag_name);
+ for (i = tag->tree_level - 1; i >= name_level; i--)
+ {
+ char *tmp;
+ if (parent == NULL)
+ {
+ sqlite3_free (str);
+ return NULL;
+ }
+ if (cnt < max || i == name_level)
+ {
+ tmp = sqlite3_mprintf ("%s_%s", parent->tag_name, str);
+ sqlite3_free (str);
+ str = tmp;
+ }
+ cnt++;
+ parent = parent->parent;
+ }
+ }
+ for (i = 0; i < (int) strlen (str); i++)
+ {
+ char c = *(str + i);
+ if (c >= 'A' && c <= 'Z')
+ *(str + i) = c - 'A' + 'a';
+ }
+ return str;
+}
+
+static void
+set_unique_names (struct xml_params *ptr, int name_level, int parent_levels)
+{
+/* setting the appropriate Unique Names */
+ struct xml_tag *pt = ptr->first_tag;
+ while (pt != NULL)
+ {
+ char *candidate = build_unique_name (pt, name_level, parent_levels);
+ if (pt->unique_name != NULL)
+ sqlite3_free (pt->unique_name);
+ pt->unique_name = candidate;
+ pt = pt->next;
+ }
+}
+
+static void
+set_table_names (struct xml_params *ptr)
+{
+/* creating the SQL table names */
+ struct xml_tag *pt = ptr->first_tag;
+ while (pt != NULL)
+ {
+ struct xml_tag *parent = pt->parent;
+ char *table_name = pt->unique_name;
+ char *parent_table = NULL;
+ if (parent != NULL)
+ parent_table = parent->unique_name;
+ append_table (ptr, pt, table_name, parent_table);
+ pt = pt->next;
+ }
+}
+
+static void
+set_xml_filename (struct xml_params *ptr, const char *path)
+{
+/* saving the XML (input) filename */
+ int len = strlen (path);
+ char *xpath = malloc (len + 1);
+ const char *filename;
+ strcpy (xpath, path);
+ filename = basename (xpath);
+ len = strlen (filename);
+ ptr->filename = malloc (len + 1);
+ strcpy (ptr->filename, filename);
+ free (xpath);
+}
+
+static void
+params_cleanup (struct xml_params *ptr)
+{
+/* memory cleanup - params */
+ struct xml_tag *pt;
+ struct xml_tag *ptn;
+ struct sql_table *ps;
+ struct sql_table *psn;
+ if (ptr == NULL)
+ return;
+
+ pt = ptr->first_tag;
+ while (pt != NULL)
+ {
+ ptn = pt->next;
+ destroy_tag (pt);
+ pt = ptn;
+ }
+ while (1)
+ {
+ if (ptr->stack == NULL)
+ break;
+ pop_stack (ptr);
+ }
+ ps = ptr->first_table;
+ while (ps != NULL)
+ {
+ psn = ps->next;
+ destroy_table (ps);
+ ps = psn;
+ }
+ if (ptr->filename != NULL)
+ free (ptr->filename);
+ if (ptr->CharData != NULL)
+ free (ptr->CharData);
+ if (ptr->sort_array != NULL)
+ free (ptr->sort_array);
+ if (ptr->CollapsedGML != NULL)
+ gmlDynBufferDestroy (ptr->CollapsedGML);
+ if (ptr->CollapsedGMLMarker != NULL)
+ sqlite3_free (ptr->CollapsedGMLMarker);
+}
+
+static void
+split_namespace (const char *str, char **ns, char **name)
+{
+/* attempting to divide an XML identifier into a namespace and a name */
+ int i;
+ int len;
+ int pos = -1;
+ *ns = NULL;
+ *name = NULL;
+
+ len = strlen (str);
+ for (i = 0; i < len; i++)
+ {
+ if (str[i] == ':')
+ {
+ pos = i;
+ break;
+ }
+ }
+ if (pos < 0)
+ {
+ *name = malloc (len + 1);
+ strcpy (*name, str);
+ return;
+ }
+ *ns = malloc (pos + 1);
+ memset (*ns, '\0', pos + 1);
+ memcpy (*ns, str, pos);
+ len = strlen (str + pos + 1);
+ *name = malloc (len + 1);
+ strcpy (*name, str + pos + 1);
+}
+
+static int
+is_gml_geometry (const char *ns, const char *name)
+{
+/* testing a possible GML Geometry */
+ int is_gml = 0;
+ int is_gml_ns = 0;
+ if (strcmp (name, "Point") == 0)
+ is_gml = 1;
+ if (strcmp (name, "LineString") == 0)
+ is_gml = 1;
+ if (strcmp (name, "Curve") == 0)
+ is_gml = 1;
+ if (strcmp (name, "Polygon") == 0)
+ is_gml = 1;
+ if (strcmp (name, "MultiPoint") == 0)
+ is_gml = 1;
+ if (strcmp (name, "MultiLineString") == 0)
+ is_gml = 1;
+ if (strcmp (name, "MultiCurve") == 0)
+ is_gml = 1;
+ if (strcmp (name, "MultiPolygon") == 0)
+ is_gml = 1;
+ if (strcmp (name, "MultiSurface") == 0)
+ is_gml = 1;
+ if (strcmp (name, "MultiGeometry") == 0)
+ is_gml = 1;
+ if (ns == NULL)
+ is_gml_ns = 1;
+ else if (strcmp (ns, "gml") == 0)
+ is_gml_ns = 1;
+ if (!is_gml_ns)
+ is_gml = 0;
+ return is_gml;
+}
+
+static char *
+build_full_name (struct stack_entry *entry, const char *name)
+{
+/* building a fully qualified tag name */
+ int i;
+ char *str = NULL;
+ struct stack_entry *pe = entry;
+ while (pe != NULL)
+ {
+ if (str != NULL)
+ {
+ char *tmp = sqlite3_mprintf ("%s_%s", pe->tag_name, str);
+ sqlite3_free (str);
+ str = tmp;
+ }
+ else
+ str = sqlite3_mprintf ("%s", pe->tag_name);
+ pe = pe->prev;
+ }
+ if (str != NULL)
+ {
+ char *tmp = sqlite3_mprintf ("%s_%s", str, name);
+ sqlite3_free (str);
+ str = tmp;
+ }
+ else
+ str = sqlite3_mprintf ("%s", name);
+ for (i = 0; i < (int) strlen (str); i++)
+ {
+ char c = *(str + i);
+ if (c >= 'A' && c <= 'Z')
+ *(str + i) = c - 'A' + 'a';
+ }
+ return str;
+}
+
+static void
+start_tag_1 (void *data, const char *el, const char **attr)
+{
+/* XML element starting - Pass I */
+ const char **attrib = attr;
+ int count = 0;
+ const char *k;
+ char *ns = NULL;
+ char *name = NULL;
+ char *full_name = NULL;
+ char *parent_full_name = NULL;
+ struct xml_params *params = (struct xml_params *) data;
+ struct xml_tag *tag;
+ if (params->CollapsingGML)
+ {
+ /* collapsing GML Geometries */
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ return;
+ }
+ split_namespace (el, &ns, &name);
+ if (params->collapsed_gml)
+ {
+ /* attempting to collapse GML Geometries */
+ if (is_gml_geometry (ns, name))
+ {
+ if (ns != NULL)
+ free (ns);
+ if (name != NULL)
+ free (name);
+ params->CollapsingGML = 1;
+ if (params->CollapsedGMLMarker != NULL)
+ sqlite3_free (params->CollapsedGMLMarker);
+ params->CollapsedGMLMarker = sqlite3_mprintf ("%s", el);
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ return;
+ }
+ }
+ params->treeLevel += 1;
+ full_name = build_full_name (params->stack, name);
+ tag = find_tag (params, ns, name, full_name);
+ if (tag == NULL)
+ {
+ struct xml_tag *parent = NULL;
+ if (params->stack != NULL)
+ {
+ struct stack_entry *entry = params->stack;
+ parent_full_name =
+ build_full_name (entry->prev, entry->tag_name);
+ parent =
+ find_tag (params, entry->tag_ns, entry->tag_name,
+ parent_full_name);
+ sqlite3_free (parent_full_name);
+ }
+ tag = append_tag (params, ns, name, full_name, parent);
+ }
+ else
+ sqlite3_free (full_name);
+ push_stack (params, ns, name);
+ while (*attrib != NULL)
+ {
+ if ((count % 2) == 0)
+ k = *attrib;
+ else
+ {
+ split_namespace (k, &ns, &name);
+ append_attribute (tag, ns, name);
+ }
+ attrib++;
+ count++;
+ }
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+}
+
+static void
+end_tag_1 (void *data, const char *el)
+{
+/* XML element ending - Pass I */
+ struct xml_params *params = (struct xml_params *) data;
+ if (params->CollapsingGML)
+ {
+ /* collapsing GML Geometries */
+ if (strcmp (params->CollapsedGMLMarker, el) == 0)
+ {
+ char *full_name = build_full_name (params->stack->prev,
+ params->stack->tag_name);
+ struct xml_tag *tag = find_tag (params, params->stack->tag_ns,
+ params->stack->tag_name,
+ full_name);
+ sqlite3_free (full_name);
+ tag->has_geometry = 1;
+ params->CollapsingGML = 0;
+ }
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ return;
+ }
+ params->treeLevel -= 1;
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ pop_stack (params);
+}
+
+static int
+create_sql_table (sqlite3 * db_handle, struct sql_table *tbl, int xlink_href)
+{
+/* attempting to create a SQL Table (if not already existing) */
+ int ret;
+ char *err_msg = NULL;
+ char *sql;
+ struct xml_attr *attr;
+ int xlink_href_index = 0;
+ int gml_id_index = 0;
+ sql = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS \"%s\" (\n"
+ "node_id INTEGER PRIMARY KEY AUTOINCREMENT,\n",
+ tbl->table_name);
+ if (tbl->parent_table != NULL)
+ {
+ /* defining the Foreign Key column */
+ char *sql1 = sqlite3_mprintf ("%sparent_id INTEGER NOT NULL,\n", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ }
+ else
+ {
+ /* defining the "mtdapp_filename" column */
+ char *sql1 =
+ sqlite3_mprintf ("%smtdapp_filename TEXT NOT NULL,\n", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ }
+ attr = tbl->tag->first_attr;
+ while (attr != NULL)
+ {
+ /* defining any attribute column */
+ char *sql1;
+ if (xlink_href)
+ {
+ int is_xlink = 0;
+ int is_gml = 0;
+ if (attr->attr_ns != NULL)
+ {
+ if (strcmp (attr->attr_ns, "xlink") == 0)
+ is_xlink = 1;
+ if (strcmp (attr->attr_ns, "gml") == 0)
+ is_gml = 1;
+ }
+ if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+ {
+ sql1 =
+ sqlite3_mprintf ("%s\"%s\" TEXT,\n", sql,
+ "xlink_href");
+ sqlite3_free (sql);
+ sql = sql1;
+ xlink_href_index = 1;
+ attr = attr->next;
+ continue;
+ }
+ if (is_gml && strcmp (attr->attr_name, "id") == 0)
+ {
+ sql1 =
+ sqlite3_mprintf ("%s\"%s\" TEXT,\n", sql, "gml_id");
+ sqlite3_free (sql);
+ sql = sql1;
+ gml_id_index = 1;
+ attr = attr->next;
+ continue;
+ }
+ }
+ sql1 = sqlite3_mprintf ("%s\"%s\" TEXT,\n", sql, attr->attr_name);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ }
+ if (tbl->parent_table != NULL)
+ {
+ /* declaring the Foreign Key Constraint */
+ char *sql1;
+ if (tbl->tag->has_geometry)
+ {
+ sql1 =
+ sqlite3_mprintf
+ ("%snode_value TEXT,\nfrom_gml_geometry BLOB\n,"
+ "CONSTRAINT \"fk_%s\" FOREIGN KEY (parent_id) "
+ "REFERENCES \"%s\" (node_id) ON DELETE CASCADE)", sql,
+ tbl->table_name, tbl->parent_table);
+ }
+ else
+ {
+ sql1 = sqlite3_mprintf ("%snode_value TEXT,\n"
+ "CONSTRAINT \"fk_%s\" FOREIGN KEY (parent_id) "
+ "REFERENCES \"%s\" (node_id) ON DELETE CASCADE)",
+ sql, tbl->table_name,
+ tbl->parent_table);
+ }
+ sqlite3_free (sql);
+ sql = sql1;
+ }
+ else
+ {
+ /* root table */
+ char *sql1;
+ if (tbl->tag->has_geometry)
+ sql1 =
+ sqlite3_mprintf
+ ("%snode_value TEXT,\nfrom_gml_geometry BLOB)", sql);
+ else
+ sql1 = sqlite3_mprintf ("%snode_value TEXT)", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ }
+/* executing the SQL statement */
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CREATE TABLE error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+
+ if (tbl->parent_table != NULL)
+ {
+ /* creating an Index supporting the Foreign Key */
+ sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+ "\"idx_%s\" ON \"%s\" (parent_id)",
+ tbl->table_name, tbl->table_name);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CREATE INDEX [FK] error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ }
+
+ if (xlink_href_index)
+ {
+ /* creating an Index supporting the xlink_href column */
+ sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+ "\"idx_%s_xlink_href\" ON \"%s\" (xlink_href)",
+ tbl->table_name, tbl->table_name);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CREATE INDEX [xlink_href] error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ }
+
+ if (gml_id_index)
+ {
+ /* creating an Index supporting the gnk_id column */
+ sql = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS "
+ "\"idx_%s_gml_id\" ON \"%s\" (gml_id)",
+ tbl->table_name, tbl->table_name);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CREATE INDEX [gml_id] error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+check_baseline_table (sqlite3 * db_handle, struct sql_table *tbl)
+{
+/* checking the expected baseline definition for some table */
+ int ret;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ int ok_pk = 0;
+ int ok_fk = 0;
+ int ok_value = 0;
+ int error = 0;
+
+/* checking the expected columns */
+ char *sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", tbl->table_name);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA table_info error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ if (strcmp (name, "node_id") == 0)
+ {
+ if (atoi (results[(i * columns) + 5]) == 1)
+ ok_pk = 1;
+ else
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": column \"node_id\" isn't defined as a PRIMARY KEY\n",
+ tbl->table_name);
+ error = 1;
+ }
+ }
+ else if (atoi (results[(i * columns) + 5]) == 1)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": unexpected column \"%s\" defined as a PRIMARY KEY\n",
+ tbl->table_name, name);
+ error = 1;
+ }
+ if (strcmp (name, "parent_id") == 0)
+ ok_fk = 1;
+ if (strcmp (name, "node_value") == 0)
+ ok_value = 1;
+ }
+ }
+ sqlite3_free_table (results);
+ if (error)
+ return 0;
+ if (ok_pk == 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": unable to found the expected \"node_id\" PRIMARY KEY\n",
+ tbl->table_name);
+ return 0;
+ }
+ if (tbl->parent_table != NULL && ok_fk == 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": unable to found the expected \"parent_id\" column\n",
+ tbl->table_name);
+ return 0;
+ }
+ if (tbl->parent_table == NULL && ok_fk != 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": found an unexpected \"parent_id\" column\n",
+ tbl->table_name);
+ return 0;
+ }
+ if (ok_value == 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": unable to found the expected \"node_value\" column\n",
+ tbl->table_name);
+ return 0;
+ }
+
+ ok_fk = 0;
+ if (tbl->parent_table != NULL)
+ {
+ /* checking the Foreing Key */
+ char *sql = sqlite3_mprintf ("PRAGMA foreign_key_list(\"%s\")",
+ tbl->table_name);
+ ret =
+ sqlite3_get_table (db_handle, sql, &results, &rows, &columns,
+ NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA foreign_key_list error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 2];
+ if (strcmp (name, tbl->parent_table) != 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": mismatching FOREIGN KEY [references \"%s\"]\n",
+ tbl->table_name, name);
+ error = 1;
+ }
+ else
+ ok_fk = 1;
+ if (strcmp (results[(i * columns) + 3], "parent_id") != 0
+ || strcmp (results[(i * columns) + 4],
+ "node_id") != 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": mismatching FOREIGN KEY [not \"parent_id\" -> \"node_id\"]\n",
+ tbl->table_name);
+ error = 1;
+ }
+ }
+ }
+ sqlite3_free_table (results);
+ if (error)
+ return 0;
+ if (ok_fk == 0)
+ {
+ fprintf (stderr,
+ "TABLE \"%s\": unable to found the expected FOREIGN KEY\n",
+ tbl->table_name);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+upgrade_sql_table (sqlite3 * db_handle, struct sql_table *tbl, int xlink_href)
+{
+/* attempting to upgrade some table */
+ int ret;
+ char *err_msg = NULL;
+ char **results;
+ int rows;
+ int columns;
+ int i;
+ struct xml_attr *attr;
+
+/* checking the attribute columns */
+ char *sql = sqlite3_mprintf ("PRAGMA table_info(\"%s\")", tbl->table_name);
+ ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "PRAGMA table_info error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ if (rows < 1)
+ ;
+ else
+ {
+ for (i = 1; i <= rows; i++)
+ {
+ const char *name = results[(i * columns) + 1];
+ attr = tbl->tag->first_attr;
+ while (attr != NULL)
+ {
+ if (xlink_href)
+ {
+ /* special cases: xlink_href and gml_id */
+ int is_xlink = 0;
+ int is_gml = 0;
+ if (attr->attr_ns != NULL)
+ {
+ if (strcmp (attr->attr_ns, "xlink") == 0)
+ is_xlink = 1;
+ if (strcmp (attr->attr_ns, "gml") == 0)
+ is_gml = 1;
+ }
+ if (is_xlink
+ && strcmp (attr->attr_name, "href") == 0)
+ {
+ if (strcmp (name, "xlink_href") == 0)
+ {
+ attr->exists = 1;
+ attr = attr->next;
+ continue;
+ }
+ }
+ if (is_gml && strcmp (attr->attr_name, "id") == 0)
+ {
+ if (strcmp (name, "gml_id") == 0)
+ {
+ attr->exists = 1;
+ attr = attr->next;
+ continue;
+ }
+ }
+ }
+ if (strcmp (attr->attr_name, name) == 0)
+ attr->exists = 1;
+ attr = attr->next;
+ }
+ }
+ }
+ sqlite3_free_table (results);
+
+ attr = tbl->tag->first_attr;
+ while (attr != NULL)
+ {
+ if (attr->exists != 1)
+ {
+ /* attempting to add an attribute column */
+ sql =
+ sqlite3_mprintf
+ ("ALTER TABLE \"%s\" ADD COLUMN \"%s\" TEXT",
+ tbl->table_name, attr->attr_name);
+ ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "ALTER TABLE error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+ }
+ attr = attr->next;
+ }
+ return 1;
+}
+
+static int
+prepare_sql_statements (sqlite3 * db_handle, struct sql_table *tbl,
+ int xlink_href)
+{
+/* preparing the INSERT and UPDATE SQL statements */
+ struct xml_attr *attr;
+ char *sql;
+ char *sql1;
+ int ret;
+ sqlite3_stmt *stmt;
+
+/* preparing the INSERT statement */
+ if (tbl->parent_table == NULL)
+ sql =
+ sqlite3_mprintf ("INSERT INTO \"%s\" (node_id, mtdapp_filename",
+ tbl->table_name);
+ else
+ sql =
+ sqlite3_mprintf ("INSERT INTO \"%s\" (node_id, parent_id",
+ tbl->table_name);
+ attr = tbl->tag->first_attr;
+ while (attr != NULL)
+ {
+ if (xlink_href)
+ {
+ /* special cases: xlink_href and gml_id */
+ int is_xlink = 0;
+ int is_gml = 0;
+ if (attr->attr_ns != NULL)
+ {
+ if (strcmp (attr->attr_ns, "xlink") == 0)
+ is_xlink = 1;
+ if (strcmp (attr->attr_ns, "gml") == 0)
+ is_gml = 1;
+ }
+ if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+ {
+ sql1 = sqlite3_mprintf ("%s, xlink_href", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ continue;
+ }
+ if (is_gml && strcmp (attr->attr_name, "id") == 0)
+ {
+ sql1 = sqlite3_mprintf ("%s, gml_id", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ continue;
+ }
+ }
+ sql1 = sqlite3_mprintf ("%s, \"%s\"", sql, attr->attr_name);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ }
+ sql1 = sqlite3_mprintf ("%s) VALUES (NULL, ?", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = tbl->tag->first_attr;
+ while (attr != NULL)
+ {
+ sql1 = sqlite3_mprintf ("%s, ?", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ attr = attr->next;
+ }
+ sql1 = sqlite3_mprintf ("%s)", sql);
+ sqlite3_free (sql);
+ sql = sql1;
+ ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "INSERT INTO error: %s\n",
+ sqlite3_errmsg (db_handle));
+ return 0;
+ }
+ tbl->ins_stmt = stmt;
+
+/* preparing the UPDATE statement */
+ if (tbl->tag->has_geometry)
+ sql = sqlite3_mprintf ("UPDATE \"%s\" SET node_value = ?, "
+ "from_gml_geometry = ? WHERE node_id = ?",
+ tbl->table_name);
+ else
+ sql =
+ sqlite3_mprintf
+ ("UPDATE \"%s\" SET node_value = ? WHERE node_id = ?",
+ tbl->table_name);
+ ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "UPDATE error: %s\n", sqlite3_errmsg (db_handle));
+ return 0;
+ }
+ tbl->upd_stmt = stmt;
+ return 1;
+}
+
+static int
+prepare_sql_tables (struct xml_params *ptr)
+{
+/* creating/updating the SQL tables */
+ int ret;
+ int error = 0;
+ const char *sql;
+ char *err_msg;
+ sqlite3_stmt *stmt;
+ struct sql_table *tbl = ptr->first_table;
+ while (tbl != NULL)
+ {
+ ret = create_sql_table (ptr->db_handle, tbl, ptr->xlink_href);
+ if (!ret)
+ return 0;
+ ret = check_baseline_table (ptr->db_handle, tbl);
+ if (!ret)
+ return 0;
+ ret = upgrade_sql_table (ptr->db_handle, tbl, ptr->xlink_href);
+ if (!ret)
+ return 0;
+ ret = prepare_sql_statements (ptr->db_handle, tbl, ptr->xlink_href);
+ if (!ret)
+ return 0;
+ tbl = tbl->next;
+ }
+
+/* creating the "xml_metacatalog_tables" table */
+ sql = "CREATE TABLE IF NOT EXISTS xml_metacatalog_tables (\n"
+ "table_name TEXT NOT NULL PRIMARY KEY,\n"
+ "tree_level INTEGER NOT NULL,\n"
+ "xml_tag_namespace TEXT,\n"
+ "xml_tag_name TEXT NOT NULL,\n"
+ "parent_table_name TEXT,\n"
+ "gml_geometry_column TEXT,\n"
+ "status TEXT NOT NULL,\n"
+ "CONSTRAINT fk_xml_meta_tables FOREIGN KEY (parent_table_name) "
+ "REFERENCES xml_metacatalog_tables (table_name))";
+ ret = sqlite3_exec (ptr->db_handle, sql, NULL, NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CREATE TABLE xml_meta_catalog_tables error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+
+/* prepared statement for INSERT INTO xml_metacatalog_tables */
+ sql =
+ "INSERT OR IGNORE INTO xml_metacatalog_tables (table_name, tree_level, "
+ "xml_tag_namespace, xml_tag_name, parent_table_name, "
+ "gml_geometry_column, status) VALUES (?, ?, ?, ?, ?, ?, ?)";
+ ret = sqlite3_prepare_v2 (ptr->db_handle, sql, strlen (sql), &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "INSERT INTO xml_metacatalog_tables error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ return 0;
+ }
+
+/* updating "xml_metacatalog_tables" */
+ tbl = ptr->first_table;
+ while (tbl != NULL)
+ {
+ const char *str;
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name, strlen (tbl->table_name),
+ SQLITE_STATIC);
+ sqlite3_bind_int (stmt, 2, tbl->tag->tree_level);
+ if (tbl->tag->tag_ns == NULL)
+ sqlite3_bind_null (stmt, 3);
+ else
+ sqlite3_bind_text (stmt, 3, tbl->tag->tag_ns,
+ strlen (tbl->tag->tag_ns), SQLITE_STATIC);
+ sqlite3_bind_text (stmt, 4, tbl->tag->tag_name,
+ strlen (tbl->tag->tag_name), SQLITE_STATIC);
+ if (tbl->parent_table == NULL)
+ sqlite3_bind_null (stmt, 5);
+ else
+ sqlite3_bind_text (stmt, 5, tbl->parent_table,
+ strlen (tbl->parent_table), SQLITE_STATIC);
+ if (tbl->tag->has_geometry)
+ {
+ str = "from_gml_geometry";
+ sqlite3_bind_text (stmt, 6, str, strlen (str), SQLITE_STATIC);
+ }
+ else
+ sqlite3_bind_null (stmt, 6);
+ str = "raw (not post-processed)";
+ sqlite3_bind_text (stmt, 7, str, strlen (str), SQLITE_STATIC);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "INSERT xml_metacatalog_tables error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop;
+ }
+ tbl = tbl->next;
+ }
+ stop:
+ sqlite3_finalize (stmt);
+
+/* creating the "xml_metacatalog_columns" table */
+ sql = "CREATE TABLE IF NOT EXISTS xml_metacatalog_columns (\n"
+ "table_name TEXT NOT NULL,\n"
+ "column_name TEXT NOT NULL,\n"
+ "origin TEXT NOT NULL,\n"
+ "destination TEXT,\n"
+ "xml_reference TEXT NOT NULL,\n"
+ "CONSTRAINT pk_xml_meta_columns PRIMARY KEY (table_name, column_name),\n"
+ "CONSTRAINT fk_xml_meta_columns FOREIGN KEY (table_name) "
+ "REFERENCES xml_metacatalog_tables (table_name))";
+ ret = sqlite3_exec (ptr->db_handle, sql, NULL, NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "CREATE TABLE xml_meta_catalog_columns error: %s\n",
+ err_msg);
+ sqlite3_free (err_msg);
+ return 0;
+ }
+
+/* prepared statement for INSERT INTO xml_metacatalog_columns */
+ sql =
+ "INSERT OR IGNORE INTO xml_metacatalog_columns (table_name, column_name, "
+ "origin, destination, xml_reference) VALUES (?, ?, ?, NULL, ?)";
+ ret = sqlite3_prepare_v2 (ptr->db_handle, sql, strlen (sql), &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "INSERT INTO xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ return 0;
+ }
+
+/* updating "xml_metacatalog_columns" */
+ tbl = ptr->first_table;
+ while (tbl != NULL)
+ {
+ char *xml;
+ const char *str;
+ struct xml_attr *attr;
+ /* node_id column */
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name, strlen (tbl->table_name),
+ SQLITE_STATIC);
+ str = "node_id";
+ sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+ str = "DBMS internal identifier - Primary Key";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ str = "n.a.";
+ sqlite3_bind_text (stmt, 4, str, strlen (str), SQLITE_STATIC);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ if (tbl->parent_table != NULL)
+ {
+ /* parent_id column */
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name,
+ strlen (tbl->table_name), SQLITE_STATIC);
+ str = "parent_id";
+ sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+ str = "DBMS internal identifier - Foreign Key";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ str = "n.a.";
+ sqlite3_bind_text (stmt, 4, str, strlen (str), SQLITE_STATIC);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr,
+ "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ }
+ /* node_value column */
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name, strlen (tbl->table_name),
+ SQLITE_STATIC);
+ str = "node_value";
+ sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+ str = "imported from XML Node value";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ if (tbl->tag->tag_ns == NULL)
+ xml =
+ sqlite3_mprintf ("<%s>value</%s>",
+ tbl->tag->tag_name, tbl->tag->tag_name);
+ else
+ xml =
+ sqlite3_mprintf ("<%s:%s>value</%s:%s>",
+ tbl->tag->tag_ns,
+ tbl->tag->tag_name,
+ tbl->tag->tag_ns, tbl->tag->tag_name);
+ sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ if (tbl->tag->has_geometry == 0)
+ {
+ /* node_value_column */
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name,
+ strlen (tbl->table_name), SQLITE_STATIC);
+ str = "node_value";
+ sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+ str = "imported from XML node value";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ if (tbl->tag->tag_ns == NULL)
+ xml =
+ sqlite3_mprintf ("<%s>value</%s>", tbl->tag->tag_name,
+ tbl->tag->tag_name);
+ else
+ xml =
+ sqlite3_mprintf ("<%s:%s>value</%s:%s>",
+ tbl->tag->tag_ns, tbl->tag->tag_name,
+ tbl->tag->tag_ns, tbl->tag->tag_name);
+ sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr,
+ "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ }
+ else
+ {
+ /* collapsed GML Geometry */
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name,
+ strlen (tbl->table_name), SQLITE_STATIC);
+ str = "node_value";
+ sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+ str = "imported from collapsed GML Geometry tags";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ if (tbl->tag->tag_ns == NULL)
+ xml =
+ sqlite3_mprintf ("<%s>gml_expr</%s>",
+ tbl->tag->tag_name,
+ tbl->tag->tag_name);
+ else
+ xml =
+ sqlite3_mprintf ("<%s:%s>gml_expr</%s:%s>",
+ tbl->tag->tag_ns, tbl->tag->tag_name,
+ tbl->tag->tag_ns, tbl->tag->tag_name);
+ sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr,
+ "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name,
+ strlen (tbl->table_name), SQLITE_STATIC);
+ str = "from_gml_geometry";
+ sqlite3_bind_text (stmt, 2, str, strlen (str), SQLITE_STATIC);
+ str = "GeomFromGML(node_value)";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ if (tbl->tag->tag_ns == NULL)
+ xml =
+ sqlite3_mprintf ("<%s>gml_expr</%s>",
+ tbl->tag->tag_name,
+ tbl->tag->tag_name);
+ else
+ xml =
+ sqlite3_mprintf ("<%s:%s>gml_expr</%s:%s>",
+ tbl->tag->tag_ns, tbl->tag->tag_name,
+ tbl->tag->tag_ns, tbl->tag->tag_name);
+ sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr,
+ "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ }
+ attr = tbl->tag->first_attr;
+ while (attr != NULL)
+ {
+ /* XML attributes */
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, tbl->table_name,
+ strlen (tbl->table_name), SQLITE_STATIC);
+ if (ptr->xlink_href)
+ {
+ int is_xlink = 0;
+ int is_gml = 0;
+ if (attr->attr_ns != NULL)
+ {
+ if (strcmp (attr->attr_ns, "xlink") == 0)
+ is_xlink = 1;
+ if (strcmp (attr->attr_ns, "gml") == 0)
+ is_gml = 1;
+ }
+ if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+ {
+ const char *xlhr = "xlink_href";
+ sqlite3_bind_text (stmt, 2, xlhr, strlen (xlhr),
+ SQLITE_STATIC);
+ }
+ else if (is_gml && strcmp (attr->attr_name, "id") == 0)
+ {
+ const char *gmid = "gml_id";
+ sqlite3_bind_text (stmt, 2, gmid, strlen (gmid),
+ SQLITE_STATIC);
+ }
+ else
+ sqlite3_bind_text (stmt, 2, attr->attr_name,
+ strlen (attr->attr_name),
+ SQLITE_STATIC);
+ }
+ else
+ sqlite3_bind_text (stmt, 2, attr->attr_name,
+ strlen (attr->attr_name), SQLITE_STATIC);
+ str = "imported from XML attribute";
+ sqlite3_bind_text (stmt, 3, str, strlen (str), SQLITE_STATIC);
+ if (tbl->tag->tag_ns == NULL)
+ {
+ if (attr->attr_ns == NULL)
+ xml =
+ sqlite3_mprintf ("<%s %s=\"value\" />",
+ tbl->tag->tag_name,
+ attr->attr_name);
+ else
+ xml =
+ sqlite3_mprintf ("<%s %s:%s=\"value\" />",
+ tbl->tag->tag_name,
+ attr->attr_ns, attr->attr_name);
+ }
+ else
+ {
+ if (attr->attr_ns == NULL)
+ xml =
+ sqlite3_mprintf ("<%s:%s %s=\"value\" />",
+ tbl->tag->tag_ns,
+ tbl->tag->tag_name,
+ attr->attr_name);
+ else
+ xml =
+ sqlite3_mprintf ("<%s:%s %s:%s=\"value\" />",
+ tbl->tag->tag_ns,
+ tbl->tag->tag_name,
+ attr->attr_ns, attr->attr_name);
+ }
+ sqlite3_bind_text (stmt, 4, xml, strlen (xml), sqlite3_free);
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr,
+ "INSERT xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (ptr->db_handle));
+ error = 1;
+ goto stop2;
+ }
+ attr = attr->next;
+ }
+ tbl = tbl->next;
+ }
+ stop2:
+ sqlite3_finalize (stmt);
+
+ if (error)
+ return 0;
+ return 1;
+}
+
+static int
+do_insert (sqlite3 * db_handle, struct xml_tag *tag, const char *filename,
+ int xlink_href)
+{
+/* attempting to INSERT an XML Node into the appropriate table */
+ struct xml_attr *attr;
+ int ret;
+ int pos = 1;
+ sqlite3_stmt *stmt = tag->table->ins_stmt;
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ if (tag->table->parent_table != NULL)
+ {
+ /* retrieving the Foreign Key value */
+ sqlite3_int64 fk_value = tag->parent->table->current;
+ sqlite3_bind_int64 (stmt, pos, fk_value);
+ pos++;
+ }
+ else
+ {
+ /* setting the "mtdapp_filename" value */
+ sqlite3_bind_text (stmt, pos, filename, strlen (filename),
+ SQLITE_STATIC);
+ pos++;
+ }
+ attr = tag->first_attr;
+ while (attr != NULL)
+ {
+ if (xlink_href && attr->attr_value != NULL)
+ {
+ /* special case: xlink_href */
+ int is_xlink = 0;
+ if (attr->attr_ns != NULL)
+ {
+ if (strcmp (attr->attr_ns, "xlink") == 0)
+ is_xlink = 1;
+ }
+ if (is_xlink && strcmp (attr->attr_name, "href") == 0)
+ {
+ if (*(attr->attr_value) == '#')
+ {
+ /* skipping the initial # "anchor" marker */
+ sqlite3_bind_text (stmt, pos, attr->attr_value + 1,
+ strlen (attr->attr_value) - 1,
+ SQLITE_STATIC);
+ pos++;
+ attr = attr->next;
+ }
+ continue;
+ }
+ }
+ if (attr->attr_value == NULL)
+ sqlite3_bind_null (stmt, pos);
+ else
+ sqlite3_bind_text (stmt, pos, attr->attr_value,
+ strlen (attr->attr_value), SQLITE_STATIC);
+ pos++;
+ attr = attr->next;
+ }
+/* INSERTing */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ tag->table->current = sqlite3_last_insert_rowid (db_handle);
+ else
+ {
+ fprintf (stderr, "INSERT error: %s\n", sqlite3_errmsg (db_handle));
+ return 0;
+ }
+ return 1;
+}
+
+static int
+do_update (sqlite3 * db_handle, struct xml_tag *tag, const char *value, int len)
+{
+/* attempting to UPDATE an XML Node by setting the node's value */
+ int ret;
+ sqlite3_stmt *stmt = tag->table->upd_stmt;
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, value, len, SQLITE_STATIC);
+ sqlite3_bind_int64 (stmt, 2, tag->table->current);
+/* UPDATing */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "UPDATE error: %s\n", sqlite3_errmsg (db_handle));
+ return 0;
+ }
+ return 1;
+}
+
+static int
+do_update_with_geom (sqlite3 * db_handle, struct xml_tag *tag,
+ const char *value, int len)
+{
+/* attempting to UPDATE an XML Node by setting the node's value */
+ int ret;
+ gaiaGeomCollPtr geo;
+ unsigned char *gml_expr;
+ sqlite3_stmt *stmt = tag->table->upd_stmt;
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_text (stmt, 1, value, len, SQLITE_STATIC);
+ gml_expr = malloc (len + 1);
+ memcpy (gml_expr, value, len);
+ *(gml_expr + len) = '\0';
+ geo = gaiaParseGml (gml_expr, db_handle);
+ free (gml_expr);
+ if (geo == NULL)
+ sqlite3_bind_null (stmt, 2);
+ else
+ {
+ int blob_len;
+ unsigned char *blob;
+ gaiaToSpatiaLiteBlobWkb (geo, &blob, &blob_len);
+ gaiaFreeGeomColl (geo);
+ sqlite3_bind_blob (stmt, 2, blob, blob_len, free);
+ }
+ sqlite3_bind_int64 (stmt, 3, tag->table->current);
+/* UPDATing */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE || ret == SQLITE_ROW)
+ ;
+ else
+ {
+ fprintf (stderr, "UPDATE error: %s\n", sqlite3_errmsg (db_handle));
+ return 0;
+ }
+ return 1;
+}
+
+static void
+start_tag_2 (void *data, const char *el, const char **attr)
+{
+/* XML element starting - Pass II */
+ const char **attrib = attr;
+ int count = 0;
+ const char *k;
+ const char *v;
+ char *ns = NULL;
+ char *name = NULL;
+ char *full_name = NULL;
+ struct xml_params *params = (struct xml_params *) data;
+ struct xml_tag *tag;
+ if (params->CollapsingGML)
+ {
+ /* collapsing GML Geometries */
+ gmlDynBufferAppend (params->CollapsedGML, "<", 1);
+ gmlDynBufferAppend (params->CollapsedGML, el, strlen (el));
+ while (*attrib != NULL)
+ {
+ if ((count % 2) == 0)
+ k = *attrib;
+ else
+ {
+ v = *attrib;
+ gmlDynBufferAppend (params->CollapsedGML, " ", 1);
+ gmlDynBufferAppend (params->CollapsedGML, k, strlen (k));
+ gmlDynBufferAppend (params->CollapsedGML, "=\"", 2);
+ gmlDynBufferAppend (params->CollapsedGML, v, strlen (v));
+ gmlDynBufferAppend (params->CollapsedGML, "\"", 1);
+ }
+ attrib++;
+ count++;
+ }
+ gmlDynBufferAppend (params->CollapsedGML, ">", 1);
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ return;
+ }
+ split_namespace (el, &ns, &name);
+ if (params->collapsed_gml)
+ {
+ /* attempting to collapse GML Geometries */
+ if (is_gml_geometry (ns, name))
+ {
+ if (ns != NULL)
+ free (ns);
+ if (name != NULL)
+ free (name);
+ if (params->CollapsedGML != NULL)
+ gmlDynBufferDestroy (params->CollapsedGML);
+ params->CollapsedGML = gmlDynBufferAlloc ();
+ gmlDynBufferAppend (params->CollapsedGML, "<", 1);
+ gmlDynBufferAppend (params->CollapsedGML, el, strlen (el));
+ while (*attrib != NULL)
+ {
+ if ((count % 2) == 0)
+ k = *attrib;
+ else
+ {
+ v = *attrib;
+ gmlDynBufferAppend (params->CollapsedGML, " ", 1);
+ gmlDynBufferAppend (params->CollapsedGML, k,
+ strlen (k));
+ gmlDynBufferAppend (params->CollapsedGML, "=\"", 2);
+ gmlDynBufferAppend (params->CollapsedGML, v,
+ strlen (v));
+ gmlDynBufferAppend (params->CollapsedGML, "\"", 1);
+ }
+ attrib++;
+ count++;
+ }
+ gmlDynBufferAppend (params->CollapsedGML, ">", 1);
+ params->CollapsingGML = 1;
+ if (params->CollapsedGMLMarker != NULL)
+ sqlite3_free (params->CollapsedGMLMarker);
+ params->CollapsedGMLMarker = sqlite3_mprintf ("%s", el);
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ return;
+ }
+ }
+ full_name = build_full_name (params->stack, name);
+ tag = find_tag (params, ns, name, full_name);
+ sqlite3_free (full_name);
+ reset_tag_attributes (tag);
+ push_stack (params, ns, name);
+ while (*attrib != NULL)
+ {
+ if ((count % 2) == 0)
+ k = *attrib;
+ else
+ {
+ v = *attrib;
+ split_namespace (k, &ns, &name);
+ set_attribute_value (tag, ns, name, v);
+ if (ns != NULL)
+ free (ns);
+ if (name != NULL)
+ free (name);
+ }
+ attrib++;
+ count++;
+ }
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ if (!do_insert
+ (params->db_handle, tag, params->filename, params->xlink_href))
+ params->db_error = 1;
+}
+
+static void
+end_tag_2 (void *data, const char *el)
+{
+/* XML element ending - Pass II */
+ struct xml_params *params = (struct xml_params *) data;
+ if (params->CollapsingGML)
+ {
+ /* collapsing GML Geometries */
+ if (valid_char_data (params))
+ gmlDynBufferAppend (params->CollapsedGML, params->CharData,
+ params->CharDataLen);
+ gmlDynBufferAppend (params->CollapsedGML, "</", 2);
+ gmlDynBufferAppend (params->CollapsedGML, el, strlen (el));
+ gmlDynBufferAppend (params->CollapsedGML, ">", 1);
+ if (strcmp (params->CollapsedGMLMarker, el) == 0)
+ {
+ sqlite3_free (params->CollapsedGMLMarker);
+ params->CollapsedGMLMarker = NULL;
+ params->CollapsingGML = 0;
+ }
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ return;
+ }
+ if (params->CollapsedGML != NULL)
+ {
+ /* updating the Node value - collapsed GML */
+ char *full_name =
+ build_full_name (params->stack->prev, params->stack->tag_name);
+ struct xml_tag *tag =
+ find_tag (params, params->stack->tag_ns, params->stack->tag_name,
+ full_name);
+ sqlite3_free (full_name);
+ if (!do_update_with_geom
+ (params->db_handle, tag, params->CollapsedGML->Buffer,
+ params->CollapsedGML->WriteOffset))
+ params->db_error = 1;
+ gmlDynBufferDestroy (params->CollapsedGML);
+ params->CollapsedGML = NULL;
+ goto done;
+ }
+ if (valid_char_data (params))
+ {
+ /* updating the Node value */
+ char *full_name =
+ build_full_name (params->stack->prev, params->stack->tag_name);
+ struct xml_tag *tag =
+ find_tag (params, params->stack->tag_ns, params->stack->tag_name,
+ full_name);
+ sqlite3_free (full_name);
+ if (!do_update
+ (params->db_handle, tag, params->CharData, params->CharDataLen))
+ params->db_error = 1;
+ }
+ done:
+ *(params->CharData) = '\0';
+ params->CharDataLen = 0;
+ pop_stack (params);
+}
+
+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 void
+open_db (const char *path, sqlite3 ** handle, int cache_size, void *cache)
+{
+/* opening the DB */
+ sqlite3 *db_handle;
+ int ret;
+ char sql[1024];
+
+ *handle = NULL;
+ printf ("SQLite version: %s\n", sqlite3_libversion ());
+ printf ("SpatiaLite version: %s\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);
+ db_handle = NULL;
+ 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);
+ }
+
+/* enabling PK/FK constraints */
+ sqlite3_exec (db_handle, "PRAGMA foreign_keys = 1", NULL, NULL, NULL);
+ *handle = db_handle;
+ return;
+}
+
+#ifndef timersub
+/* This is a copy from GNU C Library (GNU LGPL 2.1), sys/time.h. */
+#define timersub(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((result)->tv_usec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
+static void
+format_elapsed_time (struct timeval *start, struct timeval *stop, char *elapsed)
+{
+/* well formatting elapsed time */
+ struct timeval diff;
+ int x;
+ int millis;
+ int secs;
+ int mins;
+ int hh;
+
+ timersub (stop, start, &diff);
+ millis = diff.tv_usec / 1000;
+ secs = diff.tv_sec % 60;
+ x = diff.tv_sec / 60;
+ mins = x % 60;
+ x /= 60;
+ hh = x;
+ sprintf (elapsed, "%d:%02d:%02d.%03d", hh, mins, secs, millis);
+}
+
+static void
+do_update_progress (int phase, sqlite3_int64 totlen, sqlite3_int64 donelen)
+{
+/* updating the "running wheel" */
+ char progress[64];
+ strcpy (progress, "........................................");
+ if (donelen)
+ {
+ double percent = (double) donelen / (double) totlen;
+ int tics = 40.0 * percent;
+ int i;
+ for (i = 0; i < tics; i++)
+ progress[i] = 'X';
+ }
+ switch (phase % 8)
+ {
+ case 0:
+ printf ("| %s\r", progress);
+ break;
+ case 1:
+ printf ("/ %s\r", progress);
+ break;
+ case 2:
+ printf ("- %s\r", progress);
+ break;
+ case 3:
+ printf ("\\ %s\r", progress);
+ break;
+ case 4:
+ printf ("| %s\r", progress);
+ break;
+ case 5:
+ printf ("/ %s\r", progress);
+ break;
+ case 6:
+ printf ("- %s\r", progress);
+ break;
+ case 7:
+ printf ("\\ %s\r", progress);
+ break;
+ };
+ fflush (stdout);
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+ fprintf (stderr, "\n\nusage: spatialite_xml_load ARGLIST\n");
+ fprintf (stderr,
+ "==============================================================\n");
+ fprintf (stderr,
+ "-h or --help print this help message\n");
+ fprintf (stderr, "-x or --xml-path pathname the XML file path\n");
+ fprintf (stderr,
+ "-d or --db-path pathname the SpatiaLite DB path\n\n");
+ fprintf (stderr, "you can specify the following options as well\n");
+ fprintf (stderr,
+ "-cg or --collapsed-gml collapsed GML Geometries\n");
+ fprintf (stderr,
+ "-xl or --xlink-href special GML xlink:href handling\n");
+ fprintf (stderr,
+ "-nl or --nl-level num tree-level for table-names (dft: 0)\n");
+ fprintf (stderr,
+ "-pl or --parent-levels num how many ancestors for table-names (dft: -1)\n");
+ fprintf (stderr,
+ "-jo or --journal-off unsafe [but faster] mode\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");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+ sqlite3 *handle;
+ char *err_msg = NULL;
+ int ret;
+ int i;
+ int next_arg = ARG_NONE;
+ const char *xml_path = NULL;
+ const char *db_path = NULL;
+ int name_level = 0;
+ int parent_levels = -1;
+ int in_memory = 0;
+ int cache_size = 0;
+ int journal_off = 0;
+ int collapsed_gml = 0;
+ int xlink_href = 0;
+ int error = 0;
+ char Buff[BUFFSIZE];
+ int done = 0;
+ int len;
+ XML_Parser parser = NULL;
+ FILE *xml_file;
+ struct xml_params params;
+ void *cache;
+ struct timeval start;
+ struct timeval stop;
+ char elapsed[64];
+ int phase = 0;
+ int blklen = 0;
+ sqlite3_int64 totlen = 0;
+ sqlite3_int64 donelen = 0;
+
+ gettimeofday (&start, NULL);
+
+ params.filename = NULL;
+ params.db_handle = NULL;
+ params.journal_off = 0;
+ params.collapsed_gml = 0;
+ params.xlink_href = 0;
+ params.CharDataStep = 65536;
+ params.CharDataMax = params.CharDataStep;
+ params.CharData = malloc (params.CharDataStep);
+ params.CharDataLen = 0;
+ params.parse_error = 0;
+ params.db_error = 0;
+ params.first_tag = NULL;
+ params.last_tag = NULL;
+ params.sort_array = NULL;
+ params.count_array = 0;
+ params.first_table = NULL;
+ params.last_table = NULL;
+ params.stack = NULL;
+ params.CollapsingGML = 0;
+ params.CollapsedGML = NULL;
+ params.CollapsedGMLMarker = NULL;
+ params.treeLevel = -1;
+
+ for (i = 1; i < argc; i++)
+ {
+ /* parsing the invocation arguments */
+ if (next_arg != ARG_NONE)
+ {
+ switch (next_arg)
+ {
+ case ARG_XML_PATH:
+ xml_path = argv[i];
+ break;
+ case ARG_DB_PATH:
+ db_path = argv[i];
+ break;
+ case ARG_CACHE_SIZE:
+ cache_size = atoi (argv[i]);
+ break;
+ case ARG_NAME_LEVEL:
+ name_level = atoi (argv[i]);
+ break;
+ case ARG_PARENT_LEVELS:
+ parent_levels = atoi (argv[i]);
+ 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], "-x") == 0)
+ {
+ next_arg = ARG_XML_PATH;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--xml-path") == 0)
+ {
+ next_arg = ARG_XML_PATH;
+ continue;
+ }
+ 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], "--cache-size") == 0
+ || strcmp (argv[i], "-cs") == 0)
+ {
+ next_arg = ARG_CACHE_SIZE;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--name-level") == 0
+ || strcmp (argv[i], "-nl") == 0)
+ {
+ next_arg = ARG_NAME_LEVEL;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--parent-levels") == 0
+ || strcmp (argv[i], "-pl") == 0)
+ {
+ next_arg = ARG_PARENT_LEVELS;
+ 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;
+ }
+ if (strcasecmp (argv[i], "-cg") == 0)
+ {
+ collapsed_gml = 1;
+ next_arg = ARG_NONE;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--collapsed-gml") == 0)
+ {
+ collapsed_gml = 1;
+ next_arg = ARG_NONE;
+ continue;
+ }
+ if (strcasecmp (argv[i], "-xl") == 0)
+ {
+ xlink_href = 1;
+ next_arg = ARG_NONE;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--xlink-href") == 0)
+ {
+ xlink_href = 1;
+ next_arg = ARG_NONE;
+ 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;
+ }
+ fprintf (stderr, "unknown argument: %s\n", argv[i]);
+ error = 1;
+ }
+ if (error)
+ {
+ do_help ();
+ return -1;
+ }
+
+/* checking the arguments */
+ if (!xml_path)
+ {
+ fprintf (stderr,
+ "did you forget setting the --xml-path argument ?\n");
+ error = 1;
+ }
+ if (!db_path)
+ {
+ fprintf (stderr, "did you forget setting the --db-path argument ?\n");
+ error = 1;
+ }
+ if (error)
+ {
+ do_help ();
+ return -1;
+ }
+
+/* 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;
+
+ printf ("Target DB: %s\n", db_path);
+
+ 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.journal_off = journal_off;
+ params.collapsed_gml = collapsed_gml;
+ params.xlink_href = xlink_href;
+ set_xml_filename (¶ms, xml_path);
+
+/* XML parsing - pass I */
+ xml_file = fopen (xml_path, "rb");
+ if (!xml_file)
+ {
+ fprintf (stderr, "cannot open %s\n", xml_path);
+ sqlite3_close (handle);
+ return -1;
+ }
+ parser = XML_ParserCreate (NULL);
+ if (!parser)
+ {
+ fprintf (stderr, "Couldn't allocate memory for parser\n");
+ sqlite3_close (handle);
+ return -1;
+ }
+
+ printf ("Input XML: %s\n", xml_path);
+
+ XML_SetUserData (parser, ¶ms);
+/* XML parsing - pass I */
+ XML_SetElementHandler (parser, start_tag_1, end_tag_1);
+ XML_SetCharacterDataHandler (parser, xmlCharData);
+ blklen = 0;
+ while (!done)
+ {
+ if (params.parse_error || params.db_error)
+ goto parser_error1;
+ len = fread (Buff, 1, BUFFSIZE, xml_file);
+ totlen += len;
+ blklen += len;
+ if (blklen > BUFFSIZE * 100)
+ {
+ do_update_progress (phase++, totlen, donelen);
+ blklen -= BUFFSIZE * 100;
+ }
+ if (ferror (xml_file))
+ {
+ fprintf (stderr, "XML Read error\n");
+ goto parser_error1;
+ }
+ done = feof (xml_file);
+ if (!XML_Parse (parser, Buff, len, done))
+ {
+ fprintf (stderr, "Parse error at line %d:\n%s\n",
+ (int) XML_GetCurrentLineNumber (parser),
+ XML_ErrorString (XML_GetErrorCode (parser)));
+ goto parser_error1;
+ }
+ }
+ parser_error1:
+ XML_ParserFree (parser);
+ fclose (xml_file);
+
+/* assigning the SQL table names for each XML Node class */
+ set_unique_names (¶ms, name_level, parent_levels);
+ set_table_names (¶ms);
+
+ if (params.journal_off)
+ {
+ /* disabling the Journal File */
+ ret =
+ sqlite3_exec (params.db_handle, "PRAGMA journal_mode=OFF", NULL,
+ NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "JOURNAL MODE=OFF error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto abort;
+ }
+ ret =
+ sqlite3_exec (params.db_handle, "PRAGMA synchronous=OFF", NULL,
+ NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SYNCHRONOUS=OFF error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto abort;
+ }
+ }
+
+/* starting a transaction */
+ ret = sqlite3_exec (params.db_handle, "BEGIN", NULL, NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "BEGIN error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ goto abort;
+ }
+
+/* creating/updating the SQL tables */
+ if (!prepare_sql_tables (¶ms))
+ goto abort;
+
+/* XML parsing - pass II */
+ done = 0;
+ if (params.CollapsedGMLMarker != NULL)
+ {
+ sqlite3_free (params.CollapsedGMLMarker);
+ params.CollapsedGMLMarker = NULL;
+ }
+ if (params.CollapsedGML != NULL)
+ {
+ gmlDynBufferDestroy (params.CollapsedGML);
+ params.CollapsedGML = NULL;
+ }
+ params.CollapsingGML = 0;
+
+ xml_file = fopen (xml_path, "rb");
+ if (!xml_file)
+ {
+ fprintf (stderr, "cannot open %s\n", xml_path);
+ sqlite3_close (handle);
+ return -1;
+ }
+ parser = XML_ParserCreate (NULL);
+ if (!parser)
+ {
+ fprintf (stderr, "Couldn't allocate memory for parser\n");
+ sqlite3_close (handle);
+ return -1;
+ }
+
+ XML_SetUserData (parser, ¶ms);
+/* XML parsing - pass II */
+ XML_SetElementHandler (parser, start_tag_2, end_tag_2);
+ XML_SetCharacterDataHandler (parser, xmlCharData);
+ blklen = 0;
+ while (!done)
+ {
+ if (params.parse_error || params.db_error)
+ goto parser_error2;
+ len = fread (Buff, 1, BUFFSIZE, xml_file);
+ donelen += len;
+ blklen += len;
+ if (blklen > BUFFSIZE * 10)
+ {
+ do_update_progress (phase++, totlen, donelen);
+ blklen -= BUFFSIZE * 10;
+ }
+ if (ferror (xml_file))
+ {
+ fprintf (stderr, "XML Read error\n");
+ goto parser_error2;
+ }
+ done = feof (xml_file);
+ if (!XML_Parse (parser, Buff, len, done))
+ {
+ fprintf (stderr, "Parse error at line %d:\n%s\n",
+ (int) XML_GetCurrentLineNumber (parser),
+ XML_ErrorString (XML_GetErrorCode (parser)));
+ goto parser_error2;
+ }
+ }
+ parser_error2:
+ XML_ParserFree (parser);
+ fclose (xml_file);
+
+/* committing the transaction */
+ ret = sqlite3_exec (params.db_handle, "COMMIT", NULL, NULL, &err_msg);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "COMMIT error: %s\n", err_msg);
+ sqlite3_free (err_msg);
+ }
+
+ gettimeofday (&stop, NULL);
+ format_elapsed_time (&start, &stop, elapsed);
+ printf ("Done - inserted/updated rows: %d [%s]\n\n",
+ sqlite3_total_changes (params.db_handle), elapsed);
+
+ abort:
+ params_cleanup (¶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");
+ }
+
+ sqlite3_close (handle);
+ spatialite_cleanup_ex (cache);
+ return 0;
+}
diff --git a/spatialite_xml_print.c b/spatialite_xml_print.c
new file mode 100644
index 0000000..8c155a0
--- /dev/null
+++ b/spatialite_xml_print.c
@@ -0,0 +1,1063 @@
+/*
+/ spatialite_xml_print
+/
+/ a tool printing an XML file from SQLite tables
+/
+/ version 1.0, 2014 July 1
+/
+/ 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 <sys/time.h>
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+/* MSVC strictly requires this include [off_t] */
+#include <sys/types.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+
+#ifdef SPATIALITE_AMALGAMATION
+#include <spatialite/sqlite3.h>
+#else
+#include <sqlite3.h>
+#endif
+#include <spatialite.h>
+#include <spatialite/gaiaaux.h>
+
+#define ARG_NONE 0
+#define ARG_XML_PATH 1
+#define ARG_DB_PATH 2
+#define ARG_CACHE_SIZE 3
+
+struct xml_attr
+{
+/* a struct wrapping an XML attribute */
+ char *attr_prefix;
+ char *attr_name;
+ struct xml_attr *next;
+};
+
+struct xml_node
+{
+/* a struct wrapping an XML node */
+ int level;
+ char *xml_prefix;
+ char *xml_tag;
+ char *table;
+ char *parent_table;
+ sqlite3_stmt *stmt;
+ struct xml_attr *first_attr;
+ struct xml_attr *last_attr;
+ struct xml_node *first;
+ struct xml_node *last;
+ struct xml_node *next;
+};
+
+static void
+do_destroy_node (struct xml_node *node)
+{
+/* memory cleanup - destroying an XML Node */
+ struct xml_attr *pa;
+ struct xml_attr *pan;
+ struct xml_node *pn;
+ struct xml_node *pnn;
+ if (node == NULL)
+ return;
+ if (node->xml_prefix != NULL)
+ free (node->xml_prefix);
+ if (node->xml_tag != NULL)
+ free (node->xml_tag);
+ if (node->table != NULL)
+ free (node->table);
+ if (node->parent_table != NULL)
+ free (node->parent_table);
+ if (node->stmt != NULL)
+ sqlite3_finalize (node->stmt);
+ pa = node->first_attr;
+ while (pa != NULL)
+ {
+ pan = pa->next;
+ if (pa->attr_prefix != NULL)
+ free (pa->attr_prefix);
+ if (pa->attr_name != NULL)
+ free (pa->attr_name);
+ free (pa);
+ pa = pan;
+ }
+ pn = node->first;
+ while (pn != NULL)
+ {
+ pnn = pn->next;
+ do_destroy_node (pn);
+ pn = pnn;
+ }
+ free (node);
+}
+
+static struct xml_node *
+alloc_xml_node (sqlite3 * sqlite, int level, const char *namespace,
+ const char *tag, const char *table, const char *parent)
+{
+/* creating an XML Node */
+ int len;
+ char *sql;
+ char *xtable;
+ int ret;
+ sqlite3_stmt *stmt;
+ struct xml_node *node = malloc (sizeof (struct xml_node));
+ node->level = level;
+ if (namespace == NULL)
+ node->xml_prefix = NULL;
+ else
+ {
+ len = strlen (namespace);
+ node->xml_prefix = malloc (len + 1);
+ strcpy (node->xml_prefix, namespace);
+ }
+ len = strlen (tag);
+ node->xml_tag = malloc (len + 1);
+ strcpy (node->xml_tag, tag);
+ len = strlen (table);
+ node->table = malloc (len + 1);
+ strcpy (node->table, table);
+ if (parent == NULL)
+ node->parent_table = NULL;
+ else
+ {
+ len = strlen (parent);
+ node->parent_table = malloc (len + 1);
+ strcpy (node->parent_table, parent);
+ }
+ xtable = gaiaDoubleQuotedSql (table);
+ if (parent == NULL)
+ sql = sqlite3_mprintf ("SELECT * FROM \"%s\"", xtable);
+ else
+ sql =
+ sqlite3_mprintf ("SELECT * FROM \"%s\" WHERE parent_id = ?",
+ xtable);
+ free (xtable);
+ node->stmt = NULL;
+ ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
+ sqlite3_free (sql);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM xml_node error: %s\n",
+ sqlite3_errmsg (sqlite));
+ return NULL;
+ }
+ node->stmt = stmt;
+ node->first = NULL;
+ node->last = NULL;
+ node->first_attr = NULL;
+ node->last_attr = NULL;
+ node->next = NULL;
+ return node;
+}
+
+static struct xml_node *
+find_node_by_table (struct xml_node *node, const char *table)
+{
+/* recursively searching the XML Tree */
+ struct xml_node *pn;
+ struct xml_node *res;
+ if (strcasecmp (node->table, table) == 0)
+ return node;
+ pn = node->first;
+ while (pn != NULL)
+ {
+ /* searching within children */
+ res = find_node_by_table (pn, table);
+ if (res != NULL)
+ return res;
+ pn = pn->next;
+ }
+ return NULL;
+}
+
+static int
+do_add_xml_node (sqlite3 * sqlite, struct xml_node *master, int level,
+ const char *namespace, const char *tag, const char *table,
+ const char *parent)
+{
+/* inserting a new node into the XML Tree */
+ struct xml_node *node;
+ struct xml_node *parent_node;
+ if (master == NULL)
+ return 0;
+ node = alloc_xml_node (sqlite, level, namespace, tag, table, parent);
+ parent_node = find_node_by_table (master, parent);
+ if (parent_node == NULL)
+ return 0;
+/* appending the child into the parent */
+ if (parent_node->first == NULL)
+ parent_node->first = node;
+ if (parent_node->last != NULL)
+ parent_node->last->next = node;
+ parent_node->last = node;
+ return 1;
+}
+
+static char *
+extract_attribute_prefix (struct xml_node *node, const char *reference)
+{
+ char *start;
+ int i;
+ if (node->xml_prefix == NULL)
+ start = sqlite3_mprintf ("<%s", node->xml_tag);
+ else
+ start = sqlite3_mprintf ("<%s:%s ", node->xml_prefix, node->xml_tag);
+
+ if (strncasecmp (start, reference, strlen (start)) == 0)
+ {
+ int a = strlen (start);
+ int b = -1;
+ for (i = a; i < (int) strlen (reference); i++)
+ {
+ if (*(reference + i) == ':')
+ {
+ b = i;
+ break;
+ }
+ }
+ sqlite3_free (start);
+ if (b > a)
+ {
+ int len = b - a;
+ char *prefix = malloc (len + 1);
+ memcpy (prefix, reference + a, len);
+ *(prefix + len) = '\0';
+ return prefix;
+ }
+ return NULL;
+ }
+ else
+ fprintf (stderr, "ERROR: invalid Attribute NameSpace\n");
+ sqlite3_free (start);
+ return NULL;
+}
+
+static void
+do_add_attribute (struct xml_node *node, char *prefix, const char *attribute)
+{
+/* creating and inserting a new XML attribute */
+ int len;
+ struct xml_attr *attr = malloc (sizeof (struct xml_attr));
+ attr->attr_prefix = prefix;
+ len = strlen (attribute);
+ attr->attr_name = malloc (len + 1);
+ strcpy (attr->attr_name, attribute);
+ attr->next = NULL;
+/* inserting into the XML Node */
+ if (node->first_attr == NULL)
+ node->first_attr = attr;
+ if (node->last_attr != NULL)
+ node->last_attr->next = attr;
+ node->last_attr = attr;
+}
+
+struct xml_node *
+do_build_master (sqlite3 * sqlite)
+{
+/* attempting to build the XML tree */
+ int ret;
+ const char *sql;
+ sqlite3_stmt *stmt = NULL;
+ struct xml_node *master = NULL;
+ struct xml_node *current = NULL;
+ int first = 1;
+
+/* extracting XML Nodes from MetaCatalog */
+ sql =
+ "SELECT tree_level, xml_tag_namespace, xml_tag_name, table_name, parent_table_name "
+ "FROM xml_metacatalog_tables " "ORDER BY tree_level, rowid";
+ ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM xml_metacatalog_tables error: %s\n",
+ sqlite3_errmsg (sqlite));
+ return NULL;
+ }
+ while (1)
+ {
+ /* fetching the result set rows */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ {
+ /* fetching a row */
+ const char *namespace = NULL;
+ const char *tag = NULL;
+ const char *table = NULL;
+ const char *parent = NULL;
+ int level = sqlite3_column_int (stmt, 0);
+ if (sqlite3_column_type (stmt, 1) == SQLITE_NULL)
+ ;
+ else
+ namespace = (const char *) sqlite3_column_text (stmt, 1);
+ if (sqlite3_column_type (stmt, 2) == SQLITE_NULL)
+ ;
+ else
+ tag = (const char *) sqlite3_column_text (stmt, 2);
+ if (sqlite3_column_type (stmt, 3) == SQLITE_NULL)
+ ;
+ else
+ table = (const char *) sqlite3_column_text (stmt, 3);
+ if (sqlite3_column_type (stmt, 4) == SQLITE_NULL)
+ ;
+ else
+ parent = (const char *) sqlite3_column_text (stmt, 4);
+ if (first)
+ {
+ /* this is the ROOT node */
+ if (parent == NULL)
+ master =
+ alloc_xml_node (sqlite, level, namespace, tag,
+ table, NULL);
+ first = 0;
+ if (master == NULL)
+ {
+ fprintf (stderr,
+ "ERROR: unable to build the XML Tree\n");
+ goto error;
+ }
+ }
+ else
+ {
+ if (!do_add_xml_node
+ (sqlite, master, level, namespace, tag, table,
+ parent))
+ {
+ fprintf (stderr,
+ "ERROR: unable to build the XML Tree\n");
+ goto error;
+ }
+ }
+ }
+ else
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ goto error;
+ }
+ }
+ sqlite3_finalize (stmt);
+
+/* extract XML Attributes from MetaCatalog */
+ sql = "SELECT table_name, column_name, xml_reference "
+ "FROM xml_metacatalog_columns "
+ "WHERE Upper(column_name) NOT IN (Upper('node_id'), Upper('parent_id'), "
+ "Upper('node_value'), Upper('from_gml_geometry')) "
+ "ORDER BY table_name, ROWID";
+ ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "SELECT FROM xml_metacatalog_columns error: %s\n",
+ sqlite3_errmsg (sqlite));
+ return NULL;
+ }
+ while (1)
+ {
+ /* fetching the result set rows */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ {
+ /* fetching a row */
+ const char *table =
+ (const char *) sqlite3_column_text (stmt, 0);
+ const char *attribute =
+ (const char *) sqlite3_column_text (stmt, 1);
+ const char *reference =
+ (const char *) sqlite3_column_text (stmt, 2);
+ char *prefix = NULL;
+ if (current == NULL)
+ current = find_node_by_table (master, table);
+ if (strcasecmp (current->table, table) != 0)
+ current = find_node_by_table (master, table);
+ if (current == NULL || strcasecmp (current->table, table) != 0)
+ {
+ fprintf (stderr, "ERROR: unable to build the XML Tree\n");
+ goto error;
+ }
+ prefix = extract_attribute_prefix (current, reference);
+ do_add_attribute (current, prefix, attribute);
+ }
+ else
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ goto error;
+ }
+ }
+ sqlite3_finalize (stmt);
+
+ return master;
+
+ error:
+ if (stmt != NULL)
+ sqlite3_finalize (stmt);
+ if (master != NULL)
+ do_destroy_node (master);
+ return NULL;
+}
+
+static char *
+clean_xml (const char *dirty)
+{
+/* well formatting an XML value */
+ char *clean;
+ char *out;
+ int i;
+ int extra = 0;
+ int len = strlen (dirty);
+ for (i = 0; i < len; i++)
+ {
+ /* computing the required extra-length */
+ switch (*(dirty + i))
+ {
+ case '&':
+ extra += 4;
+ break;
+ case '<':
+ extra += 3;
+ break;
+ case '>':
+ extra += 3;
+ break;
+ case '\'':
+ extra += 5;
+ break;
+ case '"':
+ extra += 5;
+ break;
+ };
+ }
+ clean = malloc (len + extra + 1);
+ out = clean;
+ for (i = 0; i < len; i++)
+ {
+ /* computing the required extra-length */
+ switch (*(dirty + i))
+ {
+ case '&':
+ *out++ = '&';
+ *out++ = 'a';
+ *out++ = 'm';
+ *out++ = 'p';
+ *out++ = ';';
+ break;
+ case '<':
+ *out++ = '&';
+ *out++ = 'l';
+ *out++ = 't';
+ *out++ = ';';
+ break;
+ case '>':
+ *out++ = '&';
+ *out++ = 'g';
+ *out++ = 't';
+ *out++ = ';';
+ break;
+ case '\'':
+ *out++ = '&';
+ *out++ = 'a';
+ *out++ = 'p';
+ *out++ = 'o';
+ *out++ = 's';
+ *out++ = ';';
+ break;
+ case '"':
+ *out++ = '&';
+ *out++ = 'q';
+ *out++ = 'u';
+ *out++ = 'o';
+ *out++ = 't';
+ *out++ = ';';
+ break;
+ default:
+ *out++ = *(dirty + i);
+ break;
+ };
+ }
+ *out = '\0';
+ return clean;
+}
+
+static void
+do_print_xml_child (FILE * out, struct xml_node *node, sqlite3_int64 parent_id,
+ sqlite3 * sqlite)
+{
+/* recursively printing the XML document - Child Node */
+ int ret;
+ char *indent;
+ int i;
+ sqlite3_stmt *stmt = node->stmt;
+ if (stmt == NULL)
+ return;
+
+ indent = malloc (node->level + 1);
+ for (i = 0; i < node->level; i++)
+ *(indent + i) = '\t';
+ *(indent + node->level) = '\0';
+
+ sqlite3_reset (stmt);
+ sqlite3_clear_bindings (stmt);
+ sqlite3_bind_int64 (stmt, 1, parent_id);
+ while (1)
+ {
+ /* fetching the result set rows */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ {
+ /* fetching a row */
+ struct xml_attr *attr;
+ struct xml_node *child;
+ char *xprefix;
+ char *xtag;
+ char *xvalue;
+ sqlite3_int64 node_id;
+ /* printing the XML Node start-tag */
+ if (node->xml_prefix == NULL)
+ {
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "%s<%s", indent, xtag);
+ free (xtag);
+ }
+ else
+ {
+ xprefix = clean_xml (node->xml_prefix);
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "%s<%s:%s", indent, xprefix, xtag);
+ free (xprefix);
+ free (xtag);
+ }
+ attr = node->first_attr;
+ while (attr != NULL)
+ {
+ /* printing all Node Attributes */
+ const char *value = NULL;
+ for (i = 0; i < sqlite3_column_count (stmt); i++)
+ {
+ const char *column = sqlite3_column_name (stmt, i);
+ if (strcasecmp (column, attr->attr_name) == 0)
+ {
+ if (sqlite3_column_type (stmt, i) ==
+ SQLITE_NULL)
+ ;
+ else
+ value =
+ (const char *)
+ sqlite3_column_text (stmt, i);
+ break;
+ }
+ }
+ if (value == NULL)
+ {
+ /* skipping NULL attributes */
+ attr = attr->next;
+ continue;
+ }
+ if (attr->attr_prefix == NULL)
+ {
+ xtag = clean_xml (attr->attr_name);
+ xvalue = clean_xml (value);
+ fprintf (out, " %s=\"%s\"", xtag, xvalue);
+ free (xtag);
+ free (xvalue);
+ }
+ else
+ {
+ xprefix = clean_xml (attr->attr_prefix);
+ xtag = clean_xml (attr->attr_name);
+ xvalue = clean_xml (value);
+ fprintf (out, " %s:%s=\"%s\"", xprefix, xtag,
+ xvalue);
+ free (xprefix);
+ free (xtag);
+ free (xvalue);
+ }
+ attr = attr->next;
+ }
+ if (node->first == NULL)
+ {
+ /* we have no Childern nodes for sure */
+ int from_gml_geometry = 0;
+ const char *value = NULL;
+ xvalue = NULL;
+ for (i = 0; i < sqlite3_column_count (stmt); i++)
+ {
+ const char *column = sqlite3_column_name (stmt, i);
+ if (strcasecmp (column, "from_gml_geometry") == 0)
+ from_gml_geometry = 1;
+ if (strcasecmp (column, "node_value") == 0)
+ {
+ if (sqlite3_column_type (stmt, i) !=
+ SQLITE_NULL)
+ value =
+ (const char *)
+ sqlite3_column_text (stmt, i);
+ }
+ }
+ if (value == NULL)
+ fprintf (out, " />\n");
+ else
+ {
+ if (!from_gml_geometry)
+ xvalue = clean_xml (value);
+ else
+ xvalue = (char *) value;
+ if (node->xml_prefix == NULL)
+ {
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, ">%s</%s>\n", xvalue, xtag);
+ free (xtag);
+ }
+ else
+ {
+ xprefix = clean_xml (node->xml_prefix);
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, ">%s</%s:%s>\n", xvalue,
+ xprefix, xtag);
+ free (xprefix);
+ free (xtag);
+ }
+ if (!from_gml_geometry)
+ free (xvalue);
+ }
+ }
+ else
+ {
+ int i;
+ fprintf (out, ">\n");
+ node_id = 0;
+ for (i = 0; i < sqlite3_column_count (stmt); i++)
+ {
+ const char *column = sqlite3_column_name (stmt, i);
+ if (strcasecmp (column, "node_id") == 0)
+ {
+ node_id = sqlite3_column_int64 (stmt, i);
+ break;
+ }
+ }
+ child = node->first;
+ while (child != NULL)
+ {
+ /* recursively printing all Children nodes */
+ do_print_xml_child (out, child, node_id, sqlite);
+ child = child->next;
+ }
+ /* printing the XML Node end-tag */
+ if (node->xml_prefix == NULL)
+ {
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "%s</%s>\n", indent, xtag);
+ free (xtag);
+ }
+ else
+ {
+ xprefix = clean_xml (node->xml_prefix);
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "%s</%s:%s>\n", indent, xprefix,
+ xtag);
+ free (xprefix);
+ free (xtag);
+ }
+ }
+ }
+ else
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ free (indent);
+ return;
+ }
+ }
+ free (indent);
+}
+
+static void
+do_print_xml (FILE * out, struct xml_node *node, sqlite3 * sqlite)
+{
+/* printing the XML document - ROOT Node */
+ int ret;
+ int i;
+ sqlite3_stmt *stmt = node->stmt;
+ if (stmt == NULL)
+ return;
+
+ fprintf (out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+
+ while (1)
+ {
+ /* fetching the result set rows */
+ ret = sqlite3_step (stmt);
+ if (ret == SQLITE_DONE)
+ break; /* end of result set */
+ if (ret == SQLITE_ROW)
+ {
+ /* fetching a row */
+ struct xml_attr *attr;
+ struct xml_node *child;
+ char *xprefix;
+ char *xtag;
+ char *xvalue;
+ sqlite3_int64 node_id;
+ /* printing the XML Node start-tag */
+ if (node->xml_prefix == NULL)
+ {
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "<%s", xtag);
+ free (xtag);
+ }
+ else
+ {
+ xprefix = clean_xml (node->xml_prefix);
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "<%s:%s", xprefix, xtag);
+ free (xprefix);
+ free (xtag);
+ }
+ attr = node->first_attr;
+ while (attr != NULL)
+ {
+ /* printing all Node Attributes */
+ const char *value = NULL;
+ for (i = 0; i < sqlite3_column_count (stmt); i++)
+ {
+ const char *column = sqlite3_column_name (stmt, i);
+ if (strcasecmp (column, attr->attr_name) == 0)
+ {
+ if (sqlite3_column_type (stmt, i) ==
+ SQLITE_NULL)
+ ;
+ else
+ value =
+ (const char *)
+ sqlite3_column_text (stmt, i);
+ break;
+ }
+ }
+ if (value == NULL)
+ {
+ /* skipping NULL attributes */
+ attr = attr->next;
+ continue;
+ }
+ if (attr->attr_prefix == NULL)
+ {
+ xtag = clean_xml (attr->attr_name);
+ xvalue = clean_xml (value);
+ fprintf (out, " %s=\"%s\"", xtag, xvalue);
+ free (xtag);
+ free (xvalue);
+ }
+ else
+ {
+ xprefix = clean_xml (attr->attr_prefix);
+ xtag = clean_xml (attr->attr_name);
+ xvalue = clean_xml (value);
+ fprintf (out, " %s:%s=\"%s\"", xprefix, xtag,
+ xvalue);
+ free (xprefix);
+ free (xtag);
+ free (xvalue);
+ }
+ attr = attr->next;
+ }
+ if (node->first == NULL)
+ {
+ /* we have no Childern nodes for sure */
+ int from_gml_geometry = 0;
+ const char *value = NULL;
+ xvalue = NULL;
+ for (i = 0; i < sqlite3_column_count (stmt); i++)
+ {
+ const char *column = sqlite3_column_name (stmt, i);
+ if (strcasecmp (column, "from_gml_geometry") == 0)
+ from_gml_geometry = 1;
+ if (strcasecmp (column, "node_value") == 0)
+ {
+ if (sqlite3_column_type (stmt, i) !=
+ SQLITE_NULL)
+ value =
+ (const char *)
+ sqlite3_column_text (stmt, i);
+ }
+ }
+ if (value == NULL)
+ fprintf (out, " />\n");
+ else
+ {
+ if (!from_gml_geometry)
+ xvalue = clean_xml (value);
+ else
+ xvalue = (char *) value;
+ if (node->xml_prefix == NULL)
+ {
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, ">%s</%s>\n", xvalue, xtag);
+ free (xtag);
+ }
+ else
+ {
+ xprefix = clean_xml (node->xml_prefix);
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, ">%s</%s:%s>\n", xvalue,
+ xprefix, xtag);
+ free (xprefix);
+ free (xtag);
+ }
+ if (!from_gml_geometry)
+ free (xvalue);
+ }
+ }
+ else
+ {
+ fprintf (out, ">\n");
+ node_id = 0;
+ for (i = 0; i < sqlite3_column_count (stmt); i++)
+ {
+ const char *column = sqlite3_column_name (stmt, i);
+ if (strcasecmp (column, "node_id") == 0)
+ {
+ node_id = sqlite3_column_int64 (stmt, i);
+ break;
+ }
+ }
+ child = node->first;
+ while (child != NULL)
+ {
+ /* recursively printing all Children nodes */
+ do_print_xml_child (out, child, node_id, sqlite);
+ child = child->next;
+ }
+ /* printing the XML Node end-tag */
+ if (node->xml_prefix == NULL)
+ {
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "</%s>\n", xtag);
+ free (xtag);
+ }
+ else
+ {
+ xprefix = clean_xml (node->xml_prefix);
+ xtag = clean_xml (node->xml_tag);
+ fprintf (out, "</%s:%s>\n", xprefix, xtag);
+ free (xprefix);
+ free (xtag);
+ }
+ }
+ }
+ else
+ {
+ fprintf (stderr, "SQL error: %s\n", sqlite3_errmsg (sqlite));
+ return;
+ }
+ }
+}
+
+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];
+
+ *handle = NULL;
+ printf ("SQLite version: %s\n", sqlite3_libversion ());
+ printf ("SpatiaLite version: %s\n", spatialite_version ());
+
+ ret = sqlite3_open_v2 (path, &db_handle, SQLITE_OPEN_READONLY, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf (stderr, "cannot open '%s': %s\n", path,
+ sqlite3_errmsg (db_handle));
+ sqlite3_close (db_handle);
+ db_handle = NULL;
+ return;
+ }
+ spatialite_init_ex (db_handle, cache, 0);
+
+ if (cache_size > 0)
+ {
+ /* setting the CACHE-SIZE */
+ sprintf (sql, "PRAGMA cache_size=%d", cache_size);
+ sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
+ }
+
+/* enabling PK/FK constraints */
+ sqlite3_exec (db_handle, "PRAGMA foreign_keys = 1", NULL, NULL, NULL);
+ *handle = db_handle;
+ return;
+}
+
+static void
+do_help ()
+{
+/* printing the argument list */
+ fprintf (stderr, "\n\nusage: spatialite_xml_printf 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 [INPUT] path\n\n");
+ fprintf (stderr,
+ "-x or --xml-path pathname the XML file [OUUPUT] path\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");
+}
+
+int
+main (int argc, char *argv[])
+{
+/* the MAIN function mainly perform arguments checking */
+ sqlite3 *handle;
+ int i;
+ int next_arg = ARG_NONE;
+ const char *xml_path = NULL;
+ const char *db_path = NULL;
+ int cache_size = 0;
+ int error = 0;
+ void *cache;
+ struct xml_node *master = NULL;
+ FILE *out = NULL;
+
+ for (i = 1; i < argc; i++)
+ {
+ /* parsing the invocation arguments */
+ if (next_arg != ARG_NONE)
+ {
+ switch (next_arg)
+ {
+ case ARG_XML_PATH:
+ xml_path = argv[i];
+ break;
+ case ARG_DB_PATH:
+ db_path = argv[i];
+ break;
+ case ARG_CACHE_SIZE:
+ cache_size = atoi (argv[i]);
+ 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], "-x") == 0)
+ {
+ next_arg = ARG_XML_PATH;
+ continue;
+ }
+ if (strcasecmp (argv[i], "--xml-path") == 0)
+ {
+ next_arg = ARG_XML_PATH;
+ continue;
+ }
+ 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], "--cache-size") == 0
+ || strcmp (argv[i], "-cs") == 0)
+ {
+ next_arg = ARG_CACHE_SIZE;
+ continue;
+ }
+ fprintf (stderr, "unknown argument: %s\n", argv[i]);
+ error = 1;
+ }
+ if (error)
+ {
+ do_help ();
+ return -1;
+ }
+
+/* checking the arguments */
+ if (!xml_path)
+ {
+ fprintf (stderr,
+ "did you forget setting the --xml-path argument ?\n");
+ error = 1;
+ }
+ if (!db_path)
+ {
+ fprintf (stderr, "did you forget setting the --db-path argument ?\n");
+ error = 1;
+ }
+ if (error)
+ {
+ do_help ();
+ return -1;
+ }
+
+/* opening the DB */
+ cache = spatialite_alloc_connection ();
+ open_db (db_path, &handle, cache_size, cache);
+ if (!handle)
+ return -1;
+
+ printf ("Input DB: %s\n", db_path);
+
+/* preparing the XML Tree */
+ master = do_build_master (handle);
+ if (master == NULL)
+ goto error;
+
+/* opening the XML output file */
+ out = fopen (xml_path, "w");
+ if (out == NULL)
+ {
+ fprintf (stderr,
+ "Unable to create/open the output destination \"%s\"\n",
+ xml_path);
+ }
+
+/* printing the output XML */
+ do_print_xml (out, master, handle);
+
+ error:
+ if (out != NULL)
+ fclose (out);
+ if (master != NULL)
+ do_destroy_node (master);
+ sqlite3_close (handle);
+ spatialite_cleanup_ex (cache);
+ return 0;
+}
--
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