LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitedatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1139 850 74.6 %
Date: 2013-03-30 Functions: 44 40 90.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqlitedatasource.cpp 25725 2013-03-10 11:19:30Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRSQLiteDataSource class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  *
      10                 :  * Contributor: Alessandro Furieri, a.furieri@lqt.it
      11                 :  * Portions of this module properly supporting SpatiaLite Table/Geom creation
      12                 :  * Developed for Faunalia ( http://www.faunalia.it) with funding from 
      13                 :  * Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED AMBIENTALE
      14                 :  *
      15                 :  ******************************************************************************
      16                 :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
      17                 :  *
      18                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      19                 :  * copy of this software and associated documentation files (the "Software"),
      20                 :  * to deal in the Software without restriction, including without limitation
      21                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      22                 :  * and/or sell copies of the Software, and to permit persons to whom the
      23                 :  * Software is furnished to do so, subject to the following conditions:
      24                 :  *
      25                 :  * The above copyright notice and this permission notice shall be included
      26                 :  * in all copies or substantial portions of the Software.
      27                 :  *
      28                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      29                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      30                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      31                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      32                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      33                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      34                 :  * DEALINGS IN THE SOFTWARE.
      35                 :  ****************************************************************************/
      36                 : 
      37                 : #include "ogr_sqlite.h"
      38                 : #include "cpl_conv.h"
      39                 : #include "cpl_string.h"
      40                 : #include "cpl_hash_set.h"
      41                 : #include "cpl_csv.h"
      42                 : #include "ogrsqlitevirtualogr.h"
      43                 : 
      44                 : #ifdef HAVE_SPATIALITE
      45                 : #include "spatialite.h"
      46                 : #endif
      47                 : 
      48                 : static int bSpatialiteLoaded = FALSE;
      49                 : 
      50                 : CPL_CVSID("$Id: ogrsqlitedatasource.cpp 25725 2013-03-10 11:19:30Z rouault $");
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                      OGRSQLiteInitSpatialite()                       */
      54                 : /************************************************************************/
      55                 : 
      56             604 : static int OGRSQLiteInitSpatialite()
      57                 : {
      58                 : /* -------------------------------------------------------------------- */
      59                 : /*      Try loading SpatiaLite.                                         */
      60                 : /* -------------------------------------------------------------------- */
      61                 : #ifdef HAVE_SPATIALITE
      62             604 :     if (!bSpatialiteLoaded && CSLTestBoolean(CPLGetConfigOption("SPATIALITE_LOAD", "TRUE")))
      63                 :     {
      64              13 :         bSpatialiteLoaded = TRUE;
      65              13 :         spatialite_init(CSLTestBoolean(CPLGetConfigOption("SPATIALITE_INIT_VERBOSE", "FALSE")));
      66                 :     }
      67                 : #endif
      68             604 :     return bSpatialiteLoaded;
      69                 : }
      70                 : 
      71                 : /************************************************************************/
      72                 : /*                     OGRSQLiteIsSpatialiteLoaded()                    */
      73                 : /************************************************************************/
      74                 : 
      75            3609 : int OGRSQLiteIsSpatialiteLoaded()
      76                 : {
      77            3609 :     return bSpatialiteLoaded;
      78                 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*               OGRSQLiteGetSpatialiteVersionNumber()                  */
      82                 : /************************************************************************/
      83                 : 
      84            2025 : int OGRSQLiteGetSpatialiteVersionNumber()
      85                 : {
      86            2025 :     int v = 0;
      87                 : #ifdef HAVE_SPATIALITE
      88            2025 :     if( bSpatialiteLoaded )
      89                 :     {
      90            1945 :         v = (int)(( atof( spatialite_version() ) + 0.001 )  * 10.0);
      91                 :     }
      92                 : #endif
      93            2025 :     return v;
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                        OGRSQLiteDataSource()                         */
      98                 : /************************************************************************/
      99                 : 
     100             754 : OGRSQLiteDataSource::OGRSQLiteDataSource()
     101                 : 
     102                 : {
     103             754 :     pszName = NULL;
     104             754 :     papoLayers = NULL;
     105             754 :     nLayers = 0;
     106                 : 
     107             754 :     nSoftTransactionLevel = 0;
     108                 : 
     109             754 :     nKnownSRID = 0;
     110             754 :     panSRID = NULL;
     111             754 :     papoSRS = NULL;
     112                 : 
     113             754 :     bHaveGeometryColumns = FALSE;
     114             754 :     bIsSpatiaLiteDB = FALSE;
     115             754 :     bSpatialite4Layout = FALSE;
     116             754 :     bUpdate = FALSE;
     117                 : 
     118             754 :     nUndefinedSRID = -1; /* will be changed to 0 if Spatialite >= 4.0 detected */
     119                 : 
     120             754 :     hDB = NULL;
     121                 : 
     122                 : #ifdef HAVE_SQLITE_VFS
     123             754 :     pMyVFS = NULL;
     124                 : #endif
     125                 : 
     126             754 :     fpMainFile = NULL; /* Do not close ! The VFS layer will do it for us */
     127             754 :     nFileTimestamp = 0;
     128             754 :     bLastSQLCommandIsUpdateLayerStatistics = FALSE;
     129             754 : }
     130                 : 
     131                 : /************************************************************************/
     132                 : /*                        ~OGRSQLiteDataSource()                        */
     133                 : /************************************************************************/
     134                 : 
     135             754 : OGRSQLiteDataSource::~OGRSQLiteDataSource()
     136                 : 
     137                 : {
     138                 :     int         i;
     139                 : 
     140            1390 :     for( i = 0; i < nLayers; i++ )
     141                 :     {
     142             636 :         if( papoLayers[i]->IsTableLayer() )
     143                 :         {
     144             631 :             OGRSQLiteTableLayer* poLayer = (OGRSQLiteTableLayer*) papoLayers[i];
     145             631 :             poLayer->CreateSpatialIndexIfNecessary();
     146                 :         }
     147                 :     }
     148                 : 
     149             754 :     SaveStatistics();
     150                 : 
     151             754 :     CPLFree( pszName );
     152                 : 
     153            1390 :     for( i = 0; i < nLayers; i++ )
     154             636 :         delete papoLayers[i];
     155                 :     
     156             754 :     CPLFree( papoLayers );
     157                 : 
     158             919 :     for( i = 0; i < nKnownSRID; i++ )
     159                 :     {
     160             165 :         if( papoSRS[i] != NULL )
     161             165 :             papoSRS[i]->Release();
     162                 :     }
     163             754 :     CPLFree( panSRID );
     164             754 :     CPLFree( papoSRS );
     165                 : 
     166             754 :     if( hDB != NULL )
     167             753 :         sqlite3_close( hDB );
     168                 : 
     169                 : #ifdef HAVE_SQLITE_VFS
     170             754 :     if (pMyVFS)
     171                 :     {
     172             509 :         sqlite3_vfs_unregister(pMyVFS);
     173             509 :         CPLFree(pMyVFS->pAppData);
     174             509 :         CPLFree(pMyVFS);
     175                 :     }
     176                 : #endif
     177             754 : }
     178                 : 
     179                 : /************************************************************************/
     180                 : /*                              SaveStatistics()                        */
     181                 : /************************************************************************/
     182                 : 
     183             754 : void OGRSQLiteDataSource::SaveStatistics()
     184                 : {
     185                 :     int i;
     186             754 :     int nSavedAllLayersCacheData = -1;
     187                 : 
     188             754 :     if( !bIsSpatiaLiteDB || !OGRSQLiteIsSpatialiteLoaded() || bLastSQLCommandIsUpdateLayerStatistics )
     189             268 :         return;
     190                 : 
     191             838 :     for( i = 0; i < nLayers; i++ )
     192                 :     {
     193             352 :         if( papoLayers[i]->IsTableLayer() )
     194                 :         {
     195             347 :             OGRSQLiteTableLayer* poLayer = (OGRSQLiteTableLayer*) papoLayers[i];
     196             347 :             int nSaveRet = poLayer->SaveStatistics();
     197             347 :             if( nSaveRet >= 0)
     198                 :             {
     199             116 :                 if( nSavedAllLayersCacheData < 0 )
     200              44 :                     nSavedAllLayersCacheData = nSaveRet;
     201                 :                 else
     202              72 :                     nSavedAllLayersCacheData &= nSaveRet;
     203                 :             }
     204                 :         }
     205                 :     }
     206                 : 
     207             486 :     if( hDB && nSavedAllLayersCacheData == TRUE )
     208                 :     {
     209              32 :         char* pszErrMsg = NULL;
     210                 : 
     211              32 :         int nRowCount = 0, nColCount = 0;
     212              32 :         char **papszResult = NULL;
     213              32 :         int nReplaceEventId = -1;
     214                 : 
     215                 :         sqlite3_get_table( hDB,
     216                 :                            "SELECT event_id, table_name, geometry_column, event "
     217                 :                            "FROM spatialite_history ORDER BY event_id DESC LIMIT 1",
     218                 :                            &papszResult,
     219              32 :                            &nRowCount, &nColCount, &pszErrMsg );
     220                 : 
     221              32 :         if( nRowCount == 1 )
     222                 :         {
     223              32 :             char **papszRow = papszResult + 4;
     224              32 :             const char* pszEventId = papszRow[0];
     225              32 :             const char* pszTableName = papszRow[1];
     226              32 :             const char* pszGeomCol = papszRow[2];
     227              32 :             const char* pszEvent = papszRow[3];
     228                 : 
     229              32 :             if( pszEventId != NULL && pszTableName != NULL &&
     230                 :                 pszGeomCol != NULL && pszEvent != NULL &&
     231                 :                 strcmp(pszTableName, "ALL-TABLES") == 0 &&
     232                 :                 strcmp(pszGeomCol, "ALL-GEOMETRY-COLUMNS") == 0 &&
     233                 :                 strcmp(pszEvent, "UpdateLayerStatistics") == 0 )
     234                 :             {
     235              23 :                 nReplaceEventId = atoi(pszEventId);
     236                 :             }
     237                 :         }
     238              32 :         if( pszErrMsg )
     239               0 :             sqlite3_free( pszErrMsg );
     240              32 :         pszErrMsg = NULL;
     241                 : 
     242              32 :         sqlite3_free_table( papszResult );
     243                 : 
     244                 :         int rc;
     245                 : 
     246              32 :         if( nReplaceEventId >= 0 )
     247                 :         {
     248                 :             rc = sqlite3_exec( hDB,
     249                 :                                CPLSPrintf("UPDATE spatialite_history SET "
     250                 :                                           "timestamp = DateTime('now') "
     251                 :                                           "WHERE event_id = %d", nReplaceEventId),
     252              23 :                                NULL, NULL, &pszErrMsg );
     253                 :         }
     254                 :         else
     255                 :         {
     256                 :             rc = sqlite3_exec( hDB,
     257                 :                 "INSERT INTO spatialite_history (table_name, geometry_column, "
     258                 :                 "event, timestamp, ver_sqlite, ver_splite) VALUES ("
     259                 :                 "'ALL-TABLES', 'ALL-GEOMETRY-COLUMNS', 'UpdateLayerStatistics', "
     260                 :                 "DateTime('now'), sqlite_version(), spatialite_version())",
     261               9 :                 NULL, NULL, &pszErrMsg );
     262                 :         }
     263                 : 
     264              32 :         if( rc != SQLITE_OK )
     265                 :         {
     266               0 :             CPLDebug("SQLITE", "Error %s", pszErrMsg ? pszErrMsg : "unknown");
     267               0 :             sqlite3_free( pszErrMsg );
     268                 :         }
     269                 :     }
     270                 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                              SetSynchronous()                        */
     274                 : /************************************************************************/
     275                 : 
     276             736 : int OGRSQLiteDataSource::SetSynchronous()
     277                 : {
     278                 :     int rc;
     279             736 :     const char* pszSqliteSync = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL);
     280             736 :     if (pszSqliteSync != NULL)
     281                 :     {
     282             724 :         char* pszErrMsg = NULL;
     283            1448 :         if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
     284                 :             EQUAL(pszSqliteSync, "FALSE"))
     285             724 :             rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
     286               0 :         else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
     287               0 :             rc = sqlite3_exec( hDB, "PRAGMA synchronous = NORMAL", NULL, NULL, &pszErrMsg );
     288               0 :         else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
     289                 :             EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
     290               0 :             rc = sqlite3_exec( hDB, "PRAGMA synchronous = FULL", NULL, NULL, &pszErrMsg );
     291                 :         else
     292                 :         {
     293                 :             CPLError( CE_Warning, CPLE_AppDefined, "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
     294               0 :                       pszSqliteSync);
     295               0 :             rc = SQLITE_OK;
     296                 :         }
     297                 : 
     298             724 :         if( rc != SQLITE_OK )
     299                 :         {
     300                 :             CPLError( CE_Failure, CPLE_AppDefined,
     301                 :                       "Unable to run PRAGMA synchronous : %s",
     302               0 :                       pszErrMsg );
     303               0 :             sqlite3_free( pszErrMsg );
     304               0 :             return FALSE;
     305                 :         }
     306                 :     }
     307             736 :     return TRUE;
     308                 : }
     309                 : 
     310                 : /************************************************************************/
     311                 : /*                              SetCacheSize()                          */
     312                 : /************************************************************************/
     313                 : 
     314             736 : int OGRSQLiteDataSource::SetCacheSize()
     315                 : {
     316                 :     int rc;
     317             736 :     const char* pszSqliteCacheMB = CPLGetConfigOption("OGR_SQLITE_CACHE", NULL);
     318             736 :     if (pszSqliteCacheMB != NULL)
     319                 :     {
     320               0 :         char* pszErrMsg = NULL;
     321                 :         char **papszResult;
     322                 :         int nRowCount, nColCount;
     323                 :         int iSqliteCachePages;
     324               0 :         int iSqlitePageSize = -1;
     325               0 :         int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
     326                 : 
     327                 :         /* querying the current PageSize */
     328                 :         rc = sqlite3_get_table( hDB, "PRAGMA page_size",
     329                 :                                 &papszResult, &nRowCount, &nColCount,
     330               0 :                                 &pszErrMsg );
     331               0 :         if( rc == SQLITE_OK )
     332                 :         {
     333                 :             int iRow;
     334               0 :             for (iRow = 1; iRow <= nRowCount; iRow++)
     335                 :             {
     336               0 :                 iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
     337                 :             }
     338               0 :             sqlite3_free_table(papszResult);
     339                 :         }
     340               0 :         if( iSqlitePageSize < 0 )
     341                 :         {
     342                 :             CPLError( CE_Failure, CPLE_AppDefined,
     343                 :                       "Unable to run PRAGMA page_size : %s",
     344               0 :                       pszErrMsg );
     345               0 :             sqlite3_free( pszErrMsg );
     346               0 :             return TRUE;
     347                 :         }
     348                 :     
     349                 :         /* computing the CacheSize as #Pages */
     350               0 :         iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
     351               0 :         if( iSqliteCachePages <= 0)
     352               0 :             return TRUE;
     353                 : 
     354                 :         rc = sqlite3_exec( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
     355                 :                                             iSqliteCachePages ),
     356               0 :                            NULL, NULL, &pszErrMsg );
     357               0 :         if( rc != SQLITE_OK )
     358                 :         {
     359                 :             CPLError( CE_Warning, CPLE_AppDefined,
     360                 :                       "Unrecognized value for PRAGMA cache_size : %s",
     361               0 :                       pszErrMsg );
     362               0 :             sqlite3_free( pszErrMsg );
     363               0 :             rc = SQLITE_OK;
     364                 :         }
     365                 :     }
     366             736 :     return TRUE;
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                 OGRSQLiteDataSourceNotifyFileOpened()                */
     371                 : /************************************************************************/
     372                 : 
     373                 : static
     374            1220 : void OGRSQLiteDataSourceNotifyFileOpened (void* pfnUserData,
     375                 :                                               const char* pszFilename,
     376                 :                                               VSILFILE* fp)
     377                 : {
     378            1220 :     ((OGRSQLiteDataSource*)pfnUserData)->NotifyFileOpened(pszFilename, fp);
     379            1220 : }
     380                 : 
     381                 : 
     382                 : /************************************************************************/
     383                 : /*                          NotifyFileOpened()                          */
     384                 : /************************************************************************/
     385                 : 
     386            1220 : void OGRSQLiteDataSource::NotifyFileOpened(const char* pszFilename,
     387                 :                                            VSILFILE* fp)
     388                 : {
     389            1220 :     if (strcmp(pszFilename, pszName) == 0)
     390                 :     {
     391             509 :         fpMainFile = fp;
     392                 :     }
     393            1220 : }
     394                 : 
     395                 : /************************************************************************/
     396                 : /*                            OpenOrCreateDB()                          */
     397                 : /************************************************************************/
     398                 : 
     399             753 : int OGRSQLiteDataSource::OpenOrCreateDB(int flags)
     400                 : {
     401                 :     int rc;
     402                 :     
     403                 : #ifdef HAVE_SQLITE_VFS
     404             753 :     OGR2SQLITE_Register();
     405                 : 
     406             753 :     int bUseOGRVFS = CSLTestBoolean(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
     407            1262 :     if (bUseOGRVFS || strncmp(pszName, "/vsi", 4) == 0)
     408                 :     {
     409             509 :         pMyVFS = OGRSQLiteCreateVFS(OGRSQLiteDataSourceNotifyFileOpened, this);
     410             509 :         sqlite3_vfs_register(pMyVFS, 0);
     411             509 :         rc = sqlite3_open_v2( pszName, &hDB, flags, pMyVFS->zName );
     412                 :     }
     413                 :     else
     414             244 :         rc = sqlite3_open_v2( pszName, &hDB, flags, NULL );
     415                 : #else
     416                 :     rc = sqlite3_open( pszName, &hDB );
     417                 : #endif
     418             753 :     if( rc != SQLITE_OK )
     419                 :     {
     420                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     421                 :                   "sqlite3_open(%s) failed: %s",
     422              17 :                   pszName, sqlite3_errmsg( hDB ) );
     423              17 :         return FALSE;
     424                 :     }
     425                 : 
     426             736 :     int nRowCount = 0, nColCount = 0;
     427             736 :     char** papszResult = NULL;
     428                 :     sqlite3_get_table( hDB,
     429                 :                        "SELECT name, sql FROM sqlite_master "
     430                 :                        "WHERE (type = 'trigger' OR type = 'view') AND ("
     431                 :                        "sql LIKE '%%ogr_geocode%%' OR "
     432                 :                        "sql LIKE '%%ogr_datasource_load_layers%%' OR "
     433                 :                        "sql LIKE '%%ogr_GetConfigOption%%' OR "
     434                 :                        "sql LIKE '%%ogr_SetConfigOption%%' )",
     435                 :                        &papszResult, &nRowCount, &nColCount,
     436             736 :                        NULL );
     437                 : 
     438             736 :     sqlite3_free_table(papszResult);
     439             736 :     papszResult = NULL;
     440                 : 
     441             736 :     if( nRowCount > 0 )
     442                 :     {
     443               0 :         if( !CSLTestBoolean(CPLGetConfigOption("ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")) )
     444                 :         {
     445                 :             CPLError( CE_Failure, CPLE_OpenFailed, "%s", 
     446                 :                 "A trigger and/or view calls a OGR extension SQL function that could be used to "
     447                 :                 "steal data, or use network bandwith, without your consent.\n"
     448                 :                 "The database will not be opened unless the ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW "
     449               0 :                 "configuration option to YES.");
     450               0 :             return FALSE;
     451                 :         }
     452                 :     }
     453                 : 
     454             736 :     const char* pszSqliteJournal = CPLGetConfigOption("OGR_SQLITE_JOURNAL", NULL);
     455             736 :     if (pszSqliteJournal != NULL)
     456                 :     {
     457               0 :         char* pszErrMsg = NULL;
     458                 :         char **papszResult;
     459                 :         int nRowCount, nColCount;
     460                 : 
     461                 :         const char* pszSQL = CPLSPrintf("PRAGMA journal_mode = %s",
     462               0 :                                         pszSqliteJournal);
     463                 : 
     464                 :         rc = sqlite3_get_table( hDB, pszSQL,
     465                 :                                 &papszResult, &nRowCount, &nColCount,
     466               0 :                                 &pszErrMsg );
     467               0 :         if( rc == SQLITE_OK )
     468                 :         {
     469               0 :             sqlite3_free_table(papszResult);
     470                 :         }
     471                 :         else
     472                 :         {
     473               0 :             sqlite3_free( pszErrMsg );
     474                 :         }
     475                 :     }
     476                 : 
     477             736 :     if (!SetCacheSize())
     478               0 :         return FALSE;
     479                 : 
     480             736 :     if (!SetSynchronous())
     481               0 :         return FALSE;
     482                 : 
     483             736 :     return TRUE;
     484                 : }
     485                 : 
     486                 : /************************************************************************/
     487                 : /*                               Create()                               */
     488                 : /************************************************************************/
     489                 : 
     490             196 : int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
     491                 : {
     492                 :     int rc;
     493             196 :     CPLString osCommand;
     494             196 :     char *pszErrMsg = NULL;
     495                 : 
     496             196 :     pszName = CPLStrdup( pszNameIn );
     497                 : 
     498                 : /* -------------------------------------------------------------------- */
     499                 : /*      Check that spatialite extensions are loaded if required to      */
     500                 : /*      create a spatialite database                                    */
     501                 : /* -------------------------------------------------------------------- */
     502             196 :     int bSpatialite = CSLFetchBoolean( papszOptions, "SPATIALITE", FALSE );
     503             196 :     int bMetadata = CSLFetchBoolean( papszOptions, "METADATA", TRUE );
     504                 : 
     505             196 :     if (bSpatialite == TRUE)
     506                 :     {
     507                 : #ifdef HAVE_SPATIALITE
     508              46 :         OGRSQLiteInitSpatialite();
     509              46 :         if (!OGRSQLiteIsSpatialiteLoaded())
     510                 :         {
     511                 :             CPLError( CE_Failure, CPLE_NotSupported,
     512               1 :                     "Creating a Spatialite database, but Spatialite extensions are not loaded." );
     513               1 :             return FALSE;
     514                 :         }
     515                 : #else
     516                 :         CPLError( CE_Failure, CPLE_NotSupported,
     517                 :             "OGR was built without libspatialite support\n"
     518                 :             "... sorry, creating/writing any SpatiaLite DB is unsupported\n" );
     519                 : 
     520                 :         return FALSE;
     521                 : #endif
     522                 :     }
     523                 : 
     524             195 :     bIsSpatiaLiteDB = bSpatialite;
     525                 : 
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Create the database file.                                       */
     528                 : /* -------------------------------------------------------------------- */
     529                 : #ifdef HAVE_SQLITE_VFS
     530             195 :     if (!OpenOrCreateDB(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE))
     531                 : #else
     532                 :     if (!OpenOrCreateDB(0))
     533                 : #endif
     534              17 :         return FALSE;
     535                 : 
     536                 : /* -------------------------------------------------------------------- */
     537                 : /*      Create the SpatiaLite metadata tables.                          */
     538                 : /* -------------------------------------------------------------------- */
     539             178 :     if ( bSpatialite )
     540                 :     {
     541                 :         /*
     542                 :         / SpatiaLite full support: calling InitSpatialMetadata()
     543                 :         /
     544                 :         / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
     545                 :         / to directly CREATE "geometry_columns" and "spatial_ref_sys"
     546                 :         / [by-passing InitSpatialMetadata() as absolutely required]
     547                 :         / will severely [and irremediably] corrupt the DB !!!
     548                 :         */
     549                 :         
     550              28 :         const char* pszVal = CSLFetchNameValue( papszOptions, "INIT_WITH_EPSG" );
     551              28 :         if( pszVal != NULL && !CSLTestBoolean(pszVal) &&
     552                 :             OGRSQLiteGetSpatialiteVersionNumber() >= 40 )
     553               0 :             osCommand =  "SELECT InitSpatialMetadata('NONE')";
     554                 :         else
     555              28 :             osCommand =  "SELECT InitSpatialMetadata()";
     556              28 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     557              28 :         if( rc != SQLITE_OK )
     558                 :         {
     559                 :             CPLError( CE_Failure, CPLE_AppDefined,
     560                 :                 "Unable to Initialize SpatiaLite Metadata: %s",
     561               0 :                     pszErrMsg );
     562               0 :             sqlite3_free( pszErrMsg );
     563               0 :             return FALSE;
     564                 :         }
     565                 :     }
     566                 : 
     567                 : /* -------------------------------------------------------------------- */
     568                 : /*  Create the geometry_columns and spatial_ref_sys metadata tables.    */
     569                 : /* -------------------------------------------------------------------- */
     570             150 :     else if( bMetadata )
     571                 :     {
     572                 :         osCommand =
     573                 :             "CREATE TABLE geometry_columns ("
     574                 :             "     f_table_name VARCHAR, "
     575                 :             "     f_geometry_column VARCHAR, "
     576                 :             "     geometry_type INTEGER, "
     577                 :             "     coord_dimension INTEGER, "
     578                 :             "     srid INTEGER,"
     579             142 :             "     geometry_format VARCHAR )";
     580             142 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     581             142 :         if( rc != SQLITE_OK )
     582                 :         {
     583                 :             CPLError( CE_Failure, CPLE_AppDefined,
     584                 :                       "Unable to create table geometry_columns: %s",
     585               0 :                       pszErrMsg );
     586               0 :             sqlite3_free( pszErrMsg );
     587               0 :             return FALSE;
     588                 :         }
     589                 : 
     590                 :         osCommand =
     591                 :             "CREATE TABLE spatial_ref_sys        ("
     592                 :             "     srid INTEGER UNIQUE,"
     593                 :             "     auth_name TEXT,"
     594                 :             "     auth_srid TEXT,"
     595             142 :             "     srtext TEXT)";
     596             142 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
     597             142 :         if( rc != SQLITE_OK )
     598                 :         {
     599                 :             CPLError( CE_Failure, CPLE_AppDefined,
     600                 :                       "Unable to create table spatial_ref_sys: %s",
     601               0 :                       pszErrMsg );
     602               0 :             sqlite3_free( pszErrMsg );
     603               0 :             return FALSE;
     604                 :         }
     605                 :     }
     606                 : 
     607                 : /* -------------------------------------------------------------------- */
     608                 : /*      Optionnaly initialize the content of the spatial_ref_sys table  */
     609                 : /*      with the EPSG database                                          */
     610                 : /* -------------------------------------------------------------------- */
     611             178 :     if ( (bSpatialite || bMetadata) &&
     612                 :          CSLFetchBoolean( papszOptions, "INIT_WITH_EPSG", FALSE ) )
     613                 :     {
     614               2 :         if (!InitWithEPSG())
     615               0 :             return FALSE;
     616                 :     }
     617                 : 
     618             178 :     return Open(pszName, TRUE);
     619                 : }
     620                 : 
     621                 : /************************************************************************/
     622                 : /*                           InitWithEPSG()                             */
     623                 : /************************************************************************/
     624                 : 
     625               2 : int OGRSQLiteDataSource::InitWithEPSG()
     626                 : {
     627               2 :     CPLString osCommand;
     628               2 :     char* pszErrMsg = NULL;
     629                 : 
     630               2 :     if ( bIsSpatiaLiteDB )
     631                 :     {
     632                 :         /*
     633                 :         / if v.2.4.0 (or any subsequent) InitWithEPSG make no sense at all
     634                 :         / because the EPSG dataset is already self-initialized at DB creation
     635                 :         */
     636               0 :         int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
     637               0 :         if ( iSpatialiteVersion >= 24 )
     638               0 :             return TRUE;
     639                 :     }
     640                 : 
     641               2 :     int rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     642               2 :     if( rc != SQLITE_OK )
     643                 :     {
     644                 :         CPLError( CE_Failure, CPLE_AppDefined,
     645                 :                 "Unable to insert into spatial_ref_sys: %s",
     646               0 :                 pszErrMsg );
     647               0 :         sqlite3_free( pszErrMsg );
     648               0 :         return FALSE;
     649                 :     }
     650                 : 
     651                 :     FILE* fp;
     652                 :     int i;
     653               6 :     for(i=0;i<2 && rc == SQLITE_OK;i++)
     654                 :     {
     655               4 :         const char* pszFilename = (i == 0) ? "gcs.csv" : "pcs.csv";
     656               4 :         fp = VSIFOpen(CSVFilename(pszFilename), "rt");
     657               4 :         if (fp == NULL)
     658                 :         {
     659                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     660                 :                 "Unable to open EPSG support file %s.\n"
     661                 :                 "Try setting the GDAL_DATA environment variable to point to the\n"
     662                 :                 "directory containing EPSG csv files.",
     663               0 :                 pszFilename );
     664                 : 
     665               0 :             continue;
     666                 :         }
     667                 : 
     668               4 :         OGRSpatialReference oSRS;
     669                 :         char** papszTokens;
     670               4 :         CSLDestroy(CSVReadParseLine( fp ));
     671            8598 :         while ( (papszTokens = CSVReadParseLine( fp )) != NULL && rc == SQLITE_OK)
     672                 :         {
     673            8590 :             int nSRSId = atoi(papszTokens[0]);
     674            8590 :             CSLDestroy(papszTokens);
     675                 : 
     676            8590 :             CPLPushErrorHandler(CPLQuietErrorHandler);
     677            8590 :             oSRS.importFromEPSG(nSRSId);
     678            8590 :             CPLPopErrorHandler();
     679                 : 
     680            8590 :             if (bIsSpatiaLiteDB)
     681                 :             {
     682               0 :                 char    *pszProj4 = NULL;
     683                 : 
     684               0 :                 CPLPushErrorHandler(CPLQuietErrorHandler);
     685               0 :                 OGRErr eErr = oSRS.exportToProj4( &pszProj4 );
     686               0 :                 CPLPopErrorHandler();
     687                 : 
     688               0 :                 char    *pszWKT = NULL;
     689               0 :                 if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
     690                 :                 {
     691               0 :                     CPLFree(pszWKT);
     692               0 :                     pszWKT = NULL;
     693                 :                 }
     694                 : 
     695               0 :                 if( eErr == OGRERR_NONE )
     696                 :                 {
     697               0 :                     const char  *pszProjCS = oSRS.GetAttrValue("PROJCS");
     698               0 :                     if (pszProjCS == NULL)
     699               0 :                         pszProjCS = oSRS.GetAttrValue("GEOGCS");
     700                 : 
     701               0 :                     const char* pszSRTEXTColName = GetSRTEXTColName();
     702               0 :                     if (pszSRTEXTColName != NULL)
     703                 :                     {
     704                 :                     /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
     705               0 :                         if ( pszProjCS )
     706                 :                             osCommand.Printf(
     707                 :                                 "INSERT INTO spatial_ref_sys "
     708                 :                                 "(srid, auth_name, auth_srid, ref_sys_name, proj4text, %s) "
     709                 :                                 "VALUES (%d, 'EPSG', '%d', ?, ?, ?)",
     710               0 :                                 pszSRTEXTColName, nSRSId, nSRSId);
     711                 :                         else
     712                 :                             osCommand.Printf(
     713                 :                                 "INSERT INTO spatial_ref_sys "
     714                 :                                 "(srid, auth_name, auth_srid, proj4text, %s) "
     715                 :                                 "VALUES (%d, 'EPSG', '%d', ?, ?)",
     716               0 :                                 pszSRTEXTColName, nSRSId, nSRSId);
     717                 :                     }
     718                 :                     else
     719                 :                     {
     720                 :                     /* the SPATIAL_REF_SYS table does not support a SRS_WKT column */
     721               0 :                         if ( pszProjCS )
     722                 :                             osCommand.Printf(
     723                 :                                 "INSERT INTO spatial_ref_sys "
     724                 :                                 "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
     725                 :                                 "VALUES (%d, 'EPSG', '%d', ?, ?)",
     726               0 :                                 nSRSId, nSRSId);
     727                 :                         else
     728                 :                             osCommand.Printf(
     729                 :                                 "INSERT INTO spatial_ref_sys "
     730                 :                                 "(srid, auth_name, auth_srid, proj4text) "
     731                 :                                 "VALUES (%d, 'EPSG', '%d', ?)",
     732               0 :                                 nSRSId, nSRSId);
     733                 :                     }
     734                 : 
     735               0 :                     sqlite3_stmt *hInsertStmt = NULL;
     736               0 :                     rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
     737                 : 
     738               0 :                     if ( pszProjCS )
     739                 :                     {
     740               0 :                         if( rc == SQLITE_OK)
     741               0 :                             rc = sqlite3_bind_text( hInsertStmt, 1, pszProjCS, -1, SQLITE_STATIC );
     742               0 :                         if( rc == SQLITE_OK)
     743               0 :                             rc = sqlite3_bind_text( hInsertStmt, 2, pszProj4, -1, SQLITE_STATIC );
     744               0 :                         if (pszSRTEXTColName != NULL)
     745                 :                         {
     746                 :                         /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
     747               0 :                             if( rc == SQLITE_OK && pszWKT != NULL)
     748               0 :                                 rc = sqlite3_bind_text( hInsertStmt, 3, pszWKT, -1, SQLITE_STATIC );
     749                 :                         }
     750                 :                     }
     751                 :                     else
     752                 :                     {
     753               0 :                         if( rc == SQLITE_OK)
     754               0 :                             rc = sqlite3_bind_text( hInsertStmt, 1, pszProj4, -1, SQLITE_STATIC );
     755               0 :                         if (pszSRTEXTColName != NULL)
     756                 :                         {
     757                 :                         /* the SPATIAL_REF_SYS table supports a SRS_WKT column */
     758               0 :                             if( rc == SQLITE_OK && pszWKT != NULL)
     759               0 :                                 rc = sqlite3_bind_text( hInsertStmt, 2, pszWKT, -1, SQLITE_STATIC );
     760                 :                         }
     761                 :                     }
     762                 : 
     763               0 :                     if( rc == SQLITE_OK)
     764               0 :                         rc = sqlite3_step( hInsertStmt );
     765                 : 
     766               0 :                     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     767                 :                     {
     768                 :                         CPLError( CE_Failure, CPLE_AppDefined,
     769                 :                                     "Cannot insert %s into spatial_ref_sys : %s",
     770                 :                                     pszProj4,
     771               0 :                                     sqlite3_errmsg(hDB) );
     772                 : 
     773               0 :                         sqlite3_finalize( hInsertStmt );
     774               0 :                         CPLFree(pszProj4);
     775               0 :                         CPLFree(pszWKT);
     776               0 :                         break;
     777                 :                     }
     778               0 :                     rc = SQLITE_OK;
     779                 : 
     780               0 :                     sqlite3_finalize( hInsertStmt );
     781                 :                 }
     782                 : 
     783               0 :                 CPLFree(pszProj4);
     784               0 :                 CPLFree(pszWKT);
     785                 :             }
     786                 :             else
     787                 :             {
     788            8590 :                 char    *pszWKT = NULL;
     789            8590 :                 if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
     790                 :                 {
     791                 :                     osCommand.Printf(
     792                 :                         "INSERT INTO spatial_ref_sys "
     793                 :                         "(srid, auth_name, auth_srid, srtext) "
     794                 :                         "VALUES (%d, 'EPSG', '%d', ?)",
     795            8590 :                         nSRSId, nSRSId );
     796                 : 
     797            8590 :                     sqlite3_stmt *hInsertStmt = NULL;
     798            8590 :                     rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
     799                 : 
     800            8590 :                     if( rc == SQLITE_OK)
     801            8590 :                         rc = sqlite3_bind_text( hInsertStmt, 1, pszWKT, -1, SQLITE_STATIC );
     802                 : 
     803            8590 :                     if( rc == SQLITE_OK)
     804            8590 :                         rc = sqlite3_step( hInsertStmt );
     805                 : 
     806            8590 :                     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     807                 :                     {
     808                 :                         CPLError( CE_Failure, CPLE_AppDefined,
     809                 :                                     "Cannot insert %s into spatial_ref_sys : %s",
     810                 :                                     pszWKT,
     811               0 :                                     sqlite3_errmsg(hDB) );
     812                 : 
     813               0 :                         sqlite3_finalize( hInsertStmt );
     814               0 :                         CPLFree(pszWKT);
     815               0 :                         break;
     816                 :                     }
     817            8590 :                     rc = SQLITE_OK;
     818                 : 
     819            8590 :                     sqlite3_finalize( hInsertStmt );
     820                 :                 }
     821                 : 
     822            8590 :                 CPLFree(pszWKT);
     823                 :             }
     824                 :         }
     825               4 :         VSIFClose(fp);
     826                 :     }
     827                 : 
     828               2 :     if (rc == SQLITE_OK)
     829               2 :         rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
     830                 :     else
     831               0 :         rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, &pszErrMsg );
     832                 : 
     833               2 :     if( rc != SQLITE_OK )
     834                 :     {
     835                 :         CPLError( CE_Failure, CPLE_AppDefined,
     836                 :                 "Unable to insert into spatial_ref_sys: %s",
     837               0 :                 pszErrMsg );
     838               0 :         sqlite3_free( pszErrMsg );
     839                 :     }
     840                 : 
     841               2 :     return (rc == SQLITE_OK);
     842                 : }
     843                 : 
     844                 : /************************************************************************/
     845                 : /*                        ReloadLayers()                                */
     846                 : /************************************************************************/
     847                 : 
     848             485 : void OGRSQLiteDataSource::ReloadLayers()
     849                 : {
     850             485 :     for(int i=0;i<nLayers;i++)
     851               0 :         delete papoLayers[i];
     852             485 :     CPLFree(papoLayers);
     853             485 :     papoLayers = NULL;
     854             485 :     nLayers = 0;
     855                 : 
     856             485 :     Open(pszName, bUpdate);
     857             485 : }
     858                 : 
     859                 : /************************************************************************/
     860                 : /*                                Open()                                */
     861                 : /************************************************************************/
     862                 : 
     863            1221 : int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn )
     864                 : 
     865                 : {
     866            1221 :     CPLAssert( nLayers == 0 );
     867                 : 
     868            1221 :     if (pszName == NULL)
     869             558 :         pszName = CPLStrdup( pszNewName );
     870            1221 :     bUpdate = bUpdateIn;
     871                 : 
     872                 :     VSIStatBufL sStat;
     873            1221 :     if( VSIStatL( pszName, &sStat ) == 0 )
     874                 :     {
     875            1205 :         nFileTimestamp = sStat.st_mtime;
     876                 :     }
     877                 : 
     878            1221 :     int bListAllTables = CSLTestBoolean(CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO"));
     879                 : 
     880                 :     // Don't list by default: there might be some security implications
     881                 :     // if a user is provided with a file and doesn't know that there are
     882                 :     // virtual OGR tables in it.
     883            1221 :     int bListVirtualOGRLayers = CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_LIST_VIRTUAL_OGR", "NO"));
     884                 : 
     885                 : /* -------------------------------------------------------------------- */
     886                 : /*      Try to open the sqlite database properly now.                   */
     887                 : /* -------------------------------------------------------------------- */
     888            1221 :     if (hDB == NULL)
     889                 :     {
     890             558 :         OGRSQLiteInitSpatialite();
     891                 : 
     892                 : #ifdef HAVE_SQLITE_VFS
     893             558 :         if (!OpenOrCreateDB((bUpdateIn) ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY) )
     894                 : #else
     895                 :         if (!OpenOrCreateDB(0))
     896                 : #endif
     897               0 :             return FALSE;
     898                 :     }
     899                 : 
     900                 : /* -------------------------------------------------------------------- */
     901                 : /*      If we have a GEOMETRY_COLUMNS tables, initialize on the basis   */
     902                 : /*      of that.                                                        */
     903                 : /* -------------------------------------------------------------------- */
     904                 :     int rc;
     905            1221 :     char *pszErrMsg = NULL;
     906                 :     char **papszResult;
     907                 :     int nRowCount, iRow, nColCount;
     908                 : 
     909            1221 :     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
     910                 : 
     911                 :     rc = sqlite3_get_table( 
     912                 :         hDB,
     913                 :         "SELECT f_table_name, f_geometry_column, geometry_type, coord_dimension, geometry_format, srid"
     914                 :         " FROM geometry_columns",
     915            1221 :         &papszResult, &nRowCount, &nColCount, &pszErrMsg );
     916                 : 
     917            1221 :     if( rc == SQLITE_OK )
     918                 :     {
     919             281 :         CPLDebug("SQLITE", "OGR style SQLite DB found !");
     920                 :     
     921             281 :         bHaveGeometryColumns = TRUE;
     922                 : 
     923             451 :         for ( iRow = 0; iRow < nRowCount; iRow++ )
     924                 :         {
     925             170 :             char **papszRow = papszResult + iRow * 6 + 6;
     926             170 :             const char* pszTableName = papszRow[0];
     927             170 :             const char* pszGeomCol = papszRow[1];
     928                 : 
     929             170 :             if( pszTableName == NULL || pszGeomCol == NULL )
     930               0 :                 continue;
     931                 : 
     932             170 :             aoMapTableToSetOfGeomCols[pszTableName].insert(pszGeomCol);
     933                 :         }
     934                 : 
     935             451 :         for( iRow = 0; iRow < nRowCount; iRow++ )
     936                 :         {
     937             170 :             char **papszRow = papszResult + iRow * 6 + 6;
     938             170 :             OGRwkbGeometryType eGeomType = wkbUnknown;
     939             170 :             int nSRID = 0;
     940             170 :             const char* pszTableName = papszRow[0];
     941             170 :             const char* pszGeomCol = papszRow[1];
     942                 : 
     943             510 :             if (pszTableName == NULL ||
     944                 :                 pszGeomCol == NULL ||
     945             170 :                 papszRow[2] == NULL ||
     946             170 :                 papszRow[3] == NULL)
     947               0 :                 continue;
     948                 : 
     949             170 :             eGeomType = (OGRwkbGeometryType) atoi(papszRow[2]);
     950                 : 
     951             170 :             if( atoi(papszRow[3]) > 2 )
     952               0 :                 eGeomType = (OGRwkbGeometryType) (((int)eGeomType) | wkb25DBit);
     953                 : 
     954             170 :             if( papszRow[5] != NULL )
     955              89 :                 nSRID = atoi(papszRow[5]);
     956                 : 
     957             170 :             int nOccurences = (int)aoMapTableToSetOfGeomCols[pszTableName].size();
     958                 : 
     959             170 :             OpenTable( pszTableName, pszGeomCol, nOccurences > 1, eGeomType, papszRow[4],
     960             340 :                        FetchSRS( nSRID ) );
     961                 :                        
     962             170 :             if (bListAllTables)
     963               0 :                 CPLHashSetInsert(hSet, CPLStrdup(papszRow[0]));
     964                 :         }
     965                 : 
     966             281 :         sqlite3_free_table(papszResult);
     967                 : 
     968                 : /* -------------------------------------------------------------------- */
     969                 : /*      Detect VirtualOGR layers                                        */
     970                 : /* -------------------------------------------------------------------- */
     971             281 :         if( bListVirtualOGRLayers )
     972                 :         {
     973                 :             rc = sqlite3_get_table( hDB,
     974                 :                                 "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
     975                 :                                 &papszResult, &nRowCount, 
     976               2 :                                 &nColCount, &pszErrMsg );
     977                 : 
     978               2 :             if ( rc == SQLITE_OK )
     979                 :             {
     980               4 :                 for( iRow = 0; iRow < nRowCount; iRow++ )
     981                 :                 {
     982               2 :                     char **papszRow = papszResult + iRow * 2 + 2;
     983               2 :                     const char *pszName = papszRow[0];
     984               2 :                     const char *pszSQL = papszRow[1];
     985               2 :                     if( pszName == NULL || pszSQL == NULL )
     986               0 :                         continue;
     987                 : 
     988               2 :                     if( strstr(pszSQL, "VirtualOGR") )
     989                 :                     {
     990               2 :                         OpenVirtualTable(pszName, pszSQL);
     991                 : 
     992               2 :                         if (bListAllTables)
     993               0 :                             CPLHashSetInsert(hSet, CPLStrdup(pszName));
     994                 :                     }
     995                 :                 }
     996                 :             }
     997                 :             else
     998                 :             {
     999                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    1000                 :                         "Unable to fetch list of tables: %s", 
    1001               0 :                         pszErrMsg );
    1002               0 :                 sqlite3_free( pszErrMsg );
    1003                 :             }
    1004                 : 
    1005               2 :             sqlite3_free_table(papszResult);
    1006                 :         }
    1007                 : 
    1008             281 :         if (bListAllTables)
    1009               0 :             goto all_tables;
    1010                 :             
    1011             281 :         CPLHashSetDestroy(hSet);
    1012                 :         
    1013             281 :         return TRUE;
    1014                 :     }
    1015                 : 
    1016                 : /* -------------------------------------------------------------------- */
    1017                 : /*      Otherwise we can deal with SpatiaLite database.                 */
    1018                 : /* -------------------------------------------------------------------- */
    1019             940 :     sqlite3_free( pszErrMsg );
    1020                 :     rc = sqlite3_get_table( hDB,
    1021                 :                             "SELECT f_table_name, f_geometry_column, "
    1022                 :                             "type, coord_dimension, srid, "
    1023                 :                             "spatial_index_enabled FROM geometry_columns",
    1024                 :                             &papszResult, &nRowCount, 
    1025             940 :                             &nColCount, &pszErrMsg );
    1026             940 :     if (rc != SQLITE_OK )
    1027                 :     {
    1028                 :         /* Test with SpatiaLite 4.0 schema */
    1029              69 :         sqlite3_free( pszErrMsg );
    1030                 :         rc = sqlite3_get_table( hDB,
    1031                 :                                 "SELECT f_table_name, f_geometry_column, "
    1032                 :                                 "geometry_type, coord_dimension, srid, "
    1033                 :                                 "spatial_index_enabled FROM geometry_columns",
    1034                 :                                 &papszResult, &nRowCount,
    1035              69 :                                 &nColCount, &pszErrMsg );
    1036              69 :         if ( rc == SQLITE_OK )
    1037                 :         {
    1038               2 :             bSpatialite4Layout = TRUE;
    1039               2 :             nUndefinedSRID = 0;
    1040                 :         }
    1041                 :     }
    1042                 : 
    1043             940 :     if ( rc == SQLITE_OK )
    1044                 :     {
    1045             873 :         bIsSpatiaLiteDB = TRUE;
    1046             873 :         bHaveGeometryColumns = TRUE;
    1047                 : 
    1048             873 :         int iSpatialiteVersion = -1;
    1049                 : 
    1050                 :         /* Only enables write-mode if linked against SpatiaLite */
    1051             873 :         if( OGRSQLiteIsSpatialiteLoaded() )
    1052                 :         {
    1053             873 :             iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
    1054                 :         }
    1055               0 :         else if( bUpdate )
    1056                 :         {
    1057                 :             CPLDebug("SQLITE", "SpatiaLite%s DB found, "
    1058                 :                      "but updating tables disabled because no linking against spatialite library !",
    1059               0 :                      (bSpatialite4Layout) ? " v4" : "");
    1060               0 :             bUpdate = FALSE;
    1061                 :         }
    1062                 : 
    1063             875 :         if (bSpatialite4Layout && bUpdate && iSpatialiteVersion > 0 && iSpatialiteVersion < 40)
    1064                 :         {
    1065                 :             CPLDebug("SQLITE", "SpatiaLite v4 DB found, "
    1066                 :                      "but updating tables disabled because runtime spatialite library is v%.1f !",
    1067               2 :                      iSpatialiteVersion / 10.0);
    1068               2 :             bUpdate = FALSE;
    1069                 :         }
    1070                 :         else
    1071                 :         {
    1072                 :             CPLDebug("SQLITE", "SpatiaLite%s DB found !",
    1073             871 :                      (bSpatialite4Layout) ? " v4" : "");
    1074                 :         }
    1075                 : 
    1076            1092 :         for ( iRow = 0; iRow < nRowCount; iRow++ )
    1077                 :         {
    1078             219 :             char **papszRow = papszResult + iRow * 6 + 6;
    1079             219 :             const char* pszTableName = papszRow[0];
    1080             219 :             const char* pszGeomCol = papszRow[1];
    1081                 : 
    1082             219 :             if( pszTableName == NULL || pszGeomCol == NULL )
    1083               0 :                 continue;
    1084                 : 
    1085             219 :             aoMapTableToSetOfGeomCols[pszTableName].insert(pszGeomCol);
    1086                 :         }
    1087                 : 
    1088            1092 :         for ( iRow = 0; iRow < nRowCount; iRow++ )
    1089                 :         {
    1090             219 :             char **papszRow = papszResult + iRow * 6 + 6;
    1091             219 :             OGRwkbGeometryType eGeomType = wkbUnknown;
    1092             219 :             int nSRID = 0;
    1093             219 :             int bHasM = FALSE;
    1094             219 :             int bHasSpatialIndex = FALSE;
    1095             219 :             const char* pszTableName = papszRow[0];
    1096             219 :             const char* pszGeomCol = papszRow[1];
    1097                 : 
    1098             657 :             if (pszTableName == NULL ||
    1099                 :                 pszGeomCol == NULL ||
    1100             219 :                 papszRow[2] == NULL ||
    1101             219 :                 papszRow[3] == NULL)
    1102               0 :                 continue;
    1103                 : 
    1104             219 :             if( bSpatialite4Layout )
    1105                 :             {
    1106               2 :                 int nGeomType = atoi(papszRow[2]);
    1107                 : 
    1108               4 :                 if( nGeomType >= 0 && nGeomType <= 7 ) /* XY */
    1109               2 :                     eGeomType = (OGRwkbGeometryType) nGeomType;
    1110               0 :                 else if( nGeomType >= 1000 && nGeomType <= 1007 ) /* XYZ */
    1111               0 :                     eGeomType = (OGRwkbGeometryType) ((nGeomType - 1000) | wkb25DBit);
    1112               0 :                 else if( nGeomType >= 2000 && nGeomType <= 2007 ) /* XYM */
    1113                 :                 {
    1114               0 :                     eGeomType = (OGRwkbGeometryType) (nGeomType - 2000);
    1115               0 :                     bHasM = TRUE;
    1116                 :                 }
    1117               0 :                 else if( nGeomType >= 3000 && nGeomType <= 3007 ) /* XYZM */
    1118                 :                 {
    1119               0 :                     eGeomType = (OGRwkbGeometryType) ((nGeomType - 3000) | wkb25DBit);
    1120               0 :                     bHasM = TRUE;
    1121                 :                 }
    1122                 :             }
    1123                 :             else
    1124                 :             {
    1125             217 :                 eGeomType = OGRFromOGCGeomType(papszRow[2]);
    1126                 : 
    1127             603 :                 if( strcmp ( papszRow[3], "XYZ" ) == 0 ||
    1128             193 :                     strcmp ( papszRow[3], "XYZM" ) == 0 ||
    1129             193 :                     strcmp ( papszRow[3], "3" ) == 0) // SpatiaLite's own 3D geometries
    1130              24 :                     eGeomType = (OGRwkbGeometryType) (((int)eGeomType) | wkb25DBit);
    1131                 : 
    1132             434 :                 if( strcmp ( papszRow[3], "XYM" ) == 0 ||
    1133             217 :                     strcmp ( papszRow[3], "XYZM" ) == 0 ) // M coordinate declared
    1134               0 :                     bHasM = TRUE;
    1135                 :             }
    1136                 : 
    1137                 : 
    1138             219 :             if( papszRow[4] != NULL )
    1139             219 :                 nSRID = atoi(papszRow[4]);
    1140                 : 
    1141             219 :             if( papszRow[5] != NULL )
    1142             219 :                 bHasSpatialIndex = atoi(papszRow[5]);
    1143                 : 
    1144             219 :             int nOccurences = (int)aoMapTableToSetOfGeomCols[pszTableName].size();
    1145                 : 
    1146                 :             OpenTable( pszTableName, pszGeomCol, nOccurences > 1, eGeomType, "SpatiaLite",
    1147             219 :                        FetchSRS( nSRID ), nSRID, bHasSpatialIndex, bHasM );
    1148                 :                        
    1149             219 :             if (bListAllTables)
    1150               0 :                 CPLHashSetInsert(hSet, CPLStrdup(papszRow[0]));
    1151                 :         }
    1152                 : 
    1153             873 :         sqlite3_free_table(papszResult);
    1154                 : 
    1155                 : /* -------------------------------------------------------------------- */
    1156                 : /*      Detect VirtualShape, VirtualXL and VirtualOGR layers            */
    1157                 : /* -------------------------------------------------------------------- */
    1158                 :         rc = sqlite3_get_table( hDB,
    1159                 :                             "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
    1160                 :                             &papszResult, &nRowCount, 
    1161             873 :                             &nColCount, &pszErrMsg );
    1162                 : 
    1163             873 :         if ( rc == SQLITE_OK )
    1164                 :         {
    1165            2016 :             for( iRow = 0; iRow < nRowCount; iRow++ )
    1166                 :             {
    1167            1143 :                 char **papszRow = papszResult + iRow * 2 + 2;
    1168            1143 :                 const char *pszName = papszRow[0];
    1169            1143 :                 const char *pszSQL = papszRow[1];
    1170            1143 :                 if( pszName == NULL || pszSQL == NULL )
    1171               0 :                     continue;
    1172                 : 
    1173            1143 :                 if( (OGRSQLiteIsSpatialiteLoaded() &&
    1174                 :                         (strstr(pszSQL, "VirtualShape") || strstr(pszSQL, "VirtualXL"))) ||
    1175                 :                     (bListVirtualOGRLayers && strstr(pszSQL, "VirtualOGR")) )
    1176                 :                 {
    1177               2 :                     OpenVirtualTable(pszName, pszSQL);
    1178                 : 
    1179               2 :                     if (bListAllTables)
    1180               0 :                         CPLHashSetInsert(hSet, CPLStrdup(pszName));
    1181                 :                 }
    1182                 :             }
    1183                 :         }
    1184                 :         else
    1185                 :         {
    1186                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1187                 :                     "Unable to fetch list of tables: %s", 
    1188               0 :                     pszErrMsg );
    1189               0 :             sqlite3_free( pszErrMsg );
    1190                 :         }
    1191                 : 
    1192             873 :         sqlite3_free_table(papszResult);
    1193                 : 
    1194                 : /* -------------------------------------------------------------------- */
    1195                 : /*      Detect spatial views                                            */
    1196                 : /* -------------------------------------------------------------------- */
    1197                 :         rc = sqlite3_get_table( hDB,
    1198                 :                                 "SELECT view_name, view_geometry, view_rowid, f_table_name, f_geometry_column FROM views_geometry_columns",
    1199                 :                                 &papszResult, &nRowCount,
    1200             873 :                                 &nColCount, &pszErrMsg );
    1201             873 :         if ( rc == SQLITE_OK )
    1202                 :         {
    1203             874 :             for( iRow = 0; iRow < nRowCount; iRow++ )
    1204                 :             {
    1205               5 :                 char **papszRow = papszResult + iRow * 5 + 5;
    1206               5 :                 const char* pszViewName = papszRow[0];
    1207               5 :                 const char* pszViewGeometry = papszRow[1];
    1208               5 :                 const char* pszViewRowid = papszRow[2];
    1209               5 :                 const char* pszTableName = papszRow[3];
    1210               5 :                 const char* pszGeometryColumn = papszRow[4];
    1211                 : 
    1212               5 :                 if (pszViewName == NULL ||
    1213                 :                     pszViewGeometry == NULL ||
    1214                 :                     pszViewRowid == NULL ||
    1215                 :                     pszTableName == NULL ||
    1216                 :                     pszGeometryColumn == NULL)
    1217               0 :                     continue;
    1218                 : 
    1219                 :                 OpenView( pszViewName, pszViewGeometry, pszViewRowid,
    1220               5 :                           pszTableName, pszGeometryColumn );
    1221                 : 
    1222               5 :                 if (bListAllTables)
    1223               0 :                     CPLHashSetInsert(hSet, CPLStrdup(pszViewName));
    1224                 :             }
    1225             869 :             sqlite3_free_table(papszResult);
    1226                 :         }
    1227                 : 
    1228                 : 
    1229             873 :         if (bListAllTables)
    1230               0 :             goto all_tables;
    1231                 : 
    1232             873 :         CPLHashSetDestroy(hSet);
    1233                 :         
    1234             873 :         return TRUE;
    1235                 :     }
    1236                 : 
    1237                 : /* -------------------------------------------------------------------- */
    1238                 : /*      Otherwise our final resort is to return all tables and views    */
    1239                 : /*      as non-spatial tables.                                          */
    1240                 : /* -------------------------------------------------------------------- */
    1241              67 :     sqlite3_free( pszErrMsg );
    1242                 :     
    1243                 : all_tables:
    1244                 :     rc = sqlite3_get_table( hDB,
    1245                 :                             "SELECT name FROM sqlite_master "
    1246                 :                             "WHERE type IN ('table','view') "
    1247                 :                             "UNION ALL "
    1248                 :                             "SELECT name FROM sqlite_temp_master "
    1249                 :                             "WHERE type IN ('table','view') "
    1250                 :                             "ORDER BY 1",
    1251                 :                             &papszResult, &nRowCount, 
    1252              67 :                             &nColCount, &pszErrMsg );
    1253                 : 
    1254              67 :     if( rc != SQLITE_OK )
    1255                 :     {
    1256                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1257                 :                   "Unable to fetch list of tables: %s", 
    1258               0 :                   pszErrMsg );
    1259               0 :         sqlite3_free( pszErrMsg );
    1260               0 :         CPLHashSetDestroy(hSet);
    1261               0 :         return FALSE;
    1262                 :     }
    1263                 :     
    1264             143 :     for( iRow = 0; iRow < nRowCount; iRow++ )
    1265                 :     {
    1266              76 :         const char* pszTableName = papszResult[iRow+1];
    1267              76 :         if (CPLHashSetLookup(hSet, pszTableName) == NULL)
    1268              76 :             OpenTable( pszTableName );
    1269                 :     }
    1270                 :     
    1271              67 :     sqlite3_free_table(papszResult);
    1272              67 :     CPLHashSetDestroy(hSet);
    1273                 : 
    1274              67 :     return TRUE;
    1275                 : }
    1276                 : 
    1277                 : /************************************************************************/
    1278                 : /*                          OpenVirtualTable()                          */
    1279                 : /************************************************************************/
    1280                 : 
    1281              14 : int OGRSQLiteDataSource::OpenVirtualTable(const char* pszName, const char* pszSQL)
    1282                 : {
    1283              14 :     int nSRID = nUndefinedSRID;
    1284              14 :     const char* pszVirtualShape = strstr(pszSQL, "VirtualShape");
    1285              14 :     if (pszVirtualShape != NULL)
    1286                 :     {
    1287               4 :         const char* pszParenthesis = strchr(pszVirtualShape, '(');
    1288               4 :         if (pszParenthesis)
    1289                 :         {
    1290                 :             /* CREATE VIRTUAL TABLE table_name VirtualShape(shapename, codepage, srid) */
    1291                 :             /* Extract 3rd parameter */
    1292               4 :             char** papszTokens = CSLTokenizeString2( pszParenthesis + 1, ",", CSLT_HONOURSTRINGS );
    1293               4 :             if (CSLCount(papszTokens) == 3)
    1294                 :             {
    1295               4 :                 nSRID = atoi(papszTokens[2]);
    1296                 :             }
    1297               4 :             CSLDestroy(papszTokens);
    1298                 :         }
    1299                 :     }
    1300                 : 
    1301              14 :     if (OpenTable(pszName, NULL, FALSE, wkbUnknown, NULL,
    1302                 :                  (nSRID > 0) ? FetchSRS( nSRID ) : NULL, nSRID,
    1303                 :                   FALSE, FALSE,
    1304                 :                   pszVirtualShape != NULL))
    1305                 :     {
    1306              14 :         OGRSQLiteLayer* poLayer = papoLayers[nLayers-1];
    1307              14 :         OGRFeature* poFeature = poLayer->GetNextFeature();
    1308              14 :         if (poFeature)
    1309                 :         {
    1310              12 :             OGRGeometry* poGeom = poFeature->GetGeometryRef();
    1311              12 :             if (poGeom)
    1312              12 :                 poLayer->GetLayerDefn()->SetGeomType(poGeom->getGeometryType());
    1313              12 :             delete poFeature;
    1314                 :         }
    1315              14 :         poLayer->ResetReading();
    1316              14 :         return TRUE;
    1317                 :     }
    1318               0 :     return FALSE;
    1319                 : }
    1320                 : 
    1321                 : /************************************************************************/
    1322                 : /*                             OpenTable()                              */
    1323                 : /************************************************************************/
    1324                 : 
    1325             617 : int OGRSQLiteDataSource::OpenTable( const char *pszTableName,
    1326                 :                                     const char *pszGeomCol,
    1327                 :                                     int bMustIncludeGeomColName,
    1328                 :                                     OGRwkbGeometryType eGeomType,
    1329                 :                                     const char *pszGeomFormat,
    1330                 :                                     OGRSpatialReference *poSRS, int nSRID,
    1331                 :                                     int bHasSpatialIndex, int bHasM, 
    1332                 :                                     int bIsVirtualShapeIn )
    1333                 : 
    1334                 : {
    1335                 : /* -------------------------------------------------------------------- */
    1336                 : /*      Create the layer object.                                        */
    1337                 : /* -------------------------------------------------------------------- */
    1338                 :     OGRSQLiteTableLayer  *poLayer;
    1339                 : 
    1340             617 :     poLayer = new OGRSQLiteTableLayer( this );
    1341                 : 
    1342             617 :     if( poLayer->Initialize( pszTableName, pszGeomCol, bMustIncludeGeomColName,
    1343                 :                              eGeomType, pszGeomFormat,
    1344                 :                              poSRS, nSRID, bHasSpatialIndex, 
    1345                 :                              bHasM,
    1346                 :                              bIsVirtualShapeIn) != CE_None )
    1347                 :     {
    1348               0 :         delete poLayer;
    1349               0 :         return FALSE;
    1350                 :     }
    1351                 : 
    1352                 : /* -------------------------------------------------------------------- */
    1353                 : /*      Add layer to data source layer list.                            */
    1354                 : /* -------------------------------------------------------------------- */
    1355                 :     papoLayers = (OGRSQLiteLayer **)
    1356             617 :         CPLRealloc( papoLayers,  sizeof(OGRSQLiteLayer *) * (nLayers+1) );
    1357             617 :     papoLayers[nLayers++] = poLayer;
    1358                 :     
    1359             617 :     return TRUE;
    1360                 : }
    1361                 : 
    1362                 : /************************************************************************/
    1363                 : /*                             OpenView()                               */
    1364                 : /************************************************************************/
    1365                 : 
    1366               5 : int OGRSQLiteDataSource::OpenView( const char *pszViewName,
    1367                 :                                    const char *pszViewGeometry,
    1368                 :                                    const char *pszViewRowid,
    1369                 :                                    const char *pszTableName,
    1370                 :                                    const char *pszGeometryColumn)
    1371                 : 
    1372                 : {
    1373                 : /* -------------------------------------------------------------------- */
    1374                 : /*      Create the layer object.                                        */
    1375                 : /* -------------------------------------------------------------------- */
    1376                 :     OGRSQLiteViewLayer  *poLayer;
    1377                 : 
    1378               5 :     poLayer = new OGRSQLiteViewLayer( this );
    1379                 : 
    1380               5 :     if( poLayer->Initialize( pszViewName, pszViewGeometry,
    1381                 :                              pszViewRowid, pszTableName, pszGeometryColumn ) != CE_None )
    1382                 :     {
    1383               0 :         delete poLayer;
    1384               0 :         return FALSE;
    1385                 :     }
    1386                 : 
    1387                 : /* -------------------------------------------------------------------- */
    1388                 : /*      Add layer to data source layer list.                            */
    1389                 : /* -------------------------------------------------------------------- */
    1390                 :     papoLayers = (OGRSQLiteLayer **)
    1391               5 :         CPLRealloc( papoLayers,  sizeof(OGRSQLiteLayer *) * (nLayers+1) );
    1392               5 :     papoLayers[nLayers++] = poLayer;
    1393                 : 
    1394               5 :     return TRUE;
    1395                 : }
    1396                 : 
    1397                 : /************************************************************************/
    1398                 : /*                           TestCapability()                           */
    1399                 : /************************************************************************/
    1400                 : 
    1401              18 : int OGRSQLiteDataSource::TestCapability( const char * pszCap )
    1402                 : 
    1403                 : {
    1404              18 :     if( EQUAL(pszCap,ODsCCreateLayer) )
    1405               8 :         return bUpdate;
    1406              10 :     else if( EQUAL(pszCap,ODsCDeleteLayer) )
    1407               0 :         return bUpdate;
    1408                 :     else
    1409              10 :         return FALSE;
    1410                 : }
    1411                 : 
    1412                 : /************************************************************************/
    1413                 : /*                              GetLayer()                              */
    1414                 : /************************************************************************/
    1415                 : 
    1416             921 : OGRLayer *OGRSQLiteDataSource::GetLayer( int iLayer )
    1417                 : 
    1418                 : {
    1419             921 :     if( iLayer < 0 || iLayer >= nLayers )
    1420              20 :         return NULL;
    1421                 :     else
    1422             901 :         return papoLayers[iLayer];
    1423                 : }
    1424                 : 
    1425                 : /************************************************************************/
    1426                 : /*                           GetLayerByName()                           */
    1427                 : /************************************************************************/
    1428                 : 
    1429             386 : OGRLayer *OGRSQLiteDataSource::GetLayerByName( const char* pszLayerName )
    1430                 : 
    1431                 : {
    1432             386 :     OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszLayerName);
    1433             386 :     if( poLayer != NULL )
    1434             248 :         return poLayer;
    1435                 : 
    1436             138 :     if( !OpenTable(pszLayerName) )
    1437               0 :         return NULL;
    1438                 : 
    1439             138 :     poLayer = papoLayers[nLayers-1];
    1440             138 :     CPLErrorReset();
    1441             138 :     CPLPushErrorHandler(CPLQuietErrorHandler);
    1442             138 :     poLayer->GetLayerDefn();
    1443             138 :     CPLPopErrorHandler();
    1444             138 :     if( CPLGetLastErrorType() != 0 )
    1445                 :     {
    1446              84 :         delete poLayer;
    1447              84 :         nLayers --;
    1448              84 :         return NULL;
    1449                 :     }
    1450                 : 
    1451              54 :     return poLayer;
    1452                 : }
    1453                 : 
    1454                 : /************************************************************************/
    1455                 : /*                             ExecuteSQL()                             */
    1456                 : /************************************************************************/
    1457                 : 
    1458                 : static const char* apszFuncsWithSideEffects[] =
    1459                 : {
    1460                 :     "InitSpatialMetaData",
    1461                 :     "AddGeometryColumn",
    1462                 :     "RecoverGeometryColumn",
    1463                 :     "DiscardGeometryColumn",
    1464                 :     "CreateSpatialIndex",
    1465                 :     "CreateMbrCache",
    1466                 :     "DisableSpatialIndex",
    1467                 :     "UpdateLayerStatistics",
    1468                 : 
    1469                 :     "ogr_datasource_load_layers"
    1470                 : };
    1471                 : 
    1472             633 : OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
    1473                 :                                           OGRGeometry *poSpatialFilter,
    1474                 :                                           const char *pszDialect )
    1475                 : 
    1476                 : {
    1477             633 :     if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
    1478                 :         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
    1479                 :                                           poSpatialFilter, 
    1480               4 :                                           pszDialect );
    1481                 : 
    1482                 : /* -------------------------------------------------------------------- */
    1483                 : /*      Special case DELLAYER: command.                                 */
    1484                 : /* -------------------------------------------------------------------- */
    1485             629 :     if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
    1486                 :     {
    1487              22 :         const char *pszLayerName = pszSQLCommand + 9;
    1488                 : 
    1489              44 :         while( *pszLayerName == ' ' )
    1490               0 :             pszLayerName++;
    1491                 : 
    1492              22 :         DeleteLayer( pszLayerName );
    1493              22 :         return NULL;
    1494                 :     }
    1495                 : 
    1496                 : /* -------------------------------------------------------------------- */
    1497                 : /*      Special case GetVSILFILE() command (used by GDAL MBTiles driver)*/
    1498                 : /* -------------------------------------------------------------------- */
    1499             607 :     if (strcmp(pszSQLCommand, "GetVSILFILE()") == 0)
    1500                 :     {
    1501               1 :         if (fpMainFile == NULL)
    1502               0 :             return NULL;
    1503                 : 
    1504                 :         char szVal[64];
    1505               1 :         int nRet = CPLPrintPointer( szVal, fpMainFile, sizeof(szVal)-1 );
    1506               1 :         szVal[nRet] = '\0';
    1507               1 :         return new OGRSQLiteSingleFeatureLayer( "VSILFILE", szVal );
    1508                 :     }
    1509                 : 
    1510                 : /* -------------------------------------------------------------------- */
    1511                 : /*      Special case for SQLITE_HAS_COLUMN_METADATA()                   */
    1512                 : /* -------------------------------------------------------------------- */
    1513             606 :     if (strcmp(pszSQLCommand, "SQLITE_HAS_COLUMN_METADATA()") == 0)
    1514                 :     {
    1515                 : #ifdef SQLITE_HAS_COLUMN_METADATA
    1516               0 :         return new OGRSQLiteSingleFeatureLayer( "SQLITE_HAS_COLUMN_METADATA", TRUE );
    1517                 : #else
    1518                 :         return new OGRSQLiteSingleFeatureLayer( "SQLITE_HAS_COLUMN_METADATA", FALSE );
    1519                 : #endif
    1520                 :     }
    1521                 : 
    1522                 : /* -------------------------------------------------------------------- */
    1523                 : /*      In case, this is not a SELECT, invalidate cached feature        */
    1524                 : /*      count and extent to be on the safe side.                        */
    1525                 : /* -------------------------------------------------------------------- */
    1526             606 :     if( EQUAL(pszSQLCommand, "VACUUM") )
    1527                 :     {
    1528               1 :         int bNeedRefresh = -1;
    1529                 :         int i;
    1530               4 :         for( i = 0; i < nLayers; i++ )
    1531                 :         {
    1532               3 :             if( papoLayers[i]->IsTableLayer() )
    1533                 :             {
    1534               3 :                 OGRSQLiteTableLayer* poLayer = (OGRSQLiteTableLayer*) papoLayers[i];
    1535               3 :                 if ( !(poLayer->AreStatisticsValid()) ||
    1536                 :                      poLayer->DoStatisticsNeedToBeFlushed())
    1537                 :                 {
    1538               0 :                     bNeedRefresh = FALSE;
    1539               0 :                     break;
    1540                 :                 }
    1541               3 :                 else if( bNeedRefresh < 0 )
    1542               1 :                     bNeedRefresh = TRUE;
    1543                 :             }
    1544                 :         }
    1545               1 :         if( bNeedRefresh == TRUE )
    1546                 :         {
    1547               4 :             for( i = 0; i < nLayers; i++ )
    1548                 :             {
    1549               3 :                 if( papoLayers[i]->IsTableLayer() )
    1550                 :                 {
    1551               3 :                     OGRSQLiteTableLayer* poLayer = (OGRSQLiteTableLayer*) papoLayers[i];
    1552               3 :                     poLayer->ForceStatisticsToBeFlushed();
    1553                 :                 }
    1554                 :             }
    1555                 :         }
    1556                 :     }
    1557             605 :     else if( !EQUALN(pszSQLCommand,"SELECT ",7) && !EQUAL(pszSQLCommand, "BEGIN")
    1558                 :         && !EQUAL(pszSQLCommand, "COMMIT")
    1559                 :         && !EQUALN(pszSQLCommand, "CREATE TABLE ", strlen("CREATE TABLE ")) )
    1560                 :     {
    1561             332 :         for(int i = 0; i < nLayers; i++)
    1562             249 :             papoLayers[i]->InvalidateCachedFeatureCountAndExtent();
    1563                 :     }
    1564                 : 
    1565                 :     bLastSQLCommandIsUpdateLayerStatistics =
    1566             606 :         EQUAL(pszSQLCommand, "SELECT UpdateLayerStatistics()");
    1567                 : 
    1568                 : /* -------------------------------------------------------------------- */
    1569                 : /*      Prepare statement.                                              */
    1570                 : /* -------------------------------------------------------------------- */
    1571                 :     int rc;
    1572             606 :     sqlite3_stmt *hSQLStmt = NULL;
    1573                 : 
    1574             606 :     CPLString osSQLCommand = pszSQLCommand;
    1575                 : 
    1576                 :     /* This will speed-up layer creation */
    1577                 :     /* ORDER BY are costly to evaluate and are not necessary to establish */
    1578                 :     /* the layer definition. */
    1579             606 :     int bUseStatementForGetNextFeature = TRUE;
    1580             606 :     int bEmptyLayer = FALSE;
    1581                 : 
    1582             606 :     if( osSQLCommand.ifind("SELECT ") == 0 &&
    1583                 :         osSQLCommand.ifind(" UNION ") == std::string::npos &&
    1584                 :         osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
    1585                 :         osSQLCommand.ifind(" EXCEPT ") == std::string::npos )
    1586                 :     {
    1587             428 :         size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY ");
    1588             428 :         if( nOrderByPos != std::string::npos )
    1589                 :         {
    1590              37 :             osSQLCommand.resize(nOrderByPos);
    1591              37 :             bUseStatementForGetNextFeature = FALSE;
    1592                 :         }
    1593                 :     }
    1594                 : 
    1595                 :     rc = sqlite3_prepare( GetDB(), osSQLCommand.c_str(), osSQLCommand.size(),
    1596             606 :                           &hSQLStmt, NULL );
    1597                 : 
    1598             606 :     if( rc != SQLITE_OK )
    1599                 :     {
    1600                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1601                 :                 "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s", 
    1602              14 :                 pszSQLCommand, sqlite3_errmsg(GetDB()) );
    1603                 : 
    1604              14 :         if( hSQLStmt != NULL )
    1605                 :         {
    1606               0 :             sqlite3_finalize( hSQLStmt );
    1607                 :         }
    1608                 : 
    1609              14 :         return NULL;
    1610                 :     }
    1611                 : 
    1612                 : /* -------------------------------------------------------------------- */
    1613                 : /*      Do we get a resultset?                                          */
    1614                 : /* -------------------------------------------------------------------- */
    1615             592 :     rc = sqlite3_step( hSQLStmt );
    1616             592 :     if( rc != SQLITE_ROW )
    1617                 :     {
    1618             214 :         if ( rc != SQLITE_DONE )
    1619                 :         {
    1620                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1621                 :                   "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
    1622              12 :                   pszSQLCommand, sqlite3_errmsg(GetDB()) );
    1623                 : 
    1624              12 :             sqlite3_finalize( hSQLStmt );
    1625              12 :             return NULL;
    1626                 :         }
    1627                 : 
    1628             202 :         if( EQUALN(pszSQLCommand, "CREATE ", 7) )
    1629                 :         {
    1630              66 :             char **papszTokens = CSLTokenizeString( pszSQLCommand );
    1631             142 :             if ( CSLCount(papszTokens) >= 4 &&
    1632              66 :                  EQUAL(papszTokens[1], "VIRTUAL") &&
    1633              10 :                  EQUAL(papszTokens[2], "TABLE") )
    1634                 :             {
    1635              10 :                 OpenVirtualTable(papszTokens[3], pszSQLCommand);
    1636                 :             }
    1637              66 :             CSLDestroy(papszTokens);
    1638                 : 
    1639              66 :             sqlite3_finalize( hSQLStmt );
    1640              66 :             return NULL;
    1641                 :         }
    1642                 : 
    1643             136 :         if( !EQUALN(pszSQLCommand, "SELECT ", 7) )
    1644                 :         {
    1645              92 :             sqlite3_finalize( hSQLStmt );
    1646              92 :             return NULL;
    1647                 :         }
    1648                 : 
    1649              44 :         bUseStatementForGetNextFeature = FALSE;
    1650              44 :         bEmptyLayer = TRUE;
    1651                 :     }
    1652                 :     
    1653                 : /* -------------------------------------------------------------------- */
    1654                 : /*      Special case for some functions which must be run               */
    1655                 : /*      only once                                                       */
    1656                 : /* -------------------------------------------------------------------- */
    1657             422 :     if( EQUALN(pszSQLCommand,"SELECT ",7) )
    1658                 :     {
    1659                 :         unsigned int i;
    1660            3910 :         for(i=0;i<sizeof(apszFuncsWithSideEffects)/
    1661                 :                   sizeof(apszFuncsWithSideEffects[0]);i++)
    1662                 :         {
    1663            3556 :             if( EQUALN(apszFuncsWithSideEffects[i], pszSQLCommand + 7,
    1664                 :                        strlen(apszFuncsWithSideEffects[i])) )
    1665                 :             {
    1666              68 :                 if (sqlite3_column_count( hSQLStmt ) == 1 &&
    1667                 :                     sqlite3_column_type( hSQLStmt, 0 ) == SQLITE_INTEGER )
    1668                 :                 {
    1669              68 :                     int ret = sqlite3_column_int( hSQLStmt, 0 );
    1670                 : 
    1671              68 :                     sqlite3_finalize( hSQLStmt );
    1672                 : 
    1673                 :                     return new OGRSQLiteSingleFeatureLayer
    1674              68 :                                         ( apszFuncsWithSideEffects[i], ret );
    1675                 :                 }
    1676                 :             }
    1677                 :         }
    1678                 :     }
    1679                 : 
    1680                 : /* -------------------------------------------------------------------- */
    1681                 : /*      Create layer.                                                   */
    1682                 : /* -------------------------------------------------------------------- */
    1683             354 :     OGRSQLiteSelectLayer *poLayer = NULL;
    1684                 :         
    1685             354 :     CPLString osSQL = pszSQLCommand;
    1686                 :     poLayer = new OGRSQLiteSelectLayer( this, osSQL, hSQLStmt,
    1687             354 :                                         bUseStatementForGetNextFeature, bEmptyLayer );
    1688                 : 
    1689             354 :     if( poSpatialFilter != NULL )
    1690               0 :         poLayer->SetSpatialFilter( poSpatialFilter );
    1691                 :     
    1692             354 :     return poLayer;
    1693                 : }
    1694                 : 
    1695                 : /************************************************************************/
    1696                 : /*                          ReleaseResultSet()                          */
    1697                 : /************************************************************************/
    1698                 : 
    1699             441 : void OGRSQLiteDataSource::ReleaseResultSet( OGRLayer * poLayer )
    1700                 : 
    1701                 : {
    1702             441 :     delete poLayer;
    1703             441 : }
    1704                 : 
    1705                 : /************************************************************************/
    1706                 : /*                            CreateLayer()                             */
    1707                 : /************************************************************************/
    1708                 : 
    1709                 : OGRLayer *
    1710             127 : OGRSQLiteDataSource::CreateLayer( const char * pszLayerNameIn,
    1711                 :                                   OGRSpatialReference *poSRS,
    1712                 :                                   OGRwkbGeometryType eType,
    1713                 :                                   char ** papszOptions )
    1714                 : 
    1715                 : {
    1716                 :     char                *pszLayerName;
    1717                 :     const char          *pszGeomFormat;
    1718             127 :     int                  bImmediateSpatialIndexCreation = FALSE;
    1719             127 :     int                  bDeferedSpatialIndexCreation = FALSE;
    1720                 : 
    1721                 : /* -------------------------------------------------------------------- */
    1722                 : /*      Verify we are in update mode.                                   */
    1723                 : /* -------------------------------------------------------------------- */
    1724             127 :     if( !bUpdate )
    1725                 :     {
    1726                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
    1727                 :                   "Data source %s opened read-only.\n"
    1728                 :                   "New layer %s cannot be created.\n",
    1729               2 :                   pszName, pszLayerNameIn );
    1730                 : 
    1731               2 :         return NULL;
    1732                 :     }
    1733                 : 
    1734             125 :     if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
    1735             124 :         pszLayerName = LaunderName( pszLayerNameIn );
    1736                 :     else
    1737               1 :         pszLayerName = CPLStrdup( pszLayerNameIn );
    1738                 : 
    1739             125 :     CPLString osEscapedLayerName = OGRSQLiteEscape(pszLayerName);
    1740             125 :     const char* pszEscapedLayerName = osEscapedLayerName.c_str();
    1741                 :     
    1742             125 :     pszGeomFormat = CSLFetchNameValue( papszOptions, "FORMAT" );
    1743             125 :     if( pszGeomFormat == NULL )
    1744                 :     {
    1745             116 :         if ( !bIsSpatiaLiteDB )
    1746              46 :             pszGeomFormat = "WKB";
    1747                 :         else
    1748              70 :             pszGeomFormat = "SpatiaLite";
    1749                 :     }
    1750                 : 
    1751             125 :     if( !EQUAL(pszGeomFormat,"WKT") 
    1752                 :         && !EQUAL(pszGeomFormat,"WKB")
    1753                 :         && !EQUAL(pszGeomFormat, "SpatiaLite") )
    1754                 :     {
    1755                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1756                 :                   "FORMAT=%s not recognised or supported.", 
    1757               2 :                   pszGeomFormat );
    1758               2 :         CPLFree( pszLayerName );
    1759               2 :         return NULL;
    1760                 :     }
    1761                 : 
    1762             123 :     if (bIsSpatiaLiteDB && !EQUAL(pszGeomFormat, "SpatiaLite") )
    1763                 :     {
    1764                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1765                 :                   "FORMAT=%s not supported on a SpatiaLite enabled database.",
    1766               1 :                   pszGeomFormat );
    1767               1 :         CPLFree( pszLayerName );
    1768               1 :         return NULL;
    1769                 :     }
    1770                 : 
    1771                 :     /* Shouldn't happen since a spatialite DB should be opened in read-only mode */
    1772                 :     /* if libspatialite isn't loaded */
    1773             122 :     if (bIsSpatiaLiteDB && !OGRSQLiteIsSpatialiteLoaded())
    1774                 :     {
    1775                 :         CPLError( CE_Failure, CPLE_NotSupported,
    1776                 :                   "Creating layers on a SpatiaLite enabled database, "
    1777               0 :                   "without Spatialite extensions loaded, is not supported." );
    1778               0 :         CPLFree( pszLayerName );
    1779               0 :         return NULL;
    1780                 :     }
    1781                 : 
    1782                 : /* -------------------------------------------------------------------- */
    1783                 : /*      Do we already have this layer?  If so, should we blow it        */
    1784                 : /*      away?                                                           */
    1785                 : /* -------------------------------------------------------------------- */
    1786                 :     int iLayer;
    1787                 : 
    1788            1221 :     for( iLayer = 0; iLayer < nLayers; iLayer++ )
    1789                 :     {
    1790            1101 :         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
    1791                 :         {
    1792               4 :             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
    1793                 :                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
    1794                 :             {
    1795               2 :                 DeleteLayer( pszLayerName );
    1796                 :             }
    1797                 :             else
    1798                 :             {
    1799                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
    1800                 :                           "Layer %s already exists, CreateLayer failed.\n"
    1801                 :                           "Use the layer creation option OVERWRITE=YES to "
    1802                 :                           "replace it.",
    1803               2 :                           pszLayerName );
    1804               2 :                 CPLFree( pszLayerName );
    1805               2 :                 return NULL;
    1806                 :             }
    1807                 :         }
    1808                 :     }
    1809                 : 
    1810                 : /* -------------------------------------------------------------------- */
    1811                 : /*      Try to get the SRS Id of this spatial reference system,         */
    1812                 : /*      adding to the srs table if needed.                              */
    1813                 : /* -------------------------------------------------------------------- */
    1814             120 :     int nSRSId = nUndefinedSRID;
    1815             120 :     const char* pszSRID = CSLFetchNameValue(papszOptions, "SRID");
    1816                 : 
    1817             120 :     if( pszSRID != NULL )
    1818                 :     {
    1819               6 :         nSRSId = atoi(pszSRID);
    1820               6 :         if( nSRSId > 0 )
    1821                 :         {
    1822               6 :             OGRSpatialReference* poSRSFetched = FetchSRS( nSRSId );
    1823               6 :             if( poSRSFetched == NULL )
    1824                 :             {
    1825                 :                 CPLError(CE_Warning, CPLE_AppDefined,
    1826                 :                          "SRID %d will be used, but no matching SRS is defined in spatial_ref_sys",
    1827               3 :                          nSRSId);
    1828                 :             }
    1829                 :         }
    1830                 :     }
    1831             114 :     else if( poSRS != NULL )
    1832              80 :         nSRSId = FetchSRSId( poSRS );
    1833                 : 
    1834                 : /* -------------------------------------------------------------------- */
    1835                 : /*      Create a basic table with the FID.  Also include the            */
    1836                 : /*      geometry if this is not a PostGIS enabled table.                */
    1837                 : /* -------------------------------------------------------------------- */
    1838                 :     int rc;
    1839                 :     char *pszErrMsg;
    1840             120 :     const char *pszGeomCol = NULL;
    1841             120 :     CPLString osCommand;
    1842                 : 
    1843             120 :     if( eType == wkbNone )
    1844                 :         osCommand.Printf( 
    1845                 :             "CREATE TABLE '%s' ( OGC_FID INTEGER PRIMARY KEY )", 
    1846               8 :             pszEscapedLayerName );
    1847                 :     else
    1848                 :     {
    1849             112 :         if( EQUAL(pszGeomFormat,"WKT") )
    1850                 :         {
    1851               2 :             pszGeomCol = "WKT_GEOMETRY";
    1852                 :             osCommand.Printf(
    1853                 :                 "CREATE TABLE '%s' ( "
    1854                 :                 "  OGC_FID INTEGER PRIMARY KEY,"
    1855                 :                 "  '%s' VARCHAR )", 
    1856                 :                 pszEscapedLayerName,
    1857               2 :                 OGRSQLiteEscape(pszGeomCol).c_str() );
    1858                 :         }
    1859                 :         else
    1860                 :         {
    1861             110 :             pszGeomCol = "GEOMETRY";
    1862                 : 
    1863                 :             /* Only if was created as a SpatiaLite DB */
    1864             110 :             if ( bIsSpatiaLiteDB )
    1865                 :             {
    1866                 :                 /* 
    1867                 :                 / SpatiaLite full support: we must create the 
    1868                 :                 / Geometry in a second time using AddGeometryColumn()
    1869                 :                 /
    1870                 :                 / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
    1871                 :                 / to directly creating some Geometry column 
    1872                 :                 / [by-passing AddGeometryColumn() as absolutely required]
    1873                 :                 / will severely [and irremediably] corrupt the DB !!!
    1874                 :                 */
    1875                 :                 osCommand.Printf( "CREATE TABLE '%s' ( "
    1876                 :                                   "  OGC_FID INTEGER PRIMARY KEY)",
    1877              70 :                                   pszEscapedLayerName);
    1878                 :             }
    1879                 :             else
    1880                 :             {
    1881                 :                 osCommand.Printf( "CREATE TABLE '%s' ( "
    1882                 :                                   "  OGC_FID INTEGER PRIMARY KEY,"
    1883                 :                                   "  '%s' BLOB )", 
    1884                 :                                   pszEscapedLayerName,
    1885              40 :                                   OGRSQLiteEscape(pszGeomCol).c_str() );
    1886                 :             }
    1887                 :         }
    1888                 :     }
    1889                 : 
    1890                 : #ifdef DEBUG
    1891             120 :     CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
    1892                 : #endif
    1893                 : 
    1894             120 :     rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
    1895             120 :     if( rc != SQLITE_OK )
    1896                 :     {
    1897                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1898                 :                   "Unable to create table %s: %s",
    1899               0 :                   pszLayerName, pszErrMsg );
    1900               0 :         sqlite3_free( pszErrMsg );
    1901               0 :         return FALSE;
    1902                 :     }
    1903                 : 
    1904                 : /* -------------------------------------------------------------------- */
    1905                 : /*      Eventually we should be adding this table to a table of         */
    1906                 : /*      "geometric layers", capturing the WKT projection, and           */
    1907                 : /*      perhaps some other housekeeping.                                */
    1908                 : /* -------------------------------------------------------------------- */
    1909             120 :     if( bHaveGeometryColumns && eType != wkbNone )
    1910                 :     {
    1911                 :         int nCoordDim;
    1912                 : 
    1913                 :         /* Sometimes there is an old cruft entry in the geometry_columns
    1914                 :          * table if things were not properly cleaned up before.  We make
    1915                 :          * an effort to clean out such cruft.
    1916                 :          */
    1917                 :         osCommand.Printf(
    1918                 :             "DELETE FROM geometry_columns WHERE f_table_name = '%s'", 
    1919             112 :             pszEscapedLayerName );
    1920                 :                  
    1921                 : #ifdef DEBUG
    1922             112 :         CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
    1923                 : #endif
    1924                 : 
    1925             112 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
    1926             112 :         if( rc != SQLITE_OK )
    1927                 :         {
    1928               0 :             sqlite3_free( pszErrMsg );
    1929               0 :             return FALSE;
    1930                 :         }
    1931                 :         
    1932             112 :         if( eType == wkbFlatten(eType) )
    1933              88 :             nCoordDim = 2;
    1934                 :         else
    1935              24 :             nCoordDim = 3;
    1936                 :         
    1937             112 :         if ( bIsSpatiaLiteDB )
    1938                 :         {
    1939                 :             /*
    1940                 :             / SpatiaLite full support: calling AddGeometryColumn()
    1941                 :             /
    1942                 :             / IMPORTANT NOTICE: on SpatiaLite any attempt aimed
    1943                 :             / to directly INSERT a row into GEOMETRY_COLUMNS
    1944                 :             / [by-passing AddGeometryColumn() as absolutely required]
    1945                 :             / will severely [and irremediably] corrupt the DB !!!
    1946                 :             */
    1947              70 :             const char *pszType = OGRToOGCGeomType(eType);
    1948              70 :             if (pszType[0] == '\0')
    1949               0 :                 pszType = "GEOMETRY";
    1950                 : 
    1951                 :             /*
    1952                 :             / SpatiaLite v.2.4.0 (or any subsequent) is required
    1953                 :             / to support 2.5D: if an obsolete version of the library
    1954                 :             / is found we'll unconditionally activate 2D casting mode
    1955                 :             */
    1956              70 :             int iSpatialiteVersion = OGRSQLiteGetSpatialiteVersionNumber();
    1957              70 :             if ( iSpatialiteVersion < 24 && nCoordDim == 3 )
    1958                 :             {
    1959               0 :                 CPLDebug("SQLITE", "Spatialite < 2.4.0 --> 2.5D geometry not supported. Casting to 2D");
    1960               0 :                 nCoordDim = 2;
    1961                 :             }
    1962                 : 
    1963                 :             osCommand.Printf( "SELECT AddGeometryColumn("
    1964                 :                               "'%s', '%s', %d, '%s', %d)",
    1965                 :                               pszEscapedLayerName,
    1966                 :                               OGRSQLiteEscape(pszGeomCol).c_str(), nSRSId,
    1967              70 :                               pszType, nCoordDim );
    1968                 :         }
    1969                 :         else
    1970                 :         {
    1971              42 :             if( nSRSId > 0 )
    1972                 :             {
    1973                 :                 osCommand.Printf(
    1974                 :                     "INSERT INTO geometry_columns "
    1975                 :                     "(f_table_name, f_geometry_column, geometry_format, "
    1976                 :                     "geometry_type, coord_dimension, srid) VALUES "
    1977                 :                     "('%s','%s','%s', %d, %d, %d)", 
    1978                 :                     pszEscapedLayerName,
    1979                 :                     OGRSQLiteEscape(pszGeomCol).c_str(), pszGeomFormat,
    1980              16 :                     (int) wkbFlatten(eType), nCoordDim, nSRSId );
    1981                 :             }
    1982                 :             else
    1983                 :             {
    1984                 :                 osCommand.Printf(
    1985                 :                     "INSERT INTO geometry_columns "
    1986                 :                     "(f_table_name, f_geometry_column, geometry_format, "
    1987                 :                     "geometry_type, coord_dimension) VALUES "
    1988                 :                     "('%s','%s','%s', %d, %d)",
    1989                 :                     pszEscapedLayerName,
    1990                 :                     OGRSQLiteEscape(pszGeomCol).c_str(), pszGeomFormat,
    1991              26 :                     (int) wkbFlatten(eType), nCoordDim );
    1992                 :             }
    1993                 :         }
    1994                 : 
    1995                 : #ifdef DEBUG
    1996             112 :         CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
    1997                 : #endif
    1998                 : 
    1999             112 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
    2000             112 :         if( rc != SQLITE_OK )
    2001                 :         {
    2002                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2003                 :                       "Unable to add %s table to geometry_columns:\n%s",
    2004               0 :                       pszLayerName, pszErrMsg );
    2005               0 :             sqlite3_free( pszErrMsg );
    2006               0 :             return FALSE;
    2007                 :         }
    2008                 : 
    2009                 : /* -------------------------------------------------------------------- */
    2010                 : /*      Create the spatial index.                                       */
    2011                 : /*                                                                      */
    2012                 : /*      We're doing this before we add geometry and record to the table */
    2013                 : /*      so this may not be exactly the best way to do it.               */
    2014                 : /* -------------------------------------------------------------------- */
    2015                 : 
    2016             112 :         const char* pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
    2017             112 :         if ( pszSI != NULL && CSLTestBoolean(pszSI) &&
    2018                 :              (bIsSpatiaLiteDB || EQUAL(pszGeomFormat, "SpatiaLite")) && !OGRSQLiteIsSpatialiteLoaded() )
    2019                 :         {
    2020                 :             CPLError( CE_Warning, CPLE_OpenFailed,
    2021               0 :                     "Cannot create a spatial index when Spatialite extensions are not loaded." );
    2022                 :         }
    2023                 : 
    2024                 : #ifdef HAVE_SPATIALITE
    2025                 :         /* Only if linked against SpatiaLite and the datasource was created as a SpatiaLite DB */
    2026             112 :         if ( bIsSpatiaLiteDB && OGRSQLiteIsSpatialiteLoaded() )
    2027                 : #else
    2028                 :         if ( 0 )
    2029                 : #endif
    2030                 :         {
    2031              70 :             if( pszSI != NULL && EQUAL(pszSI, "IMMEDIATE") )
    2032                 :             {
    2033               0 :                 bImmediateSpatialIndexCreation = TRUE;
    2034                 :             }
    2035              70 :             else if( pszSI == NULL || CSLTestBoolean(pszSI) )
    2036                 :             {
    2037              70 :                 bDeferedSpatialIndexCreation = TRUE;
    2038                 :             }
    2039                 :         }
    2040                 :     }
    2041                 : 
    2042                 : /* -------------------------------------------------------------------- */
    2043                 : /*      Create the layer object.                                        */
    2044                 : /* -------------------------------------------------------------------- */
    2045                 :     OGRSQLiteTableLayer     *poLayer;
    2046                 : 
    2047             120 :     poLayer = new OGRSQLiteTableLayer( this );
    2048                 : 
    2049             240 :     if ( poLayer->Initialize( pszLayerName, pszGeomCol, FALSE, eType, pszGeomFormat,
    2050                 :                               FetchSRS(nSRSId), nSRSId, FALSE, FALSE,
    2051                 :                               FALSE ) != CE_None )
    2052                 :     {
    2053               0 :         delete poLayer;
    2054               0 :         CPLFree( pszLayerName );
    2055               0 :         return NULL;
    2056                 :     }
    2057                 : 
    2058             120 :     poLayer->InitFeatureCount();
    2059             120 :     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
    2060             120 :     if ( CSLFetchBoolean(papszOptions,"COMPRESS_GEOM",FALSE) )
    2061              32 :         poLayer->SetUseCompressGeom( TRUE );
    2062             120 :     if( bImmediateSpatialIndexCreation )
    2063               0 :         poLayer->CreateSpatialIndex();
    2064             120 :     else if( bDeferedSpatialIndexCreation )
    2065              70 :         poLayer->SetDeferedSpatialIndexCreation( TRUE );
    2066             120 :     poLayer->SetCompressedColumns( CSLFetchNameValue(papszOptions,"COMPRESS_COLUMNS") );
    2067                 : 
    2068             120 :     if( bIsSpatiaLiteDB && nLayers == 0)
    2069                 :     {
    2070                 :         /* To create the layer_statistics and spatialite_history tables */
    2071               5 :         sqlite3_exec( hDB, "SELECT UpdateLayerStatistics()", NULL, NULL, NULL );
    2072                 :     }
    2073                 : 
    2074                 : /* -------------------------------------------------------------------- */
    2075                 : /*      Add layer to data source layer list.                            */
    2076                 : /* -------------------------------------------------------------------- */
    2077                 :     papoLayers = (OGRSQLiteLayer **)
    2078             120 :         CPLRealloc( papoLayers,  sizeof(OGRSQLiteLayer *) * (nLayers+1) );
    2079                 :     
    2080             120 :     papoLayers[nLayers++] = poLayer;
    2081                 : 
    2082             120 :     CPLFree( pszLayerName );
    2083                 : 
    2084             120 :     return poLayer;
    2085                 : }
    2086                 : 
    2087                 : /************************************************************************/
    2088                 : /*                            LaunderName()                             */
    2089                 : /************************************************************************/
    2090                 : 
    2091             205 : char *OGRSQLiteDataSource::LaunderName( const char *pszSrcName )
    2092                 : 
    2093                 : {
    2094             205 :     char    *pszSafeName = CPLStrdup( pszSrcName );
    2095                 :     int     i;
    2096                 : 
    2097            1546 :     for( i = 0; pszSafeName[i] != '\0'; i++ )
    2098                 :     {
    2099            1341 :         pszSafeName[i] = (char) tolower( pszSafeName[i] );
    2100            1341 :         if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
    2101               0 :             pszSafeName[i] = '_';
    2102                 :     }
    2103                 : 
    2104             205 :     return pszSafeName;
    2105                 : }
    2106                 : 
    2107                 : /************************************************************************/
    2108                 : /*                       OGRSQLiteParamsUnquote()                       */
    2109                 : /************************************************************************/
    2110                 : 
    2111            8489 : CPLString OGRSQLiteParamsUnquote(const char* pszVal)
    2112                 : {
    2113            8489 :     char chQuoteChar = pszVal[0];
    2114            8489 :     if( chQuoteChar != '\'' && chQuoteChar != '"' )
    2115            8148 :         return pszVal;
    2116                 :     
    2117             341 :     CPLString osRet;
    2118             341 :     pszVal ++;
    2119            2930 :     while( *pszVal != '\0' )
    2120                 :     {
    2121            2589 :         if( *pszVal == chQuoteChar )
    2122                 :         {
    2123             347 :             if( pszVal[1] == chQuoteChar )
    2124               6 :                 pszVal ++;
    2125                 :             else
    2126             341 :                 break;
    2127                 :         }
    2128            2248 :         osRet += *pszVal;
    2129            2248 :         pszVal ++;
    2130                 :     }
    2131             341 :     return osRet;
    2132                 : }
    2133                 : 
    2134                 : /************************************************************************/
    2135                 : /*                          OGRSQLiteEscape()                           */
    2136                 : /************************************************************************/
    2137                 : 
    2138            2658 : CPLString OGRSQLiteEscape( const char *pszLiteral )
    2139                 : {
    2140            2658 :     CPLString osVal;
    2141           22786 :     for( int i = 0; pszLiteral[i] != '\0'; i++ )
    2142                 :     {
    2143           20128 :         if ( pszLiteral[i] == '\'' )
    2144              14 :             osVal += '\'';
    2145           20128 :         osVal += pszLiteral[i];
    2146                 :     }
    2147               0 :     return osVal;
    2148                 : }
    2149                 : 
    2150                 : /************************************************************************/
    2151                 : /*                        OGRSQLiteEscapeName()                         */
    2152                 : /************************************************************************/
    2153                 : 
    2154            4270 : CPLString OGRSQLiteEscapeName(const char* pszName)
    2155                 : {
    2156            4270 :     CPLString osRet;
    2157           44504 :     while( *pszName != '\0' )
    2158                 :     {
    2159           35964 :         if( *pszName == '"' )
    2160               8 :             osRet += "\"\"";
    2161                 :         else
    2162           35956 :             osRet += *pszName;
    2163           35964 :         pszName ++;
    2164                 :     }
    2165               0 :     return osRet;
    2166                 : }
    2167                 : 
    2168                 : /************************************************************************/
    2169                 : /*                            DeleteLayer()                             */
    2170                 : /************************************************************************/
    2171                 : 
    2172              24 : void OGRSQLiteDataSource::DeleteLayer( const char *pszLayerName )
    2173                 : 
    2174                 : {
    2175                 :     int iLayer;
    2176                 : 
    2177                 : /* -------------------------------------------------------------------- */
    2178                 : /*      Verify we are in update mode.                                   */
    2179                 : /* -------------------------------------------------------------------- */
    2180              24 :     if( !bUpdate )
    2181                 :     {
    2182                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
    2183                 :                   "Data source %s opened read-only.\n"
    2184                 :                   "Layer %s cannot be deleted.\n",
    2185               0 :                   pszName, pszLayerName );
    2186                 : 
    2187               0 :         return;
    2188                 :     }
    2189                 : 
    2190                 : /* -------------------------------------------------------------------- */
    2191                 : /*      Try to find layer.                                              */
    2192                 : /* -------------------------------------------------------------------- */
    2193              78 :     for( iLayer = 0; iLayer < nLayers; iLayer++ )
    2194                 :     {
    2195              76 :         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
    2196              22 :             break;
    2197                 :     }
    2198                 : 
    2199              24 :     if( iLayer == nLayers )
    2200                 :     {
    2201                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2202                 :                   "Attempt to delete layer '%s', but this layer is not known to OGR.", 
    2203               2 :                   pszLayerName );
    2204               2 :         return;
    2205                 :     }
    2206                 : 
    2207              22 :     DeleteLayer(iLayer);
    2208                 : }
    2209                 : 
    2210                 : /************************************************************************/
    2211                 : /*                            DeleteLayer()                             */
    2212                 : /************************************************************************/
    2213                 : 
    2214              22 : OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
    2215                 : {
    2216              22 :     if( iLayer < 0 || iLayer >= nLayers )
    2217                 :     {
    2218                 :         CPLError( CE_Failure, CPLE_AppDefined,
    2219                 :                   "Layer %d not in legal range of 0 to %d.",
    2220               0 :                   iLayer, nLayers-1 );
    2221               0 :         return OGRERR_FAILURE;
    2222                 :     }
    2223                 : 
    2224              22 :     CPLString osLayerName = GetLayer(iLayer)->GetName();
    2225              22 :     CPLString osGeometryColumn = GetLayer(iLayer)->GetGeometryColumn();
    2226                 : 
    2227                 : /* -------------------------------------------------------------------- */
    2228                 : /*      Blow away our OGR structures related to the layer.  This is     */
    2229                 : /*      pretty dangerous if anything has a reference to this layer!     */
    2230                 : /* -------------------------------------------------------------------- */
    2231              22 :     CPLDebug( "OGR_SQLITE", "DeleteLayer(%s)", osLayerName.c_str() );
    2232                 : 
    2233              22 :     delete papoLayers[iLayer];
    2234                 :     memmove( papoLayers + iLayer, papoLayers + iLayer + 1, 
    2235              22 :              sizeof(void *) * (nLayers - iLayer - 1) );
    2236              22 :     nLayers--;
    2237                 : 
    2238                 : /* -------------------------------------------------------------------- */
    2239                 : /*      Remove from the database.                                       */
    2240                 : /* -------------------------------------------------------------------- */
    2241                 :     int rc;
    2242                 :     char *pszErrMsg;
    2243                 : 
    2244              22 :     CPLString osEscapedLayerName = OGRSQLiteEscape(osLayerName);
    2245              22 :     const char* pszEscapedLayerName = osEscapedLayerName.c_str();
    2246              22 :     const char* pszGeometryColumn = osGeometryColumn.size() ? osGeometryColumn.c_str() : NULL;
    2247                 : 
    2248                 :     rc = sqlite3_exec( hDB, CPLSPrintf( "DROP TABLE '%s'", pszEscapedLayerName ),
    2249              22 :                        NULL, NULL, &pszErrMsg );
    2250              22 :     if( rc != SQLITE_OK )
    2251                 :     {
    2252                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2253                 :                   "Unable to drop table %s: %s",
    2254               0 :                   osLayerName.c_str(), pszErrMsg );
    2255               0 :         sqlite3_free( pszErrMsg );
    2256               0 :         return OGRERR_FAILURE;
    2257                 :     }
    2258                 : 
    2259                 : /* -------------------------------------------------------------------- */
    2260                 : /*      Drop from geometry_columns table.                               */
    2261                 : /* -------------------------------------------------------------------- */
    2262              22 :     if( bHaveGeometryColumns )
    2263                 :     {
    2264              22 :         CPLString osCommand;
    2265                 : 
    2266                 :         osCommand.Printf( 
    2267                 :             "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
    2268              22 :             pszEscapedLayerName );
    2269                 :         
    2270              22 :         rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
    2271              22 :         if( rc != SQLITE_OK )
    2272                 :         {
    2273                 :             CPLError( CE_Warning, CPLE_AppDefined,
    2274                 :                       "Removal from geometry_columns failed.\n%s: %s", 
    2275               0 :                       osCommand.c_str(), pszErrMsg );
    2276               0 :             sqlite3_free( pszErrMsg );
    2277               0 :             return OGRERR_FAILURE;
    2278                 :         }
    2279                 : 
    2280                 : /* -------------------------------------------------------------------- */
    2281                 : /*      Drop spatialite spatial index tables                            */
    2282                 : /* -------------------------------------------------------------------- */
    2283              22 :         if( bIsSpatiaLiteDB && pszGeometryColumn )
    2284                 :         {
    2285                 :             osCommand.Printf( "DROP TABLE 'idx_%s_%s'", pszEscapedLayerName,
    2286               0 :                               OGRSQLiteEscape(pszGeometryColumn).c_str());
    2287               0 :             rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
    2288                 : 
    2289                 :             osCommand.Printf( "DROP TABLE 'idx_%s_%s_node'", pszEscapedLayerName,
    2290               0 :                               OGRSQLiteEscape(pszGeometryColumn).c_str());
    2291               0 :             rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
    2292                 : 
    2293                 :             osCommand.Printf( "DROP TABLE 'idx_%s_%s_parent'", pszEscapedLayerName,
    2294               0 :                               OGRSQLiteEscape(pszGeometryColumn).c_str());
    2295               0 :             rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
    2296                 : 
    2297                 :             osCommand.Printf( "DROP TABLE 'idx_%s_%s_rowid'", pszEscapedLayerName,
    2298               0 :                               OGRSQLiteEscape(pszGeometryColumn).c_str());
    2299               0 :             rc = sqlite3_exec( hDB, osCommand, NULL, NULL, NULL );
    2300               0 :         }
    2301                 :     }
    2302              22 :     return OGRERR_NONE;
    2303                 : }
    2304                 : 
    2305                 : /************************************************************************/
    2306                 : /*                        SoftStartTransaction()                        */
    2307                 : /*                                                                      */
    2308                 : /*      Create a transaction scope.  If we already have a               */
    2309                 : /*      transaction active this isn't a real transaction, but just      */
    2310                 : /*      an increment to the scope count.                                */
    2311                 : /************************************************************************/
    2312                 : 
    2313              58 : OGRErr OGRSQLiteDataSource::SoftStartTransaction()
    2314                 : 
    2315                 : {
    2316              58 :     nSoftTransactionLevel++;
    2317                 : 
    2318              58 :     if( nSoftTransactionLevel == 1 )
    2319                 :     {
    2320                 :         int rc;
    2321                 :         char *pszErrMsg;
    2322                 :         
    2323                 : #ifdef DEBUG
    2324              58 :         CPLDebug( "OGR_SQLITE", "BEGIN Transaction" );
    2325                 : #endif
    2326                 : 
    2327              58 :         rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
    2328              58 :         if( rc != SQLITE_OK )
    2329                 :         {
    2330               0 :             nSoftTransactionLevel--;
    2331                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2332                 :                       "BEGIN transaction failed: %s",
    2333               0 :                       pszErrMsg );
    2334               0 :             sqlite3_free( pszErrMsg );
    2335               0 :             return OGRERR_FAILURE;
    2336                 :         }
    2337                 :     }
    2338                 : 
    2339              58 :     return OGRERR_NONE;
    2340                 : }
    2341                 : 
    2342                 : /************************************************************************/
    2343                 : /*                             SoftCommit()                             */
    2344                 : /*                                                                      */
    2345                 : /*      Commit the current transaction if we are at the outer           */
    2346                 : /*      scope.                                                          */
    2347                 : /************************************************************************/
    2348                 : 
    2349              47 : OGRErr OGRSQLiteDataSource::SoftCommit()
    2350                 : 
    2351                 : {
    2352              47 :     if( nSoftTransactionLevel <= 0 )
    2353                 :     {
    2354               0 :         CPLDebug( "OGR_SQLITE", "SoftCommit() with no transaction active." );
    2355               0 :         return OGRERR_FAILURE;
    2356                 :     }
    2357                 : 
    2358              47 :     nSoftTransactionLevel--;
    2359                 : 
    2360              47 :     if( nSoftTransactionLevel == 0 )
    2361                 :     {
    2362                 :         int rc;
    2363                 :         char *pszErrMsg;
    2364                 :         
    2365                 : #ifdef DEBUG
    2366              47 :         CPLDebug( "OGR_SQLITE", "COMMIT Transaction" );
    2367                 : #endif
    2368                 : 
    2369              47 :         rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
    2370              47 :         if( rc != SQLITE_OK )
    2371                 :         {
    2372                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    2373                 :                       "COMMIT transaction failed: %s",
    2374               0 :                       pszErrMsg );
    2375               0 :             sqlite3_free( pszErrMsg );
    2376               0 :             return OGRERR_FAILURE;
    2377                 :         }
    2378                 :     }
    2379                 : 
    2380              47 :     return OGRERR_NONE;
    2381                 : }
    2382                 : 
    2383                 : /************************************************************************/
    2384                 : /*                            SoftRollback()                            */
    2385                 : /*                                                                      */
    2386                 : /*      Force a rollback of the current transaction if there is one,    */
    2387                 : /*      even if we are nested several levels deep.                      */
    2388                 : /************************************************************************/
    2389                 : 
    2390              11 : OGRErr OGRSQLiteDataSource::SoftRollback()
    2391                 : 
    2392                 : {
    2393              11 :     if( nSoftTransactionLevel <= 0 )
    2394                 :     {
    2395               0 :         CPLDebug( "OGR_SQLITE", "SoftRollback() with no transaction active." );
    2396               0 :         return OGRERR_FAILURE;
    2397                 :     }
    2398                 : 
    2399              11 :     nSoftTransactionLevel = 0;
    2400                 : 
    2401                 :     int rc;
    2402                 :     char *pszErrMsg;
    2403                 :     
    2404                 : #ifdef DEBUG
    2405              11 :     CPLDebug( "OGR_SQLITE", "ROLLBACK Transaction" );
    2406                 : #endif
    2407                 : 
    2408              11 :     rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, &pszErrMsg );
    2409              11 :     if( rc != SQLITE_OK )
    2410                 :     {
    2411                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2412                 :                   "ROLLBACK transaction failed: %s",
    2413               0 :                   pszErrMsg );
    2414               0 :         sqlite3_free( pszErrMsg );
    2415               0 :         return OGRERR_FAILURE;
    2416                 :     }
    2417                 : 
    2418              24 :     for(int i = 0; i < nLayers; i++)
    2419              13 :         papoLayers[i]->InvalidateCachedFeatureCountAndExtent();
    2420                 : 
    2421              11 :     return OGRERR_NONE;
    2422                 : }
    2423                 : 
    2424                 : /************************************************************************/
    2425                 : /*                        FlushSoftTransaction()                        */
    2426                 : /*                                                                      */
    2427                 : /*      Force the unwinding of any active transaction, and it's         */
    2428                 : /*      commit.                                                         */
    2429                 : /************************************************************************/
    2430                 : 
    2431               0 : OGRErr OGRSQLiteDataSource::FlushSoftTransaction()
    2432                 : 
    2433                 : {
    2434               0 :     if( nSoftTransactionLevel <= 0 )
    2435               0 :         return OGRERR_NONE;
    2436                 : 
    2437               0 :     nSoftTransactionLevel = 1;
    2438                 : 
    2439               0 :     return SoftCommit();
    2440                 : }
    2441                 : 
    2442                 : /************************************************************************/
    2443                 : /*                          GetSRTEXTColName()                        */
    2444                 : /************************************************************************/
    2445                 : 
    2446             137 : const char* OGRSQLiteDataSource::GetSRTEXTColName()
    2447                 : {
    2448             137 :     if( !bIsSpatiaLiteDB || bSpatialite4Layout )
    2449              12 :         return "srtext";
    2450                 : 
    2451                 : /* testing for SRS_WKT column presence */
    2452             125 :     int bHasSrsWkt = FALSE;
    2453                 :     char **papszResult;
    2454                 :     int nRowCount, nColCount;
    2455             125 :     char *pszErrMsg = NULL;
    2456                 :     int rc = sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
    2457                 :                             &papszResult, &nRowCount, &nColCount,
    2458             125 :                             &pszErrMsg );
    2459                 : 
    2460             125 :     if( rc == SQLITE_OK )
    2461                 :     {
    2462                 :         int iRow;
    2463             871 :         for (iRow = 1; iRow <= nRowCount; iRow++)
    2464                 :         {
    2465             746 :             if (EQUAL("srs_wkt",
    2466                 :                         papszResult[(iRow * nColCount) + 1]))
    2467             121 :                 bHasSrsWkt = TRUE;
    2468                 :         }
    2469             125 :         sqlite3_free_table(papszResult);
    2470                 :     }
    2471                 :     else
    2472                 :     {
    2473               0 :         sqlite3_free( pszErrMsg );
    2474                 :     }
    2475                 : 
    2476             125 :     return bHasSrsWkt ? "srs_wkt" : NULL;
    2477                 : }
    2478                 : 
    2479                 : /************************************************************************/
    2480                 : /*                         AddSRIDToCache()                             */
    2481                 : /*                                                                      */
    2482                 : /*      Note: this will not add a reference on the poSRS object. Make   */
    2483                 : /*      sure it is freshly created, or add a reference yourself if not. */
    2484                 : /************************************************************************/
    2485                 : 
    2486             165 : void OGRSQLiteDataSource::AddSRIDToCache(int nId, OGRSpatialReference * poSRS )
    2487                 : {
    2488                 : /* -------------------------------------------------------------------- */
    2489                 : /*      Add to the cache.                                               */
    2490                 : /* -------------------------------------------------------------------- */
    2491             165 :     panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
    2492                 :     papoSRS = (OGRSpatialReference **)
    2493             165 :         CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
    2494             165 :     panSRID[nKnownSRID] = nId;
    2495             165 :     papoSRS[nKnownSRID] = poSRS;
    2496             165 :     nKnownSRID++;
    2497             165 : }
    2498                 : 
    2499                 : /************************************************************************/
    2500                 : /*                             FetchSRSId()                             */
    2501                 : /*                                                                      */
    2502                 : /*      Fetch the id corresponding to an SRS, and if not found, add     */
    2503                 : /*      it to the table.                                                */
    2504                 : /************************************************************************/
    2505                 : 
    2506             170 : int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
    2507                 : 
    2508                 : {
    2509             170 :     int                 nSRSId = nUndefinedSRID;
    2510             170 :     const char          *pszAuthorityName, *pszAuthorityCode = NULL;
    2511             170 :     CPLString           osCommand;
    2512                 :     char *pszErrMsg;
    2513                 :     int   rc;
    2514                 :     char **papszResult;
    2515                 :     int nRowCount, nColCount;
    2516                 : 
    2517             170 :     if( poSRS == NULL )
    2518               0 :         return nSRSId;
    2519                 : 
    2520                 : /* -------------------------------------------------------------------- */
    2521                 : /*      First, we look through our SRID cache, is it there?             */
    2522                 : /* -------------------------------------------------------------------- */
    2523                 :     int  i;
    2524                 : 
    2525             304 :     for( i = 0; i < nKnownSRID; i++ )
    2526                 :     {
    2527             135 :         if( papoSRS[i] == poSRS )
    2528               1 :             return panSRID[i];
    2529                 :     }
    2530             170 :     for( i = 0; i < nKnownSRID; i++ )
    2531                 :     {
    2532             133 :         if( papoSRS[i] != NULL && papoSRS[i]->IsSame(poSRS) )
    2533             132 :             return panSRID[i];
    2534                 :     }
    2535                 : 
    2536                 : /* -------------------------------------------------------------------- */
    2537                 : /*      Build a copy since we may call AutoIdentifyEPSG()               */
    2538                 : /* -------------------------------------------------------------------- */
    2539              37 :     OGRSpatialReference oSRS(*poSRS);
    2540              37 :     poSRS = NULL;
    2541                 : 
    2542              37 :     pszAuthorityName = oSRS.GetAuthorityName(NULL);
    2543                 : 
    2544              37 :     if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
    2545                 :     {
    2546                 : /* -------------------------------------------------------------------- */
    2547                 : /*      Try to identify an EPSG code                                    */
    2548                 : /* -------------------------------------------------------------------- */
    2549              15 :         oSRS.AutoIdentifyEPSG();
    2550                 : 
    2551              15 :         pszAuthorityName = oSRS.GetAuthorityName(NULL);
    2552              15 :         if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
    2553                 :         {
    2554               2 :             pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
    2555               2 :             if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
    2556                 :             {
    2557                 :                 /* Import 'clean' SRS */
    2558               2 :                 oSRS.importFromEPSG( atoi(pszAuthorityCode) );
    2559                 : 
    2560               2 :                 pszAuthorityName = oSRS.GetAuthorityName(NULL);
    2561               2 :                 pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
    2562                 :             }
    2563                 :         }
    2564                 :     }
    2565                 : 
    2566                 : /* -------------------------------------------------------------------- */
    2567                 : /*      Check whether the EPSG authority code is already mapped to a    */
    2568                 : /*      SRS ID.                                                         */
    2569                 : /* -------------------------------------------------------------------- */
    2570              37 :     if( pszAuthorityName != NULL && strlen(pszAuthorityName) > 0 )
    2571                 :     {
    2572              24 :         pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
    2573                 : 
    2574              24 :         if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
    2575                 :         {
    2576                 :             // XXX: We are using case insensitive comparison for "auth_name"
    2577                 :             // values, because there are variety of options exist. By default
    2578                 :             // the driver uses 'EPSG' in upper case, but SpatiaLite extension
    2579                 :             // uses 'epsg' in lower case.
    2580                 :             osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
    2581                 :                               "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s'",
    2582              24 :                               pszAuthorityName, pszAuthorityCode );
    2583                 : 
    2584                 :             rc = sqlite3_get_table( hDB, osCommand, &papszResult, 
    2585              24 :                                     &nRowCount, &nColCount, &pszErrMsg );
    2586              24 :             if( rc != SQLITE_OK )
    2587                 :             {
    2588                 :                 /* Retry without COLLATE NOCASE which may not be understood by older sqlite3 */
    2589               0 :                 sqlite3_free( pszErrMsg );
    2590                 : 
    2591                 :                 osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
    2592                 :                                   "auth_name = '%s' AND auth_srid = '%s'",
    2593               0 :                                   pszAuthorityName, pszAuthorityCode );
    2594                 : 
    2595                 :                 rc = sqlite3_get_table( hDB, osCommand, &papszResult, 
    2596               0 :                                         &nRowCount, &nColCount, &pszErrMsg );
    2597                 : 
    2598                 :                 /* Retry in lower case for SpatiaLite */
    2599               0 :                 if( rc != SQLITE_OK )
    2600                 :                 {
    2601               0 :                     sqlite3_free( pszErrMsg );
    2602                 :                 }
    2603               0 :                 else if ( nRowCount == 0 &&
    2604                 :                           strcmp(pszAuthorityName, "EPSG") == 0)
    2605                 :                 {
    2606                 :                     /* If it's in upper case, look for lower case */
    2607               0 :                     sqlite3_free_table(papszResult);
    2608                 : 
    2609                 :                     osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
    2610                 :                                       "auth_name = 'epsg' AND auth_srid = '%s'",
    2611               0 :                                       pszAuthorityCode );
    2612                 : 
    2613                 :                     rc = sqlite3_get_table( hDB, osCommand, &papszResult, 
    2614               0 :                                             &nRowCount, &nColCount, &pszErrMsg );
    2615                 : 
    2616               0 :                     if( rc != SQLITE_OK )
    2617                 :                     {
    2618               0 :                         sqlite3_free( pszErrMsg );
    2619                 :                     }
    2620                 :                 }
    2621                 :             }
    2622                 : 
    2623              24 :             if( rc == SQLITE_OK && nRowCount == 1 )
    2624                 :             {
    2625              17 :                 nSRSId = (papszResult[1] != NULL) ? atoi(papszResult[1]) : nUndefinedSRID;
    2626              17 :                 sqlite3_free_table(papszResult);
    2627                 : 
    2628              17 :                 if( nSRSId != nUndefinedSRID)
    2629              17 :                     AddSRIDToCache(nSRSId, new OGRSpatialReference(oSRS));
    2630                 : 
    2631              17 :                 return nSRSId;
    2632                 :             }
    2633               7 :             sqlite3_free_table(papszResult);
    2634                 :         }
    2635                 :     }
    2636                 : 
    2637                 : /* -------------------------------------------------------------------- */
    2638                 : /*      Search for existing record using either WKT definition or       */
    2639                 : /*      PROJ.4 string (SpatiaLite variant).                             */
    2640                 : /* -------------------------------------------------------------------- */
    2641              20 :     CPLString   osWKT, osProj4;
    2642                 : 
    2643                 : /* -------------------------------------------------------------------- */
    2644                 : /*      Translate SRS to WKT.                                           */
    2645                 : /* -------------------------------------------------------------------- */
    2646              20 :     char    *pszWKT = NULL;
    2647                 : 
    2648              20 :     if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
    2649                 :     {
    2650               0 :         CPLFree(pszWKT);
    2651               0 :         return nUndefinedSRID;
    2652                 :     }
    2653                 : 
    2654              20 :     osWKT = pszWKT;
    2655              20 :     CPLFree( pszWKT );
    2656              20 :     pszWKT = NULL;
    2657                 : 
    2658              20 :     const char* pszSRTEXTColName = GetSRTEXTColName();
    2659                 : 
    2660              20 :     if ( pszSRTEXTColName != NULL )
    2661                 :     {
    2662                 : /* -------------------------------------------------------------------- */
    2663                 : /*      Try to find based on the WKT match.                             */
    2664                 : /* -------------------------------------------------------------------- */
    2665                 :         osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE \"%s\" = ?",
    2666              20 :                           OGRSQLiteEscapeName(pszSRTEXTColName).c_str());
    2667                 :     }
    2668                 : 
    2669                 : /* -------------------------------------------------------------------- */
    2670                 : /*      Handle SpatiaLite (< 4) flavour of the spatial_ref_sys.         */
    2671                 : /* -------------------------------------------------------------------- */
    2672                 :     else
    2673                 :     {
    2674                 : /* -------------------------------------------------------------------- */
    2675                 : /*      Translate SRS to PROJ.4 string.                                 */
    2676                 : /* -------------------------------------------------------------------- */
    2677               0 :         char    *pszProj4 = NULL;
    2678                 : 
    2679               0 :         if( oSRS.exportToProj4( &pszProj4 ) != OGRERR_NONE )
    2680                 :         {
    2681               0 :             CPLFree(pszProj4);
    2682               0 :             return nUndefinedSRID;
    2683                 :         }
    2684                 : 
    2685               0 :         osProj4 = pszProj4;
    2686               0 :         CPLFree( pszProj4 );
    2687               0 :         pszProj4 = NULL;
    2688                 : 
    2689                 : /* -------------------------------------------------------------------- */
    2690                 : /*      Try to find based on the PROJ.4 match.                          */
    2691                 : /* -------------------------------------------------------------------- */
    2692                 :         osCommand.Printf(
    2693               0 :             "SELECT srid FROM spatial_ref_sys WHERE proj4text = ?");
    2694                 :     }
    2695                 : 
    2696              20 :     sqlite3_stmt *hSelectStmt = NULL;
    2697              20 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hSelectStmt, NULL );
    2698                 : 
    2699              20 :     if( rc == SQLITE_OK)
    2700                 :         rc = sqlite3_bind_text( hSelectStmt, 1,
    2701                 :                                 ( pszSRTEXTColName != NULL ) ? osWKT.c_str() : osProj4.c_str(),
    2702              20 :                                 -1, SQLITE_STATIC );
    2703                 : 
    2704              20 :     if( rc == SQLITE_OK)
    2705              20 :         rc = sqlite3_step( hSelectStmt );
    2706                 : 
    2707              20 :     if (rc == SQLITE_ROW)
    2708                 :     {
    2709               0 :         if (sqlite3_column_type( hSelectStmt, 0 ) == SQLITE_INTEGER)
    2710               0 :             nSRSId = sqlite3_column_int( hSelectStmt, 0 );
    2711                 :         else
    2712               0 :             nSRSId = nUndefinedSRID;
    2713                 : 
    2714               0 :         sqlite3_finalize( hSelectStmt );
    2715                 : 
    2716               0 :         if( nSRSId != nUndefinedSRID)
    2717               0 :             AddSRIDToCache(nSRSId, new OGRSpatialReference(oSRS));
    2718                 : 
    2719               0 :         return nSRSId;
    2720                 :     }
    2721                 : 
    2722                 : /* -------------------------------------------------------------------- */
    2723                 : /*      If the command actually failed, then the metadata table is      */
    2724                 : /*      likely missing, so we give up.                                  */
    2725                 : /* -------------------------------------------------------------------- */
    2726              20 :     if (rc != SQLITE_DONE && rc != SQLITE_ROW)
    2727                 :     {
    2728               0 :         sqlite3_finalize( hSelectStmt );
    2729               0 :         return nUndefinedSRID;
    2730                 :     }
    2731                 : 
    2732              20 :     sqlite3_finalize( hSelectStmt );
    2733                 : 
    2734                 : /* -------------------------------------------------------------------- */
    2735                 : /*      If we have an authority code try to assign SRS ID the same      */
    2736                 : /*      as that code.                                                   */
    2737                 : /* -------------------------------------------------------------------- */
    2738              20 :     if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
    2739                 :     {
    2740                 :         osCommand.Printf( "SELECT * FROM spatial_ref_sys WHERE auth_srid='%s'",
    2741               7 :                           OGRSQLiteEscape(pszAuthorityCode).c_str() );
    2742                 :         rc = sqlite3_get_table( hDB, osCommand, &papszResult,
    2743               7 :                                 &nRowCount, &nColCount, &pszErrMsg );
    2744                 :         
    2745               7 :         if( rc != SQLITE_OK )
    2746                 :         {
    2747                 :             CPLError( CE_Failure, CPLE_AppDefined,
    2748                 :                       "exec(SELECT '%s' FROM spatial_ref_sys) failed: %s",
    2749               0 :                       pszAuthorityCode, pszErrMsg );
    2750               0 :             sqlite3_free( pszErrMsg );
    2751                 :         }
    2752                 : 
    2753                 : /* -------------------------------------------------------------------- */
    2754                 : /*      If there is no SRS ID with such auth_srid, use it as SRS ID.    */
    2755                 : /* -------------------------------------------------------------------- */
    2756               7 :         if ( nRowCount < 1 )
    2757               7 :             nSRSId = atoi(pszAuthorityCode);
    2758               7 :         sqlite3_free_table(papszResult);
    2759                 :     }
    2760                 : 
    2761                 : /* -------------------------------------------------------------------- */
    2762                 : /*      Otherwise get the current maximum srid in the srs table.        */
    2763                 : /* -------------------------------------------------------------------- */
    2764              20 :     if ( nSRSId == nUndefinedSRID )
    2765                 :     {
    2766                 :         rc = sqlite3_get_table( hDB, "SELECT MAX(srid) FROM spatial_ref_sys", 
    2767                 :                                 &papszResult, &nRowCount, &nColCount,
    2768              13 :                                 &pszErrMsg );
    2769                 :         
    2770              13 :         if( rc != SQLITE_OK )
    2771                 :         {
    2772                 :             CPLError( CE_Failure, CPLE_AppDefined,
    2773               0 :                       "SELECT of the maximum SRS ID failed: %s", pszErrMsg );
    2774               0 :             sqlite3_free( pszErrMsg );
    2775               0 :             return nUndefinedSRID;
    2776                 :         }
    2777                 : 
    2778              18 :         if ( nRowCount < 1 || !papszResult[1] )
    2779               5 :             nSRSId = 50000;
    2780                 :         else
    2781               8 :             nSRSId = atoi(papszResult[1]) + 1;  // Insert as the next SRS ID
    2782              13 :         sqlite3_free_table(papszResult);
    2783                 :     }
    2784                 : 
    2785                 : /* -------------------------------------------------------------------- */
    2786                 : /*      Try adding the SRS to the SRS table.                            */
    2787                 : /* -------------------------------------------------------------------- */
    2788                 : 
    2789              20 :     const char* apszToInsert[] = { NULL, NULL, NULL, NULL, NULL, NULL };
    2790                 : 
    2791              20 :     if ( !bIsSpatiaLiteDB )
    2792                 :     {
    2793              12 :         if( pszAuthorityName != NULL )
    2794                 :         {
    2795                 :             osCommand.Printf(
    2796                 :                 "INSERT INTO spatial_ref_sys (srid,srtext,auth_name,auth_srid) "
    2797                 :                 "                     VALUES (%d, ?, ?, ?)",
    2798               7 :                 nSRSId );
    2799               7 :             apszToInsert[0] = osWKT.c_str();
    2800               7 :             apszToInsert[1] = pszAuthorityName;
    2801               7 :             apszToInsert[2] = pszAuthorityCode;
    2802                 :         }
    2803                 :         else
    2804                 :         {
    2805                 :             osCommand.Printf(
    2806                 :                 "INSERT INTO spatial_ref_sys (srid,srtext) "
    2807                 :                 "                     VALUES (%d, ?)",
    2808               5 :                 nSRSId );
    2809               5 :             apszToInsert[0] = osWKT.c_str();
    2810                 :         }
    2811                 :     }
    2812                 :     else
    2813                 :     {
    2814               8 :         CPLString osSRTEXTColNameWithCommaBefore;
    2815               8 :         if( pszSRTEXTColName != NULL )
    2816               8 :             osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
    2817                 : 
    2818               8 :         const char  *pszProjCS = oSRS.GetAttrValue("PROJCS");
    2819               8 :         if (pszProjCS == NULL)
    2820               1 :             pszProjCS = oSRS.GetAttrValue("GEOGCS");
    2821                 : 
    2822               8 :         if( pszAuthorityName != NULL )
    2823                 :         {
    2824               0 :             if ( pszProjCS )
    2825                 :             {
    2826                 :                 osCommand.Printf(
    2827                 :                     "INSERT INTO spatial_ref_sys "
    2828                 :                     "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) "
    2829                 :                     "VALUES (%d, ?, ?, ?, ?%s)",
    2830                 :                     (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "",
    2831                 :                     nSRSId,
    2832               0 :                     (pszSRTEXTColName != NULL) ? ", ?" : "");
    2833               0 :                 apszToInsert[0] = pszAuthorityName;
    2834               0 :                 apszToInsert[1] = pszAuthorityCode;
    2835               0 :                 apszToInsert[2] = pszProjCS;
    2836               0 :                 apszToInsert[3] = osProj4.c_str();
    2837               0 :                 apszToInsert[4] = (pszSRTEXTColName != NULL) ? osWKT.c_str() : NULL;
    2838                 :             }
    2839                 :             else
    2840                 :             {
    2841                 :                 osCommand.Printf(
    2842                 :                     "INSERT INTO spatial_ref_sys "
    2843                 :                     "(srid, auth_name, auth_srid, proj4text%s) "
    2844                 :                     "VALUES (%d, ?, ?, ?%s)",
    2845                 :                     (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "",
    2846                 :                     nSRSId,
    2847               0 :                     (pszSRTEXTColName != NULL) ? ", ?" : "");
    2848               0 :                 apszToInsert[0] = pszAuthorityName;
    2849               0 :                 apszToInsert[1] = pszAuthorityCode;
    2850               0 :                 apszToInsert[2] = osProj4.c_str();
    2851               0 :                 apszToInsert[3] = (pszSRTEXTColName != NULL) ? osWKT.c_str() : NULL;
    2852                 :             }
    2853                 :         }
    2854                 :         else
    2855                 :         {
    2856                 :             /* SpatiaLite spatial_ref_sys auth_name and auth_srid columns must be NOT NULL */
    2857                 :             /* so insert within a fake OGR "authority" */
    2858               8 :             if ( pszProjCS )
    2859                 :             {
    2860                 :                 osCommand.Printf(
    2861                 :                     "INSERT INTO spatial_ref_sys "
    2862                 :                     "(srid, auth_name, auth_srid, ref_sys_name, proj4text%s) VALUES (%d, 'OGR', %d, ?, ?%s)",
    2863                 :                     (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "",
    2864                 :                     nSRSId, nSRSId,
    2865               7 :                     (pszSRTEXTColName != NULL) ? ", ?" : "");
    2866               7 :                 apszToInsert[0] = pszProjCS;
    2867               7 :                 apszToInsert[1] = osProj4.c_str();
    2868               7 :                 apszToInsert[2] = (pszSRTEXTColName != NULL) ? osWKT.c_str() : NULL;
    2869                 :             }
    2870                 :             else
    2871                 :             {
    2872                 :                 osCommand.Printf(
    2873                 :                     "INSERT INTO spatial_ref_sys "
    2874                 :                     "(srid, auth_name, auth_srid, proj4text%s) VALUES (%d, 'OGR', %d, ?%s)",
    2875                 :                     (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "",
    2876                 :                     nSRSId, nSRSId,
    2877               1 :                     (pszSRTEXTColName != NULL) ? ", ?" : "");
    2878               1 :                 apszToInsert[0] = osProj4.c_str();
    2879               1 :                 apszToInsert[1] = (pszSRTEXTColName != NULL) ? osWKT.c_str() : NULL;
    2880                 :             }
    2881               8 :         }
    2882                 :     }
    2883                 : 
    2884              20 :     sqlite3_stmt *hInsertStmt = NULL;
    2885              20 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
    2886                 : 
    2887              69 :     for(i=0;apszToInsert[i]!=NULL;i++)
    2888                 :     {
    2889              49 :         if( rc == SQLITE_OK)
    2890              49 :             rc = sqlite3_bind_text( hInsertStmt, i+1, apszToInsert[i], -1, SQLITE_STATIC );
    2891                 :     }
    2892                 : 
    2893              20 :     if( rc == SQLITE_OK)
    2894              20 :         rc = sqlite3_step( hInsertStmt );
    2895                 : 
    2896              20 :     if( rc != SQLITE_OK && rc != SQLITE_DONE )
    2897                 :     {
    2898                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2899                 :                   "Unable to insert SRID (%s): %s",
    2900               0 :                   osCommand.c_str(), sqlite3_errmsg(hDB) );
    2901                 : 
    2902               0 :         sqlite3_finalize( hInsertStmt );
    2903               0 :         return FALSE;
    2904                 :     }
    2905                 : 
    2906              20 :     sqlite3_finalize( hInsertStmt );
    2907                 : 
    2908              20 :     if( nSRSId != nUndefinedSRID)
    2909              20 :         AddSRIDToCache(nSRSId, new OGRSpatialReference(oSRS));
    2910                 : 
    2911              20 :     return nSRSId;
    2912                 : }
    2913                 : 
    2914                 : /************************************************************************/
    2915                 : /*                              FetchSRS()                              */
    2916                 : /*                                                                      */
    2917                 : /*      Return a SRS corresponding to a particular id.  Note that       */
    2918                 : /*      reference counting should be honoured on the returned           */
    2919                 : /*      OGRSpatialReference, as handles may be cached.                  */
    2920                 : /************************************************************************/
    2921                 : 
    2922             658 : OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
    2923                 : 
    2924                 : {
    2925             658 :     if( nId <= 0 )
    2926             235 :         return NULL;
    2927                 : 
    2928                 : /* -------------------------------------------------------------------- */
    2929                 : /*      First, we look through our SRID cache, is it there?             */
    2930                 : /* -------------------------------------------------------------------- */
    2931                 :     int  i;
    2932                 : 
    2933             441 :     for( i = 0; i < nKnownSRID; i++ )
    2934                 :     {
    2935             292 :         if( panSRID[i] == nId )
    2936             274 :             return papoSRS[i];
    2937                 :     }
    2938                 : 
    2939                 : /* -------------------------------------------------------------------- */
    2940                 : /*      Try looking up in spatial_ref_sys table.                        */
    2941                 : /* -------------------------------------------------------------------- */
    2942                 :     char *pszErrMsg;
    2943                 :     int   rc;
    2944                 :     char **papszResult;
    2945                 :     int nRowCount, nColCount;
    2946             149 :     CPLString osCommand;
    2947             149 :     OGRSpatialReference *poSRS = NULL;
    2948                 : 
    2949                 :     osCommand.Printf( "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
    2950             149 :                       nId );
    2951                 :     rc = sqlite3_get_table( hDB, osCommand, 
    2952             149 :                             &papszResult, &nRowCount, &nColCount, &pszErrMsg );
    2953                 : 
    2954             149 :     if ( rc == SQLITE_OK )
    2955                 :     {
    2956              32 :         if( nRowCount < 1 )
    2957                 :         {
    2958              10 :             sqlite3_free_table(papszResult);
    2959              10 :             return NULL;
    2960                 :         }
    2961                 : 
    2962              22 :         char** papszRow = papszResult + nColCount;
    2963              22 :         if (papszRow[0] != NULL)
    2964                 :         {
    2965              22 :             CPLString osWKT = papszRow[0];
    2966                 : 
    2967                 : /* -------------------------------------------------------------------- */
    2968                 : /*      Translate into a spatial reference.                             */
    2969                 : /* -------------------------------------------------------------------- */
    2970              22 :             char *pszWKT = (char *) osWKT.c_str();
    2971                 : 
    2972              22 :             poSRS = new OGRSpatialReference();
    2973              44 :             if( poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
    2974                 :             {
    2975               0 :                 delete poSRS;
    2976               0 :                 poSRS = NULL;
    2977              22 :             }
    2978                 :         }
    2979                 : 
    2980              22 :         sqlite3_free_table(papszResult);
    2981                 :     }
    2982                 : 
    2983                 : /* -------------------------------------------------------------------- */
    2984                 : /*      Next try SpatiaLite flavour. SpatiaLite uses PROJ.4 strings     */
    2985                 : /*      in 'proj4text' column instead of WKT in 'srtext'. Note: recent  */
    2986                 : /*      versions of spatialite have a srs_wkt column too                */
    2987                 : /* -------------------------------------------------------------------- */
    2988                 :     else
    2989                 :     {
    2990             117 :         sqlite3_free( pszErrMsg );
    2991             117 :         pszErrMsg = NULL;
    2992                 : 
    2993             117 :         const char* pszSRTEXTColName = GetSRTEXTColName();
    2994             117 :         CPLString osSRTEXTColNameWithCommaBefore;
    2995             117 :         if( pszSRTEXTColName != NULL )
    2996             113 :             osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
    2997                 : 
    2998                 :         osCommand.Printf(
    2999                 :             "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys WHERE srid = %d",
    3000             117 :             (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "", nId );
    3001                 :         rc = sqlite3_get_table( hDB, osCommand, 
    3002                 :                                 &papszResult, &nRowCount,
    3003             117 :                                 &nColCount, &pszErrMsg );
    3004             117 :         if ( rc == SQLITE_OK )
    3005                 :         {
    3006             117 :             if( nRowCount < 1 )
    3007                 :             {
    3008              11 :                 sqlite3_free_table(papszResult);
    3009              11 :                 return NULL;
    3010                 :             }
    3011                 : 
    3012                 : /* -------------------------------------------------------------------- */
    3013                 : /*      Translate into a spatial reference.                             */
    3014                 : /* -------------------------------------------------------------------- */
    3015             106 :             char** papszRow = papszResult + nColCount;
    3016                 : 
    3017             106 :             const char* pszProj4Text = papszRow[0];
    3018             106 :             const char* pszAuthName = papszRow[1];
    3019             106 :             int nAuthSRID = (papszRow[2] != NULL) ? atoi(papszRow[2]) : 0;
    3020             106 :             char* pszWKT = (pszSRTEXTColName != NULL) ? (char*) papszRow[3] : NULL;
    3021                 : 
    3022             106 :             poSRS = new OGRSpatialReference();
    3023                 : 
    3024                 :             /* Try first from EPSG code */
    3025             212 :             if (pszAuthName != NULL &&
    3026                 :                 EQUAL(pszAuthName, "EPSG") &&
    3027                 :                 poSRS->importFromEPSG( nAuthSRID ) == OGRERR_NONE)
    3028                 :             {
    3029                 :                 /* Do nothing */
    3030                 :             }
    3031                 :             /* Then from WKT string */
    3032               8 :             else if( pszWKT != NULL &&
    3033                 :                      poSRS->importFromWkt( &pszWKT ) == OGRERR_NONE )
    3034                 :             {
    3035                 :                 /* Do nothing */
    3036                 :             }
    3037                 :             /* Finally from Proj4 string */
    3038               0 :             else if( pszProj4Text != NULL &&
    3039                 :                      poSRS->importFromProj4( pszProj4Text ) == OGRERR_NONE )
    3040                 :             {
    3041                 :                 /* Do nothing */
    3042                 :             }
    3043                 :             else
    3044                 :             {
    3045               0 :                 delete poSRS;
    3046               0 :                 poSRS = NULL;
    3047                 :             }
    3048                 : 
    3049             106 :             sqlite3_free_table(papszResult);
    3050                 :         }
    3051                 : 
    3052                 : /* -------------------------------------------------------------------- */
    3053                 : /*      No success, report an error.                                    */
    3054                 : /* -------------------------------------------------------------------- */
    3055                 :         else
    3056                 :         {
    3057                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    3058               0 :                       "%s: %s", osCommand.c_str(), pszErrMsg );
    3059               0 :             sqlite3_free( pszErrMsg );
    3060               0 :             return NULL;
    3061               0 :         }
    3062                 :     }
    3063                 : 
    3064                 : /* -------------------------------------------------------------------- */
    3065                 : /*      Add to the cache.                                               */
    3066                 : /* -------------------------------------------------------------------- */
    3067             128 :     AddSRIDToCache(nId, poSRS);
    3068                 : 
    3069             128 :     return poSRS;
    3070                 : }
    3071                 : 
    3072                 : /************************************************************************/
    3073                 : /*                              SetName()                               */
    3074                 : /************************************************************************/
    3075                 : 
    3076               1 : void OGRSQLiteDataSource::SetName(const char* pszNameIn)
    3077                 : {
    3078               1 :     CPLFree(pszName);
    3079               1 :     pszName = CPLStrdup(pszNameIn);
    3080               1 : }
    3081                 : 
    3082                 : /************************************************************************/
    3083                 : /*                       GetEnvelopeFromSQL()                           */
    3084                 : /************************************************************************/
    3085                 : 
    3086              14 : const OGREnvelope* OGRSQLiteDataSource::GetEnvelopeFromSQL(const CPLString& osSQL)
    3087                 : {
    3088              14 :     std::map<CPLString, OGREnvelope>::iterator oIter = oMapSQLEnvelope.find(osSQL);
    3089              14 :     if (oIter != oMapSQLEnvelope.end())
    3090               3 :         return &oIter->second;
    3091                 :     else
    3092              11 :         return NULL;
    3093                 : }
    3094                 : 
    3095                 : /************************************************************************/
    3096                 : /*                         SetEnvelopeForSQL()                          */
    3097                 : /************************************************************************/
    3098                 : 
    3099               7 : void OGRSQLiteDataSource::SetEnvelopeForSQL(const CPLString& osSQL,
    3100                 :                                             const OGREnvelope& oEnvelope)
    3101                 : {
    3102               7 :     oMapSQLEnvelope[osSQL] = oEnvelope;
    3103               7 : }

Generated by: LCOV version 1.7