LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 452 359 79.4 %
Date: 2010-01-09 Functions: 20 16 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqlitelayer.cpp 17772 2009-10-07 20:54:45Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRSQLiteLayer class, code shared between 
       6                 :  *           the direct table access, and the generic SQL results.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "ogr_sqlite.h"
      34                 : #include <cassert>
      35                 : 
      36                 : CPL_CVSID("$Id: ogrsqlitelayer.cpp 17772 2009-10-07 20:54:45Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                           OGRSQLiteLayer()                           */
      40                 : /************************************************************************/
      41                 : 
      42             132 : OGRSQLiteLayer::OGRSQLiteLayer()
      43                 : 
      44                 : {
      45             132 :     poDS = NULL;
      46                 : 
      47             132 :     pszFIDColumn = NULL;
      48                 : 
      49             132 :     eGeomFormat = OSGF_None;
      50                 : 
      51             132 :     hStmt = NULL;
      52                 : 
      53             132 :     iNextShapeId = 0;
      54                 : 
      55             132 :     poSRS = NULL;
      56             132 :     nSRSId = -2; // we haven't even queried the database for it yet. 
      57                 : 
      58             132 :     panFieldOrdinals = NULL;
      59                 : 
      60             132 :     bTriedAsSpatiaLite = FALSE;
      61             132 :     bHasSpatialIndex = FALSE;
      62             132 : }
      63                 : 
      64                 : /************************************************************************/
      65                 : /*                          ~OGRSQLiteLayer()                           */
      66                 : /************************************************************************/
      67                 : 
      68             132 : OGRSQLiteLayer::~OGRSQLiteLayer()
      69                 : 
      70                 : {
      71             132 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
      72                 :     {
      73                 :         CPLDebug( "SQLite", "%d features read on layer '%s'.",
      74                 :                   (int) m_nFeaturesRead, 
      75              29 :                   poFeatureDefn->GetName() );
      76                 :     }
      77                 : 
      78             132 :     if( hStmt != NULL )
      79                 :     {
      80               0 :         sqlite3_finalize( hStmt );
      81               0 :         hStmt = NULL;
      82                 :     }
      83                 : 
      84             132 :     if( poFeatureDefn != NULL )
      85                 :     {
      86             132 :         poFeatureDefn->Release();
      87             132 :         poFeatureDefn = NULL;
      88                 :     }
      89                 : 
      90             132 :     if( poSRS != NULL )
      91              16 :         poSRS->Dereference();
      92                 : 
      93             132 :     CPLFree( pszFIDColumn );
      94             132 :     CPLFree( panFieldOrdinals );
      95             132 : }
      96                 : 
      97                 : /************************************************************************/
      98                 : /*                          BuildFeatureDefn()                          */
      99                 : /*                                                                      */
     100                 : /*      Build feature definition from a set of column definitions       */
     101                 : /*      set on a statement.  Sift out geometry and FID fields.          */
     102                 : /************************************************************************/
     103                 : 
     104             132 : CPLErr OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName, 
     105                 :                                          sqlite3_stmt *hStmt )
     106                 : 
     107                 : {
     108             132 :     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     109             132 :     int    nRawColumns = sqlite3_column_count( hStmt );
     110                 : 
     111             132 :     poFeatureDefn->Reference();
     112                 : 
     113             132 :     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
     114                 : 
     115             132 :     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     116                 :     {
     117                 :         OGRFieldDefn    oField( sqlite3_column_name( hStmt, iCol ), 
     118             639 :                                 OFTString );
     119                 : 
     120                 :         // In some cases, particularly when there is a real name for
     121                 :         // the primary key/_rowid_ column we will end up getting the
     122                 :         // primary key column appearing twice.  Ignore any repeated names.
     123             639 :         if( poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
     124               0 :             continue;
     125                 : 
     126             639 :         if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oField.GetNameRef()))
     127             177 :             continue;
     128                 : 
     129                 :         //oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
     130                 : 
     131             462 :         if( osGeomColumn.size()
     132                 :             && EQUAL(oField.GetNameRef(),osGeomColumn) )
     133              45 :             continue;
     134                 :         
     135             417 :         int nColType = sqlite3_column_type( hStmt, iCol );
     136             417 :         const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
     137                 :         //CPLDebug("SQLITE", "decltype(%s) = %s",
     138                 :         //         oField.GetNameRef(), pszDeclType ? pszDeclType : "null");
     139             417 :         if (pszDeclType != NULL)
     140                 :         {
     141             388 :             if (EQUAL(pszDeclType, "INTEGER"))
     142             159 :                 nColType = SQLITE_INTEGER;
     143             229 :             else if (EQUAL(pszDeclType, "FLOAT"))
     144              11 :                 nColType = SQLITE_FLOAT;
     145             218 :             else if (EQUAL(pszDeclType, "BLOB"))
     146              34 :                 nColType = SQLITE_BLOB;
     147             184 :             else if (EQUAL(pszDeclType, "TEXT") ||
     148                 :                      EQUAL(pszDeclType, "VARCHAR"))
     149             108 :                 nColType = SQLITE_TEXT;
     150                 :         }
     151                 : 
     152                 :         // Recognise some common geometry column names.
     153             417 :         if( (EQUAL(oField.GetNameRef(),"wkt_geometry") 
     154                 :              || EQUAL(oField.GetNameRef(),"geometry")
     155                 :              || EQUALN(oField.GetNameRef(), "asbinary(", 9)
     156                 :              || EQUALN(oField.GetNameRef(), "astext(", 7))
     157                 :             && osGeomColumn.size() == 0 )
     158                 :         {
     159              13 :             if( nColType == SQLITE_BLOB )
     160                 :             {
     161              12 :                 osGeomColumn = oField.GetNameRef();
     162              12 :                 eGeomFormat = OSGF_WKB;
     163                 :                 /* This could also be a SpatialLite geometry, so */
     164                 :                 /* we'll also try to decode as SpatialLite if */
     165                 :                 /* bTriedAsSpatiaLite is not FALSE */
     166              12 :                 continue;
     167                 :             }
     168               1 :             else if( nColType == SQLITE_TEXT )
     169                 :             {
     170               1 :                 osGeomColumn = oField.GetNameRef();
     171               1 :                 eGeomFormat = OSGF_WKT;
     172               1 :                 continue;
     173                 :             }
     174                 :         }
     175                 : 
     176                 :         // SpatialLite / Gaia
     177             404 :         if( EQUAL(oField.GetNameRef(),"GaiaGeometry") 
     178                 :             && osGeomColumn.size() == 0 )
     179                 :         {
     180               0 :             osGeomColumn = oField.GetNameRef();
     181               0 :             eGeomFormat = OSGF_SpatiaLite;
     182               0 :             continue;
     183                 :         }
     184                 : 
     185                 :         // The rowid is for internal use, not a real column.
     186             404 :         if( EQUAL(oField.GetNameRef(),"_rowid_") )
     187               0 :             continue;
     188                 : 
     189                 :         // The OGC_FID is for internal use, not a real user visible column.
     190             404 :         if( EQUAL(oField.GetNameRef(),"OGC_FID") )
     191               3 :             continue;
     192                 : 
     193             401 :         switch( nColType )
     194                 :         {
     195                 :           case SQLITE_INTEGER:
     196             165 :             oField.SetType( OFTInteger );
     197             165 :             break;
     198                 : 
     199                 :           case SQLITE_FLOAT:
     200              45 :             oField.SetType( OFTReal );
     201              45 :             break;
     202                 : 
     203                 :           case SQLITE_BLOB:
     204              32 :             oField.SetType( OFTBinary );
     205                 :             break;
     206                 : 
     207                 :           default:
     208                 :             /* leave it as OFTString */;
     209                 :         }
     210                 : 
     211             401 :         poFeatureDefn->AddFieldDefn( &oField );
     212             401 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
     213                 :     }
     214                 : 
     215                 : /* -------------------------------------------------------------------- */
     216                 : /*      If we have no geometry source, we know our geometry type is     */
     217                 : /*      none.                                                           */
     218                 : /* -------------------------------------------------------------------- */
     219             132 :     if( osGeomColumn.size() == 0 )
     220              74 :         poFeatureDefn->SetGeomType( wkbNone );
     221                 : 
     222             132 :     return CE_None;
     223                 : }
     224                 : 
     225                 : /************************************************************************/
     226                 : /*                            GetFIDColumn()                            */
     227                 : /************************************************************************/
     228                 : 
     229               0 : const char *OGRSQLiteLayer::GetFIDColumn() 
     230                 : 
     231                 : {
     232               0 :     if( pszFIDColumn != NULL )
     233               0 :         return pszFIDColumn;
     234                 :     else
     235               0 :         return "";
     236                 : }
     237                 : 
     238                 : /************************************************************************/
     239                 : /*                         GetGeometryColumn()                          */
     240                 : /************************************************************************/
     241                 : 
     242               0 : const char *OGRSQLiteLayer::GetGeometryColumn() 
     243                 : 
     244                 : {
     245               0 :     if( osGeomColumn.size() != 0 )
     246               0 :         return osGeomColumn.c_str();
     247                 :     else
     248               0 :         return "";
     249                 : }
     250                 : 
     251                 : /************************************************************************/
     252                 : /*                            ResetReading()                            */
     253                 : /************************************************************************/
     254                 : 
     255             103 : void OGRSQLiteLayer::ResetReading()
     256                 : 
     257                 : {
     258             103 :     iNextShapeId = 0;
     259             103 : }
     260                 : 
     261                 : /************************************************************************/
     262                 : /*                           GetNextFeature()                           */
     263                 : /************************************************************************/
     264                 : 
     265             171 : OGRFeature *OGRSQLiteLayer::GetNextFeature()
     266                 : 
     267                 : {
     268              32 :     for( ; TRUE; )
     269                 :     {
     270                 :         OGRFeature      *poFeature;
     271                 : 
     272             171 :         poFeature = GetNextRawFeature();
     273             171 :         if( poFeature == NULL )
     274              24 :             return NULL;
     275                 : 
     276             147 :         if( (m_poFilterGeom == NULL
     277                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     278                 :             && (m_poAttrQuery == NULL
     279                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     280             115 :             return poFeature;
     281                 : 
     282              32 :         delete poFeature;
     283                 :     }
     284                 : }
     285                 : 
     286                 : /************************************************************************/
     287                 : /*                         GetNextRawFeature()                          */
     288                 : /************************************************************************/
     289                 : 
     290             172 : OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
     291                 : 
     292                 : {
     293             172 :     if( GetStatement() == NULL )
     294               0 :         return NULL;
     295                 : 
     296                 : /* -------------------------------------------------------------------- */
     297                 : /*      If we are marked to restart then do so, and fetch a record.     */
     298                 : /* -------------------------------------------------------------------- */
     299                 :     int rc;
     300                 : 
     301             172 :     rc = sqlite3_step( hStmt );
     302             172 :     if( rc != SQLITE_ROW )
     303                 :     {
     304              24 :         if ( rc != SQLITE_DONE )
     305                 :         {
     306                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     307                 :                     "In GetNextRawFeature(): sqlite3_step() : %s", 
     308               0 :                     sqlite3_errmsg(poDS->GetDB()) );
     309                 :         }
     310                 : 
     311              24 :         ClearStatement();
     312                 : 
     313              24 :         return NULL;
     314                 :     }
     315                 : 
     316                 : /* -------------------------------------------------------------------- */
     317                 : /*      Create a feature from the current result.                       */
     318                 : /* -------------------------------------------------------------------- */
     319                 :     int         iField;
     320             148 :     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     321                 : 
     322                 : /* -------------------------------------------------------------------- */
     323                 : /*      Set FID if we have a column to set it from.                     */
     324                 : /* -------------------------------------------------------------------- */
     325             148 :     if( pszFIDColumn != NULL )
     326                 :     {
     327                 :         int iFIDCol;
     328                 : 
     329             103 :         for( iFIDCol = 0; iFIDCol < sqlite3_column_count(hStmt); iFIDCol++ )
     330                 :         {
     331             103 :             if( EQUAL(sqlite3_column_name(hStmt,iFIDCol),
     332                 :                       pszFIDColumn) )
     333             103 :                 break;
     334                 :         }
     335                 : 
     336             103 :         if( iFIDCol == sqlite3_column_count(hStmt) )
     337                 :         {
     338                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     339                 :                       "Unable to find FID column '%s'.", 
     340               0 :                       pszFIDColumn );
     341               0 :             return NULL;
     342                 :         }
     343                 :         
     344             103 :         poFeature->SetFID( sqlite3_column_int( hStmt, iFIDCol ) );
     345                 :     }
     346                 :     else
     347              45 :         poFeature->SetFID( iNextShapeId );
     348                 : 
     349             148 :     iNextShapeId++;
     350                 : 
     351             148 :     m_nFeaturesRead++;
     352                 : 
     353                 : /* -------------------------------------------------------------------- */
     354                 : /*      Process Geometry if we have a column.                           */
     355                 : /* -------------------------------------------------------------------- */
     356             148 :     if( osGeomColumn.size() )
     357                 :     {
     358                 :         int iGeomCol;
     359                 : 
     360             353 :         for( iGeomCol = 0; iGeomCol < sqlite3_column_count(hStmt); iGeomCol++ )
     361                 :         {
     362             353 :             if( EQUAL(sqlite3_column_name(hStmt,iGeomCol),
     363                 :                       osGeomColumn) )
     364             109 :                 break;
     365                 :         }
     366                 : 
     367             109 :         if( iGeomCol == sqlite3_column_count(hStmt) )
     368                 :         {
     369                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     370                 :                       "Unable to find Geometry column '%s'.", 
     371               0 :                       osGeomColumn.c_str() );
     372               0 :             return NULL;
     373                 :         }
     374                 : 
     375             109 :         OGRGeometry *poGeometry = NULL;
     376             109 :         if ( eGeomFormat == OSGF_WKT )
     377                 :         {
     378               3 :             char *pszWKTCopy, *pszWKT = NULL;
     379                 : 
     380               3 :             pszWKT = (char *) sqlite3_column_text( hStmt, iGeomCol );
     381               3 :             pszWKTCopy = pszWKT;
     382               3 :             if( OGRGeometryFactory::createFromWkt( 
     383                 :                     &pszWKTCopy, NULL, &poGeometry ) == OGRERR_NONE )
     384               3 :                 poFeature->SetGeometryDirectly( poGeometry );
     385                 :         }
     386             106 :         else if ( eGeomFormat == OSGF_WKB )
     387                 :         {
     388              74 :             const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
     389                 : 
     390              74 :             if( OGRGeometryFactory::createFromWkb( 
     391                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
     392                 :                     NULL, &poGeometry, nBytes ) == OGRERR_NONE )
     393              65 :                 poFeature->SetGeometryDirectly( poGeometry );
     394               9 :             else if (!bTriedAsSpatiaLite)
     395                 :             {
     396                 :                 /* If the layer is the result of a sql select, we cannot be sure if it is */
     397                 :                 /* WKB or SpatialLite format */
     398               7 :                 if( ImportSpatiaLiteGeometry( 
     399                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
     400                 :                     &poGeometry ) == OGRERR_NONE )
     401                 :                 {
     402               6 :                     poFeature->SetGeometryDirectly( poGeometry );
     403               6 :                     eGeomFormat = OSGF_SpatiaLite;
     404                 :                 }
     405               7 :                 bTriedAsSpatiaLite = TRUE;
     406                 :             }
     407                 :         }
     408              32 :         else if ( eGeomFormat == OSGF_FGF )
     409                 :         {
     410               8 :             const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
     411                 : 
     412               8 :             if( OGRGeometryFactory::createFromFgf( 
     413                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ),
     414                 :                     NULL, &poGeometry, nBytes, NULL ) == OGRERR_NONE )
     415               8 :                 poFeature->SetGeometryDirectly( poGeometry );
     416                 :         }
     417              24 :         else if ( eGeomFormat == OSGF_SpatiaLite )
     418                 :         {
     419              24 :             const int nBytes = sqlite3_column_bytes( hStmt, iGeomCol );
     420                 : 
     421              24 :             if( ImportSpatiaLiteGeometry( 
     422                 :                     (GByte*)sqlite3_column_blob( hStmt, iGeomCol ), nBytes,
     423                 :                     &poGeometry ) == OGRERR_NONE )
     424              21 :                 poFeature->SetGeometryDirectly( poGeometry );
     425                 :         }
     426                 : 
     427             109 :         if (poGeometry != NULL && poSRS != NULL)
     428               5 :             poGeometry->assignSpatialReference(poSRS);
     429                 :     }
     430                 : 
     431                 : /* -------------------------------------------------------------------- */
     432                 : /*      set the fields.                                                 */
     433                 : /* -------------------------------------------------------------------- */
     434             530 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     435                 :     {
     436             382 :         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
     437             382 :         int iRawField = panFieldOrdinals[iField] - 1;
     438                 : 
     439             382 :         if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
     440             117 :             continue;
     441                 : 
     442             265 :         switch( poFieldDefn->GetType() )
     443                 :         {
     444                 :         case OFTInteger:
     445                 :             poFeature->SetField( iField, 
     446             100 :                 sqlite3_column_int( hStmt, iRawField ) );
     447             100 :             break;
     448                 : 
     449                 :         case OFTReal:
     450                 :             poFeature->SetField( iField, 
     451              77 :                 sqlite3_column_double( hStmt, iRawField ) );
     452              77 :             break;
     453                 : 
     454                 :         case OFTBinary:
     455                 :             {
     456              13 :                 const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
     457                 : 
     458                 :                 poFeature->SetField( iField, nBytes,
     459              13 :                     (GByte*)sqlite3_column_blob( hStmt, iRawField ) );
     460                 :             }
     461              13 :             break;
     462                 : 
     463                 :         case OFTString:
     464                 :             poFeature->SetField( iField, 
     465                 :                 (const char *) 
     466              75 :                 sqlite3_column_text( hStmt, iRawField ) );
     467                 :             break;
     468                 : 
     469                 :         default:
     470                 :             break;
     471                 :         }
     472                 :     }
     473                 : 
     474             148 :     return poFeature;
     475                 : }
     476                 : 
     477                 : /************************************************************************/
     478                 : /*                             GetFeature()                             */
     479                 : /************************************************************************/
     480                 : 
     481               2 : OGRFeature *OGRSQLiteLayer::GetFeature( long nFeatureId )
     482                 : 
     483                 : {
     484               2 :     return OGRLayer::GetFeature( nFeatureId );
     485                 : }
     486                 : 
     487                 : 
     488                 : /************************************************************************/
     489                 : /*                     createFromSpatialiteInternal()                   */
     490                 : /************************************************************************/
     491                 : 
     492                 : /* See http://www.gaia-gis.it/spatialite/spatialite-manual-2.3.0.html#t3.3 */
     493                 : /* for the specification of the spatialite BLOB geometry format */
     494                 : /* Derived from WKB, but unfortunately it is not practical to reuse existing */
     495                 : /* WKB encoding/decoding code */
     496                 : 
     497                 : #ifdef CPL_LSB
     498                 : #define NEED_SWAP_SPATIALITE()  (eByteOrder != wkbNDR)
     499                 : #else
     500                 : #define NEED_SWAP_SPATIALITE()  (eByteOrder == wkbNDR)
     501                 : #endif
     502                 : 
     503                 : 
     504              37 : OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
     505                 :                                                     OGRGeometry **ppoReturn,
     506                 :                                                     int nBytes,
     507                 :                                                     OGRwkbByteOrder eByteOrder,
     508                 :                                                     int* pnBytesConsumed)
     509                 : {
     510              37 :     OGRErr      eErr = OGRERR_NONE;
     511              37 :     OGRGeometry *poGeom = NULL;
     512                 :     GInt32       nGType;
     513                 : 
     514              37 :     *ppoReturn = NULL;
     515                 : 
     516              37 :     if (nBytes < 4)
     517               0 :         return OGRERR_NOT_ENOUGH_DATA;
     518                 : 
     519                 : /* -------------------------------------------------------------------- */
     520                 : /*      Decode the geometry type.                                       */
     521                 : /* -------------------------------------------------------------------- */
     522              37 :     memcpy( &nGType, pabyData, 4 );
     523              37 :     if (NEED_SWAP_SPATIALITE())
     524               0 :         CPL_SWAP32PTR( &nGType );
     525                 : 
     526              37 :     if( nGType < 1 || nGType > 7 )
     527               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     528                 : 
     529                 : /* -------------------------------------------------------------------- */
     530                 : /*      Point                                                           */
     531                 : /* -------------------------------------------------------------------- */
     532              37 :     if( nGType == 1 )
     533                 :     {
     534                 :         double  adfTuple[2];
     535                 : 
     536               7 :         if( nBytes < 4 + 2 * 8 )
     537               0 :             return OGRERR_NOT_ENOUGH_DATA;
     538                 : 
     539               7 :         memcpy( adfTuple, pabyData + 4, 2*8 );
     540               7 :         if (NEED_SWAP_SPATIALITE())
     541                 :         {
     542               0 :             CPL_SWAP64PTR( adfTuple );
     543               0 :             CPL_SWAP64PTR( adfTuple + 1 );
     544                 :         }
     545                 : 
     546               7 :         poGeom = new OGRPoint( adfTuple[0], adfTuple[1] );
     547                 : 
     548               7 :         if( pnBytesConsumed )
     549               3 :             *pnBytesConsumed = 4 + 2 * 8;
     550                 :     }
     551                 : 
     552                 : /* -------------------------------------------------------------------- */
     553                 : /*      LineString                                                      */
     554                 : /* -------------------------------------------------------------------- */
     555              30 :     else if( nGType == 2 )
     556                 :     {
     557                 :         double adfTuple[2];
     558                 :         GInt32 nPointCount;
     559                 :         int    iPoint;
     560                 :         OGRLineString *poLS;
     561                 : 
     562               4 :         if( nBytes < 8 )
     563               0 :             return OGRERR_NOT_ENOUGH_DATA;
     564                 : 
     565               4 :         memcpy( &nPointCount, pabyData + 4, 4 );
     566               4 :         if (NEED_SWAP_SPATIALITE())
     567               0 :             CPL_SWAP32PTR( &nPointCount );
     568                 : 
     569               4 :         if( nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
     570               0 :             return OGRERR_CORRUPT_DATA;
     571                 : 
     572               4 :         if (nBytes - 8 < 2 * 8 * nPointCount )
     573               0 :             return OGRERR_NOT_ENOUGH_DATA;
     574                 : 
     575               4 :         poGeom = poLS = new OGRLineString();
     576               4 :         poLS->setNumPoints( nPointCount );
     577                 : 
     578              10 :         for( iPoint = 0; iPoint < nPointCount; iPoint++ )
     579                 :         {
     580               6 :             memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
     581               6 :             if (NEED_SWAP_SPATIALITE())
     582                 :             {
     583               0 :                 CPL_SWAP64PTR( adfTuple );
     584               0 :                 CPL_SWAP64PTR( adfTuple + 1 );
     585                 :             }
     586                 : 
     587               6 :             poLS->setPoint( iPoint, adfTuple[0], adfTuple[1] );
     588                 :         }
     589                 : 
     590               4 :         if( pnBytesConsumed )
     591               2 :             *pnBytesConsumed = 8 + 2 * 8 * nPointCount;
     592                 :     }
     593                 : 
     594                 : /* -------------------------------------------------------------------- */
     595                 : /*      Polygon                                                         */
     596                 : /* -------------------------------------------------------------------- */
     597              26 :     else if( nGType == 3 )
     598                 :     {
     599                 :         double adfTuple[2];
     600                 :         GInt32 nPointCount;
     601                 :         GInt32 nRingCount;
     602                 :         int    iPoint, iRing;
     603                 :         OGRLinearRing *poLR;
     604                 :         OGRPolygon *poPoly;
     605                 :         int    nNextByte;
     606                 : 
     607              17 :         if( nBytes < 8 )
     608               0 :             return OGRERR_NOT_ENOUGH_DATA;
     609                 : 
     610              17 :         memcpy( &nRingCount, pabyData + 4, 4 );
     611              17 :         if (NEED_SWAP_SPATIALITE())
     612               0 :             CPL_SWAP32PTR( &nRingCount );
     613                 : 
     614              17 :         if (nRingCount < 0 || nRingCount > INT_MAX / 4)
     615               0 :             return OGRERR_CORRUPT_DATA;
     616                 : 
     617                 :         /* Each ring has a minimum of 4 bytes */
     618              17 :         if (nBytes - 8 < nRingCount * 4)
     619               0 :             return OGRERR_NOT_ENOUGH_DATA;
     620                 : 
     621              17 :         nNextByte = 8;
     622                 :         
     623              17 :         poGeom = poPoly = new OGRPolygon();
     624                 : 
     625              34 :         for( iRing = 0; iRing < nRingCount; iRing++ )
     626                 :         {
     627              17 :             if( nBytes - nNextByte < 4 )
     628               0 :                 return OGRERR_NOT_ENOUGH_DATA;
     629                 : 
     630              17 :             memcpy( &nPointCount, pabyData + nNextByte, 4 );
     631              17 :             if (NEED_SWAP_SPATIALITE())
     632               0 :                 CPL_SWAP32PTR( &nPointCount );
     633                 : 
     634              17 :             if (nPointCount < 0 || nPointCount > INT_MAX / (2 * 8))
     635               0 :                 return OGRERR_CORRUPT_DATA;
     636                 : 
     637              17 :             nNextByte += 4;
     638                 : 
     639              17 :             if( nBytes - nNextByte < 2 * 8 * nPointCount )
     640               0 :                 return OGRERR_NOT_ENOUGH_DATA;
     641                 : 
     642              17 :             poLR = new OGRLinearRing();
     643              17 :             poLR->setNumPoints( nPointCount );
     644                 :             
     645              78 :             for( iPoint = 0; iPoint < nPointCount; iPoint++ )
     646                 :             {
     647              61 :                 memcpy( adfTuple, pabyData + nNextByte, 2*8 );
     648              61 :                 nNextByte += 2 * 8;
     649                 : 
     650              61 :                 if (NEED_SWAP_SPATIALITE())
     651                 :                 {
     652               0 :                     CPL_SWAP64PTR( adfTuple );
     653               0 :                     CPL_SWAP64PTR( adfTuple + 1 );
     654                 :                 }
     655                 : 
     656              61 :                 poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
     657                 :             }
     658                 : 
     659              17 :             poPoly->addRingDirectly( poLR );
     660                 :         }
     661                 : 
     662              17 :         if( pnBytesConsumed )
     663               5 :             *pnBytesConsumed = nNextByte;
     664                 :     }
     665                 : 
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      GeometryCollections of various kinds.                           */
     668                 : /* -------------------------------------------------------------------- */
     669              18 :     else if( nGType == 4         // MultiPoint
     670                 :              || nGType == 5      // MultiLineString
     671                 :              || nGType == 6      // MultiPolygon
     672                 :              || nGType == 7 )    // MultiGeometry
     673                 :     {
     674               9 :         OGRGeometryCollection *poGC = NULL;
     675               9 :         GInt32 nGeomCount = 0;
     676               9 :         int iGeom = 0;
     677               9 :         int nBytesUsed = 0;
     678                 : 
     679               9 :         if( nGType == 4 )
     680               2 :             poGC = new OGRMultiPoint();
     681               7 :         else if( nGType == 5 )
     682               2 :             poGC = new OGRMultiLineString();
     683               5 :         else if( nGType == 6 )
     684               2 :             poGC = new OGRMultiPolygon();
     685               3 :         else if( nGType == 7 )
     686               3 :             poGC = new OGRGeometryCollection();
     687                 : 
     688               9 :         assert(NULL != poGC);
     689                 : 
     690               9 :         if( nBytes < 8 )
     691               0 :             return OGRERR_NOT_ENOUGH_DATA;
     692                 : 
     693               9 :         memcpy( &nGeomCount, pabyData + 4, 4 );
     694               9 :         if (NEED_SWAP_SPATIALITE())
     695               0 :             CPL_SWAP32PTR( &nGeomCount );
     696                 : 
     697               9 :         if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
     698               0 :             return OGRERR_CORRUPT_DATA;
     699                 : 
     700                 :         /* Each sub geometry takes at least 9 bytes */
     701               9 :         if (nBytes - 8 < nGeomCount * 9)
     702               0 :             return OGRERR_NOT_ENOUGH_DATA;
     703                 : 
     704               9 :         nBytesUsed = 8;
     705                 : 
     706              19 :         for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
     707                 :         {
     708                 :             int nThisGeomSize;
     709              10 :             OGRGeometry *poThisGeom = NULL;
     710                 : 
     711              10 :             if (nBytes - nBytesUsed < 5)
     712               0 :                 return OGRERR_NOT_ENOUGH_DATA;
     713                 : 
     714              10 :             if (pabyData[nBytesUsed] != 0x69)
     715               0 :                 return OGRERR_CORRUPT_DATA;
     716                 : 
     717              10 :             nBytesUsed ++;
     718                 : 
     719                 :             eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
     720                 :                                                  &poThisGeom, nBytes - nBytesUsed,
     721              10 :                                                  eByteOrder, &nThisGeomSize);
     722              10 :             if( eErr != OGRERR_NONE )
     723                 :             {
     724               0 :                 delete poGC;
     725               0 :                 return eErr;
     726                 :             }
     727                 : 
     728              10 :             nBytesUsed += nThisGeomSize;
     729              10 :             eErr = poGC->addGeometryDirectly( poThisGeom );
     730              10 :             if( eErr != OGRERR_NONE )
     731                 :             {
     732               0 :                 delete poGC;
     733               0 :                 return eErr;
     734                 :             }
     735                 :         }
     736                 : 
     737               9 :         poGeom = poGC;
     738               9 :         if( pnBytesConsumed )
     739               0 :             *pnBytesConsumed = nBytesUsed;
     740                 :     }
     741                 : 
     742                 : /* -------------------------------------------------------------------- */
     743                 : /*      Currently unsupported geometry.                                 */
     744                 : /* -------------------------------------------------------------------- */
     745                 :     else
     746                 :     {
     747               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     748                 :     }
     749                 : 
     750                 : /* -------------------------------------------------------------------- */
     751                 : /*      Assign spatial reference system.                                */
     752                 : /* -------------------------------------------------------------------- */
     753              37 :     if( eErr == OGRERR_NONE )
     754                 :     {
     755              37 :         *ppoReturn = poGeom;
     756                 :     }
     757                 :     else
     758                 :     {
     759               0 :         delete poGeom;
     760                 :     }
     761                 : 
     762              37 :     return eErr;
     763                 : }
     764                 : 
     765                 : /************************************************************************/
     766                 : /*                      ImportSpatiaLiteGeometry()                      */
     767                 : /************************************************************************/
     768                 : 
     769              31 : OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
     770                 :                                                  int nBytes,
     771                 :                                                  OGRGeometry **ppoGeometry )
     772                 : 
     773                 : {
     774                 :     OGRwkbByteOrder eByteOrder;
     775                 : 
     776              31 :     *ppoGeometry = NULL;
     777                 : 
     778             112 :     if( nBytes < 44
     779              27 :         || pabyData[0] != 0
     780              27 :         || pabyData[38] != 0x7C
     781              27 :         || pabyData[nBytes-1] != 0xFE )
     782               4 :         return OGRERR_CORRUPT_DATA;
     783                 : 
     784              27 :     eByteOrder = (OGRwkbByteOrder) pabyData[1];
     785                 : 
     786                 :     return createFromSpatialiteInternal(pabyData + 39, ppoGeometry,
     787              27 :                                         nBytes - 39, eByteOrder, NULL);
     788                 : }
     789                 : 
     790                 : /************************************************************************/
     791                 : /*                  ComputeSpatiaLiteGeometrySize()                     */
     792                 : /************************************************************************/
     793                 : 
     794              34 : int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry)
     795                 : {
     796              34 :     switch (wkbFlatten(poGeometry->getGeometryType()))
     797                 :     {
     798                 :         case wkbPoint:
     799               5 :             return 16;
     800                 : 
     801                 :         case wkbLineString:
     802                 :         case wkbLinearRing:
     803              12 :             return 4 + 16 * ((OGRLineString*)poGeometry)->getNumPoints();
     804                 : 
     805                 :         case wkbPolygon:
     806                 :         {
     807               8 :             int nSize = 4;
     808               8 :             OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
     809               8 :             if (poPoly->getExteriorRing() != NULL)
     810                 :             {
     811               7 :                 nSize += ComputeSpatiaLiteGeometrySize(poPoly->getExteriorRing());
     812                 : 
     813               7 :                 int nInteriorRingCount = poPoly->getNumInteriorRings();
     814               8 :                 for(int i=0;i<nInteriorRingCount;i++)
     815               1 :                     nSize += ComputeSpatiaLiteGeometrySize(poPoly->getInteriorRing(i));
     816                 :             }
     817               8 :             return nSize;
     818                 :         }
     819                 : 
     820                 :         case wkbMultiPoint:
     821                 :         case wkbMultiLineString:
     822                 :         case wkbMultiPolygon:
     823                 :         case wkbGeometryCollection:
     824                 :         {
     825               9 :             int nSize = 4;
     826               9 :             OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
     827               9 :             int nParts = poGeomCollection->getNumGeometries();
     828              19 :             for(int i=0;i<nParts;i++)
     829              10 :                 nSize += 5 + ComputeSpatiaLiteGeometrySize(poGeomCollection->getGeometryRef(i));
     830               9 :             return nSize;
     831                 :         }
     832                 : 
     833                 :         default:
     834               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
     835               0 :             return 0;
     836                 :     }
     837                 : }
     838                 : 
     839                 : /************************************************************************/
     840                 : /*                      ExportSpatiaLiteGeometry()                      */
     841                 : /************************************************************************/
     842                 : 
     843              34 : int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeometry,
     844                 :                                                      OGRwkbByteOrder eByteOrder,
     845                 :                                                      GByte* pabyData)
     846                 : {
     847              34 :     switch (wkbFlatten(poGeometry->getGeometryType()))
     848                 :     {
     849                 :         case wkbPoint:
     850                 :         {
     851               5 :             OGRPoint* poPoint = (OGRPoint*) poGeometry;
     852               5 :             double x = poPoint->getX();
     853               5 :             double y = poPoint->getY();
     854               5 :             memcpy(pabyData, &x, 8);
     855               5 :             memcpy(pabyData + 8, &y, 8);
     856               5 :             if (NEED_SWAP_SPATIALITE())
     857                 :             {
     858               0 :                 CPL_SWAP64PTR( pabyData );
     859               0 :                 CPL_SWAP64PTR( pabyData + 8 );
     860                 :             }
     861               5 :             return 16;
     862                 :         }
     863                 : 
     864                 :         case wkbLineString:
     865                 :         case wkbLinearRing:
     866                 :         {
     867              12 :             OGRLineString* poLineString = (OGRLineString*) poGeometry;
     868              12 :             int nTotalSize = 4;
     869              12 :             int nPointCount = poLineString->getNumPoints();
     870              12 :             memcpy(pabyData, &nPointCount, 4);
     871              12 :             if (NEED_SWAP_SPATIALITE())
     872               0 :                 CPL_SWAP32PTR( pabyData );
     873              34 :             for(int i=0;i<nPointCount;i++)
     874                 :             {
     875              22 :                 double x = poLineString->getX(i);
     876              22 :                 double y = poLineString->getY(i);
     877              22 :                 memcpy(pabyData + nTotalSize, &x, 8);
     878              22 :                 memcpy(pabyData + nTotalSize + 8, &y, 8);
     879              22 :                 if (NEED_SWAP_SPATIALITE())
     880                 :                 {
     881               0 :                     CPL_SWAP64PTR( pabyData + nTotalSize );
     882               0 :                     CPL_SWAP64PTR( pabyData + nTotalSize + 8 );
     883                 :                 }
     884              22 :                 nTotalSize += 16;
     885                 :             }
     886              12 :             return nTotalSize;
     887                 :         }
     888                 : 
     889                 :         case wkbPolygon:
     890                 :         {
     891               8 :             OGRPolygon* poPoly = (OGRPolygon*) poGeometry;
     892               8 :             int nParts = 0;
     893               8 :             int nTotalSize = 4;
     894               8 :             if (poPoly->getExteriorRing() != NULL)
     895                 :             {
     896               7 :                 int nInteriorRingCount = poPoly->getNumInteriorRings();
     897               7 :                 nParts = 1 + nInteriorRingCount;
     898               7 :                 memcpy(pabyData, &nParts, 4);
     899               7 :                 if (NEED_SWAP_SPATIALITE())
     900               0 :                     CPL_SWAP32PTR( pabyData );
     901                 : 
     902                 :                 nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getExteriorRing(),
     903               7 :                                                               eByteOrder, pabyData + nTotalSize);
     904                 : 
     905               8 :                 for(int i=0;i<nInteriorRingCount;i++)
     906                 :                 {
     907                 :                     nTotalSize += ExportSpatiaLiteGeometryInternal(poPoly->getInteriorRing(i),
     908               1 :                                                                    eByteOrder, pabyData + nTotalSize);
     909                 :                 }
     910                 :             }
     911                 :             else
     912                 :             {
     913               1 :                 memset(pabyData, 0, 4);
     914                 :             }
     915               8 :             return nTotalSize;
     916                 :         }
     917                 : 
     918                 :         case wkbMultiPoint:
     919                 :         case wkbMultiLineString:
     920                 :         case wkbMultiPolygon:
     921                 :         case wkbGeometryCollection:
     922                 :         {
     923               9 :             OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*) poGeometry;
     924               9 :             int nTotalSize = 4;
     925               9 :             int nParts = poGeomCollection->getNumGeometries();
     926               9 :             memcpy(pabyData, &nParts, 4);
     927               9 :             if (NEED_SWAP_SPATIALITE())
     928               0 :                 CPL_SWAP32PTR( pabyData );
     929                 : 
     930              19 :             for(int i=0;i<nParts;i++)
     931                 :             {
     932              10 :                 pabyData[nTotalSize] = 0x69;
     933              10 :                 nTotalSize ++;
     934                 :                 int nCode;
     935              10 :                 switch (wkbFlatten(poGeomCollection->getGeometryRef(i)->getGeometryType()))
     936                 :                 {
     937               3 :                     case wkbPoint: nCode = 1; break;
     938               2 :                     case wkbLineString: nCode = 2; break;
     939               5 :                     case wkbPolygon: nCode = 3; break;
     940               0 :                     default: CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type"); return 0;
     941                 :                 }
     942              10 :                 memcpy(pabyData + nTotalSize, &nCode, 4);
     943              10 :                 if (NEED_SWAP_SPATIALITE())
     944               0 :                     CPL_SWAP32PTR( pabyData + nTotalSize );
     945              10 :                 nTotalSize += 4;
     946                 :                 nTotalSize += ExportSpatiaLiteGeometryInternal(poGeomCollection->getGeometryRef(i),
     947              10 :                                                                eByteOrder, pabyData + nTotalSize);
     948                 :             }
     949               9 :             return nTotalSize;
     950                 :         }
     951                 : 
     952                 :         default:
     953               0 :             return 0;
     954                 :     }
     955                 : }
     956                 : 
     957                 : 
     958              16 : OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
     959                 :                                                  GInt32 nSRID,
     960                 :                                                  OGRwkbByteOrder eByteOrder,
     961                 :                                                  GByte **ppabyData,
     962                 :                                                  int *pnDataLenght )
     963                 : 
     964                 : {
     965              16 :     int     nDataLen = 44 + ComputeSpatiaLiteGeometrySize(poGeometry);
     966              16 :     OGREnvelope sEnvelope;
     967                 : 
     968              16 :     *ppabyData =  (GByte *) CPLMalloc( nDataLen );
     969                 : 
     970              16 :     (*ppabyData)[0] = 0x00;
     971              16 :     (*ppabyData)[1] = eByteOrder;
     972                 : 
     973                 :     // Write out SRID
     974              16 :     memcpy( *ppabyData + 2, &nSRID, 4 );
     975                 : 
     976                 :     // Write out the geometry bounding rectangle
     977              16 :     poGeometry->getEnvelope( &sEnvelope );
     978              16 :     memcpy( *ppabyData + 6, &sEnvelope.MinX, 8 );
     979              16 :     memcpy( *ppabyData + 14, &sEnvelope.MinY, 8 );
     980              16 :     memcpy( *ppabyData + 22, &sEnvelope.MaxX, 8 );
     981              16 :     memcpy( *ppabyData + 30, &sEnvelope.MaxY, 8 );
     982                 : 
     983              16 :     (*ppabyData)[38] = 0x7C;
     984                 : 
     985              16 :     int nCode = 0;
     986              16 :     switch (wkbFlatten(poGeometry->getGeometryType()))
     987                 :     {
     988                 :         case wkbPoint:
     989               2 :             nCode = 1;
     990               2 :             break;
     991                 : 
     992                 :         case wkbLineString:
     993                 :         case wkbLinearRing:
     994               2 :             nCode = 2;
     995               2 :             break;
     996                 : 
     997                 :         case wkbPolygon:
     998               3 :             nCode = 3;
     999               3 :             break;
    1000                 : 
    1001                 :         case wkbMultiPoint:
    1002               2 :             nCode = 4;
    1003               2 :             break;
    1004                 : 
    1005                 :         case wkbMultiLineString:
    1006               2 :             nCode = 5;
    1007               2 :             break;
    1008                 : 
    1009                 :         case wkbMultiPolygon:
    1010               2 :             nCode = 6;
    1011               2 :             break;
    1012                 : 
    1013                 :         case wkbGeometryCollection:
    1014               3 :             nCode = 7;
    1015               3 :             break;
    1016                 : 
    1017                 :         default:
    1018               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
    1019               0 :             CPLFree(*ppabyData);
    1020               0 :             *ppabyData = NULL;
    1021               0 :             *pnDataLenght = 0;
    1022               0 :             return CE_Failure;
    1023                 :     }
    1024              16 :     memcpy( *ppabyData + 39, &nCode, 4 );
    1025                 : 
    1026              16 :     int nWritten = ExportSpatiaLiteGeometryInternal(poGeometry, eByteOrder, *ppabyData + 43);
    1027              16 :     if (nWritten == 0)
    1028                 :     {
    1029               0 :         CPLFree(*ppabyData);
    1030               0 :         *ppabyData = NULL;
    1031               0 :         *pnDataLenght = 0;
    1032               0 :         return CE_Failure;
    1033                 :     }
    1034                 : 
    1035              16 :     (*ppabyData)[nDataLen - 1] = 0xFE;
    1036                 : 
    1037              16 :     if( NEED_SWAP_SPATIALITE() )
    1038                 :     {
    1039               0 :         CPL_SWAP32PTR( *ppabyData + 2 );
    1040               0 :         CPL_SWAP64PTR( *ppabyData + 6 );
    1041               0 :         CPL_SWAP64PTR( *ppabyData + 14 );
    1042               0 :         CPL_SWAP64PTR( *ppabyData + 22 );
    1043               0 :         CPL_SWAP64PTR( *ppabyData + 30 );
    1044               0 :         CPL_SWAP32PTR( *ppabyData + 39 );
    1045                 :     }
    1046                 : 
    1047              16 :     *pnDataLenght = nDataLen;
    1048                 : 
    1049              16 :     return CE_None;
    1050                 : }
    1051                 : 
    1052                 : /************************************************************************/
    1053                 : /*                           TestCapability()                           */
    1054                 : /************************************************************************/
    1055                 : 
    1056               0 : int OGRSQLiteLayer::TestCapability( const char * pszCap )
    1057                 : 
    1058                 : {
    1059               0 :     if( EQUAL(pszCap,OLCRandomRead) )
    1060               0 :         return FALSE;
    1061                 : 
    1062               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
    1063               0 :         return FALSE;
    1064                 : 
    1065               0 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
    1066               0 :         return FALSE;
    1067                 : 
    1068               0 :     else if( EQUAL(pszCap,OLCTransactions) )
    1069               0 :         return FALSE;
    1070                 : 
    1071                 :     else 
    1072               0 :         return FALSE;
    1073                 : }
    1074                 : 
    1075                 : /************************************************************************/
    1076                 : /*                           GetSpatialRef()                            */
    1077                 : /************************************************************************/
    1078                 : 
    1079               5 : OGRSpatialReference *OGRSQLiteLayer::GetSpatialRef()
    1080                 : 
    1081                 : {
    1082               5 :     return poSRS;
    1083                 : }
    1084                 : 
    1085                 : /************************************************************************/
    1086                 : /*                          StartTransaction()                          */
    1087                 : /************************************************************************/
    1088                 : 
    1089               4 : OGRErr OGRSQLiteLayer::StartTransaction()
    1090                 : 
    1091                 : {
    1092               4 :     return poDS->SoftStartTransaction();
    1093                 : }
    1094                 : 
    1095                 : /************************************************************************/
    1096                 : /*                         CommitTransaction()                          */
    1097                 : /************************************************************************/
    1098                 : 
    1099               3 : OGRErr OGRSQLiteLayer::CommitTransaction()
    1100                 : 
    1101                 : {
    1102               3 :     return poDS->SoftCommit();
    1103                 : }
    1104                 : 
    1105                 : /************************************************************************/
    1106                 : /*                        RollbackTransaction()                         */
    1107                 : /************************************************************************/
    1108                 : 
    1109               1 : OGRErr OGRSQLiteLayer::RollbackTransaction()
    1110                 : 
    1111                 : {
    1112               1 :     return poDS->SoftRollback();
    1113                 : }

Generated by: LCOV version 1.7