LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/sqlite - ogrsqlitetablelayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 316
Code covered: 87.0 % Executed lines: 275

       1                 : /******************************************************************************
       2                 :  * $Id: ogrsqlitetablelayer.cpp 19800 2010-06-04 21:38:03Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2004, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "cpl_conv.h"
      31                 : #include "cpl_string.h"
      32                 : #include "ogr_sqlite.h"
      33                 : #include <string>
      34                 : 
      35                 : CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 19800 2010-06-04 21:38:03Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                        OGRSQLiteTableLayer()                         */
      39                 : /************************************************************************/
      40                 : 
      41             590 : OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
      42                 : 
      43                 : {
      44             590 :     poDS = poDSIn;
      45                 : 
      46             590 :     bUpdateAccess = TRUE;
      47                 : 
      48             590 :     iNextShapeId = 0;
      49                 : 
      50             590 :     nSRSId = -1;
      51                 : 
      52             590 :     poFeatureDefn = NULL;
      53             590 : }
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                        ~OGRSQLiteTableLayer()                        */
      57                 : /************************************************************************/
      58                 : 
      59             590 : OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
      60                 : 
      61                 : {
      62             590 :     ClearStatement();
      63             590 : }
      64                 : 
      65                 : /************************************************************************/
      66                 : /*                             Initialize()                             */
      67                 : /************************************************************************/
      68                 : 
      69                 : CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableName, 
      70                 :                                         const char *pszGeomCol,
      71                 :                                         OGRwkbGeometryType eGeomType,
      72                 :                                         const char *pszGeomFormat,
      73                 :                                         OGRSpatialReference *poSRS,
      74                 :                                         int nSRSId,
      75             590 :                                         int bHasSpatialIndex)
      76                 : 
      77                 : {
      78                 :     int rc;
      79             590 :     sqlite3 *hDB = poDS->GetDB();
      80                 : 
      81             590 :     if( pszGeomCol == NULL )
      82             474 :         osGeomColumn = "";
      83                 :     else
      84             116 :         osGeomColumn = pszGeomCol;
      85                 : 
      86             590 :     if( pszGeomFormat )
      87                 :     {
      88             116 :         if ( EQUAL(pszGeomFormat, "WKT") )
      89               6 :             eGeomFormat = OSGF_WKT;
      90             110 :         else if ( EQUAL(pszGeomFormat,"WKB") )
      91              32 :             eGeomFormat = OSGF_WKB;
      92              78 :         else if ( EQUAL(pszGeomFormat,"FGF") )
      93               1 :             eGeomFormat = OSGF_FGF;
      94              77 :         else if( EQUAL(pszGeomFormat,"SpatiaLite") )
      95              77 :             eGeomFormat = OSGF_SpatiaLite;
      96                 :     }
      97                 : 
      98             590 :     CPLFree( pszFIDColumn );
      99             590 :     pszFIDColumn = NULL;
     100                 : 
     101             590 :     this->poSRS = poSRS;
     102             590 :     this->nSRSId = nSRSId;
     103             590 :     this->bHasSpatialIndex = bHasSpatialIndex;
     104                 : 
     105             590 :     if( poSRS )
     106              85 :         poSRS->Reference();
     107                 : 
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Get the column definitions for this table.                      */
     110                 : /* -------------------------------------------------------------------- */
     111                 :     CPLErr eErr;
     112             590 :     sqlite3_stmt *hColStmt = NULL;
     113                 :     const char *pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
     114             590 :                                      pszTableName );
     115                 : 
     116             590 :     rc = sqlite3_prepare( hDB, pszSQL, strlen(pszSQL), &hColStmt, NULL ); 
     117             590 :     if( rc != SQLITE_OK )
     118                 :     {
     119                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     120                 :                   "Unable to query table %s for column definitions : %s.",
     121               0 :                   pszTableName, sqlite3_errmsg(hDB) );
     122                 :         
     123               0 :         return CE_Failure;
     124                 :     }
     125                 : 
     126             590 :     rc = sqlite3_step( hColStmt );
     127             590 :     if ( rc != SQLITE_DONE && rc != SQLITE_ROW )
     128                 :     {
     129                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     130                 :                   "In Initialize(): sqlite3_step(%s):\n  %s", 
     131               0 :                   pszSQL, sqlite3_errmsg(hDB) );
     132               0 :         sqlite3_finalize( hColStmt );
     133               0 :         return CE_Failure;
     134                 :     }
     135                 : 
     136                 : /* -------------------------------------------------------------------- */
     137                 : /*      What should we use as FID?  If there is a primary key           */
     138                 : /*      integer field, then this will be used as the _rowid_, and we    */
     139                 : /*      will pick up the real column name here.  Otherwise, we will     */
     140                 : /*      just use fid.                                                   */
     141                 : /*                                                                      */
     142                 : /*      Note that the select _rowid_ will return the real column        */
     143                 : /*      name if the rowid corresponds to another primary key            */
     144                 : /*      column.                                                         */
     145                 : /* -------------------------------------------------------------------- */
     146             590 :     pszFIDColumn = CPLStrdup(sqlite3_column_name( hColStmt, 0 ));
     147                 : 
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Collect the rest of the fields.                                 */
     150                 : /* -------------------------------------------------------------------- */
     151             590 :     eErr = BuildFeatureDefn( pszTableName, hColStmt );
     152             590 :     sqlite3_finalize( hColStmt );
     153                 : 
     154             590 :     if( eErr != CE_None )
     155               0 :         return eErr;
     156                 : 
     157                 : 
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      Set the geometry type if we know it.                            */
     160                 : /* -------------------------------------------------------------------- */
     161             590 :     if( eGeomType != wkbUnknown )
     162              46 :         poFeatureDefn->SetGeomType( eGeomType );
     163                 : 
     164             590 :     return CE_None;
     165                 : }
     166                 : 
     167                 : /************************************************************************/
     168                 : /*                           ResetStatement()                           */
     169                 : /************************************************************************/
     170                 : 
     171              82 : OGRErr OGRSQLiteTableLayer::ResetStatement()
     172                 : 
     173                 : {
     174                 :     int rc;
     175              82 :     CPLString osSQL;
     176                 : 
     177              82 :     ClearStatement();
     178                 : 
     179              82 :     iNextShapeId = 0;
     180                 : 
     181                 :     osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s", 
     182                 :                     poFeatureDefn->GetName(), 
     183              82 :                     osWHERE.c_str() );
     184                 : 
     185                 :     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(),
     186              82 :               &hStmt, NULL );
     187                 : 
     188              82 :     if( rc == SQLITE_OK )
     189                 :     {
     190              82 :   return OGRERR_NONE;
     191                 :     }
     192                 :     else
     193                 :     {
     194                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     195                 :                   "In ResetStatement(): sqlite3_prepare(%s):\n  %s", 
     196               0 :                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
     197               0 :         hStmt = NULL;
     198               0 :         return OGRERR_FAILURE;
     199               0 :     }
     200                 : }
     201                 : 
     202                 : 
     203                 : /************************************************************************/
     204                 : /*                             GetFeature()                             */
     205                 : /************************************************************************/
     206                 : 
     207               1 : OGRFeature *OGRSQLiteTableLayer::GetFeature( long nFeatureId )
     208                 : 
     209                 : {
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      If we don't have an explicit FID column, just read through      */
     212                 : /*      the result set iteratively to find our target.                  */
     213                 : /* -------------------------------------------------------------------- */
     214               1 :     if( pszFIDColumn == NULL )
     215               0 :         return OGRSQLiteLayer::GetFeature( nFeatureId );
     216                 : 
     217                 : /* -------------------------------------------------------------------- */
     218                 : /*      Setup explicit query statement to fetch the record we want.     */
     219                 : /* -------------------------------------------------------------------- */
     220               1 :     CPLString osSQL;
     221                 :     int rc;
     222                 : 
     223               1 :     ClearStatement();
     224                 : 
     225               1 :     iNextShapeId = nFeatureId;
     226                 : 
     227                 :     osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = %d", 
     228                 :                   poFeatureDefn->GetName(), 
     229               1 :                   pszFIDColumn, (int) nFeatureId );
     230                 : 
     231               1 :     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
     232                 : 
     233                 :     rc = sqlite3_prepare( poDS->GetDB(), osSQL, osSQL.size(), 
     234               1 :                           &hStmt, NULL );
     235               1 :     if( rc != SQLITE_OK )
     236                 :     {
     237                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     238                 :                   "In GetFeature(): sqlite3_prepare(%s):\n  %s", 
     239               0 :                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
     240                 : 
     241               1 :         return NULL;
     242                 :     }
     243                 : /* -------------------------------------------------------------------- */
     244                 : /*      Get the feature if possible.                                    */
     245                 : /* -------------------------------------------------------------------- */
     246               1 :     OGRFeature *poFeature = NULL;
     247                 : 
     248               1 :     poFeature = GetNextRawFeature();
     249                 : 
     250               1 :     ResetReading();
     251                 : 
     252               1 :     return poFeature;
     253                 : }
     254                 : 
     255                 : /************************************************************************/
     256                 : /*                         SetAttributeFilter()                         */
     257                 : /************************************************************************/
     258                 : 
     259              22 : OGRErr OGRSQLiteTableLayer::SetAttributeFilter( const char *pszQuery )
     260                 : 
     261                 : {
     262              22 :     if( pszQuery == NULL )
     263               8 :         osQuery = "";
     264                 :     else
     265              14 :         osQuery = pszQuery;
     266                 : 
     267              22 :     BuildWhere();
     268                 : 
     269              22 :     ResetReading();
     270                 : 
     271              22 :     return OGRERR_NONE;
     272                 : }
     273                 : 
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                          SetSpatialFilter()                          */
     277                 : /************************************************************************/
     278                 : 
     279               5 : void OGRSQLiteTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     280                 : 
     281                 : {
     282               5 :     if( InstallFilter( poGeomIn ) )
     283                 :     {
     284               5 :         BuildWhere();
     285                 : 
     286               5 :         ResetReading();
     287                 :     }
     288               5 : }
     289                 : 
     290                 : /************************************************************************/
     291                 : /*                             BuildWhere()                             */
     292                 : /*                                                                      */
     293                 : /*      Build the WHERE statement appropriate to the current set of     */
     294                 : /*      criteria (spatial and attribute queries).                       */
     295                 : /************************************************************************/
     296                 : 
     297              27 : void OGRSQLiteTableLayer::BuildWhere()
     298                 : 
     299                 : {
     300              27 :     osWHERE = "";
     301                 : 
     302              33 :     if( m_poFilterGeom != NULL && bHasSpatialIndex )
     303                 :     {
     304               1 :         OGREnvelope  sEnvelope;
     305                 : 
     306               1 :         m_poFilterGeom->getEnvelope( &sEnvelope );
     307                 :         osWHERE.Printf("WHERE MBRWithin(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f, %d)) ",
     308                 :                        osGeomColumn.c_str(),
     309                 :                        sEnvelope.MinX, sEnvelope.MinY,
     310                 :                        sEnvelope.MaxX, sEnvelope.MaxY,
     311               1 :                        nSRSId);
     312                 :     }
     313                 : 
     314              27 :     if( strlen(osQuery) > 0 )
     315                 :     {
     316              14 :         if( strlen(osWHERE) == 0 )
     317                 :         {
     318              14 :             osWHERE.Printf( "WHERE %s ", osQuery.c_str()  );
     319                 :         }
     320                 :         else  
     321                 :         {
     322               0 :             osWHERE += "AND ";
     323               0 :             osWHERE += osQuery;
     324                 :         }
     325                 :     }
     326              27 : }
     327                 : 
     328                 : /************************************************************************/
     329                 : /*                           TestCapability()                           */
     330                 : /************************************************************************/
     331                 : 
     332              15 : int OGRSQLiteTableLayer::TestCapability( const char * pszCap )
     333                 : 
     334                 : {
     335              15 :     if (EQUAL(pszCap,OLCFastFeatureCount))
     336                 :         return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
     337              11 :                bHasSpatialIndex;
     338                 : 
     339               4 :     else if (EQUAL(pszCap,OLCFastSpatialFilter))
     340               2 :         return bHasSpatialIndex;
     341                 : 
     342               2 :     else if( EQUAL(pszCap,OLCRandomRead) )
     343               0 :         return pszFIDColumn != NULL;
     344                 : 
     345               2 :     else if( EQUAL(pszCap,OLCSequentialWrite) 
     346                 :              || EQUAL(pszCap,OLCRandomWrite) )
     347               0 :         return bUpdateAccess;
     348                 : 
     349               2 :     else if( EQUAL(pszCap,OLCCreateField) )
     350               0 :         return bUpdateAccess;
     351                 : 
     352                 :     else 
     353               2 :         return OGRSQLiteLayer::TestCapability( pszCap );
     354                 : }
     355                 : 
     356                 : /************************************************************************/
     357                 : /*                          GetFeatureCount()                           */
     358                 : /*                                                                      */
     359                 : /*      If a spatial filter is in effect, we turn control over to       */
     360                 : /*      the generic counter.  Otherwise we return the total count.      */
     361                 : /*      Eventually we should consider implementing a more efficient     */
     362                 : /*      way of counting features matching a spatial query.              */
     363                 : /************************************************************************/
     364                 : 
     365               9 : int OGRSQLiteTableLayer::GetFeatureCount( int bForce )
     366                 : 
     367                 : {
     368               9 :     if( !TestCapability(OLCFastFeatureCount) )
     369               3 :         return OGRSQLiteLayer::GetFeatureCount( bForce );
     370                 : 
     371                 : /* -------------------------------------------------------------------- */
     372                 : /*      Form count SQL.                                                 */
     373                 : /* -------------------------------------------------------------------- */
     374                 :     const char *pszSQL;
     375                 : 
     376                 :     pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
     377               6 :                             poFeatureDefn->GetName(), osWHERE.c_str() );
     378                 : 
     379                 : /* -------------------------------------------------------------------- */
     380                 : /*      Execute.                                                        */
     381                 : /* -------------------------------------------------------------------- */
     382                 :     char **papszResult, *pszErrMsg;
     383                 :     int nRowCount, nColCount;
     384               6 :     int nResult = -1;
     385                 : 
     386               6 :     if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult, 
     387                 :                            &nColCount, &nRowCount, &pszErrMsg ) != SQLITE_OK )
     388               0 :         return -1;
     389                 : 
     390               6 :     if( nRowCount == 1 && nColCount == 1 )
     391               6 :         nResult = atoi(papszResult[1]);
     392                 : 
     393               6 :     sqlite3_free_table( papszResult );
     394                 : 
     395               6 :     return nResult;
     396                 : }
     397                 : 
     398                 : /************************************************************************/
     399                 : /*                           GetSpatialRef()                            */
     400                 : /*                                                                      */
     401                 : /*      We override this to try and fetch the table SRID from the       */
     402                 : /*      geometry_columns table if the srsid is -2 (meaning we           */
     403                 : /*      haven't yet even looked for it).                                */
     404                 : /************************************************************************/
     405                 : 
     406              29 : OGRSpatialReference *OGRSQLiteTableLayer::GetSpatialRef()
     407                 : 
     408                 : {
     409              29 :     return OGRSQLiteLayer::GetSpatialRef();
     410                 : }
     411                 : 
     412                 : /************************************************************************/
     413                 : /*                            CreateField()                             */
     414                 : /************************************************************************/
     415                 : 
     416                 : OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
     417              20 :                                          int bApproxOK )
     418                 : 
     419                 : {
     420              20 :     OGRFieldDefn        oField( poFieldIn );
     421                 : 
     422              20 :     ResetReading();
     423                 : 
     424                 : /* -------------------------------------------------------------------- */
     425                 : /*      Do we want to "launder" the column names into SQLite            */
     426                 : /*      friendly format?                                                */
     427                 : /* -------------------------------------------------------------------- */
     428              20 :     if( bLaunderColumnNames )
     429                 :     {
     430              19 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
     431                 : 
     432              19 :         oField.SetName( pszSafeName );
     433              19 :         CPLFree( pszSafeName );
     434                 :     }
     435                 : 
     436                 : /* -------------------------------------------------------------------- */
     437                 : /*      How much space do we need for the list of fields.               */
     438                 : /* -------------------------------------------------------------------- */
     439              20 :     int iField, nFieldListLen = 100;
     440                 :     char *pszOldFieldList, *pszNewFieldList;
     441                 : 
     442              48 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     443                 :     {
     444                 :         nFieldListLen += 
     445              28 :             strlen(poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) + 50;
     446                 :     }
     447                 : 
     448              20 :     nFieldListLen += strlen( oField.GetNameRef() );
     449                 : 
     450              20 :     pszOldFieldList = (char *) CPLCalloc(1,nFieldListLen);
     451              20 :     pszNewFieldList = (char *) CPLCalloc(1,nFieldListLen);
     452                 : 
     453                 : /* -------------------------------------------------------------------- */
     454                 : /*      Build list of old fields, and the list of new fields.           */
     455                 : /* -------------------------------------------------------------------- */
     456                 :     const char *pszType;
     457              20 :     sprintf( pszOldFieldList, "%s", "OGC_FID" );
     458              20 :     sprintf( pszNewFieldList, "%s", "OGC_FID INTEGER PRIMARY KEY" );
     459                 :     
     460              20 :     int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
     461                 : 
     462              20 :     if( poFeatureDefn->GetGeomType() != wkbNone )
     463                 :     {
     464              20 :         strcat( pszOldFieldList, "," );
     465              20 :         strcat( pszNewFieldList, "," );
     466                 : 
     467              20 :         strcat( pszOldFieldList, osGeomColumn );
     468              20 :         strcat( pszNewFieldList, osGeomColumn );
     469                 : 
     470              20 :         if ( eGeomFormat == OSGF_WKT )
     471               1 :             strcat( pszNewFieldList, " VARCHAR" );
     472                 :         else
     473              19 :             strcat( pszNewFieldList, " BLOB" );
     474                 : 
     475              20 :         iNextOrdinal++;
     476                 :     }
     477                 : 
     478              48 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     479                 :     {
     480              28 :         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
     481                 : 
     482                 :         // we already added OGC_FID so don't do it again
     483              28 :         if( EQUAL(poFldDefn->GetNameRef(),"OGC_FID") )
     484               0 :             continue;
     485                 : 
     486              28 :         if( poFldDefn->GetType() == OFTInteger )
     487              10 :             pszType = "INTEGER";
     488              18 :         else if( poFldDefn->GetType() == OFTReal )
     489              12 :             pszType = "FLOAT";
     490               6 :         else if( poFldDefn->GetType() == OFTBinary )
     491               1 :             pszType = "BLOB";
     492                 :         else
     493               5 :             pszType = "VARCHAR";
     494                 :         
     495                 :         sprintf( pszOldFieldList+strlen(pszOldFieldList), 
     496              28 :                  ", '%s'", poFldDefn->GetNameRef() );
     497                 : 
     498                 :         sprintf( pszNewFieldList+strlen(pszNewFieldList), 
     499              28 :                  ", '%s' %s", poFldDefn->GetNameRef(), pszType );
     500                 : 
     501              28 :         iNextOrdinal++;
     502                 :     }
     503                 : 
     504                 : /* -------------------------------------------------------------------- */
     505                 : /*      Add the new field.                                              */
     506                 : /* -------------------------------------------------------------------- */
     507              20 :     if( oField.GetType() == OFTInteger )
     508               4 :         pszType = "INTEGER";
     509              16 :     else if( oField.GetType() == OFTReal )
     510               4 :         pszType = "FLOAT";
     511              12 :     else if( oField.GetType() == OFTBinary )
     512               5 :         pszType = "BLOB";
     513                 :     else
     514               7 :         pszType = "VARCHAR";
     515                 :     
     516                 :     sprintf( pszNewFieldList+strlen(pszNewFieldList), 
     517              20 :              ", '%s' %s", oField.GetNameRef(), pszType );
     518                 : 
     519                 : /* ==================================================================== */
     520                 : /*      Backup, destroy, recreate and repopulate the table.  SQLite     */
     521                 : /*      has no ALTER TABLE so we have to do all this to add a           */
     522                 : /*      column.                                                         */
     523                 : /* ==================================================================== */
     524                 : 
     525                 : /* -------------------------------------------------------------------- */
     526                 : /*      Do this all in a transaction.                                   */
     527                 : /* -------------------------------------------------------------------- */
     528              20 :     poDS->SoftStartTransaction();
     529                 : 
     530                 : /* -------------------------------------------------------------------- */
     531                 : /*      Save existing related triggers and index                        */
     532                 : /* -------------------------------------------------------------------- */
     533                 :     int rc;
     534              20 :     char *pszErrMsg = NULL;
     535              20 :     sqlite3 *hDB = poDS->GetDB();
     536              20 :     CPLString osSQL;
     537                 : 
     538                 :     osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'", 
     539              20 :                    poFeatureDefn->GetName() );
     540                 : 
     541                 :     int nRowTriggerIndexCount, nColTriggerIndexCount;
     542              20 :     char **papszTriggerIndexResult = NULL;
     543                 :     rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult, 
     544              20 :                             &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
     545                 : 
     546                 : /* -------------------------------------------------------------------- */
     547                 : /*      Make a backup of the table.                                     */
     548                 : /* -------------------------------------------------------------------- */
     549                 : 
     550              20 :     if( rc == SQLITE_OK )
     551                 :         rc = sqlite3_exec( hDB, 
     552                 :                        CPLSPrintf( "CREATE TEMPORARY TABLE t1_back(%s)",
     553                 :                                    pszOldFieldList ),
     554              20 :                        NULL, NULL, &pszErrMsg );
     555                 : 
     556              20 :     if( rc == SQLITE_OK )
     557                 :         rc = sqlite3_exec( hDB, 
     558                 :                            CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
     559                 :                                        pszOldFieldList, 
     560                 :                                        poFeatureDefn->GetName() ),
     561              20 :                            NULL, NULL, &pszErrMsg );
     562                 : 
     563                 : 
     564                 : /* -------------------------------------------------------------------- */
     565                 : /*      Drop the original table, and recreate with new field.           */
     566                 : /* -------------------------------------------------------------------- */
     567              20 :     if( rc == SQLITE_OK )
     568                 :         rc = sqlite3_exec( hDB, 
     569                 :                            CPLSPrintf( "DROP TABLE '%s'", 
     570                 :                                        poFeatureDefn->GetName() ),
     571              20 :                            NULL, NULL, &pszErrMsg );
     572                 : 
     573              20 :     if( rc == SQLITE_OK )
     574                 :     {
     575                 :         const char *pszCmd = 
     576                 :             CPLSPrintf( "CREATE TABLE '%s' (%s)", 
     577                 :                         poFeatureDefn->GetName(),
     578              20 :                         pszNewFieldList );
     579                 :         rc = sqlite3_exec( hDB, pszCmd, 
     580              20 :                            NULL, NULL, &pszErrMsg );
     581                 : 
     582              20 :         CPLDebug( "OGR_SQLITE", "exec(%s)", pszCmd );
     583                 :     }
     584                 : 
     585                 : /* -------------------------------------------------------------------- */
     586                 : /*      Copy backup field values into new table.                        */
     587                 : /* -------------------------------------------------------------------- */
     588                 :     
     589              20 :     if( rc == SQLITE_OK )
     590                 :         rc = sqlite3_exec( hDB, 
     591                 :                            CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
     592                 :                                        poFeatureDefn->GetName(),
     593                 :                                        pszOldFieldList ),
     594              20 :                            NULL, NULL, &pszErrMsg );
     595                 : 
     596              20 :     CPLFree( pszOldFieldList );
     597              20 :     CPLFree( pszNewFieldList );
     598                 : 
     599                 : /* -------------------------------------------------------------------- */
     600                 : /*      Cleanup backup table.                                           */
     601                 : /* -------------------------------------------------------------------- */
     602                 :     
     603              20 :     if( rc == SQLITE_OK )
     604                 :         rc = sqlite3_exec( hDB, 
     605                 :                            CPLSPrintf( "DROP TABLE t1_back" ),
     606              20 :                            NULL, NULL, &pszErrMsg );
     607                 : 
     608                 : /* -------------------------------------------------------------------- */
     609                 : /*      Recreate existing related tables, triggers and index            */
     610                 : /* -------------------------------------------------------------------- */
     611                 : 
     612              20 :     if( rc == SQLITE_OK )
     613                 :     {
     614                 :         int i;
     615                 : 
     616              25 :         for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
     617                 :         {
     618               5 :             if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
     619                 :                 rc = sqlite3_exec( hDB, 
     620                 :                             papszTriggerIndexResult[i],
     621               5 :                             NULL, NULL, &pszErrMsg );
     622                 :         }
     623                 :     }
     624                 : 
     625                 : /* -------------------------------------------------------------------- */
     626                 : /*      COMMIT on success or ROLLBACK on failuire.                      */
     627                 : /* -------------------------------------------------------------------- */
     628                 : 
     629              20 :     sqlite3_free_table( papszTriggerIndexResult );
     630                 : 
     631              20 :     if( rc == SQLITE_OK )
     632                 :     {
     633              20 :         poDS->SoftCommit();
     634                 :     }
     635                 :     else
     636                 :     {
     637                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     638                 :                   "Failed to add field %s to table %s:\n %s",
     639                 :                   oField.GetNameRef(), poFeatureDefn->GetName(), 
     640               0 :                   pszErrMsg );
     641               0 :         sqlite3_free( pszErrMsg );
     642                 : 
     643               0 :         poDS->SoftRollback();
     644                 : 
     645               0 :         return OGRERR_FAILURE;
     646                 :     }
     647                 : 
     648                 : /* -------------------------------------------------------------------- */
     649                 : /*      Add the field to the OGRFeatureDefn.                            */
     650                 : /* -------------------------------------------------------------------- */
     651                 :     int iNewField;
     652                 : 
     653              20 :     poFeatureDefn->AddFieldDefn( &oField );
     654                 : 
     655              20 :     iNewField = poFeatureDefn->GetFieldCount() - 1;
     656                 :     panFieldOrdinals = (int *) 
     657              20 :         CPLRealloc(panFieldOrdinals, (iNewField+1) * sizeof(int) );
     658              20 :     panFieldOrdinals[iNewField] = iNextOrdinal;
     659                 : 
     660              20 :     return OGRERR_NONE;
     661                 : }
     662                 : 
     663                 : /************************************************************************/
     664                 : /*                             SetFeature()                             */
     665                 : /************************************************************************/
     666                 : 
     667               1 : OGRErr OGRSQLiteTableLayer::SetFeature( OGRFeature *poFeature )
     668                 : 
     669                 : {
     670               1 :     if( pszFIDColumn == NULL )
     671                 :     {
     672                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     673               0 :                   "SetFeature() without any FID column." );
     674               0 :         return OGRERR_FAILURE;
     675                 :     }
     676                 :     
     677               1 :     if( poFeature->GetFID() == OGRNullFID )
     678                 :     {
     679                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     680               0 :                   "SetFeature() with unset FID fails." );
     681               0 :         return OGRERR_FAILURE;
     682                 :     }
     683                 : /* -------------------------------------------------------------------- */
     684                 : /*      Drop the record with this FID.                                  */
     685                 : /* -------------------------------------------------------------------- */
     686                 :     int rc;
     687               1 :     char *pszErrMsg = NULL;
     688                 :     const char *pszSQL;
     689                 : 
     690                 :     pszSQL = 
     691                 :         CPLSPrintf( "DELETE FROM '%s' WHERE \"%s\" = %ld", 
     692                 :                     poFeatureDefn->GetName(), 
     693                 :                     pszFIDColumn,
     694               1 :                     poFeature->GetFID() );
     695                 : 
     696               1 :     CPLDebug( "OGR_SQLITE", "exec(%s)", pszSQL );
     697                 :     
     698                 :     rc = sqlite3_exec( poDS->GetDB(), pszSQL,
     699               1 :                        NULL, NULL, &pszErrMsg );
     700                 :     
     701               1 :     if( rc != SQLITE_OK )
     702                 :     {
     703                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     704                 :                   "Attempt to delete old feature with FID %d failed.\n%s", 
     705               0 :                   (int) poFeature->GetFID(), pszErrMsg );
     706               0 :         return OGRERR_FAILURE;
     707                 :     }
     708                 :     
     709                 : /* -------------------------------------------------------------------- */
     710                 : /*      Recreate the feature.                                           */
     711                 : /* -------------------------------------------------------------------- */
     712               1 :     return CreateFeature( poFeature );
     713                 : }
     714                 : 
     715                 : /************************************************************************/
     716                 : /*                           CreateFeature()                            */
     717                 : /************************************************************************/
     718                 : 
     719             217 : OGRErr OGRSQLiteTableLayer::CreateFeature( OGRFeature *poFeature )
     720                 : 
     721                 : {
     722             217 :     sqlite3 *hDB = poDS->GetDB();
     723             217 :     CPLString      osCommand;
     724             217 :     CPLString      osValues;
     725             217 :     int            bNeedComma = FALSE;
     726                 : 
     727             217 :     ResetReading();
     728                 : 
     729                 : /* -------------------------------------------------------------------- */
     730                 : /*      Form the INSERT command.                                        */
     731                 : /* -------------------------------------------------------------------- */
     732             217 :     osCommand += CPLSPrintf( "INSERT INTO '%s' (", poFeatureDefn->GetName() );
     733                 : 
     734                 : /* -------------------------------------------------------------------- */
     735                 : /*      Add FID if we have a cleartext FID column.                      */
     736                 : /* -------------------------------------------------------------------- */
     737             217 :     if( pszFIDColumn != NULL // && !EQUAL(pszFIDColumn,"OGC_FID") 
     738                 :         && poFeature->GetFID() != OGRNullFID )
     739                 :     {
     740              58 :         osCommand += pszFIDColumn;
     741                 : 
     742              58 :         osValues += CPLSPrintf( "%ld", poFeature->GetFID() );
     743              58 :         bNeedComma = TRUE;
     744                 :     }
     745                 : 
     746                 : /* -------------------------------------------------------------------- */
     747                 : /*      Add geometry.                                                   */
     748                 : /* -------------------------------------------------------------------- */
     749             217 :     OGRGeometry *poGeom = poFeature->GetGeometryRef();
     750                 : 
     751             217 :     if( osGeomColumn.size() != 0 &&
     752                 :         poGeom != NULL &&
     753                 :         eGeomFormat != OSGF_FGF )
     754                 :     {
     755                 : 
     756             195 :         if( bNeedComma )
     757                 :         {
     758              58 :             osCommand += ",";
     759              58 :             osValues += ",";
     760                 :         }
     761                 : 
     762             195 :         osCommand += osGeomColumn;
     763                 : 
     764             195 :         osValues += "?";
     765                 : 
     766             195 :         bNeedComma = TRUE;
     767                 :     }
     768                 : 
     769                 : /* -------------------------------------------------------------------- */
     770                 : /*      Add field values.                                               */
     771                 : /* -------------------------------------------------------------------- */
     772                 :     int iField;
     773             217 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     774                 : 
     775             592 :     for( iField = 0; iField < nFieldCount; iField++ )
     776                 :     {
     777             375 :         if( !poFeature->IsFieldSet( iField ) )
     778             110 :             continue;
     779                 : 
     780             265 :         if( bNeedComma )
     781                 :         {
     782             243 :             osCommand += ",";
     783             243 :             osValues += ",";
     784                 :         }
     785                 : 
     786             265 :         osCommand += "'";
     787             265 :         osCommand +=poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
     788             265 :         osCommand += "'";
     789                 : 
     790             265 :         osValues += "?";
     791                 : 
     792             265 :         bNeedComma = TRUE;
     793                 :     }
     794                 : 
     795                 : /* -------------------------------------------------------------------- */
     796                 : /*      Merge final command.                                            */
     797                 : /* -------------------------------------------------------------------- */
     798             217 :     osCommand += ") VALUES (";
     799             217 :     osCommand += osValues;
     800             217 :     osCommand += ")";
     801                 : 
     802                 : /* -------------------------------------------------------------------- */
     803                 : /*      Prepare the statement.                                          */
     804                 : /* -------------------------------------------------------------------- */
     805                 :     int rc;
     806                 :     sqlite3_stmt *hInsertStmt;
     807                 : 
     808                 : #ifdef DEBUG
     809             217 :     CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
     810                 : #endif
     811                 : 
     812             217 :     rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
     813             217 :     if( rc != SQLITE_OK )
     814                 :     {
     815                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     816                 :                   "In CreateFeature(): sqlite3_prepare(%s):\n  %s", 
     817               0 :                   osCommand.c_str(), sqlite3_errmsg(hDB) );
     818                 : 
     819               0 :         return OGRERR_FAILURE;
     820                 :     }
     821                 : 
     822                 : /* -------------------------------------------------------------------- */
     823                 : /*      Bind the geometry                                               */
     824                 : /* -------------------------------------------------------------------- */
     825             217 :     int nBindField = 1;
     826                 : 
     827             217 :     if( osGeomColumn.size() != 0 &&
     828                 :         poGeom != NULL &&
     829                 :         eGeomFormat != OSGF_FGF )
     830                 :     {
     831             195 :         if ( eGeomFormat == OSGF_WKT )
     832                 :         {
     833               1 :             char *pszWKT = NULL;
     834               1 :             poGeom->exportToWkt( &pszWKT );
     835               1 :             rc = sqlite3_bind_text( hInsertStmt, nBindField++, pszWKT, -1, CPLFree );
     836                 :         }
     837             194 :         else if( eGeomFormat == OSGF_WKB )
     838                 :         {
     839              57 :             int nWKBLen = poGeom->WkbSize();
     840              57 :             GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
     841                 : 
     842              57 :             poGeom->exportToWkb( wkbNDR, pabyWKB );
     843              57 :             rc = sqlite3_bind_blob( hInsertStmt, nBindField++, pabyWKB, nWKBLen, CPLFree );
     844                 :         }
     845             137 :         else if ( eGeomFormat == OSGF_SpatiaLite )
     846                 :         {
     847                 :             int     nBLOBLen;
     848                 :             GByte   *pabySLBLOB;
     849                 : 
     850                 :             ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR,
     851             137 :                                       &pabySLBLOB, &nBLOBLen );
     852             137 :             rc = sqlite3_bind_blob( hInsertStmt, nBindField++, pabySLBLOB, nBLOBLen, CPLFree );
     853                 :         }
     854                 :         else
     855                 :         {
     856               0 :             CPLAssert(0);
     857                 :         }
     858                 : 
     859             195 :         if( rc != SQLITE_OK )
     860                 :         {
     861                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     862                 :                       "sqlite3_bind_blob/text() failed:\n  %s", 
     863               0 :                       sqlite3_errmsg(hDB) );
     864                 :             
     865               0 :             sqlite3_finalize( hInsertStmt );
     866               0 :             return OGRERR_FAILURE;
     867                 :         }
     868                 :     }
     869                 :     
     870                 : /* -------------------------------------------------------------------- */
     871                 : /*      Bind field values.                                              */
     872                 : /* -------------------------------------------------------------------- */
     873                 :     
     874             592 :     for( iField = 0; iField < nFieldCount; iField++ )
     875                 :     {
     876                 :         const char *pszRawValue;
     877                 : 
     878             375 :         if( !poFeature->IsFieldSet( iField ) )
     879             110 :             continue;
     880                 : 
     881             265 :         switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
     882                 :         {
     883                 :             case OFTInteger:
     884                 :             {
     885              93 :                 int nFieldVal = poFeature->GetFieldAsInteger( iField );
     886              93 :                 rc = sqlite3_bind_int(hInsertStmt, nBindField++, nFieldVal);
     887              93 :                 break;
     888                 :             }
     889                 :             
     890                 :             case OFTReal:
     891                 :             {
     892              37 :                 double dfFieldVal = poFeature->GetFieldAsDouble( iField );
     893              37 :                 rc = sqlite3_bind_double(hInsertStmt, nBindField++, dfFieldVal);
     894              37 :                 break;
     895                 :             }
     896                 :             
     897                 :             case OFTBinary:
     898                 :             {
     899              21 :                 int nDataLength = 0;
     900                 :                 GByte* pabyData =
     901              21 :                     poFeature->GetFieldAsBinary( iField, &nDataLength );
     902                 :                 rc = sqlite3_bind_blob(hInsertStmt, nBindField++,
     903              21 :                                        pabyData, nDataLength, SQLITE_TRANSIENT);
     904              21 :                 break;
     905                 :             }
     906                 :             
     907                 :             default:
     908                 :             {
     909             114 :                 pszRawValue = poFeature->GetFieldAsString( iField );
     910                 :                 rc = sqlite3_bind_text(hInsertStmt, nBindField++,
     911             114 :                                        pszRawValue, -1, SQLITE_TRANSIENT);
     912                 :                 break;
     913                 :             }
     914                 :         }
     915                 :         
     916             265 :         if( rc != SQLITE_OK )
     917                 :         {
     918                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     919                 :                       "sqlite3_bind_() for column %s failed:\n  %s", 
     920                 :                       poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
     921               0 :                       sqlite3_errmsg(hDB) );
     922                 :             
     923               0 :             sqlite3_finalize( hInsertStmt );
     924               0 :             return OGRERR_FAILURE;
     925                 :         }
     926                 :     }
     927                 : 
     928                 : /* -------------------------------------------------------------------- */
     929                 : /*      Execute the insert.                                             */
     930                 : /* -------------------------------------------------------------------- */
     931             217 :     rc = sqlite3_step( hInsertStmt );
     932                 : 
     933             217 :     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     934                 :     {
     935                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     936                 :                   "sqlite3_step() failed:\n  %s", 
     937               0 :                   sqlite3_errmsg(hDB) );
     938                 :                   
     939               0 :         sqlite3_finalize( hInsertStmt );
     940               0 :         return OGRERR_FAILURE;
     941                 :     }
     942                 : 
     943                 : /* -------------------------------------------------------------------- */
     944                 : /*      Capture the FID/rowid.                                          */
     945                 : /* -------------------------------------------------------------------- */
     946             217 :     const sqlite_int64 nFID = sqlite3_last_insert_rowid( hDB );
     947             217 :     if(nFID > 0)
     948                 :     {
     949             216 :         poFeature->SetFID( nFID );
     950                 :     }
     951                 : 
     952             217 :     sqlite3_finalize( hInsertStmt );
     953                 : 
     954             217 :     return OGRERR_NONE;
     955                 : }
     956                 : 

Generated by: LTP GCOV extension version 1.5