LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitetablelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 932 766 82.2 %
Date: 2013-03-30 Functions: 46 42 91.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqlitetablelayer.cpp 25394 2012-12-29 22:01:36Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_conv.h"
      31                 : #include "cpl_string.h"
      32                 : #include "ogr_sqlite.h"
      33                 : #include "ogr_p.h"
      34                 : #include "cpl_time.h"
      35                 : #include <string>
      36                 : 
      37                 : #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
      38                 : 
      39                 : CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 25394 2012-12-29 22:01:36Z rouault $");
      40                 : 
      41                 : /************************************************************************/
      42                 : /*                        OGRSQLiteTableLayer()                         */
      43                 : /************************************************************************/
      44                 : 
      45             737 : OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
      46                 : 
      47                 : {
      48             737 :     poDS = poDSIn;
      49                 : 
      50             737 :     bLaunderColumnNames = TRUE;
      51                 : 
      52                 :     /* SpatiaLite v.2.4.0 (or any subsequent) is required
      53                 :        to support 2.5D: if an obsolete version of the library
      54                 :        is found we'll unconditionally activate 2D casting mode.
      55                 :     */
      56             737 :     bSpatialite2D = OGRSQLiteGetSpatialiteVersionNumber() < 24;
      57                 : 
      58             737 :     iNextShapeId = 0;
      59                 : 
      60             737 :     poFeatureDefn = NULL;
      61             737 :     pszTableName = NULL;
      62             737 :     pszEscapedTableName = NULL;
      63                 : 
      64             737 :     bHasCheckedSpatialIndexTable = FALSE;
      65             737 :     bDeferedSpatialIndexCreation = FALSE;
      66                 : 
      67             737 :     hInsertStmt = NULL;
      68                 : 
      69             737 :     eGeomType = wkbUnknown;
      70             737 :     bLayerDefnError = FALSE;
      71                 : 
      72             737 :     bStatisticsNeedsToBeFlushed = FALSE;
      73             737 :     bCachedExtentIsValid = FALSE;
      74             737 :     nFeatureCount = -1;
      75             737 : }
      76                 : 
      77                 : /************************************************************************/
      78                 : /*                        ~OGRSQLiteTableLayer()                        */
      79                 : /************************************************************************/
      80                 : 
      81             737 : OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
      82                 : 
      83                 : {
      84             737 :     ClearStatement();
      85             737 :     ClearInsertStmt();
      86                 : 
      87             737 :     CPLFree(pszTableName);
      88             737 :     CPLFree(pszEscapedTableName);
      89             737 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                     CreateSpatialIndexIfNecessary()                  */
      93                 : /************************************************************************/
      94                 : 
      95             631 : void OGRSQLiteTableLayer::CreateSpatialIndexIfNecessary()
      96                 : {
      97             631 :     if( bDeferedSpatialIndexCreation )
      98                 :     {
      99              70 :         CreateSpatialIndex();
     100                 :     }
     101             631 : }
     102                 : 
     103                 : /************************************************************************/
     104                 : /*                          ClearInsertStmt()                           */
     105                 : /************************************************************************/
     106                 : 
     107            1078 : void OGRSQLiteTableLayer::ClearInsertStmt()
     108                 : {
     109            1078 :     if( hInsertStmt != NULL )
     110                 :     {
     111             241 :         sqlite3_finalize( hInsertStmt );
     112             241 :         hInsertStmt = NULL;
     113                 :     }
     114            1078 :     osLastInsertStmt = "";
     115            1078 : }
     116                 : 
     117                 : /************************************************************************/
     118                 : /*                             Initialize()                             */
     119                 : /************************************************************************/
     120                 : 
     121             737 : CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName, 
     122                 :                                         const char *pszGeomCol,
     123                 :                                         int bMustIncludeGeomColName,
     124                 :                                         OGRwkbGeometryType eGeomType,
     125                 :                                         const char *pszGeomFormat,
     126                 :                                         OGRSpatialReference *poSRS,
     127                 :                                         int nSRSId,
     128                 :                                         int bHasSpatialIndex,
     129                 :                                         int bHasM, 
     130                 :                                         int bIsVirtualShapeIn )
     131                 : 
     132                 : {
     133                 :     int rc;
     134             737 :     sqlite3 *hDB = poDS->GetDB();
     135                 : 
     136             737 :     if( pszGeomCol == NULL )
     137             236 :         osGeomColumn = "";
     138                 :     else
     139             501 :         osGeomColumn = pszGeomCol;
     140                 : 
     141             737 :     if( pszGeomFormat )
     142                 :     {
     143             509 :         if ( EQUAL(pszGeomFormat, "WKT") )
     144              18 :             eGeomFormat = OSGF_WKT;
     145             491 :         else if ( EQUAL(pszGeomFormat,"WKB") )
     146             140 :             eGeomFormat = OSGF_WKB;
     147             351 :         else if ( EQUAL(pszGeomFormat,"FGF") )
     148               2 :             eGeomFormat = OSGF_FGF;
     149             349 :         else if( EQUAL(pszGeomFormat,"SpatiaLite") )
     150             349 :             eGeomFormat = OSGF_SpatiaLite;
     151                 :     }
     152                 : 
     153             737 :     CPLFree( pszFIDColumn );
     154             737 :     pszFIDColumn = NULL;
     155                 : 
     156             737 :     if( nSRSId == UNINITIALIZED_SRID )
     157             384 :         nSRSId = poDS->GetUndefinedSRID();
     158                 : 
     159             737 :     this->poSRS = poSRS;
     160             737 :     this->nSRSId = nSRSId;
     161             737 :     this->bHasSpatialIndex = bHasSpatialIndex;
     162             737 :     this->bHasM = bHasM;
     163             737 :     this->bIsVirtualShape = bIsVirtualShapeIn;
     164             737 :     this->pszTableName = CPLStrdup(pszTableName);
     165             737 :     this->eGeomType = eGeomType;
     166                 : 
     167             737 :     if( bMustIncludeGeomColName )
     168               6 :         osLayerName.Printf("%s(%s)", pszTableName, osGeomColumn.c_str());
     169                 :     else
     170             731 :         osLayerName = pszTableName;
     171                 : 
     172             737 :     pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
     173                 : 
     174             737 :     sqlite3_stmt *hColStmt = NULL;
     175                 :     const char *pszSQL;
     176                 : 
     177            1086 :     if ( eGeomFormat == OSGF_SpatiaLite &&
     178                 :          OGRSQLiteIsSpatialiteLoaded() && 
     179                 :          OGRSQLiteGetSpatialiteVersionNumber() < 24 && poDS->GetUpdate() )
     180                 :     {
     181                 :     // we need to test version required by Spatialite TRIGGERs 
     182               0 :         hColStmt = NULL;
     183                 :         pszSQL = CPLSPrintf( "SELECT sql FROM sqlite_master WHERE type = 'trigger' AND tbl_name = '%s' AND sql LIKE '%%RTreeAlign%%'",
     184               0 :             pszEscapedTableName );
     185                 : 
     186                 :         int nRowTriggerCount, nColTriggerCount;
     187                 :         char **papszTriggerResult, *pszErrMsg;
     188                 : 
     189                 :         rc = sqlite3_get_table( hDB, pszSQL, &papszTriggerResult,
     190               0 :             &nRowTriggerCount, &nColTriggerCount, &pszErrMsg );
     191               0 :         if( nRowTriggerCount >= 1 )
     192                 :         {
     193                 :         // obsolete library version not supporting new triggers
     194                 :         // enforcing ReadOnly mode
     195               0 :             CPLDebug("SQLITE", "Enforcing ReadOnly mode : obsolete library version not supporting new triggers");
     196               0 :             poDS->SetUpdate(FALSE);
     197                 :         }
     198                 : 
     199               0 :         sqlite3_free_table( papszTriggerResult );
     200                 :     }
     201                 :   
     202             737 :     if( poSRS )
     203             283 :         poSRS->Reference();
     204                 : 
     205             737 :     LoadStatistics();
     206                 : 
     207             737 :     return CE_None;
     208                 : }
     209                 : 
     210                 : /************************************************************************/
     211                 : /*                               GetName()                              */
     212                 : /************************************************************************/
     213                 : 
     214             823 : const char* OGRSQLiteTableLayer::GetName()
     215                 : {
     216             823 :     return osLayerName.c_str();
     217                 : }
     218                 : 
     219                 : /************************************************************************/
     220                 : /*                         EstablishFeatureDefn()                       */
     221                 : /************************************************************************/
     222                 : 
     223             516 : CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn()
     224                 : {
     225             516 :     sqlite3 *hDB = poDS->GetDB();
     226                 :     int rc;
     227                 :     const char *pszSQL;
     228             516 :     sqlite3_stmt *hColStmt = NULL;
     229                 : 
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Get the column definitions for this table.                      */
     232                 : /* -------------------------------------------------------------------- */
     233                 : 
     234                 :     pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
     235             516 :                                      pszEscapedTableName );
     236                 : 
     237             516 :     rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
     238             516 :     if( rc != SQLITE_OK )
     239                 :     {
     240                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     241                 :                   "Unable to query table %s for column definitions : %s.",
     242              85 :                   pszTableName, sqlite3_errmsg(hDB) );
     243                 :         
     244              85 :         return CE_Failure;
     245                 :     }
     246                 : 
     247             431 :     rc = sqlite3_step( hColStmt );
     248             431 :     if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
     249                 :     {
     250                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     251                 :                   "In Initialize(): sqlite3_step(%s):\n  %s", 
     252               0 :                   pszSQL, sqlite3_errmsg(hDB) );
     253               0 :         sqlite3_finalize( hColStmt );
     254               0 :         return CE_Failure;
     255                 :     }
     256                 : 
     257                 : /* -------------------------------------------------------------------- */
     258                 : /*      What should we use as FID?  If there is a primary key           */
     259                 : /*      integer field, then this will be used as the _rowid_, and we    */
     260                 : /*      will pick up the real column name here.  Otherwise, we will     */
     261                 : /*      just use fid.                                                   */
     262                 : /*                                                                      */
     263                 : /*      Note that the select _rowid_ will return the real column        */
     264                 : /*      name if the rowid corresponds to another primary key            */
     265                 : /*      column.                                                         */
     266                 : /* -------------------------------------------------------------------- */
     267             431 :     pszFIDColumn = CPLStrdup(OGRSQLiteParamsUnquote(sqlite3_column_name( hColStmt, 0 )));
     268                 : 
     269                 : /* -------------------------------------------------------------------- */
     270                 : /*      Collect the rest of the fields.                                 */
     271                 : /* -------------------------------------------------------------------- */
     272             431 :     BuildFeatureDefn( osLayerName, hColStmt, poDS->GetGeomColsForTable(pszTableName) );
     273             431 :     sqlite3_finalize( hColStmt );
     274                 : 
     275                 : /* -------------------------------------------------------------------- */
     276                 : /*      Set the geometry type if we know it.                            */
     277                 : /* -------------------------------------------------------------------- */
     278             431 :     if( eGeomType != wkbUnknown )
     279             206 :         poFeatureDefn->SetGeomType( eGeomType );
     280                 : 
     281             431 :     return CE_None;
     282                 : }
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                           GetLayerDefn()                             */
     286                 : /************************************************************************/
     287                 : 
     288            4039 : OGRFeatureDefn* OGRSQLiteTableLayer::GetLayerDefn()
     289                 : {
     290            4039 :     if (poFeatureDefn)
     291            3523 :         return poFeatureDefn;
     292                 : 
     293             516 :     EstablishFeatureDefn();
     294                 : 
     295             516 :     if (poFeatureDefn == NULL)
     296                 :     {
     297              85 :         bLayerDefnError = TRUE;
     298                 : 
     299              85 :         poFeatureDefn = new OGRFeatureDefn( osLayerName );
     300              85 :         poFeatureDefn->Reference();
     301                 :     }
     302                 : 
     303             516 :     return poFeatureDefn;
     304                 : }
     305                 : 
     306                 : /************************************************************************/
     307                 : /*                           ResetStatement()                           */
     308                 : /************************************************************************/
     309                 : 
     310             355 : OGRErr OGRSQLiteTableLayer::ResetStatement()
     311                 : 
     312                 : {
     313                 :     int rc;
     314             355 :     CPLString osSQL;
     315                 : 
     316             355 :     ClearStatement();
     317                 : 
     318             355 :     iNextShapeId = 0;
     319                 : 
     320                 :     osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s",
     321                 :                     pszEscapedTableName, 
     322             355 :                     osWHERE.c_str() );
     323                 : 
     324                 : 
     325                 : //#ifdef HAVE_SQLITE3_PREPARE_V2
     326                 : //    rc = sqlite3_prepare_v2( poDS->GetDB(), osSQL, osSQL.size(),
     327                 : //                  &hStmt, NULL );
     328                 : //#else
     329                 :     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
     330             355 :               &hStmt, NULL );
     331                 : //#endif
     332                 : 
     333             355 :     if( rc == SQLITE_OK )
     334                 :     {
     335             353 :   return OGRERR_NONE;
     336                 :     }
     337                 :     else
     338                 :     {
     339                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     340                 :                   "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
     341               2 :                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
     342               2 :         hStmt = NULL;
     343               2 :         return OGRERR_FAILURE;
     344               0 :     }
     345                 : }
     346                 : 
     347                 : /************************************************************************/
     348                 : /*                           GetNextFeature()                           */
     349                 : /************************************************************************/
     350                 : 
     351            1177 : OGRFeature *OGRSQLiteTableLayer::GetNextFeature()
     352                 : 
     353                 : {
     354            1177 :     if (HasLayerDefnError())
     355               1 :         return NULL;
     356                 : 
     357            1176 :     return OGRSQLiteLayer::GetNextFeature();
     358                 : }
     359                 : 
     360                 : /************************************************************************/
     361                 : /*                             GetFeature()                             */
     362                 : /************************************************************************/
     363                 : 
     364              38 : OGRFeature *OGRSQLiteTableLayer::GetFeature( long nFeatureId )
     365                 : 
     366                 : {
     367              38 :     if (HasLayerDefnError())
     368               0 :         return NULL;
     369                 : 
     370                 : /* -------------------------------------------------------------------- */
     371                 : /*      If we don't have an explicit FID column, just read through      */
     372                 : /*      the result set iteratively to find our target.                  */
     373                 : /* -------------------------------------------------------------------- */
     374              38 :     if( pszFIDColumn == NULL )
     375               0 :         return OGRSQLiteLayer::GetFeature( nFeatureId );
     376                 : 
     377                 : /* -------------------------------------------------------------------- */
     378                 : /*      Setup explicit query statement to fetch the record we want.     */
     379                 : /* -------------------------------------------------------------------- */
     380              38 :     CPLString osSQL;
     381                 :     int rc;
     382                 : 
     383              38 :     ClearStatement();
     384                 : 
     385              38 :     iNextShapeId = nFeatureId;
     386                 : 
     387                 :     osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = %ld",
     388                 :                   pszEscapedTableName, 
     389              38 :                   OGRSQLiteEscape(pszFIDColumn).c_str(), nFeatureId );
     390                 : 
     391              38 :     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
     392                 : 
     393                 :     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(), 
     394              38 :                           &hStmt, NULL );
     395              38 :     if( rc != SQLITE_OK )
     396                 :     {
     397                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     398                 :                   "In GetFeature(): sqlite3_prepare(%s):\n  %s", 
     399               0 :                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
     400                 : 
     401               0 :         return NULL;
     402                 :     }
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Get the feature if possible.                                    */
     405                 : /* -------------------------------------------------------------------- */
     406              38 :     OGRFeature *poFeature = NULL;
     407                 : 
     408              38 :     poFeature = GetNextRawFeature();
     409                 : 
     410              38 :     ResetReading();
     411                 : 
     412              38 :     return poFeature;
     413                 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                         SetAttributeFilter()                         */
     417                 : /************************************************************************/
     418                 : 
     419             137 : OGRErr OGRSQLiteTableLayer::SetAttributeFilter( const char *pszQuery )
     420                 : 
     421                 : {
     422             137 :     if( pszQuery == NULL )
     423              43 :         osQuery = "";
     424                 :     else
     425              94 :         osQuery = pszQuery;
     426                 : 
     427             137 :     BuildWhere();
     428                 : 
     429             137 :     ResetReading();
     430                 : 
     431             137 :     return OGRERR_NONE;
     432                 : }
     433                 : 
     434                 : 
     435                 : /************************************************************************/
     436                 : /*                          SetSpatialFilter()                          */
     437                 : /************************************************************************/
     438                 : 
     439              68 : void OGRSQLiteTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     440                 : 
     441                 : {
     442              68 :     if( InstallFilter( poGeomIn ) )
     443                 :     {
     444              29 :         BuildWhere();
     445                 : 
     446              29 :         ResetReading();
     447                 :     }
     448              68 : }
     449                 : 
     450                 : /************************************************************************/
     451                 : /*                        CheckSpatialIndexTable()                      */
     452                 : /************************************************************************/
     453                 : 
     454              42 : int OGRSQLiteTableLayer::CheckSpatialIndexTable()
     455                 : {
     456              42 :     if (HasSpatialIndex() && !bHasCheckedSpatialIndexTable)
     457                 :     {
     458              13 :         bHasCheckedSpatialIndexTable = TRUE;
     459                 :         char **papszResult;
     460                 :         int nRowCount, nColCount;
     461              13 :         char *pszErrMsg = NULL;
     462                 : 
     463              13 :         CPLString osSQL;
     464                 : 
     465                 :         /* This will ensure that RTree support is available */
     466                 :         osSQL.Printf("SELECT pkid FROM 'idx_%s_%s' WHERE xmax > 0 AND xmin < 0 AND ymax > 0 AND ymin < 0",
     467              13 :                      pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
     468                 : 
     469                 :         int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
     470                 :                                     &papszResult, &nRowCount,
     471              13 :                                     &nColCount, &pszErrMsg );
     472                 : 
     473              13 :         if( rc != SQLITE_OK )
     474                 :         {
     475                 :             CPLDebug("SQLITE", "Count not find or use idx_%s_%s layer (%s). Disabling spatial index",
     476               0 :                         pszEscapedTableName, osGeomColumn.c_str(), pszErrMsg);
     477               0 :             sqlite3_free( pszErrMsg );
     478               0 :             bHasSpatialIndex = FALSE;
     479                 :         }
     480                 :         else
     481                 :         {
     482              13 :             sqlite3_free_table(papszResult);
     483              13 :         }
     484                 :     }
     485                 : 
     486              42 :     return bHasSpatialIndex;
     487                 : }
     488                 : 
     489                 : /************************************************************************/
     490                 : /*                           GetSpatialWhere()                          */
     491                 : /************************************************************************/
     492                 : 
     493             183 : CPLString OGRSQLiteTableLayer::GetSpatialWhere(OGRGeometry* poFilterGeom)
     494                 : {
     495             183 :     CPLString osSpatialWHERE;
     496                 : 
     497             183 :     if( !poDS->IsSpatialiteDB() )
     498             135 :         return osSpatialWHERE;
     499                 : 
     500              48 :     if( poFilterGeom != NULL && CheckSpatialIndexTable() )
     501                 :     {
     502              22 :         OGREnvelope  sEnvelope;
     503                 : 
     504              22 :         CPLLocaleC  oLocaleEnforcer;
     505                 : 
     506              22 :         poFilterGeom->getEnvelope( &sEnvelope );
     507                 : 
     508                 :         osSpatialWHERE.Printf("ROWID IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
     509                 :                         "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f)",
     510                 :                         pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
     511                 :                         sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
     512              22 :                         sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
     513                 :     }
     514                 : 
     515              48 :     if( poFilterGeom != NULL &&
     516                 :         OGRSQLiteIsSpatialiteLoaded() && !bHasSpatialIndex )
     517                 :     {
     518               2 :         OGREnvelope  sEnvelope;
     519                 : 
     520               2 :         CPLLocaleC  oLocaleEnforcer;
     521                 : 
     522               2 :         poFilterGeom->getEnvelope( &sEnvelope );
     523                 : 
     524                 :         /* A bit inefficient but still faster than OGR filtering */
     525                 :         osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f, %d))",
     526                 :                        OGRSQLiteEscapeName(osGeomColumn).c_str(),
     527                 :                        sEnvelope.MinX - 1e-11, sEnvelope.MinY - 1e-11,
     528                 :                        sEnvelope.MaxX + 1e-11, sEnvelope.MaxY + 1e-11,
     529               2 :                        nSRSId);
     530                 :     }
     531                 : 
     532              48 :     return osSpatialWHERE;
     533                 : }
     534                 : 
     535                 : /************************************************************************/
     536                 : /*                             BuildWhere()                             */
     537                 : /*                                                                      */
     538                 : /*      Build the WHERE statement appropriate to the current set of     */
     539                 : /*      criteria (spatial and attribute queries).                       */
     540                 : /************************************************************************/
     541                 : 
     542             166 : void OGRSQLiteTableLayer::BuildWhere()
     543                 : 
     544                 : {
     545             166 :     osWHERE = "";
     546                 : 
     547             166 :     CPLString osSpatialWHERE = GetSpatialWhere(m_poFilterGeom);
     548             332 :     if (osSpatialWHERE.size() != 0)
     549                 :     {
     550              11 :         osWHERE = "WHERE ";
     551              11 :         osWHERE += osSpatialWHERE;
     552                 :     }
     553                 : 
     554             166 :     if( osQuery.size() > 0 )
     555                 :     {
     556              90 :         if( osWHERE.size() == 0 )
     557                 :         {
     558              90 :             osWHERE = "WHERE ";
     559              90 :             osWHERE += osQuery;
     560                 :         }
     561                 :         else  
     562                 :         {
     563               0 :             osWHERE += " AND (";
     564               0 :             osWHERE += osQuery;
     565               0 :             osWHERE += ")";
     566                 :         }
     567             166 :     }
     568             166 : }
     569                 : 
     570                 : /************************************************************************/
     571                 : /*                           TestCapability()                           */
     572                 : /************************************************************************/
     573                 : 
     574             176 : int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
     575                 : 
     576                 : {
     577             176 :     if (EQUAL(pszCap,OLCFastFeatureCount))
     578                 :         return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
     579             101 :                HasSpatialIndex();
     580                 : 
     581              75 :     else if (EQUAL(pszCap,OLCFastSpatialFilter))
     582               2 :         return HasSpatialIndex();
     583                 : 
     584              73 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     585               0 :         return bCachedExtentIsValid;
     586                 : 
     587              73 :     else if( EQUAL(pszCap,OLCRandomRead) )
     588              14 :         return pszFIDColumn != NULL;
     589                 : 
     590              59 :     else if( EQUAL(pszCap,OLCSequentialWrite) 
     591                 :              || EQUAL(pszCap,OLCRandomWrite) )
     592                 :     {
     593              12 :         return poDS->GetUpdate();
     594                 :     }
     595                 : 
     596              47 :     else if( EQUAL(pszCap,OLCDeleteFeature) )
     597                 :     {
     598              10 :         return poDS->GetUpdate() && pszFIDColumn != NULL;
     599                 :     }
     600                 : 
     601              37 :     else if( EQUAL(pszCap,OLCCreateField) )
     602               0 :         return poDS->GetUpdate();
     603                 : 
     604              37 :     else if( EQUAL(pszCap,OLCDeleteField) )
     605               1 :         return poDS->GetUpdate();
     606                 : 
     607              36 :     else if( EQUAL(pszCap,OLCAlterFieldDefn) )
     608               1 :         return poDS->GetUpdate();
     609                 : 
     610              35 :     else if( EQUAL(pszCap,OLCReorderFields) )
     611               1 :         return poDS->GetUpdate();
     612                 : 
     613                 :     else 
     614              34 :         return OGRSQLiteLayer::TestCapability( pszCap );
     615                 : }
     616                 : 
     617                 : /************************************************************************/
     618                 : /*                          GetFeatureCount()                           */
     619                 : /************************************************************************/
     620                 : 
     621              99 : int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
     622                 : 
     623                 : {
     624              99 :     if (HasLayerDefnError())
     625               0 :         return 0;
     626                 : 
     627              99 :     if( !TestCapability(OLCFastFeatureCount) )
     628               9 :         return OGRSQLiteLayer::GetFeatureCount( bForce );
     629                 : 
     630              90 :     if (nFeatureCount >= 0 && m_poFilterGeom == NULL &&
     631                 :         osQuery.size() == 0 )
     632                 :     {
     633              49 :         return nFeatureCount;
     634                 :     }
     635                 : 
     636                 : /* -------------------------------------------------------------------- */
     637                 : /*      Form count SQL.                                                 */
     638                 : /* -------------------------------------------------------------------- */
     639                 :     const char *pszSQL;
     640                 : 
     641              41 :     if (m_poFilterGeom != NULL && CheckSpatialIndexTable() &&
     642                 :         strlen(osQuery) == 0)
     643                 :     {
     644               9 :         OGREnvelope  sEnvelope;
     645                 : 
     646               9 :         m_poFilterGeom->getEnvelope( &sEnvelope );
     647                 :         pszSQL = CPLSPrintf("SELECT count(*) FROM 'idx_%s_%s' WHERE "
     648                 :                             "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f",
     649                 :                             pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
     650                 :                             sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
     651               9 :                             sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
     652                 :     }
     653                 :     else
     654                 :     {
     655                 :         pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
     656              32 :                             pszEscapedTableName, osWHERE.c_str() );
     657                 :     }
     658                 : 
     659              41 :     CPLDebug("SQLITE", "Running %s", pszSQL);
     660                 : 
     661                 : /* -------------------------------------------------------------------- */
     662                 : /*      Execute.                                                        */
     663                 : /* -------------------------------------------------------------------- */
     664                 :     char **papszResult, *pszErrMsg;
     665                 :     int nRowCount, nColCount;
     666              41 :     int nResult = -1;
     667                 : 
     668              41 :     if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
     669                 :                            &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
     670               0 :         return -1;
     671                 : 
     672              41 :     if( nRowCount == 1 && nColCount == 1 )
     673                 :     {
     674              41 :         nResult = atoi(papszResult[1]);
     675                 : 
     676              41 :         if( m_poFilterGeom == NULL && osQuery.size() == 0 )
     677                 :         {
     678              18 :             nFeatureCount = nResult;
     679              18 :             bStatisticsNeedsToBeFlushed = TRUE;
     680                 :         }
     681                 :     }
     682                 : 
     683              41 :     sqlite3_free_table( papszResult );
     684                 : 
     685              41 :     return nResult;
     686                 : }
     687                 : 
     688                 : /************************************************************************/
     689                 : /*                             GetExtent()                              */
     690                 : /************************************************************************/
     691                 : 
     692              36 : OGRErr OGRSQLiteTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     693                 : {
     694              36 :     if (HasLayerDefnError())
     695               0 :         return OGRERR_FAILURE;
     696                 : 
     697              36 :     if (GetGeomType() == wkbNone)
     698               0 :         return OGRERR_FAILURE;
     699                 : 
     700              36 :     if (bCachedExtentIsValid)
     701                 :     {
     702              27 :         memcpy(psExtent, &oCachedExtent, sizeof(oCachedExtent));
     703              27 :         return OGRERR_NONE;
     704                 :     }
     705                 : 
     706               9 :     if (CheckSpatialIndexTable() &&
     707                 :         !CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO")))
     708                 :     {
     709                 :         const char* pszSQL;
     710                 : 
     711                 :         pszSQL = CPLSPrintf("SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM 'idx_%s_%s'",
     712               2 :                             pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
     713                 : 
     714               2 :         CPLDebug("SQLITE", "Running %s", pszSQL);
     715                 : 
     716                 : /* -------------------------------------------------------------------- */
     717                 : /*      Execute.                                                        */
     718                 : /* -------------------------------------------------------------------- */
     719                 :         char **papszResult, *pszErrMsg;
     720                 :         int nRowCount, nColCount;
     721                 : 
     722               2 :         if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
     723                 :                                &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
     724               0 :             return OGRSQLiteLayer::GetExtent(psExtent, bForce);
     725                 : 
     726               2 :         OGRErr eErr = OGRERR_FAILURE;
     727                 : 
     728              10 :         if( nRowCount == 1 && nColCount == 4 &&
     729               2 :             papszResult[4+0] != NULL &&
     730               2 :             papszResult[4+1] != NULL &&
     731               2 :             papszResult[4+2] != NULL &&
     732               2 :             papszResult[4+3] != NULL)
     733                 :         {
     734               2 :             psExtent->MinX = atof(papszResult[4+0]);
     735               2 :             psExtent->MinY = atof(papszResult[4+1]);
     736               2 :             psExtent->MaxX = atof(papszResult[4+2]);
     737               2 :             psExtent->MaxY = atof(papszResult[4+3]);
     738               2 :             eErr = OGRERR_NONE;
     739                 : 
     740               2 :             if( m_poFilterGeom == NULL && osQuery.size() == 0 )
     741                 :             {
     742               2 :                 bCachedExtentIsValid = TRUE;
     743               2 :                 bStatisticsNeedsToBeFlushed = TRUE;
     744               2 :                 memcpy(&oCachedExtent, psExtent, sizeof(oCachedExtent));
     745                 :             }
     746                 :         }
     747                 : 
     748               2 :         sqlite3_free_table( papszResult );
     749                 : 
     750               2 :         if (eErr == OGRERR_NONE)
     751               2 :             return eErr;
     752                 :     }
     753                 : 
     754               7 :     OGRErr eErr = OGRSQLiteLayer::GetExtent(psExtent, bForce);
     755               7 :     if( eErr == OGRERR_NONE && m_poFilterGeom == NULL && osQuery.size() == 0 )
     756                 :     {
     757               7 :         bCachedExtentIsValid = TRUE;
     758               7 :         bStatisticsNeedsToBeFlushed = TRUE;
     759               7 :         memcpy(&oCachedExtent, psExtent, sizeof(oCachedExtent));
     760                 :     }
     761               7 :     return eErr;
     762                 : }
     763                 : 
     764                 : /************************************************************************/
     765                 : /*                  OGRSQLiteFieldDefnToSQliteFieldDefn()               */
     766                 : /************************************************************************/
     767                 : 
     768            1967 : CPLString OGRSQLiteFieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn )
     769                 : {
     770            1967 :     switch( poFieldDefn->GetType() )
     771                 :     {
     772             409 :         case OFTInteger: return "INTEGER"; break;
     773             257 :         case OFTReal   : return "FLOAT"; break;
     774             196 :         case OFTBinary : return "BLOB"; break;
     775                 :         case OFTString :
     776                 :         {
     777             541 :             if( poFieldDefn->GetWidth() > 0 )
     778             118 :                 return CPLSPrintf("VARCHAR(%d)", poFieldDefn->GetWidth());
     779                 :             else
     780             423 :                 return "VARCHAR";
     781                 :             break;
     782                 :         }
     783             188 :         case OFTDateTime: return "TIMESTAMP"; break;
     784             188 :         case OFTDate    : return "DATE"; break;
     785             188 :         case OFTTime    : return "TIME"; break;
     786               0 :         default         : return "VARCHAR"; break;
     787                 :     }
     788                 : }
     789                 : 
     790                 : /************************************************************************/
     791                 : /*                    FieldDefnToSQliteFieldDefn()                      */
     792                 : /************************************************************************/
     793                 : 
     794             172 : CPLString OGRSQLiteTableLayer::FieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn )
     795                 : {
     796             172 :     CPLString osRet = OGRSQLiteFieldDefnToSQliteFieldDefn(poFieldDefn);
     797             172 :     if( poFieldDefn->GetType() == OFTString &&
     798                 :         CSLFindString(papszCompressedColumns, poFieldDefn->GetNameRef()) >= 0 )
     799               8 :         osRet += "_deflate";
     800                 : 
     801               0 :     return osRet;
     802                 : }
     803                 : 
     804                 : /************************************************************************/
     805                 : /*                            CreateField()                             */
     806                 : /************************************************************************/
     807                 : 
     808              83 : OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
     809                 :                                          int bApproxOK )
     810                 : 
     811                 : {
     812              83 :     OGRFieldDefn        oField( poFieldIn );
     813                 : 
     814              83 :     if (HasLayerDefnError())
     815               0 :         return OGRERR_FAILURE;
     816                 : 
     817              83 :     ResetReading();
     818                 : 
     819              83 :     if (!poDS->GetUpdate())
     820                 :     {
     821                 :         CPLError( CE_Failure, CPLE_NotSupported,
     822                 :                   UNSUPPORTED_OP_READ_ONLY,
     823               0 :                   "CreateField");
     824               0 :         return OGRERR_FAILURE;
     825                 :     }
     826                 : 
     827              83 :     ClearInsertStmt();
     828                 : 
     829                 : /* -------------------------------------------------------------------- */
     830                 : /*      Do we want to "launder" the column names into SQLite            */
     831                 : /*      friendly format?                                                */
     832                 : /* -------------------------------------------------------------------- */
     833              83 :     if( bLaunderColumnNames )
     834                 :     {
     835              81 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
     836                 : 
     837              81 :         oField.SetName( pszSafeName );
     838              81 :         CPLFree( pszSafeName );
     839                 :     }
     840                 : 
     841                 : 
     842              83 :     if( (oField.GetType() == OFTTime || oField.GetType() == OFTDate ||
     843                 :          oField.GetType() == OFTDateTime) &&
     844                 :         !(CSLTestBoolean(
     845                 :             CPLGetConfigOption("OGR_SQLITE_ENABLE_DATETIME", "YES"))) )
     846                 :     {
     847               0 :         oField.SetType(OFTString);
     848                 :     }
     849                 : 
     850                 :     /* ADD COLUMN only avaliable since sqlite 3.1.3 */
     851              83 :     if (CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_USE_ADD_COLUMN", "YES")) &&
     852                 :         sqlite3_libversion_number() > 3 * 1000000 + 1 * 1000 + 3)
     853                 :     {
     854                 :         int rc;
     855              83 :         char *pszErrMsg = NULL;
     856              83 :         sqlite3 *hDB = poDS->GetDB();
     857              83 :         CPLString osCommand;
     858                 : 
     859              83 :         CPLString osFieldType(FieldDefnToSQliteFieldDefn(&oField));
     860                 :         osCommand.Printf("ALTER TABLE '%s' ADD COLUMN '%s' %s",
     861                 :                         pszEscapedTableName,
     862                 :                         OGRSQLiteEscape(oField.GetNameRef()).c_str(),
     863              83 :                         osFieldType.c_str());
     864                 : 
     865                 :     #ifdef DEBUG
     866              83 :         CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
     867                 :     #endif
     868                 : 
     869              83 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     870              83 :         if( rc != SQLITE_OK )
     871                 :         {
     872                 :             CPLError( CE_Failure, CPLE_AppDefined,
     873                 :                       "Failed to add field %s to table %s:\n %s",
     874                 :                       oField.GetNameRef(), poFeatureDefn->GetName(), 
     875               0 :                       pszErrMsg );
     876               0 :             sqlite3_free( pszErrMsg );
     877               0 :             return OGRERR_FAILURE;
     878               0 :         }
     879                 :     }
     880                 :     else
     881                 :     {
     882               0 :         OGRErr eErr = AddColumnAncientMethod(oField);
     883               0 :         if (eErr != OGRERR_NONE)
     884               0 :             return eErr;
     885                 :     }
     886                 : 
     887                 : /* -------------------------------------------------------------------- */
     888                 : /*      Add the field to the OGRFeatureDefn.                            */
     889                 : /* -------------------------------------------------------------------- */
     890                 :     int iNewField;
     891              83 :     int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
     892                 : 
     893              83 :     if( poFeatureDefn->GetGeomType() != wkbNone )
     894                 :     {
     895              67 :         iNextOrdinal++;
     896                 :     }
     897                 : 
     898             180 :     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     899                 :     {
     900              97 :         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
     901                 : 
     902                 :         // we already added OGC_FID so don't do it again
     903              97 :         if( EQUAL(poFldDefn->GetNameRef(),"OGC_FID") )
     904               0 :             continue;
     905                 : 
     906              97 :         iNextOrdinal++;
     907                 :     }
     908                 : 
     909              83 :     poFeatureDefn->AddFieldDefn( &oField );
     910                 : 
     911              83 :     iNewField = poFeatureDefn->GetFieldCount() - 1;
     912                 :     panFieldOrdinals = (int *)
     913              83 :         CPLRealloc(panFieldOrdinals, (iNewField+1) * sizeof(int) );
     914              83 :     panFieldOrdinals[iNewField] = iNextOrdinal;
     915                 : 
     916              83 :     return OGRERR_NONE;
     917                 : }
     918                 : 
     919                 : /************************************************************************/
     920                 : /*                     InitFieldListForRecrerate()                      */
     921                 : /************************************************************************/
     922                 : 
     923              23 : void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
     924                 :                                                     char* & pszFieldListForSelect,
     925                 :                                                     int nExtraSpace)
     926                 : {
     927              23 :     int iField, nFieldListLen = 100 + 2 * nExtraSpace;
     928                 : 
     929             118 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     930                 :     {
     931                 :         nFieldListLen +=
     932              95 :             2 * strlen(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) + 50;
     933                 :     }
     934                 : 
     935              23 :     nFieldListLen += 50 + (pszFIDColumn ? 2 * strlen(pszFIDColumn) : strlen("OGC_FID"));
     936              23 :     if( poFeatureDefn->GetGeomType() != wkbNone )
     937                 :     {
     938              23 :         nFieldListLen += 50 + 2 * strlen(osGeomColumn);
     939                 :     }
     940                 : 
     941              23 :     pszFieldListForSelect = (char *) CPLCalloc(1,nFieldListLen);
     942              23 :     pszNewFieldList = (char *) CPLCalloc(1,nFieldListLen);
     943                 : 
     944                 : /* -------------------------------------------------------------------- */
     945                 : /*      Build list of old fields, and the list of new fields.           */
     946                 : /* -------------------------------------------------------------------- */
     947              23 :     sprintf( pszFieldListForSelect, "\"%s\"", pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
     948              23 :     sprintf( pszNewFieldList, "\"%s\" INTEGER PRIMARY KEY",pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
     949                 : 
     950              23 :     if( poFeatureDefn->GetGeomType() != wkbNone )
     951                 :     {
     952              23 :         strcat( pszFieldListForSelect, "," );
     953              23 :         strcat( pszNewFieldList, "," );
     954                 : 
     955              23 :         strcat( pszFieldListForSelect, "\"");
     956              23 :         strcat( pszFieldListForSelect, OGRSQLiteEscapeName(osGeomColumn) );
     957              23 :         strcat( pszFieldListForSelect, "\"");
     958                 :         
     959              23 :         strcat( pszNewFieldList, "\"");
     960              46 :         strcat( pszNewFieldList, OGRSQLiteEscapeName(osGeomColumn) );
     961              23 :         strcat( pszNewFieldList, "\"");
     962                 : 
     963              23 :         if ( eGeomFormat == OSGF_WKT )
     964               0 :             strcat( pszNewFieldList, " VARCHAR" );
     965                 :         else
     966              23 :             strcat( pszNewFieldList, " BLOB" );
     967                 :     }
     968              23 : }
     969                 : 
     970                 : /************************************************************************/
     971                 : /*                       AddColumnAncientMethod()                       */
     972                 : /************************************************************************/
     973                 : 
     974               0 : OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
     975                 : {
     976                 :     
     977                 : /* -------------------------------------------------------------------- */
     978                 : /*      How much space do we need for the list of fields.               */
     979                 : /* -------------------------------------------------------------------- */
     980                 :     int iField;
     981                 :     char *pszOldFieldList, *pszNewFieldList;
     982                 : 
     983                 :     InitFieldListForRecrerate(pszNewFieldList, pszOldFieldList,
     984               0 :                               strlen( oField.GetNameRef() ));
     985                 : 
     986                 : /* -------------------------------------------------------------------- */
     987                 : /*      Build list of old fields, and the list of new fields.           */
     988                 : /* -------------------------------------------------------------------- */
     989                 : 
     990               0 :     int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
     991                 : 
     992               0 :     if( poFeatureDefn->GetGeomType() != wkbNone )
     993                 :     {
     994               0 :         iNextOrdinal++;
     995                 :     }
     996                 : 
     997               0 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     998                 :     {
     999               0 :         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
    1000                 : 
    1001                 :         // we already added OGC_FID so don't do it again
    1002               0 :         if( EQUAL(poFldDefn->GetNameRef(),pszFIDColumn ? pszFIDColumn : "OGC_FID") )
    1003               0 :             continue;
    1004                 : 
    1005                 :         sprintf( pszOldFieldList+strlen(pszOldFieldList), 
    1006               0 :                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
    1007                 : 
    1008                 :         sprintf( pszNewFieldList+strlen(pszNewFieldList), 
    1009                 :                  ", '%s' %s", OGRSQLiteEscape(poFldDefn->GetNameRef()).c_str(),
    1010               0 :                  FieldDefnToSQliteFieldDefn(poFldDefn).c_str() );
    1011                 : 
    1012               0 :         iNextOrdinal++;
    1013                 :     }
    1014                 : 
    1015                 : /* -------------------------------------------------------------------- */
    1016                 : /*      Add the new field.                                              */
    1017                 : /* -------------------------------------------------------------------- */
    1018                 : 
    1019                 :     sprintf( pszNewFieldList+strlen(pszNewFieldList), 
    1020                 :              ", '%s' %s", OGRSQLiteEscape(oField.GetNameRef()).c_str(),
    1021               0 :              FieldDefnToSQliteFieldDefn(&oField).c_str() );
    1022                 : 
    1023                 : /* ==================================================================== */
    1024                 : /*      Backup, destroy, recreate and repopulate the table.  SQLite     */
    1025                 : /*      has no ALTER TABLE so we have to do all this to add a           */
    1026                 : /*      column.                                                         */
    1027                 : /* ==================================================================== */
    1028                 : 
    1029                 : /* -------------------------------------------------------------------- */
    1030                 : /*      Do this all in a transaction.                                   */
    1031                 : /* -------------------------------------------------------------------- */
    1032               0 :     poDS->SoftStartTransaction();
    1033                 : 
    1034                 : /* -------------------------------------------------------------------- */
    1035                 : /*      Save existing related triggers and index                        */
    1036                 : /* -------------------------------------------------------------------- */
    1037                 :     int rc;
    1038               0 :     char *pszErrMsg = NULL;
    1039               0 :     sqlite3 *hDB = poDS->GetDB();
    1040               0 :     CPLString osSQL;
    1041                 : 
    1042                 :     osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
    1043               0 :                    pszEscapedTableName );
    1044                 : 
    1045                 :     int nRowTriggerIndexCount, nColTriggerIndexCount;
    1046               0 :     char **papszTriggerIndexResult = NULL;
    1047                 :     rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult, 
    1048               0 :                             &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
    1049                 : 
    1050                 : /* -------------------------------------------------------------------- */
    1051                 : /*      Make a backup of the table.                                     */
    1052                 : /* -------------------------------------------------------------------- */
    1053                 : 
    1054               0 :     if( rc == SQLITE_OK )
    1055                 :         rc = sqlite3_exec( hDB, 
    1056                 :                        CPLSPrintf( "CREATE TEMPORARY TABLE t1_back(%s)",
    1057                 :                                    pszOldFieldList ),
    1058               0 :                        NULL, NULL, &pszErrMsg );
    1059                 : 
    1060               0 :     if( rc == SQLITE_OK )
    1061                 :         rc = sqlite3_exec( hDB, 
    1062                 :                            CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
    1063                 :                                        pszOldFieldList, 
    1064                 :                                        pszEscapedTableName ),
    1065               0 :                            NULL, NULL, &pszErrMsg );
    1066                 : 
    1067                 : 
    1068                 : /* -------------------------------------------------------------------- */
    1069                 : /*      Drop the original table, and recreate with new field.           */
    1070                 : /* -------------------------------------------------------------------- */
    1071               0 :     if( rc == SQLITE_OK )
    1072                 :         rc = sqlite3_exec( hDB, 
    1073                 :                            CPLSPrintf( "DROP TABLE '%s'", 
    1074                 :                                        pszEscapedTableName ),
    1075               0 :                            NULL, NULL, &pszErrMsg );
    1076                 : 
    1077               0 :     if( rc == SQLITE_OK )
    1078                 :     {
    1079                 :         const char *pszCmd = 
    1080                 :             CPLSPrintf( "CREATE TABLE '%s' (%s)", 
    1081                 :                         pszEscapedTableName,
    1082               0 :                         pszNewFieldList );
    1083                 :         rc = sqlite3_exec( hDB, pszCmd, 
    1084               0 :                            NULL, NULL, &pszErrMsg );
    1085                 : 
    1086               0 :         CPLDebug( "OGR_SQLITE", "exec(%s)", pszCmd );
    1087                 :     }
    1088                 : 
    1089                 : /* -------------------------------------------------------------------- */
    1090                 : /*      Copy backup field values into new table.                        */
    1091                 : /* -------------------------------------------------------------------- */
    1092                 :     
    1093               0 :     if( rc == SQLITE_OK )
    1094                 :         rc = sqlite3_exec( hDB, 
    1095                 :                            CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
    1096                 :                                        pszEscapedTableName,
    1097                 :                                        pszOldFieldList ),
    1098               0 :                            NULL, NULL, &pszErrMsg );
    1099                 : 
    1100               0 :     CPLFree( pszOldFieldList );
    1101               0 :     CPLFree( pszNewFieldList );
    1102                 : 
    1103                 : /* -------------------------------------------------------------------- */
    1104                 : /*      Cleanup backup table.                                           */
    1105                 : /* -------------------------------------------------------------------- */
    1106                 :     
    1107               0 :     if( rc == SQLITE_OK )
    1108                 :         rc = sqlite3_exec( hDB, 
    1109                 :                            CPLSPrintf( "DROP TABLE t1_back" ),
    1110               0 :                            NULL, NULL, &pszErrMsg );
    1111                 : 
    1112                 : /* -------------------------------------------------------------------- */
    1113                 : /*      Recreate existing related tables, triggers and index            */
    1114                 : /* -------------------------------------------------------------------- */
    1115                 : 
    1116               0 :     if( rc == SQLITE_OK )
    1117                 :     {
    1118                 :         int i;
    1119                 : 
    1120               0 :         for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
    1121                 :         {
    1122               0 :             if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
    1123                 :                 rc = sqlite3_exec( hDB, 
    1124               0 :                             papszTriggerIndexResult[i],
    1125               0 :                             NULL, NULL, &pszErrMsg );
    1126                 :         }
    1127                 :     }
    1128                 : 
    1129                 : /* -------------------------------------------------------------------- */
    1130                 : /*      COMMIT on success or ROLLBACK on failuire.                      */
    1131                 : /* -------------------------------------------------------------------- */
    1132                 : 
    1133               0 :     sqlite3_free_table( papszTriggerIndexResult );
    1134                 : 
    1135               0 :     if( rc == SQLITE_OK )
    1136                 :     {
    1137               0 :         poDS->SoftCommit();
    1138                 :     }
    1139                 :     else
    1140                 :     {
    1141                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1142                 :                   "Failed to add field %s to table %s:\n %s",
    1143                 :                   oField.GetNameRef(), poFeatureDefn->GetName(), 
    1144               0 :                   pszErrMsg );
    1145               0 :         sqlite3_free( pszErrMsg );
    1146                 : 
    1147               0 :         poDS->SoftRollback();
    1148                 : 
    1149               0 :         return OGRERR_FAILURE;
    1150                 :     }
    1151                 : 
    1152               0 :     return OGRERR_NONE;
    1153                 : }
    1154                 : 
    1155                 : /************************************************************************/
    1156                 : /*                           RecreateTable()                            */
    1157                 : /************************************************************************/
    1158                 : 
    1159              23 : OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
    1160                 :                                           const char* pszNewFieldList,
    1161                 :                                           const char* pszGenericErrorMessage)
    1162                 : {
    1163                 : /* -------------------------------------------------------------------- */
    1164                 : /*      Do this all in a transaction.                                   */
    1165                 : /* -------------------------------------------------------------------- */
    1166              23 :     poDS->SoftStartTransaction();
    1167                 : 
    1168                 : /* -------------------------------------------------------------------- */
    1169                 : /*      Save existing related triggers and index                        */
    1170                 : /* -------------------------------------------------------------------- */
    1171                 :     int rc;
    1172              23 :     char *pszErrMsg = NULL;
    1173              23 :     sqlite3 *hDB = poDS->GetDB();
    1174              23 :     CPLString osSQL;
    1175                 : 
    1176                 :     osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
    1177              23 :                    pszEscapedTableName );
    1178                 : 
    1179                 :     int nRowTriggerIndexCount, nColTriggerIndexCount;
    1180              23 :     char **papszTriggerIndexResult = NULL;
    1181                 :     rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
    1182              23 :                             &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
    1183                 : 
    1184                 : /* -------------------------------------------------------------------- */
    1185                 : /*      Make a backup of the table.                                     */
    1186                 : /* -------------------------------------------------------------------- */
    1187                 : 
    1188              23 :     if( rc == SQLITE_OK )
    1189                 :         rc = sqlite3_exec( hDB,
    1190                 :                        CPLSPrintf( "CREATE TABLE t1_back(%s)",
    1191                 :                                    pszNewFieldList ),
    1192              23 :                        NULL, NULL, &pszErrMsg );
    1193                 : 
    1194              23 :     if( rc == SQLITE_OK )
    1195                 :         rc = sqlite3_exec( hDB,
    1196                 :                            CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
    1197                 :                                        pszFieldListForSelect,
    1198                 :                                        pszEscapedTableName ),
    1199              23 :                            NULL, NULL, &pszErrMsg );
    1200                 : 
    1201                 : 
    1202                 : /* -------------------------------------------------------------------- */
    1203                 : /*      Drop the original table                                         */
    1204                 : /* -------------------------------------------------------------------- */
    1205              23 :     if( rc == SQLITE_OK )
    1206                 :         rc = sqlite3_exec( hDB,
    1207                 :                            CPLSPrintf( "DROP TABLE '%s'",
    1208                 :                                        pszEscapedTableName ),
    1209              23 :                            NULL, NULL, &pszErrMsg );
    1210                 : 
    1211                 : /* -------------------------------------------------------------------- */
    1212                 : /*      Rename backup table as new table                                */
    1213                 : /* -------------------------------------------------------------------- */
    1214              23 :     if( rc == SQLITE_OK )
    1215                 :     {
    1216                 :         const char *pszCmd =
    1217                 :             CPLSPrintf( "ALTER TABLE t1_back RENAME TO '%s'",
    1218              23 :                         pszEscapedTableName);
    1219                 :         rc = sqlite3_exec( hDB, pszCmd,
    1220              23 :                            NULL, NULL, &pszErrMsg );
    1221                 :     }
    1222                 : 
    1223                 : /* -------------------------------------------------------------------- */
    1224                 : /*      Recreate existing related tables, triggers and index            */
    1225                 : /* -------------------------------------------------------------------- */
    1226                 : 
    1227              23 :     if( rc == SQLITE_OK )
    1228                 :     {
    1229                 :         int i;
    1230                 : 
    1231              23 :         for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
    1232                 :         {
    1233               0 :             if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
    1234                 :                 rc = sqlite3_exec( hDB,
    1235               0 :                             papszTriggerIndexResult[i],
    1236               0 :                             NULL, NULL, &pszErrMsg );
    1237                 :         }
    1238                 :     }
    1239                 : 
    1240                 : /* -------------------------------------------------------------------- */
    1241                 : /*      COMMIT on success or ROLLBACK on failuire.                      */
    1242                 : /* -------------------------------------------------------------------- */
    1243                 : 
    1244              23 :     sqlite3_free_table( papszTriggerIndexResult );
    1245                 : 
    1246              23 :     if( rc == SQLITE_OK )
    1247                 :     {
    1248              23 :         poDS->SoftCommit();
    1249                 : 
    1250              23 :         return OGRERR_NONE;
    1251                 :     }
    1252                 :     else
    1253                 :     {
    1254                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1255                 :                   "%s:\n %s",
    1256                 :                   pszGenericErrorMessage,
    1257               0 :                   pszErrMsg );
    1258               0 :         sqlite3_free( pszErrMsg );
    1259                 : 
    1260               0 :         poDS->SoftRollback();
    1261                 : 
    1262               0 :         return OGRERR_FAILURE;
    1263               0 :     }
    1264                 : }
    1265                 : 
    1266                 : /************************************************************************/
    1267                 : /*                             DeleteField()                            */
    1268                 : /************************************************************************/
    1269                 : 
    1270               8 : OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
    1271                 : {
    1272               8 :     if (HasLayerDefnError())
    1273               0 :         return OGRERR_FAILURE;
    1274                 : 
    1275               8 :     if (!poDS->GetUpdate())
    1276                 :     {
    1277                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1278                 :                   UNSUPPORTED_OP_READ_ONLY,
    1279               0 :                   "DeleteField");
    1280               0 :         return OGRERR_FAILURE;
    1281                 :     }
    1282                 : 
    1283               8 :     if (iFieldToDelete < 0 || iFieldToDelete >= poFeatureDefn->GetFieldCount())
    1284                 :     {
    1285                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1286               2 :                   "Invalid field index");
    1287               2 :         return OGRERR_FAILURE;
    1288                 :     }
    1289                 : 
    1290               6 :     ResetReading();
    1291                 : 
    1292                 : /* -------------------------------------------------------------------- */
    1293                 : /*      Build list of old fields, and the list of new fields.           */
    1294                 : /* -------------------------------------------------------------------- */
    1295                 :     int iField;
    1296                 :     char *pszNewFieldList, *pszFieldListForSelect;
    1297               6 :     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
    1298                 : 
    1299              26 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    1300                 :     {
    1301              20 :         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
    1302                 : 
    1303              20 :         if (iField == iFieldToDelete)
    1304               6 :             continue;
    1305                 : 
    1306                 :         sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
    1307              14 :                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
    1308                 : 
    1309                 :         sprintf( pszNewFieldList+strlen(pszNewFieldList),
    1310                 :                  ", '%s' %s", OGRSQLiteEscape(poFldDefn->GetNameRef()).c_str(),
    1311              28 :                  FieldDefnToSQliteFieldDefn(poFldDefn).c_str() );
    1312                 :     }
    1313                 : 
    1314                 : /* -------------------------------------------------------------------- */
    1315                 : /*      Recreate table.                                                 */
    1316                 : /* -------------------------------------------------------------------- */
    1317               6 :     CPLString osErrorMsg;
    1318                 :     osErrorMsg.Printf("Failed to remove field %s from table %s",
    1319                 :                   poFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef(),
    1320               6 :                   poFeatureDefn->GetName());
    1321                 : 
    1322                 :     OGRErr eErr = RecreateTable(pszFieldListForSelect,
    1323                 :                                 pszNewFieldList,
    1324               6 :                                 osErrorMsg.c_str());
    1325                 : 
    1326               6 :     CPLFree( pszFieldListForSelect );
    1327               6 :     CPLFree( pszNewFieldList );
    1328                 : 
    1329               6 :     if (eErr != OGRERR_NONE)
    1330               0 :         return eErr;
    1331                 : 
    1332                 : /* -------------------------------------------------------------------- */
    1333                 : /*      Finish                                                          */
    1334                 : /* -------------------------------------------------------------------- */
    1335               6 :     int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
    1336                 : 
    1337               6 :     if( poFeatureDefn->GetGeomType() != wkbNone )
    1338                 :     {
    1339               6 :         iNextOrdinal++;
    1340                 :     }
    1341                 : 
    1342               6 :     int iNewField = 0;
    1343              26 :     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    1344                 :     {
    1345              20 :         if (iField == iFieldToDelete)
    1346               6 :             continue;
    1347                 : 
    1348              14 :         panFieldOrdinals[iNewField ++] = iNextOrdinal++;
    1349                 :     }
    1350                 : 
    1351               6 :     return poFeatureDefn->DeleteFieldDefn( iFieldToDelete );
    1352                 : }
    1353                 : 
    1354                 : /************************************************************************/
    1355                 : /*                           AlterFieldDefn()                           */
    1356                 : /************************************************************************/
    1357                 : 
    1358               9 : OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
    1359                 : {
    1360               9 :     if (HasLayerDefnError())
    1361               0 :         return OGRERR_FAILURE;
    1362                 : 
    1363               9 :     if (!poDS->GetUpdate())
    1364                 :     {
    1365                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1366                 :                   UNSUPPORTED_OP_READ_ONLY,
    1367               0 :                   "AlterFieldDefn");
    1368               0 :         return OGRERR_FAILURE;
    1369                 :     }
    1370                 : 
    1371               9 :     if (iFieldToAlter < 0 || iFieldToAlter >= poFeatureDefn->GetFieldCount())
    1372                 :     {
    1373                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1374               2 :                   "Invalid field index");
    1375               2 :         return OGRERR_FAILURE;
    1376                 :     }
    1377                 : 
    1378               7 :     ClearInsertStmt();
    1379               7 :     ResetReading();
    1380                 : 
    1381                 : /* -------------------------------------------------------------------- */
    1382                 : /*      Build list of old fields, and the list of new fields.           */
    1383                 : /* -------------------------------------------------------------------- */
    1384                 :     int iField;
    1385                 :     char *pszNewFieldList, *pszFieldListForSelect;
    1386                 :     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect,
    1387               7 :                               strlen(poNewFieldDefn->GetNameRef()));
    1388                 : 
    1389              40 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    1390                 :     {
    1391              33 :         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
    1392                 : 
    1393                 :         sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
    1394              33 :                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
    1395                 : 
    1396              33 :         if (iField == iFieldToAlter)
    1397                 :         {
    1398               7 :             OGRFieldDefn oTmpFieldDefn(poFldDefn);
    1399               7 :             if( (nFlags & ALTER_NAME_FLAG) )
    1400               7 :                 oTmpFieldDefn.SetName(poNewFieldDefn->GetNameRef());
    1401               7 :             if( (nFlags & ALTER_TYPE_FLAG) )
    1402               7 :                 oTmpFieldDefn.SetType(poNewFieldDefn->GetType());
    1403               7 :             if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
    1404                 :             {
    1405               7 :                 oTmpFieldDefn.SetWidth(poNewFieldDefn->GetWidth());
    1406               7 :                 oTmpFieldDefn.SetPrecision(poNewFieldDefn->GetPrecision());
    1407                 :             }
    1408                 : 
    1409                 :             sprintf( pszNewFieldList+strlen(pszNewFieldList),
    1410                 :                     ", '%s' %s",
    1411                 :                     OGRSQLiteEscape(oTmpFieldDefn.GetNameRef()).c_str(),
    1412               7 :                     FieldDefnToSQliteFieldDefn(&oTmpFieldDefn).c_str() );
    1413               7 :             if ( (nFlags & ALTER_NAME_FLAG) &&
    1414                 :                  oTmpFieldDefn.GetType() == OFTString &&
    1415                 :                  CSLFindString(papszCompressedColumns, poFldDefn->GetNameRef()) >= 0 )
    1416                 :             {
    1417               0 :                 sprintf( pszNewFieldList+strlen(pszNewFieldList), "_deflate");
    1418               7 :             }
    1419                 :         }
    1420                 :         else
    1421                 :         {
    1422                 :             sprintf( pszNewFieldList+strlen(pszNewFieldList),
    1423                 :                     ", '%s' %s", OGRSQLiteEscape(poFldDefn->GetNameRef()).c_str(),
    1424              26 :                     FieldDefnToSQliteFieldDefn(poFldDefn).c_str() );
    1425                 :         }
    1426                 :     }
    1427                 : 
    1428                 : /* -------------------------------------------------------------------- */
    1429                 : /*      Recreate table.                                                 */
    1430                 : /* -------------------------------------------------------------------- */
    1431               7 :     CPLString osErrorMsg;
    1432                 :     osErrorMsg.Printf("Failed to alter field %s from table %s",
    1433                 :                   poFeatureDefn->GetFieldDefn(iFieldToAlter)->GetNameRef(),
    1434               7 :                   poFeatureDefn->GetName());
    1435                 : 
    1436                 :     OGRErr eErr = RecreateTable(pszFieldListForSelect,
    1437                 :                                 pszNewFieldList,
    1438               7 :                                 osErrorMsg.c_str());
    1439                 : 
    1440               7 :     CPLFree( pszFieldListForSelect );
    1441               7 :     CPLFree( pszNewFieldList );
    1442                 : 
    1443               7 :     if (eErr != OGRERR_NONE)
    1444               0 :         return eErr;
    1445                 : 
    1446                 : /* -------------------------------------------------------------------- */
    1447                 : /*      Finish                                                          */
    1448                 : /* -------------------------------------------------------------------- */
    1449                 : 
    1450               7 :     OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iFieldToAlter);
    1451                 : 
    1452               7 :     if (nFlags & ALTER_TYPE_FLAG)
    1453                 :     {
    1454                 :         int iIdx;
    1455               7 :         if( poNewFieldDefn->GetType() != OFTString &&
    1456                 :             (iIdx = CSLFindString(papszCompressedColumns,
    1457                 :                                   poFieldDefn->GetNameRef())) >= 0 )
    1458                 :         {
    1459                 :             papszCompressedColumns = CSLRemoveStrings(papszCompressedColumns,
    1460               0 :                                                       iIdx, 1, NULL);
    1461                 :         }
    1462               7 :         poFieldDefn->SetType(poNewFieldDefn->GetType());
    1463                 :     }
    1464               7 :     if (nFlags & ALTER_NAME_FLAG)
    1465                 :     {
    1466                 :         int iIdx;
    1467               7 :         if( (iIdx = CSLFindString(papszCompressedColumns,
    1468                 :                                   poFieldDefn->GetNameRef())) >= 0 )
    1469                 :         {
    1470               0 :             CPLFree(papszCompressedColumns[iIdx]);
    1471               0 :             papszCompressedColumns[iIdx] =
    1472               0 :                 CPLStrdup(poNewFieldDefn->GetNameRef());
    1473                 :         }
    1474               7 :         poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
    1475                 :     }
    1476               7 :     if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
    1477                 :     {
    1478               7 :         poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
    1479               7 :         poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
    1480                 :     }
    1481               7 :     return OGRERR_NONE;
    1482                 : }
    1483                 : 
    1484                 : /************************************************************************/
    1485                 : /*                           ReorderFields()                            */
    1486                 : /************************************************************************/
    1487                 : 
    1488              12 : OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
    1489                 : {
    1490              12 :     if (HasLayerDefnError())
    1491               0 :         return OGRERR_FAILURE;
    1492                 : 
    1493              12 :     if (!poDS->GetUpdate())
    1494                 :     {
    1495                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1496                 :                   UNSUPPORTED_OP_READ_ONLY,
    1497               0 :                   "ReorderFields");
    1498               0 :         return OGRERR_FAILURE;
    1499                 :     }
    1500                 : 
    1501              12 :     if (poFeatureDefn->GetFieldCount() == 0)
    1502               1 :         return OGRERR_NONE;
    1503                 : 
    1504              11 :     OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
    1505              11 :     if (eErr != OGRERR_NONE)
    1506               1 :         return eErr;
    1507                 : 
    1508              10 :     ClearInsertStmt();
    1509              10 :     ResetReading();
    1510                 : 
    1511                 : /* -------------------------------------------------------------------- */
    1512                 : /*      Build list of old fields, and the list of new fields.           */
    1513                 : /* -------------------------------------------------------------------- */
    1514                 :     int iField;
    1515                 :     char *pszNewFieldList, *pszFieldListForSelect;
    1516              10 :     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect);
    1517                 : 
    1518             104 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    1519                 :     {
    1520              42 :         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(panMap[iField]);
    1521                 : 
    1522                 :         sprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
    1523              42 :                  ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
    1524                 : 
    1525                 :         sprintf( pszNewFieldList+strlen(pszNewFieldList),
    1526                 :                 ", '%s' %s", OGRSQLiteEscape(poFldDefn->GetNameRef()).c_str(),
    1527              84 :                 FieldDefnToSQliteFieldDefn(poFldDefn).c_str() );
    1528                 :     }
    1529                 : 
    1530                 : /* -------------------------------------------------------------------- */
    1531                 : /*      Recreate table.                                                 */
    1532                 : /* -------------------------------------------------------------------- */
    1533              10 :     CPLString osErrorMsg;
    1534                 :     osErrorMsg.Printf("Failed to reorder fields from table %s",
    1535              10 :                   poFeatureDefn->GetName());
    1536                 : 
    1537                 :     eErr = RecreateTable(pszFieldListForSelect,
    1538                 :                                 pszNewFieldList,
    1539              10 :                                 osErrorMsg.c_str());
    1540                 : 
    1541              10 :     CPLFree( pszFieldListForSelect );
    1542              10 :     CPLFree( pszNewFieldList );
    1543                 : 
    1544              10 :     if (eErr != OGRERR_NONE)
    1545               0 :         return eErr;
    1546                 : 
    1547                 : /* -------------------------------------------------------------------- */
    1548                 : /*      Finish                                                          */
    1549                 : /* -------------------------------------------------------------------- */
    1550                 : 
    1551              10 :     return poFeatureDefn->ReorderFieldDefns( panMap );
    1552                 : }
    1553                 : 
    1554                 : /************************************************************************/
    1555                 : /*                             BindValues()                             */
    1556                 : /************************************************************************/
    1557                 : 
    1558                 : /* the bBindNullValues is set to TRUE by SetFeature() for UPDATE statements, */
    1559                 : /* and to FALSE by CreateFeature() for INSERT statements; */
    1560                 : 
    1561             473 : OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
    1562                 :                                         sqlite3_stmt* hStmt,
    1563                 :                                         int bBindNullValues )
    1564                 : {
    1565                 :     int rc;
    1566             473 :     sqlite3 *hDB = poDS->GetDB();
    1567                 : 
    1568                 : /* -------------------------------------------------------------------- */
    1569                 : /*      Bind the geometry                                               */
    1570                 : /* -------------------------------------------------------------------- */
    1571             473 :     int nBindField = 1;
    1572                 : 
    1573             473 :     if( osGeomColumn.size() != 0 &&
    1574                 :         eGeomFormat != OSGF_FGF )
    1575                 :     {
    1576             429 :         OGRGeometry* poGeom = poFeature->GetGeometryRef();
    1577             429 :         if ( poGeom != NULL )
    1578                 :         {
    1579             405 :             if ( eGeomFormat == OSGF_WKT )
    1580                 :             {
    1581               2 :                 char *pszWKT = NULL;
    1582               2 :                 poGeom->exportToWkt( &pszWKT );
    1583               2 :                 rc = sqlite3_bind_text( hStmt, nBindField++, pszWKT, -1, CPLFree );
    1584                 :             }
    1585             403 :             else if( eGeomFormat == OSGF_WKB )
    1586                 :             {
    1587             170 :                 int nWKBLen = poGeom->WkbSize();
    1588             170 :                 GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
    1589                 : 
    1590             170 :                 poGeom->exportToWkb( wkbNDR, pabyWKB );
    1591             170 :                 rc = sqlite3_bind_blob( hStmt, nBindField++, pabyWKB, nWKBLen, CPLFree );
    1592                 :             }
    1593             233 :             else if ( eGeomFormat == OSGF_SpatiaLite )
    1594                 :             {
    1595                 :                 int     nBLOBLen;
    1596                 :                 GByte   *pabySLBLOB;
    1597                 : 
    1598             233 :                 if( nSRSId == UNINITIALIZED_SRID )
    1599               0 :                     nSRSId = poDS->GetUndefinedSRID();
    1600                 : 
    1601                 :                 ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR, bHasM,
    1602             233 :                                         bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen );
    1603                 :                 rc = sqlite3_bind_blob( hStmt, nBindField++, pabySLBLOB,
    1604             233 :                                         nBLOBLen, CPLFree );
    1605                 :             }
    1606                 :             else
    1607                 :             {
    1608               0 :                 rc = SQLITE_OK;
    1609               0 :                 CPLAssert(0);
    1610                 :             }
    1611                 :         }
    1612                 :         else
    1613                 :         {
    1614              24 :             if (bBindNullValues)
    1615               2 :                 rc = sqlite3_bind_null( hStmt, nBindField++ );
    1616                 :             else
    1617              22 :                 rc = SQLITE_OK;
    1618                 :         }
    1619                 : 
    1620             429 :         if( rc != SQLITE_OK )
    1621                 :         {
    1622                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1623                 :                       "sqlite3_bind_blob/text() failed:\n  %s",
    1624               0 :                       sqlite3_errmsg(hDB) );
    1625               0 :             return OGRERR_FAILURE;
    1626                 :         }
    1627                 :     }
    1628                 : 
    1629                 : /* -------------------------------------------------------------------- */
    1630                 : /*      Bind field values.                                              */
    1631                 : /* -------------------------------------------------------------------- */
    1632                 :     int iField;
    1633             473 :     int nFieldCount = poFeatureDefn->GetFieldCount();
    1634            1491 :     for( iField = 0; iField < nFieldCount; iField++ )
    1635                 :     {
    1636                 :         const char *pszRawValue;
    1637                 : 
    1638            1018 :         if( !poFeature->IsFieldSet( iField ) )
    1639                 :         {
    1640             342 :             if (bBindNullValues)
    1641               8 :                 rc = sqlite3_bind_null( hStmt, nBindField++ );
    1642                 :             else
    1643             334 :                 rc = SQLITE_OK;
    1644                 :         }
    1645                 :         else
    1646                 :         {
    1647             676 :             switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
    1648                 :             {
    1649                 :                 case OFTInteger:
    1650                 :                 {
    1651             143 :                     int nFieldVal = poFeature->GetFieldAsInteger( iField );
    1652             143 :                     rc = sqlite3_bind_int(hStmt, nBindField++, nFieldVal);
    1653             143 :                     break;
    1654                 :                 }
    1655                 : 
    1656                 :                 case OFTReal:
    1657                 :                 {
    1658             210 :                     double dfFieldVal = poFeature->GetFieldAsDouble( iField );
    1659             210 :                     rc = sqlite3_bind_double(hStmt, nBindField++, dfFieldVal);
    1660             210 :                     break;
    1661                 :                 }
    1662                 : 
    1663                 :                 case OFTBinary:
    1664                 :                 {
    1665              24 :                     int nDataLength = 0;
    1666                 :                     GByte* pabyData =
    1667              24 :                         poFeature->GetFieldAsBinary( iField, &nDataLength );
    1668                 :                     rc = sqlite3_bind_blob(hStmt, nBindField++,
    1669              24 :                                         pabyData, nDataLength, SQLITE_TRANSIENT);
    1670              24 :                     break;
    1671                 :                 }
    1672                 : 
    1673                 :                 case OFTDateTime:
    1674                 :                 {
    1675                 :                     int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZ;
    1676                 :                     poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
    1677               2 :                                                 &nHour, &nMinute, &nSecond, &nTZ);
    1678                 :                     char szBuffer[64];
    1679                 :                     sprintf(szBuffer, "%04d-%02d-%02dT%02d:%02d:%02d",
    1680               2 :                             nYear, nMonth, nDay, nHour, nMinute, nSecond);
    1681                 :                     rc = sqlite3_bind_text(hStmt, nBindField++,
    1682               2 :                                            szBuffer, -1, SQLITE_TRANSIENT);
    1683               2 :                     break;
    1684                 :                 }
    1685                 : 
    1686                 :                 case OFTDate:
    1687                 :                 {
    1688                 :                     int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZ;
    1689                 :                     poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
    1690               2 :                                                 &nHour, &nMinute, &nSecond, &nTZ);
    1691                 :                     char szBuffer[64];
    1692               2 :                     sprintf(szBuffer, "%04d-%02d-%02dT", nYear, nMonth, nDay);
    1693                 :                     rc = sqlite3_bind_text(hStmt, nBindField++,
    1694               2 :                                            szBuffer, -1, SQLITE_TRANSIENT);
    1695               2 :                     break;
    1696                 :                 }
    1697                 : 
    1698                 :                 case OFTTime:
    1699                 :                 {
    1700                 :                     int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZ;
    1701                 :                     poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
    1702               2 :                                                 &nHour, &nMinute, &nSecond, &nTZ);
    1703                 :                     char szBuffer[64];
    1704               2 :                     sprintf(szBuffer, "%02d:%02d:%02d", nHour, nMinute, nSecond);
    1705                 :                     rc = sqlite3_bind_text(hStmt, nBindField++,
    1706               2 :                                            szBuffer, -1, SQLITE_TRANSIENT);
    1707               2 :                     break;
    1708                 :                 }
    1709                 : 
    1710                 :                 default:
    1711                 :                 {
    1712             293 :                     pszRawValue = poFeature->GetFieldAsString( iField );
    1713             293 :                     if( CSLFindString(papszCompressedColumns,
    1714                 :                                       poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) >= 0 )
    1715                 :                     {
    1716              17 :                         size_t nBytesOut = 0;
    1717                 :                         void* pOut = CPLZLibDeflate( pszRawValue,
    1718                 :                                                      strlen(pszRawValue), -1,
    1719                 :                                                      NULL, 0,
    1720              17 :                                                      &nBytesOut );
    1721              17 :                         if( pOut != NULL )
    1722                 :                         {
    1723                 :                             rc = sqlite3_bind_blob(hStmt, nBindField++,
    1724                 :                                                    pOut,
    1725                 :                                                    nBytesOut,
    1726              17 :                                                    CPLFree);
    1727                 :                         }
    1728                 :                         else
    1729               0 :                             rc = SQLITE_ERROR;
    1730                 :                     }
    1731                 :                     else
    1732                 :                     {
    1733                 :                         rc = sqlite3_bind_text(hStmt, nBindField++,
    1734             276 :                                                pszRawValue, -1, SQLITE_TRANSIENT);
    1735                 :                     }
    1736                 :                     break;
    1737                 :                 }
    1738                 :             }
    1739                 :         }
    1740                 : 
    1741            1018 :         if( rc != SQLITE_OK )
    1742                 :         {
    1743                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1744                 :                       "sqlite3_bind_() for column %s failed:\n  %s",
    1745                 :                       poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
    1746               0 :                       sqlite3_errmsg(hDB) );
    1747               0 :             return OGRERR_FAILURE;
    1748                 :         }
    1749                 :     }
    1750                 : 
    1751             473 :     return OGRERR_NONE;
    1752                 : }
    1753                 : 
    1754                 : /************************************************************************/
    1755                 : /*                             SetFeature()                             */
    1756                 : /************************************************************************/
    1757                 : 
    1758              21 : OGRErr OGRSQLiteTableLayer::SetFeature( OGRFeature *poFeature )
    1759                 : 
    1760                 : {
    1761              21 :     if (HasLayerDefnError())
    1762               0 :         return OGRERR_FAILURE;
    1763                 : 
    1764              21 :     if( pszFIDColumn == NULL )
    1765                 :     {
    1766                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1767               0 :                   "SetFeature() without any FID column." );
    1768               0 :         return OGRERR_FAILURE;
    1769                 :     }
    1770                 :     
    1771              21 :     if( poFeature->GetFID() == OGRNullFID )
    1772                 :     {
    1773                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1774               0 :                   "SetFeature() with unset FID fails." );
    1775               0 :         return OGRERR_FAILURE;
    1776                 :     }
    1777                 : 
    1778              21 :     if (!poDS->GetUpdate())
    1779                 :     {
    1780                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1781                 :                   UNSUPPORTED_OP_READ_ONLY,
    1782               0 :                   "SetFeature");
    1783               0 :         return OGRERR_FAILURE;
    1784                 :     }
    1785                 : 
    1786              21 :     sqlite3 *hDB = poDS->GetDB();
    1787              21 :     CPLString      osCommand;
    1788              21 :     int            bNeedComma = FALSE;
    1789                 : 
    1790              21 :     ResetReading();
    1791                 : 
    1792                 : /* -------------------------------------------------------------------- */
    1793                 : /*      Form the UPDATE command.                                        */
    1794                 : /* -------------------------------------------------------------------- */
    1795              21 :     osCommand += CPLSPrintf( "UPDATE '%s' SET ", pszEscapedTableName );
    1796                 : 
    1797                 : /* -------------------------------------------------------------------- */
    1798                 : /*      Add geometry field name.                                        */
    1799                 : /* -------------------------------------------------------------------- */
    1800              21 :     if( osGeomColumn.size() != 0 &&
    1801                 :         eGeomFormat != OSGF_FGF )
    1802                 :     {
    1803              21 :         osCommand += "\"";
    1804              21 :         osCommand += OGRSQLiteEscapeName(osGeomColumn);
    1805              21 :         osCommand += "\" = ?";
    1806                 : 
    1807              21 :         bNeedComma = TRUE;
    1808                 :     }
    1809                 : 
    1810                 : /* -------------------------------------------------------------------- */
    1811                 : /*      Add field names.                                                */
    1812                 : /* -------------------------------------------------------------------- */
    1813                 :     int iField;
    1814              21 :     int nFieldCount = poFeatureDefn->GetFieldCount();
    1815                 : 
    1816              89 :     for( iField = 0; iField < nFieldCount; iField++ )
    1817                 :     {
    1818              68 :         if( bNeedComma )
    1819              68 :             osCommand += ",";
    1820                 : 
    1821              68 :         osCommand += "\"";
    1822              68 :         osCommand += OGRSQLiteEscapeName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef());
    1823              68 :         osCommand += "\" = ?";
    1824                 : 
    1825              68 :         bNeedComma = TRUE;
    1826                 :     }
    1827                 : 
    1828              21 :     if (!bNeedComma)
    1829               0 :         return OGRERR_NONE;
    1830                 : 
    1831                 : /* -------------------------------------------------------------------- */
    1832                 : /*      Merge final command.                                            */
    1833                 : /* -------------------------------------------------------------------- */
    1834              21 :     osCommand += " WHERE \"";
    1835              21 :     osCommand += OGRSQLiteEscapeName(pszFIDColumn);
    1836              21 :     osCommand += CPLSPrintf("\" = %ld", poFeature->GetFID());
    1837                 : 
    1838                 : /* -------------------------------------------------------------------- */
    1839                 : /*      Prepare the statement.                                          */
    1840                 : /* -------------------------------------------------------------------- */
    1841                 :     int rc;
    1842                 :     sqlite3_stmt *hUpdateStmt;
    1843                 : 
    1844                 : #ifdef DEBUG
    1845              21 :     CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
    1846                 : #endif
    1847                 : 
    1848              21 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
    1849              21 :     if( rc != SQLITE_OK )
    1850                 :     {
    1851                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1852                 :                   "In SetFeature(): sqlite3_prepare(%s):\n  %s",
    1853               0 :                   osCommand.c_str(), sqlite3_errmsg(hDB) );
    1854                 : 
    1855               0 :         return OGRERR_FAILURE;
    1856                 :     }
    1857                 : 
    1858                 : /* -------------------------------------------------------------------- */
    1859                 : /*      Bind values.                                                   */
    1860                 : /* -------------------------------------------------------------------- */
    1861              21 :     OGRErr eErr = BindValues( poFeature, hUpdateStmt, TRUE );
    1862              21 :     if (eErr != OGRERR_NONE)
    1863                 :     {
    1864               0 :         sqlite3_finalize( hUpdateStmt );
    1865               0 :         return eErr;
    1866                 :     }
    1867                 : 
    1868                 : /* -------------------------------------------------------------------- */
    1869                 : /*      Execute the update.                                             */
    1870                 : /* -------------------------------------------------------------------- */
    1871              21 :     rc = sqlite3_step( hUpdateStmt );
    1872                 : 
    1873              21 :     if( rc != SQLITE_OK && rc != SQLITE_DONE )
    1874                 :     {
    1875                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1876                 :                   "sqlite3_step() failed:\n  %s",
    1877               0 :                   sqlite3_errmsg(hDB) );
    1878                 : 
    1879               0 :         sqlite3_finalize( hUpdateStmt );
    1880               0 :         return OGRERR_FAILURE;
    1881                 :     }
    1882                 : 
    1883              21 :     sqlite3_finalize( hUpdateStmt );
    1884                 : 
    1885              21 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
    1886              22 :     if( bCachedExtentIsValid &&
    1887               1 :         poGeom != NULL && !poGeom->IsEmpty() )
    1888                 :     {
    1889               1 :         OGREnvelope sGeomEnvelope;
    1890               1 :         poGeom->getEnvelope(&sGeomEnvelope);
    1891               1 :         oCachedExtent.Merge(sGeomEnvelope);
    1892                 :     }
    1893              21 :     bStatisticsNeedsToBeFlushed = TRUE;
    1894                 : 
    1895              21 :     return OGRERR_NONE;
    1896                 : }
    1897                 : 
    1898                 : /************************************************************************/
    1899                 : /*                           CreateFeature()                            */
    1900                 : /************************************************************************/
    1901                 : 
    1902             452 : OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
    1903                 : 
    1904                 : {
    1905             452 :     sqlite3 *hDB = poDS->GetDB();
    1906             452 :     CPLString      osCommand;
    1907             452 :     CPLString      osValues;
    1908             452 :     int            bNeedComma = FALSE;
    1909                 : 
    1910             452 :     if (HasLayerDefnError())
    1911               0 :         return OGRERR_FAILURE;
    1912                 : 
    1913             452 :     if (!poDS->GetUpdate())
    1914                 :     {
    1915                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1916                 :                   UNSUPPORTED_OP_READ_ONLY,
    1917               0 :                   "CreateFeature");
    1918               0 :         return OGRERR_FAILURE;
    1919                 :     }
    1920                 : 
    1921             452 :     ResetReading();
    1922                 : 
    1923                 : /* -------------------------------------------------------------------- */
    1924                 : /*      Form the INSERT command.                                        */
    1925                 : /* -------------------------------------------------------------------- */
    1926             452 :     osCommand += CPLSPrintf( "INSERT INTO '%s' (", pszEscapedTableName );
    1927                 : 
    1928                 : /* -------------------------------------------------------------------- */
    1929                 : /*      Add FID if we have a cleartext FID column.                      */
    1930                 : /* -------------------------------------------------------------------- */
    1931             452 :     if( pszFIDColumn != NULL // && !EQUAL(pszFIDColumn,"OGC_FID") 
    1932                 :         && poFeature->GetFID() != OGRNullFID )
    1933                 :     {
    1934             100 :         osCommand += "\"";
    1935             100 :         osCommand += OGRSQLiteEscapeName(pszFIDColumn);
    1936             100 :         osCommand += "\"";
    1937                 : 
    1938             100 :         osValues += CPLSPrintf( "%ld", poFeature->GetFID() );
    1939             100 :         bNeedComma = TRUE;
    1940                 :     }
    1941                 : 
    1942                 : /* -------------------------------------------------------------------- */
    1943                 : /*      Add geometry.                                                   */
    1944                 : /* -------------------------------------------------------------------- */
    1945             452 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
    1946                 : 
    1947             452 :     if( osGeomColumn.size() != 0 &&
    1948                 :         poGeom != NULL &&
    1949                 :         eGeomFormat != OSGF_FGF )
    1950                 :     {
    1951                 : 
    1952             386 :         if( bNeedComma )
    1953                 :         {
    1954             100 :             osCommand += ",";
    1955             100 :             osValues += ",";
    1956                 :         }
    1957                 : 
    1958             386 :         osCommand += "\"";
    1959             386 :         osCommand += OGRSQLiteEscapeName(osGeomColumn);
    1960             386 :         osCommand += "\"";
    1961                 : 
    1962             386 :         osValues += "?";
    1963                 : 
    1964             386 :         bNeedComma = TRUE;
    1965                 :     }
    1966                 : 
    1967                 : /* -------------------------------------------------------------------- */
    1968                 : /*      Add field values.                                               */
    1969                 : /* -------------------------------------------------------------------- */
    1970                 :     int iField;
    1971             452 :     int nFieldCount = poFeatureDefn->GetFieldCount();
    1972                 : 
    1973            1402 :     for( iField = 0; iField < nFieldCount; iField++ )
    1974                 :     {
    1975             950 :         if( !poFeature->IsFieldSet( iField ) )
    1976             334 :             continue;
    1977                 : 
    1978             616 :         if( bNeedComma )
    1979                 :         {
    1980             552 :             osCommand += ",";
    1981             552 :             osValues += ",";
    1982                 :         }
    1983                 : 
    1984             616 :         osCommand += "\"";
    1985             616 :         osCommand += OGRSQLiteEscapeName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef());
    1986             616 :         osCommand += "\"";
    1987                 : 
    1988             616 :         osValues += "?";
    1989                 : 
    1990             616 :         bNeedComma = TRUE;
    1991                 :     }
    1992                 : 
    1993                 : /* -------------------------------------------------------------------- */
    1994                 : /*      Merge final command.                                            */
    1995                 : /* -------------------------------------------------------------------- */
    1996             452 :     osCommand += ") VALUES (";
    1997             452 :     osCommand += osValues;
    1998             452 :     osCommand += ")";
    1999                 : 
    2000             452 :     if (bNeedComma == FALSE)
    2001               2 :         osCommand = CPLSPrintf( "INSERT INTO '%s' DEFAULT VALUES", pszEscapedTableName );
    2002                 : 
    2003                 : /* -------------------------------------------------------------------- */
    2004                 : /*      Prepare the statement.                                          */
    2005                 : /* -------------------------------------------------------------------- */
    2006                 :     int rc;
    2007                 : 
    2008             452 :     if (hInsertStmt == NULL ||
    2009                 :         osCommand != osLastInsertStmt)
    2010                 :     {
    2011                 :     #ifdef DEBUG
    2012             241 :         CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
    2013                 :     #endif
    2014                 : 
    2015             241 :         ClearInsertStmt();
    2016             241 :         osLastInsertStmt = osCommand;
    2017                 : 
    2018                 : #ifdef HAVE_SQLITE3_PREPARE_V2
    2019             241 :         rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
    2020                 : #else
    2021                 :         rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
    2022                 : #endif
    2023             241 :         if( rc != SQLITE_OK )
    2024                 :         {
    2025                 :             CPLError( CE_Failure, CPLE_AppDefined,
    2026                 :                     "In CreateFeature(): sqlite3_prepare(%s):\n  %s",
    2027               0 :                     osCommand.c_str(), sqlite3_errmsg(hDB) );
    2028                 : 
    2029               0 :             ClearInsertStmt();
    2030               0 :             return OGRERR_FAILURE;
    2031                 :         }
    2032                 :     }
    2033                 : 
    2034                 : /* -------------------------------------------------------------------- */
    2035                 : /*      Bind values.                                                   */
    2036                 : /* -------------------------------------------------------------------- */
    2037             452 :     OGRErr eErr = BindValues( poFeature, hInsertStmt, FALSE );
    2038             452 :     if (eErr != OGRERR_NONE)
    2039                 :     {
    2040               0 :         sqlite3_reset( hInsertStmt );
    2041               0 :         return eErr;
    2042                 :     }
    2043                 : 
    2044                 : /* -------------------------------------------------------------------- */
    2045                 : /*      Execute the insert.                                             */
    2046                 : /* -------------------------------------------------------------------- */
    2047             452 :     rc = sqlite3_step( hInsertStmt );
    2048                 : 
    2049             452 :     if( rc != SQLITE_OK && rc != SQLITE_DONE )
    2050                 :     {
    2051                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2052                 :                   "sqlite3_step() failed:\n  %s (%d)", 
    2053               0 :                   sqlite3_errmsg(hDB), rc );
    2054               0 :         sqlite3_reset( hInsertStmt );
    2055               0 :         return OGRERR_FAILURE;
    2056                 :     }
    2057                 : 
    2058                 : /* -------------------------------------------------------------------- */
    2059                 : /*      Capture the FID/rowid.                                          */
    2060                 : /* -------------------------------------------------------------------- */
    2061             452 :     const sqlite_int64 nFID = sqlite3_last_insert_rowid( hDB );
    2062             452 :     if(nFID > 0)
    2063                 :     {
    2064             450 :         poFeature->SetFID( (long)nFID ); /* Possible truncation if nFID is 64bit */
    2065                 :     }
    2066                 : 
    2067             452 :     sqlite3_reset( hInsertStmt );
    2068                 : 
    2069             793 :     if( (bCachedExtentIsValid || nFeatureCount == 0) &&
    2070             341 :         poGeom != NULL && !poGeom->IsEmpty() )
    2071                 :     {
    2072             317 :         OGREnvelope sGeomEnvelope;
    2073             317 :         poGeom->getEnvelope(&sGeomEnvelope);
    2074             317 :         oCachedExtent.Merge(sGeomEnvelope);
    2075             317 :         bCachedExtentIsValid = TRUE;
    2076             317 :         bStatisticsNeedsToBeFlushed = TRUE;
    2077                 :     }
    2078             452 :     if( nFeatureCount >= 0 )
    2079                 :     {
    2080             376 :         bStatisticsNeedsToBeFlushed = TRUE;
    2081             376 :         nFeatureCount ++;
    2082                 :     }
    2083                 : 
    2084             452 :     return OGRERR_NONE;
    2085                 : }
    2086                 : 
    2087                 : /************************************************************************/
    2088                 : /*                           DeleteFeature()                            */
    2089                 : /************************************************************************/
    2090                 : 
    2091               8 : OGRErr OGRSQLiteTableLayer::DeleteFeature( long nFID )
    2092                 : 
    2093                 : {
    2094               8 :     CPLString      osSQL;
    2095                 :     int            rc;
    2096               8 :     char          *pszErrMsg = NULL;
    2097                 : 
    2098               8 :     if (HasLayerDefnError())
    2099               0 :         return OGRERR_FAILURE;
    2100                 : 
    2101               8 :     if( pszFIDColumn == NULL )
    2102                 :     {
    2103                 :         CPLError( CE_Failure, CPLE_NotSupported,
    2104               0 :                   "Can't delete feature on a layer without FID column.");
    2105               0 :         return OGRERR_FAILURE;
    2106                 :     }
    2107                 : 
    2108               8 :     if (!poDS->GetUpdate())
    2109                 :     {
    2110                 :         CPLError( CE_Failure, CPLE_NotSupported,
    2111                 :                   UNSUPPORTED_OP_READ_ONLY,
    2112               0 :                   "DeleteFeature");
    2113               0 :         return OGRERR_FAILURE;
    2114                 :     }
    2115                 : 
    2116               8 :     ResetReading();
    2117                 : 
    2118                 :     osSQL.Printf( "DELETE FROM '%s' WHERE \"%s\" = %ld",
    2119                 :                   pszEscapedTableName,
    2120               8 :                   OGRSQLiteEscapeName(pszFIDColumn).c_str(), nFID );
    2121                 : 
    2122               8 :     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
    2123                 : 
    2124               8 :     rc = sqlite3_exec( poDS->GetDB(), osSQL, NULL, NULL, &pszErrMsg );
    2125               8 :     if( rc != SQLITE_OK )
    2126                 :     {
    2127                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2128                 :                     "In DeleteFeature(): sqlite3_exec(%s):\n  %s",
    2129               0 :                     osSQL.c_str(), pszErrMsg );
    2130               0 :         sqlite3_free( pszErrMsg );
    2131               0 :         return OGRERR_FAILURE;
    2132                 :     }
    2133                 : 
    2134               8 :     int nChanged = sqlite3_changes( poDS->GetDB() );
    2135                 : 
    2136               8 :     if( nChanged == 1 )
    2137                 :     {
    2138               8 :         bCachedExtentIsValid = FALSE;
    2139               8 :         nFeatureCount --;
    2140               8 :         bStatisticsNeedsToBeFlushed = TRUE;
    2141                 :     }
    2142                 : 
    2143               8 :     return OGRERR_NONE;
    2144                 : }
    2145                 : 
    2146                 : /************************************************************************/
    2147                 : /*                         CreateSpatialIndex()                         */
    2148                 : /************************************************************************/
    2149                 : 
    2150              70 : int OGRSQLiteTableLayer::CreateSpatialIndex()
    2151                 : {
    2152              70 :     CPLString osCommand;
    2153                 : 
    2154                 :     osCommand.Printf("SELECT CreateSpatialIndex('%s', '%s')",
    2155              70 :                      pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
    2156                 : 
    2157              70 :     char* pszErrMsg = NULL;
    2158              70 :     sqlite3 *hDB = poDS->GetDB();
    2159                 : #ifdef DEBUG
    2160              70 :     CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
    2161                 : #endif
    2162              70 :     int rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
    2163              70 :     if( rc != SQLITE_OK )
    2164                 :     {
    2165                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2166               0 :                 "Unable to create spatial index:\n%s", pszErrMsg );
    2167               0 :         sqlite3_free( pszErrMsg );
    2168               0 :         return FALSE;
    2169                 :     }
    2170                 : 
    2171              70 :     bHasSpatialIndex = TRUE;
    2172              70 :     return TRUE;
    2173                 : }
    2174                 : 
    2175                 : /************************************************************************/
    2176                 : /*                           HasSpatialIndex()                          */
    2177                 : /************************************************************************/
    2178                 : 
    2179              68 : int OGRSQLiteTableLayer::HasSpatialIndex()
    2180                 : {
    2181              68 :     if( bDeferedSpatialIndexCreation )
    2182                 :     {
    2183               0 :         bDeferedSpatialIndexCreation = FALSE;
    2184               0 :         bHasSpatialIndex = CreateSpatialIndex();
    2185                 :     }
    2186                 : 
    2187              68 :     return bHasSpatialIndex;
    2188                 : }
    2189                 : 
    2190                 : /************************************************************************/
    2191                 : /*                          InitFeatureCount()                          */
    2192                 : /************************************************************************/
    2193                 : 
    2194             120 : void OGRSQLiteTableLayer::InitFeatureCount()
    2195                 : {
    2196             120 :     nFeatureCount = 0;
    2197             120 :     bStatisticsNeedsToBeFlushed = TRUE;
    2198             120 : }
    2199                 : 
    2200                 : /************************************************************************/
    2201                 : /*                 InvalidateCachedFeatureCountAndExtent()              */
    2202                 : /************************************************************************/
    2203                 : 
    2204             261 : void OGRSQLiteTableLayer::InvalidateCachedFeatureCountAndExtent()
    2205                 : {
    2206             261 :     nFeatureCount = -1;
    2207             261 :     bCachedExtentIsValid = FALSE;
    2208             261 :     bStatisticsNeedsToBeFlushed = TRUE;
    2209             261 : }
    2210                 : 
    2211                 : /************************************************************************/
    2212                 : /*                     DoStatisticsNeedToBeFlushed()                    */
    2213                 : /************************************************************************/
    2214                 : 
    2215               3 : int OGRSQLiteTableLayer::DoStatisticsNeedToBeFlushed()
    2216                 : {
    2217                 :     return bStatisticsNeedsToBeFlushed &&
    2218                 :            poDS->IsSpatialiteDB() &&
    2219               3 :            OGRSQLiteIsSpatialiteLoaded();
    2220                 : }
    2221                 : 
    2222                 : /************************************************************************/
    2223                 : /*                     ForceStatisticsToBeFlushed()                     */
    2224                 : /************************************************************************/
    2225                 : 
    2226               3 : void OGRSQLiteTableLayer::ForceStatisticsToBeFlushed()
    2227                 : {
    2228               3 :     bStatisticsNeedsToBeFlushed = TRUE;
    2229               3 : }
    2230                 : 
    2231                 : /************************************************************************/
    2232                 : /*                         AreStatisticsValid()                         */
    2233                 : /************************************************************************/
    2234                 : 
    2235               3 : int OGRSQLiteTableLayer::AreStatisticsValid()
    2236                 : {
    2237               3 :     return nFeatureCount >= 0;
    2238                 : }
    2239                 : 
    2240                 : /************************************************************************/
    2241                 : /*                     LoadStatisticsSpatialite4DB()                    */
    2242                 : /************************************************************************/
    2243                 : 
    2244               4 : void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
    2245                 : {
    2246               4 :     CPLString osSQL;
    2247               4 :     CPLString osLastEvtDate;
    2248                 :     osSQL.Printf("SELECT MAX(last_insert, last_update, last_delete) FROM geometry_columns_time WHERE "
    2249                 :                  "f_table_name = '%s' AND f_geometry_column = '%s'",
    2250               4 :                  pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
    2251                 : 
    2252               4 :     sqlite3 *hDB = poDS->GetDB();
    2253               4 :     int nRowCount = 0, nColCount = 0;
    2254               4 :     char **papszResult = NULL;
    2255                 : 
    2256                 :     sqlite3_get_table( hDB, osSQL.c_str(), &papszResult,
    2257               4 :                        &nRowCount, &nColCount, NULL );
    2258                 : 
    2259                 :     /* Make it a Unix timestamp */
    2260                 :     int nYear, nMonth, nDay, nHour, nMinute;
    2261                 :     float fSecond;
    2262               6 :     if( nRowCount == 1 && nColCount == 1 && papszResult[1] != NULL &&
    2263               2 :         sscanf( papszResult[1], "%04d-%02d-%02dT%02d:%02d:%f",
    2264                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond ) == 6 )
    2265                 :     {
    2266               2 :         osLastEvtDate = papszResult[1];
    2267                 :     }
    2268                 : 
    2269               4 :     sqlite3_free_table( papszResult );
    2270               4 :     papszResult = NULL;
    2271                 : 
    2272               4 :     if( osLastEvtDate.size() == 0 )
    2273                 :         return;
    2274                 : 
    2275                 :     osSQL.Printf("SELECT last_verified, row_count, extent_min_x, extent_min_y, "
    2276                 :                  "extent_max_x, extent_max_y FROM geometry_columns_statistics WHERE "
    2277                 :                  "f_table_name = '%s' AND f_geometry_column = '%s'",
    2278               2 :                  pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
    2279                 : 
    2280               2 :     nRowCount = 0;
    2281               2 :     nColCount = 0;
    2282                 :     sqlite3_get_table( hDB, osSQL.c_str(), &papszResult,
    2283               2 :                        &nRowCount, &nColCount, NULL );
    2284                 : 
    2285               4 :     if( nRowCount == 1 && nColCount == 6 && papszResult[6] != NULL &&
    2286               2 :         sscanf( papszResult[6], "%04d-%02d-%02dT%02d:%02d:%f",
    2287                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond ) == 6 )
    2288                 :     {
    2289               2 :         CPLString osLastVerified(papszResult[6]);
    2290                 : 
    2291                 :         /* Check that the information in geometry_columns_statistics is more */
    2292                 :         /* recent than geometry_columns_time */
    2293               2 :         if( osLastVerified.compare(osLastEvtDate) > 0 )
    2294                 :         {
    2295               2 :             char **papszRow = papszResult + 6;
    2296               2 :             const char* pszRowCount = papszRow[1];
    2297               2 :             const char* pszMinX = papszRow[2];
    2298               2 :             const char* pszMinY = papszRow[3];
    2299               2 :             const char* pszMaxX = papszRow[4];
    2300               2 :             const char* pszMaxY = papszRow[5];
    2301                 : 
    2302               2 :             CPLDebug("SQLITE",  "Loading statistics for %s", pszTableName);
    2303                 : 
    2304               2 :             if( pszRowCount != NULL )
    2305                 :             {
    2306               2 :                 nFeatureCount = (GIntBig) CPLScanUIntBig( pszRowCount, 32 );
    2307               2 :                 if( nFeatureCount == 0)
    2308                 :                 {
    2309               0 :                     nFeatureCount = -1;
    2310               0 :                     pszMinX = NULL;
    2311                 :                 }
    2312                 :                 else
    2313                 :                 {
    2314                 :                     CPLDebug("SQLite", "Layer %s feature count : " CPL_FRMT_GIB,
    2315               2 :                                 pszTableName, nFeatureCount);
    2316                 :                 }
    2317                 :             }
    2318                 : 
    2319               2 :             if( pszMinX != NULL && pszMinY != NULL &&
    2320                 :                 pszMaxX != NULL && pszMaxY != NULL )
    2321                 :             {
    2322               2 :                 bCachedExtentIsValid = TRUE;
    2323               2 :                 oCachedExtent.MinX = CPLAtof(pszMinX);
    2324               2 :                 oCachedExtent.MinY = CPLAtof(pszMinY);
    2325               2 :                 oCachedExtent.MaxX = CPLAtof(pszMaxX);
    2326               2 :                 oCachedExtent.MaxY = CPLAtof(pszMaxY);
    2327                 :                 CPLDebug("SQLite", "Layer %s extent : %s,%s,%s,%s",
    2328               2 :                             pszTableName, pszMinX,pszMinY,pszMaxX,pszMaxY);
    2329                 :             }
    2330               2 :         }
    2331                 :     }
    2332                 : 
    2333               2 :     sqlite3_free_table( papszResult );
    2334               2 :     papszResult = NULL;
    2335                 : }
    2336                 : 
    2337                 : /************************************************************************/
    2338                 : /*                          LoadStatistics()                            */
    2339                 : /************************************************************************/
    2340                 : 
    2341             737 : void OGRSQLiteTableLayer::LoadStatistics()
    2342                 : {
    2343             737 :     if( !poDS->IsSpatialiteDB() || !OGRSQLiteIsSpatialiteLoaded() )
    2344             327 :         return;
    2345                 : 
    2346             410 :     if( poDS->HasSpatialite4Layout() )
    2347                 :     {
    2348               4 :         LoadStatisticsSpatialite4DB();
    2349               4 :         return;
    2350                 :     }
    2351                 : 
    2352             406 :     GIntBig nFileTimestamp = poDS->GetFileTimestamp();
    2353             406 :     if( nFileTimestamp == 0 )
    2354              71 :         return;
    2355                 : 
    2356                 :     /* Find the most recent event in the 'spatialite_history' that is */
    2357                 :     /* a UpdateLayerStatistics event on all tables and geometry columns */
    2358             335 :     CPLString osSQL;
    2359                 :     osSQL.Printf("SELECT MAX(timestamp) FROM spatialite_history WHERE "
    2360                 :                  "((table_name = '%s' AND geometry_column = '%s') OR "
    2361                 :                  "(table_name = 'ALL-TABLES' AND geometry_column = 'ALL-GEOMETRY-COLUMNS')) AND "
    2362                 :                  "event = 'UpdateLayerStatistics'",
    2363             335 :                  pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
    2364                 : 
    2365             335 :     sqlite3 *hDB = poDS->GetDB();
    2366             335 :     int nRowCount = 0, nColCount = 0;
    2367             335 :     char **papszResult = NULL, *pszErrMsg = NULL;
    2368                 : 
    2369                 :     sqlite3_get_table( hDB, osSQL.c_str(), &papszResult,
    2370             335 :                        &nRowCount, &nColCount, &pszErrMsg );
    2371                 : 
    2372                 :     /* Make it a Unix timestamp */
    2373                 :     int nYear, nMonth, nDay, nHour, nMinute, nSecond;
    2374                 :     struct tm brokendown;
    2375             335 :     GIntBig nTS = -1;
    2376             621 :     if( nRowCount >= 1 && nColCount == 1 && papszResult[1] != NULL &&
    2377             286 :         sscanf( papszResult[1], "%04d-%02d-%02d %02d:%02d:%02d",
    2378                 :                 &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond ) == 6 )
    2379                 :     {
    2380             286 :         brokendown.tm_year = nYear - 1900;
    2381             286 :         brokendown.tm_mon = nMonth - 1;
    2382             286 :         brokendown.tm_mday = nDay;
    2383             286 :         brokendown.tm_hour = nHour;
    2384             286 :         brokendown.tm_min = nMinute;
    2385             286 :         brokendown.tm_sec = nSecond;
    2386             286 :         nTS = CPLYMDHMSToUnixTime(&brokendown);
    2387                 :     }
    2388                 : 
    2389                 :     /* If it is equal to the modified timestamp of the DB (as a file) */
    2390                 :     /* then we can safely use the data from the layer_statistics, since */
    2391                 :     /* it will be up-to-date */
    2392             335 :     if( nFileTimestamp == nTS || nFileTimestamp == nTS + 1 )
    2393                 :     {
    2394                 :         osSQL.Printf("SELECT row_count, extent_min_x, extent_min_y, extent_max_x, extent_max_y "
    2395                 :                         "FROM layer_statistics WHERE table_name = '%s' AND geometry_column = '%s'",
    2396             286 :                         pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
    2397                 : 
    2398             286 :         sqlite3_free_table( papszResult );
    2399             286 :         papszResult = NULL;
    2400                 : 
    2401                 :         sqlite3_get_table( hDB, osSQL.c_str(), &papszResult,
    2402             286 :                             &nRowCount, &nColCount, &pszErrMsg );
    2403                 : 
    2404             286 :         if( nRowCount == 1 )
    2405                 :         {
    2406             126 :             char **papszRow = papszResult + 5;
    2407             126 :             const char* pszRowCount = papszRow[0];
    2408             126 :             const char* pszMinX = papszRow[1];
    2409             126 :             const char* pszMinY = papszRow[2];
    2410             126 :             const char* pszMaxX = papszRow[3];
    2411             126 :             const char* pszMaxY = papszRow[4];
    2412                 : 
    2413                 :             CPLDebug("SQLITE", "File timestamp matches layer statistics timestamp. "
    2414             126 :                         "Loading statistics for %s", pszTableName);
    2415                 : 
    2416             126 :             if( pszRowCount != NULL )
    2417                 :             {
    2418             126 :                 nFeatureCount = (GIntBig) CPLScanUIntBig( pszRowCount, 32 );
    2419                 :                 CPLDebug("SQLite", "Layer %s feature count : " CPL_FRMT_GIB,
    2420             126 :                             pszTableName, nFeatureCount);
    2421                 :             }
    2422                 : 
    2423             126 :             if( pszMinX != NULL && pszMinY != NULL &&
    2424                 :                 pszMaxX != NULL && pszMaxY != NULL )
    2425                 :             {
    2426              88 :                 bCachedExtentIsValid = TRUE;
    2427              88 :                 oCachedExtent.MinX = CPLAtof(pszMinX);
    2428              88 :                 oCachedExtent.MinY = CPLAtof(pszMinY);
    2429              88 :                 oCachedExtent.MaxX = CPLAtof(pszMaxX);
    2430              88 :                 oCachedExtent.MaxY = CPLAtof(pszMaxY);
    2431                 :                 CPLDebug("SQLite", "Layer %s extent : %s,%s,%s,%s",
    2432              88 :                             pszTableName, pszMinX,pszMinY,pszMaxX,pszMaxY);
    2433                 :             }
    2434                 :         }
    2435                 :     }
    2436                 : 
    2437             335 :     if( pszErrMsg )
    2438              12 :         sqlite3_free( pszErrMsg );
    2439                 : 
    2440             335 :     sqlite3_free_table( papszResult );
    2441                 : }
    2442                 : 
    2443                 : /************************************************************************/
    2444                 : /*                          SaveStatistics()                            */
    2445                 : /************************************************************************/
    2446                 : 
    2447             347 : int OGRSQLiteTableLayer::SaveStatistics()
    2448                 : {
    2449             347 :     if( !bStatisticsNeedsToBeFlushed || !poDS->IsSpatialiteDB()  || !OGRSQLiteIsSpatialiteLoaded() )
    2450             231 :         return -1;
    2451                 : 
    2452             116 :     CPLString osSQL;
    2453             116 :     sqlite3 *hDB = poDS->GetDB();
    2454             116 :     char* pszErrMsg = NULL;
    2455                 : 
    2456             116 :     if( nFeatureCount >= 0 )
    2457                 :     {
    2458                 :         /* Update or add entry in the layer_statistics table */
    2459              95 :         if( bCachedExtentIsValid )
    2460                 :         {
    2461                 :             osSQL.Printf("INSERT OR REPLACE INTO layer_statistics (raster_layer, "
    2462                 :                             "table_name, geometry_column, row_count, extent_min_x, "
    2463                 :                             "extent_min_y, extent_max_x, extent_max_y) VALUES ("
    2464                 :                             "0, '%s', '%s', " CPL_FRMT_GIB ", %.18g, %.18g, %.18g, %.18g)",
    2465                 :                             pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
    2466                 :                             nFeatureCount,
    2467                 :                             oCachedExtent.MinX, oCachedExtent.MinY,
    2468              76 :                             oCachedExtent.MaxX, oCachedExtent.MaxY);
    2469                 :         }
    2470                 :         else
    2471                 :         {
    2472                 :             osSQL.Printf("INSERT OR REPLACE INTO layer_statistics (raster_layer, "
    2473                 :                             "table_name, geometry_column, row_count, extent_min_x, "
    2474                 :                             "extent_min_y, extent_max_x, extent_max_y) VALUES ("
    2475                 :                             "0, '%s', '%s', " CPL_FRMT_GIB ", NULL, NULL, NULL, NULL)",
    2476                 :                             pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str(),
    2477              19 :                             nFeatureCount);
    2478                 :         }
    2479                 :     }
    2480                 :     else
    2481                 :     {
    2482                 :         /* Remove any existing entry in layer_statistics if for some reason */
    2483                 :         /* we know that it will out-of-sync */
    2484                 :         osSQL.Printf("DELETE FROM layer_statistics WHERE "
    2485                 :                      "table_name = '%s' AND geometry_column = '%s'",
    2486              21 :                      pszEscapedTableName, OGRSQLiteEscape(osGeomColumn).c_str());
    2487                 :     }
    2488                 : 
    2489             116 :     int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg );
    2490             116 :     if( rc != SQLITE_OK )
    2491                 :     {
    2492              13 :         CPLDebug("SQLITE", "Error %s", pszErrMsg ? pszErrMsg : "unknown");
    2493              13 :         sqlite3_free( pszErrMsg );
    2494              13 :         return FALSE;
    2495                 :     }
    2496                 :     else
    2497             103 :         return TRUE;
    2498                 : }
    2499                 : 
    2500                 : /************************************************************************/
    2501                 : /*                      SetCompressedColumns()                          */
    2502                 : /************************************************************************/
    2503                 : 
    2504             120 : void OGRSQLiteTableLayer::SetCompressedColumns( const char* pszCompressedColumns )
    2505                 : {
    2506                 :     papszCompressedColumns = CSLTokenizeString2( pszCompressedColumns, ",",
    2507             120 :                                                  CSLT_HONOURSTRINGS );
    2508             120 : }

Generated by: LCOV version 1.7