LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gft - ogrgfttablelayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 597 424 71.0 %
Date: 2011-12-18 Functions: 25 20 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgfttablelayer.cpp 22407 2011-05-20 19:31:11Z rouault $
       3                 :  *
       4                 :  * Project:  GFT Translator
       5                 :  * Purpose:  Implements OGRGFTTableLayer class.
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Even Rouault <even dot rouault at mines dash paris dot org>
      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 "ogr_gft.h"
      31                 : 
      32                 : CPL_CVSID("$Id: ogrgfttablelayer.cpp 22407 2011-05-20 19:31:11Z rouault $");
      33                 : 
      34                 : /************************************************************************/
      35                 : /*                         OGRGFTTableLayer()                           */
      36                 : /************************************************************************/
      37                 : 
      38              97 : OGRGFTTableLayer::OGRGFTTableLayer(OGRGFTDataSource* poDS,
      39                 :                          const char* pszTableName,
      40                 :                          const char* pszTableId,
      41              97 :                          const char* pszGeomColumnName) : OGRGFTLayer(poDS)
      42                 : 
      43                 : {
      44              97 :     osTableName = pszTableName;
      45              97 :     osTableId = pszTableId;
      46              97 :     osGeomColumnName = pszGeomColumnName ? pszGeomColumnName : "";
      47                 : 
      48              97 :     bHasTriedCreateTable = FALSE;
      49              97 :     bInTransaction = FALSE;
      50              97 :     nFeaturesInTransaction = 0;
      51                 : 
      52              97 :     bFirstTokenIsFID = TRUE;
      53              97 :     eGTypeForCreation = wkbUnknown;
      54              97 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                        ~OGRGFTTableLayer()                           */
      58                 : /************************************************************************/
      59                 : 
      60              97 : OGRGFTTableLayer::~OGRGFTTableLayer()
      61                 : 
      62                 : {
      63              97 :     CreateTableIfNecessary();
      64              97 : }
      65                 : 
      66                 : /************************************************************************/
      67                 : /*                            ResetReading()                            */
      68                 : /************************************************************************/
      69                 : 
      70               4 : void OGRGFTTableLayer::ResetReading()
      71                 : 
      72                 : {
      73               4 :     OGRGFTLayer::ResetReading();
      74               4 :     aosRows.resize(0);
      75               4 : }
      76                 : 
      77                 : /************************************************************************/
      78                 : /*                           TestCapability()                           */
      79                 : /************************************************************************/
      80                 : 
      81               0 : int OGRGFTTableLayer::TestCapability( const char * pszCap )
      82                 : 
      83                 : {
      84               0 :     if( EQUAL(pszCap,OLCRandomRead) )
      85               0 :         return TRUE;
      86                 : 
      87               0 :     else if( EQUAL(pszCap,OLCSequentialWrite)
      88                 :              || EQUAL(pszCap,OLCRandomWrite)
      89                 :              || EQUAL(pszCap,OLCDeleteFeature) )
      90               0 :         return poDS->IsReadWrite();
      91                 : 
      92               0 :     else if( EQUAL(pszCap,OLCCreateField) )
      93               0 :         return poDS->IsReadWrite();
      94                 : 
      95               0 :     else if( EQUAL(pszCap, OLCTransactions) )
      96               0 :         return poDS->IsReadWrite();
      97                 : 
      98               0 :     return OGRGFTLayer::TestCapability(pszCap);
      99                 : }
     100                 : 
     101                 : /************************************************************************/
     102                 : /*                           FetchDescribe()                            */
     103                 : /************************************************************************/
     104                 : 
     105               8 : int OGRGFTTableLayer::FetchDescribe()
     106                 : {
     107               8 :     poFeatureDefn = new OGRFeatureDefn( osTableName );
     108               8 :     poFeatureDefn->Reference();
     109                 : 
     110               8 :     const CPLString& osAuth = poDS->GetAuth();
     111               8 :     std::vector<CPLString> aosHeaderAndFirstDataLine;
     112              16 :     if (osAuth.size())
     113                 :     {
     114               7 :         CPLString osSQL("DESCRIBE ");
     115               7 :         osSQL += osTableId;
     116               7 :         CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
     117                 : 
     118               7 :         if (psResult == NULL)
     119               3 :             return FALSE;
     120                 : 
     121               4 :         char* pszLine = (char*) psResult->pabyData;
     122               4 :         if (pszLine == NULL ||
     123                 :             psResult->pszErrBuf != NULL ||
     124                 :             strncmp(pszLine, "column id,name,type",
     125                 :                     strlen("column id,name,type")) != 0)
     126                 :         {
     127               0 :             CPLHTTPDestroyResult(psResult);
     128               0 :             return FALSE;
     129                 :         }
     130                 : 
     131               4 :         pszLine = OGRGFTGotoNextLine(pszLine);
     132                 : 
     133               4 :         std::vector<CPLString> aosLines;
     134               4 :         ParseCSVResponse(pszLine, aosLines);
     135              15 :         for(int i=0;i<(int)aosLines.size();i++)
     136                 :         {
     137              11 :             char** papszTokens = OGRGFTCSVSplitLine(aosLines[i], ',');
     138              11 :             if (CSLCount(papszTokens) == 3)
     139                 :             {
     140              11 :                 aosColumnInternalName.push_back(papszTokens[0]);
     141                 : 
     142                 :                 //CPLDebug("GFT", "%s %s %s", papszTokens[0], papszTokens[1], papszTokens[2]);
     143              11 :                 OGRFieldType eType = OFTString;
     144              11 :                 if (EQUAL(papszTokens[2], "number"))
     145               3 :                     eType = OFTReal;
     146               8 :                 else if (EQUAL(papszTokens[2], "datetime"))
     147               0 :                     eType = OFTDateTime;
     148                 : 
     149              11 :                 if (EQUAL(papszTokens[2], "location") && osGeomColumnName.size() == 0)
     150                 :                 {
     151               3 :                     if (iGeometryField < 0)
     152               3 :                         iGeometryField = poFeatureDefn->GetFieldCount();
     153                 :                     else
     154                 :                         CPLDebug("GFT", "Multiple geometry fields detected. "
     155               0 :                                          "Only first encountered one is handled");
     156                 :                 }
     157                 : 
     158              11 :                 CPLString osLaunderedColName(LaunderColName(papszTokens[1]));
     159              11 :                 OGRFieldDefn oFieldDefn(osLaunderedColName, eType);
     160              11 :                 poFeatureDefn->AddFieldDefn(&oFieldDefn);
     161                 :             }
     162              11 :             CSLDestroy(papszTokens);
     163                 :         }
     164                 : 
     165               4 :         CPLHTTPDestroyResult(psResult);
     166                 :     }
     167                 :     else
     168                 :     {
     169                 :         /* http://code.google.com/intl/fr/apis/fusiontables/docs/developers_guide.html#Exploring states */
     170                 :         /* that DESCRIBE should work on public tables without authentication, but it is not true... */
     171               1 :         CPLString osSQL("SELECT * FROM ");
     172               1 :         osSQL += osTableId;
     173               1 :         osSQL += " OFFSET 0 LIMIT 1";
     174                 : 
     175               1 :         CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
     176                 : 
     177               1 :         if (psResult == NULL)
     178               0 :             return FALSE;
     179                 : 
     180               1 :         char* pszLine = (char*) psResult->pabyData;
     181               1 :         if (pszLine == NULL || psResult->pszErrBuf != NULL)
     182                 :         {
     183               0 :             CPLHTTPDestroyResult(psResult);
     184               0 :             return FALSE;
     185                 :         }
     186                 : 
     187               1 :         ParseCSVResponse(pszLine, aosHeaderAndFirstDataLine);
     188               1 :         if (aosHeaderAndFirstDataLine.size() > 0)
     189                 :         {
     190               1 :             char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[0], ',');
     191              31 :             for(int i=0;papszTokens && papszTokens[i];i++)
     192                 :             {
     193              30 :                 CPLString osLaunderedColName(LaunderColName(papszTokens[i]));
     194              30 :                 OGRFieldDefn oFieldDefn(osLaunderedColName, OFTString);
     195              30 :                 poFeatureDefn->AddFieldDefn(&oFieldDefn);
     196                 :             }
     197               1 :             CSLDestroy(papszTokens);
     198                 :         }
     199                 : 
     200               1 :         CPLHTTPDestroyResult(psResult);
     201                 :     }
     202                 :     
     203               5 :     if (osGeomColumnName.size() > 0)
     204                 :     {
     205               0 :         iGeometryField = poFeatureDefn->GetFieldIndex(osGeomColumnName);
     206               0 :         if (iGeometryField < 0)
     207                 :         {
     208                 :             CPLError(CE_Warning, CPLE_AppDefined,
     209               0 :                      "Cannot find column called %s", osGeomColumnName.c_str());
     210                 :         }
     211                 :     }
     212                 : 
     213              46 :     for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
     214                 :     {
     215              41 :         const char* pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     216              42 :         if (EQUAL(pszName, "latitude") || EQUAL(pszName, "lat") ||
     217                 :             EQUAL(pszName, "latdec"))
     218               1 :             iLatitudeField = i;
     219              40 :         else if (EQUAL(pszName, "longitude") || EQUAL(pszName, "lon") ||
     220                 :                  EQUAL(pszName, "londec") || EQUAL(pszName, "long"))
     221               1 :             iLongitudeField = i;
     222                 :     }
     223                 : 
     224               6 :     if (iLatitudeField >= 0 && iLongitudeField >= 0)
     225                 :     {
     226               1 :         if (iGeometryField < 0)
     227               1 :             iGeometryField = iLatitudeField;
     228               1 :         poFeatureDefn->GetFieldDefn(iLatitudeField)->SetType(OFTReal);
     229               1 :         poFeatureDefn->GetFieldDefn(iLongitudeField)->SetType(OFTReal);
     230               1 :         poFeatureDefn->SetGeomType( wkbPoint );
     231                 :     }
     232               4 :     else if (iGeometryField < 0 && osGeomColumnName.size() == 0)
     233                 :     {
     234               1 :         iLatitudeField = iLongitudeField = -1;
     235                 : 
     236                 :         /* In the unauthentified case, we try to parse the first record to */
     237                 :         /* autodetect the geometry field */
     238               1 :         OGRwkbGeometryType eType = wkbUnknown;
     239               1 :         if (aosHeaderAndFirstDataLine.size() == 2)
     240                 :         {
     241               0 :             char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[1], ',');
     242               0 :             if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
     243                 :             {
     244               0 :                 for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
     245                 :                 {
     246               0 :                     const char* pszVal = papszTokens[i];
     247               0 :                     if (pszVal != NULL &&
     248                 :                         (strncmp(pszVal, "<Point>", 7) == 0 ||
     249                 :                          strncmp(pszVal, "<LineString>", 12) == 0 ||
     250                 :                          strncmp(pszVal, "<Polygon>", 9) == 0 ||
     251                 :                          strncmp(pszVal, "<MultiGeometry>", 15) == 0))
     252                 :                     {
     253               0 :                         if (iGeometryField < 0)
     254                 :                         {
     255               0 :                             iGeometryField = i;
     256                 :                         }
     257                 :                         else
     258                 :                         {
     259                 :                             CPLDebug("GFT", "Multiple geometry fields detected. "
     260               0 :                                      "Only first encountered one is handled");
     261                 :                         }
     262                 :                     }
     263               0 :                     else if (pszVal)
     264                 :                     {
     265                 :                         /* http://www.google.com/fusiontables/DataSource?dsrcid=423292 */
     266               0 :                         char** papszTokens2 = CSLTokenizeString2(pszVal, " ,", 0);
     267               0 :                         if (CSLCount(papszTokens2) == 2 &&
     268               0 :                             CPLGetValueType(papszTokens2[0]) == CPL_VALUE_REAL &&
     269               0 :                             CPLGetValueType(papszTokens2[1]) == CPL_VALUE_REAL &&
     270               0 :                             fabs(CPLAtof(papszTokens2[0])) <= 90 &&
     271               0 :                             fabs(CPLAtof(papszTokens2[1])) <= 180 )
     272                 :                         {
     273               0 :                             if (iGeometryField < 0)
     274                 :                             {
     275               0 :                                 iGeometryField = i;
     276               0 :                                 eType = wkbPoint;
     277                 :                             }
     278                 :                             else
     279                 :                             {
     280                 :                                 CPLDebug("GFT", "Multiple geometry fields detected. "
     281               0 :                                          "Only first encountered one is handled");
     282                 :                             }
     283                 :                         }
     284               0 :                         CSLDestroy(papszTokens2);
     285                 :                     }
     286                 :                 }
     287                 :             }
     288               0 :             CSLDestroy(papszTokens);
     289                 :         }
     290                 :         
     291               1 :         if (iGeometryField < 0)
     292               1 :             poFeatureDefn->SetGeomType( wkbNone );
     293                 :         else
     294               0 :             poFeatureDefn->SetGeomType( eType );
     295                 :     }
     296                 : 
     297               5 :     return TRUE;
     298                 : }
     299                 : 
     300                 : /************************************************************************/
     301                 : /*                         EscapeAndQuote()                             */
     302                 : /************************************************************************/
     303                 : 
     304              63 : static CPLString EscapeAndQuote(const char* pszStr)
     305                 : {
     306                 :     char ch;
     307              63 :     CPLString osRes("'");
     308             431 :     while((ch = *pszStr) != 0)
     309                 :     {
     310             305 :         if (ch == '\'')
     311               3 :             osRes += "\\\'";
     312                 :         else
     313             302 :             osRes += ch;
     314             305 :         pszStr ++;
     315                 :     }
     316              63 :     osRes += "'";
     317               0 :     return osRes;
     318                 : }
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                           FetchNextRows()                            */
     322                 : /************************************************************************/
     323                 : 
     324               4 : int OGRGFTTableLayer::FetchNextRows()
     325                 : {
     326               4 :     aosRows.resize(0);
     327                 : 
     328               4 :     CPLString osSQL("SELECT ROWID");
     329              15 :     for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
     330                 :     {
     331              11 :         osSQL += ",";
     332                 : 
     333              11 :         if (i < (int)aosColumnInternalName.size())
     334               9 :             osSQL += aosColumnInternalName[i];
     335                 :         else
     336                 :         {
     337                 :             const char* pszFieldName =
     338               2 :                 poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     339               2 :             osSQL += EscapeAndQuote(pszFieldName);
     340                 :         }
     341                 :     }
     342               4 :     if (bHiddenGeometryField)
     343                 :     {
     344               1 :         osSQL += ",";
     345               1 :         osSQL += EscapeAndQuote(GetGeometryColumn());
     346                 :     }
     347               4 :     osSQL += " FROM ";
     348               4 :     osSQL += osTableId;
     349               4 :     if (osWHERE.size())
     350                 :     {
     351               0 :         osSQL += " ";
     352               0 :         osSQL += osWHERE;
     353                 :     }
     354                 : 
     355               4 :     int nFeaturesToFetch = GetFeaturesToFetch();
     356               4 :     if (nFeaturesToFetch > 0)
     357               4 :         osSQL += CPLSPrintf(" OFFSET %d LIMIT %d", nOffset, nFeaturesToFetch);
     358                 : 
     359               4 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     360               4 :     CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
     361               4 :     CPLPopErrorHandler();
     362                 : 
     363               4 :     if (psResult == NULL)
     364                 :     {
     365               0 :         bEOF = TRUE;
     366               0 :         return FALSE;
     367                 :     }
     368                 : 
     369               4 :     char* pszLine = (char*) psResult->pabyData;
     370               4 :     if (pszLine == NULL || psResult->pszErrBuf != NULL)
     371                 :     {
     372               0 :         CPLDebug("GFT", "Error : %s", pszLine ? pszLine : psResult->pszErrBuf);
     373               0 :         CPLHTTPDestroyResult(psResult);
     374               0 :         bEOF = TRUE;
     375               0 :         return FALSE;
     376                 :     }
     377                 : 
     378               4 :     ParseCSVResponse(pszLine, aosRows);
     379                 : 
     380               4 :     if (aosRows.size() > 0)
     381               4 :         aosRows.erase(aosRows.begin());
     382                 : 
     383               4 :     if (nFeaturesToFetch > 0)
     384               4 :         bEOF = (int)aosRows.size() < GetFeaturesToFetch();
     385                 :     else
     386               0 :         bEOF = TRUE;
     387                 : 
     388               4 :     CPLHTTPDestroyResult(psResult);
     389                 : 
     390               4 :     return TRUE;
     391                 : }
     392                 : /************************************************************************/
     393                 : /*                            GetFeature()                              */
     394                 : /************************************************************************/
     395                 : 
     396               1 : OGRFeature * OGRGFTTableLayer::GetFeature( long nFID )
     397                 : {
     398               1 :     GetLayerDefn();
     399                 : 
     400               1 :     CPLString osSQL("SELECT ROWID");
     401               3 :     for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
     402                 :     {
     403               2 :         osSQL += ",";
     404                 : 
     405                 :         const char* pszFieldName =
     406               2 :             poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     407               2 :         osSQL += EscapeAndQuote(pszFieldName);
     408                 :     }
     409               1 :     if (bHiddenGeometryField)
     410                 :     {
     411               1 :         osSQL += ",";
     412               1 :         osSQL += EscapeAndQuote(GetGeometryColumn());
     413                 :     }
     414               1 :     osSQL += " FROM ";
     415               1 :     osSQL += osTableId;
     416               1 :     osSQL += CPLSPrintf(" WHERE ROWID='%ld'", nFID);
     417                 : 
     418               1 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     419               1 :     CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
     420               1 :     CPLPopErrorHandler();
     421                 : 
     422               1 :     if (psResult == NULL)
     423               0 :         return NULL;
     424                 : 
     425               1 :     char* pszLine = (char*) psResult->pabyData;
     426               1 :     if (pszLine == NULL || psResult->pszErrBuf != NULL)
     427                 :     {
     428               0 :         CPLHTTPDestroyResult(psResult);
     429               0 :         return NULL;
     430                 :     }
     431                 : 
     432                 :     /* skip header line */
     433               1 :     pszLine = OGRGFTGotoNextLine(pszLine);
     434               1 :     if (pszLine == NULL || pszLine[0] == 0)
     435                 :     {
     436               0 :         CPLHTTPDestroyResult(psResult);
     437               0 :         return NULL;
     438                 :     }
     439                 : 
     440               1 :     int nLen = (int)strlen(pszLine);
     441               1 :     if (nLen > 0 && pszLine[nLen-1] == '\n')
     442               1 :         pszLine[nLen-1] = '\0';
     443                 : 
     444               1 :     OGRFeature* poFeature = BuildFeatureFromSQL(pszLine);
     445                 : 
     446               1 :     CPLHTTPDestroyResult(psResult);
     447                 : 
     448               1 :     return poFeature;
     449                 : }
     450                 : 
     451                 : /************************************************************************/
     452                 : /*                           GetLayerDefn()                             */
     453                 : /************************************************************************/
     454                 : 
     455              61 : OGRFeatureDefn * OGRGFTTableLayer::GetLayerDefn()
     456                 : {
     457              61 :     if (poFeatureDefn == NULL)
     458                 :     {
     459              11 :         if (osTableId.size() == 0)
     460               3 :             return NULL;
     461               8 :         FetchDescribe();
     462                 :     }
     463                 : 
     464              58 :     return poFeatureDefn;
     465                 : }
     466                 : 
     467                 : /************************************************************************/
     468                 : /*                          GetFeatureCount()                           */
     469                 : /************************************************************************/
     470                 : 
     471               5 : int OGRGFTTableLayer::GetFeatureCount(int bForce)
     472                 : {
     473               5 :     GetLayerDefn();
     474                 : 
     475               5 :     CPLString osSQL("SELECT COUNT() FROM ");
     476               5 :     osSQL += osTableId;
     477               5 :     if (osWHERE.size())
     478                 :     {
     479               1 :         osSQL += " ";
     480               1 :         osSQL += osWHERE;
     481                 :     }
     482                 : 
     483               5 :     CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
     484                 : 
     485               5 :     if (psResult == NULL)
     486               0 :         return 0;
     487                 : 
     488               5 :     char* pszLine = (char*) psResult->pabyData;
     489               5 :     if (pszLine == NULL ||
     490                 :         strncmp(pszLine, "count()", 7) != 0 ||
     491                 :         psResult->pszErrBuf != NULL)
     492                 :     {
     493               0 :         CPLError(CE_Failure, CPLE_AppDefined, "GetFeatureCount() failed");
     494               0 :         CPLHTTPDestroyResult(psResult);
     495               0 :         return 0;
     496                 :     }
     497                 : 
     498               5 :     pszLine = OGRGFTGotoNextLine(pszLine);
     499               5 :     if (pszLine == NULL)
     500                 :     {
     501               0 :         CPLError(CE_Failure, CPLE_AppDefined, "GetFeatureCount() failed");
     502               0 :         CPLHTTPDestroyResult(psResult);
     503               0 :         return 0;
     504                 :     }
     505                 : 
     506               5 :     char* pszNextLine = OGRGFTGotoNextLine(pszLine);
     507               5 :     if (pszNextLine)
     508               5 :         pszNextLine[-1] = 0;
     509                 : 
     510               5 :     int nFeatureCount = atoi(pszLine);
     511                 : 
     512               5 :     CPLHTTPDestroyResult(psResult);
     513                 : 
     514               5 :     return nFeatureCount;
     515                 : }
     516                 : 
     517                 : /************************************************************************/
     518                 : /*                            CreateField()                             */
     519                 : /************************************************************************/
     520                 : 
     521               9 : OGRErr OGRGFTTableLayer::CreateField( OGRFieldDefn *poField,
     522                 :                                  int bApproxOK )
     523                 : {
     524                 : 
     525               9 :     if (!poDS->IsReadWrite())
     526                 :     {
     527                 :         CPLError(CE_Failure, CPLE_AppDefined,
     528               0 :                  "Operation not available in read-only mode");
     529               0 :         return OGRERR_FAILURE;
     530                 :     }
     531                 : 
     532               9 :     if (osTableId.size() != 0)
     533                 :     {
     534                 :         CPLError(CE_Failure, CPLE_NotSupported,
     535               0 :                  "Cannot add field to already created table");
     536               0 :         return OGRERR_FAILURE;
     537                 :     }
     538                 : 
     539               9 :     if (poDS->GetAuth().size() == 0)
     540                 :     {
     541                 :         CPLError(CE_Failure, CPLE_AppDefined,
     542               0 :                  "Operation not available in unauthenticated mode");
     543               0 :         return OGRERR_FAILURE;
     544                 :     }
     545                 : 
     546               9 :     if (poFeatureDefn == NULL)
     547                 :     {
     548               4 :         poFeatureDefn = new OGRFeatureDefn( osTableName );
     549               4 :         poFeatureDefn->Reference();
     550                 :     }
     551                 : 
     552               9 :     poFeatureDefn->AddFieldDefn(poField);
     553                 : 
     554               9 :     return OGRERR_NONE;
     555                 : }
     556                 : 
     557                 : /************************************************************************/
     558                 : /*                       CreateTableIfNecessary()                       */
     559                 : /************************************************************************/
     560                 : 
     561             101 : void OGRGFTTableLayer::CreateTableIfNecessary()
     562                 : {
     563             101 :     if (bHasTriedCreateTable || osTableId.size() != 0)
     564              97 :         return;
     565                 : 
     566               4 :     bHasTriedCreateTable = TRUE;
     567                 : 
     568               4 :     CPLString osSQL("CREATE TABLE '");
     569               4 :     osSQL += osTableName;
     570               4 :     osSQL += "' (";
     571                 : 
     572                 :     int i;
     573                 : 
     574               4 :     if (poFeatureDefn == NULL)
     575                 :     {
     576                 :         /* In case CreateField() hasn't yet been called */
     577               0 :         poFeatureDefn = new OGRFeatureDefn( osTableName );
     578               0 :         poFeatureDefn->Reference();
     579                 :     }
     580                 : 
     581                 :     /* If there are longitude and latitude fields, use the latitude */
     582                 :     /* field as the LOCATION field */
     583              13 :     for(i=0;i<poFeatureDefn->GetFieldCount();i++)
     584                 :     {
     585               9 :         const char* pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     586               9 :         if (EQUAL(pszName, "latitude") || EQUAL(pszName, "lat") ||
     587                 :             EQUAL(pszName, "latdec"))
     588               0 :             iLatitudeField = i;
     589               9 :         else if (EQUAL(pszName, "longitude") || EQUAL(pszName, "lon") ||
     590                 :                  EQUAL(pszName, "londec") || EQUAL(pszName, "long"))
     591               0 :             iLongitudeField = i;
     592                 :     }
     593                 : 
     594               4 :     if (iLatitudeField >= 0 && iLongitudeField >= 0)
     595                 :     {
     596               0 :         iGeometryField = iLatitudeField;
     597               0 :         poFeatureDefn->SetGeomType( wkbPoint );
     598                 :     }
     599                 :     /* If no longitude/latitude field exist, let's look at a column */
     600                 :     /* named 'geometry' and use it as the LOCATION column if the layer */
     601                 :     /* hasn't been created with a none geometry type */
     602               7 :     else if (iGeometryField < 0 && eGTypeForCreation != wkbNone)
     603                 :     {
     604               3 :         iGeometryField = poFeatureDefn->GetFieldIndex(GetDefaultGeometryColumnName());
     605               3 :         poFeatureDefn->SetGeomType( eGTypeForCreation );
     606                 :     }
     607                 :     /* The user doesn't want geometries, so don't create one */
     608               1 :     else if (eGTypeForCreation == wkbNone)
     609                 :     {
     610               1 :         poFeatureDefn->SetGeomType( eGTypeForCreation );
     611                 :     }
     612                 : 
     613              13 :     for(i=0;i<poFeatureDefn->GetFieldCount();i++)
     614                 :     {
     615               9 :         if (i > 0)
     616               5 :             osSQL += ", ";
     617                 : 
     618                 :         const char* pszFieldName =
     619               9 :             poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     620               9 :         osSQL += EscapeAndQuote(pszFieldName);
     621               9 :         osSQL += ": ";
     622                 : 
     623               9 :         if (iGeometryField == i)
     624                 :         {
     625               1 :             osSQL += "LOCATION";
     626                 :         }
     627                 :         else
     628                 :         {
     629               8 :             switch(poFeatureDefn->GetFieldDefn(i)->GetType())
     630                 :             {
     631                 :                 case OFTInteger:
     632                 :                 case OFTReal:
     633               3 :                     osSQL += "NUMBER";
     634               3 :                     break;
     635                 :                 default:
     636               5 :                     osSQL += "STRING";
     637                 :             }
     638                 :         }
     639                 :     }
     640                 : 
     641                 :     /* If there's not yet a geometry field and the user didn't forbid */
     642                 :     /* the creation of one, then let's add it to the CREATE TABLE, but */
     643                 :     /* DO NOT add it to the feature defn as a feature might already have */
     644                 :     /* been created with it, so it is not safe to alter it at that point. */
     645                 :     /* So we set the bHiddenGeometryField flag to be able to fetch/set this */
     646                 :     /* column but not try to get/set a related feature field */
     647               4 :     if (iGeometryField < 0 && eGTypeForCreation != wkbNone)
     648                 :     {
     649               2 :         if (i > 0)
     650               2 :             osSQL += ", ";
     651               2 :         osSQL += EscapeAndQuote(GetDefaultGeometryColumnName());
     652               2 :         osSQL += ": LOCATION";
     653                 : 
     654               2 :         iGeometryField = poFeatureDefn->GetFieldCount();
     655               2 :         bHiddenGeometryField = TRUE;
     656                 :     }
     657               4 :     osSQL += ")";
     658                 : 
     659               4 :     CPLHTTPResult * psResult = poDS->RunSQL(osSQL);
     660               4 :     if (psResult == NULL)
     661                 :     {
     662               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
     663                 :         return;
     664                 :     }
     665                 : 
     666               4 :     char* pszLine = (char*) psResult->pabyData;
     667               4 :     if (pszLine == NULL ||
     668                 :         strncmp(pszLine, "tableid", 7) != 0 ||
     669                 :         psResult->pszErrBuf != NULL)
     670                 :     {
     671               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
     672               0 :         CPLHTTPDestroyResult(psResult);
     673                 :         return;
     674                 :     }
     675                 : 
     676               4 :     pszLine = OGRGFTGotoNextLine(pszLine);
     677               4 :     if (pszLine == NULL)
     678                 :     {
     679               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Table creation failed");
     680               0 :         CPLHTTPDestroyResult(psResult);
     681                 :         return;
     682                 :     }
     683                 : 
     684               4 :     char* pszNextLine = OGRGFTGotoNextLine(pszLine);
     685               4 :     if (pszNextLine)
     686               4 :         pszNextLine[-1] = 0;
     687                 : 
     688               4 :     osTableId = pszLine;
     689               4 :     CPLDebug("GFT", "Table %s --> id = %s", osTableName.c_str(), osTableId.c_str());
     690                 : 
     691               4 :     CPLHTTPDestroyResult(psResult);
     692                 : }
     693                 : 
     694                 : /************************************************************************/
     695                 : /*                           CreateFeature()                            */
     696                 : /************************************************************************/
     697                 : 
     698              10 : OGRErr OGRGFTTableLayer::CreateFeature( OGRFeature *poFeature )
     699                 : 
     700                 : {
     701              10 :     if (!poDS->IsReadWrite())
     702                 :     {
     703                 :         CPLError(CE_Failure, CPLE_AppDefined,
     704               0 :                  "Operation not available in read-only mode");
     705               0 :         return OGRERR_FAILURE;
     706                 :     }
     707                 : 
     708              10 :     if (osTableId.size() == 0)
     709                 :     {
     710               1 :         CreateTableIfNecessary();
     711               1 :         if (osTableId.size() == 0)
     712                 :         {
     713                 :             CPLError(CE_Failure, CPLE_NotSupported,
     714               0 :                     "Cannot add feature to non-created table");
     715               0 :             return OGRERR_FAILURE;
     716                 :         }
     717                 :     }
     718                 : 
     719              10 :     if (poDS->GetAuth().size() == 0)
     720                 :     {
     721                 :         CPLError(CE_Failure, CPLE_AppDefined,
     722               0 :                  "Operation not available in unauthenticated mode");
     723               0 :         return OGRERR_FAILURE;
     724                 :     }
     725                 : 
     726              10 :     CPLString      osCommand;
     727                 : 
     728              10 :     osCommand += "INSERT INTO ";
     729              10 :     osCommand += osTableId;
     730              10 :     osCommand += " (";
     731                 : 
     732                 :     int iField;
     733              10 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     734              33 :     for(iField = 0; iField < nFieldCount; iField++)
     735                 :     {
     736              23 :         if (iField > 0)
     737              13 :             osCommand += ", ";
     738                 : 
     739                 :         const char* pszFieldName =
     740              23 :             poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
     741              23 :         osCommand += EscapeAndQuote(pszFieldName);
     742                 :     }
     743              10 :     if (bHiddenGeometryField)
     744                 :     {
     745               4 :         if (iField > 0)
     746               4 :             osCommand += ", ";
     747               4 :         osCommand += EscapeAndQuote(GetGeometryColumn());
     748                 :     }
     749              10 :     osCommand += ") VALUES (";
     750              37 :     for(iField = 0; iField < nFieldCount + bHiddenGeometryField; iField++)
     751                 :     {
     752              27 :         if (iField > 0)
     753              17 :             osCommand += ", ";
     754                 : 
     755              27 :         OGRGeometry* poGeom = poFeature->GetGeometryRef();
     756                 :         /* If there's a geometry, let's use it in priority over the textual */
     757                 :         /* content of the field. */
     758              27 :         if (iGeometryField != iLatitudeField && iField == iGeometryField &&
     759                 :             (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSet( iField )))
     760                 :         {
     761               7 :             if (poGeom == NULL)
     762               0 :                 osCommand += "''";
     763                 :             else
     764                 :             {
     765                 :                 char* pszKML;
     766               7 :                 if (poGeom->getSpatialReference() != NULL &&
     767                 :                     !poGeom->getSpatialReference()->IsSame(poSRS))
     768                 :                 {
     769               0 :                     OGRGeometry* poGeom4326 = poGeom->clone();
     770               0 :                     poGeom4326->transformTo(poSRS);
     771               0 :                     pszKML = poGeom4326->exportToKML();
     772               0 :                     delete poGeom4326;
     773                 :                 }
     774                 :                 else
     775                 :                 {
     776               7 :                     pszKML = poGeom->exportToKML();
     777                 :                 }
     778               7 :                 osCommand += "'";
     779               7 :                 osCommand += pszKML;
     780               7 :                 osCommand += "'";
     781               7 :                 CPLFree(pszKML);
     782                 :             }
     783               7 :             continue;
     784                 :         }
     785                 : 
     786              20 :         if( !poFeature->IsFieldSet( iField ) )
     787                 :         {
     788               0 :             osCommand += "''";
     789                 :         }
     790                 :         else
     791                 :         {
     792              20 :             OGRFieldType eType = poFeatureDefn->GetFieldDefn(iField)->GetType();
     793              33 :             if (eType != OFTInteger && eType != OFTReal)
     794                 :             {
     795              13 :                 CPLString osTmp;
     796              13 :                 const char* pszVal = poFeature->GetFieldAsString(iField);
     797                 : 
     798              13 :                 if (!CPLIsUTF8(pszVal, -1))
     799                 :                 {
     800                 :                     static int bFirstTime = TRUE;
     801               0 :                     if (bFirstTime)
     802                 :                     {
     803               0 :                         bFirstTime = FALSE;
     804                 :                         CPLError(CE_Warning, CPLE_AppDefined,
     805                 :                                 "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
     806               0 :                                 "This warning won't be issued anymore", pszVal);
     807                 :                     }
     808                 :                     else
     809                 :                     {
     810                 :                         CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
     811               0 :                                 pszVal);
     812                 :                     }
     813               0 :                     char* pszEscaped = CPLForceToASCII(pszVal, -1, '?');
     814               0 :                     osTmp = pszEscaped;
     815               0 :                     CPLFree(pszEscaped);
     816               0 :                     pszVal = osTmp.c_str();
     817                 :                 }
     818                 : 
     819              13 :                 osCommand += EscapeAndQuote(pszVal);
     820                 :             }
     821                 :             else
     822               7 :                 osCommand += poFeature->GetFieldAsString(iField);
     823                 :         }
     824                 :     }
     825                 : 
     826              10 :     osCommand += ")";
     827                 : 
     828                 :     //CPLDebug("GFT", "%s",  osCommand.c_str());
     829                 : 
     830              10 :     if (bInTransaction)
     831                 :     {
     832               9 :         nFeaturesInTransaction ++;
     833               9 :         if (nFeaturesInTransaction > 1)
     834               6 :             osTransaction += "; ";
     835               9 :         osTransaction += osCommand;
     836               9 :         return OGRERR_NONE;
     837                 :     }
     838                 : 
     839               1 :     CPLHTTPResult * psResult = poDS->RunSQL(osCommand);
     840               1 :     if (psResult == NULL)
     841                 :     {
     842               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
     843               0 :         return OGRERR_FAILURE;
     844                 :     }
     845                 : 
     846               1 :     char* pszLine = (char*) psResult->pabyData;
     847               1 :     if (pszLine == NULL ||
     848                 :         strncmp(pszLine, "rowid", 5) != 0 ||
     849                 :         psResult->pszErrBuf != NULL)
     850                 :     {
     851               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
     852               0 :         CPLHTTPDestroyResult(psResult);
     853               0 :         return OGRERR_FAILURE;
     854                 :     }
     855                 : 
     856               1 :     pszLine = OGRGFTGotoNextLine(pszLine);
     857               1 :     if (pszLine == NULL)
     858                 :     {
     859               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature creation failed");
     860               0 :         CPLHTTPDestroyResult(psResult);
     861               0 :         return OGRERR_FAILURE;
     862                 :     }
     863                 : 
     864               1 :     char* pszNextLine = OGRGFTGotoNextLine(pszLine);
     865               1 :     if (pszNextLine)
     866               1 :         pszNextLine[-1] = 0;
     867                 : 
     868               1 :     CPLDebug("GFT", "Feature id = %s",  pszLine);
     869                 : 
     870               1 :     int nFID = atoi(pszLine);
     871               1 :     if (strcmp(CPLSPrintf("%d", nFID), pszLine) == 0)
     872               1 :         poFeature->SetFID(nFID);
     873                 : 
     874               1 :     CPLHTTPDestroyResult(psResult);
     875                 : 
     876               1 :     return OGRERR_NONE;
     877                 : }
     878                 : 
     879                 : /************************************************************************/
     880                 : /*                           SetFeature()                               */
     881                 : /************************************************************************/
     882                 : 
     883               1 : OGRErr      OGRGFTTableLayer::SetFeature( OGRFeature *poFeature )
     884                 : {
     885               1 :     GetLayerDefn();
     886                 : 
     887               1 :     if (!poDS->IsReadWrite())
     888                 :     {
     889                 :         CPLError(CE_Failure, CPLE_AppDefined,
     890               0 :                  "Operation not available in read-only mode");
     891               0 :         return OGRERR_FAILURE;
     892                 :     }
     893                 : 
     894               1 :     if (osTableId.size() == 0)
     895                 :     {
     896                 :         CPLError(CE_Failure, CPLE_NotSupported,
     897               0 :                 "Cannot set feature to non-created table");
     898               0 :         return OGRERR_FAILURE;
     899                 :     }
     900                 : 
     901               1 :     if (poDS->GetAuth().size() == 0)
     902                 :     {
     903                 :         CPLError(CE_Failure, CPLE_AppDefined,
     904               0 :                  "Operation not available in unauthenticated mode");
     905               0 :         return OGRERR_FAILURE;
     906                 :     }
     907                 : 
     908               1 :     if (poFeature->GetFID() == OGRNullFID)
     909                 :     {
     910                 :         CPLError( CE_Failure, CPLE_AppDefined,
     911               0 :                   "FID required on features given to SetFeature()." );
     912               0 :         return OGRERR_FAILURE;
     913                 :     }
     914                 : 
     915               1 :     CPLString      osCommand;
     916                 : 
     917               1 :     osCommand += "UPDATE ";
     918               1 :     osCommand += osTableId;
     919               1 :     osCommand += " SET ";
     920                 : 
     921                 :     int iField;
     922               1 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     923               4 :     for(iField = 0; iField < nFieldCount + bHiddenGeometryField; iField++)
     924                 :     {
     925               3 :         if (iField > 0)
     926               2 :             osCommand += ", ";
     927                 : 
     928               3 :         if (iField == nFieldCount)
     929                 :         {
     930               1 :             osCommand += EscapeAndQuote(GetGeometryColumn());
     931                 :         }
     932                 :         else
     933                 :         {
     934                 :             const char* pszFieldName =
     935               2 :                 poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
     936               2 :             osCommand += EscapeAndQuote(pszFieldName);
     937                 :         }
     938                 : 
     939               3 :         osCommand += " = ";
     940                 : 
     941               3 :         OGRGeometry* poGeom = poFeature->GetGeometryRef();
     942               3 :         if (iGeometryField != iLatitudeField && iField == iGeometryField &&
     943                 :             (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSet( iField )))
     944                 :         {
     945               1 :             if (poGeom == NULL)
     946               0 :                 osCommand += "''";
     947                 :             else
     948                 :             {
     949                 :                 char* pszKML;
     950               1 :                 if (poGeom->getSpatialReference() != NULL &&
     951                 :                     !poGeom->getSpatialReference()->IsSame(poSRS))
     952                 :                 {
     953               0 :                     OGRGeometry* poGeom4326 = poGeom->clone();
     954               0 :                     poGeom4326->transformTo(poSRS);
     955               0 :                     pszKML = poGeom4326->exportToKML();
     956               0 :                     delete poGeom4326;
     957                 :                 }
     958                 :                 else
     959                 :                 {
     960               1 :                     pszKML = poGeom->exportToKML();
     961                 :                 }
     962               1 :                 osCommand += "'";
     963               1 :                 osCommand += pszKML;
     964               1 :                 osCommand += "'";
     965               1 :                 CPLFree(pszKML);
     966                 :             }
     967               1 :             continue;
     968                 :         }
     969                 : 
     970               2 :         if( !poFeature->IsFieldSet( iField ) )
     971                 :         {
     972               0 :             osCommand += "''";
     973                 :         }
     974                 :         else
     975                 :         {
     976               2 :             OGRFieldType eType = poFeatureDefn->GetFieldDefn(iField)->GetType();
     977               3 :             if (eType != OFTInteger && eType != OFTReal)
     978                 :             {
     979               1 :                 CPLString osTmp;
     980               1 :                 const char* pszVal = poFeature->GetFieldAsString(iField);
     981                 : 
     982               1 :                 if (!CPLIsUTF8(pszVal, -1))
     983                 :                 {
     984                 :                     static int bFirstTime = TRUE;
     985               0 :                     if (bFirstTime)
     986                 :                     {
     987               0 :                         bFirstTime = FALSE;
     988                 :                         CPLError(CE_Warning, CPLE_AppDefined,
     989                 :                                 "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
     990               0 :                                 "This warning won't be issued anymore", pszVal);
     991                 :                     }
     992                 :                     else
     993                 :                     {
     994                 :                         CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
     995               0 :                                 pszVal);
     996                 :                     }
     997               0 :                     char* pszEscaped = CPLForceToASCII(pszVal, -1, '?');
     998               0 :                     osTmp = pszEscaped;
     999               0 :                     CPLFree(pszEscaped);
    1000               0 :                     pszVal = osTmp.c_str();
    1001                 :                 }
    1002                 : 
    1003               1 :                 osCommand += EscapeAndQuote(pszVal);
    1004                 :             }
    1005                 :             else
    1006               1 :                 osCommand += poFeature->GetFieldAsString(iField);
    1007                 :         }
    1008                 :     }
    1009                 : 
    1010               1 :     osCommand += " WHERE ROWID = '";
    1011               1 :     osCommand += CPLSPrintf("%ld", poFeature->GetFID());
    1012               1 :     osCommand += "'";
    1013                 : 
    1014                 :     //CPLDebug("GFT", "%s",  osCommand.c_str());
    1015                 : 
    1016               1 :     CPLHTTPResult * psResult = poDS->RunSQL(osCommand);
    1017               1 :     if (psResult == NULL)
    1018                 :     {
    1019               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature update failed");
    1020               0 :         return OGRERR_FAILURE;
    1021                 :     }
    1022                 : 
    1023               1 :     char* pszLine = (char*) psResult->pabyData;
    1024               1 :     if (pszLine == NULL ||
    1025                 :         strncmp(pszLine, "OK", 2) != 0 ||
    1026                 :         psResult->pszErrBuf != NULL)
    1027                 :     {
    1028               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature update failed");
    1029               0 :         CPLHTTPDestroyResult(psResult);
    1030               0 :         return OGRERR_FAILURE;
    1031                 :     }
    1032                 : 
    1033               1 :     CPLHTTPDestroyResult(psResult);
    1034                 : 
    1035               1 :     return OGRERR_NONE;
    1036                 : }
    1037                 : 
    1038                 : /************************************************************************/
    1039                 : /*                          DeleteFeature()                             */
    1040                 : /************************************************************************/
    1041                 : 
    1042               1 : OGRErr OGRGFTTableLayer::DeleteFeature( long nFID )
    1043                 : {
    1044               1 :     GetLayerDefn();
    1045                 : 
    1046               1 :     if (!poDS->IsReadWrite())
    1047                 :     {
    1048                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1049               0 :                  "Operation not available in read-only mode");
    1050               0 :         return OGRERR_FAILURE;
    1051                 :     }
    1052                 : 
    1053               1 :     if (osTableId.size() == 0)
    1054                 :     {
    1055                 :         CPLError(CE_Failure, CPLE_NotSupported,
    1056               0 :                 "Cannot delete feature in non-created table");
    1057               0 :         return OGRERR_FAILURE;
    1058                 :     }
    1059                 : 
    1060               1 :     if (poDS->GetAuth().size() == 0)
    1061                 :     {
    1062                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1063               0 :                  "Operation not available in unauthenticated mode");
    1064               0 :         return OGRERR_FAILURE;
    1065                 :     }
    1066                 : 
    1067               1 :     CPLString      osCommand;
    1068                 : 
    1069               1 :     osCommand += "DELETE FROM ";
    1070               1 :     osCommand += osTableId;
    1071               1 :     osCommand += " WHERE ROWID = '";
    1072               1 :     osCommand += CPLSPrintf("%ld", nFID);
    1073               1 :     osCommand += "'";
    1074                 : 
    1075                 :     //CPLDebug("GFT", "%s",  osCommand.c_str());
    1076                 : 
    1077               1 :     CPLHTTPResult * psResult = poDS->RunSQL(osCommand);
    1078               1 :     if (psResult == NULL)
    1079                 :     {
    1080               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature deletion failed");
    1081               0 :         return OGRERR_FAILURE;
    1082                 :     }
    1083                 : 
    1084               1 :     char* pszLine = (char*) psResult->pabyData;
    1085               1 :     if (pszLine == NULL ||
    1086                 :         strncmp(pszLine, "OK", 2) != 0 ||
    1087                 :         psResult->pszErrBuf != NULL)
    1088                 :     {
    1089               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Feature deletion failed");
    1090               0 :         CPLHTTPDestroyResult(psResult);
    1091               0 :         return OGRERR_FAILURE;
    1092                 :     }
    1093                 : 
    1094               1 :     CPLHTTPDestroyResult(psResult);
    1095                 : 
    1096               1 :     return OGRERR_NONE;
    1097                 : }
    1098                 : 
    1099                 : /************************************************************************/
    1100                 : /*                         StartTransaction()                           */
    1101                 : /************************************************************************/
    1102                 : 
    1103               3 : OGRErr OGRGFTTableLayer::StartTransaction()
    1104                 : {
    1105               3 :     GetLayerDefn();
    1106                 : 
    1107               3 :     if (bInTransaction)
    1108                 :     {
    1109               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Already in transaction");
    1110               0 :         return OGRERR_FAILURE;
    1111                 :     }
    1112                 : 
    1113               3 :     if (!poDS->IsReadWrite())
    1114                 :     {
    1115                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1116               0 :                  "Operation not available in read-only mode");
    1117               0 :         return OGRERR_FAILURE;
    1118                 :     }
    1119                 : 
    1120               3 :     if (osTableId.size() == 0)
    1121                 :     {
    1122               3 :         CreateTableIfNecessary();
    1123               3 :         if (osTableId.size() == 0)
    1124                 :         {
    1125                 :             CPLError(CE_Failure, CPLE_NotSupported,
    1126               0 :                     "Cannot add feature to non-created table");
    1127               0 :             return OGRERR_FAILURE;
    1128                 :         }
    1129                 :     }
    1130                 : 
    1131               3 :     if (poDS->GetAuth().size() == 0)
    1132                 :     {
    1133                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1134               0 :                  "Operation not available in unauthenticated mode");
    1135               0 :         return OGRERR_FAILURE;
    1136                 :     }
    1137                 : 
    1138               3 :     bInTransaction = TRUE;
    1139               3 :     osTransaction.resize(0);
    1140               3 :     nFeaturesInTransaction = 0;
    1141                 : 
    1142               3 :     return OGRERR_NONE;
    1143                 : }
    1144                 : 
    1145                 : /************************************************************************/
    1146                 : /*                         CommitTransaction()                          */
    1147                 : /************************************************************************/
    1148                 : 
    1149               3 : OGRErr OGRGFTTableLayer::CommitTransaction()
    1150                 : {
    1151               3 :     GetLayerDefn();
    1152                 : 
    1153               3 :     if (!bInTransaction)
    1154                 :     {
    1155               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
    1156               0 :         return OGRERR_FAILURE;
    1157                 :     }
    1158                 : 
    1159               3 :     bInTransaction = FALSE;
    1160                 : 
    1161               3 :     if (nFeaturesInTransaction > 0)
    1162                 :     {
    1163               3 :         if (nFeaturesInTransaction > 1)
    1164               3 :             osTransaction += ";";
    1165                 : 
    1166               3 :         CPLHTTPResult * psResult = poDS->RunSQL(osTransaction);
    1167               3 :         osTransaction.resize(0);
    1168               3 :         nFeaturesInTransaction = 0;
    1169                 : 
    1170               3 :         if (psResult == NULL)
    1171                 :         {
    1172               0 :             CPLError(CE_Failure, CPLE_AppDefined, "CommitTransaction failed");
    1173               0 :             return OGRERR_FAILURE;
    1174                 :         }
    1175                 : 
    1176               3 :         char* pszLine = (char*) psResult->pabyData;
    1177               3 :         if (pszLine == NULL ||
    1178                 :             strncmp(pszLine, "rowid", 5) != 0 ||
    1179                 :             psResult->pszErrBuf != NULL)
    1180                 :         {
    1181                 :             CPLError(CE_Failure, CPLE_AppDefined, "CommitTransaction failed : %s",
    1182               0 :                      pszLine ? pszLine : psResult->pszErrBuf);
    1183               0 :             CPLHTTPDestroyResult(psResult);
    1184               0 :             return OGRERR_FAILURE;
    1185                 :         }
    1186                 : 
    1187               3 :         pszLine = OGRGFTGotoNextLine(pszLine);
    1188              15 :         while(pszLine && *pszLine != 0)
    1189                 :         {
    1190               9 :             char* pszNextLine = OGRGFTGotoNextLine(pszLine);
    1191               9 :             if (pszNextLine)
    1192               9 :                 pszNextLine[-1] = 0;
    1193                 :             //CPLDebug("GFT", "Feature id = %s",  pszLine);
    1194                 : 
    1195               9 :             pszLine = pszNextLine;
    1196                 :         }
    1197                 : 
    1198               3 :         CPLHTTPDestroyResult(psResult);
    1199                 :     }
    1200                 : 
    1201               3 :     return OGRERR_NONE;
    1202                 : }
    1203                 : 
    1204                 : /************************************************************************/
    1205                 : /*                        RollbackTransaction()                         */
    1206                 : /************************************************************************/
    1207                 : 
    1208               0 : OGRErr OGRGFTTableLayer::RollbackTransaction()
    1209                 : {
    1210               0 :     GetLayerDefn();
    1211                 : 
    1212               0 :     if (!bInTransaction)
    1213                 :     {
    1214               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
    1215               0 :         return OGRERR_FAILURE;
    1216                 :     }
    1217               0 :     bInTransaction = FALSE;
    1218               0 :     nFeaturesInTransaction = 0;
    1219               0 :     osTransaction.resize(0);
    1220               0 :     return OGRERR_NONE;
    1221                 : }
    1222                 : 
    1223                 : /************************************************************************/
    1224                 : /*                         SetAttributeFilter()                         */
    1225                 : /************************************************************************/
    1226                 : 
    1227               1 : OGRErr OGRGFTTableLayer::SetAttributeFilter( const char *pszQuery )
    1228                 : 
    1229                 : {
    1230               1 :     GetLayerDefn();
    1231                 : 
    1232               1 :     if( pszQuery == NULL )
    1233               0 :         osQuery = "";
    1234                 :     else
    1235                 :     {
    1236               1 :         osQuery = PatchSQL(pszQuery);
    1237                 :     }
    1238                 : 
    1239               1 :     BuildWhere();
    1240                 : 
    1241               1 :     ResetReading();
    1242                 : 
    1243               1 :     return OGRERR_NONE;
    1244                 : }
    1245                 : 
    1246                 : 
    1247                 : /************************************************************************/
    1248                 : /*                          SetSpatialFilter()                          */
    1249                 : /************************************************************************/
    1250                 : 
    1251               1 : void OGRGFTTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
    1252                 : 
    1253                 : {
    1254               1 :     GetLayerDefn();
    1255                 : 
    1256               1 :     if( InstallFilter( poGeomIn ) )
    1257                 :     {
    1258               1 :         BuildWhere();
    1259                 : 
    1260               1 :         ResetReading();
    1261                 :     }
    1262               1 : }
    1263                 : 
    1264                 : /************************************************************************/
    1265                 : /*                             BuildWhere()                             */
    1266                 : /*                                                                      */
    1267                 : /*      Build the WHERE statement appropriate to the current set of     */
    1268                 : /*      criteria (spatial and attribute queries).                       */
    1269                 : /************************************************************************/
    1270                 : 
    1271               2 : void OGRGFTTableLayer::BuildWhere()
    1272                 : 
    1273                 : {
    1274               2 :     osWHERE = "";
    1275                 : 
    1276               4 :     if( m_poFilterGeom != NULL && iGeometryField >= 0)
    1277                 :     {
    1278               2 :         OGREnvelope  sEnvelope;
    1279                 : 
    1280               2 :         m_poFilterGeom->getEnvelope( &sEnvelope );
    1281                 : 
    1282               2 :         CPLString osQuotedGeomColumn(EscapeAndQuote(GetGeometryColumn()));
    1283                 : 
    1284                 :         osWHERE.Printf("WHERE ST_INTERSECTS(%s, RECTANGLE(LATLNG(%.12f, %.12f), LATLNG(%.12f, %.12f)))",
    1285                 :                        osQuotedGeomColumn.c_str(),
    1286                 :                        MAX(-90.,sEnvelope.MinY - 1e-11), MAX(-180., sEnvelope.MinX - 1e-11),
    1287               2 :                        MIN(90.,sEnvelope.MaxY + 1e-11), MIN(180.,sEnvelope.MaxX + 1e-11));
    1288                 :     }
    1289                 : 
    1290               2 :     if( strlen(osQuery) > 0 )
    1291                 :     {
    1292               1 :         if( strlen(osWHERE) == 0 )
    1293               0 :             osWHERE = "WHERE ";
    1294                 :         else
    1295               1 :             osWHERE += " AND ";
    1296               1 :         osWHERE += osQuery;
    1297                 :     }
    1298               2 : }
    1299                 : 
    1300                 : /************************************************************************/
    1301                 : /*                          SetGeometryType()                           */
    1302                 : /************************************************************************/
    1303                 : 
    1304               4 : void OGRGFTTableLayer::SetGeometryType(OGRwkbGeometryType eGType)
    1305                 : {
    1306               4 :     eGTypeForCreation = eGType;
    1307               4 : }

Generated by: LCOV version 1.7