LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitedatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 878 596 67.9 %
Date: 2011-12-18 Functions: 33 29 87.9 %

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

Generated by: LCOV version 1.7