[gdal] 03/08: Imported Upstream version 2.1.2~rc1+dfsg

Bas Couwenberg sebastic at debian.org
Fri Oct 14 17:09:16 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch experimental-2.1
in repository gdal.

commit e24d48963eaaf1bbc9f417e8b9f77482bf54159c
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Oct 14 13:52:47 2016 +0200

    Imported Upstream version 2.1.2~rc1+dfsg
---
 GDALmake.opt.in                                    |    2 +-
 NEWS                                               |  163 +-
 VERSION                                            |    2 +-
 apps/gdal_translate_bin.cpp                        |   10 +-
 apps/gdal_translate_lib.cpp                        |   14 +-
 apps/gdal_utilities.dox                            |   10 +-
 apps/gdaldem_lib.cpp                               |    4 +-
 apps/gdalwarp_bin.cpp                              |   10 +-
 apps/gdalwarp_lib.cpp                              |    6 +-
 apps/ogr2ogr_lib.cpp                               |    8 +-
 frmts/aigrid/gridlib.c                             |   52 +-
 frmts/georaster/GNUmakefile                        |    4 +-
 frmts/georaster/georaster_priv.h                   |    6 +-
 frmts/georaster/georaster_wrapper.cpp              |  300 ++--
 frmts/gtiff/geotiff.cpp                            |   68 +-
 frmts/gtiff/gt_overview.cpp                        |   96 +-
 frmts/hdf4/hdf4dataset.cpp                         |   36 +-
 frmts/hdf5/hdf5imagedataset.cpp                    |   37 +-
 frmts/mbtiles/mbtilesdataset.cpp                   |   38 +-
 frmts/netcdf/netcdfdataset.cpp                     |   12 +-
 frmts/raw/btdataset.cpp                            |    4 +-
 frmts/raw/envidataset.cpp                          |   39 +-
 frmts/raw/iscedataset.cpp                          |   29 +-
 frmts/raw/roipacdataset.cpp                        |   23 +-
 frmts/rmf/rmfdem.cpp                               |    4 +-
 frmts/srtmhgt/srtmhgtdataset.cpp                   |   10 +-
 frmts/vrt/vrtdataset.cpp                           |    9 +-
 frmts/vrt/vrtdataset.h                             |    6 +-
 frmts/vrt/vrtfilters.cpp                           |   10 +-
 frmts/vrt/vrtsourcedrasterband.cpp                 |   99 +-
 frmts/vrt/vrtsources.cpp                           |  228 +--
 gcore/gdal_priv.h                                  |   11 +-
 gcore/gdal_version.h                               |    6 +-
 gcore/gdaldataset.cpp                              |   80 +-
 gcore/gdaldrivermanager.cpp                        |    8 +-
 gcore/gdalrasterband.cpp                           |   41 +-
 gcore/gdalrasterblock.cpp                          |   12 +-
 man/man1/gdal-config.1                             |    2 +-
 man/man1/gdal2tiles.1                              |    2 +-
 man/man1/gdal_calc.1                               |    2 +-
 man/man1/gdal_contour.1                            |    2 +-
 man/man1/gdal_edit.1                               |    2 +-
 man/man1/gdal_fillnodata.1                         |    2 +-
 man/man1/gdal_grid.1                               |    2 +-
 man/man1/gdal_merge.1                              |    2 +-
 man/man1/gdal_pansharpen.1                         |    2 +-
 man/man1/gdal_polygonize.1                         |    2 +-
 man/man1/gdal_proximity.1                          |    2 +-
 man/man1/gdal_rasterize.1                          |    2 +-
 man/man1/gdal_retile.1                             |    2 +-
 man/man1/gdal_sieve.1                              |    2 +-
 man/man1/gdal_translate.1                          |    4 +-
 man/man1/gdal_utilities.1                          |    2 +-
 man/man1/gdaladdo.1                                |    2 +-
 man/man1/gdalbuildvrt.1                            |    2 +-
 man/man1/gdalcompare.1                             |    2 +-
 man/man1/gdaldem.1                                 |    2 +-
 man/man1/gdalinfo.1                                |    2 +-
 man/man1/gdallocationinfo.1                        |    2 +-
 man/man1/gdalmanage.1                              |    2 +-
 man/man1/gdalmove.1                                |    2 +-
 man/man1/gdalsrsinfo.1                             |    2 +-
 man/man1/gdaltindex.1                              |    2 +-
 man/man1/gdaltransform.1                           |    2 +-
 man/man1/gdalwarp.1                                |    2 +-
 man/man1/gnm_utilities.1                           |    2 +-
 man/man1/gnmanalyse.1                              |    2 +-
 man/man1/gnmmanage.1                               |    2 +-
 man/man1/nearblack.1                               |    2 +-
 man/man1/ogr2ogr.1                                 |    2 +-
 man/man1/ogr_utilities.1                           |    2 +-
 man/man1/ogrinfo.1                                 |    2 +-
 man/man1/ogrlineref.1                              |    2 +-
 man/man1/ogrtindex.1                               |    2 +-
 man/man1/pct2rgb.1                                 |    2 +-
 man/man1/rgb2pct.1                                 |    2 +-
 ogr/ogrgeometry.cpp                                |   12 +-
 ogr/ogrsf_frmts/GNUmakefile                        |    2 +-
 ogr/ogrsf_frmts/{cartodb => carto}/GNUmakefile     |    4 +-
 .../drv_cartodb.html => carto/drv_carto.html}      |   40 +-
 ogr/ogrsf_frmts/{cartodb => carto}/makefile.vc     |    2 +-
 .../{cartodb/ogr_cartodb.h => carto/ogr_carto.h}   |   74 +-
 .../ogrcartodatasource.cpp}                        |  133 +-
 .../ogrcartodriver.cpp}                            |   64 +-
 .../ogrcartolayer.cpp}                             |   51 +-
 .../ogrcartoresultlayer.cpp}                       |   31 +-
 .../ogrcartotablelayer.cpp}                        |  224 +--
 ogr/ogrsf_frmts/csv/drv_csv.html                   |    2 +-
 ogr/ogrsf_frmts/generic/GNUmakefile                |    2 +-
 ogr/ogrsf_frmts/generic/makefile.vc                |    4 +-
 ogr/ogrsf_frmts/generic/ogrregisterall.cpp         |    8 +-
 ogr/ogrsf_frmts/gml/drv_gml.html                   |   18 +-
 ogr/ogrsf_frmts/gml/gmlhandler.cpp                 |   13 +-
 ogr/ogrsf_frmts/gml/gmlreader.cpp                  |   11 +-
 ogr/ogrsf_frmts/gml/gmlreader.h                    |    4 +-
 ogr/ogrsf_frmts/gml/gmlreaderp.h                   |   10 +-
 ogr/ogrsf_frmts/gml/gmlutils.cpp                   |   39 +-
 ogr/ogrsf_frmts/gml/gmlutils.h                     |   10 +-
 ogr/ogrsf_frmts/gml/ogr_gml.h                      |    5 +-
 ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp           |   13 +-
 ogr/ogrsf_frmts/gml/ogrgmldriver.cpp               |   11 +-
 ogr/ogrsf_frmts/gml/ogrgmllayer.cpp                |    6 +-
 ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp  |  248 +--
 ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h           |    7 +-
 ogr/ogrsf_frmts/gpkg/ogr_geopackage.h              |  115 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |  876 ++++++++---
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp       |    5 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp        |   28 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp   | 1604 ++++++++++++++++----
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp      |  136 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h        |    6 +-
 ogr/ogrsf_frmts/makefile.vc                        |    8 +-
 .../mssqlspatial/ogrmssqlspatialselectlayer.cpp    |   30 +-
 ogr/ogrsf_frmts/nas/nashandler.cpp                 |   10 +-
 ogr/ogrsf_frmts/oci/GNUmakefile                    |    4 +-
 ogr/ogrsf_frmts/oci/drv_oci.html                   |   44 +-
 ogr/ogrsf_frmts/oci/makefile.vc                    |    1 +
 ogr/ogrsf_frmts/oci/ogr_oci.h                      |   10 +-
 ogr/ogrsf_frmts/oci/ogrocidatasource.cpp           |   48 +-
 ogr/ogrsf_frmts/oci/ogrocidriver.cpp               |    9 +-
 ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp           |   42 +-
 ogr/ogrsf_frmts/ogr_formats.html                   |    4 +-
 ogr/ogrsf_frmts/ogrsf_frmts.h                      |    5 +-
 ogr/ogrsf_frmts/pg/ogr_pg.h                        |    5 +-
 ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp             |   13 +-
 ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp             |   11 +-
 ogr/ogrsf_frmts/pg/ogrpgutility.cpp                |   22 +-
 ogr/ogrsf_frmts/pg/ogrpgutility.h                  |    4 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp    |    5 +-
 ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp      |   52 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp  |    5 +-
 ogr/ogrsf_frmts/s57/ogrs57datasource.cpp           |   26 +-
 ogr/ogrsf_frmts/shape/dbfopen.c                    |    7 +-
 ogr/ogrsf_frmts/shape/ogrshapelayer.cpp            |  566 +++++--
 ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp     |   21 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp     |   20 +-
 ogr/ogrsf_frmts/xlsx/ogr_xlsx.h                    |   15 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp         |  112 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp             |   13 +-
 port/cpl_vsil_curl.cpp                             |  108 +-
 port/cpl_worker_thread_pool.cpp                    |    4 +-
 port/cplgetsymbol.cpp                              |   19 +-
 scripts/gdal-bash-completion.sh                    |    2 +-
 swig/include/perl/gdal_perl.i                      |    4 +-
 swig/include/perl/ogr_perl.i                       |    2 +-
 swig/perl/lib/Geo/GDAL.pm                          |    4 +-
 swig/perl/lib/Geo/OGR.pm                           |    2 +-
 swig/python/scripts/gdal2xyz.py                    |    8 +-
 swig/python/setup.py                               |    2 +-
 149 files changed, 4711 insertions(+), 1951 deletions(-)

diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index e3ebef4..4a05588 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -121,7 +121,7 @@ GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
 LIBGDAL_CURRENT	:=	21
-LIBGDAL_REVISION	:=	1
+LIBGDAL_REVISION	:=	2
 LIBGDAL_AGE	:=	1
 
 # native build targets and variables
diff --git a/NEWS b/NEWS
index 2937495..c0b8bec 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,158 @@
+= GDAL/OGR 2.1.2 Release Notes = 
+
+The 2.1.2 release is a bug fix release.
+
+== Port ==
+* Fix deadlock at CPLWorkerThreadPool destruction (#6646)
+* CPLGetSymbol() on Windows: honour GDAL_FILENAME_IS_UTF8 setting to call
+  LoadLibraryW() (#6650)
+* /vsicurl/: take CPL_VSIL_CURL_ALLOWED_EXTENSIONS into account even if
+  GDAL_DISABLE_READDIR_ON_OPEN is defined (#6681)
+
+== GDAL algorithms ==
+
+== GDAL Core ==
+* Nodata comparison: fix test when nodata is FLT_MIN or DBL_MIN (#6578)
+* External overview: fix incorrect overview building when generating from greater
+  overview factors to lower ones, in compressed and single-band case (#6617)
+* Make sure that GDALSetCacheMax() initialize the raster block mutex (#6611)
+* Fix potential deadlock in multithreaded writing scenarios (#6661)
+* Make multi-threaded reading/writing when using GetLockedBlock()/MarkDirty()/
+  DropLock() lower level interfaces (#6665)
+
+== Utilities ==
+* gdal_translate & gdalwarp: lower the default value of GDAL_MAX_DATASET_POOL_SIZE
+  to 100 on MacOSX (#6604)
+* gdalwarp: when -to RPC_DEM is specified, make -et default to 0 as documented (#6608)
+* gdal_translate: when using -projwin with default nearest neighbour resampling,
+  align on integer source pixels (#6610)
+* gdal2xyz: use %d formatting for Int32/UInt32 data types (#6644)
+
+== GDAL drivers ==
+
+AIGRID driver:
+* fix 2.1.0 regression when reading statistics (.sta) file with only 3 values,
+  and fix <2.1 behaviour to read them in LSB order (#6633)
+
+ENVI driver:
+* on closing, pad image file with trailing nul bytes if needed (#6662)
+
+GeoRaster driver:
+* fix for geotransform matrix with rotation terms (#6593)
+
+GPKG driver:
+* check if transaction COMMIT is successful (#6667)
+* fix crash on overview building on big overview factor (#6668)
+
+GTiff driver:
+* fix saving and loading band description (#6592)
+* avoid reading external metadata file that could be related to the target
+  filename when using Create() or CreateCopy() (#6594)
+* do not generate erroneous ExtraSamples tag when translating from a RGB UInt16,
+  without explicit PHOTOMETRIC=RGB (#6647)
+
+HDF4 driver:
+* Fixed erroneous type casting in HDF4Dataset::AnyTypeToDouble() breaking reading
+  georeference data and some other metadata from HDF4-EOS datasets (#6618)
+
+HDF5 driver:
+* correct number of GCPs to avoid dummy trailing (0,0)->(0,0,0) and remove +180
+  offset applied to GCP longitude. Add instead a heuristics to determine if the
+  product is crossing the antimeridian, and a HDF5_SHIFT_GCPX_BY_180 config option
+  to be able to override the heuristics (#6666)
+
+ISCE driver:
+* make parsing of properties case insensitive (#6637)
+
+netCDF driver:
+* fix crash on datasets with 1D variable with 0 record (#6645)
+
+RMF driver:
+* fix wrong counter decrement that caused compressed RMF to be incorrectly
+  decompressed (https://github.com/OSGeo/gdal/pull/153)
+
+ROI_PAC driver:
+* fix computation of line offset for multi-band BIP files, and warn if detecting
+  a wrong file produced by GDAL >= 2.0.0 (#6591)
+
+SRTMHGT driver:
+* accept filenames like NXXEYYY.SRTMGL1.hgt (#6614)
+
+VRT driver:
+* make CheckCompatibleForDatasetIO() return FALSE on VRTDerivedRasterBands (#6599)
+* fix performance issue when nodata set at band level and non-nearest resampling used (#6628)
+* VRTComplexSource: do temp computations on double to avoid precision issues
+  when band data type is Int32/UInt32/CInt32/Float64/CFloat64 (#6642)
+
+== OGR core ==
+
+== OGR utilities ==
+* GDALVectorTranslate(): imply update mode if access mode not explicitly
+  specified and hDstDS != NULL (#6612)
+
+== OGR drivers == 
+
+Carto driver:
+* rebranded from CartoDB to Carto. "CartoDB" is still a valid alias to Carto
+
+GPKG:
+* update schema to reflect CURRENT_TIMESTAMP -> 'now' changes (https://github.com/OSGeo/gdal/pull/155)
+* do not emit error when running ExecuteSQL() with a spatial filter on an empty
+  layer (#6639)
+* list (non spatial) layers not registered in gpkg_contents (#6679)
+* robustified layer deletion and renaming (#6679)
+* implementation of DeleteField, AlterFieldDefn and ReorderFields (#6679)
+* GetExtent() to save computed extent in gpkg_contents if empty (#6679)
+* add 'RECOMPUTE EXTENT ON' special SQL (#6679)
+* update last modified date on tiles update (#6679) 
+* check identifier unicity on layer creation (#6679)
+* add possibility to disable foreign key check by setting
+  OGR_GPKG_FOREIGN_KEY_CHECK=NO config option (#6679)
+* add HasSpatialIndex(tblname,geomcolname) SQL function (#6679)
+
+GML driver:
+* remove hack for CityGML regarding forcing srsDimension to 3 if not specified.
+  Instead add a GML_SRS_DIMENSION_IF_MISSING config option that can be set to
+  3 if needed (#6597)
+* consider srsName with URL like 'http://www.opengis.net/def/crs/EPSG/0/' as
+  following EPSG axis order. Add SWAP_COORDINATES=YES/NO/AUTO (and
+  GML_SWAP_COORDINATES configuration option) to override all auto guessing (#6678)
+
+MSSQLSpatial driver:
+* Fix select layer to recognize geometry column with sqlncli (#6641)
+
+NAS driver:
+* Fix to handle that 'anlass' is optional
+
+OCI driver:
+* 3 new options: MULTI_LOAD, MULTI_LOAD_COUNT, FIRST_ID (#6606)
+
+PG driver:
+* fix errors caused by missing geometry_columns/spatial_ref_sys tables in non
+  PostGIS databases, that prevent reading more than 500 features (http://hub.qgis.org/issues/10904)
+
+PLScenes driver:
+* add HTTP retry logic (#6655)
+* V0 API: workaround limitations on filtering on image_statistics.image_quality (#6657)
+
+S57 driver:
+* fix GDAL 2.1.1 regression where open options are ignored if OGR_S57_OPTIONS
+  config option is not defined (#6609)
+
+Shapefile driver:
+* change REPACK implementation on Windows to be robust to remaining file
+  descriptors openend on the .shp/.shx/.dbf (#6672)
+
+SQLite driver:
+* do not emit error when running ExecuteSQL() with a spatial filter on an
+  empty layer (#6639)
+* Spatialite: avoid crash when creating layer with geom_type = wkbCurve (#6660)
+* don't touch nSoftTransactionLevel in DoTransactionCommand() in case of error,
+  since it can cause later CPLAssert() to trigger (#6667)
+
+XLSX driver:
+* only list worksheets (and no charts) as layers (#6680)
+
 = GDAL/OGR 2.1.1 Release Notes = 
 
 The 2.1.1 release is a bug fix release.
@@ -776,7 +931,7 @@ PG driver:
  * Add PRELUDE_STATEMENTS and CLOSING_STATEMENTS open option to be for example able to specify options, like statement_timeout, with pg_bouncer
  * Fix 2.0 regression when overwriting several existing PostGIS layers with ogr2ogr (#6018)
  * Update PG, PGDump and CartoDB drivers to correctly export POINT EMPTY for PostGIS 2.2
- * avoid reseting error potentially emitted by ExecuteSQL() (#6194)
+ * avoid resetting error potentially emitted by ExecuteSQL() (#6194)
  * sanitize management of quoting for FID column at layer creation
  * fix to get SRID on result layer with PostGIS 2.2
  * in copy mode (the default on layer creation), do not truncate the concatenated string list to the field width (#6356)
@@ -1418,7 +1573,7 @@ Utilities:
  * ogr2ogr: add special case for -update and GPKG and input=output
  * ogr2ogr: when copying a layer that has a source integer/integer64 field with same name as target FID column, avoid creating it into target layer and use its content as the FID value (#5845)
  * ogr2ogr: in non-append mode, if target layer has a FID creation option, reuse source FID name and source FIDs, unless -unsetFid is specified (#5845)
- * ogr2ogr: copy source dataset and layer metadata, unless disabled by -nomd. Additionnal dataset metadata can be set with -mo KEY=VALUE
+ * ogr2ogr: copy source dataset and layer metadata, unless disabled by -nomd. Additional dataset metadata can be set with -mo KEY=VALUE
  * ogr2ogr: add -ds_transaction to force dataset transactions, mainly for FileGDB driver
  * ogr2ogr: fix crash with -clipdst when a reprojection fails before (#5973)
  * ogrlineref: fix project if reper lies on first point or last point of line
@@ -3440,7 +3595,7 @@ Port:
  * /vsicurl/ : fetch more info (size, date) when listing FTP or HTTP directories and save it in cache; use those info for ReadDir() and Stat()
  * /vsicurl/: accept 225 as a valid response code for FTP downloads (#4365)
  * /vsicurl/ : add CPL_VSIL_CURL_ALLOWED_EXTENSIONS configuration option that can be used to restrict files whose existence is going to be tested.
- * /vsitar/ : Recognize additionnal .tar files with slightly header differences
+ * /vsitar/ : Recognize additional .tar files with slightly header differences
  * /vsizip/ : wrap the returned file handle in a BufferedReader
  * /vsizip/ : fix 1900 year offset for year returned by VSIStatL()
  * /vsizip and /vsitar: remove leading './' pattern at the beginning of filenames contained in the archive
@@ -6364,7 +6519,7 @@ NITF driver:
  * Apply untested RPC00A remapping (#2040)
  * Fix #2135 by narrowing workaround test made for #1750
  * Prevent crash on NITF file without image segment (#2362)
- * Additionnal fix for handling 1-bit uncompressed NITF images with NITF_IC=NM  (#1854)
+ * Additional fix for handling 1-bit uncompressed NITF images with NITF_IC=NM  (#1854)
  * Set IREP=RGB implicitly when the first 3 channels of an image are R,G,B (#2343)
  * Allocate one extra byte for the NULL terminating character when reading TEXT data in NITF file (#2366)
  * Fix 'adding BLOCKA TRE precludes writing IGEOLO' (#2475)
diff --git a/VERSION b/VERSION
index 3e3c2f1..eca07e4 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.1
+2.1.2
diff --git a/apps/gdal_translate_bin.cpp b/apps/gdal_translate_bin.cpp
index 95abfc1..bc8e71f 100644
--- a/apps/gdal_translate_bin.cpp
+++ b/apps/gdal_translate_bin.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_translate_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
+ * $Id: gdal_translate_bin.cpp 34776 2016-07-25 21:22:15Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Image Translator Program
@@ -34,7 +34,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdal_translate_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdal_translate_bin.cpp 34776 2016-07-25 21:22:15Z rouault $");
 
 /*  ******************************************************************* */
 /*                               Usage()                                */
@@ -167,7 +167,13 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL )
     {
+#if defined(__MACH__) && defined(__APPLE__)
+        // On Mach, the default limit is 256 files per process
+        // We should eventually dynamically query the limit
+        CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
+#else
         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
+#endif
     }
 
     GDALTranslateOptionsForBinary* psOptionsForBinary = GDALTranslateOptionsForBinaryNew();
diff --git a/apps/gdal_translate_lib.cpp b/apps/gdal_translate_lib.cpp
index 114507e..9be69a7 100644
--- a/apps/gdal_translate_lib.cpp
+++ b/apps/gdal_translate_lib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_translate_lib.cpp 33967 2016-04-13 21:29:33Z rouault $
+ * $Id: gdal_translate_lib.cpp 34813 2016-07-28 16:38:56Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Image Translator Program
@@ -38,7 +38,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdal_translate_lib.cpp 33967 2016-04-13 21:29:33Z rouault $");
+CPL_CVSID("$Id: gdal_translate_lib.cpp 34813 2016-07-28 16:38:56Z rouault $");
 
 static int ArgIsNumeric( const char * );
 static void AttachMetadata( GDALDatasetH, char ** );
@@ -728,6 +728,16 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 
         psOptions->adfSrcWin[2] = (psOptions->dfLRX - psOptions->dfULX) / adfGeoTransform[1];
         psOptions->adfSrcWin[3] = (psOptions->dfLRY - psOptions->dfULY) / adfGeoTransform[5];
+        
+        // In case of nearest resampling, round to integer pixels (#6610)
+        if( psOptions->pszResampling == NULL ||
+            EQUALN(psOptions->pszResampling, "NEAR", 4) )
+        {
+            psOptions->adfSrcWin[0] = floor(psOptions->adfSrcWin[0] + 0.001); 
+            psOptions->adfSrcWin[1] = floor(psOptions->adfSrcWin[1] + 0.001);
+            psOptions->adfSrcWin[2] = floor(psOptions->adfSrcWin[2] + 0.5);
+            psOptions->adfSrcWin[3] = floor(psOptions->adfSrcWin[3] + 0.5);
+        }
 
         /*if( !bQuiet )
             fprintf( stdout,
diff --git a/apps/gdal_utilities.dox b/apps/gdal_utilities.dox
index eb398f2..58e4ef0 100644
--- a/apps/gdal_utilities.dox
+++ b/apps/gdal_utilities.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_utilities.dox 33514 2016-02-20 15:02:29Z rouault $ */
+/* $Id: gdal_utilities.dox 34813 2016-07-28 16:38:56Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*! 
@@ -175,7 +175,7 @@ and exit.
 
 \htmlonly
 <p>
-$Id: gdal_utilities.dox 33514 2016-02-20 15:02:29Z rouault $
+$Id: gdal_utilities.dox 34813 2016-07-28 16:38:56Z rouault $
 </p>
 \endhtmlonly
 */
@@ -392,7 +392,11 @@ from the source image for copying based on pixel/line location.  </dd>
 <dt> <b>-projwin</b> <i>ulx uly lrx lry</i>:</dt><dd> Selects a subwindow from
 the source image for copying (like <b>-srcwin</b>) but with the corners given
 in georeferenced coordinates (by default expressed in the SRS of the dataset. Can be
-changed with -projwin_srs). </dd>
+changed with -projwin_srs).
+Note: in GDAL 2.1.0 and 2.1.1, using -projwin with coordinates not aligned with
+pixels will result in a sub-pixel shift. This has been corrected in later versions.
+When selecting non-nearest neighbour resampling, starting with GDAL 2.1.0,
+sub-pixel accuracy is however used.</dd>
 <dt> <b>-projwin_srs</b> <i>srs_def</i>:</dt><dd> (GDAL >= 2.0) Specifies the SRS in
 which to interpret the coordinates given with -projwin. The <i>srs_def</i> may
 be any of the usual GDAL/OGR forms, complete WKT, PROJ.4, EPSG:n or a file
diff --git a/apps/gdaldem_lib.cpp b/apps/gdaldem_lib.cpp
index 204b8d5..5ad1979 100644
--- a/apps/gdaldem_lib.cpp
+++ b/apps/gdaldem_lib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldem_lib.cpp 33782 2016-03-24 10:41:09Z rouault $
+ * $Id: gdaldem_lib.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  GDAL DEM Utilities
  * Purpose:
@@ -96,7 +96,7 @@
 #include "gdal_priv.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdaldem_lib.cpp 33782 2016-03-24 10:41:09Z rouault $");
+CPL_CVSID("$Id: gdaldem_lib.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 #define INTERPOL(a,b) ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) || ARE_REAL_EQUAL(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
 
diff --git a/apps/gdalwarp_bin.cpp b/apps/gdalwarp_bin.cpp
index 468d898..6e611f2 100644
--- a/apps/gdalwarp_bin.cpp
+++ b/apps/gdalwarp_bin.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarp_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $
+ * $Id: gdalwarp_bin.cpp 34776 2016-07-25 21:22:15Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -34,7 +34,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdalwarp_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: gdalwarp_bin.cpp 34776 2016-07-25 21:22:15Z rouault $");
 
 /******************************************************************************/
 /*! \page gdalwarp gdalwarp
@@ -381,7 +381,13 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
     if( CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", NULL) == NULL )
     {
+#if defined(__MACH__) && defined(__APPLE__)
+        // On Mach, the default limit is 256 files per process
+        // We should eventually dynamically query the limit
+        CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
+#else
         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
+#endif
     }
 
     GDALWarpAppOptionsForBinary* psOptionsForBinary = GDALWarpAppOptionsForBinaryNew();
diff --git a/apps/gdalwarp_lib.cpp b/apps/gdalwarp_lib.cpp
index 95e8f46..45cc937 100644
--- a/apps/gdalwarp_lib.cpp
+++ b/apps/gdalwarp_lib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarp_lib.cpp 34210 2016-05-10 21:08:22Z rouault $
+ * $Id: gdalwarp_lib.cpp 34790 2016-07-26 16:52:37Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -42,7 +42,7 @@
 #include <algorithm>
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdalwarp_lib.cpp 34210 2016-05-10 21:08:22Z rouault $");
+CPL_CVSID("$Id: gdalwarp_lib.cpp 34790 2016-07-26 16:52:37Z rouault $");
 
 /************************************************************************/
 /*                        GDALWarpAppOptions                            */
@@ -529,7 +529,7 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
     if( psOptions->dfErrorThreshold < 0 )
     {
         // By default, use approximate transformer unless RPC_DEM is specified
-        if( CSLFetchNameValue(psOptions->papszWarpOptions, "RPC_DEM") != NULL )
+        if( CSLFetchNameValue(psOptions->papszTO, "RPC_DEM") != NULL )
             psOptions->dfErrorThreshold = 0.0;
         else
             psOptions->dfErrorThreshold = 0.125;
diff --git a/apps/ogr2ogr_lib.cpp b/apps/ogr2ogr_lib.cpp
index e6ecaa1..efeb7e0 100644
--- a/apps/ogr2ogr_lib.cpp
+++ b/apps/ogr2ogr_lib.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr_lib.cpp 34384 2016-06-20 17:09:24Z rouault $
+ * $Id: ogr2ogr_lib.cpp 34858 2016-08-02 12:42:28Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for translating between formats.
@@ -42,7 +42,7 @@
 #include <map>
 #include <vector>
 
-CPL_CVSID("$Id: ogr2ogr_lib.cpp 34384 2016-06-20 17:09:24Z rouault $");
+CPL_CVSID("$Id: ogr2ogr_lib.cpp 34858 2016-08-02 12:42:28Z rouault $");
 
 typedef enum
 {
@@ -1267,6 +1267,10 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
         bOverwrite = true;
         bUpdate = true;
     }
+    else if( hDstDS != NULL )
+    {
+        bUpdate = true;
+    }
 
     osDateLineOffset = CPLOPrintf("%g", psOptions->dfDateLineOffset);
 
diff --git a/frmts/aigrid/gridlib.c b/frmts/aigrid/gridlib.c
index 48ad64e..0b624c1 100644
--- a/frmts/aigrid/gridlib.c
+++ b/frmts/aigrid/gridlib.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gridlib.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gridlib.c 35241 2016-08-29 08:49:57Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file reading code.
@@ -30,7 +30,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: gridlib.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gridlib.c 35241 2016-08-29 08:49:57Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -1122,11 +1122,12 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
     VSILFILE	*fp;
     double	adfStats[4];
     const size_t nHDRFilenameLen = strlen(pszCoverName)+40;
+    size_t nRead;
 
     psInfo->dfMin = 0.0;
     psInfo->dfMax = 0.0;
     psInfo->dfMean = 0.0;
-    psInfo->dfStdDev = 0.0;
+    psInfo->dfStdDev = -1.0;
 
 /* -------------------------------------------------------------------- */
 /*      Open the file sta.adf file.                                     */
@@ -1149,27 +1150,44 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
     CPLFree( pszHDRFilename );
 
 /* -------------------------------------------------------------------- */
-/*      Get the contents - four doubles.                                */
+/*      Get the contents - 3 or 4 doubles.                              */
 /* -------------------------------------------------------------------- */
-    if( VSIFReadL( adfStats, 1, 32, fp ) != 32 )
-    {
-        CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
-        return CE_Failure;
-    }
+    nRead = VSIFReadL( adfStats, 1, 32, fp );
 
     CPL_IGNORE_RET_VAL_INT(VSIFCloseL( fp ));
 
+    if( nRead == 32 )
+    {
 #ifdef CPL_LSB
-    CPL_SWAPDOUBLE(adfStats+0);
-    CPL_SWAPDOUBLE(adfStats+1);
-    CPL_SWAPDOUBLE(adfStats+2);
-    CPL_SWAPDOUBLE(adfStats+3);
+        CPL_SWAPDOUBLE(adfStats+0);
+        CPL_SWAPDOUBLE(adfStats+1);
+        CPL_SWAPDOUBLE(adfStats+2);
+        CPL_SWAPDOUBLE(adfStats+3);
 #endif
 
-    psInfo->dfMin = adfStats[0];
-    psInfo->dfMax = adfStats[1];
-    psInfo->dfMean = adfStats[2];
-    psInfo->dfStdDev = adfStats[3];
+        psInfo->dfMin = adfStats[0];
+        psInfo->dfMax = adfStats[1];
+        psInfo->dfMean = adfStats[2];
+        psInfo->dfStdDev = adfStats[3];
+    }
+    else if( nRead == 24 )
+    {
+        /* See dataset at https://trac.osgeo.org/gdal/ticket/6633 */
+        /* In that case, we have only min, max and mean, in LSB ordering */
+        CPL_LSBPTR64(adfStats+0);
+        CPL_LSBPTR64(adfStats+1);
+        CPL_LSBPTR64(adfStats+2);
+
+        psInfo->dfMin = adfStats[0];
+        psInfo->dfMax = adfStats[1];
+        psInfo->dfMean = adfStats[2];
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Wrong content for %s",
+                  pszHDRFilename );
+        return CE_Failure;
+    }
 
     return( CE_None );
 }
diff --git a/frmts/georaster/GNUmakefile b/frmts/georaster/GNUmakefile
index 0295263..de5aed6 100644
--- a/frmts/georaster/GNUmakefile
+++ b/frmts/georaster/GNUmakefile
@@ -11,7 +11,7 @@ OBJ		=	georaster_dataset.o \
 			oci_wrapper.o \
 			georaster_wrapper.o
 
-CPPFLAGS	:=	$(XTRA_OPT)  $(OCI_INCLUDE) $(CPPFLAGS)
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(OCI_INCLUDE) $(XTRA_OPT) $(CPPFLAGS) -fPIC
 
 ifneq ($(JPEG_SETTING),no)
 CPPFLAGS	:=	$(CPPFLAGS) -DJPEG_SUPPORTED
@@ -28,7 +28,7 @@ clean:
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
-PLUGIN_SO	= gdal_GEOR.$(SO_EXT)
+PLUGIN_SO	= gdal_GEOR.so
 
 plugin: $(PLUGIN_SO)
 
diff --git a/frmts/georaster/georaster_priv.h b/frmts/georaster/georaster_priv.h
index 3b50606..5fc4a03 100644
--- a/frmts/georaster/georaster_priv.h
+++ b/frmts/georaster/georaster_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: $
+ * $Id: georaster_priv.h 34879 2016-08-03 14:05:32Z ilucena $
  *
  * Name:     georaster_priv.h
  * Project:  Oracle Spatial GeoRaster Driver
@@ -330,6 +330,8 @@ private:
     struct jpeg_decompress_struct sDInfo;
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
+    
+    void                GetSpatialReference();
 
 public:
 
@@ -434,7 +436,7 @@ public:
     CPLString           sCompressionType;
     int                 nCompressQuality;
     CPLString           sWKText;
-    CPLString           sAuthority;
+
     CPLList*            psNoDataList;
 
     int                 nRasterColumns;
diff --git a/frmts/georaster/georaster_wrapper.cpp b/frmts/georaster/georaster_wrapper.cpp
index aa2a366..2898230 100644
--- a/frmts/georaster/georaster_wrapper.cpp
+++ b/frmts/georaster/georaster_wrapper.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: $
  *
  * Name:     georaster_wrapper.cpp
  * Project:  Oracle Spatial GeoRaster Driver
@@ -35,6 +34,8 @@
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 
+CPL_CVSID("$Id: georaster_wrapper.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 //  ---------------------------------------------------------------------------
 //                                                           GeoRasterWrapper()
 //  ---------------------------------------------------------------------------
@@ -325,28 +326,13 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     char szDataTable[OWCODE];
     char szWhere[OWTEXT];
     int nRasterId = -1;
-    int nSizeX = 0;
-    int nSizeY = 0;
-    int nSRID  = 0;
     OCILobLocator* phLocator = NULL;
-    double dfULx = 0.0;
-    double dfURx = 0.0;
-    double dfLRx = 0.0;
-    double dfULy = 0.0;
-    double dfLLy = 0.0;
-    double dfLRy = 0.0;
-    char szWKText[3 * OWTEXT];
-    char szAuthority[OWTEXT];
-    char szMLC[OWTEXT];
 
     szOwner[0]     = '\0';
     szTable[0]     = '\0';
     szColumn[0]    = '\0';
     szDataTable[0] = '\0';
     szWhere[0]     = '\0';
-    szWKText[0]    = '\0';
-    szAuthority[0] = '\0';
-    szMLC[0]       = '\0';
 
     if( ! poGRW->sOwner.empty() )
     {
@@ -378,10 +364,6 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     OWStatement* poStmt = poGRW->poConnection->CreateStatement(
       "DECLARE\n"
       "  SCM VARCHAR2(64) := 'xmlns=\"http://xmlns.oracle.com/spatial/georaster\"';\n"
-      "  GUL SDO_GEOMETRY := null;\n"
-      "  GUR SDO_GEOMETRY := null;\n"
-      "  GLL SDO_GEOMETRY := null;\n"
-      "  GLR SDO_GEOMETRY := null;\n"
       "BEGIN\n"
       "\n"
       "    IF :datatable IS NOT NULL AND :rasterid  > 0 THEN\n"
@@ -416,57 +398,6 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
       "\n"
       "    END IF;\n"
       "\n"
-      "  SELECT\n"
-      "    extractValue(XMLType(:metadata),"
-      "'/georasterMetadata/rasterInfo/dimensionSize[@type=\"ROW\"]/size', "
-      "SCM),\n"
-      "    extractValue(XMLType(:metadata),"
-      "'/georasterMetadata/rasterInfo/dimensionSize[@type=\"COLUMN\"]/size', "
-      "SCM),\n"
-      "    extractValue(XMLType(:metadata),"
-      "'/georasterMetadata/spatialReferenceInfo/SRID', "
-      "SCM),\n"
-      "    extractValue(XMLType(:metadata),"
-      "'/georasterMetadata/spatialReferenceInfo/modelCoordinateLocation', "
-      "SCM)\n"
-      "    INTO :sizey, :sizex, :srid, :mcl FROM DUAL;\n"
-      "\n"
-      "  EXECUTE IMMEDIATE\n"
-      "    'SELECT\n"
-      "      SDO_GEOR.getModelCoordinate('||:column||', 0, "
-      "SDO_NUMBER_ARRAY(0, 0)),\n"
-      "      SDO_GEOR.getModelCoordinate('||:column||', 0, "
-      "SDO_NUMBER_ARRAY(0, '||:sizex||')),\n"
-      "      SDO_GEOR.getModelCoordinate('||:column||', 0, "
-      "SDO_NUMBER_ARRAY('||:sizey||', 0)),\n"
-      "      SDO_GEOR.getModelCoordinate('||:column||', 0, "
-      "SDO_NUMBER_ARRAY('||:sizey||', '||:sizex||'))\n"
-      "     FROM  '||:owner||'.'||:table||' T\n"
-      "     WHERE T.'||:column||'.RASTERDATATABLE = UPPER(:1)\n"
-      "       AND T.'||:column||'.RASTERID = :2'\n"
-      "    INTO  GUL, GLL, GUR, GLR\n"
-      "    USING :datatable, :rasterid;\n"
-      "\n"
-      "  :ULx := GUL.sdo_point.x;\n"
-      "  :URx := GUR.sdo_point.x;\n"
-      "  :LRx := GLR.sdo_point.x;\n"
-      "  :ULy := GUL.sdo_point.y;\n"
-      "  :LLy := GLL.sdo_point.y;\n"
-      "  :LRy := GLR.sdo_point.y;\n"
-      "\n"
-      "  BEGIN\n"
-      "    EXECUTE IMMEDIATE\n"
-      "      'SELECT WKTEXT, AUTH_NAME\n"
-      "       FROM   MDSYS.CS_SRS\n"
-      "       WHERE  SRID = :1 AND WKTEXT IS NOT NULL'\n"
-      "      INTO   :wktext, :authority\n"
-      "      USING  :srid;\n"
-      "  EXCEPTION\n"
-      "    WHEN no_data_found THEN\n"
-      "      :wktext := '';\n"
-      "      :authority := '';\n"
-      "  END;\n"
-      "\n"
       "  EXCEPTION\n"
       "    WHEN no_data_found THEN :counter := 0;\n"
       "    WHEN too_many_rows THEN :counter := 2;\n"
@@ -482,18 +413,6 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
     poStmt->BindName( ":where", szWhere );
     poStmt->BindName( ":counter", &nCounter );
     poStmt->BindName( ":metadata", &phLocator );
-    poStmt->BindName( ":sizex", &nSizeX );
-    poStmt->BindName( ":sizey", &nSizeY );
-    poStmt->BindName( ":srid", &nSRID );
-    poStmt->BindName( ":mcl", szMLC );
-    poStmt->BindName( ":ULx", &dfULx );
-    poStmt->BindName( ":URx", &dfURx );
-    poStmt->BindName( ":LRx", &dfLRx );
-    poStmt->BindName( ":ULy", &dfULy );
-    poStmt->BindName( ":LLy", &dfLLy );
-    poStmt->BindName( ":LRy", &dfLRy );
-    poStmt->BindName( ":wktext", szWKText, sizeof(szWKText) );
-    poStmt->BindName( ":authority", szAuthority );
 
     CPLErrorReset();
 
@@ -528,8 +447,6 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
         return poGRW;
     }
 
-    poGRW->sWKText      = szWKText;
-    poGRW->sAuthority   = szAuthority;
     poGRW->sDataTable   = szDataTable;
     poGRW->nRasterId    = nRasterId;
     poGRW->sWhere       = CPLSPrintf(
@@ -553,6 +470,7 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
 
         poGRW->phMetadata = CPLParseXMLString( pszXML );
         poGRW->GetRasterInfo();
+        poGRW->GetSpatialReference();
     }
     else
     {
@@ -560,55 +478,6 @@ GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate
         poGRW->nRasterId  = 0;
     }
 
-    // --------------------------------------------------------------------
-    // Load Coefficients matrix
-    // --------------------------------------------------------------------
-
-    if ( EQUAL( szMLC, "UPPERLEFT" ) )
-    {
-      poGRW->eModelCoordLocation = MCL_UPPERLEFT;
-    }
-    else
-    {
-      poGRW->eModelCoordLocation = MCL_DEFAULT;
-    }
-
-    double dfRotation = 0.0;
-
-    if( ! CPLIsEqual( dfULy, dfLLy ) )
-    {
-        dfRotation = ( dfURx - dfULx ) / ( dfLLy - dfULy );
-    }
-
-    poGRW->dfXCoefficient[0] = ( dfLRx - dfULx ) / nSizeX;
-    poGRW->dfXCoefficient[1] = dfRotation;
-    poGRW->dfXCoefficient[2] = dfULx;
-    poGRW->dfYCoefficient[0] = -dfRotation;
-    poGRW->dfYCoefficient[1] = ( dfLRy - dfULy ) / nSizeY;
-    poGRW->dfYCoefficient[2] = dfULy;
-
-    if ( poGRW->eModelCoordLocation == MCL_CENTER )
-    {
-      poGRW->dfXCoefficient[2] -= poGRW->dfXCoefficient[0] / 2;
-      poGRW->dfYCoefficient[2] -= poGRW->dfYCoefficient[1] / 2;
-
-      CPLDebug("GEOR","eModelCoordLocation = MCL_CENTER");
-    }
-    else
-    {
-      CPLDebug("GEOR","eModelCoordLocation = MCL_UPPERLEFT");
-    }
-
-    //  -------------------------------------------------------------------
-    //  Apply ULTCoordinate
-    //  -------------------------------------------------------------------
-
-    poGRW->dfXCoefficient[2] +=
-                ( poGRW->anULTCoordinate[0] * poGRW->dfXCoefficient[0] );
-
-    poGRW->dfYCoefficient[2] +=
-                ( poGRW->anULTCoordinate[1] * poGRW->dfYCoefficient[1] );
-
     //  -------------------------------------------------------------------
     //  Clean up
     //  -------------------------------------------------------------------
@@ -2013,7 +1882,7 @@ bool GeoRasterWrapper::GetDataBlock( int nBand,
         //  ----------------------------------------------------------------
 
 #ifndef CPL_MSB
-        if( nCellSizeBits > 8 && 
+        if( nCellSizeBits > 8 &&
             EQUAL( sCompressionType.c_str(), "DEFLATE") == false )
         {
             int nWordSize  = nCellSizeBits / 8;
@@ -2367,6 +2236,165 @@ void GeoRasterWrapper::LoadNoDataValues( void )
 }
 
 //  ---------------------------------------------------------------------------
+//                                                        GetSpatialReference()
+//  ---------------------------------------------------------------------------
+
+void GeoRasterWrapper::GetSpatialReference()
+{
+    int i;
+
+    CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata, "spatialReferenceInfo" );
+    
+    if( phSRSInfo == NULL )
+    {
+        return;
+    }
+    
+    const char* pszMCL = CPLGetXMLValue( phSRSInfo, "modelCoordinateLocation", 
+                                                    "CENTER" );
+    
+    if( EQUAL( pszMCL, "CENTER" ) )
+    {
+      eModelCoordLocation = MCL_CENTER;
+    }
+    else
+    {
+      eModelCoordLocation = MCL_UPPERLEFT;
+    }
+
+    const char* pszModelType = CPLGetXMLValue( phSRSInfo, "modelType", "None" );
+    
+    if( EQUAL( pszModelType, "FunctionalFitting" ) == false )
+    {
+        return;
+    }
+
+    CPLXMLNode* phPolyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
+
+    if ( phPolyModel == NULL )
+    {
+        return;
+    }
+
+    CPLXMLNode* phPolynomial = CPLGetXMLNode( phPolyModel, "pPolynomial" );
+
+    if ( phPolynomial == NULL )
+    {
+        return;
+    }
+
+    int nNumCoeff = atoi( CPLGetXMLValue( phPolynomial, "nCoefficients", "0" ));
+
+    if ( nNumCoeff != 3 ) 
+    {
+        return;
+    }
+
+    const char* pszPolyCoeff = CPLGetXMLValue( phPolynomial, 
+                                             "polynomialCoefficients", "None" );
+
+    if ( EQUAL( pszPolyCoeff, "None" ) )
+    {
+        return;
+    }
+
+    char** papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", 
+                                           CSLT_STRIPLEADSPACES );
+
+    if( CSLCount( papszCeoff ) < 3 )
+    {
+        return;
+    }
+
+    double adfPCoef[3];
+    
+    for( i = 0; i < 3; i++ )
+    {
+        adfPCoef[i] = CPLAtof( papszCeoff[i] );
+    }
+
+    phPolynomial = CPLGetXMLNode( phPolyModel, "rPolynomial" );
+
+    if ( phPolynomial == NULL )
+    {
+        return;
+    }
+
+    pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
+
+    if ( EQUAL( pszPolyCoeff, "None" ) )
+    {
+        return;
+    }
+
+    papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
+
+    if( CSLCount( papszCeoff ) < 3 )
+    {
+        return;
+    }
+    
+    double adfRCoef[3];
+
+    for( i = 0; i < 3; i++ )
+    {
+        adfRCoef[i] = CPLAtof( papszCeoff[i] );
+    }
+
+    //  -------------------------------------------------------------------
+    //  Inverse the transformation matrix
+    //  -------------------------------------------------------------------
+
+    double adfVal[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
+
+    double dfDet = adfRCoef[1] * adfPCoef[2] - adfRCoef[2] * adfPCoef[1];
+   
+    if( CPLIsEqual( dfDet, 0.0 ) )
+    {
+        dfDet = 0.0000000001; // to avoid divide by zero
+        CPLError( CE_Warning, CPLE_AppDefined, "Determinant is ZERO!!!");
+    }
+
+    adfVal[0] =   adfPCoef[2] / dfDet;
+    adfVal[1] =  -adfRCoef[2] / dfDet;
+    adfVal[2] = -(adfRCoef[0] * adfPCoef[2] - adfPCoef[0] * adfRCoef[2]) / dfDet;
+    adfVal[3] =  -adfPCoef[1] / dfDet;
+    adfVal[4] =   adfRCoef[1] / dfDet;
+    adfVal[5] =  (adfRCoef[0] * adfPCoef[1] - adfPCoef[0] * adfRCoef[1]) / dfDet;
+
+    //  -------------------------------------------------------------------
+    //  Adjust Model Coordinate Location
+    //  -------------------------------------------------------------------
+    
+    if ( eModelCoordLocation == MCL_CENTER )
+    {
+        adfVal[2] -= adfVal[0] / 2.0;
+        adfVal[5] -= adfVal[4] / 2.0;
+    }
+/*
+    CPLDebug("GEOR", "m = [%g, %g, %g, %g, %g, %g]", adfRCoef[1], adfRCoef[2], 
+             adfRCoef[0], adfPCoef[1], adfPCoef[2], adfPCoef[0]);
+    
+    CPLDebug("GEOR", "i = [%g, %g, %g, %g, %g, %g]", adfVal[0], adfVal[1], 
+             adfVal[2], adfVal[3], adfVal[4], adfVal[5]);
+*/    
+    dfXCoefficient[0] = adfVal[0];
+    dfXCoefficient[1] = adfVal[1];
+    dfXCoefficient[2] = adfVal[2];
+    dfYCoefficient[0] = adfVal[3];
+    dfYCoefficient[1] = adfVal[4];
+    dfYCoefficient[2] = adfVal[5];
+    
+    //  -------------------------------------------------------------------
+    //  Apply ULTCoordinate
+    //  -------------------------------------------------------------------
+
+    dfXCoefficient[2] += ( anULTCoordinate[0] * dfXCoefficient[0] );
+
+    dfYCoefficient[2] += ( anULTCoordinate[1] * dfYCoefficient[1] );
+}
+
+//  ---------------------------------------------------------------------------
 //                                                                     GetRPC()
 //  ---------------------------------------------------------------------------
 
@@ -3145,8 +3173,6 @@ bool GeoRasterWrapper::FlushMetadata()
 
     if ( eModelCoordLocation == MCL_CENTER )
     {
-      dfXCoef[2] += dfXCoefficient[0] / 2;
-      dfYCoef[2] += dfYCoefficient[1] / 2;
       nMLC = MCL_CENTER;
     }
     else
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index bbae1f4..b7616d8 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff.cpp 34555 2016-07-05 18:39:17Z rouault $
+ * $Id: geotiff.cpp 35365 2016-09-08 07:53:35Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -65,7 +65,7 @@
 #include "tifvsi.h"
 #include "xtiffio.h"
 
-CPL_CVSID("$Id: geotiff.cpp 34555 2016-07-05 18:39:17Z rouault $");
+CPL_CVSID("$Id: geotiff.cpp 35365 2016-09-08 07:53:35Z rouault $");
 
 #if SIZEOF_VOIDP == 4
 static int bGlobalStripIntegerOverflow = FALSE;
@@ -3932,6 +3932,9 @@ void GTiffRasterBand::SetDescription( const char *pszDescription )
     if( pszDescription == NULL )
         pszDescription = "";
 
+    if( osDescription != pszDescription )
+        poGDS->bMetadataChanged = true;
+
     osDescription = pszDescription;
 }
 
@@ -9397,6 +9400,7 @@ void GTiffDataset::PushMetadataToPam()
             poBand->GDALPamRasterBand::SetDescription( poBand->GetDescription() );
         }
     }
+    MarkPamDirty();
 }
 
 /************************************************************************/
@@ -11890,6 +11894,8 @@ void GTiffDataset::LoadGeoreferencingAndPamIfNeeded()
                 if (pszUnitType)
                     poBand->osUnitType = pszUnitType;
             }
+            if( poBand->osDescription.size() == 0 )
+                poBand->osDescription = poBand->GDALPamRasterBand::GetDescription();
 
             GDALColorInterp ePAMColorInterp = poBand->GDALPamRasterBand::GetColorInterpretation();
             if( ePAMColorInterp != GCI_Undefined )
@@ -13166,6 +13172,9 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
     poDS->bCrystalized = FALSE;
     poDS->nSamplesPerPixel = (uint16) nBands;
     poDS->osFilename = pszFilename;
+ 
+    // Don't try to load external metadata files (#6597)
+    poDS->bIMDRPCMetadataLoaded = TRUE;
 
     /* Avoid premature crystalization that will cause directory re-writing */
     /* if GetProjectionRef() or GetGeoTransform() are called on the newly created GeoTIFF */
@@ -13556,6 +13565,25 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 #endif
 
 /* -------------------------------------------------------------------- */
+/*      If the source is RGB, then set the PHOTOMETRIC=RGB value        */
+/* -------------------------------------------------------------------- */
+
+    const bool bForcePhotometric =
+        CSLFetchNameValue(papszOptions, "PHOTOMETRIC") != NULL;
+
+    if( nBands >= 3 && !bForcePhotometric &&
+#ifdef HAVE_LIBJPEG
+        !bCopyFromJPEG &&
+#endif
+        poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_RedBand &&
+        poSrcDS->GetRasterBand(2)->GetColorInterpretation() == GCI_GreenBand &&
+        poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand )
+    {
+        papszCreateOptions =
+            CSLSetNameValue( papszCreateOptions, "PHOTOMETRIC", "RGB" );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Create the file.                                                */
 /* -------------------------------------------------------------------- */
     VSILFILE* fpL = NULL;
@@ -13582,39 +13610,6 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
         nCompression = COMPRESSION_NONE;
 
-    bool bForcePhotometric =
-        CSLFetchNameValue(papszOptions,"PHOTOMETRIC") != NULL;
-
-/* -------------------------------------------------------------------- */
-/*      If the source is RGB, then set the PHOTOMETRIC_RGB value        */
-/* -------------------------------------------------------------------- */
-    if( nBands >= 3 && !bForcePhotometric &&
-        nCompression != COMPRESSION_JPEG &&
-        poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_RedBand &&
-        poSrcDS->GetRasterBand(2)->GetColorInterpretation() == GCI_GreenBand &&
-        poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand )
-    {
-        TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
-
-        /* We need to update the number of extra samples */
-        uint16 *v;
-        uint16 count = 0;
-        uint16 nNewExtraSamplesCount = static_cast<uint16>(nBands - 3);
-        if( nBands >= 4 &&
-            TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) &&
-            count > nNewExtraSamplesCount )
-        {
-            uint16* pasNewExtraSamples =
-                (uint16*)CPLMalloc( nNewExtraSamplesCount * sizeof(uint16) );
-            memcpy( pasNewExtraSamples, v + count - nNewExtraSamplesCount,
-                    nNewExtraSamplesCount * sizeof(uint16) );
-
-            TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nNewExtraSamplesCount, pasNewExtraSamples);
-
-            CPLFree(pasNewExtraSamples);
-        }
-    }
-
 /* -------------------------------------------------------------------- */
 /*      Set the alpha channel if it is the last one.                    */
 /* -------------------------------------------------------------------- */
@@ -14165,6 +14160,9 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     poDS->bForceUnsetProjection = FALSE;
     poDS->bStreamingOut = bStreaming;
 
+    // Don't try to load external metadata files (#6597)
+    poDS->bIMDRPCMetadataLoaded = TRUE;
+
     /* We must re-set the compression level at this point, since it has */
     /* been lost a few lines above when closing the newly create TIFF file */
     /* The TIFFTAG_ZIPQUALITY & TIFFTAG_JPEGQUALITY are not store in the TIFF file. */
diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp
index 576b5a8..cc7981d 100644
--- a/frmts/gtiff/gt_overview.cpp
+++ b/frmts/gtiff/gt_overview.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_overview.cpp 33806 2016-03-28 22:26:19Z goatbar $
+ * $Id: gt_overview.cpp 35041 2016-08-10 14:04:52Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Code to build overviews of external databases as a TIFF file.
@@ -35,7 +35,9 @@
 #include "tifvsi.h"
 #include "xtiffio.h"
 
-CPL_CVSID("$Id: gt_overview.cpp 33806 2016-03-28 22:26:19Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: gt_overview.cpp 35041 2016-08-10 14:04:52Z rouault $");
 
 /************************************************************************/
 /*                         GTIFFWriteDirectory()                        */
@@ -714,6 +716,11 @@ GTIFFBuildOverviews( const char * pszFilename,
 /*      Loop writing overview data.                                     */
 /* -------------------------------------------------------------------- */
 
+    int * panOverviewListSorted = static_cast<int*>(
+                                        CPLMalloc(sizeof(int) * nOverviews));
+    memcpy( panOverviewListSorted, panOverviewList, sizeof(int) * nOverviews);
+    std::sort(panOverviewListSorted, panOverviewListSorted + nOverviews);
+
     GTIFFSetInExternalOvr(true);
 
     if (nCompression != COMPRESSION_NONE &&
@@ -725,41 +732,67 @@ GTIFFBuildOverviews( const char * pszFilename,
          EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") ||
          EQUAL(pszResampling, "BILINEAR")))
     {
-        /* In the case of pixel interleaved compressed overviews, we want to generate */
-        /* the overviews for all the bands block by block, and not band after band, */
-        /* in order to write the block once and not loose space in the TIFF file */
-        GDALRasterBand ***papapoOverviewBands;
-
-        papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
+        // In the case of pixel interleaved compressed overviews, we want to
+        // generate the overviews for all the bands block by block, and not
+        // band after band, in order to write the block once and not loose
+        // space in the TIFF file.
+        GDALRasterBand ***papapoOverviewBands =
+            static_cast<GDALRasterBand ***>(
+                CPLCalloc(sizeof(void *), nBands) );
         for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
         {
-            GDALRasterBand    *hSrcBand = papoBandList[iBand];
-            GDALRasterBand    *hDstBand = hODS->GetRasterBand( iBand+1 );
-            papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
-            papapoOverviewBands[iBand][0] = hDstBand;
-
-            int bHasNoData;
-            double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData);
-            if (bHasNoData)
-                hDstBand->SetNoDataValue(noDataValue);
-
-            for( int i = 0; i < nOverviews-1 && eErr == CE_None; i++ )
+            GDALRasterBand *poSrcBand = papoBandList[iBand];
+            GDALRasterBand *poDstBand = hODS->GetRasterBand( iBand+1 );
+            papapoOverviewBands[iBand] =
+                static_cast<GDALRasterBand **>(
+                    CPLCalloc(sizeof(void *), nOverviews) );
+
+            int bHasNoData = FALSE;
+            const double noDataValue = poSrcBand->GetNoDataValue(&bHasNoData);
+            if( bHasNoData )
+                poDstBand->SetNoDataValue(noDataValue);
+
+            for( int i = 0; i < nOverviews && eErr == CE_None; i++ )
             {
-                papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i);
-                if (papapoOverviewBands[iBand][i+1] == NULL)
-                    eErr = CE_Failure;
-                else
+                for( int j = -1; j < poDstBand->GetOverviewCount() &&
+                                 eErr == CE_None; j++ )
                 {
-                    if (bHasNoData)
-                        papapoOverviewBands[iBand][i+1]->SetNoDataValue(noDataValue);
+                    int    nOvFactor;
+                    GDALRasterBand * poOverview =
+                            (j < 0 ) ? poDstBand : poDstBand->GetOverview( j );
+                    if( poOverview == NULL )
+                    {
+                        eErr = CE_Failure;
+                        continue;
+                    }
+
+                    nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
+                                                    poSrcBand->GetXSize(),
+                                                    poOverview->GetYSize(),
+                                                    poSrcBand->GetYSize());
+
+                    if( nOvFactor == panOverviewListSorted[i]
+                        || nOvFactor == GDALOvLevelAdjust2(
+                                            panOverviewListSorted[i],
+                                            poSrcBand->GetXSize(),
+                                            poSrcBand->GetYSize() ) )
+                    {
+                        papapoOverviewBands[iBand][i] = poOverview;
+                        if( bHasNoData )
+                            poOverview->SetNoDataValue(noDataValue);
+                        break;
+                    }
                 }
+                CPLAssert( papapoOverviewBands[iBand][i] != NULL );
             }
         }
 
-        if (eErr == CE_None)
-            eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
-                                            nOverviews, papapoOverviewBands,
-                                            pszResampling, pfnProgress, pProgressData );
+        if( eErr == CE_None )
+            eErr =
+                GDALRegenerateOverviewsMultiBand(
+                    nBands, papoBandList,
+                    nOverviews, papapoOverviewBands,
+                    pszResampling, pfnProgress, pProgressData );
 
         for( iBand = 0; iBand < nBands; iBand++ )
         {
@@ -786,6 +819,9 @@ GTIFFBuildOverviews( const char * pszFilename,
             if (bHasNoData)
                 hDstBand->SetNoDataValue(noDataValue);
 
+            // FIXME: this logic regenerates all overview bands, not only the
+            // ones requested
+
             papoOverviews[0] = hDstBand;
             nDstOverviews = hDstBand->GetOverviewCount() + 1;
             CPLAssert( nDstOverviews < 128 );
@@ -834,6 +870,8 @@ GTIFFBuildOverviews( const char * pszFilename,
 
     GTIFFSetInExternalOvr(false);
 
+    CPLFree(panOverviewListSorted);
+
     pfnProgress( 1.0, NULL, pProgressData );
 
     return eErr;
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index 1652f78..de45167 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 33722 2016-03-15 15:15:58Z dron $
+ * $Id: hdf4dataset.cpp 35036 2016-08-10 12:11:37Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -42,7 +42,7 @@
 
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 33722 2016-03-15 15:15:58Z dron $");
+CPL_CVSID("$Id: hdf4dataset.cpp 35036 2016-08-10 12:11:37Z rouault $");
 
 extern const char * const pszGDALSignature;
 
@@ -298,39 +298,29 @@ int HDF4Dataset::GetDataTypeSize( int32 iNumType )
 
 double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
 {
+    CPL_STATIC_ASSERT(sizeof(GIntBig) == 8);
     switch ( iNumType )
     {
         case DFNT_INT8:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<char *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<char *>(pData));
         case DFNT_UINT8:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<unsigned char *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GByte *>(pData));
         case DFNT_INT16:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<short *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GInt16 *>(pData));
         case DFNT_UINT16:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<unsigned short *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GUInt16 *>(pData));
         case DFNT_INT32:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<int *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GInt32 *>(pData));
         case DFNT_UINT32:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<unsigned int *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GUInt32 *>(pData));
         case DFNT_INT64:
-            // Highly suspicious! Should be GIntBig. But cannot verify.
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<char *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GIntBig *>(pData));
         case DFNT_UINT64:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<GIntBig *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<GIntBig *>(pData));
         case DFNT_FLOAT32:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<float *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<float *>(pData));
         case DFNT_FLOAT64:
-            return *reinterpret_cast<double *>(
-                reinterpret_cast<double *>( pData ) );
+            return static_cast<double>(*reinterpret_cast<double *>(pData));
         default:
         {
             CPLError( CE_Warning, CPLE_AppDefined,
diff --git a/frmts/hdf5/hdf5imagedataset.cpp b/frmts/hdf5/hdf5imagedataset.cpp
index fa982cd..88de305 100644
--- a/frmts/hdf5/hdf5imagedataset.cpp
+++ b/frmts/hdf5/hdf5imagedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5imagedataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: hdf5imagedataset.cpp 35557 2016-09-30 11:12:06Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read subdatasets of HDF5 file.
@@ -49,7 +49,7 @@
 #include "hdf5dataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hdf5imagedataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
+CPL_CVSID("$Id: hdf5imagedataset.cpp 35557 2016-09-30 11:12:06Z rouault $");
 
 /* release 1.6.3 or 1.6.4 changed the type of count in some api functions */
 
@@ -825,7 +825,7 @@ CPLErr HDF5ImageDataset::CreateProjections()
     /* -------------------------------------------------------------------- */
     /*  Fill the GCPs list.                                                 */
     /* -------------------------------------------------------------------- */
-        nGCPCount = nRasterYSize/nDeltaLat * nRasterXSize/nDeltaLon;
+        nGCPCount = (nRasterYSize/nDeltaLat) * (nRasterXSize/nDeltaLon);
 
         pasGCPList = static_cast<GDAL_GCP *>(
             CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) ) );
@@ -835,12 +835,41 @@ CPLErr HDF5ImageDataset::CreateProjections()
 
         const int nYLimit = (static_cast<int>(nRasterYSize)/nDeltaLat) * nDeltaLat;
         const int nXLimit = (static_cast<int>(nRasterXSize)/nDeltaLon) * nDeltaLon;
+
+        // The original code in https://trac.osgeo.org/gdal/changeset/8066
+        // always add +180 to the longitudes, but without justification
+        // I suspect this might be due to handling products crossing the
+        // antimeridian. Trying to do it just when needed through a heuristics.
+        bool bHasLonNearMinus180 = false;
+        bool bHasLonNearPlus180 = false;
+        bool bHasLonNearZero = false;
+        for( int j = 0; j < nYLimit; j+=nDeltaLat )
+        {
+            for( int i = 0; i < nXLimit; i+=nDeltaLon )
+            {
+                const int iGCP =  j * nRasterXSize + i;
+                if( Longitude[iGCP] > 170 && Longitude[iGCP] <= 180 )
+                    bHasLonNearPlus180 = true;
+                if( Longitude[iGCP] < -170 && Longitude[iGCP] >= -180 )
+                    bHasLonNearMinus180 = true;
+                if( fabs(Longitude[iGCP]) < 90 )
+                    bHasLonNearZero = true;
+            }
+        }
+        const char* pszShiftGCP =
+                CPLGetConfigOption("HDF5_SHIFT_GCPX_BY_180", NULL);
+        const bool bAdd180 = (bHasLonNearPlus180 && bHasLonNearMinus180 &&
+                              !bHasLonNearZero && pszShiftGCP == NULL) ||
+                             (pszShiftGCP != NULL && CPLTestBool(pszShiftGCP));
+
         for( int j = 0; j < nYLimit; j+=nDeltaLat )
         {
             for( int i = 0; i < nXLimit; i+=nDeltaLon )
             {
                 const int iGCP =  j * nRasterXSize + i;
-                pasGCPList[k].dfGCPX = static_cast<double>(Longitude[iGCP])+180.0;
+                pasGCPList[k].dfGCPX = static_cast<double>(Longitude[iGCP]);
+                if( bAdd180 )
+                    pasGCPList[k].dfGCPX += 180.0;
                 pasGCPList[k].dfGCPY = static_cast<double>(Latitude[iGCP]);
 
                 pasGCPList[k].dfGCPPixel = i + 0.5;
diff --git a/frmts/mbtiles/mbtilesdataset.cpp b/frmts/mbtiles/mbtilesdataset.cpp
index 51d7335..9ad9088 100644
--- a/frmts/mbtiles/mbtilesdataset.cpp
+++ b/frmts/mbtiles/mbtilesdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: mbtilesdataset.cpp 34004 2016-04-18 15:35:13Z rouault $
+ * $Id: mbtilesdataset.cpp 35569 2016-09-30 19:39:05Z rouault $
  *
  * Project:  GDAL MBTiles driver
  * Purpose:  Implement GDAL MBTiles support using OGR SQLite driver
@@ -39,7 +39,7 @@
 
 #include <math.h>
 
-CPL_CVSID("$Id: mbtilesdataset.cpp 34004 2016-04-18 15:35:13Z rouault $");
+CPL_CVSID("$Id: mbtilesdataset.cpp 35569 2016-09-30 19:39:05Z rouault $");
 
 static const char * const apszAllowedDrivers[] = {"JPEG", "PNG", NULL};
 
@@ -169,8 +169,8 @@ class MBTilesDataset : public GDALPamDataset, public GDALGPKGMBTilesLikePseudoDa
         virtual sqlite3                *IGetDB() { return hDB; }
         virtual bool                    IGetUpdate() { return eAccess == GA_Update; }
         virtual bool                    ICanIWriteBlock();
-        virtual void                    IStartTransaction();
-        virtual void                    ICommitTransaction();
+        virtual OGRErr                  IStartTransaction();
+        virtual OGRErr                  ICommitTransaction();
         virtual const char             *IGetFilename() { return GetDescription(); }
         virtual int                     GetRowFromIntoTopConvention(int nRow);
 
@@ -793,18 +793,40 @@ MBTilesDataset::~MBTilesDataset()
 /*                         IStartTransaction()                          */
 /************************************************************************/
 
-void MBTilesDataset::IStartTransaction()
+OGRErr MBTilesDataset::IStartTransaction()
 {
-    sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );
+    char *pszErrMsg = NULL;
+    const int rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s transaction failed: %s",
+                  "BEGIN", pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
 /*                         ICommitTransaction()                         */
 /************************************************************************/
 
-void MBTilesDataset::ICommitTransaction()
+OGRErr MBTilesDataset::ICommitTransaction()
 {
-    sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
+    char *pszErrMsg = NULL;
+    const int rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    if( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s transaction failed: %s",
+                  "COMMIT", pszErrMsg );
+        sqlite3_free( pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index 8068530..ab4fdc2 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,6 +1,6 @@
 
 /******************************************************************************
- * $Id: netcdfdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: netcdfdataset.cpp 35360 2016-09-08 00:35:56Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -40,7 +40,7 @@
 #include <map> //for NCDFWriteProjAttribs()
 #include <limits>
 
-CPL_CVSID("$Id: netcdfdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
+CPL_CVSID("$Id: netcdfdataset.cpp 35360 2016-09-08 00:35:56Z rouault $");
 
 /* Internal function declarations */
 
@@ -8212,6 +8212,14 @@ static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
         CPLCalloc( nVarValueSize, sizeof( char ) ) );
     *pszVarValue = '\0';
 
+    if ( nVarLen == 0 )
+    {
+        /* set return values */
+        *pszValue = pszVarValue;
+
+        return CE_None;
+    }
+
     if ( nVarLen > 1 && nVarType != NC_CHAR )
         NCDFSafeStrcat(&pszVarValue, "{", &nVarValueSize);
 
diff --git a/frmts/raw/btdataset.cpp b/frmts/raw/btdataset.cpp
index b69cb5c..c7fb2e8 100644
--- a/frmts/raw/btdataset.cpp
+++ b/frmts/raw/btdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: btdataset.cpp 33927 2016-04-09 19:13:34Z goatbar $
+ * $Id: btdataset.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  VTP .bt Driver
  * Purpose:  Implementation of VTP .bt elevation format read/write support.
@@ -33,7 +33,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: btdataset.cpp 33927 2016-04-09 19:13:34Z goatbar $");
+CPL_CVSID("$Id: btdataset.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/frmts/raw/envidataset.cpp b/frmts/raw/envidataset.cpp
index 4e3f50b..331635f 100644
--- a/frmts/raw/envidataset.cpp
+++ b/frmts/raw/envidataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envidataset.cpp 33934 2016-04-09 20:36:08Z goatbar $
+ * $Id: envidataset.cpp 35524 2016-09-27 13:21:23Z rouault $
  *
  * Project:  ENVI .hdr Driver
  * Purpose:  Implementation of ENVI .hdr labelled raw raster support.
@@ -35,7 +35,7 @@
 #include "rawdataset.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: envidataset.cpp 33934 2016-04-09 20:36:08Z goatbar $");
+CPL_CVSID("$Id: envidataset.cpp 35524 2016-09-27 13:21:23Z rouault $");
 
 static const int anUsgsEsriZones[] =
 {
@@ -232,6 +232,7 @@ class ENVIDataset : public RawDataset
 
     bool        bFoundMapinfo;
     bool        bHeaderDirty;
+    bool        bFillFile;
 
     double      adfGeoTransform[6];
 
@@ -256,6 +257,8 @@ class ENVIDataset : public RawDataset
     int         WriteRpcInfo();
     int         WritePseudoGcpInfo();
 
+    void        SetFillFile() { bFillFile = true; }
+
     char        **SplitList( const char * );
 
     enum Interleave { BSQ, BIL, BIP } interleave;
@@ -319,6 +322,7 @@ ENVIDataset::ENVIDataset() :
     pszHDRFilename(NULL),
     bFoundMapinfo(false),
     bHeaderDirty(false),
+    bFillFile(false),
     pszProjection(CPLStrdup("")),
     papszHeader(NULL),
     interleave(BSQ)
@@ -341,6 +345,28 @@ ENVIDataset::~ENVIDataset()
     FlushCache();
     if( fpImage )
     {
+        // Make sure the binary file has the expected size
+        if( bFillFile && nBands > 0)
+        {
+            const int nDataSize =
+                GDALGetDataTypeSizeBytes(GetRasterBand(1)->GetRasterDataType());
+            vsi_l_offset nExpectedFileSize =
+                static_cast<vsi_l_offset>(nRasterXSize) *
+                nRasterYSize * nBands * nDataSize;
+            if( VSIFSeekL( fpImage, 0, SEEK_END ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            }
+            if( VSIFTellL(fpImage) < nExpectedFileSize)
+            {
+                GByte byVal = 0;
+                if( VSIFSeekL( fpImage, nExpectedFileSize - 1, SEEK_SET ) != 0 ||
+                    VSIFWriteL( &byVal, 1, 1, fpImage ) == 0 )
+                {
+                    CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+                }
+            }
+        }
         if( VSIFCloseL( fpImage ) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "I/O error");
@@ -2795,8 +2821,13 @@ GDALDataset *ENVIDataset::Create( const char * pszFilename,
     if( !bRet )
         return NULL;
 
-    return reinterpret_cast<GDALDataset *>(
-        GDALOpen( pszFilename, GA_Update ) );
+    GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
+    ENVIDataset* poDS = reinterpret_cast<ENVIDataset*>(Open( &oOpenInfo ));
+    if( poDS )
+    {
+        poDS->SetFillFile();
+    }
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/raw/iscedataset.cpp b/frmts/raw/iscedataset.cpp
index fdb8647..5732fa1 100644
--- a/frmts/raw/iscedataset.cpp
+++ b/frmts/raw/iscedataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: iscedataset.cpp 34431 2016-06-25 15:07:10Z rouault $
+ * $Id: iscedataset.cpp 35256 2016-08-30 13:48:26Z rouault $
  *
  * Project:  ISCE Raster Reader
  * Purpose:  Implementation of the ISCE raster reader
@@ -30,7 +30,7 @@
 #include "gdal_frmts.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: iscedataset.cpp 34431 2016-06-25 15:07:10Z rouault $");
+CPL_CVSID("$Id: iscedataset.cpp 35256 2016-08-30 13:48:26Z rouault $");
 
 static const char * const apszISCE2GDALDatatypes[] = {
     "BYTE:Byte",
@@ -261,12 +261,12 @@ void ISCEDataset::FlushCache( void )
 
         /* Don't write it out if it is one of the bits of metadata that is
          * written out elsewhere in this routine */
-        if ( strcmp( papszTokens[0], "WIDTH" ) == 0
-              || strcmp( papszTokens[0], "LENGTH" ) == 0
-              || strcmp( papszTokens[0], "NUMBER_BANDS" ) == 0
-              || strcmp( papszTokens[0], "DATA_TYPE" ) == 0
-              || strcmp( papszTokens[0], "SCHEME" ) == 0
-              || strcmp( papszTokens[0], "BYTE_ORDER" ) == 0 )
+        if ( EQUAL( papszTokens[0], "WIDTH" )
+              || EQUAL( papszTokens[0], "LENGTH" )
+              || EQUAL( papszTokens[0], "NUMBER_BANDS" )
+              || EQUAL( papszTokens[0], "DATA_TYPE" )
+              || EQUAL( papszTokens[0], "SCHEME" )
+              || EQUAL( papszTokens[0], "BYTE_ORDER" ) )
         {
             CSLDestroy( papszTokens );
             continue;
@@ -362,7 +362,7 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
     char **papszXmlProps = NULL;
     while ( psCur != NULL ) {
         const char *name, *value;
-        if ( strcmp(psCur->pszValue, "property") != 0) {
+        if ( ! EQUAL(psCur->pszValue, "property") ) {
             psCur = psCur->psNext;
             continue;
         }
@@ -519,11 +519,12 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
                                           "=",
                                           CSLT_STRIPLEADSPACES
                                             | CSLT_STRIPENDSPACES);
-        if ( strcmp( papszTokens[0], "WIDTH" ) == 0
-              || strcmp( papszTokens[0], "LENGTH" ) == 0
-              || strcmp( papszTokens[0], "NUMBER_BANDS" ) == 0
-              || strcmp( papszTokens[0], "DATA_TYPE" ) == 0
-              || strcmp( papszTokens[0], "SCHEME" ) == 0 )
+        if ( EQUAL( papszTokens[0], "WIDTH" )
+              || EQUAL( papszTokens[0], "LENGTH" )
+              || EQUAL( papszTokens[0], "NUMBER_BANDS" )
+              || EQUAL( papszTokens[0], "DATA_TYPE" )
+              || EQUAL( papszTokens[0], "SCHEME" )
+              || EQUAL( papszTokens[0], "BYTE_ORDER" ) )
         {
             CSLDestroy( papszTokens );
             continue;
diff --git a/frmts/raw/roipacdataset.cpp b/frmts/raw/roipacdataset.cpp
index d3496b8..b1d718f 100644
--- a/frmts/raw/roipacdataset.cpp
+++ b/frmts/raw/roipacdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: roipacdataset.cpp 34205 2016-05-10 14:14:49Z rouault $
+ * $Id: roipacdataset.cpp 34639 2016-07-12 08:44:29Z rouault $
  *
  * Project:  ROI_PAC Raster Reader
  * Purpose:  Implementation of the ROI_PAC raster reader
@@ -31,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: roipacdataset.cpp 34205 2016-05-10 14:14:49Z rouault $");
+CPL_CVSID("$Id: roipacdataset.cpp 34639 2016-07-12 08:44:29Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -361,8 +361,25 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     }
     else { /* PIXEL */
         nPixelOffset = GDALGetDataTypeSize(eDataType)/8 * nBands;
-        nLineOffset = nPixelOffset * nWidth * nBands;
+        nLineOffset = nPixelOffset * nWidth;
         nBandOffset = GDALGetDataTypeSize(eDataType)/8;
+
+        if( nBands > 1 )
+        {
+            // GDAL 2.0.[0-3] and 2.1.0  had a value of nLineOffset that was 
+            // equal to the theoretical nLineOffset multiplied by nBands...
+            VSIFSeekL( poDS->fpImage, 0, SEEK_END );
+            const GUIntBig nWrongFileSize = GDALGetDataTypeSizeBytes(eDataType) *
+                                            nWidth * (static_cast<GUIntBig>(nFileLength - 1) * nBands * nBands + nBands);
+            if( VSIFTellL( poDS->fpImage ) == nWrongFileSize )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "This file has been incorrectly generated by an older "
+                         "GDAL version whose line offset computation was erroneous. "
+                         "Taking that into account, but the file should be re-encoded ideally");
+                nLineOffset = nLineOffset * nBands;
+            }
+        }
     }
     poDS->nBands = nBands;
     for (int b = 0; b < nBands; b++)
diff --git a/frmts/rmf/rmfdem.cpp b/frmts/rmf/rmfdem.cpp
index ac788b9..2515360 100644
--- a/frmts/rmf/rmfdem.cpp
+++ b/frmts/rmf/rmfdem.cpp
@@ -159,7 +159,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     break;
                 if ( nSizeOut < nCount )
                     break;
-                nSizeIn -= (nCount + 1) / 2;
+                nSizeIn -= nCount / 2;
                 nSizeOut -= nCount;
                 while ( nCount-- > 0 )
                 {
@@ -206,7 +206,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     break;
                 if ( nSizeOut < nCount )
                     break;
-                nSizeIn -= (3 * nCount + 1) / 2;
+                nSizeIn -= 3 * nCount / 2;
                 nSizeOut -= nCount;
 
                 while ( nCount-- > 0 )
diff --git a/frmts/srtmhgt/srtmhgtdataset.cpp b/frmts/srtmhgt/srtmhgtdataset.cpp
index 8638f38..48f573d 100644
--- a/frmts/srtmhgt/srtmhgtdataset.cpp
+++ b/frmts/srtmhgt/srtmhgtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: srtmhgtdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: srtmhgtdataset.cpp 34884 2016-08-03 16:05:33Z rouault $
  *
  * Project:  SRTM HGT Driver
  * Purpose:  SRTM HGT File Read Support.
@@ -41,7 +41,7 @@
 
 static const GInt16 SRTMHG_NODATA_VALUE = -32768;
 
-CPL_CVSID("$Id: srtmhgtdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: srtmhgtdataset.cpp 34884 2016-08-03 16:05:33Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -264,9 +264,11 @@ int SRTMHGTDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
   const char* fileName = CPLGetFilename(poOpenInfo->pszFilename);
-  if( strlen(fileName) < 11 || !STARTS_WITH_CI(&fileName[7], ".hgt") )
+  if( strlen(fileName) < 11 || fileName[7] != '.' )
+    return FALSE;
+  
+  if( !EQUAL(fileName + strlen(fileName) - strlen(".hgt"), ".hgt") )
     return FALSE;
-
 /* -------------------------------------------------------------------- */
 /*	We check the file size to see if it is 25,934,402 bytes	        */
 /*	(SRTM 1) or 2,884,802 bytes (SRTM 3)				*/
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index fb398d5..2b2df06 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
+ * $Id: vrtdataset.cpp 34730 2016-07-20 09:12:13Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDataset
@@ -35,8 +35,9 @@
 #include "ogr_spatialref.h"
 
 #include <algorithm>
+#include <typeinfo>
 
-CPL_CVSID("$Id: vrtdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: vrtdataset.cpp 34730 2016-07-20 09:12:13Z rouault $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
@@ -1257,6 +1258,10 @@ int VRTDataset::CheckCompatibleForDatasetIO()
         VRTSourcedRasterBand* poBand
             = reinterpret_cast<VRTSourcedRasterBand*>( papoBands[iBand] );
 
+        // Do not allow VRTDerivedRasterBand for example
+        if( typeid(*poBand) != typeid(VRTSourcedRasterBand) )
+            return FALSE;
+
         if (iBand == 0)
         {
             nSources = poBand->nSources;
diff --git a/frmts/vrt/vrtdataset.h b/frmts/vrt/vrtdataset.h
index eea6f28..7bf25a7 100644
--- a/frmts/vrt/vrtdataset.h
+++ b/frmts/vrt/vrtdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.h 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: vrtdataset.h 35350 2016-09-07 07:21:52Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Declaration of virtual gdal dataset classes.
@@ -865,12 +865,14 @@ protected:
 
     int            m_nColorTableComponent;
 
+    template <class WorkingDT>
     CPLErr          RasterIOInternal( int nReqXOff, int nReqYOff,
                                       int nReqXSize, int nReqYSize,
                                       void *pData, int nOutXSize, int nOutYSize,
                                       GDALDataType eBufType,
                                       GSpacing nPixelSpace, GSpacing nLineSpace,
-                                      GDALRasterIOExtraArg* psExtraArg );
+                                      GDALRasterIOExtraArg* psExtraArg,
+                                      GDALDataType eWrkDataType );
 
 public:
                    VRTComplexSource();
diff --git a/frmts/vrt/vrtfilters.cpp b/frmts/vrt/vrtfilters.cpp
index 266f569..e53bf3d 100644
--- a/frmts/vrt/vrtfilters.cpp
+++ b/frmts/vrt/vrtfilters.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtfilters.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: vrtfilters.cpp 35350 2016-09-07 07:21:52Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of some filter types.
@@ -32,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtfilters.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: vrtfilters.cpp 35350 2016-09-07 07:21:52Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -273,12 +273,14 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Load the data.                                                  */
 /* -------------------------------------------------------------------- */
+    const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eOperDataType) );
     CPLErr eErr
-        = VRTComplexSource::RasterIOInternal(
+        = VRTComplexSource::RasterIOInternal<float>(
             nFileXOff, nFileYOff, nFileXSize, nFileYSize,
             pabyWorkData + nLineOffset * nTopFill + nPixelOffset * nLeftFill,
             nFileXSize, nFileYSize, eOperDataType,
-            nPixelOffset, nLineOffset, psExtraArg );
+            nPixelOffset, nLineOffset, psExtraArg,
+            bIsComplex ? GDT_CFloat32 : GDT_Float32 );
 
     if( eErr != CE_None )
     {
diff --git a/frmts/vrt/vrtsourcedrasterband.cpp b/frmts/vrt/vrtsourcedrasterband.cpp
index d863860..00c9ec2 100644
--- a/frmts/vrt/vrtsourcedrasterband.cpp
+++ b/frmts/vrt/vrtsourcedrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsourcedrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: vrtsourcedrasterband.cpp 35188 2016-08-23 15:02:58Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSourcedRasterBand
@@ -32,7 +32,7 @@
 #include "cpl_minixml.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: vrtsourcedrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: vrtsourcedrasterband.cpp 35188 2016-08-23 15:02:58Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -123,40 +123,6 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                  GDALRasterIOExtraArg* psExtraArg )
 
 {
-    // If resampling with non-nearest neighbour, we need to be careful
-    // if the VRT band exposes a nodata value, but the sources do not have it
-    if (eRWFlag == GF_Read &&
-        (nXSize != nBufXSize || nYSize != nBufYSize) &&
-        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
-        m_bNoDataValueSet )
-    {
-        for( int i = 0; i < nSources; i++ )
-        {
-            bool bFallbackToBase = false;
-            if( !papoSources[i]->IsSimpleSource() )
-                bFallbackToBase = true;
-            else
-            {
-                VRTSimpleSource* poSource
-                    = reinterpret_cast<VRTSimpleSource *>( papoSources[i] );
-                int bSrcHasNoData = FALSE;
-                double dfSrcNoData = poSource->GetBand()->GetNoDataValue(&bSrcHasNoData);
-                if( !bSrcHasNoData || dfSrcNoData != m_dfNoDataValue )
-                    bFallbackToBase = true;
-            }
-            if( bFallbackToBase )
-            {
-                return GDALRasterBand::IRasterIO( eRWFlag,
-                                                nXOff, nYOff, nXSize, nYSize,
-                                                pData, nBufXSize, nBufYSize,
-                                                eBufType,
-                                                nPixelSpace,
-                                                nLineSpace,
-                                                psExtraArg );
-            }
-        }
-    }
-
     if( eRWFlag == GF_Write )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -190,6 +156,67 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             return CE_None;
     }
 
+    // If resampling with non-nearest neighbour, we need to be careful
+    // if the VRT band exposes a nodata value, but the sources do not have it
+    if( eRWFlag == GF_Read &&
+        (nXSize != nBufXSize || nYSize != nBufYSize) &&
+        psExtraArg->eResampleAlg != GRIORA_NearestNeighbour &&
+        m_bNoDataValueSet )
+    {
+        for( int i = 0; i < nSources; i++ )
+        {
+            bool bFallbackToBase = false;
+            if( !papoSources[i]->IsSimpleSource() )
+            {
+                bFallbackToBase = true;
+            }
+            else
+            {
+                VRTSimpleSource* const poSource
+                    = reinterpret_cast<VRTSimpleSource *>( papoSources[i] );
+                // The window we will actually request from the source raster band.
+                double dfReqXOff = 0.0;
+                double dfReqYOff = 0.0;
+                double dfReqXSize = 0.0;
+                double dfReqYSize = 0.0;
+                int nReqXOff = 0;
+                int nReqYOff = 0;
+                int nReqXSize = 0;
+                int nReqYSize = 0;
+
+                // The window we will actual set _within_ the pData buffer.
+                int nOutXOff = 0;
+                int nOutYOff = 0;
+                int nOutXSize = 0;
+                int nOutYSize = 0;
+
+                if( !poSource->GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
+                                      nBufXSize, nBufYSize,
+                                      &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
+                                      &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
+                                      &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
+                {
+                    continue;
+                }
+                int bSrcHasNoData = FALSE;
+                const double dfSrcNoData =
+                    poSource->GetBand()->GetNoDataValue(&bSrcHasNoData);
+                if( !bSrcHasNoData || dfSrcNoData != m_dfNoDataValue )
+                    bFallbackToBase = true;
+            }
+            if( bFallbackToBase )
+            {
+                return GDALRasterBand::IRasterIO( eRWFlag,
+                                                  nXOff, nYOff, nXSize, nYSize,
+                                                  pData, nBufXSize, nBufYSize,
+                                                  eBufType,
+                                                  nPixelSpace,
+                                                  nLineSpace,
+                                                  psExtraArg );
+            }
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Initialize the buffer to some background value. Use the         */
 /*      nodata value if available.                                      */
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index 032a10f..cbc7881 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 34511 2016-07-01 21:50:45Z rouault $
+ * $Id: vrtsources.cpp 35369 2016-09-08 09:33:26Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and
@@ -43,7 +43,7 @@
 #define isnan std::isnan
 #endif
 
-CPL_CVSID("$Id: vrtsources.cpp 34511 2016-07-01 21:50:45Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 35369 2016-09-08 09:33:26Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -2132,13 +2132,34 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
-    CPLErr eErr = RasterIOInternal(nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                       ((GByte *)pData)
-                            + nPixelSpace * nOutXOff
-                            + (GPtrDiff_t)nLineSpace * nOutYOff,
-                       nOutXSize, nOutYSize,
-                       eBufType,
-                       nPixelSpace, nLineSpace, psExtraArg );
+    const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eBufType) );
+    CPLErr eErr;
+    // For Int32, float32 isn't sufficiently precise as working data type
+    if( eBufType == GDT_CInt32 || eBufType == GDT_CFloat64 ||
+        eBufType == GDT_Int32 || eBufType == GDT_UInt32 ||
+        eBufType == GDT_Float64 )
+    {
+        eErr = RasterIOInternal<double>(
+                nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                static_cast<GByte *>(pData) + nPixelSpace * nOutXOff
+                    + static_cast<GPtrDiff_t>(nLineSpace) * nOutYOff,
+                nOutXSize, nOutYSize,
+                eBufType,
+                nPixelSpace, nLineSpace, psExtraArg,
+                bIsComplex ? GDT_CFloat64 : GDT_Float64);
+    }
+    else
+    {
+        eErr = RasterIOInternal<float>(
+                nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                static_cast<GByte *>(pData) + nPixelSpace * nOutXOff
+                    + static_cast<GPtrDiff_t>(nLineSpace) * nOutYOff,
+                nOutXSize, nOutYSize,
+                eBufType,
+                nPixelSpace, nLineSpace, psExtraArg,
+                bIsComplex ? GDT_CFloat32 : GDT_Float32);
+    }
+
 
     return eErr;
 }
@@ -2147,55 +2168,67 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*                          RasterIOInternal()                          */
 /************************************************************************/
 
-/* nReqXOff, nReqYOff, nReqXSize, nReqYSize are expressed in source band */
-/* referential */
+// nReqXOff, nReqYOff, nReqXSize, nReqYSize are expressed in source band
+// referential.
+template <class WorkingDT>
 CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
-                                      int nReqXSize, int nReqYSize,
-                                      void *pData, int nOutXSize, int nOutYSize,
-                                      GDALDataType eBufType,
-                                      GSpacing nPixelSpace,
-                                      GSpacing nLineSpace,
-                                      GDALRasterIOExtraArg* psExtraArg )
+                                           int nReqXSize, int nReqYSize,
+                                           void *pData,
+                                           int nOutXSize, int nOutYSize,
+                                           GDALDataType eBufType,
+                                           GSpacing nPixelSpace,
+                                           GSpacing nLineSpace,
+                                           GDALRasterIOExtraArg* psExtraArg,
+                                           GDALDataType eWrkDataType )
 {
 /* -------------------------------------------------------------------- */
 /*      Read into a temporary buffer.                                   */
 /* -------------------------------------------------------------------- */
-    float *pafData;
-    CPLErr eErr;
     GDALColorTable* poColorTable = NULL;
-    const int bIsComplex = GDALDataTypeIsComplex(eBufType);
-    const GDALDataType eWrkDataType = (bIsComplex) ? GDT_CFloat32 : GDT_Float32;
-    const int nWordSize = GDALGetDataTypeSize(eWrkDataType) / 8;
-    const int bNoDataSetIsNan = m_bNoDataSet && CPLIsNan(m_dfNoDataValue);
-    const int bNoDataSetAndNotNan = m_bNoDataSet && !CPLIsNan(m_dfNoDataValue);
+    const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eBufType) );
+    const int nWordSize = GDALGetDataTypeSizeBytes(eWrkDataType);
+    const bool bNoDataSetIsNan = m_bNoDataSet && CPLIsNan(m_dfNoDataValue);
+    const bool bNoDataSetAndNotNan = m_bNoDataSet && !CPLIsNan(m_dfNoDataValue);
 
+    WorkingDT *pafData = NULL;
     if( m_eScalingType == VRT_SCALING_LINEAR &&
-        m_bNoDataSet == FALSE && m_dfScaleRatio == 0)
+        m_bNoDataSet == FALSE &&
+        m_dfScaleRatio == 0 )
     {
 /* -------------------------------------------------------------------- */
 /*      Optimization when writing a constant value                      */
 /*      (used by the -addalpha option of gdalbuildvrt)                  */
 /* -------------------------------------------------------------------- */
-        pafData = NULL;
+        // Already set to NULL when defined.
+        // pafData = NULL;
     }
     else
     {
-        pafData = (float *) VSI_MALLOC3_VERBOSE(nOutXSize,nOutYSize,nWordSize);
-        if (pafData == NULL)
+        pafData = static_cast<WorkingDT *>(
+            VSI_MALLOC3_VERBOSE(nOutXSize,nOutYSize,nWordSize) );
+        if( pafData == NULL )
         {
             return CE_Failure;
         }
 
-        GDALRIOResampleAlg     eResampleAlgBack = psExtraArg->eResampleAlg;
+        const GDALRIOResampleAlg eResampleAlgBack = psExtraArg->eResampleAlg;
         if( m_osResampling.size() )
         {
-            psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
+            psExtraArg->eResampleAlg =
+                GDALRasterIOGetResampleAlg(m_osResampling);
         }
 
-        eErr = m_poRasterBand->RasterIO( GF_Read,
-                                       nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                                       pafData, nOutXSize, nOutYSize, eWrkDataType,
-                                       nWordSize, nWordSize * (GSpacing)nOutXSize, psExtraArg );
+        const CPLErr eErr =
+            m_poRasterBand->RasterIO( GF_Read,
+                                      nReqXOff, nReqYOff,
+                                      nReqXSize, nReqYSize,
+                                      pafData,
+                                      nOutXSize, nOutYSize,
+                                      eWrkDataType,
+                                      nWordSize,
+                                      nWordSize *
+                                      static_cast<GSpacing>(nOutXSize),
+                                      psExtraArg );
         if( m_osResampling.size() )
             psExtraArg->eResampleAlg = eResampleAlgBack;
 
@@ -2205,13 +2238,13 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
             return eErr;
         }
 
-        if (m_nColorTableComponent != 0)
+        if( m_nColorTableComponent != 0 )
         {
             poColorTable = m_poRasterBand->GetColorTable();
-            if (poColorTable == NULL)
+            if( poColorTable == NULL )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Source band has no color table.");
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Source band has no color table." );
                 CPLFree( pafData );
                 return CE_Failure;
             }
@@ -2222,65 +2255,71 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
 /*      Selectively copy into output buffer with nodata masking,        */
 /*      and/or scaling.                                                 */
 /* -------------------------------------------------------------------- */
-    int iX, iY;
-
-    for( iY = 0; iY < nOutYSize; iY++ )
+    for( int iY = 0; iY < nOutYSize; iY++ )
     {
-        for( iX = 0; iX < nOutXSize; iX++ )
+        for( int iX = 0; iX < nOutXSize; iX++ )
         {
-            GByte *pDstLocation;
-
-            pDstLocation = ((GByte *)pData)
+            GByte *pDstLocation =
+                static_cast<GByte *>(pData)
                 + nPixelSpace * iX
-                + (GPtrDiff_t)nLineSpace * iY;
+                + static_cast<GPtrDiff_t>(nLineSpace) * iY;
 
-            if (pafData && !bIsComplex)
+            if( pafData && !bIsComplex )
             {
-                float fResult = pafData[iX + iY * nOutXSize];
+                WorkingDT fResult = pafData[iX + iY * nOutXSize];
                 if( bNoDataSetIsNan && CPLIsNan(fResult) )
                     continue;
-                if( bNoDataSetAndNotNan && ARE_REAL_EQUAL(fResult, m_dfNoDataValue) )
+                if( bNoDataSetAndNotNan &&
+                    ARE_REAL_EQUAL(fResult, m_dfNoDataValue) )
                     continue;
 
-                if (m_nColorTableComponent)
+                if( m_nColorTableComponent )
                 {
-                    const GDALColorEntry* poEntry = poColorTable->GetColorEntry((int)fResult);
-                    if (poEntry)
+                    const GDALColorEntry* poEntry =
+                        poColorTable->GetColorEntry(static_cast<int>(fResult));
+                    if( poEntry )
                     {
-                        if (m_nColorTableComponent == 1)
+                        if( m_nColorTableComponent == 1 )
                             fResult = poEntry->c1;
-                        else if (m_nColorTableComponent == 2)
+                        else if( m_nColorTableComponent == 2 )
                             fResult = poEntry->c2;
-                        else if (m_nColorTableComponent == 3)
+                        else if( m_nColorTableComponent == 3 )
                             fResult = poEntry->c3;
-                        else if (m_nColorTableComponent == 4)
+                        else if( m_nColorTableComponent == 4 )
                             fResult = poEntry->c4;
                     }
                     else
                     {
-                        static int bHasWarned = FALSE;
-                        if (!bHasWarned)
+                        static bool bHasWarned = false;
+                        if( !bHasWarned )
                         {
-                            bHasWarned = TRUE;
-                            CPLError(CE_Failure, CPLE_AppDefined,
-                                    "No entry %d.", (int)fResult);
+                            bHasWarned = true;
+                            CPLError(
+                                CE_Failure, CPLE_AppDefined,
+                                "No entry %d.", static_cast<int>(fResult) );
                         }
                         continue;
                     }
                 }
 
                 if( m_eScalingType == VRT_SCALING_LINEAR )
-                    fResult = (float) (fResult * m_dfScaleRatio + m_dfScaleOff);
+                {
+                    fResult = static_cast<WorkingDT>(
+                        fResult * m_dfScaleRatio + m_dfScaleOff );
+                }
                 else if( m_eScalingType == VRT_SCALING_EXPONENTIAL )
                 {
                     if( !m_bSrcMinMaxDefined )
                     {
-                        int bSuccessMin = FALSE, bSuccessMax = FALSE;
-                        double adfMinMax[2];
-                        adfMinMax[0] = m_poRasterBand->GetMinimum(&bSuccessMin);
-                        adfMinMax[1] = m_poRasterBand->GetMaximum(&bSuccessMax);
+                        int bSuccessMin = FALSE;
+                        int bSuccessMax = FALSE;
+                        double adfMinMax[2] = {
+                            m_poRasterBand->GetMinimum(&bSuccessMin),
+                            m_poRasterBand->GetMaximum(&bSuccessMax) };
                         if( (bSuccessMin && bSuccessMax) ||
-                            m_poRasterBand->ComputeRasterMinMax( TRUE, adfMinMax ) == CE_None )
+                            m_poRasterBand->ComputeRasterMinMax( TRUE,
+                                                                 adfMinMax )
+                            == CE_None )
                         {
                             m_dfSrcMin = adfMinMax[0];
                             m_dfSrcMax = adfMinMax[1];
@@ -2288,8 +2327,9 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                         }
                         else
                         {
-                            CPLError(CE_Failure, CPLE_AppDefined,
-                                    "Cannot determine source min/max value");
+                            CPLError(
+                                CE_Failure, CPLE_AppDefined,
+                                "Cannot determine source min/max value" );
                             return CE_Failure;
                         }
                     }
@@ -2300,58 +2340,64 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                         dfPowVal = 0.0;
                     else if( dfPowVal > 1.0 )
                         dfPowVal = 1.0;
-                    fResult = static_cast<float>((m_dfDstMax - m_dfDstMin) * pow( dfPowVal, m_dfExponent ) + m_dfDstMin);
+                    fResult = static_cast<WorkingDT>(
+                        (m_dfDstMax - m_dfDstMin) *
+                        pow( dfPowVal, m_dfExponent ) +
+                        m_dfDstMin);
                 }
 
-                if (m_nLUTItemCount)
-                    fResult = static_cast<float>(LookupValue( fResult ));
+                if( m_nLUTItemCount )
+                    fResult = static_cast<WorkingDT>(LookupValue( fResult ));
 
                 if( m_nMaxValue != 0 && fResult > m_nMaxValue )
-                    fResult = static_cast<float>(m_nMaxValue);
+                    fResult = static_cast<WorkingDT>(m_nMaxValue);
 
                 if( eBufType == GDT_Byte )
                     *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
                 else
-                    GDALCopyWords( &fResult, GDT_Float32, 0,
+                    GDALCopyWords( &fResult, eWrkDataType, 0,
                                 pDstLocation, eBufType, 0, 1 );
             }
-            else if (pafData && bIsComplex)
+            else if( pafData && bIsComplex )
             {
-                float afResult[2];
-                afResult[0] = pafData[2 * (iX + iY * nOutXSize)];
-                afResult[1] = pafData[2 * (iX + iY * nOutXSize) + 1];
-
-                /* Do not use color table */
+                WorkingDT afResult[2] = {
+                    pafData[2 * (iX + iY * nOutXSize)],
+                    pafData[2 * (iX + iY * nOutXSize) + 1] };
 
+                // Do not use color table.
                 if( m_eScalingType == VRT_SCALING_LINEAR )
                 {
-                    afResult[0] = (float) (afResult[0] * m_dfScaleRatio + m_dfScaleOff);
-                    afResult[1] = (float) (afResult[1] * m_dfScaleRatio + m_dfScaleOff);
+                    afResult[0] = static_cast<WorkingDT>(
+                        afResult[0] * m_dfScaleRatio + m_dfScaleOff );
+                    afResult[1] = static_cast<WorkingDT>(
+                        afResult[1] * m_dfScaleRatio + m_dfScaleOff );
                 }
 
                 /* Do not use LUT */
 
                 if( eBufType == GDT_Byte )
-                    *pDstLocation = (GByte) MIN(255,MAX(0,afResult[0] + 0.5));
+                    *pDstLocation = static_cast<GByte>(
+                        MIN(255,MAX(0,afResult[0] + 0.5) ) );
                 else
-                    GDALCopyWords( afResult, GDT_CFloat32, 0,
+                    GDALCopyWords( afResult, eWrkDataType, 0,
                                    pDstLocation, eBufType, 0, 1 );
             }
             else
             {
-                float fResult = static_cast<float>(m_dfScaleOff);
+                WorkingDT fResult = static_cast<WorkingDT>(m_dfScaleOff);
 
-                if (m_nLUTItemCount)
-                    fResult = static_cast<float>(LookupValue( fResult ));
+                if( m_nLUTItemCount )
+                    fResult = static_cast<WorkingDT>(LookupValue( fResult ));
 
                 if( m_nMaxValue != 0 && fResult > m_nMaxValue )
-                    fResult = static_cast<float>(m_nMaxValue);
+                    fResult = static_cast<WorkingDT>(m_nMaxValue);
 
                 if( eBufType == GDT_Byte )
-                    *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
+                    *pDstLocation = static_cast<GByte>(
+                        MIN(255,MAX(0,fResult + 0.5)) );
                 else
-                    GDALCopyWords( &fResult, GDT_Float32, 0,
-                                pDstLocation, eBufType, 0, 1 );
+                    GDALCopyWords( &fResult, eWrkDataType, 0,
+                                   pDstLocation, eBufType, 0, 1 );
             }
 
         }
diff --git a/gcore/gdal_priv.h b/gcore/gdal_priv.h
index 76ba9a6..ecf6be4 100644
--- a/gcore/gdal_priv.h
+++ b/gcore/gdal_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_priv.h 33808 2016-03-29 21:15:28Z goatbar $
+ * $Id: gdal_priv.h 35549 2016-09-29 22:56:53Z rouault $
  *
  * Name:     gdal_priv.h
  * Project:  GDAL Core
@@ -404,6 +404,7 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     // should not be used by out-of-tree code if possible.
     int                 EnterReadWrite(GDALRWFlag eRWFlag);
     void                LeaveReadWrite();
+    void                InitRWLock();
 
     void                TemporarilyDropReadWriteLock();
     void                ReacquireReadWriteLock();
@@ -782,6 +783,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     int          EnterReadWrite(GDALRWFlag eRWFlag);
     void         LeaveReadWrite();
+    void         InitRWLock();
 
   protected:
     virtual CPLErr IReadBlock( int, int, void * ) = 0;
@@ -1344,7 +1346,12 @@ int CPL_DLL GDALCheckBandCount( int nBands, int bIsZeroAllowed );
 // Test if 2 floating point values match. Useful when comparing values
 // stored as a string at some point. See #3573, #4183, #4506
 #define ARE_REAL_EQUAL(dfVal1, dfVal2) \
- (dfVal1 == dfVal2 || fabs(dfVal1 - dfVal2) < 1e-10 || (dfVal2 != 0 && fabs(1 - dfVal1 / dfVal2) < 1e-10 ))
+ /* Is it FLT_MIN ? Cf #6578 */ \
+ (((float)dfVal2 == (float)1.17549435e-38) ? ((float)dfVal1 == (float)dfVal2) : \
+ /* Or DBL_MIN ? */ \
+  (dfVal2 == 2.2250738585072014e-308) ? (dfVal1 == dfVal2) : \
+ /* General case */ \
+  (dfVal1 == dfVal2 || fabs(dfVal1 - dfVal2) < 1e-10 || (dfVal2 != 0 && fabs(1 - dfVal1 / dfVal2) < 1e-10 )))
 
 /* Internal use only */
 
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index 367af46..f10ac50 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -6,7 +6,7 @@
 #ifndef GDAL_VERSION_MAJOR
 #  define GDAL_VERSION_MAJOR    2
 #  define GDAL_VERSION_MINOR    1
-#  define GDAL_VERSION_REV      1
+#  define GDAL_VERSION_REV      2
 #  define GDAL_VERSION_BUILD    0
 #endif
 
@@ -22,8 +22,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20160707
+#  define GDAL_RELEASE_DATE     20161014
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "2.1.1"
+#  define GDAL_RELEASE_NAME     "2.1.2"
 #endif
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index 2dc9275..a71cb37 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 34092 2016-04-25 09:09:46Z rouault $
+ * $Id: gdaldataset.cpp 35553 2016-09-29 23:19:16Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for raster file formats.
@@ -46,8 +46,9 @@
 #endif
 
 #include <map>
+#include <new>
 
-CPL_CVSID("$Id: gdaldataset.cpp 34092 2016-04-25 09:09:46Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 35553 2016-09-29 23:19:16Z rouault $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -69,12 +70,18 @@ typedef enum
     RW_MUTEX_STATE_DISABLED
 } GDALAllowReadWriteMutexState;
 
-typedef struct
+class GDALDatasetPrivate
 {
-    CPLMutex* hMutex;
-    int       nMutexTakenCount;
-    GDALAllowReadWriteMutexState eStateReadWriteMutex;
-} GDALDatasetPrivate;
+    public:
+        CPLMutex* hMutex;
+        std::map<GIntBig, int> oMapThreadToMutexTakenCount;
+        GDALAllowReadWriteMutexState eStateReadWriteMutex;
+
+        GDALDatasetPrivate() :
+            hMutex(NULL),
+            eStateReadWriteMutex(RW_MUTEX_STATE_UNKNOWN) {}
+
+};
 
 typedef struct
 {
@@ -215,9 +222,7 @@ void GDALDataset::Init(int bForceCachedIOIn)
     bForceCachedIO = (GByte)bForceCachedIOIn;
 
     m_poStyleTable = NULL;
-    m_hPrivateData = VSI_CALLOC_VERBOSE(1, sizeof(GDALDatasetPrivate));
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_UNKNOWN;
+    m_hPrivateData = new (std::nothrow) GDALDatasetPrivate;
 }
 
 /************************************************************************/
@@ -325,7 +330,7 @@ GDALDataset::~GDALDataset()
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
     if( psPrivate != NULL && psPrivate->hMutex != NULL )
         CPLDestroyMutex( psPrivate->hMutex );
-    CPLFree(psPrivate);
+    delete psPrivate;
 
     CSLDestroy( papszOpenOptions );
 }
@@ -6096,11 +6101,15 @@ int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
             // There should be no race related to creating this mutex since
             // it should be first created through IWriteBlock() / IRasterIO()
             // and then GDALRasterBlock might call it from another thread
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
+                     CPLGetPID(), GetDescription());
+#endif
             if( psPrivate->hMutex == NULL )
                 psPrivate->hMutex = CPLCreateMutex();
             else
                 CPLAcquireMutex(psPrivate->hMutex, 1000.0);
-            psPrivate->nMutexTakenCount ++; /* not sure if we can have recursive calls, so ...*/
+            psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ] ++; /* not sure if we can have recursive calls, so ...*/
             return TRUE;
         }
     }
@@ -6116,8 +6125,29 @@ void GDALDataset::LeaveReadWrite()
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
     if( psPrivate )
     {
-        psPrivate->nMutexTakenCount --;
+        psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ] --;
         CPLReleaseMutex(psPrivate->hMutex);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
+                     CPLGetPID(), GetDescription());
+#endif
+    }
+}
+
+/************************************************************************/
+/*                           InitRWLock()                               */
+/************************************************************************/
+
+void GDALDataset::InitRWLock()
+{
+    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    if( psPrivate )
+    {
+        if( psPrivate->eStateReadWriteMutex == RW_MUTEX_STATE_UNKNOWN )
+        {
+            if( EnterReadWrite(GF_Write) )
+                LeaveReadWrite();
+        }
     }
 }
 
@@ -6145,10 +6175,18 @@ void GDALDataset::DisableReadWriteMutex()
 void GDALDataset::TemporarilyDropReadWriteLock()
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    if( psPrivate )
+    if( psPrivate && psPrivate->hMutex )
     {
-        for(int i=0;i<psPrivate->nMutexTakenCount;i++)
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] "
+                 "Temporarily drop RW mutex for %s",
+                 CPLGetPID(), GetDescription());
+#endif
+        const int nCount = psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ];
+        for(int i=0;i<nCount;i++)
+        {
             CPLReleaseMutex(psPrivate->hMutex);
+        }
     }
 }
 
@@ -6159,10 +6197,18 @@ void GDALDataset::TemporarilyDropReadWriteLock()
 void GDALDataset::ReacquireReadWriteLock()
 {
     GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    if( psPrivate )
+    if( psPrivate && psPrivate->hMutex )
     {
-        for(int i=0;i<psPrivate->nMutexTakenCount;i++)
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] "
+                 "Reacquire temporarily dropped RW mutex for %s",
+                 CPLGetPID(), GetDescription());
+#endif
+        const int nCount = psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ];
+        for(int i=0;i<nCount;i++)
+        {
             CPLAcquireMutex(psPrivate->hMutex, 1000.0);
+        }
     }
 }
 
diff --git a/gcore/gdaldrivermanager.cpp b/gcore/gdaldrivermanager.cpp
index b9ff7b3..66fd3e4 100644
--- a/gcore/gdaldrivermanager.cpp
+++ b/gcore/gdaldrivermanager.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaldrivermanager.cpp 33711 2016-03-12 06:29:35Z goatbar $
+ * $Id: gdaldrivermanager.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriverManager class.
@@ -42,7 +42,7 @@
 #  endif
 #endif
 
-CPL_CVSID("$Id: gdaldrivermanager.cpp 33711 2016-03-12 06:29:35Z goatbar $");
+CPL_CVSID("$Id: gdaldrivermanager.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -551,6 +551,10 @@ GDALDriver * GDALDriverManager::GetDriverByName( const char * pszName )
 {
     CPLMutexHolderD( &hDMMutex );
 
+    // Alias old name to new name
+    if( EQUAL(pszName, "CartoDB") )
+        pszName = "Carto";
+
     return oMapNameToDrivers[CPLString(pszName).toupper()];
 }
 
diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp
index f13e8fa..b8f7c3f 100644
--- a/gcore/gdalrasterband.cpp
+++ b/gcore/gdalrasterband.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $
+ * $Id: gdalrasterband.cpp 35549 2016-09-29 22:56:53Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for format specific band class implementation.  This
@@ -33,7 +33,7 @@
 #include "gdal_rat.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdalrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: gdalrasterband.cpp 35549 2016-09-29 22:56:53Z rouault $");
 
 /************************************************************************/
 /*                           GDALRasterBand()                           */
@@ -1140,21 +1140,24 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
             return( NULL );
         }
 
-        if( !bJustInitialize
-         && IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef()) != CE_None)
-        {
-            poBlock->DropLock();
-            FlushBlock( nXBlockOff, nYBlockOff );
-            ReportError( CE_Failure, CPLE_AppDefined,
-                "IReadBlock failed at X offset %d, Y offset %d",
-                nXBlockOff, nYBlockOff );
-            return( NULL );
-        }
-
         if( !bJustInitialize )
         {
+            int bCallLeaveReadWrite = EnterReadWrite(GF_Read);
+            eErr = IReadBlock(nXBlockOff,nYBlockOff,poBlock->GetDataRef());
+            if( bCallLeaveReadWrite) LeaveReadWrite();
+            if( eErr != CE_None )
+            {
+                poBlock->DropLock();
+                FlushBlock( nXBlockOff, nYBlockOff );
+                ReportError( CE_Failure, CPLE_AppDefined,
+                    "IReadBlock failed at X offset %d, Y offset %d",
+                    nXBlockOff, nYBlockOff );
+                return NULL;
+            }
+
             nBlockReads++;
-            if( static_cast<GIntBig>(nBlockReads) == static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn + 1
+            if( static_cast<GIntBig>(nBlockReads) ==
+                static_cast<GIntBig>(nBlocksPerRow) * nBlocksPerColumn + 1
                 && nBand == 1 && poDS != NULL )
             {
                 CPLDebug( "GDAL", "Potential thrashing on band %d of %s.",
@@ -5300,3 +5303,13 @@ void GDALRasterBand::LeaveReadWrite()
     if( poDS != NULL )
         poDS->LeaveReadWrite();
 }
+
+/************************************************************************/
+/*                           InitRWLock()                               */
+/************************************************************************/
+
+void GDALRasterBand::InitRWLock()
+{
+    if( poDS != NULL )
+        poDS->InitRWLock();
+}
diff --git a/gcore/gdalrasterblock.cpp b/gcore/gdalrasterblock.cpp
index ced14d7..c3001e4 100644
--- a/gcore/gdalrasterblock.cpp
+++ b/gcore/gdalrasterblock.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalrasterblock.cpp 33694 2016-03-10 17:54:30Z goatbar $
+ * $Id: gdalrasterblock.cpp 35549 2016-09-29 22:56:53Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterBlock class and related global
@@ -32,7 +32,7 @@
 #include "gdal_priv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: gdalrasterblock.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+CPL_CVSID("$Id: gdalrasterblock.cpp 35549 2016-09-29 22:56:53Z rouault $");
 
 static bool bCacheMaxInitialized = false;
 static GIntBig nCacheMax = 40 * 1024*1024; /* Will later be overridden by the default 5% if GDAL_CACHEMAX not defined */
@@ -138,6 +138,9 @@ void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
     }
 #endif
 
+    {
+        INITIALIZE_LOCK;
+    }   
     bCacheMaxInitialized = true;
     nCacheMax = nNewSizeInBytes;
 
@@ -966,9 +969,10 @@ CPLErr GDALRasterBlock::Internalize()
  */
 
 void GDALRasterBlock::MarkDirty()
-
 {
-    bDirty = TRUE;
+    bDirty = true;
+    if( poBand )
+        poBand->InitRWLock();
 }
 
 
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index da96dcc..93d5d77 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,4 +1,4 @@
-.TH "gdal-config" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index 408edd4..84dc1f1 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,4 +1,4 @@
-.TH "gdal2tiles" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
index 48756d6..0e293d5 100644
--- a/man/man1/gdal_calc.1
+++ b/man/man1/gdal_calc.1
@@ -1,4 +1,4 @@
-.TH "gdal_calc" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_calc" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index 366deaf..fd981ff 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,4 +1,4 @@
-.TH "gdal_contour" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index adbaae5..971ad13 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,4 +1,4 @@
-.TH "gdal_edit" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index c48ef1b..f56e96f 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,4 +1,4 @@
-.TH "gdal_fillnodata" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index 82678c2..93d834e 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,4 +1,4 @@
-.TH "gdal_grid" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index 41fbf51..0db2355 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,4 +1,4 @@
-.TH "gdal_merge" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_pansharpen.1 b/man/man1/gdal_pansharpen.1
index aaad1a4..db5b919 100644
--- a/man/man1/gdal_pansharpen.1
+++ b/man/man1/gdal_pansharpen.1
@@ -1,4 +1,4 @@
-.TH "gdal_pansharpen" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_pansharpen" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index 62e345c..ffc8ed5 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,4 +1,4 @@
-.TH "gdal_polygonize" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index 48aaf19..ffc72d0 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,4 +1,4 @@
-.TH "gdal_proximity" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index 97e137c..c8eee30 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,4 +1,4 @@
-.TH "gdal_rasterize" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index af283e0..01a9250 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,4 +1,4 @@
-.TH "gdal_retile" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index 495d2aa..350350e 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,4 +1,4 @@
-.TH "gdal_sieve" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index e1356f9..68e182e 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,4 +1,4 @@
-.TH "gdal_translate" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -56,7 +56,7 @@ Apply the scale/offset metadata for the bands to convert scaled values to unscal
 .IP "\fB\fB-srcwin\fP \fIxoff yoff xsize ysize\fP:\fP" 1c
 Selects a subwindow from the source image for copying based on pixel/line location\&.  
 .IP "\fB\fB-projwin\fP \fIulx uly lrx lry\fP:\fP" 1c
-Selects a subwindow from the source image for copying (like \fB-srcwin\fP) but with the corners given in georeferenced coordinates (by default expressed in the SRS of the dataset\&. Can be changed with -projwin_srs)\&.  
+Selects a subwindow from the source image for copying (like \fB-srcwin\fP) but with the corners given in georeferenced coordinates (by default expressed in the SRS of the dataset\&. Can be changed with -projwin_srs)\&. Note: in GDAL 2\&.1\&.0 and 2\&.1\&.1, using -projwin with coordinates not aligned with pixels will result in a sub-pixel shift\&. This has been corrected in later versions\&. When selecting non-nearest neighbour resampling, starting with GDAL 2\&.1\&.0, sub-pixel accuracy [...]
 .IP "\fB\fB-projwin_srs\fP \fIsrs_def\fP:\fP" 1c
 (GDAL >= 2\&.0) Specifies the SRS in which to interpret the coordinates given with -projwin\&. The \fIsrs_def\fP may be any of the usual GDAL/OGR forms, complete WKT, PROJ\&.4, EPSG:n or a file containing the WKT\&. Note that this does not cause reprojection of the dataset to the specified SRS\&.  
 .IP "\fB\fB-epo\fP: (Error when Partially Outside)\fP" 1c
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index c7dd774..ec316da 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,4 +1,4 @@
-.TH "gdal_utilities" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 402cdf2..2fe4487 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,4 +1,4 @@
-.TH "gdaladdo" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index 3c00f9d..4c0ded8 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,4 +1,4 @@
-.TH "gdalbuildvrt" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
index f4c1ea5..51e8fb4 100644
--- a/man/man1/gdalcompare.1
+++ b/man/man1/gdalcompare.1
@@ -1,4 +1,4 @@
-.TH "gdalcompare" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalcompare" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index 97d821f..613208b 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,4 +1,4 @@
-.TH "gdaldem" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 9698c1a..26c555f 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalinfo" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index fe50612..63d9bee 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,4 +1,4 @@
-.TH "gdallocationinfo" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index 374ff1f..18441bf 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,4 +1,4 @@
-.TH "gdalmanage" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index bf7e16a..1bc40a0 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,4 +1,4 @@
-.TH "gdalmove" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index 737e650..95ba6fc 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,4 +1,4 @@
-.TH "gdalsrsinfo" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index 5817f55..7660a95 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,4 +1,4 @@
-.TH "gdaltindex" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index 5cbc783..486f2e8 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,4 +1,4 @@
-.TH "gdaltransform" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index 744599e..cc291b6 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,4 +1,4 @@
-.TH "gdalwarp" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnm_utilities.1 b/man/man1/gnm_utilities.1
index 6d331ef..f4a4924 100644
--- a/man/man1/gnm_utilities.1
+++ b/man/man1/gnm_utilities.1
@@ -1,4 +1,4 @@
-.TH "gnm_utilities" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gnm_utilities" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmanalyse.1 b/man/man1/gnmanalyse.1
index 0304331..c6875f2 100644
--- a/man/man1/gnmanalyse.1
+++ b/man/man1/gnmanalyse.1
@@ -1,4 +1,4 @@
-.TH "gnmanalyse" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gnmanalyse" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmmanage.1 b/man/man1/gnmmanage.1
index 2a0477f..19eedbf 100644
--- a/man/man1/gnmmanage.1
+++ b/man/man1/gnmmanage.1
@@ -1,4 +1,4 @@
-.TH "gnmmanage" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "gnmmanage" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index b3fe43e..9517677 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,4 +1,4 @@
-.TH "nearblack" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index 48b7e4d..952b2b0 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,4 +1,4 @@
-.TH "ogr2ogr" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index 70552da..b5451c7 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,4 +1,4 @@
-.TH "ogr_utilities" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index 09e66a0..b652fe1 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,4 +1,4 @@
-.TH "ogrinfo" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
index fffeaf1..c3a79a5 100644
--- a/man/man1/ogrlineref.1
+++ b/man/man1/ogrlineref.1
@@ -1,4 +1,4 @@
-.TH "ogrlineref" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrlineref" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index 70ec006..bc8bd80 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,4 +1,4 @@
-.TH "ogrtindex" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index 3470311..0793f2f 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,4 +1,4 @@
-.TH "pct2rgb" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index 207a72a..e46bffa 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,4 +1,4 @@
-.TH "rgb2pct" 1 "Thu Jul 7 2016" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Fri Oct 14 2016" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp
index f8b1e89..23f2511 100644
--- a/ogr/ogrgeometry.cpp
+++ b/ogr/ogrgeometry.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeometry.cpp 33757 2016-03-20 20:22:33Z goatbar $
+ * $Id: ogrgeometry.cpp 35500 2016-09-23 14:10:22Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements a few base methods on OGRGeometry.
@@ -41,7 +41,7 @@
 #define UNUSED_IF_NO_GEOS
 #endif
 
-CPL_CVSID("$Id: ogrgeometry.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: ogrgeometry.cpp 35500 2016-09-23 14:10:22Z rouault $");
 
 int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
 
@@ -5968,8 +5968,9 @@ int OGR_GT_IsSurface( OGRwkbGeometryType eGeomType )
 /**
  * \brief Return if a geometry type is a non-linear geometry type.
  *
- * Such geometry type are wkbCircularString, wkbCompoundCurve, wkbCurvePolygon,
- * wkbMultiCurve, wkbMultiSurface and their 3D variant.
+ * Such geometry type are wkbCurve, wkbCircularString, wkbCompoundCurve,
+ * wkbSurface, wkbCurvePolygon, wkbMultiCurve, wkbMultiSurface and their
+ * Z/M variants.
  *
  * @param eGeomType the geometry type
  * @return TRUE if the geometry type is a non-linear geometry type.
@@ -5980,7 +5981,8 @@ int OGR_GT_IsSurface( OGRwkbGeometryType eGeomType )
 int OGR_GT_IsNonLinear( OGRwkbGeometryType eGeomType )
 {
     OGRwkbGeometryType eFGeomType = wkbFlatten(eGeomType);
-    return eFGeomType == wkbCircularString || eFGeomType == wkbCompoundCurve ||
+    return eFGeomType == wkbCurve || eFGeomType == wkbSurface ||
+           eFGeomType == wkbCircularString || eFGeomType == wkbCompoundCurve ||
            eFGeomType == wkbCurvePolygon || eFGeomType == wkbMultiCurve ||
            eFGeomType == wkbMultiSurface;
 }
diff --git a/ogr/ogrsf_frmts/GNUmakefile b/ogr/ogrsf_frmts/GNUmakefile
index 351fe90..de61e6e 100644
--- a/ogr/ogrsf_frmts/GNUmakefile
+++ b/ogr/ogrsf_frmts/GNUmakefile
@@ -39,7 +39,7 @@ SUBDIRS-$(CURL_SETTING) += elastic
 SUBDIRS-$(HAVE_SQLITE)	+= gpkg
 SUBDIRS-$(HAVE_SQLITE)	+= osm
 SUBDIRS-$(HAVE_SOSI)	+= sosi
-SUBDIRS-$(CURL_SETTING) += cartodb
+SUBDIRS-$(CURL_SETTING) += carto
 SUBDIRS-$(CURL_SETTING) += amigocloud
 SUBDIRS-$(CURL_SETTING) += plscenes
 SUBDIRS-$(CURL_SETTING) += csw
diff --git a/ogr/ogrsf_frmts/cartodb/GNUmakefile b/ogr/ogrsf_frmts/carto/GNUmakefile
similarity index 54%
rename from ogr/ogrsf_frmts/cartodb/GNUmakefile
rename to ogr/ogrsf_frmts/carto/GNUmakefile
index cd4507a..66d5ec7 100644
--- a/ogr/ogrsf_frmts/cartodb/GNUmakefile
+++ b/ogr/ogrsf_frmts/carto/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrcartodbdriver.o ogrcartodbdatasource.o ogrcartodblayer.o ogrcartodbtablelayer.o ogrcartodbresultlayer.o
+OBJ	=	ogrcartodriver.o ogrcartodatasource.o ogrcartolayer.o ogrcartotablelayer.o ogrcartoresultlayer.o
 
 CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../pgdump $(CPPFLAGS)
 
@@ -11,4 +11,4 @@ default:	$(O_OBJ:.o=.$(OBJ_EXT))
 clean:
 	rm -f *.o $(O_OBJ)
 
-$(O_OBJ):	ogr_cartodb.h
\ No newline at end of file
+$(O_OBJ):	ogr_carto.h
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/cartodb/drv_cartodb.html b/ogr/ogrsf_frmts/carto/drv_carto.html
similarity index 76%
rename from ogr/ogrsf_frmts/cartodb/drv_cartodb.html
rename to ogr/ogrsf_frmts/carto/drv_carto.html
index 784084a..99172da 100644
--- a/ogr/ogrsf_frmts/cartodb/drv_cartodb.html
+++ b/ogr/ogrsf_frmts/carto/drv_carto.html
@@ -1,28 +1,28 @@
 <html>
 <head>
-<title>CartoDB</title>
+<title>Carto</title>
 </head>
 
 <body bgcolor="#ffffff">
 
-<h1>CartoDB</h1>
+<h1>Carto</h1>
 
 (GDAL/OGR >= 1.11)<p>
 
-This driver can connect to the services implementing the CartoDB API.
+This driver can connect to the services implementing the Carto API.
 GDAL/OGR must be built with Curl support in order for the
-CartoDB driver to be compiled.<p>
+Carto driver to be compiled.<p>
 
 The driver supports read and write operations.<p>
 
 <h2>Dataset name syntax</h2>
 
-The minimal syntax to open a CartoDB datasource is : <pre>CartoDB:[connection_name]</pre><p>
+The minimal syntax to open a Carto datasource is : <pre>Carto:[connection_name]</pre><p>
 
 For single-user accounts, connection name is the account name.
 For multi-user accounts, connection_name must be the user name, not the account name.
 
-Additionnal optional parameters can be specified after the ':' sign.
+Additional optional parameters can be specified after the ':' sign.
 Currently the following one is supported :<p>
 
 <ul>
@@ -36,11 +36,11 @@ If several parameters are specified, they must be separated by a space.<p>
 
 The following configuration options are available :
 <ul>
-<li>CARTODB_API_URL: defaults to https://[account_name].cartodb.com/api/v2/sql.
+<li>CARTO_API_URL: defaults to https://[account_name].carto.com/api/v2/sql.
 Can be used to point to another server.</li>
-<li>CARTODB_HTTPS: can be set to NO to use http:// protocol instead of
-https:// (only if CARTODB_API_URL is not defined).</li>
-<li>CARTODB_API_KEY: see following paragraph.</li>
+<li>CARTO_HTTPS: can be set to NO to use http:// protocol instead of
+https:// (only if CARTO_API_URL is not defined).</li>
+<li>CARTO_API_KEY: see following paragraph.</li>
 </ul>
 
 
@@ -50,8 +50,8 @@ Most operations, in particular write operations, require an authenticated
 access. The only exception is read-only access to public tables.<p>
 
 Authenticated access is obtained by specifying the API key given in the
-management interface of the CartoDB service. It is specified with the
-CARTODB_API_KEY configuration option.<p>
+management interface of the Carto service. It is specified with the
+CARTO_API_KEY configuration option.<p>
 
 <h2>Geometry</h2>
 
@@ -67,7 +67,7 @@ filters set with SetAttributeFilter().<p>
 <h2>Paging</h2>
 
 Features are retrieved from the server by chunks of 500 by default.
-This number can be altered with the CARTODB_PAGE_SIZE
+This number can be altered with the CARTO_PAGE_SIZE
 configuration option.<p>
 
 <h2>Write support</h2>
@@ -76,7 +76,7 @@ Table creation and deletion is possible.<p>
 
 Write support is only enabled when the datasource is opened in update mode.<p>
 
-The mapping between the operations of the CartoDB service and the OGR concepts is the following :
+The mapping between the operations of the Carto service and the OGR concepts is the following :
 <ul>
 <li>OGRFeature::CreateFeature() <==> INSERT operation</li>
 <li>OGRFeature::SetFeature() <==> UPDATE operation</li>
@@ -92,9 +92,9 @@ The above operations are by default issued to the server synchronously with the
 can cause performance penalties when issuing a lot of commands due to many client/server exchanges.<p>
 
 So, on a newly created layer, the INSERT of CreateFeature() operations are grouped together
-in chunks until they reach 15 MB (can be changed with the CARTODB_MAX_CHUNK_SIZE
+in chunks until they reach 15 MB (can be changed with the CARTO_MAX_CHUNK_SIZE
 configuration option, with a value in MB), at which point they are transferred
-to the server. By setting CARTODB_MAX_CHUNK_SIZE to 0, immediate transfer occurs.<p>
+to the server. By setting CARTO_MAX_CHUNK_SIZE to 0, immediate transfer occurs.<p>
 
 <h2>SQL</h2>
 
@@ -120,7 +120,7 @@ layer name to be created. Defaults to NO.</li>
 <li><b>GEOMETRY_NULLABLE</b>=YES/NO: Whether the values of the geometry column
 can be NULL. Defaults to YES.</li>
 
-<li><b>CARTODBFY</b>=YES/NO: Whether the created layer should be "CartoDBifi'ed"
+<li><b>CARTODBFY</b>=YES/NO: Whether the created layer should be "Cartodbifi'ed"
  (i.e. registered in dashboard). Defaults to YES.</li>
 
 <li> <b>LAUNDER</b>=YES/NO: This may be "YES" to force new fields created on this
@@ -137,21 +137,21 @@ The default value is "YES".  If enabled the table (layer) name will also be laun
 <li>
 Acceccing data from a public table:
 <pre>
-ogrinfo -ro "CartoDB:gdalautotest2 tables=tm_world_borders_simpl_0_3"
+ogrinfo -ro "Carto:gdalautotest2 tables=tm_world_borders_simpl_0_3"
 </pre>
 <p>
 
 <li>
 Creating and populating a table from a shapefile:
 <pre>
-ogr2ogr --config CARTODB_API_KEY abcdefghijklmnopqrstuvw -f CartoDB "CartoDB:myaccount" myshapefile.shp
+ogr2ogr --config CARTO_API_KEY abcdefghijklmnopqrstuvw -f Carto "Carto:myaccount" myshapefile.shp
 </pre>
 <p>
 
 <h2>See Also</h2>
 
 <ul>
-<li> <a href="http://docs.cartodb.com/cartodb-platform.html">CartoDB API overview</a><p>
+<li> <a href="https://carto.com/docs/">Carto API overview</a><p>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/cartodb/makefile.vc b/ogr/ogrsf_frmts/carto/makefile.vc
similarity index 56%
rename from ogr/ogrsf_frmts/cartodb/makefile.vc
rename to ogr/ogrsf_frmts/carto/makefile.vc
index 0a7c1cd..0553aa2 100644
--- a/ogr/ogrsf_frmts/cartodb/makefile.vc
+++ b/ogr/ogrsf_frmts/carto/makefile.vc
@@ -1,5 +1,5 @@
 
-OBJ	=	ogrcartodbdriver.obj ogrcartodbdatasource.obj ogrcartodblayer.obj ogrcartodbtablelayer.obj ogrcartodbresultlayer.obj
+OBJ	=	ogrcartodriver.obj ogrcartodatasource.obj ogrcartolayer.obj ogrcartotablelayer.obj ogrcartoresultlayer.obj
 
 EXTRAFLAGS =	-I.. -I..\.. -I..\geojson\libjson -I..\pgdump 
 
diff --git a/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h b/ogr/ogrsf_frmts/carto/ogr_carto.h
similarity index 82%
rename from ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
rename to ogr/ogrsf_frmts/carto/ogr_carto.h
index b44b764..6704d96 100644
--- a/ogr/ogrsf_frmts/cartodb/ogr_cartodb.h
+++ b/ogr/ogrsf_frmts/carto/ogr_carto.h
@@ -1,8 +1,8 @@
 /******************************************************************************
- * $Id: ogr_cartodb.h 33647 2016-03-05 16:43:00Z rouault $
+ * $Id: ogr_carto.h 34979 2016-08-08 09:30:34Z rouault $
  *
- * Project:  CARTODB Translator
- * Purpose:  Definition of classes for OGR CartoDB driver.
+ * Project:  CARTO Translator
+ * Purpose:  Definition of classes for OGR Carto driver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
@@ -27,8 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef OGR_CARTODB_H_INCLUDED
-#define OGR_CARTODB_H_INCLUDED
+#ifndef OGR_CARTO_H_INCLUDED
+#define OGR_CARTO_H_INCLUDED
 
 #include "ogrsf_frmts.h"
 #include "cpl_http.h"
@@ -36,34 +36,34 @@
 #include <vector>
 #include <json.h>
 
-json_object* OGRCARTODBGetSingleRow(json_object* poObj);
-CPLString OGRCARTODBEscapeIdentifier(const char* pszStr);
-CPLString OGRCARTODBEscapeLiteral(const char* pszStr);
+json_object* OGRCARTOGetSingleRow(json_object* poObj);
+CPLString OGRCARTOEscapeIdentifier(const char* pszStr);
+CPLString OGRCARTOEscapeLiteral(const char* pszStr);
 
 /************************************************************************/
-/*                      OGRCartoDBGeomFieldDefn                         */
+/*                      OGRCartoGeomFieldDefn                         */
 /************************************************************************/
 
-class OGRCartoDBGeomFieldDefn: public OGRGeomFieldDefn
+class OGRCartoGeomFieldDefn: public OGRGeomFieldDefn
 {
     public:
         int nSRID;
 
-        OGRCartoDBGeomFieldDefn(const char* pszNameIn, OGRwkbGeometryType eType) :
+        OGRCartoGeomFieldDefn(const char* pszNameIn, OGRwkbGeometryType eType) :
                 OGRGeomFieldDefn(pszNameIn, eType), nSRID(0)
         {
         }
 };
 
 /************************************************************************/
-/*                           OGRCARTODBLayer                            */
+/*                           OGRCARTOLayer                            */
 /************************************************************************/
-class OGRCARTODBDataSource;
+class OGRCARTODataSource;
 
-class OGRCARTODBLayer : public OGRLayer
+class OGRCARTOLayer : public OGRLayer
 {
 protected:
-    OGRCARTODBDataSource* poDS;
+    OGRCARTODataSource* poDS;
 
     OGRFeatureDefn      *poFeatureDefn;
     CPLString            osBaseSQL;
@@ -84,8 +84,8 @@ protected:
     virtual CPLString    GetSRS_SQL(const char* pszGeomCol) = 0;
 
   public:
-                         OGRCARTODBLayer(OGRCARTODBDataSource* poDS);
-                        ~OGRCARTODBLayer();
+                         OGRCARTOLayer(OGRCARTODataSource* poDS);
+                        ~OGRCARTOLayer();
 
     virtual void                ResetReading();
     virtual OGRFeature *        GetNextFeature();
@@ -98,7 +98,9 @@ protected:
 
     virtual int                 TestCapability( const char * );
 
-    int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("CARTODB_PAGE_SIZE", "500")); }
+    int                         GetFeaturesToFetch() {
+        return atoi(CPLGetConfigOption("CARTO_PAGE_SIZE",
+                        CPLGetConfigOption("CARTODB_PAGE_SIZE", "500"))); }
 };
 
 typedef enum
@@ -109,10 +111,10 @@ typedef enum
 } InsertState;
 
 /************************************************************************/
-/*                        OGRCARTODBTableLayer                          */
+/*                        OGRCARTOTableLayer                          */
 /************************************************************************/
 
-class OGRCARTODBTableLayer : public OGRCARTODBLayer
+class OGRCARTOTableLayer : public OGRCARTOLayer
 {
     CPLString           osName;
     CPLString           osQuery;
@@ -127,7 +129,7 @@ class OGRCARTODBTableLayer : public OGRCARTODBLayer
     GIntBig             nNextFID;
 
     int                 bDeferredCreation;
-    int                 bCartoDBify;
+    int                 bCartodbfy;
     int                 nMaxChunkSize;
 
     void                BuildWhere();
@@ -135,8 +137,8 @@ class OGRCARTODBTableLayer : public OGRCARTODBLayer
     virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
 
   public:
-                         OGRCARTODBTableLayer(OGRCARTODBDataSource* poDS, const char* pszName);
-                        ~OGRCARTODBTableLayer();
+                         OGRCARTOTableLayer(OGRCARTODataSource* poDS, const char* pszName);
+                        ~OGRCARTOTableLayer();
 
     virtual const char*         GetName() { return osName.c_str(); }
     virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn);
@@ -170,29 +172,29 @@ class OGRCARTODBTableLayer : public OGRCARTODBLayer
     void                SetDeferredCreation( OGRwkbGeometryType eGType,
                                             OGRSpatialReference* poSRS,
                                             int bGeomNullable,
-                                            int bCartoDBify);
+                                            int bCartodbfy);
     OGRErr              RunDeferredCreationIfNecessary();
     int                 GetDeferredCreation() const { return bDeferredCreation; }
-    void                CancelDeferredCreation() { bDeferredCreation = FALSE; bCartoDBify = FALSE; }
+    void                CancelDeferredCreation() { bDeferredCreation = FALSE; bCartodbfy = FALSE; }
 
     OGRErr              FlushDeferredInsert(bool bReset = true);
-    void                RunDeferredCartoDBfy();
+    void                RunDeferredCartofy();
 };
 
 /************************************************************************/
-/*                       OGRCARTODBResultLayer                          */
+/*                       OGRCARTOResultLayer                          */
 /************************************************************************/
 
-class OGRCARTODBResultLayer : public OGRCARTODBLayer
+class OGRCARTOResultLayer : public OGRCARTOLayer
 {
     OGRFeature          *poFirstFeature;
 
     virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
 
   public:
-                        OGRCARTODBResultLayer( OGRCARTODBDataSource* poDS,
+                        OGRCARTOResultLayer( OGRCARTODataSource* poDS,
                                                const char * pszRawStatement );
-    virtual             ~OGRCARTODBResultLayer();
+    virtual             ~OGRCARTOResultLayer();
 
     virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn);
     virtual OGRFeature  *GetNextRawFeature();
@@ -201,15 +203,15 @@ class OGRCARTODBResultLayer : public OGRCARTODBLayer
 };
 
 /************************************************************************/
-/*                           OGRCARTODBDataSource                       */
+/*                           OGRCARTODataSource                       */
 /************************************************************************/
 
-class OGRCARTODBDataSource : public OGRDataSource
+class OGRCARTODataSource : public OGRDataSource
 {
     char*               pszName;
     char*               pszAccount;
 
-    OGRCARTODBTableLayer**  papoLayers;
+    OGRCARTOTableLayer**  papoLayers;
     int                 nLayers;
 
     int                 bReadWrite;
@@ -229,8 +231,8 @@ class OGRCARTODBDataSource : public OGRDataSource
     int                 nPostGISMinor;
 
   public:
-                        OGRCARTODBDataSource();
-                        ~OGRCARTODBDataSource();
+                        OGRCARTODataSource();
+                        ~OGRCARTODataSource();
 
     int                 Open( const char * pszFilename,
                               char** papszOpenOptions,
@@ -276,4 +278,4 @@ class OGRCARTODBDataSource : public OGRDataSource
     int                         GetPostGISMinor() const { return nPostGISMinor; }
 };
 
-#endif /* ndef OGR_CARTODB_H_INCLUDED */
+#endif /* ndef OGR_CARTO_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp b/ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp
similarity index 84%
rename from ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
rename to ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp
index 1e51176..db6f030 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbdatasource.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp
@@ -1,8 +1,7 @@
 /******************************************************************************
- * $Id: ogrcartodbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
- * Project:  CartoDB Translator
- * Purpose:  Implements OGRCARTODBDataSource class
+ * Project:  Carto Translator
+ * Purpose:  Implements OGRCARTODataSource class
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
@@ -27,16 +26,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_cartodb.h"
+#include "ogr_carto.h"
 #include "ogr_pgdump.h"
 
-CPL_CVSID("$Id: ogrcartodbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrcartodatasource.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
-/*                        OGRCARTODBDataSource()                        */
+/*                        OGRCARTODataSource()                        */
 /************************************************************************/
 
-OGRCARTODBDataSource::OGRCARTODBDataSource() :
+OGRCARTODataSource::OGRCARTODataSource() :
     pszName(NULL),
     pszAccount(NULL),
     papoLayers(NULL),
@@ -51,10 +50,10 @@ OGRCARTODBDataSource::OGRCARTODBDataSource() :
 {}
 
 /************************************************************************/
-/*                       ~OGRCARTODBDataSource()                        */
+/*                       ~OGRCARTODataSource()                        */
 /************************************************************************/
 
-OGRCARTODBDataSource::~OGRCARTODBDataSource()
+OGRCARTODataSource::~OGRCARTODataSource()
 
 {
     for( int i = 0; i < nLayers; i++ )
@@ -64,7 +63,7 @@ OGRCARTODBDataSource::~OGRCARTODBDataSource()
     if (bMustCleanPersistent)
     {
         char** papszOptions = NULL;
-        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("CARTODB:%p", this));
+        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("CARTO:%p", this));
         CPLHTTPDestroyResult( CPLHTTPFetch( GetAPIURL(), papszOptions) );
         CSLDestroy(papszOptions);
     }
@@ -77,7 +76,7 @@ OGRCARTODBDataSource::~OGRCARTODBDataSource()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRCARTODBDataSource::TestCapability( const char * pszCap )
+int OGRCARTODataSource::TestCapability( const char * pszCap )
 
 {
     if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
@@ -92,7 +91,7 @@ int OGRCARTODBDataSource::TestCapability( const char * pszCap )
 /*                              GetLayer()                              */
 /************************************************************************/
 
-OGRLayer *OGRCARTODBDataSource::GetLayer( int iLayer )
+OGRLayer *OGRCARTODataSource::GetLayer( int iLayer )
 
 {
     if( iLayer < 0 || iLayer >= nLayers )
@@ -105,17 +104,17 @@ OGRLayer *OGRCARTODBDataSource::GetLayer( int iLayer )
 /*                          GetLayerByName()                            */
 /************************************************************************/
 
-OGRLayer *OGRCARTODBDataSource::GetLayerByName(const char * pszLayerName)
+OGRLayer *OGRCARTODataSource::GetLayerByName(const char * pszLayerName)
 {
     OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
     return poLayer;
 }
 
 /************************************************************************/
-/*                     OGRCARTODBGetOptionValue()                       */
+/*                     OGRCARTOGetOptionValue()                       */
 /************************************************************************/
 
-static CPLString OGRCARTODBGetOptionValue(const char* pszFilename,
+static CPLString OGRCARTOGetOptionValue(const char* pszFilename,
                                const char* pszOptionName)
 {
     CPLString osOptionName(pszOptionName);
@@ -135,7 +134,7 @@ static CPLString OGRCARTODBGetOptionValue(const char* pszFilename,
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRCARTODBDataSource::Open( const char * pszFilename,
+int OGRCARTODataSource::Open( const char * pszFilename,
                                 char** papszOpenOptionsIn,
                                 int bUpdateIn )
 
@@ -148,7 +147,10 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
         pszAccount = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "ACCOUNT"));
     else
     {
-        pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
+        if( STARTS_WITH_CI(pszFilename, "CARTODB:") )
+            pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
+        else
+            pszAccount = CPLStrdup(pszFilename + strlen("CARTO:"));
         char* pchSpace = strchr(pszAccount, ' ');
         if( pchSpace )
             *pchSpace = '\0';
@@ -160,18 +162,20 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
     }
 
     osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "API_KEY",
-                                    CPLGetConfigOption("CARTODB_API_KEY", ""));
+                            CPLGetConfigOption("CARTO_API_KEY", 
+                                CPLGetConfigOption("CARTODB_API_KEY", "")));
 
-    CPLString osTables = OGRCARTODBGetOptionValue(pszFilename, "tables");
+    CPLString osTables = OGRCARTOGetOptionValue(pszFilename, "tables");
 
     /*if( osTables.size() == 0 && osAPIKey.size() == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "When not specifying tables option, CARTODB_API_KEY must be defined");
+                 "When not specifying tables option, CARTO_API_KEY must be defined");
         return FALSE;
     }*/
 
-    bUseHTTPS = CPLTestBool(CPLGetConfigOption("CARTODB_HTTPS", "YES"));
+    bUseHTTPS = CPLTestBool(CPLGetConfigOption("CARTO_HTTPS",
+                                CPLGetConfigOption("CARTODB_HTTPS", "YES")));
 
     OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
     if( poSchemaLayer )
@@ -254,9 +258,9 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
         char** papszTables = CSLTokenizeString2(osTables, ",", 0);
         for(int i=0;papszTables && papszTables[i];i++)
         {
-            papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
-                papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
-            papoLayers[nLayers ++] = new OGRCARTODBTableLayer(this, papszTables[i]);
+            papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
+                papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
+            papoLayers[nLayers ++] = new OGRCARTOTableLayer(this, papszTables[i]);
         }
         CSLDestroy(papszTables);
         return TRUE;
@@ -270,9 +274,9 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
         {
             if( poFeat->GetFieldCount() == 1 )
             {
-                papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
-                    papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
-                papoLayers[nLayers ++] = new OGRCARTODBTableLayer(
+                papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
+                    papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
+                papoLayers[nLayers ++] = new OGRCARTOTableLayer(
                             this, poFeat->GetFieldAsString(0));
             }
             delete poFeat;
@@ -288,7 +292,7 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
         CPLString osSQL;
         osSQL.Printf("SELECT c.relname FROM pg_class c, pg_namespace n "
                      "WHERE c.relkind in ('r', 'v') AND c.relname !~ '^pg_' AND c.relnamespace=n.oid AND n.nspname = '%s'",
-                     OGRCARTODBEscapeLiteral(osCurrentSchema).c_str());
+                     OGRCARTOEscapeLiteral(osCurrentSchema).c_str());
         poTableListLayer = ExecuteSQLInternal(osSQL);
         if( poTableListLayer )
         {
@@ -297,9 +301,9 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
             {
                 if( poFeat->GetFieldCount() == 1 )
                 {
-                    papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
-                        papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
-                    papoLayers[nLayers ++] = new OGRCARTODBTableLayer(
+                    papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
+                        papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
+                    papoLayers[nLayers ++] = new OGRCARTOTableLayer(
                                 this, poFeat->GetFieldAsString(0));
                 }
                 delete poFeat;
@@ -317,22 +321,23 @@ int OGRCARTODBDataSource::Open( const char * pszFilename,
 /*                            GetAPIURL()                               */
 /************************************************************************/
 
-const char* OGRCARTODBDataSource::GetAPIURL() const
+const char* OGRCARTODataSource::GetAPIURL() const
 {
-    const char* pszAPIURL = CPLGetConfigOption("CARTODB_API_URL", NULL);
+    const char* pszAPIURL = CPLGetConfigOption("CARTO_API_URL",
+                                CPLGetConfigOption("CARTODB_API_URL", NULL));
     if (pszAPIURL)
         return pszAPIURL;
     else if (bUseHTTPS)
-        return CPLSPrintf("https://%s.cartodb.com/api/v2/sql", pszAccount);
+        return CPLSPrintf("https://%s.carto.com/api/v2/sql", pszAccount);
     else
-        return CPLSPrintf("http://%s.cartodb.com/api/v2/sql", pszAccount);
+        return CPLSPrintf("http://%s.carto.com/api/v2/sql", pszAccount);
 }
 
 /************************************************************************/
 /*                             FetchSRSId()                             */
 /************************************************************************/
 
-int OGRCARTODBDataSource::FetchSRSId( OGRSpatialReference * poSRS )
+int OGRCARTODataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
     const char*         pszAuthorityName;
@@ -388,7 +393,7 @@ int OGRCARTODBDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*                          ICreateLayer()                              */
 /************************************************************************/
 
-OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszNameIn,
+OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
                                            OGRSpatialReference *poSpatialRef,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
@@ -427,7 +432,7 @@ OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszNameIn,
     }
 
     CPLString osName(pszNameIn);
-    if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+    if( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) )
     {
         char* pszTmp = OGRPGCommonLaunderName(pszNameIn);
         osName = pszTmp;
@@ -435,13 +440,13 @@ OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszNameIn,
     }
 
 
-    OGRCARTODBTableLayer* poLayer = new OGRCARTODBTableLayer(this, osName);
-    int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    OGRCARTOTableLayer* poLayer = new OGRCARTOTableLayer(this, osName);
+    const bool bGeomNullable = CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true);
     int nSRID = (poSpatialRef && eGType != wkbNone) ? FetchSRSId( poSpatialRef ) : 0;
-    int bCartoDBify = CSLFetchBoolean(papszOptions, "CARTODBFY",
-                                      CSLFetchBoolean(papszOptions, "CARTODBIFY",
-                                      TRUE));
-    if( bCartoDBify )
+    bool bCartoify = CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBFY",
+                                    CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBIFY",
+                                                 true));
+    if( bCartoify )
     {
         if( nSRID != 4326 )
         {
@@ -451,14 +456,14 @@ OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszNameIn,
                         "Cannot register table in dashboard with "
                         "cdb_cartodbfytable() since its SRS is not EPSG:4326");
             }
-            bCartoDBify = FALSE;
+            bCartoify = false;
         }
     }
 
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable, bCartoDBify);
-    papoLayers = (OGRCARTODBTableLayer**) CPLRealloc(
-                    papoLayers, (nLayers + 1) * sizeof(OGRCARTODBTableLayer*));
+    poLayer->SetLaunderFlag( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) );
+    poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable, bCartoify);
+    papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
+                    papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
     papoLayers[nLayers ++] = poLayer;
 
     return poLayer;
@@ -468,7 +473,7 @@ OGRLayer   *OGRCARTODBDataSource::ICreateLayer( const char *pszNameIn,
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
-OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
+OGRErr OGRCARTODataSource::DeleteLayer(int iLayer)
 {
     if (!bReadWrite)
     {
@@ -491,7 +496,7 @@ OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
 /* -------------------------------------------------------------------- */
     CPLString osLayerName = papoLayers[iLayer]->GetLayerDefn()->GetName();
 
-    CPLDebug( "CARTODB", "DeleteLayer(%s)", osLayerName.c_str() );
+    CPLDebug( "CARTO", "DeleteLayer(%s)", osLayerName.c_str() );
 
     int bDeferredCreation = papoLayers[iLayer]->GetDeferredCreation();
     papoLayers[iLayer]->CancelDeferredCreation();
@@ -507,7 +512,7 @@ OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
     {
         CPLString osSQL;
         osSQL.Printf("DROP TABLE %s",
-                    OGRCARTODBEscapeIdentifier(osLayerName).c_str());
+                    OGRCARTOEscapeIdentifier(osLayerName).c_str());
 
         json_object* poObj = RunSQL(osSQL);
         if( poObj == NULL )
@@ -522,18 +527,18 @@ OGRErr OGRCARTODBDataSource::DeleteLayer(int iLayer)
 /*                          AddHTTPOptions()                            */
 /************************************************************************/
 
-char** OGRCARTODBDataSource::AddHTTPOptions()
+char** OGRCARTODataSource::AddHTTPOptions()
 {
     bMustCleanPersistent = TRUE;
 
-    return CSLAddString(NULL, CPLSPrintf("PERSISTENT=CARTODB:%p", this));
+    return CSLAddString(NULL, CPLSPrintf("PERSISTENT=CARTO:%p", this));
 }
 
 /************************************************************************/
 /*                               RunSQL()                               */
 /************************************************************************/
 
-json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
+json_object* OGRCARTODataSource::RunSQL(const char* pszUnescapedSQL)
 {
     CPLString osSQL("POSTFIELDS=q=");
     /* Do post escaping */
@@ -573,7 +578,7 @@ json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
     if (psResult->pszContentType &&
         STARTS_WITH(psResult->pszContentType, "text/html"))
     {
-        CPLDebug( "CARTODB", "RunSQL HTML Response:%s", psResult->pabyData );
+        CPLDebug( "CARTO", "RunSQL HTML Response:%s", psResult->pabyData );
         CPLError(CE_Failure, CPLE_AppDefined,
                  "HTML error page returned by server");
         CPLHTTPDestroyResult(psResult);
@@ -597,7 +602,7 @@ json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
     }
 
     if( strlen((const char*)psResult->pabyData) < 1000 )
-        CPLDebug( "CARTODB", "RunSQL Response:%s", psResult->pabyData );
+        CPLDebug( "CARTO", "RunSQL Response:%s", psResult->pabyData );
 
     json_tokener* jstok = NULL;
     json_object* poObj = NULL;
@@ -646,10 +651,10 @@ json_object* OGRCARTODBDataSource::RunSQL(const char* pszUnescapedSQL)
 }
 
 /************************************************************************/
-/*                        OGRCARTODBGetSingleRow()                      */
+/*                        OGRCARTOGetSingleRow()                      */
 /************************************************************************/
 
-json_object* OGRCARTODBGetSingleRow(json_object* poObj)
+json_object* OGRCARTOGetSingleRow(json_object* poObj)
 {
     if( poObj == NULL )
     {
@@ -677,7 +682,7 @@ json_object* OGRCARTODBGetSingleRow(json_object* poObj)
 /*                             ExecuteSQL()                             */
 /************************************************************************/
 
-OGRLayer * OGRCARTODBDataSource::ExecuteSQL( const char *pszSQLCommand,
+OGRLayer * OGRCARTODataSource::ExecuteSQL( const char *pszSQLCommand,
                                         OGRGeometry *poSpatialFilter,
                                         const char *pszDialect )
 
@@ -686,7 +691,7 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQL( const char *pszSQLCommand,
                               TRUE);
 }
 
-OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
+OGRLayer * OGRCARTODataSource::ExecuteSQLInternal( const char *pszSQLCommand,
                                                      OGRGeometry *poSpatialFilter,
                                                      const char *pszDialect,
                                                      int bRunDeferredActions )
@@ -698,7 +703,7 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
         {
             papoLayers[iLayer]->RunDeferredCreationIfNecessary();
             CPL_IGNORE_RET_VAL(papoLayers[iLayer]->FlushDeferredInsert());
-            papoLayers[iLayer]->RunDeferredCartoDBfy();
+            papoLayers[iLayer]->RunDeferredCartofy();
         }
     }
 
@@ -744,7 +749,7 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
         return NULL;
     }
 
-    OGRCARTODBResultLayer* poLayer = new OGRCARTODBResultLayer( this, pszSQLCommand );
+    OGRCARTOResultLayer* poLayer = new OGRCARTOResultLayer( this, pszSQLCommand );
 
     if( poSpatialFilter != NULL )
         poLayer->SetSpatialFilter( poSpatialFilter );
@@ -762,7 +767,7 @@ OGRLayer * OGRCARTODBDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
 /*                          ReleaseResultSet()                          */
 /************************************************************************/
 
-void OGRCARTODBDataSource::ReleaseResultSet( OGRLayer * poLayer )
+void OGRCARTODataSource::ReleaseResultSet( OGRLayer * poLayer )
 
 {
     delete poLayer;
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp b/ogr/ogrsf_frmts/carto/ogrcartodriver.cpp
similarity index 73%
rename from ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
rename to ogr/ogrsf_frmts/carto/ogrcartodriver.cpp
index 79a9232..21b3df3 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbdriver.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartodriver.cpp
@@ -1,8 +1,7 @@
 /******************************************************************************
- * $Id: ogrcartodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
- * Project:  CartoDB Translator
- * Purpose:  Implements OGRCARTODBDriver.
+ * Project:  Carto Translator
+ * Purpose:  Implements OGRCARTODriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
@@ -27,34 +26,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_cartodb.h"
+#include "ogr_carto.h"
 
-// g++ -g -Wall -fPIC -shared -o ogr_CARTODB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/cartodb ogr/ogrsf_frmts/cartodb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/libjson
+// g++ -g -Wall -fPIC -shared -o ogr_CARTO.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/carto ogr/ogrsf_frmts/carto/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/libjson
 
-CPL_CVSID("$Id: ogrcartodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrcartodriver.cpp 35040 2016-08-10 14:02:46Z rouault $");
 
-extern "C" void RegisterOGRCartoDB();
+extern "C" void RegisterOGRCarto();
 
 /************************************************************************/
-/*                        OGRCartoDBDriverIdentify()                    */
+/*                        OGRCartoDriverIdentify()                    */
 /************************************************************************/
 
-static int OGRCartoDBDriverIdentify( GDALOpenInfo* poOpenInfo )
+static int OGRCartoDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
-    return STARTS_WITH_CI(poOpenInfo->pszFilename, "CARTODB:");
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, "CARTO:") ||
+           STARTS_WITH_CI(poOpenInfo->pszFilename, "CARTODB:");
 }
 
 /************************************************************************/
-/*                           OGRCartoDBDriverOpen()                     */
+/*                           OGRCartoDriverOpen()                     */
 /************************************************************************/
 
-static GDALDataset *OGRCartoDBDriverOpen( GDALOpenInfo* poOpenInfo )
+static GDALDataset *OGRCartoDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    if( !OGRCartoDBDriverIdentify(poOpenInfo) )
+    if( !OGRCartoDriverIdentify(poOpenInfo) )
         return NULL;
 
-    OGRCARTODBDataSource   *poDS = new OGRCARTODBDataSource();
+    OGRCARTODataSource   *poDS = new OGRCARTODataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions,
                      poOpenInfo->eAccess == GA_Update ) )
@@ -67,10 +67,10 @@ static GDALDataset *OGRCartoDBDriverOpen( GDALOpenInfo* poOpenInfo )
 }
 
 /************************************************************************/
-/*                      OGRCartoDBDriverCreate()                        */
+/*                      OGRCartoDriverCreate()                        */
 /************************************************************************/
 
-static GDALDataset *OGRCartoDBDriverCreate( const char * pszName,
+static GDALDataset *OGRCartoDriverCreate( const char * pszName,
                                             CPL_UNUSED int nBands,
                                             CPL_UNUSED int nXSize,
                                             CPL_UNUSED int nYSize,
@@ -78,13 +78,13 @@ static GDALDataset *OGRCartoDBDriverCreate( const char * pszName,
                                             CPL_UNUSED char **papszOptions )
 
 {
-    OGRCARTODBDataSource   *poDS = new OGRCARTODBDataSource();
+    OGRCARTODataSource   *poDS = new OGRCARTODataSource();
 
     if( !poDS->Open( pszName, NULL, TRUE ) )
     {
         delete poDS;
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "CartoDB driver doesn't support database creation." );
+                  "Carto driver doesn't support database creation." );
         return NULL;
     }
 
@@ -92,25 +92,25 @@ static GDALDataset *OGRCartoDBDriverCreate( const char * pszName,
 }
 
 /************************************************************************/
-/*                         RegisterOGRCARTODB()                         */
+/*                         RegisterOGRCARTO()                         */
 /************************************************************************/
 
-void RegisterOGRCartoDB()
+void RegisterOGRCarto()
 
 {
-    if( GDALGetDriverByName( "CartoDB" ) != NULL )
+    if( GDALGetDriverByName( "Carto" ) != NULL )
       return;
 
     GDALDriver* poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "CartoDB" );
+    poDriver->SetDescription( "Carto" );
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                  "CartoDB" );
+                                  "Carto" );
     poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                    "drv_cartodb.html" );
+                                    "drv_carto.html" );
 
-    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CARTODB:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CARTO:" );
 
     poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
     "<OpenOptionList>"
@@ -126,7 +126,7 @@ void RegisterOGRCartoDB()
     "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
     "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
     "  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
-    "  <Option name='CARTODBFY' alias='CARTODBIFY' type='boolean' description='Whether the created layer should be \"CartoDBifi'ed\" (i.e. registered in dashboard)' default='YES'/>"
+    "  <Option name='CARTODBFY' alias='CARTODBIFY' type='boolean' description='Whether the created layer should be \"Cartodbifi'ed\" (i.e. registered in dashboard)' default='YES'/>"
     "</LayerCreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES, "Integer Integer64 Real String Date DateTime Time" );
@@ -134,9 +134,15 @@ void RegisterOGRCartoDB()
     poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
 
-    poDriver->pfnOpen = OGRCartoDBDriverOpen;
-    poDriver->pfnIdentify = OGRCartoDBDriverIdentify;
-    poDriver->pfnCreate = OGRCartoDBDriverCreate;
+    poDriver->pfnOpen = OGRCartoDriverOpen;
+    poDriver->pfnIdentify = OGRCartoDriverIdentify;
+    poDriver->pfnCreate = OGRCartoDriverCreate;
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
+
+// Just kept for C ABI stability
+void RegisterOGRCartoDB()
+{
+    RegisterOGRCarto();
+}
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp b/ogr/ogrsf_frmts/carto/ogrcartolayer.cpp
similarity index 90%
rename from ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
rename to ogr/ogrsf_frmts/carto/ogrcartolayer.cpp
index 7d0791b..242c376 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodblayer.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartolayer.cpp
@@ -1,8 +1,7 @@
 /******************************************************************************
- * $Id: ogrcartodblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
- * Project:  CartoDB Translator
- * Purpose:  Implements OGRCARTODBLayer class.
+ * Project:  Carto Translator
+ * Purpose:  Implements OGRCARTOLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
@@ -27,16 +26,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_cartodb.h"
+#include "ogr_carto.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcartodblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrcartolayer.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
-/*                         OGRCARTODBLayer()                            */
+/*                         OGRCARTOLayer()                            */
 /************************************************************************/
 
-OGRCARTODBLayer::OGRCARTODBLayer(OGRCARTODBDataSource* poDSIn) :
+OGRCARTOLayer::OGRCARTOLayer(OGRCARTODataSource* poDSIn) :
     poDS(poDSIn),
     poFeatureDefn(NULL),
     poCachedObj(NULL)
@@ -45,10 +44,10 @@ OGRCARTODBLayer::OGRCARTODBLayer(OGRCARTODBDataSource* poDSIn) :
 }
 
 /************************************************************************/
-/*                         ~OGRCARTODBLayer()                           */
+/*                         ~OGRCARTOLayer()                           */
 /************************************************************************/
 
-OGRCARTODBLayer::~OGRCARTODBLayer()
+OGRCARTOLayer::~OGRCARTOLayer()
 
 {
     if( poCachedObj != NULL )
@@ -62,7 +61,7 @@ OGRCARTODBLayer::~OGRCARTODBLayer()
 /*                            ResetReading()                            */
 /************************************************************************/
 
-void OGRCARTODBLayer::ResetReading()
+void OGRCARTOLayer::ResetReading()
 
 {
     if( poCachedObj != NULL )
@@ -78,7 +77,7 @@ void OGRCARTODBLayer::ResetReading()
 /*                           GetLayerDefn()                             */
 /************************************************************************/
 
-OGRFeatureDefn * OGRCARTODBLayer::GetLayerDefn()
+OGRFeatureDefn * OGRCARTOLayer::GetLayerDefn()
 {
     return GetLayerDefnInternal(NULL);
 }
@@ -87,13 +86,13 @@ OGRFeatureDefn * OGRCARTODBLayer::GetLayerDefn()
 /*                           BuildFeature()                             */
 /************************************************************************/
 
-OGRFeature *OGRCARTODBLayer::BuildFeature(json_object* poRowObj)
+OGRFeature *OGRCARTOLayer::BuildFeature(json_object* poRowObj)
 {
     OGRFeature* poFeature = NULL;
     if( poRowObj != NULL &&
         json_object_get_type(poRowObj) == json_type_object )
     {
-        //CPLDebug("CartoDB", "Row: %s", json_object_to_json_string(poRowObj));
+        //CPLDebug("Carto", "Row: %s", json_object_to_json_string(poRowObj));
         poFeature = new OGRFeature(poFeatureDefn);
 
         if( osFIDColName.size() )
@@ -167,7 +166,7 @@ OGRFeature *OGRCARTODBLayer::BuildFeature(json_object* poRowObj)
 /*                        FetchNewFeatures()                            */
 /************************************************************************/
 
-json_object* OGRCARTODBLayer::FetchNewFeatures(GIntBig iNextIn)
+json_object* OGRCARTOLayer::FetchNewFeatures(GIntBig iNextIn)
 {
     CPLString osSQL = osBaseSQL;
     if( osSQL.ifind("SELECT") != std::string::npos &&
@@ -185,7 +184,7 @@ json_object* OGRCARTODBLayer::FetchNewFeatures(GIntBig iNextIn)
 /*                        GetNextRawFeature()                           */
 /************************************************************************/
 
-OGRFeature *OGRCARTODBLayer::GetNextRawFeature()
+OGRFeature *OGRCARTOLayer::GetNextRawFeature()
 {
     if( bEOF )
         return NULL;
@@ -248,7 +247,7 @@ OGRFeature *OGRCARTODBLayer::GetNextRawFeature()
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
-OGRFeature *OGRCARTODBLayer::GetNextFeature()
+OGRFeature *OGRCARTOLayer::GetNextFeature()
 {
     OGRFeature  *poFeature;
 
@@ -274,7 +273,7 @@ OGRFeature *OGRCARTODBLayer::GetNextFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRCARTODBLayer::TestCapability( const char * pszCap )
+int OGRCARTOLayer::TestCapability( const char * pszCap )
 
 {
     if ( EQUAL(pszCap, OLCStringsAsUTF8) )
@@ -286,7 +285,7 @@ int OGRCARTODBLayer::TestCapability( const char * pszCap )
 /*                          EstablishLayerDefn()                        */
 /************************************************************************/
 
-void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
+void OGRCARTOLayer::EstablishLayerDefn(const char* pszLayerName,
                                          json_object* poObjIn)
 {
     poFeatureDefn = new OGRFeatureDefn(pszLayerName);
@@ -341,7 +340,7 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
             if( poType != NULL && json_object_get_type(poType) == json_type_string )
             {
                 const char* pszType = json_object_get_string(poType);
-                CPLDebug("CARTODB", "%s : %s", pszColName, pszType);
+                CPLDebug("CARTO", "%s : %s", pszColName, pszType);
                 if( EQUAL(pszType, "string") ||
                     EQUAL(pszType, "unknown(19)") /* name */ )
                 {
@@ -371,8 +370,8 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
                 {
                     if( !EQUAL(pszColName, "the_geom_webmercator") )
                     {
-                        OGRCartoDBGeomFieldDefn *poFieldDefn =
-                            new OGRCartoDBGeomFieldDefn(pszColName, wkbUnknown);
+                        OGRCartoGeomFieldDefn *poFieldDefn =
+                            new OGRCartoGeomFieldDefn(pszColName, wkbUnknown);
                         poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
                         OGRSpatialReference* l_poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
                         if( l_poSRS != NULL )
@@ -391,7 +390,7 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
                 }
                 else
                 {
-                    CPLDebug("CARTODB", "Unhandled type: %s. Defaulting to string", pszType);
+                    CPLDebug("CARTO", "Unhandled type: %s. Defaulting to string", pszType);
                     OGRFieldDefn oFieldDefn(pszColName, OFTString);
                     poFeatureDefn->AddFieldDefn(&oFieldDefn);
                 }
@@ -399,8 +398,8 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
             else if( poType != NULL && json_object_get_type(poType) == json_type_int )
             {
                 /* FIXME? manual creations of geometry columns return integer types */
-                OGRCartoDBGeomFieldDefn *poFieldDefn =
-                    new OGRCartoDBGeomFieldDefn(pszColName, wkbUnknown);
+                OGRCartoGeomFieldDefn *poFieldDefn =
+                    new OGRCartoGeomFieldDefn(pszColName, wkbUnknown);
                 poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
                 OGRSpatialReference* l_poSRS = GetSRS(pszColName, &poFieldDefn->nSRID);
                 if( l_poSRS != NULL )
@@ -420,11 +419,11 @@ void OGRCARTODBLayer::EstablishLayerDefn(const char* pszLayerName,
 /*                               GetSRS()                               */
 /************************************************************************/
 
-OGRSpatialReference* OGRCARTODBLayer::GetSRS(const char* pszGeomCol,
+OGRSpatialReference* OGRCARTOLayer::GetSRS(const char* pszGeomCol,
                                              int *pnSRID)
 {
     json_object* poObj = poDS->RunSQL(GetSRS_SQL(pszGeomCol));
-    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
     if( poRowObj == NULL )
     {
         if( poObj != NULL )
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp b/ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp
similarity index 83%
rename from ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
rename to ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp
index bb26d49..1e7814d 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbresultlayer.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp
@@ -1,8 +1,7 @@
 /******************************************************************************
- * $Id
  *
- * Project:  CartoDB Translator
- * Purpose:  Implements OGRCARTODBResultLayer class.
+ * Project:  Carto Translator
+ * Purpose:  Implements OGRCARTOResultLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
@@ -27,17 +26,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_cartodb.h"
+#include "ogr_carto.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogrcartoresultlayer.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
-/*                          OGRCARTODBResultLayer()                     */
+/*                          OGRCARTOResultLayer()                     */
 /************************************************************************/
 
-OGRCARTODBResultLayer::OGRCARTODBResultLayer( OGRCARTODBDataSource* poDSIn,
+OGRCARTOResultLayer::OGRCARTOResultLayer( OGRCARTODataSource* poDSIn,
                                               const char * pszRawQueryIn ) :
-    OGRCARTODBLayer(poDSIn),
+    OGRCARTOLayer(poDSIn),
     poFirstFeature(NULL)
 {
     osBaseSQL = pszRawQueryIn;
@@ -45,10 +44,10 @@ OGRCARTODBResultLayer::OGRCARTODBResultLayer( OGRCARTODBDataSource* poDSIn,
 }
 
 /************************************************************************/
-/*                       ~OGRCARTODBResultLayer()                       */
+/*                       ~OGRCARTOResultLayer()                       */
 /************************************************************************/
 
-OGRCARTODBResultLayer::~OGRCARTODBResultLayer()
+OGRCARTOResultLayer::~OGRCARTOResultLayer()
 
 {
     delete poFirstFeature;
@@ -58,7 +57,7 @@ OGRCARTODBResultLayer::~OGRCARTODBResultLayer()
 /*                          GetLayerDefnInternal()                      */
 /************************************************************************/
 
-OGRFeatureDefn * OGRCARTODBResultLayer::GetLayerDefnInternal(json_object* poObjIn)
+OGRFeatureDefn * OGRCARTOResultLayer::GetLayerDefnInternal(json_object* poObjIn)
 {
     if( poFeatureDefn != NULL )
         return poFeatureDefn;
@@ -72,7 +71,7 @@ OGRFeatureDefn * OGRCARTODBResultLayer::GetLayerDefnInternal(json_object* poObjI
 /*                           GetNextRawFeature()                        */
 /************************************************************************/
 
-OGRFeature  *OGRCARTODBResultLayer::GetNextRawFeature()
+OGRFeature  *OGRCARTOResultLayer::GetNextRawFeature()
 {
     if( poFirstFeature )
     {
@@ -81,14 +80,14 @@ OGRFeature  *OGRCARTODBResultLayer::GetNextRawFeature()
         return poRet;
     }
     else
-        return OGRCARTODBLayer::GetNextRawFeature();
+        return OGRCARTOLayer::GetNextRawFeature();
 }
 
 /************************************************************************/
 /*                                IsOK()                                */
 /************************************************************************/
 
-int  OGRCARTODBResultLayer::IsOK()
+int  OGRCARTOResultLayer::IsOK()
 {
     CPLErrorReset();
     poFirstFeature = GetNextFeature();
@@ -99,7 +98,7 @@ int  OGRCARTODBResultLayer::IsOK()
 /*                             GetSRS_SQL()                             */
 /************************************************************************/
 
-CPLString OGRCARTODBResultLayer::GetSRS_SQL(const char* pszGeomCol)
+CPLString OGRCARTOResultLayer::GetSRS_SQL(const char* pszGeomCol)
 {
     CPLString osSQL;
     CPLString osLimitedSQL;
@@ -126,7 +125,7 @@ CPLString OGRCARTODBResultLayer::GetSRS_SQL(const char* pszGeomCol)
     /* to geometries of all rows. */
     osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
                 "(SELECT ST_SRID(%s) FROM (%s) ogr_subselect)",
-                OGRCARTODBEscapeIdentifier(pszGeomCol).c_str(),
+                OGRCARTOEscapeIdentifier(pszGeomCol).c_str(),
                 osLimitedSQL.c_str());
 
     return osSQL;
diff --git a/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp b/ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp
similarity index 85%
rename from ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
rename to ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp
index 11f7e49..d3e7a89 100644
--- a/ogr/ogrsf_frmts/cartodb/ogrcartodbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp
@@ -1,8 +1,7 @@
 /******************************************************************************
- * $Id: ogrcartodbtablelayer.cpp 34476 2016-06-30 15:43:07Z rouault $
  *
- * Project:  CartoDB Translator
- * Purpose:  Implements OGRCARTODBTableLayer class.
+ * Project:  Carto Translator
+ * Purpose:  Implements OGRCARTOTableLayer class.
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
  *
  ******************************************************************************
@@ -27,17 +26,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_cartodb.h"
+#include "ogr_carto.h"
 #include "ogr_p.h"
 #include "ogr_pgdump.h"
 
-CPL_CVSID("$Id: ogrcartodbtablelayer.cpp 34476 2016-06-30 15:43:07Z rouault $");
+CPL_CVSID("$Id: ogrcartotablelayer.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
-/*                    OGRCARTODBEscapeIdentifier( )                     */
+/*                    OGRCARTOEscapeIdentifier( )                     */
 /************************************************************************/
 
-CPLString OGRCARTODBEscapeIdentifier(const char* pszStr)
+CPLString OGRCARTOEscapeIdentifier(const char* pszStr)
 {
     CPLString osStr;
 
@@ -57,10 +56,10 @@ CPLString OGRCARTODBEscapeIdentifier(const char* pszStr)
 }
 
 /************************************************************************/
-/*                    OGRCARTODBEscapeLiteral( )                        */
+/*                    OGRCARTOEscapeLiteral( )                        */
 /************************************************************************/
 
-CPLString OGRCARTODBEscapeLiteral(const char* pszStr)
+CPLString OGRCARTOEscapeLiteral(const char* pszStr)
 {
     CPLString osStr;
 
@@ -76,12 +75,12 @@ CPLString OGRCARTODBEscapeLiteral(const char* pszStr)
 }
 
 /************************************************************************/
-/*                        OGRCARTODBTableLayer()                        */
+/*                        OGRCARTOTableLayer()                        */
 /************************************************************************/
 
-OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDSIn,
+OGRCARTOTableLayer::OGRCARTOTableLayer(OGRCARTODataSource* poDSIn,
                                            const char* pszName) :
-                                           OGRCARTODBLayer(poDSIn)
+                                           OGRCARTOLayer(poDSIn)
 
 {
     osName = pszName;
@@ -91,27 +90,28 @@ OGRCARTODBTableLayer::OGRCARTODBTableLayer(OGRCARTODBDataSource* poDSIn,
     eDeferredInsertState = INSERT_UNINIT;
     nNextFID = -1;
     bDeferredCreation = FALSE;
-    bCartoDBify = FALSE;
-    nMaxChunkSize = atoi(CPLGetConfigOption("CARTODB_MAX_CHUNK_SIZE", "15")) * 1024 * 1024;
+    bCartodbfy = FALSE;
+    nMaxChunkSize = atoi(CPLGetConfigOption("CARTO_MAX_CHUNK_SIZE", 
+            CPLGetConfigOption("CARTODB_MAX_CHUNK_SIZE", "15"))) * 1024 * 1024;
 }
 
 /************************************************************************/
-/*                    ~OGRCARTODBTableLayer()                           */
+/*                    ~OGRCARTOTableLayer()                           */
 /************************************************************************/
 
-OGRCARTODBTableLayer::~OGRCARTODBTableLayer()
+OGRCARTOTableLayer::~OGRCARTOTableLayer()
 
 {
     if( bDeferredCreation ) RunDeferredCreationIfNecessary();
     CPL_IGNORE_RET_VAL(FlushDeferredInsert());
-    RunDeferredCartoDBfy();
+    RunDeferredCartofy();
 }
 
 /************************************************************************/
 /*                          GetLayerDefnInternal()                      */
 /************************************************************************/
 
-OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object* poObjIn)
+OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object* poObjIn)
 {
     if( poFeatureDefn != NULL )
         return poFeatureDefn;
@@ -142,14 +142,14 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
                                               "def.adnum = a.attnum "
                  "LEFT JOIN spatial_ref_sys srs ON srs.srid = postgis_typmod_srid(a.atttypmod) "
                  "ORDER BY a.attnum",
-                 OGRCARTODBEscapeLiteral(osName).c_str(),
-                 OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str());
+                 OGRCARTOEscapeLiteral(osName).c_str(),
+                 OGRCARTOEscapeLiteral(poDS->GetCurrentSchema()).c_str());
     }
     else if( poDS->HasOGRMetadataFunction() != FALSE )
     {
         osCommand.Printf( "SELECT * FROM ogr_table_metadata('%s', '%s')",
-                          OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
-                          OGRCARTODBEscapeLiteral(osName).c_str() );
+                          OGRCARTOEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
+                          OGRCARTOEscapeLiteral(osName).c_str() );
     }
 
     if( osCommand.size() )
@@ -162,12 +162,12 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
             CPLPopErrorHandler();
             if( poLyr == NULL )
             {
-                CPLDebug("CARTODB", "ogr_table_metadata(text, text) not available");
+                CPLDebug("CARTO", "ogr_table_metadata(text, text) not available");
                 CPLErrorReset();
             }
             else if( poLyr->GetLayerDefn()->GetFieldCount() != 12 )
             {
-                CPLDebug("CARTODB", "ogr_table_metadata(text, text) has unexpected column count");
+                CPLDebug("CARTO", "ogr_table_metadata(text, text) has unexpected column count");
                 poDS->ReleaseResultSet(poLyr);
                 poLyr = NULL;
             }
@@ -227,8 +227,8 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
                         OGRwkbGeometryType eType = OGRFromOGCGeomType(pszGeomType);
                         if( nDim == 3 )
                             eType = wkbSetZ(eType);
-                        OGRCartoDBGeomFieldDefn *poFieldDefn =
-                            new OGRCartoDBGeomFieldDefn(pszAttname, eType);
+                        OGRCartoGeomFieldDefn *poFieldDefn =
+                            new OGRCartoGeomFieldDefn(pszAttname, eType);
                         if( bNotNull )
                             poFieldDefn->SetNullable(FALSE);
                         OGRSpatialReference* l_poSRS = NULL;
@@ -271,7 +271,7 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
 
     if( poFeatureDefn == NULL )
     {
-        osBaseSQL.Printf("SELECT * FROM %s", OGRCARTODBEscapeIdentifier(osName).c_str());
+        osBaseSQL.Printf("SELECT * FROM %s", OGRCARTOEscapeIdentifier(osName).c_str());
         EstablishLayerDefn(osName, NULL);
         osBaseSQL = "";
     }
@@ -279,7 +279,7 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
     if( osFIDColName.size() > 0 )
     {
         osBaseSQL = "SELECT ";
-        osBaseSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
+        osBaseSQL += OGRCARTOEscapeIdentifier(osFIDColName);
     }
     for(int i=0; i<poFeatureDefn->GetGeomFieldCount(); i++)
     {
@@ -287,7 +287,7 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
             osBaseSQL = "SELECT ";
         else
             osBaseSQL += ", ";
-        osBaseSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+        osBaseSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
     }
     for(int i=0; i<poFeatureDefn->GetFieldCount(); i++)
     {
@@ -295,12 +295,12 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
             osBaseSQL = "SELECT ";
         else
             osBaseSQL += ", ";
-        osBaseSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        osBaseSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
     if( osBaseSQL.size() == 0 )
         osBaseSQL = "SELECT *";
     osBaseSQL += " FROM ";
-    osBaseSQL += OGRCARTODBEscapeIdentifier(osName);
+    osBaseSQL += OGRCARTOEscapeIdentifier(osName);
 
     osSELECTWithoutWHERE = osBaseSQL;
 
@@ -311,7 +311,7 @@ OGRFeatureDefn * OGRCARTODBTableLayer::GetLayerDefnInternal(CPL_UNUSED json_obje
 /*                        FetchNewFeatures()                            */
 /************************************************************************/
 
-json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNextIn)
+json_object* OGRCARTOTableLayer::FetchNewFeatures(GIntBig iNextIn)
 {
     if( osFIDColName.size() > 0 )
     {
@@ -319,34 +319,34 @@ json_object* OGRCARTODBTableLayer::FetchNewFeatures(GIntBig iNextIn)
         osSQL.Printf("%s WHERE %s%s >= " CPL_FRMT_GIB " ORDER BY %s ASC LIMIT %d",
                      osSELECTWithoutWHERE.c_str(),
                      ( osWHERE.size() ) ? CPLSPrintf("%s AND ", osWHERE.c_str()) : "",
-                     OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                     OGRCARTOEscapeIdentifier(osFIDColName).c_str(),
                      iNext,
-                     OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                     OGRCARTOEscapeIdentifier(osFIDColName).c_str(),
                      GetFeaturesToFetch());
         return poDS->RunSQL(osSQL);
     }
     else
-        return OGRCARTODBLayer::FetchNewFeatures(iNextIn);
+        return OGRCARTOLayer::FetchNewFeatures(iNextIn);
 }
 
 /************************************************************************/
 /*                           GetNextRawFeature()                        */
 /************************************************************************/
 
-OGRFeature  *OGRCARTODBTableLayer::GetNextRawFeature()
+OGRFeature  *OGRCARTOTableLayer::GetNextRawFeature()
 {
     if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return NULL;
     if( FlushDeferredInsert() != OGRERR_NONE )
         return NULL;
-    return OGRCARTODBLayer::GetNextRawFeature();
+    return OGRCARTOLayer::GetNextRawFeature();
 }
 
 /************************************************************************/
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::SetAttributeFilter( const char *pszQuery )
+OGRErr OGRCARTOTableLayer::SetAttributeFilter( const char *pszQuery )
 
 {
     GetLayerDefn();
@@ -371,7 +371,7 @@ OGRErr OGRCARTODBTableLayer::SetAttributeFilter( const char *pszQuery )
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
 
-void OGRCARTODBTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
+void OGRCARTOTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
 {
     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
@@ -395,25 +395,25 @@ void OGRCARTODBTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeo
 }
 
 /************************************************************************/
-/*                         RunDeferredCartoDBfy()                         */
+/*                         RunDeferredCartofy()                         */
 /************************************************************************/
 
 
-void OGRCARTODBTableLayer::RunDeferredCartoDBfy()
+void OGRCARTOTableLayer::RunDeferredCartofy()
 
 {
-    if( bCartoDBify )
+    if( bCartodbfy )
     {
-        bCartoDBify = FALSE;
+        bCartodbfy = FALSE;
 
         CPLString osSQL;
         if( poDS->GetCurrentSchema() == "public" )
             osSQL.Printf("SELECT cdb_cartodbfytable('%s')",
-                                OGRCARTODBEscapeLiteral(osName).c_str());
+                                OGRCARTOEscapeLiteral(osName).c_str());
         else
             osSQL.Printf("SELECT cdb_cartodbfytable('%s', '%s')",
-                                OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
-                                OGRCARTODBEscapeLiteral(osName).c_str());
+                                OGRCARTOEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
+                                OGRCARTOEscapeLiteral(osName).c_str());
 
         json_object* poObj = poDS->RunSQL(osSQL);
         if( poObj != NULL )
@@ -425,7 +425,7 @@ void OGRCARTODBTableLayer::RunDeferredCartoDBfy()
 /*                         FlushDeferredInsert()                         */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::FlushDeferredInsert(bool bReset)
+OGRErr OGRCARTOTableLayer::FlushDeferredInsert(bool bReset)
 
 {
     OGRErr eErr = OGRERR_NONE;
@@ -464,7 +464,7 @@ OGRErr OGRCARTODBTableLayer::FlushDeferredInsert(bool bReset)
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
+OGRErr OGRCARTOTableLayer::CreateField( OGRFieldDefn *poFieldIn,
                                           CPL_UNUSED int bApproxOK )
 {
     GetLayerDefn();
@@ -498,8 +498,8 @@ OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
     {
         CPLString osSQL;
         osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
-                    OGRCARTODBEscapeIdentifier(osName).c_str(),
-                    OGRCARTODBEscapeIdentifier(oField.GetNameRef()).c_str(),
+                    OGRCARTOEscapeIdentifier(osName).c_str(),
+                    OGRCARTOEscapeIdentifier(oField.GetNameRef()).c_str(),
                     OGRPGCommonLayerGetType(oField, FALSE, TRUE).c_str() );
         if( !oField.IsNullable() )
             osSQL += " NOT NULL";
@@ -524,7 +524,7 @@ OGRErr OGRCARTODBTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 /*                            DeleteField()                             */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::DeleteField( int iField )
+OGRErr OGRCARTOTableLayer::DeleteField( int iField )
 {
     CPLString           osSQL;
 
@@ -553,8 +553,8 @@ OGRErr OGRCARTODBTableLayer::DeleteField( int iField )
 /* -------------------------------------------------------------------- */
 
     osSQL.Printf( "ALTER TABLE %s DROP COLUMN %s",
-                  OGRCARTODBEscapeIdentifier(osName).c_str(),
-                  OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()).c_str() );
+                  OGRCARTOEscapeIdentifier(osName).c_str(),
+                  OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()).c_str() );
 
     json_object* poObj = poDS->RunSQL(osSQL);
     if( poObj == NULL )
@@ -568,7 +568,7 @@ OGRErr OGRCARTODBTableLayer::DeleteField( int iField )
 /*                           ICreateFeature()                            */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
+OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
     int i;
@@ -597,10 +597,10 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
     if( !bHasUserFieldMatchingFID && bInDeferredInsert && nNextFID < 0 && osFIDColName.size() )
     {
         osSQL.Printf("SELECT nextval('%s') AS nextid",
-                     OGRCARTODBEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
+                     OGRCARTOEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
 
         json_object* poObj = poDS->RunSQL(osSQL);
-        json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+        json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
         if( poRowObj != NULL )
         {
             json_object* poID = json_object_object_get(poRowObj, "nextid");
@@ -654,7 +654,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
     int bMustComma = FALSE;
     if( bWriteInsertInto )
     {
-        osSQL.Printf("INSERT INTO %s ", OGRCARTODBEscapeIdentifier(osName).c_str());
+        osSQL.Printf("INSERT INTO %s ", OGRCARTOEscapeIdentifier(osName).c_str());
         for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
         {
             if( eDeferredInsertState != INSERT_MULTIPLE_FEATURE &&
@@ -669,7 +669,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
                 bMustComma = TRUE;
             }
 
-            osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+            osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
         }
 
         for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
@@ -686,7 +686,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
                 bMustComma = TRUE;
             }
 
-            osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+            osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
         }
 
         if( !bHasUserFieldMatchingFID &&
@@ -700,7 +700,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
                 bMustComma = TRUE;
             }
 
-            osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
+            osSQL += OGRCARTOEscapeIdentifier(osFIDColName);
         }
 
         if( !bMustComma && eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
@@ -741,7 +741,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
             if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
             {
                 osSQL += "'";
-                osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
+                osSQL += OGRCARTOEscapeLiteral(poFeature->GetFieldAsString(i));
                 osSQL += "'";
             }
             else if( (eType == OFTInteger || eType == OFTInteger64) &&
@@ -774,8 +774,8 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
             else
                 bMustComma = TRUE;
 
-            OGRCartoDBGeomFieldDefn* poGeomFieldDefn =
-                (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
+            OGRCartoGeomFieldDefn* poGeomFieldDefn =
+                (OGRCartoGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
             int nSRID = poGeomFieldDefn->nSRID;
             if( nSRID == 0 )
                 nSRID = 4326;
@@ -863,10 +863,10 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
     if( osFIDColName.size() )
     {
         osSQL += " RETURNING ";
-        osSQL += OGRCARTODBEscapeIdentifier(osFIDColName);
+        osSQL += OGRCARTOEscapeIdentifier(osFIDColName);
 
         json_object* poObj = poDS->RunSQL(osSQL);
-        json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+        json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
         if( poRowObj == NULL )
         {
             if( poObj != NULL )
@@ -911,7 +911,7 @@ OGRErr OGRCARTODBTableLayer::ICreateFeature( OGRFeature *poFeature )
 /*                            ISetFeature()                              */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
+OGRErr OGRCARTOTableLayer::ISetFeature( OGRFeature *poFeature )
 
 {
     if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -936,7 +936,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
     }
 
     CPLString osSQL;
-    osSQL.Printf("UPDATE %s SET ", OGRCARTODBEscapeIdentifier(osName).c_str());
+    osSQL.Printf("UPDATE %s SET ", OGRCARTOEscapeIdentifier(osName).c_str());
     int bMustComma = FALSE;
     for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
@@ -945,7 +945,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
         else
             bMustComma = TRUE;
 
-        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
         osSQL += " = ";
 
         if( !poFeature->IsFieldSet(i) )
@@ -958,7 +958,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
             if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
             {
                 osSQL += "'";
-                osSQL += OGRCARTODBEscapeLiteral(poFeature->GetFieldAsString(i));
+                osSQL += OGRCARTOEscapeLiteral(poFeature->GetFieldAsString(i));
                 osSQL += "'";
             }
             else if( (eType == OFTInteger || eType == OFTInteger64) &&
@@ -978,7 +978,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
         else
             bMustComma = TRUE;
 
-        osSQL += OGRCARTODBEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
+        osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
         osSQL += " = ";
 
         OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
@@ -988,8 +988,8 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
         }
         else
         {
-            OGRCartoDBGeomFieldDefn* poGeomFieldDefn =
-                (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
+            OGRCartoGeomFieldDefn* poGeomFieldDefn =
+                (OGRCartoGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
             int nSRID = poGeomFieldDefn->nSRID;
             if( nSRID == 0 )
                 nSRID = 4326;
@@ -1004,7 +1004,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
     }
 
     osSQL += CPLSPrintf(" WHERE %s = " CPL_FRMT_GIB,
-                    OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                    OGRCARTOEscapeIdentifier(osFIDColName).c_str(),
                     poFeature->GetFID());
 
     OGRErr eRet = OGRERR_FAILURE;
@@ -1032,7 +1032,7 @@ OGRErr OGRCARTODBTableLayer::ISetFeature( OGRFeature *poFeature )
 /*                          DeleteFeature()                             */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::DeleteFeature( GIntBig nFID )
+OGRErr OGRCARTOTableLayer::DeleteFeature( GIntBig nFID )
 
 {
 
@@ -1055,8 +1055,8 @@ OGRErr OGRCARTODBTableLayer::DeleteFeature( GIntBig nFID )
 
     CPLString osSQL;
     osSQL.Printf("DELETE FROM %s WHERE %s = " CPL_FRMT_GIB,
-                    OGRCARTODBEscapeIdentifier(osName).c_str(),
-                    OGRCARTODBEscapeIdentifier(osFIDColName).c_str(),
+                    OGRCARTOEscapeIdentifier(osName).c_str(),
+                    OGRCARTOEscapeIdentifier(osFIDColName).c_str(),
                     nFID);
 
     OGRErr eRet = OGRERR_FAILURE;
@@ -1084,15 +1084,15 @@ OGRErr OGRCARTODBTableLayer::DeleteFeature( GIntBig nFID )
 /*                             GetSRS_SQL()                             */
 /************************************************************************/
 
-CPLString OGRCARTODBTableLayer::GetSRS_SQL(const char* pszGeomCol)
+CPLString OGRCARTOTableLayer::GetSRS_SQL(const char* pszGeomCol)
 {
     CPLString osSQL;
 
     osSQL.Printf("SELECT srid, srtext FROM spatial_ref_sys WHERE srid IN "
                 "(SELECT Find_SRID('%s', '%s', '%s'))",
-                OGRCARTODBEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
-                OGRCARTODBEscapeLiteral(osName).c_str(),
-                OGRCARTODBEscapeLiteral(pszGeomCol).c_str());
+                OGRCARTOEscapeLiteral(poDS->GetCurrentSchema()).c_str(),
+                OGRCARTOEscapeLiteral(osName).c_str(),
+                OGRCARTOEscapeLiteral(pszGeomCol).c_str());
 
     return osSQL;
 }
@@ -1104,7 +1104,7 @@ CPLString OGRCARTODBTableLayer::GetSRS_SQL(const char* pszGeomCol)
 /*      criteria (spatial and attribute queries).                       */
 /************************************************************************/
 
-void OGRCARTODBTableLayer::BuildWhere()
+void OGRCARTOTableLayer::BuildWhere()
 
 {
     osWHERE = "";
@@ -1130,7 +1130,7 @@ void OGRCARTODBTableLayer::BuildWhere()
         while((pszComma = strchr(szBox3D_2, ',')) != NULL)
             *pszComma = '.';
         osWHERE.Printf("(%s && 'BOX3D(%s, %s)'::box3d)",
-                       OGRCARTODBEscapeIdentifier(osGeomColumn).c_str(),
+                       OGRCARTOEscapeIdentifier(osGeomColumn).c_str(),
                        szBox3D_1, szBox3D_2 );
     }
 
@@ -1156,7 +1156,7 @@ void OGRCARTODBTableLayer::BuildWhere()
 /*                              GetFeature()                            */
 /************************************************************************/
 
-OGRFeature* OGRCARTODBTableLayer::GetFeature( GIntBig nFeatureId )
+OGRFeature* OGRCARTOTableLayer::GetFeature( GIntBig nFeatureId )
 {
 
     if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -1167,21 +1167,21 @@ OGRFeature* OGRCARTODBTableLayer::GetFeature( GIntBig nFeatureId )
     GetLayerDefn();
 
     if( osFIDColName.size() == 0 )
-        return OGRCARTODBLayer::GetFeature(nFeatureId);
+        return OGRCARTOLayer::GetFeature(nFeatureId);
 
     CPLString osSQL = osSELECTWithoutWHERE;
     osSQL += " WHERE ";
-    osSQL += OGRCARTODBEscapeIdentifier(osFIDColName).c_str();
+    osSQL += OGRCARTOEscapeIdentifier(osFIDColName).c_str();
     osSQL += " = ";
     osSQL += CPLSPrintf(CPL_FRMT_GIB, nFeatureId);
 
     json_object* poObj = poDS->RunSQL(osSQL);
-    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
     if( poRowObj == NULL )
     {
         if( poObj != NULL )
             json_object_put(poObj);
-        return OGRCARTODBLayer::GetFeature(nFeatureId);
+        return OGRCARTOLayer::GetFeature(nFeatureId);
     }
 
     OGRFeature* poFeature = BuildFeature(poRowObj);
@@ -1194,7 +1194,7 @@ OGRFeature* OGRCARTODBTableLayer::GetFeature( GIntBig nFeatureId )
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
-GIntBig OGRCARTODBTableLayer::GetFeatureCount(int bForce)
+GIntBig OGRCARTOTableLayer::GetFeatureCount(int bForce)
 {
 
     if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -1205,7 +1205,7 @@ GIntBig OGRCARTODBTableLayer::GetFeatureCount(int bForce)
     GetLayerDefn();
 
     CPLString osSQL(CPLSPrintf("SELECT COUNT(*) FROM %s",
-                               OGRCARTODBEscapeIdentifier(osName).c_str()));
+                               OGRCARTOEscapeIdentifier(osName).c_str()));
     if( osWHERE.size() )
     {
         osSQL += " WHERE ";
@@ -1213,19 +1213,19 @@ GIntBig OGRCARTODBTableLayer::GetFeatureCount(int bForce)
     }
 
     json_object* poObj = poDS->RunSQL(osSQL);
-    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
     if( poRowObj == NULL )
     {
         if( poObj != NULL )
             json_object_put(poObj);
-        return OGRCARTODBLayer::GetFeatureCount(bForce);
+        return OGRCARTOLayer::GetFeatureCount(bForce);
     }
 
     json_object* poCount = json_object_object_get(poRowObj, "count");
     if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
     {
         json_object_put(poObj);
-        return OGRCARTODBLayer::GetFeatureCount(bForce);
+        return OGRCARTOLayer::GetFeatureCount(bForce);
     }
 
     GIntBig nRet = (GIntBig)json_object_get_int64(poCount);
@@ -1242,7 +1242,7 @@ GIntBig OGRCARTODBTableLayer::GetFeatureCount(int bForce)
 /*      in other cases we use standard OGRLayer::GetExtent()            */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
+OGRErr OGRCARTOTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce )
 {
     CPLString   osSQL;
 
@@ -1267,11 +1267,11 @@ OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, i
 
     /* Do not take the spatial filter into account */
     osSQL.Printf( "SELECT ST_Extent(%s) FROM %s",
-                  OGRCARTODBEscapeIdentifier(poGeomFieldDefn->GetNameRef()).c_str(),
-                  OGRCARTODBEscapeIdentifier(osName).c_str());
+                  OGRCARTOEscapeIdentifier(poGeomFieldDefn->GetNameRef()).c_str(),
+                  OGRCARTOEscapeIdentifier(osName).c_str());
 
     json_object* poObj = poDS->RunSQL(osSQL);
-    json_object* poRowObj = OGRCARTODBGetSingleRow(poObj);
+    json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
     if( poRowObj != NULL )
     {
         json_object* poExtent = json_object_object_get(poRowObj, "st_extent");
@@ -1342,7 +1342,7 @@ OGRErr OGRCARTODBTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, i
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRCARTODBTableLayer::TestCapability( const char * pszCap )
+int OGRCARTOTableLayer::TestCapability( const char * pszCap )
 
 {
     if( EQUAL(pszCap, OLCFastFeatureCount) )
@@ -1364,22 +1364,22 @@ int OGRCARTODBTableLayer::TestCapability( const char * pszCap )
         return poDS->IsReadWrite();
     }
 
-    return OGRCARTODBLayer::TestCapability(pszCap);
+    return OGRCARTOLayer::TestCapability(pszCap);
 }
 
 /************************************************************************/
 /*                        SetDeferredCreation()                          */
 /************************************************************************/
 
-void OGRCARTODBTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
+void OGRCARTOTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
                                                OGRSpatialReference* poSRSIn,
                                                int bGeomNullable,
-                                               int bCartoDBifyIn)
+                                               int bCartodbfyIn)
 {
     bDeferredCreation = TRUE;
     nNextFID = 1;
     CPLAssert(poFeatureDefn == NULL);
-    this->bCartoDBify = bCartoDBifyIn;
+    this->bCartodbfy = bCartodbfyIn;
     poFeatureDefn = new OGRFeatureDefn(osName);
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(wkbNone);
@@ -1389,8 +1389,8 @@ void OGRCARTODBTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
         eGType = wkbMultiPolygon25D;
     if( eGType != wkbNone )
     {
-        OGRCartoDBGeomFieldDefn *poFieldDefn =
-            new OGRCartoDBGeomFieldDefn("the_geom", eGType);
+        OGRCartoGeomFieldDefn *poFieldDefn =
+            new OGRCartoGeomFieldDefn("the_geom", eGType);
         poFieldDefn->SetNullable(bGeomNullable);
         poFeatureDefn->AddGeomFieldDefn(poFieldDefn, FALSE);
         if( poSRSIn != NULL )
@@ -1402,7 +1402,7 @@ void OGRCARTODBTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
     }
     osFIDColName = "cartodb_id";
     osBaseSQL.Printf("SELECT * FROM %s",
-                     OGRCARTODBEscapeIdentifier(osName).c_str());
+                     OGRCARTOEscapeIdentifier(osName).c_str());
     osSELECTWithoutWHERE = osBaseSQL;
 }
 
@@ -1410,7 +1410,7 @@ void OGRCARTODBTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
 /*                      RunDeferredCreationIfNecessary()                 */
 /************************************************************************/
 
-OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
+OGRErr OGRCARTOTableLayer::RunDeferredCreationIfNecessary()
 {
     if( !bDeferredCreation )
         return OGRERR_NONE;
@@ -1418,7 +1418,7 @@ OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
 
     CPLString osSQL;
     osSQL.Printf("CREATE TABLE %s ( %s SERIAL,",
-                 OGRCARTODBEscapeIdentifier(osName).c_str(),
+                 OGRCARTOEscapeIdentifier(osName).c_str(),
                  osFIDColName.c_str());
 
     int nSRID = 0;
@@ -1429,8 +1429,8 @@ OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
         if( wkbHasZ(eGType) )
             osGeomType += "Z";
 
-        OGRCartoDBGeomFieldDefn *poFieldDefn =
-            (OGRCartoDBGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(0);
+        OGRCartoGeomFieldDefn *poFieldDefn =
+            (OGRCartoGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(0);
         nSRID = poFieldDefn->nSRID;
 
         osSQL += CPLSPrintf("%s GEOMETRY(%s, %d)%s,",
@@ -1445,7 +1445,7 @@ OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
         if( strcmp(poFieldDefn->GetNameRef(), osFIDColName) != 0 )
         {
-            osSQL += OGRCARTODBEscapeIdentifier(poFieldDefn->GetNameRef());
+            osSQL += OGRCARTOEscapeIdentifier(poFieldDefn->GetNameRef());
             osSQL += " ";
             osSQL += OGRPGCommonLayerGetType(*poFieldDefn, FALSE, TRUE);
             if( !poFieldDefn->IsNullable() )
@@ -1461,7 +1461,7 @@ OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
 
     osSQL += CPLSPrintf("PRIMARY KEY (%s) )", osFIDColName.c_str());
 
-    CPLString osSeqName(OGRCARTODBEscapeIdentifier(CPLSPrintf("%s_%s_seq",
+    CPLString osSeqName(OGRCARTOEscapeIdentifier(CPLSPrintf("%s_%s_seq",
                                 osName.c_str(), osFIDColName.c_str())));
 
     osSQL += ";";
@@ -1470,10 +1470,10 @@ OGRErr OGRCARTODBTableLayer::RunDeferredCreationIfNecessary()
     osSQL += CPLSPrintf("CREATE SEQUENCE %s START 1", osSeqName.c_str());
     osSQL += ";";
     osSQL += CPLSPrintf("ALTER SEQUENCE %s OWNED BY %s.%s", osSeqName.c_str(),
-                        OGRCARTODBEscapeIdentifier(osName).c_str(), osFIDColName.c_str());
+                        OGRCARTOEscapeIdentifier(osName).c_str(), osFIDColName.c_str());
     osSQL += ";";
     osSQL += CPLSPrintf("ALTER TABLE %s ALTER COLUMN %s SET DEFAULT nextval('%s')",
-                        OGRCARTODBEscapeIdentifier(osName).c_str(),
+                        OGRCARTOEscapeIdentifier(osName).c_str(),
                         osFIDColName.c_str(), osSeqName.c_str());
 
     json_object* poObj = poDS->RunSQL(osSQL);
diff --git a/ogr/ogrsf_frmts/csv/drv_csv.html b/ogr/ogrsf_frmts/csv/drv_csv.html
index 977e356..804ebb9 100644
--- a/ogr/ogrsf_frmts/csv/drv_csv.html
+++ b/ogr/ogrsf_frmts/csv/drv_csv.html
@@ -327,7 +327,7 @@ The CSV driver can also read files whose structure is close to CSV files :
 <li>Initial development of the OGR CSV driver was supported by
 <a href="http://www.dmsolutions.ca/">DM Solutions Group</a> and
 <a href="http://www.gomoos.org/">GoMOOS</a>.
-<li><a href="https://cartodb.com/">CartoDB</a> funded field type auto-detection and open options related to geometry columns.</li>
+<li><a href="https://carto.com/">Carto</a> funded field type auto-detection and open options related to geometry columns.</li>
 </ul>
 </p>
 
diff --git a/ogr/ogrsf_frmts/generic/GNUmakefile b/ogr/ogrsf_frmts/generic/GNUmakefile
index 6d0a865..a226112 100644
--- a/ogr/ogrsf_frmts/generic/GNUmakefile
+++ b/ogr/ogrsf_frmts/generic/GNUmakefile
@@ -203,7 +203,7 @@ CXXFLAGS :=	$(CXXFLAGS) -DWALK_ENABLED
 endif
 
 ifeq ($(CURL_SETTING),yes)
-CXXFLAGS :=	$(CXXFLAGS) -DCARTODB_ENABLED
+CXXFLAGS :=	$(CXXFLAGS) -DCARTO_ENABLED
 endif
 
 ifeq ($(CURL_SETTING),yes)
diff --git a/ogr/ogrsf_frmts/generic/makefile.vc b/ogr/ogrsf_frmts/generic/makefile.vc
index 2a188b3..86beef8 100644
--- a/ogr/ogrsf_frmts/generic/makefile.vc
+++ b/ogr/ogrsf_frmts/generic/makefile.vc
@@ -20,7 +20,7 @@ EXTRAFLAGS =	-I.. -I..\.. $(OGDIDEF) $(FMEDEF) $(OCIDEF) $(PGDEF) \
 		$(SDEDEF) $(BASEFORMATS) $(IDBDEF) $(NASDEF) $(DODSDEF) \
 		$(LIBKMLDEF) $(WFSDEF) $(SOSIDEF) $(GFTDEF) \
 		$(COUCHDBDEF) $(CLOUDANTDEF) $(FGDBDEF) $(XLSDEF) $(ODSDEF) $(XLSXDEF) $(INGRESDEF) \
-		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODBDEF) $(AMIGOCLOUDDEF) $(PLSCENESDEF) $(CSWDEF) $(MONGODBDEF)
+		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODEF) $(AMIGOCLOUDDEF) $(PLSCENESDEF) $(CSWDEF) $(MONGODBDEF)
 
 !IFDEF OGDIDIR
 OGDIDEF	=	-DOGDI_ENABLED
@@ -143,7 +143,7 @@ VFKDEF	=	-DVFK_ENABLED
 !ENDIF
 
 !IFDEF CURL_LIB
-CARTODBDEF = -DCARTODB_ENABLED
+CARTODEF = -DCARTO_ENABLED
 !ENDIF
 
 !IFDEF CURL_LIB
diff --git a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
index f97f8a0..0e64e2a 100644
--- a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrregisterall.cpp 32427 2015-12-22 11:18:32Z rouault $
+ * $Id: ogrregisterall.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Function to register all known OGR drivers.
@@ -30,7 +30,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrregisterall.cpp 32427 2015-12-22 11:18:32Z rouault $");
+CPL_CVSID("$Id: ogrregisterall.cpp 34979 2016-08-08 09:30:34Z rouault $");
 
 /************************************************************************/
 /*                           OGRRegisterAll()                           */
@@ -261,8 +261,8 @@ void OGRRegisterAllInternal()
 #ifdef WALK_ENABLED
     RegisterOGRWalk();
 #endif
-#ifdef CARTODB_ENABLED
-    RegisterOGRCartoDB();
+#ifdef CARTO_ENABLED
+    RegisterOGRCarto();
 #endif
 #ifdef AMIGOCLOUD_ENABLED
     RegisterOGRAmigoCloud();
diff --git a/ogr/ogrsf_frmts/gml/drv_gml.html b/ogr/ogrsf_frmts/gml/drv_gml.html
index de85634..294da72 100644
--- a/ogr/ogrsf_frmts/gml/drv_gml.html
+++ b/ogr/ogrsf_frmts/gml/drv_gml.html
@@ -39,7 +39,8 @@ configuration option to <b>EXPAT</b> or <b>XERCES</b>.<p>
 
 Since OGR 1.8.0, the GML driver has coordinate system support. This is
 only reported when all the geometries of a layer have a srsName attribute,
-whose value is the same for all geometries. For srsName such as "urn:ogc:def:crs:EPSG:",
+whose value is the same for all geometries. For srsName such as "urn:ogc:def:crs:EPSG:"
+(or "http://www.opengis.net/def/crs/EPSG/0/" starting with GDAL 2.1.2),
 for geographic coordinate systems (as returned by WFS 1.1.0 for example), the axis order
 should be (latitude, longitude) as required by the standards, but this is
 unusual and can cause issues with applications unaware of axis order. So
@@ -56,6 +57,14 @@ order. However, if you set the configuration option <b>GML_CONSIDER_EPSG_AS_URN<
 <b>YES</b>, the rules explained in the previous paragraph will be applied.<p>
 Since OGR 1.10, the above also applied for projected coordinate systems whose EPSG
 preferred axis order is (northing, easting).<p>
+<p>Starting with GDAL 2.1.2, the SWAP_COORDINATES open option (or GML_SWAP_COORDINATES
+configuration option) can be set to AUTO/YES/NO. It controls whether the order of the x/y or long/lat
+coordinates should be swapped. In AUTO mode, the driver will determine if swapping
+must be done from the srsName and value of other options
+like CONSIDER_EPSG_AS_URN and INVERT_AXIS_ORDER_IF_LAT_LONG. When SWAP_COORDINATES
+is set to YES, coordinates will be always swapped regarding the order they appear
+in the GML, and when it set to NO, they will be kept in the same order. The default
+is AUTO.</p>
 
 <h2>Schema</h2>
 
@@ -374,6 +383,13 @@ and if it has no valid associated .xsd. Defaults to NO.</li>
 present SRS and coordinate ordering in traditional GIS order. Defaults to YES.</li>
 <li> <b>CONSIDER_EPSG_AS_URN=YES/NO/AUTO</b>: (GDAL >=2.0) Whether to
 consider srsName like EPSG:XXXX as respecting EPSG axis order. Defaults to AUTO.</li>
+<li> <b>SWAP_COORDINATES</b>=AUTO/YES/NO: (GDAL >=2.1.2) Whether the order of the x/y or long/lat
+coordinates should be swapped. In AUTO mode, the driver will determine if swapping
+must be done from the srsName and value of other options
+like CONSIDER_EPSG_AS_URN and INVERT_AXIS_ORDER_IF_LAT_LONG. When SWAP_COORDINATES
+is set to YES, coordinates will be always swapped regarding the order they appear
+in the GML, and when it set to NO, they will be kept in the same order. The default
+is AUTO.</li>
 <li> <b>READ_MODE=AUTO/STANDARD/SEQUENTIAL_LAYERS/INTERLEAVED_LAYERS</b>: (GDAL >=2.0)
 Read mode. Defaults to AUTO.</li>
 <li> <b>EXPOSE_GML_ID=YES/NO/AUTO</b>: (GDAL >=2.0)
diff --git a/ogr/ogrsf_frmts/gml/gmlhandler.cpp b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
index 08c0661..1c1cd1c 100644
--- a/ogr/ogrsf_frmts/gml/gmlhandler.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: gmlhandler.cpp 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlhandler.cpp 34706 2016-07-18 21:08:52Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLHandler class.
@@ -542,6 +542,9 @@ GMLHandler::GMLHandler( GMLReader *poReader )
 
     nStackDepth = 0;
     stateStack[0] = STATE_TOP;
+
+    m_nSRSDimensionIfMissing = atoi(
+                    CPLGetConfigOption("GML_SRS_DIMENSION_IF_MISSING", "0") );
 }
 
 /************************************************************************/
@@ -696,12 +699,12 @@ OGRErr GMLHandler::startElementGeometry(const char *pszName, int nLenName, void*
     /* Some CityGML lack a srsDimension="3" in posList, such as in */
     /* http://www.citygml.org/fileadmin/count.php?f=fileadmin%2Fcitygml%2Fdocs%2FFrankfurt_Street_Setting_LOD3.zip */
     /* So we have to add it manually */
-    if (eAppSchemaType == APPSCHEMA_CITYGML && nLenName == 7 &&
-        strcmp(pszName, "posList") == 0 &&
-        CPLGetXMLValue(psCurNode, "srsDimension", NULL) == NULL)
+    if (strcmp(pszName, "posList") == 0 &&
+        CPLGetXMLValue(psCurNode, "srsDimension", NULL) == NULL &&
+        m_nSRSDimensionIfMissing != 0 )
     {
         CPLXMLNode* psChild = CPLCreateXMLNode(NULL, CXT_Attribute, "srsDimension");
-        CPLCreateXMLNode(psChild, CXT_Text, "3");
+        CPLCreateXMLNode(psChild, CXT_Text, (m_nSRSDimensionIfMissing == 3) ? "3" : "2");
 
         if (psLastChildCurNode == NULL)
             psCurNode->psChild = psChild;
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index 0651a84..fa34b47 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.cpp 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlreader.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader class.
@@ -66,6 +66,7 @@ IGMLReader::~IGMLReader()
 IGMLReader *CreateGMLReader(bool /*bUseExpatParserPreferably*/,
                             bool /*bInvertAxisOrderIfLatLong*/,
                             bool /*bConsiderEPSGAsURN*/,
+                            GMLSwapCoordinatesEnum /* eSwapCoordinates */,
                             bool /*bGetSecondaryGeometryOption*/)
 {
     CPLError( CE_Failure, CPLE_AppDefined,
@@ -88,12 +89,14 @@ IGMLReader *CreateGMLReader(bool /*bUseExpatParserPreferably*/,
 IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
                             bool bInvertAxisOrderIfLatLong,
                             bool bConsiderEPSGAsURN,
+                            GMLSwapCoordinatesEnum eSwapCoordinates,
                             bool bGetSecondaryGeometryOption)
 
 {
     return new GMLReader(bUseExpatParserPreferably,
                          bInvertAxisOrderIfLatLong,
                          bConsiderEPSGAsURN,
+                         eSwapCoordinates,
                          bGetSecondaryGeometryOption);
 }
 
@@ -114,6 +117,7 @@ CPL_UNUSED
                      bool bUseExpatParserPreferably,
                      bool bInvertAxisOrderIfLatLong,
                      bool bConsiderEPSGAsURN,
+                     GMLSwapCoordinatesEnum eSwapCoordinates,
                      bool bGetSecondaryGeometryOption)
 {
 #ifndef HAVE_XERCES
@@ -169,6 +173,7 @@ CPL_UNUSED
 
     m_bInvertAxisOrderIfLatLong = bInvertAxisOrderIfLatLong;
     m_bConsiderEPSGAsURN = bConsiderEPSGAsURN;
+    m_eSwapCoordinates = eSwapCoordinates;
     m_bGetSecondaryGeometryOption = bGetSecondaryGeometryOption;
 
     m_pszGlobalSRSName = NULL;
@@ -1417,7 +1422,9 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
         {
             OGRGeometry *poGeometry = GML_BuildOGRGeometryFromList(
                 papsGeometry, true, m_bInvertAxisOrderIfLatLong,
-                NULL, m_bConsiderEPSGAsURN, m_bGetSecondaryGeometryOption,
+                NULL, m_bConsiderEPSGAsURN,
+                m_eSwapCoordinates,
+                m_bGetSecondaryGeometryOption,
                 hCacheSRS, m_bFaceHoleNegative );
 
             if( poGeometry != NULL && poClass->GetGeometryPropertyCount() > 0 )
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.h b/ogr/ogrsf_frmts/gml/gmlreader.h
index ea96e07..e229ff0 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.h 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlreader.h 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Public Declarations for OGR free GML Reader code.
@@ -34,6 +34,7 @@
 #include "cpl_port.h"
 #include "cpl_vsi.h"
 #include "cpl_minixml.h"
+#include "gmlutils.h"
 
 #include <vector>
 
@@ -322,6 +323,7 @@ public:
 IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
                             bool bInvertAxisOrderIfLatLong,
                             bool bConsiderEPSGAsURN,
+                            GMLSwapCoordinatesEnum eSwapCoordinates,
                             bool bGetSecondaryGeometryOption);
 
 
diff --git a/ogr/ogrsf_frmts/gml/gmlreaderp.h b/ogr/ogrsf_frmts/gml/gmlreaderp.h
index bd731d9..2ab068f 100644
--- a/ogr/ogrsf_frmts/gml/gmlreaderp.h
+++ b/ogr/ogrsf_frmts/gml/gmlreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreaderp.h 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlreaderp.h 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Private Declarations for OGR free GML Reader code.
@@ -41,6 +41,7 @@
 #include "ogr_api.h"
 #include "cpl_vsi.h"
 #include "cpl_multiproc.h"
+#include "gmlutils.h"
 
 #include <string>
 #include <vector>
@@ -146,6 +147,8 @@ class GMLHandler
 
     std::vector<NodeLastChild> apsXMLNode;
 
+    int        m_nSRSDimensionIfMissing;
+
     OGRErr     startElementTop(const char *pszName, int nLenName, void* attr);
 
     OGRErr     endElementIgnoredFeature();
@@ -429,6 +432,7 @@ private:
 
     bool          m_bInvertAxisOrderIfLatLong;
     bool          m_bConsiderEPSGAsURN;
+    GMLSwapCoordinatesEnum m_eSwapCoordinates;
     bool          m_bGetSecondaryGeometryOption;
 
     int           ParseFeatureType(CPLXMLNode *psSchemaNode,
@@ -461,7 +465,9 @@ private:
 
 public:
                 GMLReader(bool bExpatReader, bool bInvertAxisOrderIfLatLong,
-                          bool bConsiderEPSGAsURN, bool bGetSecondaryGeometryOption);
+                          bool bConsiderEPSGAsURN,
+                          GMLSwapCoordinatesEnum eSwapCoordinates,
+                          bool bGetSecondaryGeometryOption);
     virtual     ~GMLReader();
 
     bool             IsClassListLocked() const { return m_bClassListLocked; }
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.cpp b/ogr/ogrsf_frmts/gml/gmlutils.cpp
index e392311..9a2158b 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlutils.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.cpp 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlutils.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -83,24 +83,25 @@ bool GML_IsSRSLatLongOrder(const char* pszSRSName)
     if (pszSRSName == NULL)
         return false;
 
-    if (STARTS_WITH(pszSRSName, "urn:"))
+    if (STARTS_WITH(pszSRSName, "urn:") && strstr(pszSRSName, ":4326") != NULL)
     {
-        if (strstr(pszSRSName, ":4326") != NULL)
+        /* Shortcut ... */
+        return true;
+    }
+    else if( !EQUALN(pszSRSName, "EPSG:", 5) )
+    {
+        OGRSpatialReference oSRS;
+        if (oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
         {
-            /* Shortcut ... */
-            return true;
-        }
-        else
-        {
-            OGRSpatialReference oSRS;
-            if (oSRS.importFromURN(pszSRSName) == OGRERR_NONE)
-            {
-                if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
-                    return true;
-            }
+            if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
+                return true;
         }
+        return false;
+    }
+    else
+    {
+        return false;
     }
-    return false;
 }
 
 
@@ -189,6 +190,7 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                                           bool bInvertAxisOrderIfLatLong,
                                           const char* pszDefaultSRSName,
                                           bool bConsiderEPSGAsURN,
+                                          GMLSwapCoordinatesEnum eSwapCoordinates,
                                           int nPseudoBoolGetSecondaryGeometryOption,
                                           void* hCacheSRS,
                                           bool bFaceHoleNegative)
@@ -247,6 +249,7 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                                                             bInvertAxisOrderIfLatLong,
                                                             pszDefaultSRSName,
                                                             bConsiderEPSGAsURN,
+                                                            eSwapCoordinates,
                                                             nPseudoBoolGetSecondaryGeometryOption,
                                                             hCacheSRS);
                     }
@@ -280,8 +283,12 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
         SRSCache* poSRSCache = (SRSCache*)hCacheSRS;
         SRSDesc& oSRSDesc = poSRSCache->Get(pszNameLookup);
         poGeom->assignSpatialReference(oSRSDesc.poSRS);
-        if (oSRSDesc.bAxisInvert && bInvertAxisOrderIfLatLong)
+        if( (eSwapCoordinates == GML_SWAP_AUTO &&
+            oSRSDesc.bAxisInvert && bInvertAxisOrderIfLatLong) ||
+            eSwapCoordinates == GML_SWAP_YES )
+        {
             poGeom->swapXY();
+        }
     }
 
     return poGeom;
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.h b/ogr/ogrsf_frmts/gml/gmlutils.h
index e799483..3ea61a6 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.h
+++ b/ogr/ogrsf_frmts/gml/gmlutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.h 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlutils.h 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -36,6 +36,13 @@
 
 #include "ogr_geometry.h"
 
+typedef enum
+{
+    GML_SWAP_AUTO,
+    GML_SWAP_YES,
+    GML_SWAP_NO,
+} GMLSwapCoordinatesEnum;
+
 const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
                                      std::string& osWork,
                                      bool bConsiderEPSGAsURN);
@@ -50,6 +57,7 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                                           bool bInvertAxisOrderIfLatLong,
                                           const char* pszDefaultSRSName,
                                           bool bConsiderEPSGAsURN,
+                                          GMLSwapCoordinatesEnum eSwapCoordinates,
                                           int nPseudoBoolGetSecondaryGeometryOption,
                                           void* hCacheSRS,
                                           bool bFaceHoleNegative = false );
diff --git a/ogr/ogrsf_frmts/gml/ogr_gml.h b/ogr/ogrsf_frmts/gml/ogr_gml.h
index aa252d9..bd0aaed 100644
--- a/ogr/ogrsf_frmts/gml/ogr_gml.h
+++ b/ogr/ogrsf_frmts/gml/ogr_gml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gml.h 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: ogr_gml.h 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Declarations for OGR wrapper classes for GML, and GML<->OGR
@@ -34,6 +34,7 @@
 
 #include "ogrsf_frmts.h"
 #include "gmlreader.h"
+#include "gmlutils.h"
 
 class OGRGMLDataSource;
 
@@ -147,6 +148,7 @@ class OGRGMLDataSource : public OGRDataSource
 
     bool                m_bInvertAxisOrderIfLatLong;
     bool                m_bConsiderEPSGAsURN;
+    GMLSwapCoordinatesEnum m_eSwapCoordinates;
     bool                m_bGetSecondaryGeometryOption;
 
     ReadMode            eReadMode;
@@ -199,6 +201,7 @@ class OGRGMLDataSource : public OGRDataSource
 
     bool                GetInvertAxisOrderIfLatLong() const { return m_bInvertAxisOrderIfLatLong; }
     bool                GetConsiderEPSGAsURN() const { return m_bConsiderEPSGAsURN; }
+    GMLSwapCoordinatesEnum GetSwapCoordinates() const { return m_eSwapCoordinates; }
     bool                GetSecondaryGeometryOption() const { return m_bGetSecondaryGeometryOption; }
 
     ReadMode            GetReadMode() const { return eReadMode; }
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
index 9932107..5b742e3 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldatasource.cpp 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: ogrgmldatasource.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLDataSource class.
@@ -47,7 +47,7 @@
 
 #include <vector>
 
-CPL_CVSID("$Id: ogrgmldatasource.cpp 33702 2016-03-11 06:20:16Z goatbar $");
+CPL_CVSID("$Id: ogrgmldatasource.cpp 35690 2016-10-11 09:56:31Z rouault $");
 
 static bool ExtractSRSName(const char* pszXML, char* szSRSName,
                            size_t sizeof_szSRSName);
@@ -116,6 +116,7 @@ OGRGMLDataSource::OGRGMLDataSource()
 
     m_bInvertAxisOrderIfLatLong = false;
     m_bConsiderEPSGAsURN = false;
+    m_eSwapCoordinates = GML_SWAP_AUTO;
     m_bGetSecondaryGeometryOption = false;
     bEmptyAsNull = true;
 }
@@ -567,6 +568,13 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     else
         m_bConsiderEPSGAsURN = false;
 
+    const char* pszSwapCoordinates =
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                             "SWAP_COORDINATES",
+            CPLGetConfigOption("GML_SWAP_COORDINATES", "AUTO"));
+    m_eSwapCoordinates = EQUAL(pszSwapCoordinates, "AUTO") ? GML_SWAP_AUTO:
+                         CPLTestBool(pszSwapCoordinates) ? GML_SWAP_YES: GML_SWAP_NO;
+
     m_bGetSecondaryGeometryOption = CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
 
     /* EXPAT is faster than Xerces, so when it is safe to use it, use it ! */
@@ -587,6 +595,7 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     poReader = CreateGMLReader( bUseExpatParserPreferably,
                                 m_bInvertAxisOrderIfLatLong,
                                 m_bConsiderEPSGAsURN,
+                                m_eSwapCoordinates,
                                 m_bGetSecondaryGeometryOption );
     if( poReader == NULL )
     {
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
index 4ef133c..da43d35 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
+ * $Id: ogrgmldriver.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  OGR
  * Purpose:  OGRGMLDriver implementation
@@ -32,7 +32,7 @@
 #include "cpl_multiproc.h"
 #include "gmlreaderp.h"
 
-CPL_CVSID("$Id: ogrgmldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrgmldriver.cpp 35690 2016-10-11 09:56:31Z rouault $");
 
 /************************************************************************/
 /*                        OGRGMLDriverUnload()                          */
@@ -171,6 +171,13 @@ void RegisterOGRGML()
 "    <Value>YES</Value>"
 "    <Value>NO</Value>"
 "  </Option>"
+"  <Option name='SWAP_COORDINATES' type='string-select' "
+    "description='Whether the order of geometry coordinates should be inverted.' "
+    "default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
 "  <Option name='READ_MODE' type='string-select' description='Read mode' default='AUTO'>"
 "    <Value>AUTO</Value>"
 "    <Value>STANDARD</Value>"
diff --git a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
index afbd73a..14017f4 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgmllayer.cpp 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: ogrgmllayer.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLLayer class.
@@ -36,7 +36,7 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrgmllayer.cpp 33702 2016-03-11 06:20:16Z goatbar $");
+CPL_CVSID("$Id: ogrgmllayer.cpp 35690 2016-10-11 09:56:31Z rouault $");
 
 /************************************************************************/
 /*                           OGRGMLLayer()                              */
@@ -291,6 +291,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                                                   poDS->GetInvertAxisOrderIfLatLong(),
                                                   pszSRSName,
                                                   poDS->GetConsiderEPSGAsURN(),
+                                                  poDS->GetSwapCoordinates(),
                                                   poDS->GetSecondaryGeometryOption(),
                                                   hCacheSRS,
                                                   bFaceHoleNegative );
@@ -339,6 +340,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                                                   poDS->GetInvertAxisOrderIfLatLong(),
                                                   pszSRSName,
                                                   poDS->GetConsiderEPSGAsURN(),
+                                                  poDS->GetSwapCoordinates(),
                                                   poDS->GetSecondaryGeometryOption(),
                                                   hCacheSRS,
                                                   bFaceHoleNegative );
diff --git a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
index 8e1f86e..27fe977 100644
--- a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
+++ b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgeopackagerasterband.cpp 34001 2016-04-18 15:29:00Z rouault $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements GDALGeoPackageRasterBand class
@@ -31,6 +30,8 @@
 #include "memdataset.h"
 #include "gdal_alg_priv.h"
 
+CPL_CVSID("$Id: gdalgeopackagerasterband.cpp 35697 2016-10-11 18:44:52Z rouault $");
+
 #if !defined(DEBUG_VERBOSE) && defined(DEBUG_VERBOSE_GPKG)
 #define DEBUG_VERBOSE
 #endif
@@ -41,6 +42,7 @@
 
 GDALGPKGMBTilesLikePseudoDataset::GDALGPKGMBTilesLikePseudoDataset() :
     m_bNew(false),
+    m_bHasModifiedTiles(false),
     m_nZoomLevel(-1),
     m_pabyCachedTiles(NULL),
     m_nShiftXTiles(0),
@@ -55,9 +57,22 @@ GDALGPKGMBTilesLikePseudoDataset::GDALGPKGMBTilesLikePseudoDataset() :
     m_nZLevel(6),
     m_nQuality(75),
     m_bDither(false),
-    m_poParentDS(NULL)
+    m_poCT(NULL),
+    m_bTriedEstablishingCT(false),
+    m_pabyHugeColorArray(NULL),
+#ifdef HAVE_SQLITE_VFS
+  m_pMyVFS(NULL),
+#endif
+    m_hTempDB(NULL),
+    m_nLastSpaceCheckTimestamp(0),
+    m_bForceTempDBCompaction(
+        CPLTestBool(CPLGetConfigOption("GPKG_FORCE_TEMPDB_COMPACTION", "NO"))),
+    m_nAge(0),
+    m_nTileInsertionCount(0),
+    m_poParentDS(NULL),
+    m_bInWriteTile(false)
 {
-    for(int i=0;i<4;i++)
+    for( int i = 0; i < 4; i++ )
     {
         m_asCachedTilesDesc[i].nRow = -1;
         m_asCachedTilesDesc[i].nCol = -1;
@@ -67,18 +82,6 @@ GDALGPKGMBTilesLikePseudoDataset::GDALGPKGMBTilesLikePseudoDataset() :
         m_asCachedTilesDesc[i].abBandDirty[2] = FALSE;
         m_asCachedTilesDesc[i].abBandDirty[3] = FALSE;
     }
-    m_bTriedEstablishingCT = false;
-    m_pabyHugeColorArray = NULL;
-    m_poCT = NULL;
-    m_bInWriteTile = false;
-#ifdef HAVE_SQLITE_VFS
-    m_pMyVFS = NULL;
-#endif
-    m_hTempDB = NULL;
-    m_nTileInsertionCount = 0;
-    m_nLastSpaceCheckTimestamp = 0;
-    m_nAge = 0;
-    m_bForceTempDBCompaction = CPLTestBool(CPLGetConfigOption("GPKG_FORCE_TEMPDB_COMPACTION", "NO"));
 }
 
 /************************************************************************/
@@ -93,7 +96,7 @@ GDALGPKGMBTilesLikePseudoDataset::~GDALGPKGMBTilesLikePseudoDataset()
         m_hTempDB = NULL;
         VSIUnlink(m_osTempDBFilename);
 #ifdef HAVE_SQLITE_VFS
-        if (m_pMyVFS)
+        if( m_pMyVFS )
         {
             sqlite3_vfs_unregister(m_pMyVFS);
             CPLFree(m_pMyVFS->pAppData);
@@ -111,8 +114,8 @@ GDALGPKGMBTilesLikePseudoDataset::~GDALGPKGMBTilesLikePseudoDataset()
 /************************************************************************/
 
 GDALGPKGMBTilesLikeRasterBand::GDALGPKGMBTilesLikeRasterBand(
-    GDALGPKGMBTilesLikePseudoDataset* poTPD, int nTileWidth, int nTileHeight)
-    : m_poTPD(poTPD)
+    GDALGPKGMBTilesLikePseudoDataset* poTPD, int nTileWidth, int nTileHeight) :
+    m_poTPD(poTPD)
 {
     eDataType = GDT_Byte;
     nBlockXSize = nTileWidth;
@@ -140,6 +143,10 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::FlushCache()
 CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushTiles()
 {
     CPLErr eErr = CE_None;
+    GDALGPKGMBTilesLikePseudoDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
+    if( poMainDS->m_nTileInsertionCount < 0 )
+        return CE_Failure;
+
     if( IGetUpdate() )
     {
         if( m_nShiftXPixelsMod || m_nShiftYPixelsMod )
@@ -152,11 +159,17 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushTiles()
         }
     }
 
-    GDALGPKGMBTilesLikePseudoDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
-    if( poMainDS->m_nTileInsertionCount )
+    if( poMainDS->m_nTileInsertionCount > 0 )
     {
-        poMainDS->ICommitTransaction();
-        poMainDS->m_nTileInsertionCount = 0;
+        if( poMainDS->ICommitTransaction() != OGRERR_NONE )
+        {
+            poMainDS->m_nTileInsertionCount = -1;
+            eErr = CE_Failure;
+        }
+        else
+        {
+            poMainDS->m_nTileInsertionCount = 0;
+        }
     }
     return eErr;
 }
@@ -167,93 +180,93 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushTiles()
 
 GDALColorTable* GDALGPKGMBTilesLikeRasterBand::GetColorTable()
 {
-    if( poDS->GetRasterCount() == 1 )
+    if( poDS->GetRasterCount() != 1 )
+        return NULL;
+
+    if( !m_poTPD->m_bTriedEstablishingCT )
     {
-        if( !m_poTPD->m_bTriedEstablishingCT )
+        m_poTPD->m_bTriedEstablishingCT = true;
+        if( m_poTPD->m_poParentDS != NULL )
         {
-            m_poTPD->m_bTriedEstablishingCT = true;
-            if( m_poTPD->m_poParentDS != NULL )
+            m_poTPD->m_poCT
+                = m_poTPD->m_poParentDS->IGetRasterBand(1)->GetColorTable();
+            if( m_poTPD->m_poCT )
+                m_poTPD->m_poCT = m_poTPD->m_poCT->Clone();
+            return m_poTPD->m_poCT;
+        }
+
+        for( int i = 0; i < 2; i++ )
+        {
+            bool bRetry = false;
+            char* pszSQL = NULL;
+            if( i == 0 )
             {
-                m_poTPD->m_poCT
-                    = m_poTPD->m_poParentDS->IGetRasterBand(1)->GetColorTable();
-                if( m_poTPD->m_poCT )
-                    m_poTPD->m_poCT = m_poTPD->m_poCT->Clone();
-                return m_poTPD->m_poCT;
+                pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+                    "WHERE zoom_level = %d LIMIT 1",
+                    m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel);
             }
-
-            for( int i=0;i<2;i++)
+            else
             {
-                bool bRetry = false;
-                char* pszSQL;
-                if( i == 0 )
-                {
-                    pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
-                        "WHERE zoom_level = %d LIMIT 1",
-                        m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel);
-                }
-                else
-                {
-                    // Try a tile in the middle of the raster
-                    pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
-                        "WHERE zoom_level = %d AND tile_column = %d AND tile_row = %d",
-                        m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel,
-                        m_poTPD->m_nShiftXTiles + nRasterXSize / 2 / nBlockXSize,
-                        m_poTPD->GetRowFromIntoTopConvention(m_poTPD->m_nShiftYTiles + nRasterYSize / 2 / nBlockYSize));
-                }
-                sqlite3_stmt* hStmt = NULL;
-                int rc = sqlite3_prepare(m_poTPD->IGetDB(), pszSQL, -1, &hStmt, NULL);
-                if ( rc == SQLITE_OK )
+                // Try a tile in the middle of the raster
+                pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+                    "WHERE zoom_level = %d AND tile_column = %d AND tile_row = %d",
+                    m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel,
+                    m_poTPD->m_nShiftXTiles + nRasterXSize / 2 / nBlockXSize,
+                    m_poTPD->GetRowFromIntoTopConvention(m_poTPD->m_nShiftYTiles + nRasterYSize / 2 / nBlockYSize));
+            }
+            sqlite3_stmt* hStmt = NULL;
+            int rc = sqlite3_prepare(m_poTPD->IGetDB(), pszSQL, -1, &hStmt, NULL);
+            if( rc == SQLITE_OK )
+            {
+                rc = sqlite3_step( hStmt );
+                if( rc == SQLITE_ROW
+                    && sqlite3_column_type( hStmt, 0 ) == SQLITE_BLOB )
                 {
-                    rc = sqlite3_step( hStmt );
-                    if( rc == SQLITE_ROW
-                        && sqlite3_column_type( hStmt, 0 ) == SQLITE_BLOB )
+                    const int nBytes = sqlite3_column_bytes( hStmt, 0 );
+                    GByte* pabyRawData = reinterpret_cast<GByte *>(
+                        const_cast<void *>( sqlite3_column_blob( hStmt, 0 ) ) );
+                    CPLString osMemFileName;
+                    osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
+                    VSILFILE *fp = VSIFileFromMemBuffer( osMemFileName.c_str(),
+                                                        pabyRawData,
+                                                        nBytes, FALSE);
+                    VSIFCloseL(fp);
+
+                    // Only PNG can have color table.
+                    const char* apszDrivers[] = { "PNG", NULL };
+                    GDALDataset* poDSTile = reinterpret_cast<GDALDataset *>(
+                        GDALOpenEx( osMemFileName.c_str(),
+                                    GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                                    apszDrivers, NULL, NULL ) );
+                    if( poDSTile != NULL )
                     {
-                        const int nBytes = sqlite3_column_bytes( hStmt, 0 );
-                        GByte* pabyRawData = reinterpret_cast<GByte *>(
-                            const_cast<void *>( sqlite3_column_blob( hStmt, 0 ) ) );
-                        CPLString osMemFileName;
-                        osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
-                        VSILFILE *fp = VSIFileFromMemBuffer( osMemFileName.c_str(),
-                                                            pabyRawData,
-                                                            nBytes, FALSE);
-                        VSIFCloseL(fp);
-
-                        /* Only PNG can have color table. */
-                        const char* apszDrivers[] = { "PNG", NULL };
-                        GDALDataset* poDSTile = reinterpret_cast<GDALDataset *>(
-                            GDALOpenEx( osMemFileName.c_str(),
-                                        GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                        apszDrivers, NULL, NULL ) );
-                        if( poDSTile != NULL )
+                        if( poDSTile->GetRasterCount() == 1 )
                         {
-                            if( poDSTile->GetRasterCount() == 1 )
-                            {
-                                m_poTPD->m_poCT
-                                    = poDSTile->GetRasterBand(1)->GetColorTable();
-                                if( m_poTPD->m_poCT != NULL )
-                                    m_poTPD->m_poCT = m_poTPD->m_poCT->Clone();
-                            }
-                            else
-                                bRetry = true;
-                            GDALClose( poDSTile );
+                            m_poTPD->m_poCT
+                                = poDSTile->GetRasterBand(1)->GetColorTable();
+                            if( m_poTPD->m_poCT != NULL )
+                                m_poTPD->m_poCT = m_poTPD->m_poCT->Clone();
                         }
                         else
+                        {
                             bRetry = true;
-
-                        VSIUnlink(osMemFileName);
+                        }
+                        GDALClose( poDSTile );
                     }
+                    else
+                        bRetry = true;
+
+                    VSIUnlink(osMemFileName);
                 }
-                sqlite3_free(pszSQL);
-                sqlite3_finalize(hStmt);
-                if( !bRetry )
-                    break;
             }
+            sqlite3_free(pszSQL);
+            sqlite3_finalize(hStmt);
+            if( !bRetry )
+                break;
         }
-
-        return m_poTPD->m_poCT;
     }
 
-    return NULL;
+    return m_poTPD->m_poCT;
 }
 
 /************************************************************************/
@@ -650,8 +663,8 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
 GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pabyData,
                                         bool *pbIsLossyFormat)
 {
-    int nBlockXSize;
-    int nBlockYSize;
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
     IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
     const int nBands = IGetRasterCount();
 
@@ -853,7 +866,7 @@ retry:
             for(int iBand=1;iBand<=poDS->GetRasterCount();iBand++)
             {
                 GDALRasterBlock* poBlock = NULL;
-                GByte* pabyDest;
+                GByte* pabyDest = NULL;
                 if( iBand == nBand )
                 {
                     pabyDest = (GByte*)pData;
@@ -917,12 +930,9 @@ retry:
                 }
                 else
                 {
-                    int nSrcXOffset;
-                    int nSrcXSize;
-                    int nSrcYOffset;
-                    int nSrcYSize;
-                    int nDstXOffset;
-                    int nDstYOffset;
+                    int nSrcXOffset = 0;
+                    int nSrcXSize = 0;
+                    int nDstXOffset = 0;
                     if( nCol == nColMin )
                     {
                         nSrcXOffset = m_poTPD->m_nShiftXPixelsMod;
@@ -935,6 +945,9 @@ retry:
                         nSrcXSize = m_poTPD->m_nShiftXPixelsMod;
                         nDstXOffset = nBlockXSize - m_poTPD->m_nShiftXPixelsMod;
                     }
+                    int nSrcYOffset = 0;
+                    int nSrcYSize = 0;
+                    int nDstYOffset = 0;
                     if( nRow == nRowMin )
                     {
                         nSrcYOffset = m_poTPD->m_nShiftYPixelsMod;
@@ -1012,6 +1025,10 @@ static bool WEBPSupports4Bands()
 
 CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTile()
 {
+    GDALGPKGMBTilesLikePseudoDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
+    if( poMainDS->m_nTileInsertionCount < 0 )
+        return CE_Failure;
+
     CPLAssert(!m_bInWriteTile);
     m_bInWriteTile = true;
     CPLErr eErr = WriteTileInternal();
@@ -1418,7 +1435,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
                 memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
                 memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
             }
-            int i;  // TODO: Rename the variable to make it clean what it is.
+            int i = 0;  // TODO: Rename variable to make it clear what it is.
             for(int iY = iYOff; iY < iYOff + iYCount; iY ++)
             {
                 if( iXOff > 0 )
@@ -1478,8 +1495,9 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
         if( poOutDS )
         {
             GDALClose( poOutDS );
-            vsi_l_offset nBlobSize;
-            GByte* pabyBlob = VSIGetMemFileBuffer(osMemFileName, &nBlobSize, TRUE);
+            vsi_l_offset nBlobSize = 0;
+            GByte* pabyBlob =
+                VSIGetMemFileBuffer(osMemFileName, &nBlobSize, TRUE);
 
             /* Create or commit and recreate transaction */
             GDALGPKGMBTilesLikePseudoDataset* poMainDS = m_poParentDS ? m_poParentDS : this;
@@ -1489,7 +1507,14 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             }
             else if( poMainDS->m_nTileInsertionCount == 1000 )
             {
-                poMainDS->ICommitTransaction();
+                if( poMainDS->ICommitTransaction() != OGRERR_NONE )
+                {
+                    poMainDS->m_nTileInsertionCount = -1;
+                    CPLFree(pabyBlob);
+                    VSIUnlink(osMemFileName);
+                    delete poMEMDS;
+                    return CE_Failure;
+                }
                 poMainDS->IStartTransaction();
                 poMainDS->m_nTileInsertionCount = 0;
             }
@@ -1865,7 +1890,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::DoPartialFlushOfPartialTilesIfNecessary
     time_t nCurTimeStamp = time(NULL);
     if( m_nLastSpaceCheckTimestamp == 0 )
         m_nLastSpaceCheckTimestamp = nCurTimeStamp;
-    if( m_nLastSpaceCheckTimestamp > 0 && 
+    if( m_nLastSpaceCheckTimestamp > 0 &&
         (m_bForceTempDBCompaction || nCurTimeStamp - m_nLastSpaceCheckTimestamp > 10) )
     {
         m_nLastSpaceCheckTimestamp = nCurTimeStamp;
@@ -1936,7 +1961,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
         VSIUnlink(m_osTempDBFilename);
         CPLPopErrorHandler();
         m_hTempDB = NULL;
-        int rc;
+        int rc = 0;
 #ifdef HAVE_SQLITE_VFS
         if (STARTS_WITH(m_osTempDBFilename, "/vsi"))
         {
@@ -1958,6 +1983,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
             return CE_Failure;
         }
         SQLCommand(m_hTempDB, "PRAGMA synchronous = OFF");
+        /* coverity[tainted_string] */
         SQLCommand(m_hTempDB, (CPLString("PRAGMA journal_mode = ") + CPLGetConfigOption("PARTIAL_TILES_JOURNAL_MODE", "OFF")).c_str());
         SQLCommand(m_hTempDB, "CREATE TABLE partial_tiles("
                                     "id INTEGER PRIMARY KEY AUTOINCREMENT,"
@@ -2251,6 +2277,10 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
     {
         return CE_Failure;
     }
+    if( m_poTPD->m_poParentDS )
+        m_poTPD->m_poParentDS->m_bHasModifiedTiles = true;
+    else
+        m_poTPD->m_bHasModifiedTiles = true;
 
     int nRow = nBlockYOff + m_poTPD->m_nShiftYTiles;
     int nCol = nBlockXOff + m_poTPD->m_nShiftXTiles;
@@ -2297,7 +2327,7 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
             for(int iBand=1;iBand<=poDS->GetRasterCount();iBand++)
             {
                 GDALRasterBlock* poBlock = NULL;
-                GByte* pabySrc;
+                GByte* pabySrc = NULL;
                 if( iBand == nBand )
                 {
                     pabySrc = (GByte*)pData;
@@ -2317,7 +2347,7 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
                                         TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
                         if( poBlock && poBlock->GetDirty() )
                         {
-                            pabySrc = (GByte*)poBlock->GetDataRef(),
+                            pabySrc = (GByte*)poBlock->GetDataRef();
                             poBlock->MarkClean();
                         }
                         else
diff --git a/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h b/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
index eb424b1..699e11a 100644
--- a/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
+++ b/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gpkgmbtilescommon.h 34001 2016-04-18 15:29:00Z rouault $
+ * $Id: gpkgmbtilescommon.h 35697 2016-10-11 18:44:52Z rouault $
  *
  * Project:  GeoPackage/MBTiles Translator
  * Purpose:  Definition of common classes for GeoPackage and MBTiles drivers.
@@ -59,6 +59,7 @@ class GDALGPKGMBTilesLikePseudoDataset
 
   protected:
     bool                m_bNew;
+    bool                m_bHasModifiedTiles;
 
     CPLString           m_osRasterTable;
     int                 m_nZoomLevel;
@@ -126,8 +127,8 @@ class GDALGPKGMBTilesLikePseudoDataset
         virtual sqlite3                *IGetDB() = 0;
         virtual bool                    IGetUpdate() = 0;
         virtual bool                    ICanIWriteBlock() = 0;
-        virtual void                    IStartTransaction() = 0;
-        virtual void                    ICommitTransaction() = 0;
+        virtual OGRErr                  IStartTransaction() = 0;
+        virtual OGRErr                  ICommitTransaction() = 0;
         virtual const char             *IGetFilename() = 0;
         virtual int                     GetRowFromIntoTopConvention(int nRow) = 0;
 };
diff --git a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
index b43920d..034b9ba 100644
--- a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
+++ b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: ogr_geopackage.h 35695 2016-10-11 17:39:33Z rouault $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Definition of classes for OGR GeoPackage driver.
@@ -35,6 +35,8 @@
 #include "ogrgeopackageutility.h"
 #include "gpkgmbtilescommon.h"
 
+#include <vector>
+
 #define UNKNOWN_SRID   -2
 #define DEFAULT_SRID    0
 
@@ -78,37 +80,37 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
     CPLString           m_osTilingScheme;
 
         void            ComputeTileAndPixelShifts();
-        int             InitRaster ( GDALGeoPackageDataset* poParentDS,
+        bool            InitRaster ( GDALGeoPackageDataset* poParentDS,
                                      const char* pszTableName,
-                                        double dfMinX,
-                                        double dfMinY,
-                                        double dfMaxX,
-                                        double dfMaxY,
-                                        const char* pszContentsMinX,
-                                        const char* pszContentsMinY,
-                                        const char* pszContentsMaxX,
-                                        const char* pszContentsMaxY,
-                                        char** papszOpenOptions,
-                                        const SQLResult& oResult,
-                                        int nIdxInResult );
-        int             InitRaster ( GDALGeoPackageDataset* poParentDS,
+                                     double dfMinX,
+                                     double dfMinY,
+                                     double dfMaxX,
+                                     double dfMaxY,
+                                     const char* pszContentsMinX,
+                                     const char* pszContentsMinY,
+                                     const char* pszContentsMaxX,
+                                     const char* pszContentsMaxY,
+                                     char** papszOpenOptions,
+                                     const SQLResult& oResult,
+                                     int nIdxInResult );
+        bool            InitRaster ( GDALGeoPackageDataset* poParentDS,
                                      const char* pszTableName,
-                                        int nZoomLevel,
-                                        int nBandCount,
-                                        double dfTMSMinX,
-                                        double dfTMSMaxY,
-                                        double dfPixelXSize,
-                                        double dfPixelYSize,
-                                        int nTileWidth,
-                                        int nTileHeight,
-                                        int nTileMatrixWidth,
-                                        int nTileMatrixHeight,
-                                        double dfGDALMinX,
-                                        double dfGDALMinY,
-                                        double dfGDALMaxX,
-                                        double dfGDALMaxY );
-
-        int     OpenRaster( const char* pszTableName,
+                                     int nZoomLevel,
+                                     int nBandCount,
+                                     double dfTMSMinX,
+                                     double dfTMSMaxY,
+                                     double dfPixelXSize,
+                                     double dfPixelYSize,
+                                     int nTileWidth,
+                                     int nTileHeight,
+                                     int nTileMatrixWidth,
+                                     int nTileMatrixHeight,
+                                     double dfGDALMinX,
+                                     double dfGDALMinY,
+                                     double dfGDALMaxX,
+                                     double dfGDALMaxY );
+
+        bool    OpenRaster( const char* pszTableName,
                             const char* pszIdentifier,
                             const char* pszDescription,
                             int nSRSId,
@@ -123,20 +125,22 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
                             char** papszOptions );
         CPLErr   FinalizeRasterRegistration();
 
-        int                     RegisterWebPExtension();
-        int                     RegisterZoomOtherExtension();
+        bool                    RegisterWebPExtension();
+        bool                    RegisterZoomOtherExtension();
         void                    ParseCompressionOptions(char** papszOptions);
 
-        int                     HasMetadataTables();
-        int                     CreateMetadataTables();
+        bool                    HasMetadataTables();
+        bool                    CreateMetadataTables();
         const char*             CheckMetadataDomain( const char* pszDomain );
         void                    WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method */
                                               const char* pszTableName);
         CPLErr                  FlushMetadata();
 
+        int                     FindLayerIndex(const char* pszLayerName);
+
     public:
                             GDALGeoPackageDataset();
-                            ~GDALGeoPackageDataset();
+                            virtual ~GDALGeoPackageDataset();
 
         virtual char **     GetMetadata( const char *pszDomain = NULL );
         virtual const char *GetMetadataItem( const char * pszName,
@@ -191,10 +195,13 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
         OGRErr              CreateExtensionsTableIfNecessary();
         bool                HasExtensionsTable();
         OGRErr              CreateGDALAspatialExtension();
+        bool                HasDataColumnsTable();
         void                SetMetadataDirty() { m_bMetadataDirty = true; }
 
         const char*         GetGeometryTypeString(OGRwkbGeometryType eType);
 
+        void                ResetReadingAllLayers();
+
         static GDALDataset* CreateCopy( const char *pszFilename,
                                                    GDALDataset *poSrcDS,
                                                    int bStrict,
@@ -211,8 +218,8 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
         virtual sqlite3                *IGetDB() { return GetDB(); }
         virtual bool                    IGetUpdate() { return bUpdate != FALSE; }
         virtual bool                    ICanIWriteBlock();
-        virtual void                    IStartTransaction() { SoftStartTransaction(); }
-        virtual void                    ICommitTransaction() { SoftCommitTransaction(); }
+        virtual OGRErr                  IStartTransaction() { return SoftStartTransaction(); }
+        virtual OGRErr                  ICommitTransaction() { return SoftCommitTransaction(); }
         virtual const char             *IGetFilename() { return m_pszFilename; }
         virtual int                     GetRowFromIntoTopConvention(int nRow) { return nRow; }
 
@@ -220,7 +227,8 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
 
         OGRErr              PragmaCheck(const char * pszPragma, const char * pszExpected, int nRowsExpected);
         OGRErr              SetApplicationId();
-        int                 OpenOrCreateDB(int flags);
+        bool                ReOpenDB();
+        bool                OpenOrCreateDB( int flags );
         bool                HasGDALAspatialExtension();
 };
 
@@ -251,7 +259,7 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
     int                  iNextShapeId;
 
     sqlite3_stmt        *m_poQueryStatement;
-    int                  bDoStep;
+    bool                 bDoStep;
 
     char                *m_pszFidColumn;
 
@@ -270,7 +278,7 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
   public:
 
                         OGRGeoPackageLayer(GDALGeoPackageDataset* poDS);
-                        ~OGRGeoPackageLayer();
+                        virtual ~OGRGeoPackageLayer();
     /************************************************************************/
     /* OGR API methods */
 
@@ -299,6 +307,7 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     CPLString                   m_soFilter;
     CPLString                   osQuery;
     bool                        m_bExtentChanged;
+    bool                        m_bContentChanged;
     sqlite3_stmt*               m_poUpdateStatement;
     bool                        m_bInsertStatementWithFID;
     sqlite3_stmt*               m_poInsertStatement;
@@ -315,16 +324,23 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     CPLString                   m_osIdentifierLCO;
     CPLString                   m_osDescriptionLCO;
     bool                        m_bHasReadMetadataFromStorage;
+    bool                        m_bRegisterAsAspatial;
 
     virtual OGRErr      ResetStatement();
 
     void                BuildWhere(void);
     OGRErr              RegisterGeometryColumn();
 
+    CPLString           GetColumnsOfCreateTable(const std::vector<OGRFieldDefn*> apoFields);
+    CPLString           BuildSelectFieldList(const std::vector<OGRFieldDefn*> apoFields);
+    OGRErr              RecreateTable(const CPLString& osColumnsForCreate,
+                                      const CPLString& osFieldListForSelect);
+    bool                IsTable();
+
     public:
                         OGRGeoPackageTableLayer( GDALGeoPackageDataset *poDS,
                                             const char * pszTableName );
-                        ~OGRGeoPackageTableLayer();
+                        virtual ~OGRGeoPackageTableLayer();
 
     /************************************************************************/
     /* OGR API methods */
@@ -333,8 +349,11 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
     OGRErr              CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
                                          int bApproxOK = TRUE );
+    virtual OGRErr      DeleteField(  int iFieldToDelete );
+    virtual OGRErr      AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlagsIn );
+    virtual OGRErr      ReorderFields( int* panMap );
     void                ResetReading();
-	OGRErr              ICreateFeature( OGRFeature *poFeater );
+    OGRErr              ICreateFeature( OGRFeature *poFeater );
     OGRErr              ISetFeature( OGRFeature *poFeature );
     OGRErr              DeleteFeature(GIntBig nFID);
     virtual void        SetSpatialFilter( OGRGeometry * );
@@ -352,8 +371,9 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
                 { return OGRGeoPackageLayer::GetExtent(iGeomField, psExtent, bForce); }
+    void                RecomputeExtent();
 
-    OGRErr              ReadTableDefinition(int bIsSpatial);
+    OGRErr              ReadTableDefinition(bool bIsSpatial, bool bIsGpkgTable);
     void                SetCreationParameters( OGRwkbGeometryType eGType,
                                                const char* pszGeomColumnName,
                                                int bGeomNullable,
@@ -363,9 +383,11 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
                                                const char* pszDescription );
     void                SetDeferredSpatialIndexCreation( bool bFlag )
                                 { m_bDeferredSpatialIndexCreation = bFlag; }
+    void                SetRegisterAsAspatial( bool bFlag )
+                                { m_bRegisterAsAspatial = bFlag; }
 
     void                CreateSpatialIndexIfNecessary();
-    bool                CreateSpatialIndex();
+    bool                CreateSpatialIndex(const char* pszTableName = NULL);
     bool                DropSpatialIndex(bool bCalledFromSQLFunction = false);
 
     virtual char **     GetMetadata( const char *pszDomain = NULL );
@@ -398,8 +420,9 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
   private:
     OGRErr              UpdateExtent( const OGREnvelope *poExtent );
     OGRErr              SaveExtent();
+    OGRErr              SaveTimestamp();
     OGRErr              BuildColumns();
-    OGRBoolean          IsGeomFieldSet( OGRFeature *poFeature );
+    bool                IsGeomFieldSet( OGRFeature *poFeature );
     CPLString           FeatureGenerateUpdateSQL( OGRFeature *poFeature );
     CPLString           FeatureGenerateInsertSQL( OGRFeature *poFeature, bool bAddFID, bool bBindNullFields );
     OGRErr              FeatureBindUpdateParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt );
@@ -426,7 +449,7 @@ class OGRGeoPackageSelectLayer CPL_FINAL : public OGRGeoPackageLayer, public IOG
                                               sqlite3_stmt *,
                                               int bUseStatementForGetNextFeature,
                                               int bEmptyLayer );
-                       ~OGRGeoPackageSelectLayer();
+                       virtual ~OGRGeoPackageSelectLayer();
 
     virtual void        ResetReading();
 
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
index 4bf5d59..c68f572 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements GDALGeoPackageDataset class
@@ -33,10 +32,13 @@
 #include "swq.h"
 #include "gdalwarper.h"
 
-/* 1.1.1: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the application id */
-/* http://opengis.github.io/geopackage/#_file_format */
-/* 0x47503130 = 1196437808 */
-#define GPKG_APPLICATION_ID 1196437808
+CPL_CVSID("$Id: ogrgeopackagedatasource.cpp 35695 2016-10-11 17:39:33Z rouault $");
+
+// 1.1.1: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the
+// application id.
+// http://opengis.github.io/geopackage/#_file_format
+// 0x47503130 = 1196437808
+static const int GPKG_APPLICATION_ID = 1196437808;
 
 /* "GP10" in ASCII bytes */
 static const char aGpkgId[4] = {0x47, 0x50, 0x31, 0x30};
@@ -139,13 +141,28 @@ OGRErr GDALGeoPackageDataset::SetApplicationId()
     }
 
     /* And re-open the file */
-    if (!OpenOrCreateDB(SQLITE_OPEN_READWRITE) )
+    if( !OpenOrCreateDB(SQLITE_OPEN_READWRITE) )
         return OGRERR_FAILURE;
 
     return OGRERR_NONE;
 }
 
 
+bool GDALGeoPackageDataset::ReOpenDB()
+{
+    CPLAssert( hDB != NULL );
+    CPLAssert( m_pszFilename != NULL );
+
+#ifdef SPATIALITE_412_OR_LATER
+    FinishNewSpatialite();
+#endif
+    CloseDB();
+
+    /* And re-open the file */
+    return OpenOrCreateDB(SQLITE_OPEN_READWRITE);
+}
+
+
 /* Returns the first row of first column of SQL as integer */
 OGRErr GDALGeoPackageDataset::PragmaCheck(
     const char * pszPragma, const char * pszExpected, int nRowsExpected )
@@ -155,8 +172,8 @@ OGRErr GDALGeoPackageDataset::PragmaCheck(
     CPLAssert( nRowsExpected >= 0 );
 
     char **papszResult = NULL;
-    int nRowCount;
-    int nColCount;
+    int nRowCount = 0;
+    int nColCount = 0;
     char *pszErrMsg = NULL;
 
     int rc = sqlite3_get_table(
@@ -433,7 +450,8 @@ GDALGeoPackageDataset::GDALGeoPackageDataset() :
     m_nOverviewCount(0),
     m_papoOverviewDS(NULL),
     m_bZoomOther(false),
-    m_bInFlushCache(false)
+    m_bInFlushCache(false),
+    m_osTilingScheme("CUSTOM")
 {
     m_adfGeoTransform[0] = 0.0;
     m_adfGeoTransform[1] = 1.0;
@@ -441,7 +459,6 @@ GDALGeoPackageDataset::GDALGeoPackageDataset() :
     m_adfGeoTransform[3] = 0.0;
     m_adfGeoTransform[4] = 0.0;
     m_adfGeoTransform[5] = 1.0;
-    m_osTilingScheme = "CUSTOM";
 }
 
 /************************************************************************/
@@ -511,8 +528,6 @@ bool GDALGeoPackageDataset::ICanIWriteBlock()
 
 int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
 {
-    OGRErr err;
-
     CPLAssert( m_nLayers == 0 );
     CPLAssert( hDB == NULL );
 
@@ -539,7 +554,9 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     m_pszFilename = CPLStrdup( osFilename );
 
     /* See if we can open the SQLite database */
-    if (!OpenOrCreateDB((bUpdate) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY) )
+    if( !OpenOrCreateDB(bUpdate
+                        ? SQLITE_OPEN_READWRITE
+                        : SQLITE_OPEN_READONLY) )
         return FALSE;
 
     /* Requirement 6: The SQLite PRAGMA integrity_check SQL command SHALL return “ok” */
@@ -556,10 +573,13 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     /* Requirement 7: The SQLite PRAGMA foreign_key_check() SQL with no */
     /* parameter value SHALL return an empty result set */
     /* http://opengis.github.io/geopackage/#_file_integrity */
-    if ( OGRERR_NONE != PragmaCheck("foreign_key_check", "", 0) )
+    if ( CPLTestBool(CPLGetConfigOption("OGR_GPKG_FOREIGN_KEY_CHECK", "YES")) &&
+         OGRERR_NONE != PragmaCheck("foreign_key_check", "", 0) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "pragma foreign_key_check on '%s' failed",
+                  "pragma foreign_key_check on '%s' failed. You can disable "
+                  "this check by setting the OGR_GPKG_FOREIGN_KEY_CHECK "
+                  "configuration option to NO",
                   m_pszFilename);
         return FALSE;
     }
@@ -588,7 +608,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     {
         SQLResult oResult;
         char *pszSQL = sqlite3_mprintf("pragma table_info('%q')", aosGpkgTables[i].c_str());
-        err = SQLQuery(hDB, pszSQL, &oResult);
+        const OGRErr err = SQLQuery(hDB, pszSQL, &oResult);
         sqlite3_free(pszSQL);
 
         if  ( err != OGRERR_NONE )
@@ -607,12 +627,13 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     CheckUnknownExtensions();
 
     int bRet = FALSE;
-    int bHasGPKGGeometryColumns = FALSE;
+    bool bHasGPKGGeometryColumns = false;
     if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
     {
         SQLResult oResult;
-        err = SQLQuery(hDB, "pragma table_info('gpkg_geometry_columns')", &oResult);
-        bHasGPKGGeometryColumns = (err == OGRERR_NONE && oResult.nRowCount > 0);
+        const OGRErr err =
+            SQLQuery(hDB, "pragma table_info('gpkg_geometry_columns')", &oResult);
+        bHasGPKGGeometryColumns = err == OGRERR_NONE && oResult.nRowCount > 0;
         SQLResultFree(&oResult);
     }
     if( bHasGPKGGeometryColumns )
@@ -620,20 +641,29 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         /* Load layer definitions for all tables in gpkg_contents & gpkg_geometry_columns */
         /* and non-spatial tables as well */
         std::string osSQL =
-            "SELECT c.table_name, c.identifier, 1 as is_spatial, c.min_x, c.min_y, c.max_x, c.max_y "
+            "SELECT c.table_name, c.identifier, 1 as is_spatial, c.min_x, c.min_y, c.max_x, c.max_y, 1 AS is_gpkg_table "
             "  FROM gpkg_geometry_columns g JOIN gpkg_contents c ON (g.table_name = c.table_name)"
             "  WHERE c.data_type = 'features' ";
 
         if (HasGDALAspatialExtension()) {
             osSQL +=
                 "UNION ALL "
-                "SELECT table_name, identifier, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax "
+                "SELECT table_name, identifier, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax, 1 AS is_gpkg_table "
                 "  FROM gpkg_contents"
                 "  WHERE data_type = 'aspatial' ";
         }
 
+        if( CPLTestBool(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "YES")) )
+        {
+            osSQL += "UNION ALL "
+                    "SELECT name, name, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax, 0 AS is_gpkg_table "
+                    "FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'gpkg_%' "
+                    "AND name NOT LIKE 'rtree_%' AND name NOT LIKE 'sqlite_%' "
+                    "AND name NOT IN (SELECT table_name FROM gpkg_contents)";
+        }
+
         SQLResult oResult;
-        err = SQLQuery(hDB, osSQL.c_str(), &oResult);
+        OGRErr err = SQLQuery(hDB, osSQL.c_str(), &oResult);
         if  ( err != OGRERR_NONE )
         {
             SQLResultFree(&oResult);
@@ -652,9 +682,10 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
                     CPLError(CE_Warning, CPLE_AppDefined, "unable to read table name for layer(%d)", i);
                     continue;
                 }
-                int bIsSpatial = SQLResultGetValueAsInteger(&oResult, 2, i);
+                bool bIsSpatial = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResult, 2, i));
+                bool bIsGpkgTable = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResult, 7, i));
                 OGRGeoPackageTableLayer *poLayer = new OGRGeoPackageTableLayer(this, pszTableName);
-                if( OGRERR_NONE != poLayer->ReadTableDefinition(bIsSpatial) )
+                if( OGRERR_NONE != poLayer->ReadTableDefinition(bIsSpatial, bIsGpkgTable) )
                 {
                     delete poLayer;
                     CPLError(CE_Warning, CPLE_AppDefined, "unable to read table definition for '%s'", pszTableName);
@@ -668,12 +699,14 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         bRet = TRUE;
     }
 
-    int bHasTileMatrixSet = FALSE;
+    bool bHasTileMatrixSet = false;
     if( poOpenInfo->nOpenFlags & GDAL_OF_RASTER )
     {
         SQLResult oResult;
-        err = SQLQuery(hDB, "pragma table_info('gpkg_tile_matrix_set')", &oResult);
-        bHasTileMatrixSet = (err == OGRERR_NONE && oResult.nRowCount > 0);
+        const OGRErr err =
+            SQLQuery(hDB,
+                     "pragma table_info('gpkg_tile_matrix_set')", &oResult);
+        bHasTileMatrixSet = err == OGRERR_NONE && oResult.nRowCount > 0;
         SQLResultFree(&oResult);
     }
     if( bHasTileMatrixSet )
@@ -693,7 +726,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
             SetPhysicalFilename( osFilename.c_str() );
         }
 
-        err = SQLQuery(hDB, osSQL.c_str(), &oResult);
+        const OGRErr err = SQLQuery(hDB, osSQL.c_str(), &oResult);
         if  ( err != OGRERR_NONE )
         {
             SQLResultFree(&oResult);
@@ -767,7 +800,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
 /*                         InitRaster()                                 */
 /************************************************************************/
 
-int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
+bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
                                         const char* pszTableName,
                                         double dfMinX,
                                         double dfMinY,
@@ -812,7 +845,7 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
     }
     if( dfGDALMinX >= dfGDALMaxX || dfGDALMinY >= dfGDALMaxY )
     {
-        return FALSE;
+        return false;
     }
 
     int nBandCount = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "BAND_COUNT", "4"));
@@ -848,7 +881,7 @@ void GDALGeoPackageDataset::ComputeTileAndPixelShifts()
 /*                         InitRaster()                                 */
 /************************************************************************/
 
-int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
+bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
                                         const char* pszTableName,
                                         int nZoomLevel,
                                         int nBandCount,
@@ -880,14 +913,14 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
     double dfRasterXSize = 0.5 + (dfGDALMaxX - dfGDALMinX) / dfPixelXSize;
     double dfRasterYSize = 0.5 + (dfGDALMaxY - dfGDALMinY) / dfPixelYSize;
     if( dfRasterXSize > INT_MAX || dfRasterYSize > INT_MAX )
-        return FALSE;
+        return false;
     nRasterXSize = (int)dfRasterXSize;
     nRasterYSize = (int)dfRasterYSize;
 
     m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
     if( m_pabyCachedTiles == NULL )
     {
-        return FALSE;
+        return false;
     }
 
     for(int i = 1; i <= nBandCount; i ++)
@@ -914,7 +947,7 @@ int GDALGeoPackageDataset::InitRaster ( GDALGeoPackageDataset* poParentDS,
                                   poParentDS->GetDescription(), m_nZoomLevel));
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -944,25 +977,25 @@ GPKGTileFormat GDALGPKGMBTilesGetTileFormat(const char* pszTF )
 /*                         OpenRaster()                                 */
 /************************************************************************/
 
-int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
-                                       const char* pszIdentifier,
-                                       const char* pszDescription,
-                                       int nSRSId,
-                                       double dfMinX,
-                                       double dfMinY,
-                                       double dfMaxX,
-                                       double dfMaxY,
-                                       const char* pszContentsMinX,
-                                       const char* pszContentsMinY,
-                                       const char* pszContentsMaxX,
-                                       const char* pszContentsMaxY,
-                                       char** papszOpenOptionsIn )
+bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
+                                        const char* pszIdentifier,
+                                        const char* pszDescription,
+                                        int nSRSId,
+                                        double dfMinX,
+                                        double dfMinY,
+                                        double dfMaxX,
+                                        double dfMaxY,
+                                        const char* pszContentsMinX,
+                                        const char* pszContentsMinY,
+                                        const char* pszContentsMaxX,
+                                        const char* pszContentsMaxY,
+                                        char** papszOpenOptionsIn )
 {
     OGRErr err;
     SQLResult oResult;
 
     if( dfMinX >= dfMaxX || dfMinY >= dfMaxY )
-        return FALSE;
+        return false;
 
     m_bRecordInsertedInGPKGContent = true;
     m_nSRID = nSRSId;
@@ -1020,14 +1053,16 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         {
             SQLResultFree(&oResult);
             osSQL = pszSQL;
-            osSQL += " ORDER BY zoom_level DESC LIMIT 1";
+            osSQL += " ORDER BY zoom_level DESC";
+            if( !bUpdate )
+                osSQL += " LIMIT 1";
             err = SQLQuery(hDB, osSQL.c_str(), &oResult);
         }
         if( err != OGRERR_NONE || oResult.nRowCount == 0 )
         {
             SQLResultFree(&oResult);
             sqlite3_free(pszSQL);
-            return FALSE;
+            return false;
         }
     }
     sqlite3_free(pszSQL);
@@ -1047,12 +1082,12 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         {
             SQLResultFree(&oResult);
             SQLResultFree(&oResult2);
-            return FALSE;
+            return false;
         }
-        double dfPixelXSize = CPLAtof(SQLResultGetValue(&oResult, 1, 0));
-        double dfPixelYSize = CPLAtof(SQLResultGetValue(&oResult, 2, 0));
-        int nTileWidth = atoi(SQLResultGetValue(&oResult, 3, 0));
-        int nTileHeight = atoi(SQLResultGetValue(&oResult, 4, 0));
+        const double dfPixelXSize = CPLAtof(SQLResultGetValue(&oResult, 1, 0));
+        const double dfPixelYSize = CPLAtof(SQLResultGetValue(&oResult, 2, 0));
+        const int nTileWidth = atoi(SQLResultGetValue(&oResult, 3, 0));
+        const int nTileHeight = atoi(SQLResultGetValue(&oResult, 4, 0));
         osContentsMinX = CPLSPrintf("%.18g", dfMinX + dfPixelXSize * nTileWidth * atoi(SQLResultGetValue(&oResult2, 0, 0)));
         osContentsMaxY = CPLSPrintf("%.18g", dfMaxY - dfPixelYSize * nTileHeight * atoi(SQLResultGetValue(&oResult2, 1, 0)));
         osContentsMaxX = CPLSPrintf("%.18g", dfMinX + dfPixelXSize * nTileWidth * (1 + atoi(SQLResultGetValue(&oResult2, 2, 0))));
@@ -1064,12 +1099,13 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         SQLResultFree(&oResult2);
     }
 
-    if(! InitRaster ( NULL, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
-                 pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
-                 papszOpenOptionsIn, oResult, 0) )
+    if( !InitRaster(
+            NULL, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
+            pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
+            papszOpenOptionsIn, oResult, 0) )
     {
         SQLResultFree(&oResult);
-        return FALSE;
+        return false;
     }
 
     CheckUnknownExtensions(true);
@@ -1090,7 +1126,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
             if( eTF == GPKG_TF_WEBP && m_eTF != eTF )
             {
                 if( !RegisterWebPExtension() )
-                    return FALSE;
+                    return false;
             }
             m_eTF = eTF;
         }
@@ -1110,9 +1146,10 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
     for( int i = 1; i < oResult.nRowCount; i++ )
     {
         GDALGeoPackageDataset* poOvrDS = new GDALGeoPackageDataset();
-        poOvrDS->InitRaster ( this, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
-                 pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
-                 papszOpenOptionsIn, oResult, i);
+        poOvrDS->InitRaster(
+            this, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
+            pszContentsMinX, pszContentsMinY, pszContentsMaxX, pszContentsMaxY,
+            papszOpenOptionsIn, oResult, i);
 
         m_papoOverviewDS = (GDALGeoPackageDataset**) CPLRealloc(m_papoOverviewDS,
                         sizeof(GDALGeoPackageDataset*) * (m_nOverviewCount+1));
@@ -1129,7 +1166,7 @@ int GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
 
     SQLResultFree(&oResult);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1160,10 +1197,10 @@ CPLErr GDALGeoPackageDataset::SetProjection( const char* pszProjection )
         return CE_Failure;
     }
 
-    int nSRID;
+    int nSRID = -1;
     if( pszProjection == NULL || pszProjection[0] == '\0' )
     {
-        nSRID = -1;
+      // nSRID = -1;
     }
     else
     {
@@ -1302,7 +1339,6 @@ CPLErr GDALGeoPackageDataset::SetGeoTransform( double* padfGeoTransform )
 CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
 {
     OGRErr eErr;
-    char* pszSQL;
 
     m_dfTMSMinX = m_adfGeoTransform[0];
     m_dfTMSMaxY = m_adfGeoTransform[3];
@@ -1353,14 +1389,21 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
 
     SoftStartTransaction();
 
-    pszSQL = sqlite3_mprintf("INSERT INTO gpkg_contents "
-        "(table_name,data_type,identifier,description,min_x,min_y,max_x,max_y,srs_id) VALUES "
-        "('%q','tiles','%q','%q',%.18g,%.18g,%.18g,%.18g,%d)",
+    const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
+    CPLString osInsertGpkgContentsFormatting("INSERT INTO gpkg_contents "
+            "(table_name,data_type,identifier,description,min_x,min_y,max_x,max_y,last_change,srs_id) VALUES "
+            "('%q','tiles','%q','%q',%.18g,%.18g,%.18g,%.18g,");
+    osInsertGpkgContentsFormatting += ( pszCurrentDate ) ? "'%q'" : "%s";
+    osInsertGpkgContentsFormatting += ",%d)";
+    char* pszSQL =
+        sqlite3_mprintf(osInsertGpkgContentsFormatting.c_str(),
         m_osRasterTable.c_str(),
         m_osIdentifier.c_str(),
         m_osDescription.c_str(),
         dfGDALMinX, dfGDALMinY, dfGDALMaxX, dfGDALMaxY,
+        pszCurrentDate ? pszCurrentDate : "strftime('%Y-%m-%dT%H:%M:%fZ','now')",
         m_nSRID);
+
     eErr = SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
     if ( eErr != OGRERR_NONE )
@@ -1382,10 +1425,12 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
     m_papoOverviewDS = (GDALGeoPackageDataset**) CPLCalloc(sizeof(GDALGeoPackageDataset*),
                                                            m_nZoomLevel);
 
-    for(int i=0; i<=m_nZoomLevel; i++)
+    for( int i = 0; i <= m_nZoomLevel; i++ )
     {
-        double dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel;
-        int nTileMatrixWidth, nTileMatrixHeight;
+        double dfPixelXSizeZoomLevel = 0.0;
+        double dfPixelYSizeZoomLevel = 0.0;
+        int nTileMatrixWidth = 0;
+        int nTileMatrixHeight = 0;
         if( EQUAL(m_osTilingScheme, "CUSTOM") )
         {
             dfPixelXSizeZoomLevel = m_adfGeoTransform[1] * (1 << (m_nZoomLevel-i));
@@ -1413,13 +1458,13 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
         if( i < m_nZoomLevel )
         {
             GDALGeoPackageDataset* poOvrDS = new GDALGeoPackageDataset();
-            poOvrDS->InitRaster ( this, m_osRasterTable, i, nBands,
-                                  m_dfTMSMinX, m_dfTMSMaxY,
-                                  dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel,
-                                  nTileWidth, nTileHeight,
-                                  nTileMatrixWidth,nTileMatrixHeight,
-                                  dfGDALMinX, dfGDALMinY,
-                                  dfGDALMaxX, dfGDALMaxY );
+            poOvrDS->InitRaster( this, m_osRasterTable, i, nBands,
+                                 m_dfTMSMinX, m_dfTMSMaxY,
+                                 dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel,
+                                 nTileWidth, nTileHeight,
+                                 nTileMatrixWidth,nTileMatrixHeight,
+                                 dfGDALMinX, dfGDALMinY,
+                                 dfGDALMaxX, dfGDALMaxY );
 
             m_papoOverviewDS[m_nZoomLevel-1-i] = poOvrDS;
         }
@@ -1457,6 +1502,37 @@ CPLErr GDALGeoPackageDataset::IFlushCacheWithErrCode()
         m_papoLayers[i]->CreateSpatialIndexIfNecessary();
     }
 
+    // Update raster table last_change column in gpkg_contents if needed
+    if( m_bHasModifiedTiles )
+    {
+        const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
+        char *pszSQL = NULL ;
+
+        if( pszCurrentDate )
+        {
+            pszSQL = sqlite3_mprintf(
+                        "UPDATE gpkg_contents SET "
+                        "last_change = '%q'"
+                        "WHERE table_name = '%q' AND "
+                        "Lower(data_type) = 'tiles'",
+                        m_osRasterTable.c_str(), pszCurrentDate);
+        }
+        else
+        {
+            pszSQL = sqlite3_mprintf(
+                        "UPDATE gpkg_contents SET "
+                        "last_change = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ','now')"
+                        "WHERE table_name = '%q' AND "
+                        "Lower(data_type) = 'tiles'",
+                        m_osRasterTable.c_str());
+        }
+
+        CPL_IGNORE_RET_VAL(SQLCommand(hDB, pszSQL));
+        sqlite3_free(pszSQL);
+
+        m_bHasModifiedTiles = false;
+    }
+
     CPLErr eErr = FlushTiles();
 
     m_bInFlushCache = false;
@@ -1539,17 +1615,22 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
             return CE_Failure;
         }
 
-        int bFound = FALSE;
+        bool bFound = false;
         int jCandidate = -1;
         int nMaxOvFactor = 0;
-        for(int j=0;j<m_nOverviewCount;j++)
+        for( int j = 0; j < m_nOverviewCount; j++ )
         {
-            int    nOvFactor;
-
             GDALDataset* poODS = m_papoOverviewDS[j];
 
-            nOvFactor = (int)
-                (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
+            int nOvFactor = GDALComputeOvFactor(poODS->GetRasterXSize(),
+                                                GetRasterXSize(),
+                                                poODS->GetRasterYSize(),
+                                                GetRasterYSize());
+            if( nOvFactor > 64 &&
+                ABS(nOvFactor - GetFloorPowerOfTwo(nOvFactor)) <= 2 )
+            {
+                nOvFactor = GetFloorPowerOfTwo(nOvFactor);
+            }
             nMaxOvFactor = nOvFactor;
 
             if( nOvFactor == panOverviewList[i]
@@ -1557,7 +1638,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                                                     GetRasterXSize(),
                                                     GetRasterYSize() ) )
             {
-                bFound = TRUE;
+                bFound = true;
                 break;
             }
 
@@ -1573,12 +1654,10 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                 CPLString osOvrList;
                 for(int j=0;j<m_nOverviewCount;j++)
                 {
-                    int    nOvFactor;
-
                     GDALDataset* poODS = m_papoOverviewDS[j];
 
                     /* Compute overview factor */
-                    nOvFactor = (int)
+                    int nOvFactor = (int)
                         (0.5 + GetRasterXSize() / (double) poODS->GetRasterXSize());
                     int nODSXSize = (int)(0.5 + GetRasterXSize() / (double) nOvFactor);
                     if( nODSXSize != poODS->GetRasterXSize() )
@@ -1622,7 +1701,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                     !m_bZoomOther )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
-                            "Use of overview factor %d cause gpkg_zoom_other extension to be needed",
+                            "Use of overview factor %d causes gpkg_zoom_other extension to be needed",
                             nOvFactor);
                     RegisterZoomOtherExtension();
                     m_bZoomOther = true;
@@ -1694,14 +1773,15 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                     m_papoOverviewDS[k]->m_nZoomLevel ++;
 
                 GDALGeoPackageDataset* poOvrDS = new GDALGeoPackageDataset();
-                poOvrDS->InitRaster ( this, m_osRasterTable,
-                                      nNewZoomLevel, nBands,
-                                      m_dfTMSMinX, m_dfTMSMaxY,
-                                      dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel,
-                                      nTileWidth, nTileHeight,
-                                      nTileMatrixWidth,nTileMatrixHeight,
-                                      dfGDALMinX, dfGDALMinY,
-                                      dfGDALMaxX, dfGDALMaxY );
+                poOvrDS->InitRaster(
+                    this, m_osRasterTable,
+                    nNewZoomLevel, nBands,
+                    m_dfTMSMinX, m_dfTMSMaxY,
+                    dfPixelXSizeZoomLevel, dfPixelYSizeZoomLevel,
+                    nTileWidth, nTileHeight,
+                    nTileMatrixWidth,nTileMatrixHeight,
+                    dfGDALMinX, dfGDALMinY,
+                    dfGDALMaxX, dfGDALMaxY );
                 m_papoOverviewDS = (GDALGeoPackageDataset**) CPLRealloc(
                     m_papoOverviewDS, sizeof(GDALGeoPackageDataset*) * (m_nOverviewCount+1));
 
@@ -1718,22 +1798,28 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
     }
 
     GDALRasterBand*** papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
-    for( int iBand = 0; iBand < nBands; iBand++ )
+    CPLErr eErr = CE_None;
+    for( int iBand = 0; eErr == CE_None && iBand < nBands; iBand++ )
     {
         papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
         int iCurOverview = 0;
         for(int i=0;i<nOverviews;i++)
         {
-            int   j;
-            for( j = 0; j < m_nOverviewCount; j++ )
+            int j = 0;  // Used after for.
+            for( ; j < m_nOverviewCount; j++ )
             {
-                int    nOvFactor;
                 GDALDataset* poODS = m_papoOverviewDS[j];
 
-                nOvFactor = GDALComputeOvFactor(poODS->GetRasterXSize(),
-                                                GetRasterXSize(),
-                                                poODS->GetRasterYSize(),
-                                                GetRasterYSize());
+                int nOvFactor =
+                    GDALComputeOvFactor(poODS->GetRasterXSize(),
+                                        GetRasterXSize(),
+                                        poODS->GetRasterYSize(),
+                                        GetRasterYSize());
+                if( nOvFactor > 64 &&
+                    ABS(nOvFactor - GetFloorPowerOfTwo(nOvFactor)) <= 2 )
+                {
+                    nOvFactor = GetFloorPowerOfTwo(nOvFactor);
+                }
 
                 if( nOvFactor == panOverviewList[i]
                     || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
@@ -1745,12 +1831,22 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                     break;
                 }
             }
-            CPLAssert(j < m_nOverviewCount);
+            if( j == m_nOverviewCount )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Could not find dataset corresponding to ov factor %d",
+                         panOverviewList[i]);
+                eErr = CE_Failure;
+            }
+        }
+        if( eErr == CE_None )
+        {
+            CPLAssert(iCurOverview == nOverviews);
         }
-        CPLAssert(iCurOverview == nOverviews);
     }
 
-    CPLErr eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBands,
+    if( eErr == CE_None )
+        eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBands,
                                      nOverviews, papapoOverviewBands,
                                      pszResampling, pfnProgress, pProgressData );
 
@@ -1798,14 +1894,14 @@ const char* GDALGeoPackageDataset::CheckMetadataDomain( const char* pszDomain )
 /*                           HasMetadataTables()                        */
 /************************************************************************/
 
-int GDALGeoPackageDataset::HasMetadataTables()
+bool GDALGeoPackageDataset::HasMetadataTables()
 {
     OGRErr err;
-    int nCount = SQLGetInteger(hDB,
+    const int nCount = SQLGetInteger(hDB,
                   "SELECT COUNT(*) FROM sqlite_master WHERE name IN "
                   "('gpkg_metadata', 'gpkg_metadata_reference') "
                   "AND type IN ('table', 'view')", &err);
-    return ( err == OGRERR_NONE && nCount == 2 );
+    return err == OGRERR_NONE && nCount == 2;
 }
 
 /************************************************************************/
@@ -1824,10 +1920,10 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
 
     m_bHasReadMetadataFromStorage = true;
 
-    if ( !HasMetadataTables() )
+    if( !HasMetadataTables() )
         return GDALPamDataset::GetMetadata( pszDomain );
 
-    char* pszSQL;
+    char* pszSQL = NULL;
     if( m_osRasterTable.size() )
     {
         pszSQL = sqlite3_mprintf(
@@ -1962,7 +2058,7 @@ void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be dest
     }
     psXMLNode = NULL;
 
-    char* pszSQL;
+    char* pszSQL = NULL;
     if( pszTableName && pszTableName[0] != '\0' )
     {
         pszSQL = sqlite3_mprintf(
@@ -2049,9 +2145,10 @@ void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be dest
 /*                        CreateMetadataTables()                        */
 /************************************************************************/
 
-int GDALGeoPackageDataset::CreateMetadataTables()
+bool GDALGeoPackageDataset::CreateMetadataTables()
 {
-    int bCreateTriggers = CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
+    const bool bCreateTriggers =
+        CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
 
     /* From C.10. gpkg_metadata Table 35. gpkg_metadata Table Definition SQL  */
     const char* pszMetadata =
@@ -2064,7 +2161,7 @@ int GDALGeoPackageDataset::CreateMetadataTables()
         ")";
 
     if ( OGRERR_NONE != SQLCommand(hDB, pszMetadata) )
-        return FALSE;
+        return false;
 
     /* From D.2. metadata Table 40. metadata Trigger Definition SQL  */
     const char* pszMetadataTriggers =
@@ -2099,7 +2196,7 @@ int GDALGeoPackageDataset::CreateMetadataTables()
     "'collectionHardware','nonGeographicDataset','dimensionGroup')); "
     "END";
     if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszMetadataTriggers) )
-        return FALSE;
+        return false;
 
     /* From C.11. gpkg_metadata_reference Table 36. gpkg_metadata_reference Table Definition SQL */
     const char* pszMetadataReference =
@@ -2116,7 +2213,7 @@ int GDALGeoPackageDataset::CreateMetadataTables()
         ")";
 
     if ( OGRERR_NONE != SQLCommand(hDB, pszMetadataReference) )
-        return FALSE;
+        return false;
 
     /* From D.3. metadata_reference Table 41. gpkg_metadata_reference Trigger Definition SQL   */
     const char* pszMetadataReferenceTriggers =
@@ -2225,9 +2322,9 @@ int GDALGeoPackageDataset::CreateMetadataTables()
         "AND strftime('%s',NEW.timestamp) NOT NULL); "
         "END";
     if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszMetadataReferenceTriggers) )
-        return FALSE;
+        return false;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -2283,7 +2380,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         papszMDDup = CSLInsertString(papszMDDup, -1, *papszIter);
     }
 
-    CPLXMLNode* psXMLNode;
+    CPLXMLNode* psXMLNode = NULL;
     {
         GDALMultiDomainMetadata oLocalMDMD;
         char** papszDomainList = oMDMD.GetDomainList();
@@ -2430,7 +2527,6 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
                                    char **papszOptions )
 {
     CPLString osCommand;
-    const char *pszSpatialRefSysRecord;
 
     /* First, ensure there isn't any such file yet. */
     VSIStatBufL sStatBuf;
@@ -2450,10 +2546,10 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         }
     }
 
-    int bFileExists = FALSE;
+    bool bFileExists = false;
     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     {
-        bFileExists = TRUE;
+        bFileExists = true;
         if( nBandsIn == 0 ||
             !CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) )
         {
@@ -2473,11 +2569,14 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
     m_bPNGSupports2Bands = CPLTestBool(CPLGetConfigOption("GPKG_PNG_SUPPORTS_2BANDS", "TRUE"));
     m_bPNGSupportsCT = CPLTestBool(CPLGetConfigOption("GPKG_PNG_SUPPORTS_CT", "TRUE"));
 
-    if (!OpenOrCreateDB(bFileExists ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE))
+    if( !OpenOrCreateDB(bFileExists
+                        ? SQLITE_OPEN_READWRITE
+                        : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) )
         return FALSE;
 
     /* Default to synchronous=off for performance for new file */
-    if( !bFileExists && CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) == NULL )
+    if( !bFileExists &&
+        CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) == NULL )
     {
         sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL );
     }
@@ -2517,7 +2616,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
         /* contain a record for EPSG:4326, the geodetic WGS84 SRS */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        pszSpatialRefSysRecord =
+        const char *pszSpatialRefSysRecord =
             "INSERT INTO gpkg_spatial_ref_sys ("
             "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
             ") VALUES ("
@@ -2567,7 +2666,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "data_type TEXT NOT NULL,"
             "identifier TEXT UNIQUE,"
             "description TEXT DEFAULT '',"
-            "last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ',CURRENT_TIMESTAMP)),"
+            "last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),"
             "min_x DOUBLE, min_y DOUBLE,"
             "max_x DOUBLE, max_y DOUBLE,"
             "srs_id INTEGER,"
@@ -2852,7 +2951,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         if( pszTilingScheme )
         {
             m_osTilingScheme = pszTilingScheme;
-            int bFound = FALSE;
+            bool bFound = false;
             for(size_t iScheme = 0;
                 iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
                  iScheme++ )
@@ -2880,7 +2979,7 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
                     SetProjection(pszWKT);
                     CPLFree(pszWKT);
 
-                    bFound = TRUE;
+                    bFound = true;
                     break;
                 }
             }
@@ -2898,7 +2997,8 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
     SetApplicationId();
 
     /* Default to synchronous=off for performance for new file */
-    if( !bFileExists && CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) == NULL )
+    if( !bFileExists &&
+        CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) == NULL )
     {
         sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL );
     }
@@ -2965,22 +3065,23 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                    "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
+                 "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or "
+                 "4 (RGBA) band dataset supported");
         CSLDestroy(papszUpdatedOptions);
         return NULL;
     }
 
-    int bFound = FALSE;
+    bool bFound = false;
     int nEPSGCode = 0;
-    size_t iScheme;
-    for(iScheme = 0;
-        iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
-        iScheme++ )
+    size_t iScheme = 0;  // Used after for.
+    for( ;
+         iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
+         iScheme++ )
     {
         if( EQUAL(pszTilingScheme, asTilingShemes[iScheme].pszName) )
         {
             nEPSGCode = asTilingShemes[iScheme].nEPSGCode;
-            bFound = TRUE;
+            bFound = true;
             break;
         }
     }
@@ -3030,8 +3131,8 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     GDALDestroyGenImgProjTransformer( hTransformArg );
     hTransformArg = NULL;
 
-    // Hack to compensate for  GDALSuggestedWarpOutput2() failure when 
-    // reprojection latitude = +/- 90 to EPSG:3857
+    // Hack to compensate for GDALSuggestedWarpOutput2() failure when
+    // reprojection latitude = +/- 90 to EPSG:3857.
     double adfSrcGeoTransform[6];
     if( nEPSGCode == 3857 && poSrcDS->GetGeoTransform(adfSrcGeoTransform) == CE_None )
     {
@@ -3042,13 +3143,22 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
             if( oSrcSRS.SetFromUserInput( pszSrcWKT ) == OGRERR_NONE &&
                 oSrcSRS.IsGeographic() )
             {
-                double minLat = MIN( adfSrcGeoTransform[3], adfSrcGeoTransform[3] + poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5] );
-                double maxLat = MAX( adfSrcGeoTransform[3], adfSrcGeoTransform[3] + poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5] );
+                const double minLat =
+                    MIN( adfSrcGeoTransform[3],
+                         adfSrcGeoTransform[3] +
+                         poSrcDS->GetRasterYSize() *
+                         adfSrcGeoTransform[5] );
+                const double maxLat =
+                    MAX( adfSrcGeoTransform[3],
+                         adfSrcGeoTransform[3] +
+                         poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5] );
                 double maxNorthing = adfGeoTransform[3];
-                double minNorthing = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
+                double minNorthing =
+                    adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
                 bool bChanged = false;
-#define SPHERICAL_RADIUS        6378137.0
-#define MAX_GM                  (SPHERICAL_RADIUS * M_PI)               // 20037508.342789244
+                const double SPHERICAL_RADIUS = 6378137.0;
+                const double MAX_GM =
+                    SPHERICAL_RADIUS * M_PI;  // 20037508.342789244
                 if( maxLat > 89.9999999 )
                 {
                     bChanged = true;
@@ -3070,10 +3180,11 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
         }
     }
 
-    int nZoomLevel;
     double dfComputedRes = adfGeoTransform[1];
-    double dfPrevRes = 0, dfRes = 0;
-    for(nZoomLevel = 0; nZoomLevel < 25; nZoomLevel++)
+    double dfPrevRes = 0.0;
+    double dfRes = 0.0;
+    int nZoomLevel = 0;  // Used after for.
+    for( ; nZoomLevel < 25; nZoomLevel++ )
     {
         dfRes = asTilingShemes[iScheme].dfPixelXSizeZoomLevel0 / (1 << nZoomLevel);
         if( dfComputedRes > dfRes )
@@ -3294,7 +3405,7 @@ void GDALGeoPackageDataset::ParseCompressionOptions(char** papszOptions)
 /*                          RegisterWebPExtension()                     */
 /************************************************************************/
 
-int GDALGeoPackageDataset::RegisterWebPExtension()
+bool GDALGeoPackageDataset::RegisterWebPExtension()
 {
     CreateExtensionsTableIfNecessary();
 
@@ -3304,18 +3415,17 @@ int GDALGeoPackageDataset::RegisterWebPExtension()
         "VALUES "
         "('%q', 'tile_data', 'gpkg_webp', 'GeoPackage 1.0 Specification Annex P', 'read-write')",
         m_osRasterTable.c_str());
-    OGRErr eErr = SQLCommand(hDB, pszSQL);
+    const OGRErr eErr = SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
-    if ( OGRERR_NONE != eErr )
-        return FALSE;
-    return TRUE;
+
+    return OGRERR_NONE == eErr;
 }
 
 /************************************************************************/
 /*                       RegisterZoomOtherExtension()                   */
 /************************************************************************/
 
-int GDALGeoPackageDataset::RegisterZoomOtherExtension()
+bool GDALGeoPackageDataset::RegisterZoomOtherExtension()
 {
     CreateExtensionsTableIfNecessary();
 
@@ -3325,11 +3435,9 @@ int GDALGeoPackageDataset::RegisterZoomOtherExtension()
         "VALUES "
         "('%q', 'gpkg_zoom_other', 'GeoPackage 1.0 Specification Annex O', 'read-write')",
         m_osRasterTable.c_str());
-    OGRErr eErr = SQLCommand(hDB, pszSQL);
+    const OGRErr eErr = SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
-    if ( OGRERR_NONE != eErr )
-        return FALSE;
-    return TRUE;
+    return OGRERR_NONE == eErr;
 }
 
 /************************************************************************/
@@ -3358,8 +3466,6 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
                                       OGRwkbGeometryType eGType,
                                       char **papszOptions )
 {
-    int iLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
@@ -3373,13 +3479,58 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
+    // Check identifier unicity
+    const char* pszIdentifier = CSLFetchNameValue(papszOptions, "IDENTIFIER");
+    if( pszIdentifier != NULL && pszIdentifier[0] == '\0' )
+        pszIdentifier = NULL;
+    if( pszIdentifier != NULL )
+    {
+        for(int i = 0; i < m_nLayers; ++i )
+        {
+            const char* pszOtherIdentifier =
+                m_papoLayers[i]->GetMetadataItem("IDENTIFIER");
+            if( pszOtherIdentifier == NULL )
+                pszOtherIdentifier = m_papoLayers[i]->GetName();
+            if( pszOtherIdentifier != NULL &&
+                EQUAL(pszOtherIdentifier, pszIdentifier) &&
+                !EQUAL(m_papoLayers[i]->GetName(), pszLayerName) )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                     "Identifier %s is already used by table %s",
+                     pszIdentifier, m_papoLayers[i]->GetName());
+                return NULL;
+            }
+        }
+
+        // In case there would be table in gpkg_contents not listed as a
+        // vector layer
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT table_name FROM gpkg_contents WHERE identifier = '%q'",
+            pszIdentifier);
+        SQLResult oResult;
+        OGRErr eErr = SQLQuery (hDB, pszSQL, &oResult);
+        sqlite3_free(pszSQL);
+        if( eErr == OGRERR_NONE && oResult.nRowCount > 0 &&
+            SQLResultGetValue(&oResult, 0, 0) != NULL &&
+            !EQUAL(SQLResultGetValue(&oResult, 0, 0), pszLayerName) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Identifier %s is already used by table %s",
+                     pszIdentifier, SQLResultGetValue(&oResult, 0, 0));
+            SQLResultFree(&oResult);
+            return NULL;
+        }
+        SQLResultFree(&oResult);
+    }
+
     /* Read GEOMETRY_NAME option */
     const char* pszGeomColumnName = CSLFetchNameValue(papszOptions, "GEOMETRY_NAME");
     if (pszGeomColumnName == NULL) /* deprecated name */
         pszGeomColumnName = CSLFetchNameValue(papszOptions, "GEOMETRY_COLUMN");
     if (pszGeomColumnName == NULL)
         pszGeomColumnName = "geom";
-    int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    const bool bGeomNullable =
+        CPLFetchBool((const char**)papszOptions, "GEOMETRY_NULLABLE", true);
 
     /* Read FID option */
     const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
@@ -3412,7 +3563,7 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
     }
 
     /* Check for any existing layers that already use this name */
-    for( iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName, m_papoLayers[iLayer]->GetName()) )
         {
@@ -3440,7 +3591,7 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
                                     bGeomNullable,
                                     poSpatialRef,
                                     pszFIDColumnName,
-                                    CSLFetchNameValue(papszOptions, "IDENTIFIER"),
+                                    pszIdentifier,
                                     CSLFetchNameValue(papszOptions, "DESCRIPTION") );
 
     /* Should we create a spatial index ? */
@@ -3451,14 +3602,34 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
         poLayer->SetDeferredSpatialIndexCreation(true);
     }
 
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
-    poLayer->SetTruncateFieldsFlag( CSLFetchBoolean(papszOptions,"TRUNCATE_FIELDS",FALSE));
+    poLayer->SetPrecisionFlag( CPLFetchBool((const char**)papszOptions, "PRECISION", true) );
+    poLayer->SetTruncateFieldsFlag(
+        CPLFetchBool((const char**)papszOptions, "TRUNCATE_FIELDS", false));
+    if( eGType == wkbNone )
+    {
+        poLayer->SetRegisterAsAspatial( CPLFetchBool(
+            (const char**)papszOptions,"REGISTER_AS_ASPATIAL",true) );
+    }
 
     m_papoLayers = (OGRGeoPackageTableLayer**)CPLRealloc(m_papoLayers,  sizeof(OGRGeoPackageTableLayer*) * (m_nLayers+1));
     m_papoLayers[m_nLayers++] = poLayer;
     return poLayer;
 }
 
+/************************************************************************/
+/*                          FindLayerIndex()                            */
+/************************************************************************/
+
+int GDALGeoPackageDataset::FindLayerIndex( const char *pszLayerName )
+
+{
+    for( int iLayer = 0; iLayer < m_nLayers; iLayer++ )
+    {
+        if( EQUAL(pszLayerName,m_papoLayers[iLayer]->GetName()) )
+            return iLayer;
+    }
+    return -1;
+}
 
 /************************************************************************/
 /*                            DeleteLayer()                             */
@@ -3466,52 +3637,97 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
 
 OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
 {
-    char *pszSQL;
-
     if( !bUpdate || iLayer < 0 || iLayer >= m_nLayers )
         return OGRERR_FAILURE;
 
-    CPLString osLayerName = m_papoLayers[iLayer]->GetLayerDefn()->GetName();
+    m_papoLayers[iLayer]->ResetReading();
+    m_papoLayers[iLayer]->RunDeferredCreationIfNecessary();
+    m_papoLayers[iLayer]->CreateSpatialIndexIfNecessary();
+
+    CPLString osLayerName = m_papoLayers[iLayer]->GetName();
 
     CPLDebug( "GPKG", "DeleteLayer(%s)", osLayerName.c_str() );
 
+    if( SoftStartTransaction() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
     if( m_papoLayers[iLayer]->HasSpatialIndex() )
         m_papoLayers[iLayer]->DropSpatialIndex();
 
-    /* Delete the layer object and remove the gap in the layers list */
-    delete m_papoLayers[iLayer];
-    memmove( m_papoLayers + iLayer, m_papoLayers + iLayer + 1,
-             sizeof(void *) * (m_nLayers - iLayer - 1) );
-    m_nLayers--;
-
-    if (osLayerName.size() == 0)
-        return OGRERR_NONE;
-
-    pszSQL = sqlite3_mprintf(
-            "DROP TABLE \"%s\"",
+    char* pszSQL = sqlite3_mprintf(
+            "DELETE FROM gpkg_geometry_columns WHERE table_name = '%q'",
              osLayerName.c_str());
-
-    SQLCommand(hDB, pszSQL);
+    OGRErr eErr = SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf(
-            "DELETE FROM gpkg_geometry_columns WHERE table_name = '%q'",
-             osLayerName.c_str());
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_contents WHERE table_name = '%q'",
+                osLayerName.c_str());
+        eErr = SQLCommand(hDB, pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
-    SQLCommand(hDB, pszSQL);
-    sqlite3_free(pszSQL);
+    if( eErr == OGRERR_NONE && HasExtensionsTable() )
+    {
+        pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_extensions WHERE table_name = '%q'",
+                osLayerName.c_str());
+        eErr = SQLCommand(hDB, pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
-    pszSQL = sqlite3_mprintf(
-             "DELETE FROM gpkg_contents WHERE table_name = '%q'",
-              osLayerName.c_str());
+    if( eErr == OGRERR_NONE && HasMetadataTables() )
+    {
+        pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_metadata_reference WHERE table_name = '%q'",
+                osLayerName.c_str());
+        eErr = SQLCommand(hDB, pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
-    SQLCommand(hDB, pszSQL);
-    sqlite3_free(pszSQL);
+    if( eErr == OGRERR_NONE && HasDataColumnsTable() )
+    {
+        pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_data_columns WHERE table_name = '%q'",
+                osLayerName.c_str());
+        eErr = SQLCommand(hDB, pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
-    return OGRERR_NONE;
-}
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf("DROP TABLE '%q'", osLayerName.c_str());
+        eErr = SQLCommand(hDB, pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
+    // Check foreign key integrity
+    if ( eErr == OGRERR_NONE )
+    {
+        eErr = PragmaCheck("foreign_key_check", "", 0);
+    }
+
+    if( eErr == OGRERR_NONE )
+    {
+        eErr = SoftCommitTransaction();
+        if( eErr == OGRERR_NONE )
+        {
+            /* Delete the layer object and remove the gap in the layers list */
+            delete m_papoLayers[iLayer];
+            memmove( m_papoLayers + iLayer, m_papoLayers + iLayer + 1,
+                    sizeof(void *) * (m_nLayers - iLayer - 1) );
+            m_nLayers--;
+        }
+    }
+    else
+    {
+        SoftRollbackTransaction();
+    }
 
+    return eErr;
+}
 
 /************************************************************************/
 /*                       TestCapability()                               */
@@ -3520,7 +3736,8 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
 int GDALGeoPackageDataset::TestCapability( const char * pszCap )
 {
     if ( EQUAL(pszCap,ODsCCreateLayer) ||
-         EQUAL(pszCap,ODsCDeleteLayer) )
+         EQUAL(pszCap,ODsCDeleteLayer) ||
+         EQUAL(pszCap,"RenameLayer") )
     {
          return bUpdate;
     }
@@ -3528,10 +3745,23 @@ int GDALGeoPackageDataset::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
+
     return OGRSQLiteBaseDataSource::TestCapability(pszCap);
 }
 
 /************************************************************************/
+/*                       ResetReadingAllLayers()                        */
+/************************************************************************/
+
+void GDALGeoPackageDataset::ResetReadingAllLayers()
+{
+    for( int i = 0; i < m_nLayers; i++ )
+    {
+        m_papoLayers[i]->ResetReading();
+    }
+}
+
+/************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
 
@@ -3539,6 +3769,7 @@ static const char* const apszFuncsWithSideEffects[] =
 {
     "CreateSpatialIndex",
     "DisableSpatialIndex",
+    "HasSpatialIndex",
 };
 
 OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
@@ -3555,6 +3786,110 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         m_papoLayers[i]->CreateSpatialIndexIfNecessary();
     }
 
+/* -------------------------------------------------------------------- */
+/*      Special case DELLAYER: command.                                 */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") )
+    {
+        const char *pszLayerName = pszSQLCommand + strlen("DELLAYER:");
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        int idx = FindLayerIndex( pszLayerName );
+        if( idx >= 0 )
+            DeleteLayer( idx );
+        else
+            CPLError(CE_Failure, CPLE_AppDefined, "Unknown layer: %s",
+                     pszLayerName);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case RECOMPUTE EXTENT ON command.                       */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "RECOMPUTE EXTENT ON ") )
+    {
+        const char *pszLayerName = pszSQLCommand + strlen("RECOMPUTE EXTENT ON ");
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        int idx = FindLayerIndex( pszLayerName );
+        if( idx >= 0 )
+        {
+            m_papoLayers[idx]->RecomputeExtent();
+        }
+        else
+            CPLError(CE_Failure, CPLE_AppDefined, "Unknown layer: %s",
+                     pszLayerName);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Intercept DROP TABLE                                            */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "DROP TABLE ") )
+    {
+        const char *pszLayerName = pszSQLCommand + strlen("DROP TABLE ");
+
+        while( *pszLayerName == ' ' )
+            pszLayerName++;
+
+        int idx = FindLayerIndex( SQLUnescapeDoubleQuote(pszLayerName) );
+        if( idx >= 0 )
+        {
+            DeleteLayer( idx );
+            return NULL;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Intercept ALTER TABLE ... RENAME TO                             */
+/* -------------------------------------------------------------------- */
+    if( STARTS_WITH_CI(pszSQLCommand, "ALTER TABLE ") )
+    {
+        char **papszTokens = SQLTokenize( pszSQLCommand );
+        /* ALTER TABLE src_table RENAME TO dst_table */
+        if( CSLCount(papszTokens) == 6 && EQUAL(papszTokens[3], "RENAME") &&
+            EQUAL(papszTokens[4], "TO") )
+        {
+            const char* pszSrcTableName = papszTokens[2];
+            const char* pszDstTableName = papszTokens[5];
+            OGRGeoPackageTableLayer* poSrcLayer =
+                (OGRGeoPackageTableLayer*)GetLayerByName(
+                        SQLUnescapeDoubleQuote(pszSrcTableName));
+            if( poSrcLayer )
+            {
+                poSrcLayer->RenameTo( SQLUnescapeDoubleQuote(pszDstTableName) );
+                CSLDestroy(papszTokens);
+                return NULL;
+            }
+        }
+        CSLDestroy(papszTokens);
+    }
+
+    if( EQUAL(pszSQLCommand, "VACUUM") )
+    {
+        ResetReadingAllLayers();
+    }
+
+    if( EQUAL(pszSQLCommand, "BEGIN") )
+    {
+        SoftStartTransaction();
+        return NULL;
+    }
+    else if( EQUAL(pszSQLCommand, "COMMIT") )
+    {
+        SoftCommitTransaction();
+        return NULL;
+    }
+    else if( EQUAL(pszSQLCommand, "ROLLBACK") )
+    {
+        SoftRollbackTransaction();
+        return NULL;
+    }
+
     if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
         return GDALDataset::ExecuteSQL( pszSQLCommand,
                                           poSpatialFilter,
@@ -3567,7 +3902,6 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Prepare statement.                                              */
 /* -------------------------------------------------------------------- */
-    int rc;
     sqlite3_stmt *hSQLStmt = NULL;
 
     CPLString osSQLCommand = pszSQLCommand;
@@ -3575,8 +3909,8 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
     /* This will speed-up layer creation */
     /* ORDER BY are costly to evaluate and are not necessary to establish */
     /* the layer definition. */
-    int bUseStatementForGetNextFeature = TRUE;
-    int bEmptyLayer = FALSE;
+    bool bUseStatementForGetNextFeature = true;
+    bool bEmptyLayer = false;
 
     if( osSQLCommand.ifind("SELECT ") == 0 &&
         osSQLCommand.ifind(" UNION ") == std::string::npos &&
@@ -3587,13 +3921,13 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         if( nOrderByPos != std::string::npos )
         {
             osSQLCommand.resize(nOrderByPos);
-            bUseStatementForGetNextFeature = FALSE;
+            bUseStatementForGetNextFeature = false;
         }
     }
 
-    rc = sqlite3_prepare( hDB, osSQLCommand.c_str(),
-                          static_cast<int>(osSQLCommand.size()),
-                          &hSQLStmt, NULL );
+    int rc = sqlite3_prepare( hDB, osSQLCommand.c_str(),
+                              static_cast<int>(osSQLCommand.size()),
+                              &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
     {
@@ -3633,32 +3967,14 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
             return NULL;
         }
 
-        if( STARTS_WITH_CI(pszSQLCommand, "ALTER TABLE ") )
-        {
-            char **papszTokens = CSLTokenizeString( pszSQLCommand );
-            /* ALTER TABLE src_table RENAME TO dst_table */
-            if( CSLCount(papszTokens) == 6 && EQUAL(papszTokens[3], "RENAME") &&
-                EQUAL(papszTokens[4], "TO") )
-            {
-                const char* pszSrcTableName = papszTokens[2];
-                const char* pszDstTableName = papszTokens[5];
-                OGRGeoPackageTableLayer* poSrcLayer = (OGRGeoPackageTableLayer*)GetLayerByName(pszSrcTableName);
-                if( poSrcLayer )
-                {
-                    poSrcLayer->RenameTo( pszDstTableName );
-                }
-            }
-            CSLDestroy(papszTokens);
-        }
-
         if( !STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
         {
             sqlite3_finalize( hSQLStmt );
             return NULL;
         }
 
-        bUseStatementForGetNextFeature = FALSE;
-        bEmptyLayer = TRUE;
+        bUseStatementForGetNextFeature = false;
+        bEmptyLayer = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -3718,10 +4034,11 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
     OGRLayer *poLayer = NULL;
 
     CPLString osSQL = pszSQLCommand;
-    poLayer = new OGRGeoPackageSelectLayer( this, osSQL, hSQLStmt,
-                                        bUseStatementForGetNextFeature, bEmptyLayer );
+    poLayer = new OGRGeoPackageSelectLayer(
+        this, osSQL, hSQLStmt,
+        bUseStatementForGetNextFeature, bEmptyLayer );
 
-    if( poSpatialFilter != NULL )
+    if( poSpatialFilter != NULL && poLayer->GetLayerDefn()->GetGeomFieldCount() > 0 )
         poLayer->SetSpatialFilter( 0, poSpatialFilter );
 
     return poLayer;
@@ -3761,7 +4078,7 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(bool bCheckRasterTable)
     if( !HasExtensionsTable() )
         return;
 
-    char* pszSQL;
+    char* pszSQL = NULL;
     if( !bCheckRasterTable)
         pszSQL = sqlite3_mprintf(
             "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE (table_name IS NULL AND extension_name != 'gdal_aspatial')"
@@ -3911,19 +4228,34 @@ OGRErr GDALGeoPackageDataset::CreateExtensionsTableIfNecessary()
 }
 
 /************************************************************************/
+/*                         HasDataColumnsTable()                        */
+/************************************************************************/
+
+bool GDALGeoPackageDataset::HasDataColumnsTable()
+{
+    SQLResult oResultTable;
+    OGRErr err = SQLQuery(hDB,
+        "SELECT * FROM sqlite_master WHERE name = 'gpkg_data_columns' "
+        "AND type IN ('table', 'view')", &oResultTable);
+    bool bHasExtensionsTable = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
+    SQLResultFree(&oResultTable);
+    return bHasExtensionsTable;
+}
+
+/************************************************************************/
 /*                     OGRGeoPackageGetHeader()                         */
 /************************************************************************/
 
-static int OGRGeoPackageGetHeader(sqlite3_context* pContext,
-                                  CPL_UNUSED int argc,
-                                  sqlite3_value** argv,
-                                  GPkgHeader* psHeader,
-                                  int bNeedExtent)
+static bool OGRGeoPackageGetHeader( sqlite3_context* pContext,
+                                    CPL_UNUSED int argc,
+                                    sqlite3_value** argv,
+                                    GPkgHeader* psHeader,
+                                    bool bNeedExtent )
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_BLOB )
     {
         sqlite3_result_null(pContext);
-        return FALSE;
+        return false;
     }
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     const GByte* pabyBLOB = (const GByte *) sqlite3_value_blob (argv[0]);
@@ -3931,7 +4263,7 @@ static int OGRGeoPackageGetHeader(sqlite3_context* pContext,
         GPkgHeaderFromWKB(pabyBLOB, nBLOBLen, psHeader) != OGRERR_NONE )
     {
         sqlite3_result_null(pContext);
-        return FALSE;
+        return false;
     }
     if( !(psHeader->bExtentHasXY) && bNeedExtent )
     {
@@ -3940,7 +4272,7 @@ static int OGRGeoPackageGetHeader(sqlite3_context* pContext,
         {
             sqlite3_result_null(pContext);
             delete poGeom;
-            return FALSE;
+            return false;
         }
         OGREnvelope sEnvelope;
         poGeom->getEnvelope(&sEnvelope);
@@ -3950,7 +4282,7 @@ static int OGRGeoPackageGetHeader(sqlite3_context* pContext,
         psHeader->MaxY = sEnvelope.MaxY;
         delete poGeom;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3962,7 +4294,7 @@ void OGRGeoPackageSTMinX(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, TRUE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, true) )
         return;
     sqlite3_result_double( pContext, sHeader.MinX );
 }
@@ -3976,7 +4308,7 @@ void OGRGeoPackageSTMinY(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, TRUE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, true) )
         return;
     sqlite3_result_double( pContext, sHeader.MinY );
 }
@@ -3990,7 +4322,7 @@ void OGRGeoPackageSTMaxX(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, TRUE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, true) )
         return;
     sqlite3_result_double( pContext, sHeader.MaxX );
 }
@@ -4004,7 +4336,7 @@ void OGRGeoPackageSTMaxY(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, TRUE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, true) )
         return;
     sqlite3_result_double( pContext, sHeader.MaxY );
 }
@@ -4018,7 +4350,7 @@ void OGRGeoPackageSTIsEmpty(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, FALSE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, false) )
         return;
     sqlite3_result_int( pContext, sHeader.bEmpty );
 }
@@ -4032,7 +4364,7 @@ void OGRGeoPackageSTGeometryType(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, FALSE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, false) )
         return;
 
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
@@ -4083,7 +4415,7 @@ void OGRGeoPackageSTSRID(sqlite3_context* pContext,
                         int argc, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, FALSE) )
+    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, false) )
         return;
     sqlite3_result_int( pContext, sHeader.iSrsId );
 }
@@ -4163,6 +4495,46 @@ void OGRGeoPackageDisableSpatialIndex(sqlite3_context* pContext,
 }
 
 /************************************************************************/
+/*                  OGRGeoPackageHasSpatialIndex()                      */
+/************************************************************************/
+
+static
+void OGRGeoPackageHasSpatialIndex(sqlite3_context* pContext,
+                                  CPL_UNUSED int argc,
+                                  sqlite3_value** argv)
+{
+    if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
+        sqlite3_value_type (argv[1]) != SQLITE_TEXT )
+    {
+        sqlite3_result_int( pContext, 0 );
+        return;
+    }
+
+    const char* pszTableName = (const char*)sqlite3_value_text(argv[0]);
+    const char* pszGeomName = (const char*)sqlite3_value_text(argv[1]);
+    GDALGeoPackageDataset* poDS = (GDALGeoPackageDataset* )sqlite3_user_data(pContext);
+
+    OGRGeoPackageTableLayer* poLyr = (OGRGeoPackageTableLayer*)poDS->GetLayerByName(pszTableName);
+    if( poLyr == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Unknown layer name");
+        sqlite3_result_int( pContext, 0 );
+        return;
+    }
+    if( !EQUAL(poLyr->GetGeometryColumn(), pszGeomName) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Unknown geometry column name");
+        sqlite3_result_int( pContext, 0 );
+        return;
+    }
+
+    poLyr->RunDeferredCreationIfNecessary();
+    poLyr->CreateSpatialIndexIfNecessary();
+
+    sqlite3_result_int( pContext, poLyr->HasSpatialIndex() );
+}
+
+/************************************************************************/
 /*                       GPKG_hstore_get_value()                        */
 /************************************************************************/
 
@@ -4197,7 +4569,8 @@ static CPLString GPKG_GDAL_GetMemFileFromBlob(sqlite3_value** argv)
     const GByte* pabyBLOB = (const GByte *) sqlite3_value_blob (argv[0]);
     CPLString osMemFileName;
     osMemFileName.Printf("/vsimem/GPKG_GDAL_GetMemFileFromBlob_%p", argv);
-    VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), (GByte*)pabyBLOB,
+    VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(),
+                                          (GByte*)pabyBLOB,
                                           nBytes, FALSE);
     VSIFCloseL(fp);
     return osMemFileName;
@@ -4222,7 +4595,7 @@ void GPKG_GDAL_GetMimeType(sqlite3_context* pContext,
     GDALDriver* poDriver = (GDALDriver*)GDALIdentifyDriver(osMemFileName, NULL);
     if( poDriver != NULL )
     {
-        const char* pszRes;
+        const char* pszRes = NULL;
         if( EQUAL(poDriver->GetDescription(), "PNG") )
             pszRes = "image/png";
         else if( EQUAL(poDriver->GetDescription(), "JPEG") )
@@ -4302,11 +4675,12 @@ void GPKG_GDAL_HasColorTable(sqlite3_context* pContext,
 /*                         OpenOrCreateDB()                             */
 /************************************************************************/
 
-int GDALGeoPackageDataset::OpenOrCreateDB(int flags)
+bool GDALGeoPackageDataset::OpenOrCreateDB(int flags)
 {
-    int bSuccess = OGRSQLiteBaseDataSource::OpenOrCreateDB(flags, FALSE);
+    const bool bSuccess =
+        CPL_TO_BOOL(OGRSQLiteBaseDataSource::OpenOrCreateDB(flags, FALSE));
     if( !bSuccess )
-        return FALSE;
+        return false;
 
 #ifdef SPATIALITE_412_OR_LATER
     InitNewSpatialite();
@@ -4344,6 +4718,8 @@ int GDALGeoPackageDataset::OpenOrCreateDB(int flags)
                             OGRGeoPackageCreateSpatialIndex, NULL, NULL);
     sqlite3_create_function(hDB, "DisableSpatialIndex", 2, SQLITE_ANY, this,
                             OGRGeoPackageDisableSpatialIndex, NULL, NULL);
+    sqlite3_create_function(hDB, "HasSpatialIndex", 2, SQLITE_ANY, this,
+                            OGRGeoPackageHasSpatialIndex, NULL, NULL);
 
     // HSTORE functions
     sqlite3_create_function(hDB, "hstore_get_value", 2, SQLITE_ANY, NULL,
@@ -4360,7 +4736,7 @@ int GDALGeoPackageDataset::OpenOrCreateDB(int flags)
                                 GPKG_GDAL_HasColorTable, NULL, NULL);
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
index 8ab5dc2..4b658b6 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements GeoPackageDriver.
@@ -29,6 +28,8 @@
 
 #include "ogr_geopackage.h"
 
+CPL_CVSID("$Id: ogrgeopackagedriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 // g++ -g -Wall -fPIC -shared -o ogr_geopackage.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpkg ogr/ogrsf_frmts/gpkg/*.c* -L. -lgdal
 
 
@@ -245,6 +246,7 @@ void RegisterOGRGeoPackage()
 "  <Option name='DITHER' type='boolean' description='Whether to apply Floyd-Steinberg dithering (for TILE_FORMAT=PNG8)' default='NO'/>"
 
     poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
+"  <Option name='LIST_ALL_TABLES' type='boolean' description='Whether all tables, including those non listed in gpkg_contents, should be listed' default='YES' />"
 "  <Option name='TABLE' type='string' description='Name of tile user-table'/>"
 "  <Option name='ZOOM_LEVEL' type='integer' description='Zoom level of full resolution. If not specified, maximum non-empty zoom level'/>"
 "  <Option name='BAND_COUNT' type='int' min='1' max='4' description='Number of raster bands' default='4'/>"
@@ -301,6 +303,7 @@ COMPRESSION_OPTIONS
 "  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
 "  <Option name='IDENTIFIER' type='string' description='Identifier of the layer, as put in the contents table'/>"
 "  <Option name='DESCRIPTION' type='string' description='Description of the layer, as put in the contents table'/>"
+"  <Option name='REGISTER_AS_ASPATIAL' type='boolean' description='Whether non spatial tables should be registered as aspatial in gpkg_contents' default='YES'/>"
 "</LayerCreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
index a7c0657..145bb53 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements OGRGeoPackageLayer class
@@ -32,6 +31,8 @@
 #include "ogrgeopackageutility.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: ogrgeopackagelayer.cpp 35503 2016-09-23 18:22:45Z goatbar $");
+
 /************************************************************************/
 /*                      OGRGeoPackageLayer()                            */
 /************************************************************************/
@@ -41,13 +42,12 @@ OGRGeoPackageLayer::OGRGeoPackageLayer(GDALGeoPackageDataset *poDS) :
     m_poFeatureDefn(NULL),
     iNextShapeId(0),
     m_poQueryStatement(NULL),
-    bDoStep(TRUE),
+    bDoStep(true),
     m_pszFidColumn(NULL),
     iFIDCol(-1),
     iGeomCol(-1),
     panFieldOrdinals(NULL)
-{
-}
+{}
 
 /************************************************************************/
 /*                      ~OGRGeoPackageLayer()                           */
@@ -103,8 +103,6 @@ OGRFeature *OGRGeoPackageLayer::GetNextFeature()
 {
     for( ; true; )
     {
-        OGRFeature      *poFeature;
-
         if( m_poQueryStatement == NULL )
         {
             ResetStatement();
@@ -117,9 +115,7 @@ OGRFeature *OGRGeoPackageLayer::GetNextFeature()
     /* -------------------------------------------------------------------- */
         if( bDoStep )
         {
-            int rc;
-
-            rc = sqlite3_step( m_poQueryStatement );
+            int rc = sqlite3_step( m_poQueryStatement );
             if( rc != SQLITE_ROW )
             {
                 if ( rc != SQLITE_DONE )
@@ -136,9 +132,11 @@ OGRFeature *OGRGeoPackageLayer::GetNextFeature()
             }
         }
         else
-            bDoStep = TRUE;
+        {
+            bDoStep = true;
+        }
 
-        poFeature = TranslateFeature(m_poQueryStatement);
+        OGRFeature *poFeature = TranslateFeature(m_poQueryStatement);
         if( poFeature == NULL )
             return NULL;
 
@@ -159,7 +157,6 @@ OGRFeature *OGRGeoPackageLayer::GetNextFeature()
 OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
 
 {
-
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
@@ -364,7 +361,7 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
                 const GByte* pabyGpkg = (const GByte*)sqlite3_column_blob( hStmt, iCol  );
                 GPkgHeader oHeader;
                 OGRGeometry* poGeom = NULL;
-                int nSRID;
+                int nSRID = 0;
                 if( GPkgHeaderFromWKB(pabyGpkg, nBytes, &oHeader) == OGRERR_NONE &&
                     (poGeom = GPkgGeometryToOGR(pabyGpkg, nBytes, NULL)) != NULL )
                 {
@@ -462,8 +459,9 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
         if (pszDeclType != NULL)
         {
             OGRFieldSubType eSubType;
-            int nMaxWidth;
-            OGRFieldType eFieldType = GPkgFieldToOGR(pszDeclType, eSubType, nMaxWidth);
+            int nMaxWidth = 0;
+            const OGRFieldType eFieldType =
+                GPkgFieldToOGR(pszDeclType, eSubType, nMaxWidth);
             if( (int)eFieldType <= OFTMaxType )
             {
                 oField.SetType(eFieldType);
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
index d206e2e..155a36e 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements OGRGeoPackageTableLayer class
@@ -33,6 +32,11 @@
 #include "cpl_time.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: ogrgeopackagetablelayer.cpp 35695 2016-10-11 17:39:33Z rouault $");
+
+static const char UNSUPPORTED_OP_READ_ONLY[] =
+  "%s : unsupported operation on a read-only datasource.";
+
 //----------------------------------------------------------------------
 // SaveExtent()
 //
@@ -66,6 +70,50 @@ OGRErr OGRGeoPackageTableLayer::SaveExtent()
 }
 
 //----------------------------------------------------------------------
+// SaveTimestamp()
+//
+// Update the last_change column of the gpkg_contents metadata table.
+//
+OGRErr OGRGeoPackageTableLayer::SaveTimestamp()
+{
+    if ( !m_poDS->GetUpdate() || !m_bContentChanged )
+        return OGRERR_NONE;
+
+    m_bContentChanged = false;
+
+    sqlite3* poDb = m_poDS->GetDB();
+
+    if ( ! poDb ) return OGRERR_FAILURE;
+
+    const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
+    char *pszSQL = NULL;
+
+    if( pszCurrentDate )
+    {
+        pszSQL = sqlite3_mprintf(
+                    "UPDATE gpkg_contents SET "
+                    "last_change = '%q'"
+                    "WHERE table_name = '%q' AND "
+                    "Lower(data_type) IN ('features', 'gdal_aspatial')",
+                    m_pszTableName, pszCurrentDate);
+    }
+    else
+    {
+        pszSQL = sqlite3_mprintf(
+                    "UPDATE gpkg_contents SET "
+                    "last_change = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ','now')"
+                    "WHERE table_name = '%q' AND "
+                    "Lower(data_type) IN ('features', 'gdal_aspatial')",
+                    m_pszTableName);
+    }
+
+    OGRErr err = SQLCommand(poDb, pszSQL);
+    sqlite3_free(pszSQL);
+
+    return err;
+}
+
+//----------------------------------------------------------------------
 // UpdateExtent()
 //
 // Expand the layer envelope if necessary to reflect the bounds
@@ -107,7 +155,7 @@ OGRErr OGRGeoPackageTableLayer::BuildColumns()
     if ( m_poFeatureDefn->GetGeomFieldCount() )
     {
         soColumns += ", ";
-        soColumn.Printf("\"%s\"", m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
+        soColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
         soColumns += soColumn;
         iGeomCol = 1;
     }
@@ -116,7 +164,7 @@ OGRErr OGRGeoPackageTableLayer::BuildColumns()
     for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
     {
         soColumns += ", ";
-        soColumn.Printf("\"%s\"", m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        soColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(m_poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
         soColumns += soColumn;
         panFieldOrdinals[i] = 1 + (iGeomCol >= 0) + i;
     }
@@ -131,15 +179,11 @@ OGRErr OGRGeoPackageTableLayer::BuildColumns()
 // Utility method to determine if there is a non-Null geometry
 // in an OGRGeometry.
 //
-OGRBoolean OGRGeoPackageTableLayer::IsGeomFieldSet( OGRFeature *poFeature )
+bool OGRGeoPackageTableLayer::IsGeomFieldSet( OGRFeature *poFeature )
 {
-    if ( poFeature->GetDefnRef()->GetGeomFieldCount() &&
-         poFeature->GetGeomFieldRef(0) )
-    {
-        return TRUE;
-    }
-
-    return FALSE;
+    return
+        poFeature->GetDefnRef()->GetGeomFieldCount() &&
+        poFeature->GetGeomFieldRef(0);
 }
 
 OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
@@ -148,17 +192,16 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                                                        bool bAddFID,
                                                        bool bBindNullFields )
 {
-    int nColCount = 1;
-    int err;
-
     if ( ! (poFeature && poStmt && pnColCount) )
         return OGRERR_FAILURE;
 
     OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
 
+    int nColCount = 1;
     if( bAddFID )
     {
-        err = sqlite3_bind_int64(poStmt, nColCount++, poFeature->GetFID());
+        const int err =
+            sqlite3_bind_int64(poStmt, nColCount++, poFeature->GetFID());
         if ( err != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -172,11 +215,12 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
     {
         GByte *pabyWkb = NULL;
 
-        /* Non-NULL geometry */
+        int err = SQLITE_OK;
+        // Non-NULL geometry.
         OGRGeometry* poGeom = poFeature->GetGeomFieldRef(0);
         if ( poGeom )
         {
-            size_t szWkb;
+            size_t szWkb = 0;
             pabyWkb = GPkgGeometryFromOGR(poGeom, m_iSrs, &szWkb);
             err = sqlite3_bind_blob(poStmt, nColCount++, pabyWkb,
                                     static_cast<int>(szWkb), CPLFree);
@@ -200,8 +244,10 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
     }
 
     /* Bind the attributes using appropriate SQLite data types */
-    err = SQLITE_OK;
-    for( int i = 0; err == SQLITE_OK && i < poFeatureDefn->GetFieldCount(); i++ )
+    int err = SQLITE_OK;
+    for( int i = 0;
+         err == SQLITE_OK && i < poFeatureDefn->GetFieldCount();
+         i++ )
     {
         if( i == m_iFIDAsRegularColumnIndex )
             continue;
@@ -223,7 +269,7 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                 }
                 case SQLITE_BLOB:
                 {
-                    int szBlob;
+                    int szBlob = 0;
                     GByte *pabyBlob = poFeature->GetFieldAsBinary(i, &szBlob);
                     err = sqlite3_bind_blob(poStmt, nColCount++, pabyBlob, szBlob, NULL);
                     break;
@@ -244,8 +290,10 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                     }
                     else if( poFieldDefn->GetType() == OFTDateTime )
                     {
-                        float fSecond;
-                        poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond, &nTZFlag);
+                        float fSecond = 0.0f;
+                        poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
+                                                      &nHour, &nMinute,
+                                                      &fSecond, &nTZFlag);
                         if( nTZFlag == 0 || nTZFlag == 100 )
                         {
                             if( OGR_GET_MS(fSecond) )
@@ -329,13 +377,15 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
 OGRErr OGRGeoPackageTableLayer::FeatureBindUpdateParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt )
 {
 
-    int nColCount;
-    OGRErr err = FeatureBindParameters( poFeature, poStmt, &nColCount, false, true );
+    int nColCount = 0;
+    const OGRErr err =
+        FeatureBindParameters( poFeature, poStmt, &nColCount, false, true );
     if ( err != OGRERR_NONE )
         return err;
 
-    /* Bind the FID to the "WHERE" clause */
-    int sqlite_err = sqlite3_bind_int64(poStmt, nColCount, poFeature->GetFID());
+    // Bind the FID to the "WHERE" clause.
+    const int sqlite_err =
+        sqlite3_bind_int64(poStmt, nColCount, poFeature->GetFID());
     if ( sqlite_err != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -360,8 +410,10 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindInsertParameters( OGRFeature *poFeatu
                                                              bool bAddFID,
                                                              bool bBindNullFields )
 {
-    int nColCount;
-    return FeatureBindParameters( poFeature, poStmt, &nColCount, bAddFID, bBindNullFields );
+    int nColCount = 0;
+    return
+        FeatureBindParameters( poFeature, poStmt, &nColCount,
+                               bAddFID, bBindNullFields );
 }
 
 
@@ -385,11 +437,13 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
     if( poFeatureDefn->GetFieldCount() == ((m_iFIDAsRegularColumnIndex >= 0) ? 1 : 0) &&
         poFeatureDefn->GetGeomFieldCount() == 0 &&
         !bAddFID )
-        return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES", m_pszTableName);
+        return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES",
+                          SQLEscapeDoubleQuote(m_pszTableName).c_str());
 
     /* Set up our SQL string basics */
     CPLString osSQLFront;
-    osSQLFront.Printf("INSERT INTO \"%s\" ( ", m_pszTableName);
+    osSQLFront.Printf("INSERT INTO \"%s\" ( ",
+                      SQLEscapeDoubleQuote(m_pszTableName).c_str());
 
     CPLString osSQLBack;
     osSQLBack = ") VALUES (";
@@ -398,7 +452,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
 
     if( bAddFID )
     {
-        osSQLColumn.Printf("\"%s\"", GetFIDColumn());
+        osSQLColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(GetFIDColumn()).c_str());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
         bNeedComma = true;
@@ -412,7 +466,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
             osSQLBack += ", ";
         }
 
-        osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
+        osSQLColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
         bNeedComma = true;
@@ -436,7 +490,8 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
             osSQLBack += ", ";
         }
 
-        osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        osSQLColumn.Printf("\"%s\"",
+                           SQLEscapeDoubleQuote(poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
     }
@@ -444,7 +499,8 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
     osSQLBack += ")";
 
     if( !bNeedComma )
-        return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES", m_pszTableName);
+        return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES",
+                          SQLEscapeDoubleQuote(m_pszTableName).c_str());
 
     return osSQLFront + osSQLBack;
 }
@@ -468,13 +524,15 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
 
     /* Set up our SQL string basics */
     CPLString osUpdate;
-    osUpdate.Printf("UPDATE \"%s\" SET ", m_pszTableName);
+    osUpdate.Printf("UPDATE \"%s\" SET ",
+                    SQLEscapeDoubleQuote(m_pszTableName).c_str());
 
     CPLString osSQLColumn;
 
     if ( poFeatureDefn->GetGeomFieldCount() > 0 )
     {
-        osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
+        osSQLColumn.Printf("\"%s\"",
+                           SQLEscapeDoubleQuote(poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
         osUpdate += osSQLColumn;
         osUpdate += "=?";
         bNeedComma = true;
@@ -490,13 +548,15 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
         else
             osUpdate += ", ";
 
-        osSQLColumn.Printf("\"%s\"", poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        osSQLColumn.Printf("\"%s\"",
+                           SQLEscapeDoubleQuote(poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
         osUpdate += osSQLColumn;
         osUpdate += "=?";
     }
 
     CPLString osWhere;
-    osWhere.Printf(" WHERE \"%s\" = ?", m_pszFidColumn);
+    osWhere.Printf(" WHERE \"%s\" = ?",
+                   SQLEscapeDoubleQuote(m_pszFidColumn).c_str());
 
     return osUpdate + osWhere;
 }
@@ -511,11 +571,10 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
 // populate OGRSpatialReference information and OGRFeatureDefn objects,
 // among others.
 //
-OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
+OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpkgTable)
 {
     OGRErr err;
     SQLResult oResultTable;
-    char* pszSQL;
     bool bReadExtent = false;
     sqlite3* poDb = m_poDS->GetDB();
     OGREnvelope oExtent;
@@ -524,109 +583,112 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
     bool bHasZ = false;
     bool bHasM = false;
 
-    /* Check that the table name is registered in gpkg_contents */
-    pszSQL = sqlite3_mprintf(
-                "SELECT table_name, data_type, identifier, "
-                "description, min_x, min_y, max_x, max_y, srs_id "
-                "FROM gpkg_contents "
-                "WHERE table_name = '%q'"
+    if( bIsGpkgTable )
+    {
+        /* Check that the table name is registered in gpkg_contents */
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT table_name, data_type, identifier, "
+            "description, min_x, min_y, max_x, max_y, srs_id "
+            "FROM gpkg_contents "
+            "WHERE table_name = '%q'"
 #ifdef WORKAROUND_SQLITE3_BUGS
-                " OR 0"
+            " OR 0"
 #endif
-                ,m_pszTableName);
-
-    SQLResult oResultContents;
-    err = SQLQuery(poDb, pszSQL, &oResultContents);
-    sqlite3_free(pszSQL);
+            , m_pszTableName);
 
-    /* gpkg_contents query has to work */
-    /* gpkg_contents.table_name is supposed to be unique */
-    if ( err != OGRERR_NONE || oResultContents.nRowCount != 1 )
-    {
-        if ( err != OGRERR_NONE )
-            CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultContents.pszErrMsg ? oResultContents.pszErrMsg : "" );
-        else /* if ( oResultContents.nRowCount != 1 ) */
-            CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_contents", m_pszTableName );
+        SQLResult oResultContents;
+        err = SQLQuery(poDb, pszSQL, &oResultContents);
+        sqlite3_free(pszSQL);
 
-        SQLResultFree(&oResultContents);
-        return OGRERR_FAILURE;
-    }
+        /* gpkg_contents query has to work */
+        /* gpkg_contents.table_name is supposed to be unique */
+        if ( err != OGRERR_NONE || oResultContents.nRowCount != 1 )
+        {
+            if ( err != OGRERR_NONE )
+                CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultContents.pszErrMsg ? oResultContents.pszErrMsg : "" );
+            else /* if ( oResultContents.nRowCount != 1 ) */
+                CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_contents", m_pszTableName );
 
-    const char* pszIdentifier = SQLResultGetValue(&oResultContents, 2, 0);
-    if( pszIdentifier && strcmp(pszIdentifier, m_pszTableName) != 0 )
-        OGRLayer::SetMetadataItem("IDENTIFIER", pszIdentifier);
-    const char* pszDescription = SQLResultGetValue(&oResultContents, 3, 0);
-    if( pszDescription && pszDescription[0] )
-        OGRLayer::SetMetadataItem("DESCRIPTION", pszDescription);
+            SQLResultFree(&oResultContents);
+            return OGRERR_FAILURE;
+        }
 
-    if( bIsSpatial )
-    {
-        const char *pszMinX = SQLResultGetValue(&oResultContents, 4, 0);
-        const char *pszMinY = SQLResultGetValue(&oResultContents, 5, 0);
-        const char *pszMaxX = SQLResultGetValue(&oResultContents, 6, 0);
-        const char *pszMaxY = SQLResultGetValue(&oResultContents, 7, 0);
+        const char* pszIdentifier = SQLResultGetValue(&oResultContents, 2, 0);
+        if( pszIdentifier && strcmp(pszIdentifier, m_pszTableName) != 0 )
+            OGRLayer::SetMetadataItem("IDENTIFIER", pszIdentifier);
+        const char* pszDescription = SQLResultGetValue(&oResultContents, 3, 0);
+        if( pszDescription && pszDescription[0] )
+            OGRLayer::SetMetadataItem("DESCRIPTION", pszDescription);
 
-        /* All the extrema have to be non-NULL for this to make sense */
-        if ( pszMinX && pszMinY && pszMaxX && pszMaxY )
+        if( bIsSpatial )
         {
-            oExtent.MinX = CPLAtof(pszMinX);
-            oExtent.MinY = CPLAtof(pszMinY);
-            oExtent.MaxX = CPLAtof(pszMaxX);
-            oExtent.MaxY = CPLAtof(pszMaxY);
-            bReadExtent = true;
-        }
+            const char *pszMinX = SQLResultGetValue(&oResultContents, 4, 0);
+            const char *pszMinY = SQLResultGetValue(&oResultContents, 5, 0);
+            const char *pszMaxX = SQLResultGetValue(&oResultContents, 6, 0);
+            const char *pszMaxY = SQLResultGetValue(&oResultContents, 7, 0);
+
+            /* All the extrema have to be non-NULL for this to make sense */
+            if ( pszMinX && pszMinY && pszMaxX && pszMaxY )
+            {
+                oExtent.MinX = CPLAtof(pszMinX);
+                oExtent.MinY = CPLAtof(pszMinY);
+                oExtent.MaxX = CPLAtof(pszMaxX);
+                oExtent.MaxY = CPLAtof(pszMaxY);
+                bReadExtent = true;
+            }
 
-        /* Done with info from gpkg_contents now */
-        SQLResultFree(&oResultContents);
+            /* Done with info from gpkg_contents now */
+            SQLResultFree(&oResultContents);
 
-        /* Check that the table name is registered in gpkg_geometry_columns */
-        pszSQL = sqlite3_mprintf(
-                    "SELECT table_name, column_name, "
-                    "geometry_type_name, srs_id, z, m "
-                    "FROM gpkg_geometry_columns "
-                    "WHERE table_name = '%q'"
+            /* Check that the table name is registered in gpkg_geometry_columns */
+            pszSQL = sqlite3_mprintf(
+                        "SELECT table_name, column_name, "
+                        "geometry_type_name, srs_id, z, m "
+                        "FROM gpkg_geometry_columns "
+                        "WHERE table_name = '%q'"
 #ifdef WORKAROUND_SQLITE3_BUGS
-                    " OR 0"
+                        " OR 0"
 #endif
-                    ,m_pszTableName);
+                        ,m_pszTableName);
 
-        SQLResult oResultGeomCols;
-        err = SQLQuery(poDb, pszSQL, &oResultGeomCols);
-        sqlite3_free(pszSQL);
+            SQLResult oResultGeomCols;
+            err = SQLQuery(poDb, pszSQL, &oResultGeomCols);
+            sqlite3_free(pszSQL);
 
-        /* gpkg_geometry_columns query has to work */
-        /* gpkg_geometry_columns.table_name is supposed to be unique */
-        if ( err != OGRERR_NONE || oResultGeomCols.nRowCount != 1 )
-        {
-            if ( err != OGRERR_NONE )
-                CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultGeomCols.pszErrMsg ? oResultGeomCols.pszErrMsg : "" );
-            else /* if ( oResultContents.nRowCount != 1 ) */
-                CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_geometry_columns", m_pszTableName );
+            /* gpkg_geometry_columns query has to work */
+            /* gpkg_geometry_columns.table_name is supposed to be unique */
+            if ( err != OGRERR_NONE || oResultGeomCols.nRowCount != 1 )
+            {
+                if ( err != OGRERR_NONE )
+                    CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultGeomCols.pszErrMsg ? oResultGeomCols.pszErrMsg : "" );
+                else /* if ( oResultContents.nRowCount != 1 ) */
+                    CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_geometry_columns", m_pszTableName );
 
-            SQLResultFree(&oResultGeomCols);
-            return OGRERR_FAILURE;
-        }
+                SQLResultFree(&oResultGeomCols);
+                return OGRERR_FAILURE;
+            }
 
-        const char* pszGeomColName = SQLResultGetValue(&oResultGeomCols, 1, 0);
-        if( pszGeomColName != NULL )
-            osGeomColumnName = pszGeomColName;
-        const char* pszGeomColsType = SQLResultGetValue(&oResultGeomCols, 2, 0);
-        if( pszGeomColsType != NULL )
-            osGeomColsType = pszGeomColsType;
-        m_iSrs = SQLResultGetValueAsInteger(&oResultGeomCols, 3, 0);
-        bHasZ = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResultGeomCols, 4, 0));
-        bHasM = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResultGeomCols, 5, 0));
+            const char* pszGeomColName = SQLResultGetValue(&oResultGeomCols, 1, 0);
+            if( pszGeomColName != NULL )
+                osGeomColumnName = pszGeomColName;
+            const char* pszGeomColsType = SQLResultGetValue(&oResultGeomCols, 2, 0);
+            if( pszGeomColsType != NULL )
+                osGeomColsType = pszGeomColsType;
+            m_iSrs = SQLResultGetValueAsInteger(&oResultGeomCols, 3, 0);
+            bHasZ = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResultGeomCols, 4, 0));
+            bHasM = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResultGeomCols, 5, 0));
 
-        SQLResultFree(&oResultGeomCols);
+            SQLResultFree(&oResultGeomCols);
+        }
+        else
+            SQLResultFree(&oResultContents);
     }
-    else
-        SQLResultFree(&oResultContents);
 
     /* Use the "PRAGMA TABLE_INFO()" call to get table definition */
     /*  #|name|type|notnull|default|pk */
     /*  0|id|integer|0||1 */
     /*  1|name|varchar|0||0 */
-    pszSQL = sqlite3_mprintf("pragma table_info('%q')", m_pszTableName);
+    char* pszSQL = sqlite3_mprintf("pragma table_info('%q')", m_pszTableName);
     err = SQLQuery(poDb, pszSQL, &oResultTable);
     sqlite3_free(pszSQL);
 
@@ -647,10 +709,9 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
     m_poFeatureDefn->SetGeomType(wkbNone);
     m_poFeatureDefn->Reference();
 
-    int iRecord;
     bool bFidFound = false;
 
-    for ( iRecord = 0; iRecord < oResultTable.nRowCount; iRecord++ )
+    for ( int iRecord = 0; iRecord < oResultTable.nRowCount; iRecord++ )
     {
         const char *pszName = SQLResultGetValue(&oResultTable, 1, iRecord);
         const char *pszType = SQLResultGetValue(&oResultTable, 2, iRecord);
@@ -658,8 +719,8 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
         const char* pszDefault = SQLResultGetValue(&oResultTable, 4, iRecord);
         OGRBoolean bFid = SQLResultGetValueAsInteger(&oResultTable, 5, iRecord);
         OGRFieldSubType eSubType;
-        int nMaxWidth;
-        OGRFieldType oType = GPkgFieldToOGR(pszType, eSubType, nMaxWidth);
+        int nMaxWidth = 0;
+        const OGRFieldType oType = GPkgFieldToOGR(pszType, eSubType, nMaxWidth);
 
         /* Not a standard field type... */
         if ( (oType > OFTMaxType && osGeomColsType.size()) || EQUAL(osGeomColumnName, pszName) )
@@ -742,8 +803,12 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
                     oField.SetNullable(FALSE);
                 if( pszDefault != NULL )
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute;
-                    float fSecond;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    float fSecond = 0.0f;
                     if( oField.GetType() == OFTString &&
                         !EQUAL(pszDefault, "NULL") &&
                         !STARTS_WITH_CI(pszDefault, "CURRENT_") &&
@@ -846,27 +911,30 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(int bIsSpatial)
 
 OGRGeoPackageTableLayer::OGRGeoPackageTableLayer(
                     GDALGeoPackageDataset *poDS,
-                    const char * pszTableName) : OGRGeoPackageLayer(poDS)
+                    const char * pszTableName) :
+    OGRGeoPackageLayer(poDS),
+    m_pszTableName(CPLStrdup(pszTableName)),
+    m_iSrs(0),
+    m_poExtent(NULL),
+    m_soColumns(""),
+    m_soFilter(""),
+    m_bExtentChanged(false),
+    m_bContentChanged(false),
+    m_poUpdateStatement(NULL),
+    m_bInsertStatementWithFID(false),
+    m_poInsertStatement(NULL),
+    m_bDeferredSpatialIndexCreation(false),
+    m_bHasSpatialIndex(-1),
+    m_bDropRTreeTable(false),
+    m_bPreservePrecision(true),
+    m_bTruncateFields(false),
+    m_bDeferredCreation(false),
+    m_iFIDAsRegularColumnIndex(-1),
+    m_bHasReadMetadataFromStorage(false),
+    m_bRegisterAsAspatial(false)
 {
-    m_pszTableName = CPLStrdup(pszTableName);
-    m_iSrs = 0;
-    m_poExtent = NULL;
-    m_bExtentChanged = false;
     m_poQueryStatement = NULL;
-    m_poUpdateStatement = NULL;
-    m_bInsertStatementWithFID = false;
-    m_poInsertStatement = NULL;
-    m_soColumns = "";
-    m_soFilter = "";
-    m_bDeferredSpatialIndexCreation = false;
-    m_bHasSpatialIndex = -1;
-    m_bDropRTreeTable = false;
-    memset(m_abHasGeometryExtension, 0, sizeof(m_abHasGeometryExtension)); /* false */
-    m_bPreservePrecision = true;
-    m_bTruncateFields = false;
-    m_bDeferredCreation = false;
-    m_iFIDAsRegularColumnIndex = -1;
-    m_bHasReadMetadataFromStorage = false;
+    memset(m_abHasGeometryExtension, 0, sizeof(m_abHasGeometryExtension));
 }
 
 
@@ -883,8 +951,8 @@ OGRGeoPackageTableLayer::~OGRGeoPackageTableLayer()
     {
         const char* pszT = m_pszTableName;
         const char* pszC =m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
-        char* pszSQL;
-        pszSQL = sqlite3_mprintf("DROP TABLE \"rtree_%s_%s\"", pszT, pszC);
+        char* pszSQL =
+            sqlite3_mprintf("DROP TABLE \"rtree_%w_%w\"", pszT, pszC);
         SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
     }
@@ -895,6 +963,7 @@ OGRGeoPackageTableLayer::~OGRGeoPackageTableLayer()
 
     /* Save metadata back to the database */
     SaveExtent();
+    SaveTimestamp();
 
     /* Clean up resources in memory */
     if ( m_pszTableName )
@@ -921,6 +990,9 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
     OGRFieldDefn oFieldDefn(poField);
     if( !m_poDS->GetUpdate() )
     {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "CreateField");
         return OGRERR_FAILURE;
     }
 
@@ -946,20 +1018,26 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
         CPLString osCommand;
 
         osCommand.Printf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s",
-                                 m_pszTableName, poField->GetNameRef(),
-                                 GPkgFieldFromOGR(poField->GetType(),
-                                                  poField->GetSubType(),
-                                                  nMaxWidth));
+                          SQLEscapeDoubleQuote(m_pszTableName).c_str(),
+                          SQLEscapeDoubleQuote(poField->GetNameRef()).c_str(),
+                          GPkgFieldFromOGR(poField->GetType(),
+                                           poField->GetSubType(),
+                                           nMaxWidth));
         if(  !poField->IsNullable() )
             osCommand += " NOT NULL";
         if( poField->GetDefault() != NULL && !poField->IsDefaultDriverSpecific() )
         {
             osCommand += " DEFAULT ";
-            int nYear, nMonth, nDay, nHour, nMinute;
-            float fSecond;
+            int nYear = 0;
+            int nMonth = 0;
+            int nDay = 0;
+            int nHour = 0;
+            int nMinute = 0;
+            float fSecond = 0.0f;
             if( poField->GetType() == OFTDateTime &&
-                sscanf(poField->GetDefault(), "'%d/%d/%d %d:%d:%f'", &nYear, &nMonth, &nDay,
-                                        &nHour, &nMinute, &fSecond) == 6 )
+                sscanf(poField->GetDefault(), "'%d/%d/%d %d:%d:%f'",
+                       &nYear, &nMonth, &nDay,
+                       &nHour, &nMinute, &fSecond) == 6 )
             {
                 if( strchr(poField->GetDefault(), '.') == NULL )
                     osCommand += CPLSPrintf("'%04d-%02d-%02dT%02d:%02d:%02dZ'",
@@ -969,7 +1047,9 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
                                             nYear, nMonth, nDay, nHour, nMinute, fSecond);
             }
             else
+            {
                 osCommand += poField->GetDefault();
+            }
         }
         else if( !poField->IsNullable() )
         {
@@ -1039,12 +1119,11 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
 /* -------------------------------------------------------------------- */
     if( !m_bDeferredCreation )
     {
-        char *pszSQL;
-
-        pszSQL = sqlite3_mprintf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s%s",
-                                 m_pszTableName, oGeomField.GetNameRef(),
-                                 m_poDS->GetGeometryTypeString(oGeomField.GetType()),
-                                 !oGeomField.IsNullable() ? " NOT NULL DEFAULT ''" : "");
+        char *pszSQL = sqlite3_mprintf(
+            "ALTER TABLE \"%w\" ADD COLUMN \"%w\" %s%s",
+            m_pszTableName, oGeomField.GetNameRef(),
+            m_poDS->GetGeometryTypeString(oGeomField.GetType()),
+            !oGeomField.IsNullable() ? " NOT NULL DEFAULT ''" : "");
 
         OGRErr err = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -1101,8 +1180,13 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
 {
     if( !m_poDS->GetUpdate() )
     {
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "CreateFeature");
         return OGRERR_FAILURE;
     }
+    }
 
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
@@ -1111,9 +1195,8 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
     /* format of SQLite is not the one mandated by GeoPackage */
     poFeature->FillUnsetWithDefault(FALSE, NULL);
     bool bHasDefaultValue = false;
-    int iField;
-    int nFieldCount = m_poFeatureDefn->GetFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    const int nFieldCount = m_poFeatureDefn->GetFieldCount();
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         if( poFeature->IsFieldSet( iField ) )
             continue;
@@ -1212,7 +1295,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     /* Update the layer extents with this new object */
-    if ( IsGeomFieldSet(poFeature) )
+    if( IsGeomFieldSet(poFeature) )
     {
         OGREnvelope oEnv;
         poFeature->GetGeomFieldRef(0)->getEnvelope(&oEnv);
@@ -1232,6 +1315,8 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         poFeature->SetFID(OGRNullFID);
     }
 
+    m_bContentChanged = true;
+
     /* All done! */
     return OGRERR_NONE;
 }
@@ -1245,6 +1330,9 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
 {
     if( !m_poDS->GetUpdate() || m_pszFidColumn == NULL )
     {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "SetFeature");
         return OGRERR_FAILURE;
     }
 
@@ -1357,12 +1445,14 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
     if (eErr == OGRERR_NONE)
     {
         /* Update the layer extents with this new object */
-        if ( IsGeomFieldSet(poFeature) )
+        if( IsGeomFieldSet(poFeature) )
         {
             OGREnvelope oEnv;
             poFeature->GetGeomFieldRef(0)->getEnvelope(&oEnv);
             UpdateExtent(&oEnv);
         }
+
+        m_bContentChanged = true;
     }
 
     /* All done! */
@@ -1436,9 +1526,14 @@ OGRErr OGRGeoPackageTableLayer::ResetStatement()
     /* Append the attribute filter, if there is one */
     CPLString soSQL;
     if ( m_soFilter.length() > 0 )
-        soSQL.Printf("SELECT %s FROM \"%s\" WHERE %s", m_soColumns.c_str(), m_pszTableName, m_soFilter.c_str());
+        soSQL.Printf("SELECT %s FROM \"%s\" WHERE %s",
+                     m_soColumns.c_str(),
+                     SQLEscapeDoubleQuote(m_pszTableName).c_str(),
+                     m_soFilter.c_str());
     else
-        soSQL.Printf("SELECT %s FROM \"%s\" ", m_soColumns.c_str(), m_pszTableName);
+        soSQL.Printf("SELECT %s FROM \"%s\" ",
+                     m_soColumns.c_str(),
+                     SQLEscapeDoubleQuote(m_pszTableName).c_str());
 
     int err = sqlite3_prepare(m_poDS->GetDB(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
     if ( err != SQLITE_OK )
@@ -1491,7 +1586,9 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
     /* No filters apply, just use the FID */
     CPLString soSQL;
     soSQL.Printf("SELECT %s FROM \"%s\" WHERE \"%s\" = " CPL_FRMT_GIB,
-                 m_soColumns.c_str(), m_pszTableName, m_pszFidColumn, nFID);
+                 m_soColumns.c_str(),
+                 SQLEscapeDoubleQuote(m_pszTableName).c_str(),
+                 SQLEscapeDoubleQuote(m_pszFidColumn).c_str(), nFID);
 
     int err = sqlite3_prepare(m_poDS->GetDB(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
     if ( err != SQLITE_OK )
@@ -1530,7 +1627,14 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
 
 OGRErr OGRGeoPackageTableLayer::DeleteFeature(GIntBig nFID)
 {
-    if( !m_poDS->GetUpdate() || m_pszFidColumn == NULL )
+    if ( !m_poDS->GetUpdate() )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "DeleteFeature");
+        return OGRERR_FAILURE;
+    }
+    if( m_pszFidColumn == NULL )
     {
         return OGRERR_FAILURE;
     }
@@ -1551,11 +1655,17 @@ OGRErr OGRGeoPackageTableLayer::DeleteFeature(GIntBig nFID)
     /* No filters apply, just use the FID */
     CPLString soSQL;
     soSQL.Printf("DELETE FROM \"%s\" WHERE \"%s\" = " CPL_FRMT_GIB,
-                 m_pszTableName, m_pszFidColumn, nFID);
+                 SQLEscapeDoubleQuote(m_pszTableName).c_str(),
+                 SQLEscapeDoubleQuote(m_pszFidColumn).c_str(), nFID);
 
     OGRErr eErr = SQLCommand(m_poDS->GetDB(), soSQL.c_str());
     if( eErr == OGRERR_NONE )
+    {
         eErr = (sqlite3_changes(m_poDS->GetDB()) > 0) ? OGRERR_NONE : OGRERR_NON_EXISTING_FEATURE;
+
+        if( eErr == OGRERR_NONE )
+            m_bContentChanged = true;
+    }
     return eErr;
 }
 
@@ -1569,6 +1679,7 @@ OGRErr OGRGeoPackageTableLayer::SyncToDisk()
         return OGRERR_FAILURE;
 
     SaveExtent();
+    SaveTimestamp();
     return OGRERR_NONE;
 }
 
@@ -1618,9 +1729,12 @@ GIntBig OGRGeoPackageTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
     OGRErr err;
     CPLString soSQL;
     if ( m_soFilter.length() > 0 )
-        soSQL.Printf("SELECT Count(*) FROM \"%s\" WHERE %s", m_pszTableName, m_soFilter.c_str());
+        soSQL.Printf("SELECT Count(*) FROM \"%s\" WHERE %s",
+                     SQLEscapeDoubleQuote(m_pszTableName).c_str(),
+                     m_soFilter.c_str());
     else
-        soSQL.Printf("SELECT Count(*) FROM \"%s\" ", m_pszTableName);
+        soSQL.Printf("SELECT Count(*) FROM \"%s\" ",
+                     SQLEscapeDoubleQuote(m_pszTableName).c_str());
 
     /* Just run the query directly and get back integer */
     GIntBig iFeatureCount = SQLGetInteger64(m_poDS->GetDB(), soSQL.c_str(), &err);
@@ -1658,20 +1772,45 @@ OGRErr OGRGeoPackageTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     if ( bForce )
     {
         OGRErr err = OGRLayer::GetExtent(psExtent, bForce);
-        if ( err != OGRERR_NONE )
-            return err;
-
-        if ( ! m_poExtent )
+        delete m_poExtent;
+        m_poExtent = NULL;
+        if( err == OGRERR_NONE )
+        {
             m_poExtent = new OGREnvelope( *psExtent );
+            m_bExtentChanged = true;
+            SaveExtent();
+        }
         else
-            *m_poExtent = *psExtent;
-        return SaveExtent();
+        {
+            char *pszSQL = sqlite3_mprintf(
+                "UPDATE gpkg_contents SET "
+                "min_x = NULL, min_y = NULL, "
+                "max_x = NULL, max_y = NULL "
+                "WHERE table_name = '%q' AND "
+                "Lower(data_type) = 'features'",
+                m_pszTableName);
+            SQLCommand( m_poDS->GetDB(), pszSQL);
+            sqlite3_free(pszSQL);
+            m_bExtentChanged = false;
+        }
+        return err;
     }
 
     return OGRERR_FAILURE;
 }
 
+/************************************************************************/
+/*                      RecomputeExtent()                               */
+/************************************************************************/
 
+void OGRGeoPackageTableLayer::RecomputeExtent()
+{
+    m_bExtentChanged = true;
+    delete m_poExtent;
+    m_poExtent = NULL;
+    OGREnvelope sExtent;
+    GetExtent(&sExtent, true);
+}
 
 /************************************************************************/
 /*                      TestCapability()                                */
@@ -1682,7 +1821,10 @@ int OGRGeoPackageTableLayer::TestCapability ( const char * pszCap )
     if ( EQUAL(pszCap, OLCCreateField) ||
          EQUAL(pszCap, OLCSequentialWrite) ||
          EQUAL(pszCap, OLCDeleteFeature) ||
-         EQUAL(pszCap, OLCRandomWrite) )
+         EQUAL(pszCap, OLCRandomWrite) ||
+         EQUAL(pszCap, OLCDeleteField) ||
+         EQUAL(pszCap, OLCAlterFieldDefn) ||
+         EQUAL(pszCap, OLCReorderFields) )
     {
         return m_poDS->GetUpdate();
     }
@@ -1728,9 +1870,8 @@ void OGRGeoPackageTableLayer::CreateSpatialIndexIfNecessary()
 /*                       CreateSpatialIndex()                           */
 /************************************************************************/
 
-bool OGRGeoPackageTableLayer::CreateSpatialIndex()
+bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
 {
-    char* pszSQL;
     OGRErr err;
 
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -1755,18 +1896,19 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( m_poDS->CreateExtensionsTableIfNecessary() != OGRERR_NONE )
         return false;
 
-    const char* pszT = m_pszTableName;
+    const char* pszT = (pszTableName) ? pszTableName : m_pszTableName;
     const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
     const char* pszI = GetFIDColumn();
 
     m_poDS->SoftStartTransaction();
 
     /* Register the table in gpkg_extensions */
-    pszSQL = sqlite3_mprintf(
-                 "INSERT INTO gpkg_extensions "
-                 "(table_name,column_name,extension_name,definition,scope) "
-                 "VALUES ('%q', '%q', 'gpkg_rtree_index', 'GeoPackage 1.0 Specification Annex L', 'write-only')",
-                 pszT, pszC );
+    char* pszSQL = sqlite3_mprintf(
+        "INSERT INTO gpkg_extensions "
+        "(table_name,column_name,extension_name,definition,scope) "
+        "VALUES ('%q', '%q', 'gpkg_rtree_index', "
+        "'GeoPackage 1.0 Specification Annex L', 'write-only')",
+        pszT, pszC );
     err = SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
     if( err != OGRERR_NONE )
@@ -1779,7 +1921,7 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
     if( !m_bDropRTreeTable )
     {
         pszSQL = sqlite3_mprintf(
-                    "CREATE VIRTUAL TABLE \"rtree_%s_%s\" USING rtree(id, minx, maxx, miny, maxy)",
+                    "CREATE VIRTUAL TABLE \"rtree_%w_%w\" USING rtree(id, minx, maxx, miny, maxy)",
                     pszT, pszC );
         err = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
@@ -1793,8 +1935,8 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
 
     /* Populate the RTree */
     pszSQL = sqlite3_mprintf(
-                 "INSERT OR REPLACE INTO \"rtree_%s_%s\" "
-                 "SELECT \"%s\", st_minx(\"%s\"), st_maxx(\"%s\"), st_miny(\"%s\"), st_maxy(\"%s\") FROM \"%s\"",
+                 "INSERT OR REPLACE INTO \"rtree_%w_%w\" "
+                 "SELECT \"%w\", st_minx(\"%w\"), st_maxx(\"%w\"), st_miny(\"%w\"), st_maxy(\"%w\") FROM \"%w\"",
                  pszT, pszC, pszI, pszC, pszC, pszC, pszC, pszT );
     err = SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
@@ -1809,13 +1951,13 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
     /* Conditions: Insertion of non-empty geometry
        Actions   : Insert record into rtree */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%s_%s_insert\" AFTER INSERT ON \"%s\" "
-                   "WHEN (new.\"%s\" NOT NULL AND NOT ST_IsEmpty(NEW.\"%s\")) "
+                   "CREATE TRIGGER \"rtree_%w_%w_insert\" AFTER INSERT ON \"%w\" "
+                   "WHEN (new.\"%w\" NOT NULL AND NOT ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "INSERT OR REPLACE INTO \"rtree_%s_%s\" VALUES ("
-                   "NEW.\"%s\","
-                   "ST_MinX(NEW.\"%s\"), ST_MaxX(NEW.\"%s\"),"
-                   "ST_MinY(NEW.\"%s\"), ST_MaxY(NEW.\"%s\")"
+                   "INSERT OR REPLACE INTO \"rtree_%w_%w\" VALUES ("
+                   "NEW.\"%w\","
+                   "ST_MinX(NEW.\"%w\"), ST_MaxX(NEW.\"%w\"),"
+                   "ST_MinY(NEW.\"%w\"), ST_MaxY(NEW.\"%w\")"
                    "); "
                    "END",
                    pszT, pszC, pszT,
@@ -1836,14 +1978,14 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
                No row ID change
        Actions   : Update record in rtree */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%s_%s_update1\" AFTER UPDATE OF \"%s\" ON \"%s\" "
-                   "WHEN OLD.\"%s\" = NEW.\"%s\" AND "
-                   "(NEW.\"%s\" NOTNULL AND NOT ST_IsEmpty(NEW.\"%s\")) "
+                   "CREATE TRIGGER \"rtree_%w_%w_update1\" AFTER UPDATE OF \"%w\" ON \"%w\" "
+                   "WHEN OLD.\"%w\" = NEW.\"%w\" AND "
+                   "(NEW.\"%w\" NOTNULL AND NOT ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "INSERT OR REPLACE INTO \"rtree_%s_%s\" VALUES ("
-                   "NEW.\"%s\","
-                   "ST_MinX(NEW.\"%s\"), ST_MaxX(NEW.\"%s\"),"
-                   "ST_MinY(NEW.\"%s\"), ST_MaxY(NEW.\"%s\")"
+                   "INSERT OR REPLACE INTO \"rtree_%w_%w\" VALUES ("
+                   "NEW.\"%w\","
+                   "ST_MinX(NEW.\"%w\"), ST_MaxX(NEW.\"%w\"),"
+                   "ST_MinY(NEW.\"%w\"), ST_MaxY(NEW.\"%w\")"
                    "); "
                    "END",
                    pszT, pszC, pszC, pszT,
@@ -1865,11 +2007,11 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
                No row ID change
        Actions   : Remove record from rtree */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%s_%s_update2\" AFTER UPDATE OF \"%s\" ON \"%s\" "
-                   "WHEN OLD.\"%s\" = NEW.\"%s\" AND "
-                   "(NEW.\"%s\" ISNULL OR ST_IsEmpty(NEW.\"%s\")) "
+                   "CREATE TRIGGER \"rtree_%w_%w_update2\" AFTER UPDATE OF \"%w\" ON \"%w\" "
+                   "WHEN OLD.\"%w\" = NEW.\"%w\" AND "
+                   "(NEW.\"%w\" ISNULL OR ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%s_%s\" WHERE id = OLD.\"%s\"; "
+                   "DELETE FROM \"rtree_%w_%w\" WHERE id = OLD.\"%w\"; "
                    "END",
                    pszT, pszC, pszC, pszT,
                    pszI, pszI,
@@ -1889,15 +2031,15 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
         Actions   : Remove record from rtree for old <i>
                     Insert record into rtree for new <i> */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%s_%s_update3\" AFTER UPDATE OF \"%s\" ON \"%s\" "
-                   "WHEN OLD.\"%s\" != NEW.\"%s\" AND "
-                   "(NEW.\"%s\" NOTNULL AND NOT ST_IsEmpty(NEW.\"%s\")) "
+                   "CREATE TRIGGER \"rtree_%w_%w_update3\" AFTER UPDATE OF \"%w\" ON \"%w\" "
+                   "WHEN OLD.\"%w\" != NEW.\"%w\" AND "
+                   "(NEW.\"%w\" NOTNULL AND NOT ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%s_%s\" WHERE id = OLD.\"%s\"; "
-                   "INSERT OR REPLACE INTO \"rtree_%s_%s\" VALUES ("
-                   "NEW.\"%s\","
-                   "ST_MinX(NEW.\"%s\"), ST_MaxX(NEW.\"%s\"),"
-                   "ST_MinY(NEW.\"%s\"), ST_MaxY(NEW.\"%s\")"
+                   "DELETE FROM \"rtree_%w_%w\" WHERE id = OLD.\"%w\"; "
+                   "INSERT OR REPLACE INTO \"rtree_%w_%w\" VALUES ("
+                   "NEW.\"%w\","
+                   "ST_MinX(NEW.\"%w\"), ST_MaxX(NEW.\"%w\"),"
+                   "ST_MinY(NEW.\"%w\"), ST_MaxY(NEW.\"%w\")"
                    "); "
                    "END",
                    pszT, pszC, pszC, pszT,
@@ -1921,11 +2063,11 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
                     Empty geometry
         Actions   : Remove record from rtree for old and new <i> */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%s_%s_update4\" AFTER UPDATE ON \"%s\" "
-                   "WHEN OLD.\"%s\" != NEW.\"%s\" AND "
-                   "(NEW.\"%s\" ISNULL OR ST_IsEmpty(NEW.\"%s\")) "
+                   "CREATE TRIGGER \"rtree_%w_%w_update4\" AFTER UPDATE ON \"%w\" "
+                   "WHEN OLD.\"%w\" != NEW.\"%w\" AND "
+                   "(NEW.\"%w\" ISNULL OR ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%s_%s\" WHERE id IN (OLD.\"%s\", NEW.\"%s\"); "
+                   "DELETE FROM \"rtree_%w_%w\" WHERE id IN (OLD.\"%w\", NEW.\"%w\"); "
                    "END",
                    pszT, pszC, pszT,
                    pszI, pszI,
@@ -1942,10 +2084,10 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex()
     /* Conditions: Row deleted
         Actions   : Remove record from rtree for old <i> */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%s_%s_delete\" AFTER DELETE ON \"%s\" "
-                   "WHEN old.\"%s\" NOT NULL "
+                   "CREATE TRIGGER \"rtree_%w_%w_delete\" AFTER DELETE ON \"%w\" "
+                   "WHEN old.\"%w\" NOT NULL "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%s_%s\" WHERE id = OLD.\"%s\"; "
+                   "DELETE FROM \"rtree_%w_%w\" WHERE id = OLD.\"%w\"; "
                    "END",
                    pszT, pszC, pszT,
                    pszC,
@@ -1978,7 +2120,7 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
 
     /* We have only the SQL functions needed by the 3 following extensions */
     /* anything else will likely cause troubles */
-    char* pszSQL;
+    char* pszSQL = NULL;
 
     if( m_poFeatureDefn->GetGeomFieldCount() == 0 )
     {
@@ -2141,11 +2283,10 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
 
     const char* pszT = m_pszTableName;
     const char* pszC =m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
-    char* pszSQL;
-
-    pszSQL = sqlite3_mprintf("DELETE FROM gpkg_extensions WHERE table_name='%q' "
-                 "AND column_name='%q' AND extension_name='gpkg_rtree_index'",
-                 pszT, pszC );
+    char* pszSQL = sqlite3_mprintf(
+        "DELETE FROM gpkg_extensions WHERE table_name='%q' "
+        "AND column_name='%q' AND extension_name='gpkg_rtree_index'",
+        pszT, pszC );
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
@@ -2155,36 +2296,36 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
         /* remove the content and memorize that we will have to delete the */
         /* table later */
         m_bDropRTreeTable = true;
-        pszSQL = sqlite3_mprintf("DELETE FROM \"rtree_%s_%s\"", pszT, pszC);
+        pszSQL = sqlite3_mprintf("DELETE FROM \"rtree_%w_%w\"", pszT, pszC);
     }
     else
     {
-        pszSQL = sqlite3_mprintf("DROP TABLE \"rtree_%s_%s\"", pszT, pszC);
+        pszSQL = sqlite3_mprintf("DROP TABLE \"rtree_%w_%w\"", pszT, pszC);
     }
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%s_%s_insert\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_insert\"", pszT, pszC);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%s_%s_update1\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update1\"", pszT, pszC);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%s_%s_update2\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update2\"", pszT, pszC);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%s_%s_update3\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update3\"", pszT, pszC);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%s_%s_update4\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update4\"", pszT, pszC);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%s_%s_delete\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_delete\"", pszT, pszC);
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
@@ -2198,33 +2339,127 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
 
 void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
 {
-    int bHasSpatialIndex = HasSpatialIndex();
+    ResetReading();
+    RunDeferredCreationIfNecessary();
+    CreateSpatialIndexIfNecessary();
+
+    SQLResult oResultTable;
+    char* pszSQL = sqlite3_mprintf(
+        "SELECT * FROM sqlite_master WHERE name = '%q' "
+        "AND type IN ('table', 'view')",
+         pszDstTableName);
+    OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
+    sqlite3_free(pszSQL);
+    const bool bAlreadyExists = ( err == OGRERR_NONE &&
+                                  oResultTable.nRowCount == 1 );
+    SQLResultFree(&oResultTable);
+    if( bAlreadyExists )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Table %s already exists",
+                 pszDstTableName);
+        return;
+    }
 
+    if( m_poDS->SoftStartTransaction() != OGRERR_NONE )
+        return;
+
+    const bool bHasSpatialIndex = HasSpatialIndex();
     if( bHasSpatialIndex )
     {
         DropSpatialIndex();
     }
 
-    /* We also need to update GeoPackage metadata tables */
-    char* pszSQL;
     pszSQL = sqlite3_mprintf(
-            "UPDATE gpkg_geometry_columns SET table_name = '%s' WHERE table_name = '%s'",
-            pszDstTableName, m_pszTableName);
-    SQLCommand(m_poDS->GetDB(), pszSQL);
+        "UPDATE gpkg_geometry_columns SET table_name = '%q' WHERE "
+        "table_name = '%q'",
+        pszDstTableName, m_pszTableName);
+    OGRErr eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf(
-            "UPDATE gpkg_contents SET table_name = '%s' WHERE table_name = '%s'",
+    if( eErr == OGRERR_NONE )
+    {
+        // Rename the identifier if it defaulted to the table name
+        pszSQL = sqlite3_mprintf(
+                "UPDATE gpkg_contents SET identifier = '%q' WHERE "
+                "table_name = '%q' AND identifier = '%q'",
+                pszDstTableName, m_pszTableName, m_pszTableName);
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf(
+                "UPDATE gpkg_contents SET table_name = '%q' WHERE "
+                "table_name = '%q'",
+                pszDstTableName, m_pszTableName);
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+
+    if( eErr == OGRERR_NONE && m_poDS->HasExtensionsTable() )
+    {
+        pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_extensions SET table_name = '%q' WHERE "
+            "table_name = '%q'",
             pszDstTableName, m_pszTableName);
-    SQLCommand(m_poDS->GetDB(), pszSQL);
-    sqlite3_free(pszSQL);
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+
+    if( eErr == OGRERR_NONE && m_poDS->HasMetadataTables() )
+    {
+        pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_metadata_reference SET table_name = '%q' WHERE "
+            "table_name = '%q'",
+            pszDstTableName, m_pszTableName);
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
-    CPLFree(m_pszTableName);
-    m_pszTableName = CPLStrdup(pszDstTableName);
+    if( eErr == OGRERR_NONE && m_poDS->HasDataColumnsTable() )
+    {
+        pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_data_columns SET table_name = '%q' WHERE "
+            "table_name = '%q'",
+            pszDstTableName, m_pszTableName);
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
 
-    if( bHasSpatialIndex )
+    if( eErr == OGRERR_NONE )
     {
-        CreateSpatialIndex();
+        pszSQL = sqlite3_mprintf(
+                "ALTER TABLE \"%w\" RENAME TO \"%w\"",
+                m_pszTableName, pszDstTableName );
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+
+    // Check foreign key integrity
+    if ( eErr == OGRERR_NONE )
+    {
+        eErr = m_poDS->PragmaCheck("foreign_key_check", "", 0);
+    }
+
+    if( eErr == OGRERR_NONE)
+    {
+        if( bHasSpatialIndex )
+        {
+            CreateSpatialIndex(pszDstTableName);
+        }
+
+        eErr = m_poDS->SoftCommitTransaction();
+        if( eErr == OGRERR_NONE)
+        {
+            CPLFree(m_pszTableName);
+            m_pszTableName = CPLStrdup(pszDstTableName);
+        }
+    }
+    else
+    {
+        m_poDS->SoftRollbackTransaction();
     }
 }
 
@@ -2247,7 +2482,7 @@ void OGRGeoPackageTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 /*                        HasFastSpatialFilter()                        */
 /************************************************************************/
 
-int OGRGeoPackageTableLayer::HasFastSpatialFilter(int iGeomColIn)
+int OGRGeoPackageTableLayer::HasFastSpatialFilter( int iGeomColIn )
 {
     if( iGeomColIn < 0 || iGeomColIn >= m_poFeatureDefn->GetGeomFieldCount() )
         return FALSE;
@@ -2415,63 +2650,67 @@ OGRErr OGRGeoPackageTableLayer::RegisterGeometryColumn()
 }
 
 /************************************************************************/
-/*                      RunDeferredCreationIfNecessary()                */
+/*                        GetColumnsOfCreateTable()                     */
 /************************************************************************/
 
-OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
+CPLString OGRGeoPackageTableLayer::GetColumnsOfCreateTable(const std::vector<OGRFieldDefn*> apoFields)
 {
-    if( !m_bDeferredCreation )
-        return OGRERR_NONE;
-    m_bDeferredCreation = false;
-
-    const char* pszLayerName = m_poFeatureDefn->GetName();
-    OGRwkbGeometryType eGType = GetGeomType();
-
-    int bIsSpatial = (eGType != wkbNone);
-
-    /* Requirement 25: The geometry_type_name value in a gpkg_geometry_columns */
-    /* row SHALL be one of the uppercase geometry type names specified in */
-    /* Geometry Types (Normative). */
-    const char *pszGeometryType = m_poDS->GetGeometryTypeString(eGType);
+    CPLString osSQL;
 
-    /* Create the table! */
     char *pszSQL = NULL;
-    CPLString osCommand;
-
-    pszSQL = sqlite3_mprintf(
-        "CREATE TABLE \"%s\" ( "
-        "\"%s\" INTEGER PRIMARY KEY AUTOINCREMENT",
-            pszLayerName, m_pszFidColumn);
-    osCommand += pszSQL;
-    sqlite3_free(pszSQL);
+    bool bNeedComma = false;
+    if( m_pszFidColumn != NULL )
+    {
+        pszSQL = sqlite3_mprintf("\"%w\" INTEGER PRIMARY KEY AUTOINCREMENT",
+                                m_pszFidColumn);
+        osSQL += pszSQL;
+        sqlite3_free(pszSQL);
+        bNeedComma = true;
+    }
 
-    if( GetGeomType() != wkbNone )
+    const OGRwkbGeometryType eGType = GetGeomType();
+    if( eGType != wkbNone )
     {
-        pszSQL = sqlite3_mprintf(", '%q' %s",
+        if( bNeedComma )
+        {
+            osSQL += ", ";
+        }
+        bNeedComma = true;
+
+        /* Requirement 25: The geometry_type_name value in a gpkg_geometry_columns */
+        /* row SHALL be one of the uppercase geometry type names specified in */
+        /* Geometry Types (Normative). */
+        const char *pszGeometryType = m_poDS->GetGeometryTypeString(eGType);
+
+        pszSQL = sqlite3_mprintf("\"%w\" %s",
                                  GetGeometryColumn(), pszGeometryType);
-        osCommand += pszSQL;
+        osSQL += pszSQL;
         sqlite3_free(pszSQL);
         if( !m_poFeatureDefn->GetGeomFieldDefn(0)->IsNullable() )
         {
-            osCommand += " NOT NULL";
+            osSQL += " NOT NULL";
         }
     }
 
-    for(int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    for(size_t i = 0; i < apoFields.size(); i++ )
     {
-        if( i == m_iFIDAsRegularColumnIndex )
-            continue;
-        OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(i);
-        pszSQL = sqlite3_mprintf(", '%q' %s",
+        if( bNeedComma )
+        {
+            osSQL += ", ";
+        }
+        bNeedComma = true;
+
+        OGRFieldDefn* poFieldDefn = apoFields[i];
+        pszSQL = sqlite3_mprintf("\"%w\" %s",
                                  poFieldDefn->GetNameRef(),
                                  GPkgFieldFromOGR(poFieldDefn->GetType(),
                                                   poFieldDefn->GetSubType(),
                                                   poFieldDefn->GetWidth()));
-        osCommand += pszSQL;
+        osSQL += pszSQL;
         sqlite3_free(pszSQL);
         if( !poFieldDefn->IsNullable() )
         {
-            osCommand += " NOT NULL";
+            osSQL += " NOT NULL";
         }
         const char* pszDefault = poFieldDefn->GetDefault();
         if( pszDefault != NULL &&
@@ -2480,28 +2719,60 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
              (STARTS_WITH_CI(pszDefault+1, "strftime") ||
               STARTS_WITH_CI(pszDefault+1, " strftime")))) )
         {
-            osCommand += " DEFAULT ";
+            osSQL += " DEFAULT ";
             OGRField sField;
             if( poFieldDefn->GetType() == OFTDateTime &&
                 OGRParseDate(pszDefault, &sField, 0) )
             {
                 char* pszXML = OGRGetXMLDateTime(&sField);
-                osCommand += pszXML;
+                osSQL += pszXML;
                 CPLFree(pszXML);
             }
             /* Make sure CURRENT_TIMESTAMP is translated into appropriate format for GeoPackage */
             else if( poFieldDefn->GetType() == OFTDateTime &&
                      EQUAL(pszDefault, "CURRENT_TIMESTAMP") )
             {
-                osCommand += "(strftime('%Y-%m-%dT%H:%M:%fZ','now'))";
+                osSQL += "(strftime('%Y-%m-%dT%H:%M:%fZ','now'))";
             }
             else
             {
-                osCommand += poFieldDefn->GetDefault();
+                osSQL += poFieldDefn->GetDefault();
             }
         }
     }
 
+    return osSQL;
+}
+
+/************************************************************************/
+/*                      RunDeferredCreationIfNecessary()                */
+/************************************************************************/
+
+OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
+{
+    if( !m_bDeferredCreation )
+        return OGRERR_NONE;
+    m_bDeferredCreation = false;
+
+    const char* pszLayerName = m_poFeatureDefn->GetName();
+
+    /* Create the table! */
+    CPLString osCommand;
+
+    char* pszSQL = sqlite3_mprintf("CREATE TABLE '%q' ( ", pszLayerName);
+    osCommand += pszSQL;
+    sqlite3_free(pszSQL);
+
+    std::vector<OGRFieldDefn*> apoFields;
+    for(int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( i == m_iFIDAsRegularColumnIndex )
+            continue;
+        apoFields.push_back( m_poFeatureDefn->GetFieldDefn(i) );
+    }
+
+    osCommand += GetColumnsOfCreateTable(apoFields);
+
     osCommand += ")";
 
 #ifdef DEBUG
@@ -2512,31 +2783,43 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
         return OGRERR_FAILURE;
 
     /* Update gpkg_contents with the table info */
+    const OGRwkbGeometryType eGType = GetGeomType();
+    const bool bIsSpatial = (eGType != wkbNone);
     if ( bIsSpatial )
         err = RegisterGeometryColumn();
-    else
+    else if( m_bRegisterAsAspatial )
         err = m_poDS->CreateGDALAspatialExtension();
 
     if ( err != OGRERR_NONE )
         return OGRERR_FAILURE;
 
-    const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
-    if( pszIdentifier == NULL )
-        pszIdentifier = pszLayerName;
-    const char* pszDescription = GetMetadataItem("DESCRIPTION");
-    if( pszDescription == NULL )
-        pszDescription = "";
-    pszSQL = sqlite3_mprintf(
-        "INSERT INTO gpkg_contents "
-        "(table_name,data_type,identifier,description,last_change,srs_id)"
-        " VALUES "
-        "('%q','%q','%q','%q',strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',CURRENT_TIMESTAMP),%d)",
-        pszLayerName, (bIsSpatial ? "features": "aspatial"), pszIdentifier, pszDescription, m_iSrs);
+    if( bIsSpatial || m_bRegisterAsAspatial )
+    {
+        const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
+        if( pszIdentifier == NULL )
+            pszIdentifier = pszLayerName;
+        const char* pszDescription = GetMetadataItem("DESCRIPTION");
+        if( pszDescription == NULL )
+            pszDescription = "";
+        const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
+        CPLString osInsertGpkgContentsFormatting("INSERT INTO gpkg_contents "
+                 "(table_name,data_type,identifier,description,last_change,srs_id) VALUES "
+                "('%q','%q','%q','%q',");
+        osInsertGpkgContentsFormatting += ( pszCurrentDate ) ? "'%q'" : "%s";
+        osInsertGpkgContentsFormatting += ",%d)";
 
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
-    sqlite3_free(pszSQL);
-    if ( err != OGRERR_NONE )
-        return OGRERR_FAILURE;
+        pszSQL = sqlite3_mprintf(
+            osInsertGpkgContentsFormatting.c_str(),
+            pszLayerName, (bIsSpatial ? "features": "aspatial"),
+            pszIdentifier, pszDescription,
+            pszCurrentDate ? pszCurrentDate : "strftime('%Y-%m-%dT%H:%M:%fZ','now')",
+            m_iSrs);
+
+        err = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+        if ( err != OGRERR_NONE )
+            return OGRERR_FAILURE;
+    }
 
     ResetReading();
 
@@ -2555,18 +2838,16 @@ char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
 
     m_bHasReadMetadataFromStorage = true;
 
-    if ( !m_poDS->HasMetadataTables() )
+    if( !m_poDS->HasMetadataTables() )
         return OGRLayer::GetMetadata( pszDomain );
 
-    char* pszSQL;
-
-    pszSQL = sqlite3_mprintf(
-        "SELECT md.metadata, md.md_standard_uri, md.mime_type, mdr.reference_scope FROM gpkg_metadata md "
+    char* pszSQL = sqlite3_mprintf(
+        "SELECT md.metadata, md.md_standard_uri, md.mime_type, "
+        "mdr.reference_scope FROM gpkg_metadata md "
         "JOIN gpkg_metadata_reference mdr ON (md.id = mdr.md_file_id ) "
         "WHERE mdr.table_name = '%q' ORDER BY md.id",
         m_pszTableName);
 
-
     SQLResult oResult;
     OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResult);
     sqlite3_free(pszSQL);
@@ -2709,3 +2990,698 @@ CPLErr OGRGeoPackageTableLayer::SetMetadataItem( const char * pszName,
     m_poDS->SetMetadataDirty();
     return OGRLayer::SetMetadataItem(pszName, pszValue, pszDomain);
 }
+
+/************************************************************************/
+/*                          RecreateTable()                             */
+/************************************************************************/
+
+OGRErr OGRGeoPackageTableLayer::RecreateTable(const CPLString& osColumnsForCreate,
+                                              const CPLString& osFieldListForSelect)
+{
+/* -------------------------------------------------------------------- */
+/*      Save existing related triggers and index                        */
+/* -------------------------------------------------------------------- */
+    sqlite3 *hDB = m_poDS->GetDB();
+
+    char* pszSQL = sqlite3_mprintf(
+        "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') "
+        "AND tbl_name='%q'",
+        m_pszTableName );
+    SQLResult oTriggers;
+    OGRErr eErr = SQLQuery(hDB, pszSQL, &oTriggers);
+    sqlite3_free(pszSQL);
+
+/* -------------------------------------------------------------------- */
+/*      Make a temporary table with new content.                        */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf("CREATE TABLE \"%w_ogr_tmp\" (%s)",
+                                m_pszTableName, osColumnsForCreate.c_str());
+        eErr = SQLCommand( hDB, pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf(
+                "INSERT INTO \"%w_ogr_tmp\" SELECT %s FROM \"%w\"",
+                m_pszTableName,
+                osFieldListForSelect.c_str(),
+                m_pszTableName);
+        eErr = SQLCommand( hDB, pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Drop the original table                                         */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf( "DROP TABLE \"%w\"", m_pszTableName );
+        eErr = SQLCommand( hDB, pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Rename temporary table as new table                             */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {
+        pszSQL = sqlite3_mprintf( "ALTER TABLE \"%w_ogr_tmp\" RENAME TO \"%w\"",
+                                  m_pszTableName, m_pszTableName );
+        eErr = SQLCommand( hDB, pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Recreate existing related tables, triggers and index            */
+/* -------------------------------------------------------------------- */
+    for( int i = 0; i < oTriggers.nRowCount && eErr == OGRERR_NONE; i++)
+    {
+        const char* pszSQLTriggerIdx = SQLResultGetValue( &oTriggers, 0, i );
+        if (pszSQLTriggerIdx != NULL && *pszSQLTriggerIdx != '\0')
+        {
+            eErr = SQLCommand( hDB, pszSQLTriggerIdx );
+        }
+    }
+
+    SQLResultFree( &oTriggers );
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          BuildSelectFieldList()                      */
+/************************************************************************/
+
+CPLString OGRGeoPackageTableLayer::BuildSelectFieldList(const std::vector<OGRFieldDefn*> apoFields)
+{
+    CPLString osFieldListForSelect;
+
+    char *pszSQL = NULL;
+    bool bNeedComma = false;
+
+    if( m_pszFidColumn != NULL )
+    {
+        pszSQL = sqlite3_mprintf("\"%w\"", m_pszFidColumn);
+        osFieldListForSelect += pszSQL;
+        sqlite3_free(pszSQL);
+        bNeedComma = true;
+    }
+
+    if( GetGeomType() != wkbNone )
+    {
+        if( bNeedComma )
+        {
+            osFieldListForSelect += ", ";
+        }
+        bNeedComma = true;
+
+        pszSQL = sqlite3_mprintf("\"%w\"", GetGeometryColumn());
+        osFieldListForSelect += pszSQL;
+        sqlite3_free(pszSQL);
+    }
+
+    for( size_t iField = 0; iField < apoFields.size(); iField++ )
+    {
+        if( bNeedComma )
+        {
+            osFieldListForSelect += ", ";
+        }
+        bNeedComma = true;
+
+        OGRFieldDefn *poFieldDefn = apoFields[iField];
+        pszSQL = sqlite3_mprintf("\"%w\"", poFieldDefn->GetNameRef());
+        osFieldListForSelect += pszSQL;
+        sqlite3_free(pszSQL);
+    }
+
+    return osFieldListForSelect;
+}
+
+/************************************************************************/
+/*                               IsTable()                              */
+/************************************************************************/
+
+bool OGRGeoPackageTableLayer::IsTable()
+{
+    SQLResult oResultTable;
+    char* pszSQL = sqlite3_mprintf(
+        "SELECT * FROM sqlite_master WHERE name = '%q' AND type = 'table'",
+         m_pszTableName);
+    OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
+    sqlite3_free(pszSQL);
+    const bool bIsTable = ( err == OGRERR_NONE &&
+                                  oResultTable.nRowCount == 1 );
+    SQLResultFree(&oResultTable);
+    return bIsTable;
+}
+
+/************************************************************************/
+/*                             DeleteField()                            */
+/************************************************************************/
+
+OGRErr OGRGeoPackageTableLayer::DeleteField( int iFieldToDelete )
+{
+    if ( !m_poDS->GetUpdate() )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "DeleteField");
+        return OGRERR_FAILURE;
+    }
+
+    if (iFieldToDelete < 0 || iFieldToDelete >= m_poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    ResetReading();
+    RunDeferredCreationIfNecessary();
+    CreateSpatialIndexIfNecessary();
+
+/* -------------------------------------------------------------------- */
+/*      Check that is a table and not a view                            */
+/* -------------------------------------------------------------------- */
+    if( !IsTable() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Layer %s is not a table",
+                 m_pszTableName);
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+    std::vector<OGRFieldDefn*> apoFields;
+    for( int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        if (iField == iFieldToDelete)
+            continue;
+
+        OGRFieldDefn *poFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
+        apoFields.push_back(poFieldDefn);
+    }
+
+    CPLString osFieldListForSelect( BuildSelectFieldList(apoFields) );
+    CPLString osColumnsForCreate( GetColumnsOfCreateTable(apoFields) );
+
+/* -------------------------------------------------------------------- */
+/*      Drop any iterator since we change the DB structure              */
+/* -------------------------------------------------------------------- */
+    m_poDS->ResetReadingAllLayers();
+
+/* -------------------------------------------------------------------- */
+/*      Recreate table in a transaction                                 */
+/* -------------------------------------------------------------------- */
+    if( m_poDS->SoftStartTransaction() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    OGRErr eErr = RecreateTable(osColumnsForCreate, osFieldListForSelect);
+
+/* -------------------------------------------------------------------- */
+/*      Update gpkg_extensions if needed.                               */
+/* -------------------------------------------------------------------- */
+    if( m_poDS->HasExtensionsTable() )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "DELETE FROM gpkg_extensions WHERE table_name = '%q' AND "
+            "column_name = '%q'",
+            m_pszTableName,
+            m_poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef() );
+        eErr = SQLCommand( m_poDS->GetDB(), pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update gpkg_data_columns if needed.                             */
+/* -------------------------------------------------------------------- */
+    if( m_poDS->HasDataColumnsTable() )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "DELETE FROM gpkg_data_columns WHERE table_name = '%q' AND "
+            "column_name = '%q'",
+            m_pszTableName,
+            m_poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef() );
+        eErr = SQLCommand( m_poDS->GetDB(), pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check foreign key integrity.                                    */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {
+        eErr = m_poDS->PragmaCheck("foreign_key_check", "", 0);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Finish                                                          */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE)
+    {
+        eErr = m_poDS->SoftCommitTransaction();
+        if( eErr == OGRERR_NONE)
+        {
+            eErr = m_poFeatureDefn->DeleteFieldDefn( iFieldToDelete );
+
+            ResetReading();
+        }
+    }
+    else
+    {
+        m_poDS->SoftRollbackTransaction();
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
+                                                OGRFieldDefn* poNewFieldDefn,
+                                                int nFlagsIn )
+{
+    if ( !m_poDS->GetUpdate() )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "AlterFieldDefn");
+        return OGRERR_FAILURE;
+    }
+
+    if (iFieldToAlter < 0 || iFieldToAlter >= m_poFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Defered actions, reset state.                                   */
+/* -------------------------------------------------------------------- */
+    ResetReading();
+    RunDeferredCreationIfNecessary();
+    CreateSpatialIndexIfNecessary();
+
+/* -------------------------------------------------------------------- */
+/*      Check that is a table and not a view                            */
+/* -------------------------------------------------------------------- */
+    if( !IsTable() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Layer %s is not a table",
+                 m_pszTableName);
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check that the new column name is not a duplicate.              */
+/* -------------------------------------------------------------------- */
+
+    const CPLString osOldColName(
+            m_poFeatureDefn->GetFieldDefn(iFieldToAlter)->GetNameRef() );
+    const CPLString osNewColName( (nFlagsIn & ALTER_NAME_FLAG) ?
+                                  CPLString(poNewFieldDefn->GetNameRef()) :
+                                  osOldColName );
+
+    const bool bRenameCol =
+        (nFlagsIn & ALTER_NAME_FLAG) &&
+        strcmp(poNewFieldDefn->GetNameRef(), osOldColName) != 0;
+    if( bRenameCol )
+    {
+        if( (m_pszFidColumn &&
+             strcmp(poNewFieldDefn->GetNameRef(), m_pszFidColumn) == 0) ||
+            (GetGeomType() != wkbNone &&
+             strcmp(poNewFieldDefn->GetNameRef(),
+                    m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()) == 0) ||
+            m_poFeatureDefn->GetFieldIndex(poNewFieldDefn->GetNameRef()) >= 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Field name %s is already used for another field",
+                      poNewFieldDefn->GetNameRef());
+            return OGRERR_FAILURE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+    OGRFieldDefn oTmpFieldDefn(m_poFeatureDefn->GetFieldDefn(iFieldToAlter));
+    if( (nFlagsIn & ALTER_NAME_FLAG) )
+        oTmpFieldDefn.SetName(poNewFieldDefn->GetNameRef());
+    if( (nFlagsIn & ALTER_TYPE_FLAG) )
+        oTmpFieldDefn.SetType(poNewFieldDefn->GetType());
+    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
+    {
+        oTmpFieldDefn.SetWidth(poNewFieldDefn->GetWidth());
+        oTmpFieldDefn.SetPrecision(poNewFieldDefn->GetPrecision());
+    }
+    if( (nFlagsIn & ALTER_NULLABLE_FLAG) )
+    {
+        oTmpFieldDefn.SetNullable(poNewFieldDefn->IsNullable());
+    }
+    if( (nFlagsIn & ALTER_DEFAULT_FLAG) )
+    {
+        oTmpFieldDefn.SetDefault(poNewFieldDefn->GetDefault());
+    }
+    std::vector<OGRFieldDefn*> apoFields;
+    std::vector<OGRFieldDefn*> apoFieldsOld;
+    for( int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        OGRFieldDefn *poFieldDefn;
+        if (iField == iFieldToAlter)
+        {
+            poFieldDefn = &oTmpFieldDefn;
+        }
+        else
+        {
+            poFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
+        }
+        apoFields.push_back(poFieldDefn);
+        apoFieldsOld.push_back(m_poFeatureDefn->GetFieldDefn(iField));
+    }
+
+    const CPLString osColumnsForCreate( GetColumnsOfCreateTable(apoFields) );
+
+/* -------------------------------------------------------------------- */
+/*      Drop any iterator since we change the DB structure              */
+/* -------------------------------------------------------------------- */
+    m_poDS->ResetReadingAllLayers();
+
+    const bool bUseFastMethod = ( m_poDS->nSoftTransactionLevel == 0 );
+
+    if( m_poDS->SoftStartTransaction() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    sqlite3 *hDB = m_poDS->GetDB();
+    SQLResult oTriggers;
+    SQLResultInit(&oTriggers);
+    OGRErr eErr = OGRERR_NONE;
+
+/* -------------------------------------------------------------------- */
+/*      Drop triggers and index that look like to be related to the     */
+/*      column if renaming. We re-install some indexes afterwards.      */
+/* -------------------------------------------------------------------- */
+    if( bRenameCol )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT name, type, sql FROM sqlite_master WHERE "
+            "type IN ('trigger','index') "
+            "AND tbl_name='%q' AND sql LIKE '%%%q%%'",
+            m_pszTableName,
+            SQLEscapeDoubleQuote(osOldColName).c_str() );
+        eErr = SQLQuery(hDB, pszSQL, &oTriggers);
+        sqlite3_free(pszSQL);
+
+        for( int i = 0; i < oTriggers.nRowCount && eErr == OGRERR_NONE ; i++)
+        {
+            pszSQL = sqlite3_mprintf("DROP %s \"%w\"",
+                                     SQLResultGetValue(&oTriggers, 1, i),
+                                     SQLResultGetValue(&oTriggers, 0, i));
+            eErr = SQLCommand(hDB, pszSQL);
+            sqlite3_free(pszSQL);
+        }
+    }
+
+    if( !bUseFastMethod )
+    {
+/* -------------------------------------------------------------------- */
+/*      If we are withing a transaction, we cannot use the method       */
+/*      that consists in altering the database in a raw way.            */
+/* -------------------------------------------------------------------- */
+        const CPLString osFieldListForSelect( BuildSelectFieldList(apoFieldsOld) );
+
+        if( eErr == OGRERR_NONE )
+        {
+            eErr = RecreateTable(osColumnsForCreate, osFieldListForSelect);
+        }
+    }
+    else
+    {
+/* -------------------------------------------------------------------- */
+/*      Rewrite schema in a transaction by altering the database        */
+/*      schema in a rather raw way, as discribed at bottom of           */
+/*      https://www.sqlite.org/lang_altertable.html                     */
+/* -------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------- */
+/*      Collect schema version number.                                  */
+/* -------------------------------------------------------------------- */
+        int nSchemaVersion = SQLGetInteger(hDB,
+                                        "PRAGMA schema_version",
+                                        &eErr);
+
+/* -------------------------------------------------------------------- */
+/*      Turn on writable schema.                                        */
+/* -------------------------------------------------------------------- */
+        if( eErr == OGRERR_NONE )
+        {
+            eErr = m_poDS->PragmaCheck( "writable_schema=ON", "", 0 );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Rewrite CREATE TABLE statement.                                 */
+/* -------------------------------------------------------------------- */
+        if( eErr == OGRERR_NONE )
+        {
+            char* psSQLCreateTable = sqlite3_mprintf("CREATE TABLE \"%w\" (%s)",
+                                    m_pszTableName,
+                                    osColumnsForCreate.c_str());
+            char* pszSQL = sqlite3_mprintf(
+                "UPDATE sqlite_master SET sql='%q' WHERE type='table' AND name='%q'",
+                psSQLCreateTable, m_pszTableName);
+            eErr = SQLCommand( hDB, pszSQL );
+            sqlite3_free(psSQLCreateTable);
+            sqlite3_free(pszSQL);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Increment schema number.                                        */
+/* -------------------------------------------------------------------- */
+        if( eErr == OGRERR_NONE )
+        {
+            char* pszSQL = sqlite3_mprintf(
+                "PRAGMA schema_version = %d", nSchemaVersion + 1);
+            eErr = SQLCommand( hDB, pszSQL );
+            sqlite3_free(pszSQL);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Turn off writable schema.                                        */
+/* -------------------------------------------------------------------- */
+        if( eErr == OGRERR_NONE )
+        {
+            eErr = m_poDS->PragmaCheck( "writable_schema=OFF", "", 0 );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update gpkg_extensions if needed.                               */
+/* -------------------------------------------------------------------- */
+    if( bRenameCol && eErr == OGRERR_NONE && m_poDS->HasExtensionsTable() )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_extensions SET column_name = '%q' WHERE "
+            "table_name = '%q' AND column_name = '%q'",
+            poNewFieldDefn->GetNameRef(),
+            m_pszTableName,
+            osOldColName.c_str() );
+        eErr = SQLCommand( hDB, pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update gpkg_data_columns if needed.                             */
+/* -------------------------------------------------------------------- */
+    if( bRenameCol && eErr == OGRERR_NONE && m_poDS->HasDataColumnsTable() )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_data_columns SET column_name = '%q' WHERE "
+            "table_name = '%q' AND column_name = '%q'",
+            poNewFieldDefn->GetNameRef(),
+            m_pszTableName,
+            osOldColName.c_str() );
+        eErr = SQLCommand( hDB, pszSQL );
+        sqlite3_free(pszSQL);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Run integrity check.                                            */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE )
+    {
+        eErr = m_poDS->PragmaCheck("integrity_check", "ok", 1);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Finish                                                          */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE)
+    {
+        eErr = m_poDS->SoftCommitTransaction();
+
+        // We need to force database reopening due to schema change
+        if( eErr == OGRERR_NONE && bUseFastMethod && !m_poDS->ReOpenDB() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen database");
+            eErr = OGRERR_FAILURE;
+        }
+        hDB = m_poDS->GetDB();
+
+/* -------------------------------------------------------------------- */
+/*      Recreate indices.                                               */
+/* -------------------------------------------------------------------- */
+        for( int i = 0; i < oTriggers.nRowCount && eErr == OGRERR_NONE ; i++)
+        {
+            if( EQUAL(SQLResultGetValue(&oTriggers, 1, i), "index") )
+            {
+                CPLString osSQL( SQLResultGetValue(&oTriggers, 2, i) );
+                // CREATE INDEX idx_name ON table_name(column_name)
+                char** papszTokens = SQLTokenize( osSQL );
+                if( CSLCount(papszTokens) == 8 &&
+                    EQUAL(papszTokens[0], "CREATE") &&
+                    EQUAL(papszTokens[1], "INDEX") &&
+                    EQUAL(papszTokens[3], "ON") &&
+                    EQUAL(papszTokens[5], "(") &&
+                    EQUAL(papszTokens[7], ")") )
+                {
+                    osSQL = "CREATE INDEX ";
+                    osSQL += papszTokens[2];
+                    osSQL += " ON ";
+                    osSQL += papszTokens[4];
+                    osSQL += "(\"";
+                    osSQL += SQLEscapeDoubleQuote(osNewColName);
+                    osSQL += "\")";
+                    eErr = SQLCommand(hDB, osSQL);
+                }
+                CSLDestroy(papszTokens);
+            }
+        }
+
+        if( eErr == OGRERR_NONE )
+        {
+            OGRFieldDefn* poFieldDefn =
+                m_poFeatureDefn->GetFieldDefn(iFieldToAlter);
+
+            if (nFlagsIn & ALTER_TYPE_FLAG)
+            {
+                poFieldDefn->SetType(poNewFieldDefn->GetType());
+            }
+            if (nFlagsIn & ALTER_NAME_FLAG)
+            {
+                poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
+            }
+            if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
+            {
+                poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
+                poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
+            }
+            if (nFlagsIn & ALTER_NULLABLE_FLAG)
+                poFieldDefn->SetNullable(poNewFieldDefn->IsNullable());
+            if (nFlagsIn & ALTER_DEFAULT_FLAG)
+                poFieldDefn->SetDefault(poNewFieldDefn->GetDefault());
+
+            ResetReading();
+        }
+    }
+    else
+    {
+        m_poDS->SoftRollbackTransaction();
+    }
+
+    SQLResultFree(&oTriggers);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                           ReorderFields()                            */
+/************************************************************************/
+
+OGRErr OGRGeoPackageTableLayer::ReorderFields( int* panMap )
+{
+    if ( !m_poDS->GetUpdate() )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  UNSUPPORTED_OP_READ_ONLY,
+                  "ReorderFields");
+        return OGRERR_FAILURE;
+    }
+
+    if (m_poFeatureDefn->GetFieldCount() == 0)
+        return OGRERR_NONE;
+
+    OGRErr eErr = OGRCheckPermutation(panMap, m_poFeatureDefn->GetFieldCount());
+    if (eErr != OGRERR_NONE)
+        return eErr;
+
+/* -------------------------------------------------------------------- */
+/*      Defered actions, reset state.                                   */
+/* -------------------------------------------------------------------- */
+    ResetReading();
+    RunDeferredCreationIfNecessary();
+    CreateSpatialIndexIfNecessary();
+
+/* -------------------------------------------------------------------- */
+/*      Check that is a table and not a view                            */
+/* -------------------------------------------------------------------- */
+    if( !IsTable() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Layer %s is not a table",
+                 m_pszTableName);
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Drop any iterator since we change the DB structure              */
+/* -------------------------------------------------------------------- */
+    m_poDS->ResetReadingAllLayers();
+
+/* -------------------------------------------------------------------- */
+/*      Build list of old fields, and the list of new fields.           */
+/* -------------------------------------------------------------------- */
+    std::vector<OGRFieldDefn*> apoFields;
+    for( int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(panMap[iField]);
+        apoFields.push_back(poFieldDefn);
+    }
+
+    const CPLString osFieldListForSelect( BuildSelectFieldList(apoFields) );
+    const CPLString osColumnsForCreate( GetColumnsOfCreateTable(apoFields) );
+
+/* -------------------------------------------------------------------- */
+/*      Recreate table in a transaction                                 */
+/* -------------------------------------------------------------------- */
+    if( m_poDS->SoftStartTransaction() != OGRERR_NONE )
+        return OGRERR_FAILURE;
+
+    eErr = RecreateTable(osColumnsForCreate, osFieldListForSelect);
+
+/* -------------------------------------------------------------------- */
+/*      Finish                                                          */
+/* -------------------------------------------------------------------- */
+    if( eErr == OGRERR_NONE)
+    {
+        eErr = m_poDS->SoftCommitTransaction();
+
+        if( eErr == OGRERR_NONE )
+            eErr = m_poFeatureDefn->ReorderFieldDefns( panMap );
+
+        ResetReading();
+    }
+    else
+    {
+        m_poDS->SoftRollbackTransaction();
+    }
+
+    return eErr;
+}
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
index 240e74e..92fa198 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GeoPackage Translator
  * Purpose:  Utility functions for OGR GeoPackage driver.
@@ -30,6 +29,8 @@
 #include "ogrgeopackageutility.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: ogrgeopackageutility.cpp 35692 2016-10-11 15:20:11Z rouault $");
+
 /* Runs a SQL command and ignores the result (good for INSERT/UPDATE/CREATE) */
 OGRErr SQLCommand(sqlite3 * poDb, const char * pszSQL)
 {
@@ -155,12 +156,10 @@ GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
 {
     CPLAssert( poDb != NULL );
 
-    sqlite3_stmt *poStmt;
-    int rc;
-    GIntBig i;
+    sqlite3_stmt *poStmt = NULL;
 
     /* Prepare the SQL */
-    rc = sqlite3_prepare_v2(poDb, pszSQL, -1, &poStmt, NULL);
+    int rc = sqlite3_prepare_v2(poDb, pszSQL, -1, &poStmt, NULL);
     if ( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
@@ -179,7 +178,7 @@ GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
     }
 
     /* Read the integer from the row */
-    i = sqlite3_column_int64(poStmt, 0);
+    GIntBig i = sqlite3_column_int64(poStmt, 0);
     sqlite3_finalize(poStmt);
 
     if ( err ) *err = OGRERR_NONE;
@@ -390,7 +389,6 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
 {
     CPLAssert( poGeometry != NULL );
 
-    GByte *pabyPtr;
     GByte byFlags = 0;
     GByte byEnv = 1;
     OGRwkbByteOrder eByteOrder = (OGRwkbByteOrder)CPL_IS_LSB;
@@ -483,7 +481,7 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
         }
     }
 
-    pabyPtr = pabyWkb + szHeader;
+    GByte *pabyPtr = pabyWkb + szHeader;
 
     /* Use the wkbVariantIso for ISO SQL/MM output (differs for 3d geometry) */
     err = poGeometry->exportToWkb(eByteOrder, pabyPtr, wkbVariantIso);
@@ -556,7 +554,7 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHea
     }
 
     /* SrsId */
-    int iSrsId;
+    int iSrsId = 0;
     memcpy(&iSrsId, pabyGpkg+4, 4);
     if ( bSwap )
     {
@@ -620,7 +618,6 @@ OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialR
     CPLAssert( pabyGpkg != NULL );
 
     GPkgHeader oHeader;
-    OGRGeometry *poGeom;
 
     /* Read header */
     OGRErr err = GPkgHeaderFromWKB(pabyGpkg, szGpkg, &oHeader);
@@ -632,6 +629,7 @@ OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialR
     size_t szWkb = szGpkg - oHeader.szHeader;
 
     /* Parse WKB */
+    OGRGeometry *poGeom = NULL;
     err = OGRGeometryFactory::createFromWkb((GByte*)pabyWkb, poSrs, &poGeom,
                                             static_cast<int>(szWkb));
     if ( err != OGRERR_NONE )
@@ -667,3 +665,121 @@ OGRErr GPkgEnvelopeToOGR(GByte *pabyGpkg,
 
     return OGRERR_NONE;
 }
+
+CPLString SQLEscapeDoubleQuote(const char* pszStr)
+{
+    CPLString osRet;
+    while( *pszStr != '\0' )
+    {
+        if( *pszStr == '"' )
+            osRet += "\"\"";
+        else
+            osRet += *pszStr;
+        pszStr ++;
+    }
+    return osRet;
+}
+
+CPLString SQLUnescapeDoubleQuote(const char* pszStr)
+{
+    CPLString osRet;
+    const bool bStartsWithDoubleQuote = (pszStr[0] == '"');
+    if( bStartsWithDoubleQuote )
+        pszStr ++;
+    while( *pszStr != '\0' )
+    {
+        if( bStartsWithDoubleQuote && *pszStr == '"' && pszStr[1] == '"' )
+        {
+            osRet += "\"";
+            pszStr ++;
+        }
+        else if( bStartsWithDoubleQuote && *pszStr == '"' )
+        {
+            break;
+        }
+        else
+            osRet += *pszStr;
+        pszStr ++;
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                             SQLTokenize()                            */
+/************************************************************************/
+
+char** SQLTokenize( const char* pszStr )
+{
+    char** papszTokens = NULL;
+    bool bInQuote = false;
+    char chQuoteChar = '\0';
+    bool bInSpace = true;
+    CPLString osCurrentToken;
+    while( *pszStr != '\0' )
+    {
+        if( *pszStr == ' ' && !bInQuote )
+        {
+            if( !bInSpace )
+            {
+                papszTokens = CSLAddString(papszTokens, osCurrentToken);
+                osCurrentToken.clear();
+            }
+            bInSpace = true;
+        }
+        else if( (*pszStr == '(' || *pszStr == ')' || *pszStr == ',')  && !bInQuote )
+        {
+            if( !bInSpace )
+            {
+                papszTokens = CSLAddString(papszTokens, osCurrentToken);
+                osCurrentToken.clear();
+            }
+            osCurrentToken.clear();
+            osCurrentToken += *pszStr;
+            papszTokens = CSLAddString(papszTokens, osCurrentToken);
+            osCurrentToken.clear();
+            bInSpace = true;
+        }
+        else if( *pszStr == '"' || *pszStr == '\'' )
+        {
+            if( bInQuote && *pszStr == chQuoteChar && pszStr[1] == chQuoteChar )
+            {
+                osCurrentToken += *pszStr;
+                osCurrentToken += *pszStr;
+                pszStr += 2;
+                continue;
+            }
+            else if( bInQuote && *pszStr == chQuoteChar )
+            {
+                osCurrentToken += *pszStr;
+                papszTokens = CSLAddString(papszTokens, osCurrentToken);
+                osCurrentToken.clear();
+                bInSpace = true;
+                bInQuote = false;
+                chQuoteChar = '\0';
+            }
+            else if( bInQuote )
+            {
+                osCurrentToken += *pszStr;
+            }
+            else
+            {
+                chQuoteChar = *pszStr;
+                osCurrentToken.clear();
+                osCurrentToken += chQuoteChar;
+                bInQuote = true;
+                bInSpace = false;
+            }
+        }
+        else
+        {
+            osCurrentToken += *pszStr;
+            bInSpace = false;
+        }
+        pszStr ++;
+    }
+
+    if( !osCurrentToken.empty() )
+        papszTokens = CSLAddString(papszTokens, osCurrentToken);
+
+    return papszTokens;
+}
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
index 93f9e76..7471a92 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: ogrgeopackageutility.h 35679 2016-10-10 14:15:22Z rouault $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Utility header for OGR GeoPackage driver.
@@ -84,4 +84,8 @@ OGRErr              GPkgEnvelopeToOGR(GByte *pabyGpkg, size_t szGpkg, OGREnvelop
 
 OGRErr              GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHeader);
 
+CPLString           SQLEscapeDoubleQuote(const char* pszStr);
+CPLString           SQLUnescapeDoubleQuote(const char* pszStr);
+char**              SQLTokenize( const char* pszSQL );
+
 #endif
diff --git a/ogr/ogrsf_frmts/makefile.vc b/ogr/ogrsf_frmts/makefile.vc
index 140c6f4..208c973 100644
--- a/ogr/ogrsf_frmts/makefile.vc
+++ b/ogr/ogrsf_frmts/makefile.vc
@@ -15,7 +15,7 @@ DIRLIST		=	generic geojson shape ntf sdts tiger s57 dgn mitab gml \
 			$(SDE_DIR) $(IDB_DIR) $(NAS_DIR) $(DODSDIR) \
 			$(LIBKMLDIR) $(WFSDIR) $(SOSIDIR) $(GFTDIR) \
 			$(COUCHDBDIR) $(CLOUDANTDIR) $(FGDB_DIR) $(XLSDIR) $(ODSDIR) $(XLSXDIR) \
-			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR) $(CARTODBDIR) $(AMIGOCLOUD_DIR) \
+			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR) $(CARTODIR) $(AMIGOCLOUD_DIR) \
 			$(PLSCENESDIR) $(CSWDIR) $(MONGODBDIR)
 
 PLUGINDIRLIST	=	$(PLUGIN_ARCOBJECTS_DIR) \
@@ -204,8 +204,8 @@ VFK_OBJ =	vfk\*.obj
 !ENDIF
 
 !IFDEF CURL_LIB
-CARTODBDIR = cartodb
-CARTODB_OBJ = cartodb\*.obj
+CARTODIR = carto
+CARTO_OBJ = carto\*.obj
 !ENDIF
 
 !IFDEF CURL_LIB
@@ -262,7 +262,7 @@ default:
 				$(ILI_OBJ) $(DWG_OBJ) $(SDE_OBJ) $(FGDB_OBJ) $(ARCDRIVER_OBJ) $(IDB_OBJ) \
 				$(DODS_OBJ) $(NAS_OBJ) $(LIBKMLOBJ) $(WFS_OBJ) \
 				$(SOSI_OBJ) $(GFT_OBJ) $(COUCHDB_OBJ) $(CLOUDANT_OBJ) $(XLS_OBJ) $(ODS_OBJ) $(XLSX_OBJ)  \
-				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ) $(CARTODB_OBJ) $(AMIGOCLOUD_OBJ) $(PLSCENES_OBJ) \
+				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ) $(CARTO_OBJ) $(AMIGOCLOUD_OBJ) $(PLSCENES_OBJ) \
 				$(CSW_OBJ) $(MONGODBOBJ)
 	lib /out:ogrsf_frmts_sup.lib \
 				 ..\..\frmts\iso8211\*.obj \
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
index a00c5bc..596c24f 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
+ * $Id: ogrmssqlspatialselectlayer.cpp 35339 2016-09-05 21:50:17Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialSelectLayer class, layer access to the results
@@ -30,8 +30,11 @@
 
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
+#ifdef SQLNCLI_VERSION
+#include <sqlncli.h>
+#endif
 
-CPL_CVSID("$Id: ogrmssqlspatialselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrmssqlspatialselectlayer.cpp 35339 2016-09-05 21:50:17Z tamas $");
 /************************************************************************/
 /*                     OGRMSSQLSpatialSelectLayer()                     */
 /************************************************************************/
@@ -91,6 +94,29 @@ OGRMSSQLSpatialSelectLayer::OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSourc
             pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
             break;
         }
+        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "udt") )
+        {
+#ifdef SQL_CA_SS_UDT_TYPE_NAME
+            SQLCHAR     szUDTTypeName[256];
+            SQLSMALLINT nUDTTypeNameLength = 0;
+
+            SQLColAttribute(poStmt->GetStatement(), (SQLSMALLINT)(iColumn + 1), SQL_CA_SS_UDT_TYPE_NAME,
+                                     szUDTTypeName, sizeof(szUDTTypeName),
+                                     &nUDTTypeNameLength, NULL);
+
+            if ( EQUAL((char*)szUDTTypeName, "geometry") )
+            {
+                nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
+                pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+            }
+            else if ( EQUAL((char*)szUDTTypeName, "geography") )
+            {
+                nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
+                pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+            }
+#endif
+            break;
+        }   
     }
 
     if (pszGeomColumn == NULL && iImageCol >= 0)
diff --git a/ogr/ogrsf_frmts/nas/nashandler.cpp b/ogr/ogrsf_frmts/nas/nashandler.cpp
index 142e29e..727848b 100644
--- a/ogr/ogrsf_frmts/nas/nashandler.cpp
+++ b/ogr/ogrsf_frmts/nas/nashandler.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: nashandler.cpp 34462 2016-06-28 18:51:52Z jef $
+ * $Id: nashandler.cpp 34726 2016-07-19 21:49:14Z jef $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASHandler class.
@@ -269,11 +269,10 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
             return;
         }
 
-        if( EQUAL( pszLast, "Update" )  &&
-            ( m_osLastEnded == "" || m_LastOccasions.empty() ) )
+        if( EQUAL( pszLast, "Update" ) && m_osLastEnded == "" )
         {
             CPLError( CE_Failure, CPLE_AssertionFailed,
-                      "m_osLastEnded == \"\" || m_LastOccasions.empty()" );
+                      "m_osLastEnded == \"\"" );
 
             m_bIgnoreFeature = true;
             m_nDepthFeature = m_nDepth;
@@ -303,8 +302,6 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
         }
         else if( EQUAL( pszLast, "Update" ) )
         {
-            //CPLAssert( m_osLastEnded != "" );
-            //CPLAssert( m_LastOccasions.empty() );
             m_poReader->SetFeaturePropertyDirectly(
                 "endet", CPLStrdup(m_osLastEnded) );
 
@@ -315,6 +312,7 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
               m_poReader->SetFeaturePropertyDirectly(
                   "anlass", CPLStrdup(*it) );
             }
+
             m_osLastEnded = "";
             m_LastOccasions.clear();
         }
diff --git a/ogr/ogrsf_frmts/oci/GNUmakefile b/ogr/ogrsf_frmts/oci/GNUmakefile
index 79db765..987d2e8 100644
--- a/ogr/ogrsf_frmts/oci/GNUmakefile
+++ b/ogr/ogrsf_frmts/oci/GNUmakefile
@@ -7,9 +7,9 @@ OBJ	=	oci_utils.o ogrocisession.o ogrocistatement.o \
 		ogrocitablelayer.o ogrociselectlayer.o ogrocistringbuf.o \
 		ogrociwritablelayer.o ogrociloaderlayer.o ogrocistroke.o
 
-CPPFLAGS	:=	$(OCI_INCLUDE) $(CPPFLAGS)
+CPPFLAGS	:=	$(GDAL_INCLUDE) $(OCI_INCLUDE) $(XTRA_OPT) $(CPPFLAGS) -fPIC
 
-PLUGIN_SO	=	ogr_OCI.$(SO_EXT)
+PLUGIN_SO	=	ogr_OCI.so
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/oci/drv_oci.html b/ogr/ogrsf_frmts/oci/drv_oci.html
index 3a17fd2..28f9a1c 100644
--- a/ogr/ogrsf_frmts/oci/drv_oci.html
+++ b/ogr/ogrsf_frmts/oci/drv_oci.html
@@ -100,12 +100,13 @@ in USER_SDO_GEOM_METADATA and rebuilding the spatial index.<p>
 
 <ul>
 
-<li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer of the
-desired name to be destroyed before creating the requested layer.<p>
+<li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer (=table) of the
+same desired name to be destroyed before creating the requested layer. 
+The default value is “NO"<p>
 
 <li> <b>TRUNCATE</b>: This may be "YES" to force the existing table to
 be reused, but to first truncate all records in the table, preserving
-indexes or dependencies.<p>
+indexes or dependencies. The default value is “NO".<p>
 
 <li> <b>LAUNDER</b>: This may be "YES" to force new fields created on this
 layer to have their field names "laundered" into a form more compatible with
@@ -126,9 +127,10 @@ any of the layer features have valid geometries. The default is "YES".
 Note: option was called INDEX in releases before GDAL 2<p>
 
 <li> <b>INDEX_PARAMETERS</b>: This may be set to pass creation parameters
-when the spatial index is created.  For instance setting INDEX_PARAMETERS to
-SDO_LEVEL=5 would cause a 5 level tile index to be used.  By default no
-parameters are passed causing a default R-Tree spatial index to be created.<p>
+when the spatial index is created.  For instance setting INDEX_PARAMETERS
+to SDO_RTR_PCTFREE=0 would cause the rtree index to be created without any
+empty space. By default no parameters are passed causing a default R-Tree
+spatial index to be created.<p>
 
 <li> <b>ADD_LAYER_GTYPE</b>=YES/NO: (starting with GDAL 2.0) This may be
 set to NO to disable the constraints on the geometry type in the spatial index,
@@ -160,8 +162,22 @@ match the WKT the driver expects.<p>
 groups of 100 per SQL INSERT command, instead of each feature being a separate
 INSERT command.  Having this enabled is the fastest way to load data quickly.
 Multi-load mode is enabled by default, and may be forced off for existing
-layers or for new layers by setting to NO.<p>
-
+layers or for new layers by setting to NO. The number of rows in each group is defined by
+MULTI_LOAD_COUNT. To load one row at a time, set MULTI_LOAD to NO.<p>
+
+<li> <b>MULTI_LOAD_COUNT</b>: Define the number of features on each ARRAY INSERT command, 
+instead of the default 100 item defined by MULTI_LOAD. Since each array insert will commit 
+a transaction, this options shouldn't be combined with ogr2ogr "-gt N". 
+Use "-gt unlimited" preferably when using MULTI_LOAD_COUNT. The default is 100. 
+If neither MULTI_LOAD nor MULTI_LOAD_COUNT are specified, then the loading happens
+in groups of 100 rows.<p>
+    
+<li> <b>FIRST_ID</b>: Define the first numeric value of the id column on the first
+rows. It's also work as a open option when used to append or update an existing dataset.<p>
+    
+<li> <b>NO_LOGGING</b>: Define that the table and the geomtry will be create 
+with nologging attributes.<p>
+    
 <li> <b>LOADER_FILE</b>: If this option is set, all feature information will
 be written to a file suitable for use with SQL*Loader instead of inserted
 directly in the database.  The layer itself is still created in the database
@@ -175,6 +191,18 @@ it can be supplied with the GEOMETRY_NAME layer creation option.<p>
 
 </ul>
 
+<h3>Layer Open Options</h3>
+
+<ul>
+
+<li> <b>FIRST_ID</b>: See Layer Create Options comments on FIRST_ID.<p>
+    
+<li> <b>MULTI_LOAD_COUNT</b>: See Layer Create Options comments on MULTI_LOAD_COUNT.<p>
+
+<li> <b>WORKSPACE</b>: Define what user workspace to use.<p>
+
+</ul>
+
 <h3>Example</h3>
 
 Simple translation of a shapefile into Oracle.  The table 'ABC' will
diff --git a/ogr/ogrsf_frmts/oci/makefile.vc b/ogr/ogrsf_frmts/oci/makefile.vc
index 07df39a..c482878 100644
--- a/ogr/ogrsf_frmts/oci/makefile.vc
+++ b/ogr/ogrsf_frmts/oci/makefile.vc
@@ -22,6 +22,7 @@ clean:
 	-del *.lib
 	-del *.obj *.pdb
 	-del *.exe
+	-del *.dll
 
 plugin:	$(PLUGIN_DLL)
 
diff --git a/ogr/ogrsf_frmts/oci/ogr_oci.h b/ogr/ogrsf_frmts/oci/ogr_oci.h
index 8808012..6eadf36 100644
--- a/ogr/ogrsf_frmts/oci/ogr_oci.h
+++ b/ogr/ogrsf_frmts/oci/ogr_oci.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_oci.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_oci.h 34888 2016-08-03 19:59:19Z ilucena $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Oracle Spatial OGR Driver Declarations.
@@ -414,6 +414,10 @@ class OGROCITableLayer : public OGROCIWritableLayer
     CPLString           osTableName;
     CPLString           osOwner;
 
+    int                 nFirstId;
+    int                 nMultiLoadCount;
+    int                 bMultiLoad;
+
     OCIArray           *hOrdVARRAY;
     OCIArray           *hElemInfoVARRAY;
 
@@ -506,6 +510,7 @@ class OGROCIDataSource : public OGRDataSource
     char               *pszDBName;
 
     int                 bDSUpdate;
+    int                 bNoLogging;
 
     OGROCISession      *poSession;
 
@@ -524,7 +529,8 @@ class OGROCIDataSource : public OGRDataSource
     int                 Open( const char *, char** papszOpenOptions,
                               int bUpdate, int bTestOpen );
     int                 OpenTable( const char *pszTableName,
-                                   int nSRID, int bUpdate, int bTestOpen );
+                                   int nSRID, int bUpdate, int bTestOpen,
+                                   char** papszOpenOptions );
 
     const char          *GetName() { return pszName; }
     int                 GetLayerCount() { return nLayers; }
diff --git a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
index a4301fe..a8b14c2 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocidatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIDataSource class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocidatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocidatasource.cpp 35116 2016-08-15 14:54:25Z ilucena $");
 
 static const int anEPSGOracleMapping[] =
 {
@@ -126,6 +125,8 @@ int OGROCIDataSource::Open( const char * pszNewName,
     const char *pszPassword = "";
     const char *pszDatabase = "";
     char **papszTableList = NULL;
+    const char *pszWorkspace = "";
+
     int   i;
 
     if( pszNewName[4] == '\0' )
@@ -136,6 +137,7 @@ int OGROCIDataSource::Open( const char * pszNewName,
         const char* pszTables = CSLFetchNameValue(papszOpenOptionsIn, "TABLES");
         if( pszTables )
             papszTableList = CSLTokenizeStringComplex(pszTables, ",", TRUE, FALSE );
+        pszWorkspace = CSLFetchNameValueDef(papszOpenOptions, "WORKSPACE", "");
     }
     else
     {
@@ -200,6 +202,18 @@ int OGROCIDataSource::Open( const char * pszNewName,
         return FALSE;
     }
 
+    if( ! EQUAL(pszWorkspace, "") )
+    {
+        OGROCIStringBuf oValidateCmd;
+        OGROCIStatement oValidateStmt( GetSession() );
+
+        oValidateCmd.Append( "call DBMS_WM.GotoWorkspace('" );
+        oValidateCmd.Append( pszWorkspace );
+        oValidateCmd.Append( "')" );
+
+        oValidateStmt.Execute( oValidateCmd.GetString() );
+    }
+
     pszName = CPLStrdup( pszNewName );
 
     bDSUpdate = bUpdate;
@@ -241,7 +255,7 @@ int OGROCIDataSource::Open( const char * pszNewName,
 /* -------------------------------------------------------------------- */
     for( i = 0; papszTableList != NULL && papszTableList[i] != NULL; i++ )
     {
-        OpenTable( papszTableList[i], -1, bUpdate, FALSE );
+        OpenTable( papszTableList[i], -1, bUpdate, FALSE, papszOpenOptionsIn );
     }
 
     CSLDestroy( papszTableList );
@@ -254,7 +268,8 @@ int OGROCIDataSource::Open( const char * pszNewName,
 /************************************************************************/
 
 int OGROCIDataSource::OpenTable( const char *pszNewName,
-                                 int nSRID, int bUpdate, CPL_UNUSED int bTestOpen )
+                                 int nSRID, int bUpdate, CPL_UNUSED int bTestOpen,
+                                 char** papszOpenOptionsIn )
 
 {
 /* -------------------------------------------------------------------- */
@@ -278,6 +293,8 @@ int OGROCIDataSource::OpenTable( const char *pszNewName,
         CPLRealloc( papoLayers,  sizeof(OGROCILayer *) * (nLayers+1) );
     papoLayers[nLayers++] = poLayer;
 
+    poLayer->SetOptions( papszOpenOptionsIn );
+
     return TRUE;
 }
 
@@ -483,13 +500,15 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
     poSession->CleanName( pszSafeLayerName );
     CPLDebug( "OCI", "In Create Layer ..." );
 
+    bNoLogging = CSLFetchBoolean( papszOptions, "NO_LOGGING", false );
+
 /* -------------------------------------------------------------------- */
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
     int iLayer;
 
-    if( CSLFetchBoolean( papszOptions, "TRUNCATE", FALSE ) )
+    if( CSLFetchBoolean( papszOptions, "TRUNCATE", false ) )
     {
         CPLDebug( "OCI", "Calling TruncateLayer for %s", pszLayerName );
         TruncateLayer( pszSafeLayerName );
@@ -540,7 +559,8 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
         CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
     if( pszGeometryName == NULL )
         pszGeometryName = "ORA_GEOMETRY";
-    int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    const bool bGeomNullable =
+        CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true);
 
 /* -------------------------------------------------------------------- */
 /*      Create a basic table with the FID.  Also include the            */
@@ -575,6 +595,18 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
                      (!bGeomNullable) ? " NOT NULL":"");
         }
 
+        if (bNoLogging)
+        {
+            char     szCommand2[1024];
+
+            strncpy( szCommand2, szCommand, sizeof(szCommand) );
+
+            snprintf( szCommand, sizeof(szCommand), "%s NOLOGGING "
+              "VARRAY %s.SDO_ELEM_INFO STORE AS SECUREFILE LOB (NOCACHE NOLOGGING) "
+              "VARRAY %s.SDO_ORDINATES STORE AS SECUREFILE LOB (NOCACHE NOLOGGING) ",
+              szCommand2, pszGeometryName, pszGeometryName);
+        }
+
         if( oStatement.Execute( szCommand ) != CE_None )
         {
             CPLFree( pszSafeLayerName );
@@ -602,8 +634,8 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Set various options on the layer.                               */
 /* -------------------------------------------------------------------- */
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",FALSE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
+    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions, "LAUNDER", false) );
+    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions, "PRECISION", true));
 
     if( CSLFetchNameValue(papszOptions,"DIM") != NULL )
         poLayer->SetDimension( atoi(CSLFetchNameValue(papszOptions,"DIM")) );
diff --git a/ogr/ogrsf_frmts/oci/ogrocidriver.cpp b/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
index ab0bb0e..71f192a 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocidriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIDriver class.
@@ -29,7 +28,7 @@
 
 #include "ogr_oci.h"
 
-CPL_CVSID("$Id: ogrocidriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocidriver.cpp 34888 2016-08-03 19:59:19Z ilucena $");
 
 
 /************************************************************************/
@@ -120,6 +119,9 @@ void RegisterOGROCI()
 "  <Option name='USER' type='string' description='User name'/>"
 "  <Option name='PASSWORD' type='string' description='Password'/>"
 "  <Option name='TABLES' type='string' description='Restricted set of tables to list (comma separated)'/>"
+"  <Option name='WORKSPACE' type='string' description='Workspace'/>"
+"  <Option name='MULTI_LOAD_COUNT' type='int' description='Number of itens for a group INSERT' default='100'/>"
+"  <Option name='FIRST_ID' type='int' description='First id value to be used on append'/>"
 "</OpenOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
@@ -132,6 +134,7 @@ void RegisterOGROCI()
         "  <Option name='INDEX_PARAMETERS' type='string' description='Creation parameters when the spatial index is created'/>"
         "  <Option name='ADD_LAYER_GTYPE' type='boolean' description='May be set to NO to disable the constraints on the geometry type in the spatial index' default='YES'/>"
         "  <Option name='MULTI_LOAD' type='boolean' description='If enabled new features will be created in groups of 100 per SQL INSERT command' default='YES'/>"
+        "  <Option name='MULTI_LOAD_COUNT' type='int' description='Number of itens for a group INSERT' default='100'/>"
         "  <Option name='LOADER_FILE' type='string' description='If this option is set, all feature information will be written to a file suitable for use with SQL*Loader'/>"
         "  <Option name='DIM' type='integer' description='Set to 2 to force the geometries to be 2D, or 3 to be 2.5D' default='3'/>"
         "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='ORA_GEOMETRY'/>"
@@ -140,6 +143,8 @@ void RegisterOGROCI()
         "  <Option name='DIMINFO_Y' type='string' description='ymin,ymax,yres values to control the Y dimension info written into the USER_SDO_GEOM_METADATA table'/>"
         "  <Option name='DIMINFO_Z' type='string' description='zmin,zmax,zres values to control the Z dimension info written into the USER_SDO_GEOM_METADATA table'/>"
         "  <Option name='SRID' type='int' description='Forced SRID of the layer'/>"
+        "  <Option name='FIRST_ID' type='int' description='First id value'/>"
+        "  <Option name='NO_LOGGING' type='boolean' description='Create table with no_logging parameters' default='NO'/>"
         "</LayerCreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
diff --git a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
index 5cf9b45..4c853b3 100644
--- a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocitablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCITableLayer class.  This class provides
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocitablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocitablelayer.cpp 34888 2016-08-03 19:59:19Z ilucena $");
 
 static int nDiscarded = 0;
 static int nHits = 0;
@@ -903,9 +902,35 @@ OGRErr OGROCITableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Get the first id value from open options                        */
+/* -------------------------------------------------------------------- */
+
+    this->nFirstId = -1;
+
+    if (CSLFetchNameValue( papszOptions, "FIRST_ID" ) != NULL)
+    {
+        this->nFirstId = atoi( CSLFetchNameValue( papszOptions, "FIRST_ID" ) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the multi load count value from open options                */
+/* -------------------------------------------------------------------- */
+
+    this->bMultiLoad = CSLFetchBoolean( papszOptions, "MULTI_LOAD", true );
+
+    this->nMultiLoadCount = 100;
+
+    if (CSLFetchNameValue( papszOptions, "MULTI_LOAD_COUNT" ) != NULL)
+    {
+        this->nMultiLoadCount = atoi( CSLFetchNameValue( papszOptions,
+                                                         "MULTI_LOAD_COUNT" ) );
+        this->bMultiLoad = true; // overwrites MULTI_LOAD=NO
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Do the actual creation.                                         */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "MULTI_LOAD", true ) )
+    if( bMultiLoad )
         return BoundCreateFeature( poFeature );
     else
         return UnboundCreateFeature( poFeature );
@@ -1628,14 +1653,14 @@ int OGROCITableLayer::AllocAndBindForWrite()
 /*      Decide on the number of rows we want to be able to cache at     */
 /*      a time.                                                         */
 /* -------------------------------------------------------------------- */
-    nWriteCacheMax = 100;
+    nWriteCacheMax = nMultiLoadCount;
 
 /* -------------------------------------------------------------------- */
 /*      Collect the INSERT statement.                                   */
 /* -------------------------------------------------------------------- */
     OGROCIStringBuf oCmdBuf;
 
-    oCmdBuf.Append( "INSERT INTO \"" );
+    oCmdBuf.Append( "INSERT /*+ APPEND */ INTO \"" );
     oCmdBuf.Append( poFeatureDefn->GetName() );
     oCmdBuf.Append( "\"(\"" );
     oCmdBuf.Append( pszFIDName );
@@ -2118,8 +2143,8 @@ void OGROCITableLayer::CreateSpatialIndex()
 /*      If the user has disabled INDEX support then don't create the    */
 /*      index.                                                          */
 /* -------------------------------------------------------------------- */
-        if( !CSLFetchBoolean( papszOptions, "SPATIAL_INDEX", TRUE ) ||
-            !CSLFetchBoolean( papszOptions, "INDEX", TRUE ) )
+        if( !CSLFetchBoolean( papszOptions, "SPATIAL_INDEX", true ) ||
+            !CSLFetchBoolean( papszOptions, "INDEX", true ) )
             return;
 
 /* -------------------------------------------------------------------- */
@@ -2205,6 +2230,9 @@ void OGROCITableLayer::CreateSpatialIndex()
 
 int OGROCITableLayer::GetMaxFID()
 {
+    if( nFirstId > 0 )
+        return nFirstId - 1;
+
     if( pszFIDName == NULL )
         return 0;
 
diff --git a/ogr/ogrsf_frmts/ogr_formats.html b/ogr/ogrsf_frmts/ogr_formats.html
index 1af80c7..e0d1fcd 100644
--- a/ogr/ogrsf_frmts/ogr_formats.html
+++ b/ogr/ogrsf_frmts/ogr_formats.html
@@ -80,8 +80,8 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="drv_cartodb.html">CartoDB</a>
-</td><td> CartoDB
+<tr><td> <a href="drv_carto.html">Carto</a>
+</td><td> Carto
 </td><td> Yes
 </td><td> Yes
 </td><td> No, needs libcurl
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.h b/ogr/ogrsf_frmts/ogrsf_frmts.h
index cff2944..f846586 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.h
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogrsf_frmts.h 35040 2016-08-10 14:02:46Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to format registration, and file opening.
@@ -412,7 +412,8 @@ void CPL_DLL RegisterOGRXLSX();
 void CPL_DLL RegisterOGRElastic();
 void CPL_DLL RegisterOGRGeoPackage();
 void CPL_DLL RegisterOGRWalk();
-void CPL_DLL RegisterOGRCartoDB();
+void CPL_DLL RegisterOGRCarto();
+void CPL_DLL RegisterOGRCartoDB(); // Just kept for C ABI stability
 void CPL_DLL RegisterOGRAmigoCloud();
 void CPL_DLL RegisterOGRSXF();
 void CPL_DLL RegisterOGROpenFileGDB();
diff --git a/ogr/ogrsf_frmts/pg/ogr_pg.h b/ogr/ogrsf_frmts/pg/ogr_pg.h
index 5bf5ffd..d484d01 100644
--- a/ogr/ogrsf_frmts/pg/ogr_pg.h
+++ b/ogr/ogrsf_frmts/pg/ogr_pg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pg.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_pg.h 35632 2016-10-07 13:45:42Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL driver.
@@ -502,6 +502,9 @@ class OGRPGDataSource : public OGRDataSource
     int                 bBinaryTimeFormatIsInt8;
     int                 bUseEscapeStringSyntax;
 
+    bool                m_bHasGeometryColumns;
+    bool                m_bHasSpatialRefSys;
+
     int                GetUndefinedSRID() const { return nUndefinedSRID; }
 
   public:
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
index 1487659..7bcad5c 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogrpgdatasource.cpp 35632 2016-10-07 13:45:42Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -37,7 +37,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrpgdatasource.cpp 35632 2016-10-07 13:45:42Z rouault $");
 
 static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 
@@ -67,6 +67,8 @@ OGRPGDataSource::OGRPGDataSource() :
     nSoftTransactionLevel = 0;
     bBinaryTimeFormatIsInt8 = FALSE;
     bUseEscapeStringSyntax = FALSE;
+    m_bHasGeometryColumns = true;
+    m_bHasSpatialRefSys = true;
 
     nGeometryOID = (Oid) 0;
     nGeographyOID = (Oid) 0;
@@ -795,6 +797,9 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         OGRPGClearResult( hResult );
     }
 
+    m_bHasGeometryColumns = OGRPG_Check_Table_Exists(hPGConn, "geometry_columns");
+    m_bHasSpatialRefSys = OGRPG_Check_Table_Exists(hPGConn, "spatial_ref_sys");
+
 /* -------------------------------------------------------------------- */
 /*      Find out "unknown SRID" value                                   */
 /* -------------------------------------------------------------------- */
@@ -2174,7 +2179,7 @@ OGRErr OGRPGDataSource::InitializeMetadataTables()
 OGRSpatialReference *OGRPGDataSource::FetchSRS( int nId )
 
 {
-    if( nId < 0 )
+    if( nId < 0 || !m_bHasSpatialRefSys )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -2253,7 +2258,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     char                *pszWKT = NULL;
     const char*         pszAuthorityName;
 
-    if( poSRS == NULL )
+    if( poSRS == NULL || !m_bHasSpatialRefSys )
         return nUndefinedSRID;
 
     OGRSpatialReference oSRS(*poSRS);
diff --git a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
index ffd7d80..134496b 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogrpgtablelayer.cpp 35632 2016-10-07 13:45:42Z rouault $
 
  *
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -37,7 +37,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrpgtablelayer.cpp 35632 2016-10-07 13:45:42Z rouault $");
 
 
 #define USE_COPY_UNSET  -10
@@ -646,7 +646,7 @@ int OGRPGTableLayer::ReadTableDefinition()
 
       /* Get the geometry type and dimensions from the table, or */
       /* from its parents if it is a derived table, or from the parent of the parent, etc.. */
-      int bGoOn = TRUE;
+      int bGoOn = poDS->m_bHasGeometryColumns;
       int bHasPostGISGeometry =
         (poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY);
 
@@ -2837,6 +2837,11 @@ void OGRPGTableLayer::ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn)
     CPLString    osCommand;
 
     int nSRSId = poDS->GetUndefinedSRID();
+    if( !poDS->m_bHasGeometryColumns )
+    {
+        poGFldDefn->nSRSId = nSRSId;
+        return;
+    }
 
     osCommand.Printf(
                 "SELECT srid FROM geometry_columns "
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
index 58e12ae..01c6add 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgutility.cpp 32078 2015-12-08 09:09:45Z rouault $
+ * $Id: ogrpgutility.cpp 35632 2016-10-07 13:45:42Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility methods
@@ -30,7 +30,7 @@
 #include "ogr_pg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgutility.cpp 32078 2015-12-08 09:09:45Z rouault $");
+CPL_CVSID("$Id: ogrpgutility.cpp 35632 2016-10-07 13:45:42Z rouault $");
 
 /************************************************************************/
 /*                         OGRPG_PQexec()                               */
@@ -94,3 +94,21 @@ PGresult *OGRPG_PQexec(PGconn *conn, const char *query, int bMultipleCommandAllo
 
     return hResult;
 }
+
+
+/************************************************************************/
+/*                       OGRPG_Check_Table_Exists()                     */
+/************************************************************************/
+
+bool OGRPG_Check_Table_Exists(PGconn *hPGConn, const char * pszTableName)
+{
+    CPLString osSQL;
+    osSQL.Printf("SELECT 1 FROM information_schema.tables WHERE table_name = %s LIMIT 1",
+                 OGRPGEscapeString(hPGConn, pszTableName).c_str());
+    PGresult* hResult = OGRPG_PQexec(hPGConn, osSQL);
+    bool bRet = ( hResult && PQntuples(hResult) == 1 );
+    if( !bRet )
+        CPLDebug("PG", "Does not have %s table", pszTableName);
+    OGRPGClearResult( hResult );
+    return bRet;
+}
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.h b/ogr/ogrsf_frmts/pg/ogrpgutility.h
index 2371fe1..5401909 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.h
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgutility.h 27784 2014-10-02 15:43:18Z rouault $
+ * $Id: ogrpgutility.h 35632 2016-10-07 13:45:42Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private utilities for OGR/PostgreSQL driver.
@@ -53,5 +53,7 @@ inline void OGRPGClearResult( PGresult*& hResult )
     }
 }
 
+bool OGRPG_Check_Table_Exists(PGconn *hPGConn, const char * pszTableName);
+
 #endif /* ndef OGRPGUTILITY_H_INCLUDED */
 
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
index 9ebd984..b365784 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrplscenesdataset.cpp 33883 2016-04-03 17:55:21Z rouault $
+ * $Id: ogrplscenesdataset.cpp 35486 2016-09-17 16:39:10Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesDataset
@@ -29,7 +29,7 @@
 
 #include "ogr_plscenes.h"
 
-CPL_CVSID("$Id: ogrplscenesdataset.cpp 33883 2016-04-03 17:55:21Z rouault $");
+CPL_CVSID("$Id: ogrplscenesdataset.cpp 35486 2016-09-17 16:39:10Z rouault $");
 
 /************************************************************************/
 /*                         OGRPLScenesDataset()                         */
@@ -195,6 +195,7 @@ json_object* OGRPLScenesDataset::RunRequest(const char* pszURL,
                                             int bQuiet404Error)
 {
     char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
+    papszOptions = CSLSetNameValue(papszOptions, "MAX_RETRY", "3");
     CPLHTTPResult * psResult;
     if( STARTS_WITH(osBaseURL, "/vsimem/") &&
         STARTS_WITH(pszURL, "/vsimem/") )
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
index 7d15359..c1889fb 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
@@ -1,5 +1,6 @@
 /******************************************************************************
- * $Id: ogrplsceneslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ry
+ * $Id: ogrplsceneslayer.cpp 35490 2016-09-19 12:24:14Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesLayer
@@ -30,7 +31,7 @@
 #include "ogr_plscenes.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrplsceneslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrplsceneslayer.cpp 35490 2016-09-19 12:24:14Z rouault $");
 
 typedef struct
 {
@@ -194,8 +195,36 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
                   poNode->papoSubExpr[0]->field_index != poFeatureDefn->GetFieldIndex("id") &&
                   poNode->papoSubExpr[0]->field_index < poFeatureDefn->GetFieldCount() )
         {
-            OGRFieldDefn *poFieldDefn;
-            poFieldDefn = poFeatureDefn->GetFieldDefn(poNode->papoSubExpr[0]->field_index);
+            OGRFieldDefn *poFieldDefn =
+                poFeatureDefn->GetFieldDefn(poNode->papoSubExpr[0]->field_index);
+
+            int nOperation = poNode->nOperation;
+
+            // image_quality supports only gte filters
+            // (https://www.planet.com/docs-v0/v0/scenes/planetscope/#metadata)
+            if( poNode->papoSubExpr[0]->field_index ==
+                    poFeatureDefn->GetFieldIndex("image_statistics.image_quality") &&
+                nOperation != SWQ_GE )
+            {
+                // == target can be safely turned as >= target
+                if( poNode->nOperation == SWQ_EQ &&
+                    poNode->papoSubExpr[1]->field_type == SWQ_STRING &&
+                    strcmp(poNode->papoSubExpr[1]->string_value, "target") == 0 )
+                {
+                    nOperation = SWQ_GE;
+                }
+                else
+                {
+                    if( !bFilterMustBeClientSideEvaluated )
+                    {
+                        bFilterMustBeClientSideEvaluated = TRUE;
+                        CPLDebug("PLSCENES",
+                                 "Part or full filter will have to be "
+                                 "evaluated on client side.");
+                    }
+                    return "";
+                }
+            }
 
             CPLString osFilter(poFieldDefn->GetNameRef());
 
@@ -211,22 +240,23 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
             }
 
             osFilter += ".";
-            if( poNode->nOperation == SWQ_EQ )
+
+            if( nOperation == SWQ_EQ )
             {
                 if( bDateTimeParsed )
                     osFilter += "gte";
                 else
                     osFilter += "eq";
             }
-            else if( poNode->nOperation == SWQ_NE )
+            else if( nOperation == SWQ_NE )
                 osFilter += "neq";
-            else if( poNode->nOperation == SWQ_LT )
+            else if( nOperation == SWQ_LT )
                 osFilter += "lt";
-            else if( poNode->nOperation == SWQ_LE )
+            else if( nOperation == SWQ_LE )
                 osFilter += "lte";
-            else if( poNode->nOperation == SWQ_GT )
+            else if( nOperation == SWQ_GT )
                 osFilter += "gt";
-            else if( poNode->nOperation == SWQ_GE )
+            else if( nOperation == SWQ_GE )
                 osFilter += "gte";
             osFilter += "=";
 
@@ -242,7 +272,7 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
                 {
                     osFilter += CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
                                            nYear, nMonth, nDay, nHour, nMinute, nSecond);
-                    if( poNode->nOperation == SWQ_EQ )
+                    if( nOperation == SWQ_EQ )
                     {
                         osFilter += "&";
                         osFilter += poFieldDefn->GetNameRef();
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
index 8e69555..9d54d9b 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrplscenesv1dataset.cpp 33924 2016-04-09 17:59:16Z rouault $
+ * $Id: ogrplscenesv1dataset.cpp 35486 2016-09-17 16:39:10Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesV1Dataset
@@ -30,7 +30,7 @@
 #include "ogr_plscenes.h"
 #include <time.h>
 
-CPL_CVSID("$Id: ogrplscenesv1dataset.cpp 33924 2016-04-09 17:59:16Z rouault $");
+CPL_CVSID("$Id: ogrplscenesv1dataset.cpp 35486 2016-09-17 16:39:10Z rouault $");
 
 /************************************************************************/
 /*                         OGRPLScenesV1Dataset()                       */
@@ -270,6 +270,7 @@ json_object* OGRPLScenesV1Dataset::RunRequest(const char* pszURL,
         papszOptions = CSLSetNameValue(papszOptions, "HEADERS", osHeaders);
         papszOptions = CSLSetNameValue(papszOptions, "POSTFIELDS", pszPostContent);
     }
+    papszOptions = CSLSetNameValue(papszOptions, "MAX_RETRY", "3");
     CPLHTTPResult * psResult;
     if( STARTS_WITH(m_osBaseURL, "/vsimem/") &&
         STARTS_WITH(pszURL, "/vsimem/") )
diff --git a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
index 5fa2b45..ee87d11 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrs57datasource.cpp 34384 2016-06-20 17:09:24Z rouault $
+ * $Id: ogrs57datasource.cpp 34800 2016-07-27 16:52:35Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57DataSource class
@@ -32,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_s57.h"
 
-CPL_CVSID("$Id: ogrs57datasource.cpp 34384 2016-06-20 17:09:24Z rouault $");
+CPL_CVSID("$Id: ogrs57datasource.cpp 34800 2016-07-27 16:52:35Z rouault $");
 
 /************************************************************************/
 /*                          OGRS57DataSource()                          */
@@ -57,18 +57,18 @@ OGRS57DataSource::OGRS57DataSource(char** papszOpenOptionsIn) :
 /* -------------------------------------------------------------------- */
     const char *pszOptString = CPLGetConfigOption( "OGR_S57_OPTIONS", NULL );
 
-    if ( pszOptString == NULL )
-        return;
-
-    papszOptions =
-        CSLTokenizeStringComplex( pszOptString, ",", FALSE, FALSE );
-
-    if ( papszOptions && *papszOptions )
+    if ( pszOptString != NULL )
     {
-        CPLDebug( "S57", "The following S57 options are being set:" );
-        char **papszCurOption = papszOptions;
-        while( *papszCurOption )
-            CPLDebug( "S57", "    %s", *papszCurOption++ );
+        papszOptions =
+            CSLTokenizeStringComplex( pszOptString, ",", FALSE, FALSE );
+
+        if ( papszOptions && *papszOptions )
+        {
+            CPLDebug( "S57", "The following S57 options are being set:" );
+            char **papszCurOption = papszOptions;
+            while( *papszCurOption )
+                CPLDebug( "S57", "    %s", *papszCurOption++ );
+        }
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/shape/dbfopen.c b/ogr/ogrsf_frmts/shape/dbfopen.c
index 257c84e..9f8edd0 100644
--- a/ogr/ogrsf_frmts/shape/dbfopen.c
+++ b/ogr/ogrsf_frmts/shape/dbfopen.c
@@ -1635,8 +1635,11 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
    newDBF->nRecordLength = psDBF->nRecordLength;
    newDBF->nHeaderLength = psDBF->nHeaderLength;
 
-   newDBF->pszHeader = (char *) malloc ( newDBF->nHeaderLength );
-   memcpy ( newDBF->pszHeader, psDBF->pszHeader, newDBF->nHeaderLength );
+   if( psDBF->pszHeader )
+   {
+        newDBF->pszHeader = (char *) malloc ( XBASE_FLDHDR_SZ * psDBF->nFields );
+        memcpy ( newDBF->pszHeader, psDBF->pszHeader, XBASE_FLDHDR_SZ * psDBF->nFields );
+   }
 
    newDBF->panFieldOffset = (int *) malloc ( sizeof(int) * psDBF->nFields );
    memcpy ( newDBF->panFieldOffset, psDBF->panFieldOffset, sizeof(int) * psDBF->nFields );
diff --git a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
index b05c258..749331d 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshapelayer.cpp 34069 2016-04-23 17:59:00Z rouault $
+ * $Id: ogrshapelayer.cpp 35625 2016-10-06 13:59:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeLayer class.
@@ -40,7 +40,7 @@
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrshapelayer.cpp 34069 2016-04-23 17:59:00Z rouault $");
+CPL_CVSID("$Id: ogrshapelayer.cpp 35625 2016-10-06 13:59:48Z rouault $");
 
 /************************************************************************/
 /*                           OGRShapeLayer()                            */
@@ -2264,6 +2264,90 @@ OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
 }
 
 /************************************************************************/
+/*                            CopyInPlace()                             */
+/************************************************************************/
+
+static bool CopyInPlace( VSILFILE* fpTarget, const CPLString& osSourceFilename )
+{
+    VSILFILE* fpSource = VSIFOpenL(osSourceFilename, "rb");
+    if( fpSource == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Cannot open %s", osSourceFilename.c_str());
+        return false;
+    }
+
+    const size_t nBufferSize = 4096;
+    void* pBuffer = CPLMalloc(nBufferSize);
+    VSIFSeekL( fpTarget, 0, SEEK_SET );
+    bool bRet = true;
+    while( true )
+    {
+        size_t nRead = VSIFReadL( pBuffer, 1, nBufferSize, fpSource );
+        size_t nWritten = VSIFWriteL( pBuffer, 1, nRead, fpTarget );
+        if( nWritten != nRead )
+        {
+            bRet = false;
+            break;
+        }
+        if( nRead < nBufferSize )
+            break;
+    }
+
+    if( bRet )
+    {
+        bRet = VSIFTruncateL( fpTarget, VSIFTellL(fpTarget) ) == 0;
+        if( !bRet )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Truncation failed");
+        }
+    }
+
+    CPLFree(pBuffer);
+    VSIFCloseL(fpSource);
+    return bRet;
+}
+
+/************************************************************************/
+/*                       CheckFileDeletion()                            */
+/************************************************************************/
+
+static void CheckFileDeletion( const CPLString& osFilename )
+{
+    // On Windows, sometimes the file is still triansiently reported
+    // as existing although being deleted, which makes QGIS things that
+    // an issue arose. The following helps to reduce that risk.
+    VSIStatBufL sStat;
+    if( VSIStatL( osFilename, &sStat) == 0 &&
+        VSIStatL( osFilename, &sStat) == 0 )
+    {
+        CPLDebug( "Shape",
+                  "File %s is still reported as existing whereas "
+                  "it should have been deleted",
+                  osFilename.c_str() );
+    }
+}
+
+/************************************************************************/
+/*                         ForceDeleteFile()                            */
+/************************************************************************/
+
+static void ForceDeleteFile( const CPLString& osFilename )
+{
+    if( VSIUnlink( osFilename ) != 0 )
+    {
+        // In case of failure retry with a small delay (Windows specific)
+        CPLSleep(0.1);
+        if( VSIUnlink( osFilename ) != 0 )
+        {
+            CPLDebug( "Shape", "Cannot delete %s : %s",
+                      osFilename.c_str(), VSIStrerror( errno ) );
+        }
+    }
+    CheckFileDeletion( osFilename );
+}
+
+/************************************************************************/
 /*                               Repack()                               */
 /*                                                                      */
 /*      Repack the shape and dbf file, dropping deleted records.        */
@@ -2273,7 +2357,7 @@ OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
 OGRErr OGRShapeLayer::Repack()
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -2287,32 +2371,36 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
 /*      Build a list of records to be dropped.                          */
 /* -------------------------------------------------------------------- */
-    int *panRecordsToDelete = (int*) CPLMalloc(sizeof(int)*128);
-    int nDeleteCount = 0, nDeleteCountAlloc = 128;
-    int iShape = 0;
+    int *panRecordsToDelete = static_cast<int *>( CPLMalloc(sizeof(int)*128) );
+    int nDeleteCount = 0;
+    int nDeleteCountAlloc = 128;
     OGRErr eErr = OGRERR_NONE;
 
     if( hDBF != NULL )
     {
-        for( iShape = 0; iShape < nTotalShapeCount; iShape++ )
+        for( int iShape = 0; iShape < nTotalShapeCount; iShape++ )
         {
             if( DBFIsRecordDeleted( hDBF, iShape ) )
             {
                 if( nDeleteCount == nDeleteCountAlloc )
                 {
-                    int nDeleteCountAllocNew =
+                    const int nDeleteCountAllocNew =
                         nDeleteCountAlloc + nDeleteCountAlloc / 3 + 32;
                     if( nDeleteCountAlloc >= (INT_MAX - 32) / 4 * 3 ||
-                        nDeleteCountAllocNew > INT_MAX / (int)sizeof(int) )
+                        nDeleteCountAllocNew >
+                        INT_MAX / static_cast<int>(sizeof(int)) )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                "Too many features to delete : %d", nDeleteCount );
+                        CPLError(
+                            CE_Failure, CPLE_AppDefined,
+                            "Too many features to delete : %d", nDeleteCount );
                         CPLFree( panRecordsToDelete );
                         return OGRERR_FAILURE;
                     }
                     nDeleteCountAlloc = nDeleteCountAllocNew;
-                    int* panRecordsToDeleteNew = (int*) VSI_REALLOC_VERBOSE(
-                        panRecordsToDelete, nDeleteCountAlloc * sizeof(int) );
+                    int* panRecordsToDeleteNew =
+                        static_cast<int*>( VSI_REALLOC_VERBOSE(
+                            panRecordsToDelete,
+                            nDeleteCountAlloc * sizeof(int) ));
                     if( panRecordsToDeleteNew == NULL )
                     {
                         CPLFree( panRecordsToDelete );
@@ -2325,7 +2413,7 @@ OGRErr OGRShapeLayer::Repack()
             if( VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)) )
             {
                 CPLFree( panRecordsToDelete );
-                return OGRERR_FAILURE; /* There's an I/O error */
+                return OGRERR_FAILURE;  //I/O error.
             }
         }
     }
@@ -2344,32 +2432,41 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
 /*      Find existing filenames with exact case (see #3293).            */
 /* -------------------------------------------------------------------- */
-    CPLString osDirname(CPLGetPath(pszFullName));
-    CPLString osBasename(CPLGetBasename(pszFullName));
+    const CPLString osDirname(CPLGetPath(pszFullName));
+    const CPLString osBasename(CPLGetBasename(pszFullName));
 
-    CPLString osDBFName, osSHPName, osSHXName, osCPGName;
+    CPLString osDBFName;
+    CPLString osSHPName;
+    CPLString osSHXName;
+    CPLString osCPGName;
     char **papszCandidates = VSIReadDir( osDirname );
     int i = 0;
-    while(papszCandidates != NULL && papszCandidates[i] != NULL)
+    while( papszCandidates != NULL && papszCandidates[i] != NULL )
     {
-        CPLString osCandidateBasename = CPLGetBasename(papszCandidates[i]);
-        CPLString osCandidateExtension = CPLGetExtension(papszCandidates[i]);
+        const CPLString osCandidateBasename =
+            CPLGetBasename(papszCandidates[i]);
+        const CPLString osCandidateExtension =
+            CPLGetExtension(papszCandidates[i]);
 #ifdef WIN32
-        /* On Windows, as filenames are case insensitive, a shapefile layer can be made of */
-        /* foo.shp and FOO.DBF, so use case insensitive comparison */
-        if (EQUAL(osCandidateBasename, osBasename))
+        // On Windows, as filenames are case insensitive, a shapefile layer can
+        // be made of foo.shp and FOO.DBF, so use case insensitive comparison.
+        if( EQUAL(osCandidateBasename, osBasename) )
 #else
-        if (osCandidateBasename.compare(osBasename) == 0)
+        if( osCandidateBasename.compare(osBasename) == 0 )
 #endif
         {
-            if (EQUAL(osCandidateExtension, "dbf"))
-                osDBFName = CPLFormFilename(osDirname, papszCandidates[i], NULL);
-            else if (EQUAL(osCandidateExtension, "shp"))
-                osSHPName = CPLFormFilename(osDirname, papszCandidates[i], NULL);
-            else if (EQUAL(osCandidateExtension, "shx"))
-                osSHXName = CPLFormFilename(osDirname, papszCandidates[i], NULL);
-            else if (EQUAL(osCandidateExtension, "cpg"))
-                osCPGName = CPLFormFilename(osDirname, papszCandidates[i], NULL);
+            if( EQUAL(osCandidateExtension, "dbf") )
+                osDBFName =
+                    CPLFormFilename(osDirname, papszCandidates[i], NULL);
+            else if( EQUAL(osCandidateExtension, "shp") )
+                osSHPName =
+                    CPLFormFilename(osDirname, papszCandidates[i], NULL);
+            else if( EQUAL(osCandidateExtension, "shx") )
+                osSHXName =
+                    CPLFormFilename(osDirname, papszCandidates[i], NULL);
+            else if( EQUAL(osCandidateExtension, "cpg") )
+                osCPGName =
+                    CPLFormFilename(osDirname, papszCandidates[i], NULL);
         }
 
         i++;
@@ -2377,11 +2474,12 @@ OGRErr OGRShapeLayer::Repack()
     CSLDestroy(papszCandidates);
     papszCandidates = NULL;
 
-    if( hDBF != NULL && osDBFName.size() == 0)
+    if( hDBF != NULL && osDBFName.size() == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot find the filename of the DBF file, but we managed to open it before !");
-        /* Should not happen, really */
+                 "Cannot find the filename of the DBF file, but we managed to "
+                 "open it before !");
+        // Should not happen, really.
         CPLFree( panRecordsToDelete );
         return OGRERR_FAILURE;
     }
@@ -2389,8 +2487,9 @@ OGRErr OGRShapeLayer::Repack()
     if( hSHP != NULL && osSHPName.size() == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot find the filename of the SHP file, but we managed to open it before !");
-        /* Should not happen, really */
+                 "Cannot find the filename of the SHP file, but we managed to "
+                 "open it before !");
+        // Should not happen, really.
         CPLFree( panRecordsToDelete );
         return OGRERR_FAILURE;
     }
@@ -2398,8 +2497,9 @@ OGRErr OGRShapeLayer::Repack()
     if( hSHP != NULL && osSHXName.size() == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot find the filename of the SHX file, but we managed to open it before !");
-        /* Should not happen, really */
+                 "Cannot find the filename of the SHX file, but we managed to "
+                 "open it before !");
+        // Should not happen, really.
         CPLFree( panRecordsToDelete );
         return OGRERR_FAILURE;
     }
@@ -2414,36 +2514,35 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
 /*      Create a new dbf file, matching the old.                        */
 /* -------------------------------------------------------------------- */
-    int bMustReopenDBF = FALSE;
+    bool bMustReopenDBF = false;
+    CPLString oTempFileDBF;
+    const int nNewRecords = nTotalShapeCount - nDeleteCount;
 
     if( hDBF != NULL && nDeleteCount > 0 )
     {
-        bMustReopenDBF = TRUE;
+        bMustReopenDBF = true;
 
-        CPLString oTempFile(CPLFormFilename(osDirname, osBasename, NULL));
-        oTempFile += "_packed.dbf";
+        oTempFileDBF = CPLFormFilename(osDirname, osBasename, NULL);
+        oTempFileDBF += "_packed.dbf";
 
-        DBFHandle hNewDBF = DBFCloneEmpty( hDBF, oTempFile );
+        DBFHandle hNewDBF = DBFCloneEmpty( hDBF, oTempFileDBF );
         if( hNewDBF == NULL )
         {
             CPLFree( panRecordsToDelete );
 
             CPLError( CE_Failure, CPLE_OpenFailed,
-                    "Failed to create temp file %s.",
-                    oTempFile.c_str() );
+                      "Failed to create temp file %s.",
+                      oTempFileDBF.c_str() );
             return OGRERR_FAILURE;
         }
 
-        /* Delete temporary .cpg file if existing */
+        // Delete temporary .cpg file if existing.
         if( osCPGName.size() )
         {
-            CPLString oCPGTempFile = CPLFormFilename(osDirname, osBasename, NULL);
+            CPLString oCPGTempFile =
+                CPLFormFilename(osDirname, osBasename, NULL);
             oCPGTempFile += "_packed.cpg";
-            if( VSIUnlink( oCPGTempFile ) != 0 )
-            {
-                CPLDebug( "Shape", "Did not manage to remove temporary .cpg file: %s",
-                        VSIStrerror( errno ) );
-            }
+            ForceDeleteFile( oCPGTempFile );
         }
 
 /* -------------------------------------------------------------------- */
@@ -2452,73 +2551,75 @@ OGRErr OGRShapeLayer::Repack()
         int iDestShape = 0;
         int iNextDeletedShape = 0;
 
-        for( iShape = 0;
-            iShape < nTotalShapeCount && eErr == OGRERR_NONE;
-            iShape++ )
+        for( int iShape = 0;
+             iShape < nTotalShapeCount && eErr == OGRERR_NONE;
+             iShape++ )
         {
             if( panRecordsToDelete[iNextDeletedShape] == iShape )
+            {
                 iNextDeletedShape++;
+            }
             else
             {
-                void *pTuple = (void *) DBFReadTuple( hDBF, iShape );
-                if( pTuple == NULL )
-                    eErr = OGRERR_FAILURE;
-                else if( !DBFWriteTuple( hNewDBF, iDestShape++, pTuple ) )
+                void *pTuple =
+                    const_cast<char *>( DBFReadTuple( hDBF, iShape ) );
+                if( pTuple == NULL ||
+                    !DBFWriteTuple( hNewDBF, iDestShape++, pTuple ) )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Error writing record %d in .dbf", iShape);
                     eErr = OGRERR_FAILURE;
+                }
             }
         }
 
-        if( eErr != OGRERR_NONE )
-        {
-            CPLFree( panRecordsToDelete );
-            VSIUnlink( oTempFile );
-            DBFClose( hNewDBF );
-            return eErr;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup the old .dbf and rename the new one.                    */
-/* -------------------------------------------------------------------- */
-        DBFClose( hDBF );
         DBFClose( hNewDBF );
-        hDBF = hNewDBF = NULL;
-
-        if( VSIUnlink( osDBFName ) != 0 )
-        {
-            CPLDebug( "Shape", "Failed to delete DBF file: %s", VSIStrerror( errno ) );
-            CPLFree( panRecordsToDelete );
-
-            hDBF = poDS->DS_DBFOpen ( osDBFName, bUpdateAccess ? "r+" : "r" );
-
-            VSIUnlink( oTempFile );
 
-            return OGRERR_FAILURE;
-        }
-
-        if( VSIRename( oTempFile, osDBFName ) != 0 )
+        if( eErr != OGRERR_NONE )
         {
-            CPLDebug( "Shape", "Can not rename DBF file: %s", VSIStrerror( errno ) );
             CPLFree( panRecordsToDelete );
-            return OGRERR_FAILURE;
+            VSIUnlink( oTempFileDBF );
+            return eErr;
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Now create a shapefile matching the old one.                    */
 /* -------------------------------------------------------------------- */
-    int bMustReopenSHP = ( hSHP != NULL );
+    bool bMustReopenSHP = hSHP != NULL;
+    CPLString oTempFileSHP;
+    CPLString oTempFileSHX;
+
+    SHPInfo sSHPInfo;
+    memset(&sSHPInfo, 0, sizeof(sSHPInfo));
+    unsigned int *panRecOffsetNew = NULL;
+    unsigned int *panRecSizeNew = NULL;
+
+    // On Windows, use the pack-in-place approach, ie copy the content of
+    // the _packed files on top of the existing opened files. This avoids
+    // many issues with files being locked, at the expense of more I/O
+    const bool bPackInPlace =
+        CPLTestBool(CPLGetConfigOption("OGR_SHAPE_PACK_IN_PLACE",
+#ifdef WIN32
+                                        "YES"
+#else
+                                        "NO"
+#endif
+                                        ));
 
     if( hSHP != NULL )
     {
-        SHPHandle hNewSHP = NULL;
+        oTempFileSHP = CPLFormFilename(osDirname, osBasename, NULL);
+        oTempFileSHP += "_packed.shp";
+        oTempFileSHX = CPLFormFilename(osDirname, osBasename, NULL);
+        oTempFileSHX += "_packed.shx";
 
-        CPLString oTempFile = CPLFormFilename(osDirname, osBasename, NULL);
-        oTempFile += "_packed.shp";
-
-        hNewSHP = SHPCreate( oTempFile, hSHP->nShapeType );
+        SHPHandle hNewSHP = SHPCreate( oTempFileSHP, hSHP->nShapeType );
         if( hNewSHP == NULL )
         {
             CPLFree( panRecordsToDelete );
+            if( !oTempFileDBF.empty() )
+                VSIUnlink( oTempFileDBF );
             return OGRERR_FAILURE;
         }
 
@@ -2527,67 +2628,261 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
         int iNextDeletedShape = 0;
 
-        for( iShape = 0;
+        for( int iShape = 0;
              iShape < nTotalShapeCount && eErr == OGRERR_NONE;
              iShape++ )
         {
             if( panRecordsToDelete[iNextDeletedShape] == iShape )
+            {
                 iNextDeletedShape++;
+            }
             else
             {
-                SHPObject *hObject;
-
-                hObject = SHPReadObject( hSHP, iShape );
-                if( hObject == NULL )
-                    eErr = OGRERR_FAILURE;
-                else if( SHPWriteObject( hNewSHP, -1, hObject ) == -1 )
+                SHPObject *hObject = SHPReadObject( hSHP, iShape );
+                if( hObject == NULL ||
+                    SHPWriteObject( hNewSHP, -1, hObject ) == -1 )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Error writing record %d in .shp", iShape);
                     eErr = OGRERR_FAILURE;
+                }
 
                 if( hObject )
                     SHPDestroyObject( hObject );
             }
         }
 
+        if( bPackInPlace )
+        {
+            // Backup information of the updated shape context so as to
+            // restore it later in the current shape context
+            memcpy(&sSHPInfo, hNewSHP, sizeof(sSHPInfo));
+
+            // Use malloc like shapelib does
+            panRecOffsetNew = reinterpret_cast<unsigned int*>(
+                malloc(sizeof(unsigned int) * hNewSHP->nMaxRecords));
+            panRecSizeNew = reinterpret_cast<unsigned int*>(
+                malloc(sizeof(unsigned int) * hNewSHP->nMaxRecords));
+            if( panRecOffsetNew == NULL || panRecSizeNew == NULL )
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory,
+                         "Cannot allocate panRecOffsetNew/panRecSizeNew");
+                eErr = OGRERR_FAILURE;
+            }
+            else
+            {
+                memcpy(panRecOffsetNew, hNewSHP->panRecOffset,
+                       sizeof(unsigned int) * hNewSHP->nRecords);
+                memcpy(panRecSizeNew, hNewSHP->panRecSize,
+                       sizeof(unsigned int) * hNewSHP->nRecords);
+            }
+        }
+
+        SHPClose( hNewSHP );
+
         if( eErr != OGRERR_NONE )
         {
             CPLFree( panRecordsToDelete );
-            VSIUnlink( CPLResetExtension( oTempFile, "shp" ) );
-            VSIUnlink( CPLResetExtension( oTempFile, "shx" ) );
-            SHPClose( hNewSHP );
+            VSIUnlink( oTempFileSHP );
+            VSIUnlink( oTempFileSHX );
+            if( !oTempFileDBF.empty() )
+                VSIUnlink( oTempFileDBF );
+            free(panRecOffsetNew);
+            free(panRecSizeNew);
             return eErr;
         }
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup the old .shp/.shx and rename the new one.               */
-/* -------------------------------------------------------------------- */
-        SHPClose( hSHP );
-        SHPClose( hNewSHP );
-        hSHP = hNewSHP = NULL;
+    CPLFree( panRecordsToDelete );
+    panRecordsToDelete = NULL;
 
-        VSIUnlink( osSHPName );
-        VSIUnlink( osSHXName );
+    // We could also use pack in place for Unix but this involves extra I/O
+    // w.r.t to the delete and rename approach
 
-        oTempFile = CPLResetExtension( oTempFile, "shp" );
-        if( VSIRename( oTempFile, osSHPName ) != 0 )
+    if( bPackInPlace )
+    {
+        if( hDBF != NULL && !oTempFileDBF.empty() )
         {
-            CPLDebug( "Shape", "Can not rename SHP file: %s",
-                      VSIStrerror( errno ) );
-            CPLFree( panRecordsToDelete );
-            return OGRERR_FAILURE;
+            if( !CopyInPlace( VSI_SHP_GetVSIL(hDBF->fp), oTempFileDBF ) )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, 
+                        "An error occured while copying the content of %s on top of %s. "
+                        "The non corrupted version is in the _packed.dbf, "
+                        "_packed.shp and _packed.shx files that you should rename "
+                        "on top of the main ones.",
+                        oTempFileDBF.c_str(),
+                        VSI_SHP_GetFilename( hDBF->fp ) );
+                free(panRecOffsetNew);
+                free(panRecSizeNew);
+
+                DBFClose( hDBF );
+                hDBF = NULL;
+                if( hSHP != NULL )
+                {
+                    SHPClose( hSHP );
+                    hSHP = NULL;
+                }
+
+                return OGRERR_FAILURE;
+            }
+
+            // Refresh current handle
+            hDBF->nRecords = nNewRecords;
         }
 
-        oTempFile = CPLResetExtension( oTempFile, "shx" );
-        if( VSIRename( oTempFile, osSHXName ) != 0 )
+        if( hSHP != NULL && !oTempFileSHP.empty() )
         {
-            CPLDebug( "Shape", "Can not rename SHX file: %s",
-                      VSIStrerror( errno ) );
-            CPLFree( panRecordsToDelete );
-            return OGRERR_FAILURE;
+            if( !CopyInPlace( VSI_SHP_GetVSIL(hSHP->fpSHP), oTempFileSHP ) )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, 
+                        "An error occured while copying the content of %s on top of %s. "
+                        "The non corrupted version is in the _packed.dbf, "
+                        "_packed.shp and _packed.shx files that you should rename "
+                        "on top of the main ones.",
+                        oTempFileSHP.c_str(),
+                        VSI_SHP_GetFilename( hSHP->fpSHP ) );
+                free(panRecOffsetNew);
+                free(panRecSizeNew);
+
+                if( hDBF != NULL )
+                {
+                    DBFClose( hDBF );
+                    hDBF = NULL;
+                }
+                SHPClose( hSHP );
+                hSHP = NULL;
+
+                return OGRERR_FAILURE;
+            }
+            if( !CopyInPlace( VSI_SHP_GetVSIL(hSHP->fpSHX), oTempFileSHX ) )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, 
+                        "An error occured while copying the content of %s on top of %s. "
+                        "The non corrupted version is in the _packed.dbf, "
+                        "_packed.shp and _packed.shx files that you should rename "
+                        "on top of the main ones.",
+                        oTempFileSHX.c_str(),
+                        VSI_SHP_GetFilename( hSHP->fpSHX ) );
+                free(panRecOffsetNew);
+                free(panRecSizeNew);
+
+                if( hDBF != NULL )
+                {
+                    DBFClose( hDBF );
+                    hDBF = NULL;
+                }
+                SHPClose( hSHP );
+                hSHP = NULL;
+
+                return OGRERR_FAILURE;
+            }
+
+            // Refresh current handle
+            hSHP->nRecords = sSHPInfo.nRecords;
+            hSHP->nMaxRecords = sSHPInfo.nMaxRecords;
+            hSHP->nFileSize = sSHPInfo.nFileSize;
+            CPLAssert(sizeof(sSHPInfo.adBoundsMin) == 4 * sizeof(double));
+            memcpy(hSHP->adBoundsMin, sSHPInfo.adBoundsMin,
+                   sizeof(sSHPInfo.adBoundsMin));
+            memcpy(hSHP->adBoundsMax, sSHPInfo.adBoundsMax,
+                   sizeof(sSHPInfo.adBoundsMax));
+            free(hSHP->panRecOffset);
+            free(hSHP->panRecSize);
+            hSHP->panRecOffset = panRecOffsetNew;
+            hSHP->panRecSize = panRecSizeNew;
+        }
+        else
+        {
+            // The free() are not really necessary but CSA doesn't realize it
+            free(panRecOffsetNew);
+            free(panRecSizeNew);
+        }
+
+        // Now that everything is successful, we can delete the temp files
+        if( !oTempFileDBF.empty() )
+        {
+            ForceDeleteFile( oTempFileDBF );
+        }
+        if( !oTempFileSHP.empty() )
+        {
+            ForceDeleteFile( oTempFileSHP );
+            ForceDeleteFile( oTempFileSHX );
         }
     }
+    else
+    {
+/* -------------------------------------------------------------------- */
+/*      Cleanup the old .dbf, .shp, .shx and rename the new ones.       */
+/* -------------------------------------------------------------------- */
+        if( !oTempFileDBF.empty() )
+        {
+            DBFClose( hDBF );
+            hDBF = NULL;
 
-    CPLFree( panRecordsToDelete );
-    panRecordsToDelete = NULL;
+            if( VSIUnlink( osDBFName ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, 
+                        "Failed to delete old DBF file: %s",
+                        VSIStrerror( errno ) );
+
+                hDBF = poDS->DS_DBFOpen( osDBFName, bUpdateAccess ? "r+" : "r" );
+
+                VSIUnlink( oTempFileDBF );
+
+                return OGRERR_FAILURE;
+            }
+
+            if( VSIRename( oTempFileDBF, osDBFName ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, 
+                        "Can not rename new DBF file: %s",
+                        VSIStrerror( errno ) );
+                return OGRERR_FAILURE;
+            }
+
+            CheckFileDeletion ( oTempFileDBF );
+        }
+
+        if( !oTempFileSHP.empty() )
+        {
+            SHPClose( hSHP );
+            hSHP = NULL;
+
+            if( VSIUnlink( osSHPName ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "Can not delete old SHP file: %s",
+                        VSIStrerror( errno ) );
+                return OGRERR_FAILURE;
+            }
+
+            if( VSIUnlink( osSHXName ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "Can not delete old SHX file: %s",
+                        VSIStrerror( errno ) );
+                return OGRERR_FAILURE;
+            }
+
+            if( VSIRename( oTempFileSHP, osSHPName ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "Can not rename new SHP file: %s",
+                        VSIStrerror( errno ) );
+                return OGRERR_FAILURE;
+            }
+
+            if( VSIRename( oTempFileSHX, osSHXName ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "Can not rename new SHX file: %s",
+                        VSIStrerror( errno ) );
+                return OGRERR_FAILURE;
+            }
+
+            CheckFileDeletion( oTempFileSHP );
+            CheckFileDeletion( oTempFileSHX );
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Reopen the shapefile                                            */
@@ -2598,19 +2893,16 @@ OGRErr OGRShapeLayer::Repack()
 /* in the right place and accessible.                                   */
 /* -------------------------------------------------------------------- */
 
-    const char* pszAccess = NULL;
-    if( bUpdateAccess )
-        pszAccess = "r+";
-    else
-        pszAccess = "r";
+        const char * const pszAccess = bUpdateAccess ? "r+" :  "r";
 
-    if( bMustReopenSHP )
-        hSHP = poDS->DS_SHPOpen ( osSHPName , pszAccess );
-    if( bMustReopenDBF )
-        hDBF = poDS->DS_DBFOpen ( osDBFName , pszAccess );
+        if( bMustReopenSHP )
+            hSHP = poDS->DS_SHPOpen ( osSHPName , pszAccess );
+        if( bMustReopenDBF )
+            hDBF = poDS->DS_DBFOpen ( osDBFName , pszAccess );
 
-    if( (bMustReopenSHP && NULL == hSHP) || (bMustReopenDBF && NULL == hDBF) )
-        return OGRERR_FAILURE;
+        if( (bMustReopenSHP && NULL == hSHP) || (bMustReopenDBF && NULL == hDBF) )
+            return OGRERR_FAILURE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Update total shape count.                                       */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 09946a0..29be14c 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitedatasource.cpp 33821 2016-03-31 12:34:40Z rouault $
+ * $Id: ogrsqlitedatasource.cpp 35568 2016-09-30 19:38:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDataSource class.
@@ -51,7 +51,7 @@
 static int bSpatialiteGlobalLoaded = FALSE;
 #endif
 
-CPL_CVSID("$Id: ogrsqlitedatasource.cpp 33821 2016-03-31 12:34:40Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedatasource.cpp 35568 2016-09-30 19:38:55Z rouault $");
 
 /************************************************************************/
 /*                      OGRSQLiteInitOldSpatialite()                    */
@@ -2016,7 +2016,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
     poLayer = new OGRSQLiteSelectLayer( this, osSQL, hSQLStmt,
                                         bUseStatementForGetNextFeature, bEmptyLayer, TRUE );
 
-    if( poSpatialFilter != NULL )
+    if( poSpatialFilter != NULL && poLayer->GetLayerDefn()->GetGeomFieldCount() > 0 )
         poLayer->SetSpatialFilter( 0, poSpatialFilter );
 
     return poLayer;
@@ -2061,6 +2061,20 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
         return NULL;
     }
 
+    if ( bIsSpatiaLiteDB && eType != wkbNone )
+    {
+        // We need to catch this right now as AddGeometryColumn does not
+        // return an error
+        OGRwkbGeometryType eFType = wkbFlatten(eType);
+        if( eFType > wkbGeometryCollection )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "Cannot create geometry field of type %s",
+                    OGRToOGCGeomType(eType));
+            return NULL;
+        }
+    }
+
     for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( papoLayers[iLayer]->IsTableLayer() )
@@ -2689,7 +2703,6 @@ OGRErr OGRSQLiteBaseDataSource::DoTransactionCommand(const char* pszCommand)
     rc = sqlite3_exec( hDB, pszCommand, NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        nSoftTransactionLevel--;
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s transaction failed: %s",
                   pszCommand, pszErrMsg );
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index 8eadd09..ce65689 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitetablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsqlitetablelayer.cpp 35500 2016-09-23 14:10:22Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
@@ -37,7 +37,7 @@
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 35500 2016-09-23 14:10:22Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteTableLayer()                         */
@@ -1446,6 +1446,19 @@ OGRErr OGRSQLiteTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
                  "Cannot create geometry field of type wkbNone");
         return OGRERR_FAILURE;
     }
+    if ( poDS->IsSpatialiteDB() )
+    {
+        // We need to catch this right now as AddGeometryColumn does not
+        // return an error
+        OGRwkbGeometryType eFType = wkbFlatten(eType);
+        if( eFType > wkbGeometryCollection )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                    "Cannot create geometry field of type %s",
+                    OGRToOGCGeomType(eType));
+            return OGRERR_FAILURE;
+        }
+    }
 
     OGRSQLiteGeomFieldDefn *poGeomField =
         new OGRSQLiteGeomFieldDefn( poGeomFieldIn->GetNameRef(), -1 );
@@ -3374,7 +3387,8 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 poFeatureDefn->myGetGeomFieldDefn(i);
-            RunAddGeometryColumn(poGeomFieldDefn, FALSE);
+            if( RunAddGeometryColumn(poGeomFieldDefn, FALSE) != OGRERR_NONE )
+                return OGRERR_FAILURE;
         }
     }
 
diff --git a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
index ef6a3ce..d3c5885 100644
--- a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
+++ b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xlsx.h 32062 2015-12-07 11:02:56Z rouault $
+ * $Id: ogr_xlsx.h 35710 2016-10-13 07:21:17Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .xlsx driver.
@@ -51,14 +51,14 @@ class OGRXLSXLayer : public OGRMemLayer
 {
     int                bInit;
     OGRXLSXDataSource* poDS;
-    int                nSheetId;
+    CPLString          osFilename;
     void               Init();
     int                bUpdated;
     int                bHasHeaderLine;
 
     public:
         OGRXLSXLayer( OGRXLSXDataSource* poDSIn,
-                      int nSheetIdIn,
+                      const char * pszFilename,
                       const char * pszName,
                       int bUpdateIn = FALSE);
 
@@ -75,6 +75,8 @@ class OGRXLSXLayer : public OGRMemLayer
     void                ResetReading()
     { Init(); OGRMemLayer::ResetReading(); }
 
+    const CPLString&    GetFilename() const { return osFilename; }
+
     /* For external usage. Mess with FID */
     virtual OGRFeature *        GetNextFeature();
     virtual OGRFeature         *GetFeature( GIntBig nFeatureId );
@@ -157,9 +159,11 @@ class OGRXLSXDataSource : public OGRDataSource
 
     int                 nLayers;
     OGRLayer          **papoLayers;
+    std::map<CPLString, CPLString> oMapRelsIdToTarget;
 
     void                AnalyseSharedStrings(VSILFILE* fpSharedStrings);
     void                AnalyseWorkbook(VSILFILE* fpWorkbook);
+    void                AnalyseWorkbookRels(VSILFILE* fpWorkbookRels);
     void                AnalyseStyles(VSILFILE* fpStyles);
 
     std::vector<std::string>  apoSharedStrings;
@@ -216,6 +220,7 @@ class OGRXLSXDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename,
                               VSILFILE* fpWorkbook,
+                              VSILFILE* fpWorkbookRels,
                               VSILFILE* fpSharedStrings,
                               VSILFILE* fpStyles,
                               int bUpdate );
@@ -244,12 +249,14 @@ class OGRXLSXDataSource : public OGRDataSource
     void                endElementSSCbk(const char *pszName);
     void                dataHandlerSSCbk(const char *data, int nLen);
 
+    void                startElementWBRelsCbk(const char *pszName, const char **ppszAttr);
+
     void                startElementWBCbk(const char *pszName, const char **ppszAttr);
 
     void                startElementStylesCbk(const char *pszName, const char **ppszAttr);
     void                endElementStylesCbk(const char *pszName);
 
-    void                BuildLayer(OGRXLSXLayer* poLayer, int nSheetId);
+    void                BuildLayer(OGRXLSXLayer* poLayer);
 
     int                 GetUpdatable() { return bUpdatable; }
     void                SetUpdated() { bUpdated = TRUE; }
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
index 65ad997..ee6ee7c 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsxdatasource.cpp 33437 2016-02-12 11:02:55Z rouault $
+ * $Id: ogrxlsxdatasource.cpp 35710 2016-10-13 07:21:17Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDataSource class
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: ogrxlsxdatasource.cpp 33437 2016-02-12 11:02:55Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdatasource.cpp 35710 2016-10-13 07:21:17Z rouault $");
 
 namespace OGRXLSX {
 
@@ -41,13 +41,13 @@ namespace OGRXLSX {
 /************************************************************************/
 
 OGRXLSXLayer::OGRXLSXLayer( OGRXLSXDataSource* poDSIn,
-                            int nSheetIdIn,
+                            const char * pszFilename,
                             const char * pszName,
                             int bUpdatedIn) :
                                 OGRMemLayer(pszName, NULL, wkbNone)
 {
     bInit = FALSE;
-    nSheetId = nSheetIdIn;
+    osFilename = pszFilename;
     poDS = poDSIn;
     bUpdated = bUpdatedIn;
     bHasHeaderLine = FALSE;
@@ -63,7 +63,7 @@ void OGRXLSXLayer::Init()
     {
         bInit = TRUE;
         CPLDebug("XLSX", "Init(%s)", GetName());
-        poDS->BuildLayer(this, nSheetId);
+        poDS->BuildLayer(this);
     }
 }
 
@@ -244,6 +244,7 @@ int OGRXLSXDataSource::GetLayerCount()
 
 int OGRXLSXDataSource::Open( const char * pszFilename,
                              VSILFILE* fpWorkbook,
+                             VSILFILE* fpWorkbookRels,
                              VSILFILE* fpSharedStrings,
                              VSILFILE* fpStyles,
                              int bUpdateIn )
@@ -253,6 +254,7 @@ int OGRXLSXDataSource::Open( const char * pszFilename,
 
     pszName = CPLStrdup( pszFilename );
 
+    AnalyseWorkbookRels(fpWorkbookRels);
     AnalyseWorkbook(fpWorkbook);
     AnalyseSharedStrings(fpSharedStrings);
     AnalyseStyles(fpStyles);
@@ -943,13 +945,11 @@ void OGRXLSXDataSource::dataHandlerTextV(const char *data, int nLen)
 /*                              BuildLayer()                            */
 /************************************************************************/
 
-void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer, int nSheetId)
+void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
 {
     poCurLayer = poLayer;
 
-    CPLString osSheetFilename(
-        CPLSPrintf("/vsizip/%s/xl/worksheets/sheet%d.xml", pszName, nSheetId));
-    const char* pszSheetFilename = osSheetFilename.c_str();
+    const char* pszSheetFilename = poLayer->GetFilename().c_str();
     VSILFILE* fp = VSIFOpenL(pszSheetFilename, "rb");
     if (fp == NULL)
         return;
@@ -1168,6 +1168,85 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
 
 
 /************************************************************************/
+/*                        startElementWBRelsCbk()                       */
+/************************************************************************/
+
+static void XMLCALL startElementWBRelsCbk(void *pUserData, const char *pszNameIn,
+                                    const char **ppszAttr)
+{
+    ((OGRXLSXDataSource*)pUserData)->startElementWBRelsCbk(pszNameIn, ppszAttr);
+}
+
+void OGRXLSXDataSource::startElementWBRelsCbk(const char *pszNameIn,
+                                       const char **ppszAttr)
+{
+    if( bStopParsing ) return;
+
+    nWithoutEventCounter = 0;
+    if (strcmp(pszNameIn,"Relationship") == 0)
+    {
+        const char* pszId = GetAttributeValue(ppszAttr, "Id", NULL);
+        const char* pszType = GetAttributeValue(ppszAttr, "Type", NULL);
+        const char* pszTarget = GetAttributeValue(ppszAttr, "Target", NULL);
+        if (pszId && pszType && pszTarget &&
+            strstr(pszType, "/worksheet") != NULL)
+        {
+            oMapRelsIdToTarget[pszId] = pszTarget;
+        }
+    }
+}
+
+/************************************************************************/
+/*                          AnalyseWorkbookRels()                       */
+/************************************************************************/
+
+void OGRXLSXDataSource::AnalyseWorkbookRels(VSILFILE* fpWorkbookRels)
+{
+    oParser = OGRCreateExpatXMLParser();
+    XML_SetElementHandler(oParser, OGRXLSX::startElementWBRelsCbk, NULL);
+    XML_SetUserData(oParser, this);
+
+    VSIFSeekL( fpWorkbookRels, 0, SEEK_SET );
+
+    bStopParsing = false;
+    nWithoutEventCounter = 0;
+    nDataHandlerCounter = 0;
+
+    char aBuf[BUFSIZ];
+    int nDone = 0;
+    do
+    {
+        nDataHandlerCounter = 0;
+        unsigned int nLen =
+            (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpWorkbookRels );
+        nDone = VSIFEofL(fpWorkbookRels);
+        if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "XML parsing of %s file failed : %s at line %d, column %d",
+                     "xl/_rels/workbook.xml.rels",
+                     XML_ErrorString(XML_GetErrorCode(oParser)),
+                     (int)XML_GetCurrentLineNumber(oParser),
+                     (int)XML_GetCurrentColumnNumber(oParser));
+            bStopParsing = true;
+        }
+        nWithoutEventCounter ++;
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 10 );
+
+    XML_ParserFree(oParser);
+    oParser = NULL;
+
+    if (nWithoutEventCounter == 10)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too much data inside one element. File probably corrupted");
+        bStopParsing = true;
+    }
+
+    VSIFCloseL(fpWorkbookRels);
+}
+
+/************************************************************************/
 /*                          startElementWBCbk()                         */
 /************************************************************************/
 
@@ -1186,13 +1265,14 @@ void OGRXLSXDataSource::startElementWBCbk(const char *pszNameIn,
     if (strcmp(pszNameIn,"sheet") == 0)
     {
         const char* pszSheetName = GetAttributeValue(ppszAttr, "name", NULL);
-        /*const char* pszSheetId = GetAttributeValue(ppszAttr, "sheetId", NULL);*/
-        if (pszSheetName /*&& pszSheetId*/)
+        const char* pszId = GetAttributeValue(ppszAttr, "r:id", NULL);
+        if (pszSheetName && pszId &&
+            oMapRelsIdToTarget.find(pszId) != oMapRelsIdToTarget.end() )
         {
-            /*int nSheetId = atoi(pszSheetId);*/
-            int nSheetId = nLayers + 1;
             papoLayers = (OGRLayer**)CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
-            papoLayers[nLayers++] = new OGRXLSXLayer(this, nSheetId, pszSheetName);
+            papoLayers[nLayers++] = new OGRXLSXLayer(this,
+                CPLSPrintf("/vsizip/%s/xl/%s", pszName, oMapRelsIdToTarget[pszId].c_str()),
+                pszSheetName);
         }
     }
 }
@@ -1449,7 +1529,9 @@ OGRXLSXDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRLayer* poLayer = new OGRXLSXLayer(this, nLayers + 1, pszLayerName, TRUE);
+    OGRLayer* poLayer = new OGRXLSXLayer(this,
+        CPLSPrintf("/vsizip/%s/xl/worksheets/sheet%d.xml", pszName, nLayers + 1),
+        pszLayerName, TRUE);
 
     papoLayers = (OGRLayer**)CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
     papoLayers[nLayers] = poLayer;
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
index 1cda336..a5eed58 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrxlsxdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
+ * $Id: ogrxlsxdriver.cpp 35710 2016-10-13 07:21:17Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDriver.
@@ -30,7 +30,7 @@
 #include "ogr_xlsx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsxdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrxlsxdriver.cpp 35710 2016-10-13 07:21:17Z rouault $");
 
 extern "C" void RegisterOGRXLSX();
 
@@ -102,12 +102,19 @@ OGRDataSource *OGRXLSXDriver::Open( const char * pszFilename, int bUpdate )
     if (fpWorkbook == NULL)
         return NULL;
 
+    VSILFILE* fpWorkbookRels = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/_rels/workbook.xml.rels", pszFilename), "rb");
+    if (fpWorkbookRels == NULL)
+    {
+        VSIFCloseL(fpWorkbook);
+        return NULL;
+    }
+
     VSILFILE* fpSharedStrings = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/sharedStrings.xml", pszFilename), "rb");
     VSILFILE* fpStyles = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/styles.xml", pszFilename), "rb");
 
     OGRXLSXDataSource   *poDS = new OGRXLSXDataSource();
 
-    if( !poDS->Open( pszFilename, fpWorkbook, fpSharedStrings, fpStyles, bUpdate ) )
+    if( !poDS->Open( pszFilename, fpWorkbook, fpWorkbookRels, fpSharedStrings, fpStyles, bUpdate ) )
     {
         delete poDS;
         poDS = NULL;
diff --git a/port/cpl_vsil_curl.cpp b/port/cpl_vsil_curl.cpp
index a77ecf6..cc86618 100644
--- a/port/cpl_vsil_curl.cpp
+++ b/port/cpl_vsil_curl.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl.cpp 33886 2016-04-04 07:46:37Z rouault $
+ * $Id: cpl_vsil_curl.cpp 35717 2016-10-13 18:59:41Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files
@@ -36,7 +36,7 @@
 #include "cpl_aws.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl.cpp 33886 2016-04-04 07:46:37Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl.cpp 35717 2016-10-13 18:59:41Z rouault $");
 
 #ifndef HAVE_CURL
 
@@ -730,58 +730,6 @@ vsi_l_offset VSICurlHandle::GetFileSize(bool bSetError)
 
     bHasComputedFileSize = true;
 
-    /* Consider that only the files whose extension ends up with one that is */
-    /* listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server */
-    /* This can speeds up dramatically open experience, in case the server */
-    /* cannot return a file list */
-    /* {noext} can be used as a special token to mean file with no extension */
-    /* For example : */
-    /* gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif */
-    const char* pszAllowedExtensions =
-        CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", NULL);
-    if (pszAllowedExtensions)
-    {
-        char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
-        const size_t nURLLen = strlen(pszURL);
-        bool bFound = false;
-        for(int i=0;papszExtensions[i] != NULL;i++)
-        {
-            const size_t nExtensionLen = strlen(papszExtensions[i]);
-            if( EQUAL(papszExtensions[i], "{noext}") )
-            {
-                const char* pszLastSlash = strrchr(pszURL, '/');
-                if( pszLastSlash != NULL && strchr(pszLastSlash, '.') == NULL )
-                {
-                    bFound = true;
-                    break;
-                }
-            }
-            else if (nURLLen > nExtensionLen &&
-                EQUAL(pszURL + nURLLen - nExtensionLen, papszExtensions[i]))
-            {
-                bFound = true;
-                break;
-            }
-        }
-
-        if (!bFound)
-        {
-            eExists = EXIST_NO;
-            fileSize = 0;
-
-            CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-            cachedFileProp->bHasComputedFileSize = true;
-            cachedFileProp->fileSize = fileSize;
-            cachedFileProp->eExists = eExists;
-
-            CSLDestroy(papszExtensions);
-
-            return 0;
-        }
-
-        CSLDestroy(papszExtensions);
-    }
-
 #if LIBCURL_VERSION_NUM < 0x070B00
     /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
     /* previously set, so we have to reinit the connection handle */
@@ -2110,6 +2058,53 @@ VSICurlHandle* VSICurlFilesystemHandler::CreateFileHandle(const char* pszURL)
 }
 
 /************************************************************************/
+/*                        IsAllowedExtension()                          */
+/************************************************************************/
+
+static bool IsAllowedExtension( const char* pszFilename )
+{
+    /* Consider that only the files whose extension ends up with one that is */
+    /* listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server */
+    /* This can speeds up dramatically open experience, in case the server */
+    /* cannot return a file list */
+    /* {noext} can be used as a special token to mean file with no extension */
+    /* For example : */
+    /* gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif */
+    const char* pszAllowedExtensions =
+        CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", NULL);
+    if (pszAllowedExtensions)
+    {
+        char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
+        const size_t nURLLen = strlen(pszFilename);
+        bool bFound = false;
+        for(int i=0;papszExtensions[i] != NULL;i++)
+        {
+            const size_t nExtensionLen = strlen(papszExtensions[i]);
+            if( EQUAL(papszExtensions[i], "{noext}") )
+            {
+                const char* pszLastSlash = strrchr(pszFilename, '/');
+                if( pszLastSlash != NULL && strchr(pszLastSlash, '.') == NULL )
+                {
+                    bFound = true;
+                    break;
+                }
+            }
+            else if (nURLLen > nExtensionLen &&
+                EQUAL(pszFilename + nURLLen - nExtensionLen, papszExtensions[i]))
+            {
+                bFound = true;
+                break;
+            }
+        }
+
+        CSLDestroy(papszExtensions);
+
+        return bFound;
+    }
+    return TRUE;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -2124,6 +2119,8 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
                  "Only read-only mode is supported for /vsicurl");
         return NULL;
     }
+    if( !IsAllowedExtension( pszFilename ) )
+        return NULL;
 
     const char* pszOptionVal =
         CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
@@ -3014,6 +3011,9 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
+    if( !IsAllowedExtension( pszFilename ) )
+        return -1;
+
     const char* pszOptionVal =
         CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
     const bool bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
diff --git a/port/cpl_worker_thread_pool.cpp b/port/cpl_worker_thread_pool.cpp
index e9ecc17..e4a949a 100644
--- a/port/cpl_worker_thread_pool.cpp
+++ b/port/cpl_worker_thread_pool.cpp
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_worker_thread_pool.cpp 32171 2015-12-13 20:39:43Z goatbar $
+ * $Id: cpl_worker_thread_pool.cpp 35363 2016-09-08 07:35:28Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL worker thread pool
@@ -65,7 +65,9 @@ CPLWorkerThreadPool::~CPLWorkerThreadPool()
     {
         WaitCompletion();
 
+        CPLAcquireMutex(hMutex, 1000.0);
         eState = CPLWTS_STOP;
+        CPLReleaseMutex(hMutex);
 
         for(size_t i=0;i<aWT.size();i++)
         {
diff --git a/port/cplgetsymbol.cpp b/port/cplgetsymbol.cpp
index f30efac..a8f2c4b 100644
--- a/port/cplgetsymbol.cpp
+++ b/port/cplgetsymbol.cpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplgetsymbol.cpp 33646 2016-03-05 15:54:03Z goatbar $
+ * $Id: cplgetsymbol.cpp 35433 2016-09-14 07:44:24Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Fetch a function pointer from a shared library / DLL.
@@ -29,8 +29,9 @@
  ****************************************************************************/
 
 #include "cpl_conv.h"
+#include "cpl_string.h"
 
-CPL_CVSID("$Id: cplgetsymbol.cpp 33646 2016-03-05 15:54:03Z goatbar $");
+CPL_CVSID("$Id: cplgetsymbol.cpp 35433 2016-09-14 07:44:24Z rouault $");
 
 
 /* ==================================================================== */
@@ -148,7 +149,19 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
     /* Avoid error boxes to pop up (#5211, #5525) */
     uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
 
-    pLibrary = LoadLibrary(pszLibrary);
+#if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    {
+        wchar_t *pwszFilename =
+            CPLRecodeToWChar( pszLibrary, CPL_ENC_UTF8, CPL_ENC_UCS2 );
+        pLibrary = LoadLibraryW(pwszFilename);
+        CPLFree( pwszFilename );
+    }
+    else
+#endif
+    {
+        pLibrary = LoadLibrary(pszLibrary);
+    }
 
     if( pLibrary <= (void*)HINSTANCE_ERROR )
     {
diff --git a/scripts/gdal-bash-completion.sh b/scripts/gdal-bash-completion.sh
index c93e661..3b9e01a 100644
--- a/scripts/gdal-bash-completion.sh
+++ b/scripts/gdal-bash-completion.sh
@@ -459,7 +459,7 @@ _gdal_retile.py()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="-v -q -co -of -ps -ot -tileIndex -tileIndexField -csv -csvDelim -s_srs -pyramidOnly -levels -r -useDirForEachRow -multi -targetDir "
+      key_list="-v -q -co -of -ps -ot -tileIndex -tileIndexField -csv -csvDelim -s_srs -pyramidOnly -levels -r -useDirForEachRow -targetDir "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index 5f46db5..4d026e9 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -140,8 +140,8 @@ use Geo::OSR;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0101';
-our $GDAL_VERSION = '2.1.1';
+our $VERSION = '2.0102';
+our $GDAL_VERSION = '2.1.2';
 
 =pod
 
diff --git a/swig/include/perl/ogr_perl.i b/swig/include/perl/ogr_perl.i
index 3b360e2..a65acbc 100644
--- a/swig/include/perl/ogr_perl.i
+++ b/swig/include/perl/ogr_perl.i
@@ -120,7 +120,7 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 %perlcode %{
 
 package Geo::OGR;
-our $VERSION = '2.0101'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0102'; # this needs to be the same as that in gdal_perl.i
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index 31248c0..f71e845 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -1003,8 +1003,8 @@ use Geo::OSR;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0101';
-our $GDAL_VERSION = '2.1.1';
+our $VERSION = '2.0102';
+our $GDAL_VERSION = '2.1.2';
 
 =pod
 
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
index a286c88..3618973 100644
--- a/swig/perl/lib/Geo/OGR.pm
+++ b/swig/perl/lib/Geo/OGR.pm
@@ -893,7 +893,7 @@ package Geo::OGR;
 
 
 package Geo::OGR;
-our $VERSION = '2.0101'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0102'; # this needs to be the same as that in gdal_perl.i
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
diff --git a/swig/python/scripts/gdal2xyz.py b/swig/python/scripts/gdal2xyz.py
index 576fb01..d271376 100755
--- a/swig/python/scripts/gdal2xyz.py
+++ b/swig/python/scripts/gdal2xyz.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal2xyz.py 33790 2016-03-26 12:42:12Z goatbar $
+# $Id: gdal2xyz.py 35367 2016-09-08 09:30:10Z rouault $
 #
 # Project:  GDAL
 # Purpose:  Script to translate GDAL supported raster into XYZ ASCII
@@ -129,7 +129,11 @@ if __name__ == '__main__':
     else:
         dst_fh = sys.stdout
 
-    band_format = (("%g" + delim) * len(bands)).rstrip(delim) + '\n'
+    dt = srcds.GetRasterBand(1).DataType
+    if dt == gdal.GDT_Int32 or dt == gdal.GDT_UInt32:
+        band_format = (("%d" + delim) * len(bands)).rstrip(delim) + '\n'
+    else:
+        band_format = (("%g" + delim) * len(bands)).rstrip(delim) + '\n'
 
     # Setup an appropriate print format.
     if abs(gt[0]) < 180 and abs(gt[3]) < 180 \
diff --git a/swig/python/setup.py b/swig/python/setup.py
index 6a4232d..e072cd1 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -7,7 +7,7 @@
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '2.1.1'
+gdal_version = '2.1.2'
 
 import sys
 import os

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



More information about the Pkg-grass-devel mailing list