LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitelayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 452
Code covered: 81.6 % Executed lines: 369

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

Generated by: LTP GCOV extension version 1.5