LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitedatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 914 636 69.6 %
Date: 2012-04-28 Functions: 37 33 89.2 %

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

Generated by: LCOV version 1.7