LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vfk - vfkreadersqlite.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 170 150 88.2 %
Date: 2012-04-28 Functions: 13 10 76.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: vfkreadersqlite.cpp 24217 2012-04-11 14:25:09Z martinl $
       3                 :  *
       4                 :  * Project:  VFK Reader (SQLite)
       5                 :  * Purpose:  Implements VFKReaderSQLite class.
       6                 :  * Author:   Martin Landa, landa.martin gmail.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2012, Martin Landa <landa.martin gmail.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person
      12                 :  * obtaining a copy of this software and associated documentation
      13                 :  * files (the "Software"), to deal in the Software without
      14                 :  * restriction, including without limitation the rights to use, copy,
      15                 :  * modify, merge, publish, distribute, sublicense, and/or sell copies
      16                 :  * of the Software, and to permit persons to whom the Software is
      17                 :  * furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be
      20                 :  * included in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      23                 :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      24                 :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      25                 :  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
      26                 :  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
      27                 :  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
      28                 :  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      29                 :  * SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "vfkreader.h"
      33                 : #include "vfkreaderp.h"
      34                 : 
      35                 : #include "cpl_conv.h"
      36                 : #include "cpl_error.h"
      37                 : 
      38                 : #define SUPPORT_GEOMETRY
      39                 : 
      40                 : #ifdef SUPPORT_GEOMETRY
      41                 : #  include "ogr_geometry.h"
      42                 : #endif
      43                 : 
      44                 : #ifdef HAVE_SQLITE
      45                 : 
      46                 : /*!
      47                 :   \brief VFKReaderSQLite constructor
      48                 : */
      49               2 : VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilename)
      50                 : {
      51               2 :     CPLString   pszDbName(m_pszFilename);
      52               2 :     CPLString   osCommand;
      53                 :     VSIStatBufL sStatBuf;
      54                 :     bool        bNewDb;
      55                 :     
      56                 :     /* open tmp SQLite DB (re-use DB file if already exists) */
      57               2 :     pszDbName += ".db";
      58                 : 
      59               2 :     bNewDb = TRUE;
      60               2 :     if (VSIStatL(pszDbName, &sStatBuf ) == 0) {
      61               1 :         CPLDebug("OGR-VFK", "Reading DB '%s'", pszDbName.c_str());
      62               1 :         bNewDb = FALSE;
      63                 :     }
      64                 :     
      65               2 :     if (SQLITE_OK != sqlite3_open(pszDbName, &m_poDB)) {
      66                 :         CPLError(CE_Failure, CPLE_AppDefined, 
      67               0 :                  "Creating SQLite DB failed");
      68                 :     }
      69                 :     else {
      70               2 :         char* pszErrMsg = NULL;
      71               2 :         sqlite3_exec(m_poDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg);
      72               2 :         sqlite3_free(pszErrMsg);
      73                 :     }
      74                 :     
      75               2 :     if (bNewDb) {
      76                 :         /* new DB, create support metadata tables */
      77                 :         osCommand.Printf("CREATE TABLE 'vfk_blocks' "
      78                 :                          "(file_name text, table_name text, "
      79               1 :                          "num_records integer, table_defn text);");
      80               1 :         ExecuteSQL(osCommand.c_str());
      81               2 :     }
      82               2 : }
      83                 : 
      84                 : /*!
      85                 :   \brief VFKReaderSQLite destructor
      86                 : */
      87               2 : VFKReaderSQLite::~VFKReaderSQLite()
      88                 : {
      89               2 :     CPLString pszDbName(m_pszFilename);
      90                 : 
      91               2 :     pszDbName += ".db";
      92                 :     
      93                 :     /* close tmp SQLite DB */
      94               2 :     if (SQLITE_OK != sqlite3_close(m_poDB)) {
      95                 :         CPLError(CE_Failure, CPLE_AppDefined, 
      96                 :                  "Closing SQLite DB failed\n  %s",
      97               0 :                  sqlite3_errmsg(m_poDB));
      98               2 :     }
      99               2 : }
     100                 : 
     101                 : /*!
     102                 :   \brief Load data block definitions (&B)
     103                 : 
     104                 :   Call VFKReader::OpenFile() before this function.
     105                 : 
     106                 :   \return number of data blocks
     107                 :   \return -1 on error
     108                 : */
     109               2 : int VFKReaderSQLite::ReadDataBlocks()
     110                 : {
     111                 :     int  nDataBlocks;
     112               2 :     CPLString osSQL;
     113                 :     const char *pszName, *pszDefn;
     114                 :     IVFKDataBlock *poNewDataBlock;
     115                 :     
     116                 :     sqlite3_stmt *hStmt;
     117                 :     
     118                 :     osSQL.Printf("SELECT table_name, table_defn FROM 'vfk_blocks' WHERE "
     119               2 :                  "file_name = '%s'", m_pszFilename);
     120               2 :     hStmt = PrepareStatement(osSQL.c_str());
     121              65 :     while(ExecuteSQL(hStmt) == OGRERR_NONE) {
     122              61 :         pszName = (const char*) sqlite3_column_text(hStmt, 0);
     123              61 :         pszDefn = (const char*) sqlite3_column_text(hStmt, 1);
     124              61 :         poNewDataBlock = (IVFKDataBlock *) CreateDataBlock(pszName);
     125              61 :         poNewDataBlock->SetGeometryType();
     126              61 :         poNewDataBlock->SetProperties(pszDefn);
     127              61 :         VFKReader::AddDataBlock(poNewDataBlock, NULL);
     128                 :     }
     129                 :     
     130               2 :     if (m_nDataBlockCount == 0) {
     131               1 :         sqlite3_exec(m_poDB, "BEGIN", 0, 0, 0);  
     132                 :         /* CREATE TABLE ... */
     133               1 :         nDataBlocks = VFKReader::ReadDataBlocks();
     134               1 :         sqlite3_exec(m_poDB, "COMMIT", 0, 0, 0);
     135                 :     }
     136                 :     
     137               2 :     return nDataBlocks;
     138                 : }
     139                 : 
     140                 : /*!
     141                 :   \brief Load data records (&D)
     142                 : 
     143                 :   Call VFKReader::OpenFile() before this function.
     144                 :   
     145                 :   \return number of data records
     146                 :   \return -1 on error
     147                 : */
     148               8 : int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
     149                 : {
     150                 :     int         nDataRecords;
     151                 :     const char *pszName;
     152               8 :     CPLString   osSQL;
     153                 : 
     154                 :     sqlite3_stmt *hStmt;
     155                 :     
     156                 :     /* table name */
     157               8 :     pszName = poDataBlock->GetName();
     158                 :     
     159                 :     /* check for existing records (re-use already inserted data) */
     160                 :     osSQL.Printf("SELECT num_records, table_defn FROM 'vfk_blocks' WHERE "
     161                 :                  "file_name = '%s' AND table_name = '%s'",
     162               8 :                  m_pszFilename, pszName);
     163               8 :     hStmt = PrepareStatement(osSQL.c_str());
     164               8 :     nDataRecords = 0;
     165               8 :     if (ExecuteSQL(hStmt) == OGRERR_NONE) {
     166               8 :         nDataRecords = sqlite3_column_int(hStmt, 0);
     167                 :     }
     168               8 :     sqlite3_finalize(hStmt);
     169                 : 
     170               8 :     if (nDataRecords > 0) {
     171                 :         VFKFeatureSQLite *poNewFeature;
     172                 :         
     173               4 :         poDataBlock->SetFeatureCount(0);
     174               4 :         poDataBlock->SetMaxFID(0);
     175              57 :         for (int i = 0; i < nDataRecords; i++) {
     176              53 :             poNewFeature = new VFKFeatureSQLite(poDataBlock);
     177              53 :             poDataBlock->AddFeature(poNewFeature);
     178                 :         }
     179               4 :         poDataBlock->SetMaxFID(poNewFeature->GetFID()); /* update max value */
     180                 :     }
     181                 :     else {
     182               4 :         sqlite3_exec(m_poDB, "BEGIN", 0, 0, 0);
     183                 :         
     184                 :         /* INSERT ... */
     185               4 :         nDataRecords = VFKReader::ReadDataRecords(poDataBlock);
     186                 :         
     187                 :         /* update 'vfk_blocks' table */
     188                 :         osSQL.Printf("UPDATE 'vfk_blocks' SET num_records = %d WHERE file_name = '%s' AND table_name = '%s'",
     189               4 :                      nDataRecords, m_pszFilename, pszName);
     190               4 :         sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     191                 :         
     192                 :         /* create indeces */
     193                 :         osSQL.Printf("CREATE UNIQUE INDEX %s_ID ON '%s' (ID)",
     194               4 :                      pszName, pszName);
     195               4 :         sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     196                 :         
     197               4 :         if (EQUAL(pszName, "SBP")) {
     198                 :             /* create extra indices for SBP */
     199                 :             osSQL.Printf("CREATE UNIQUE INDEX SBP_OB ON '%s' (OB_ID)",
     200               1 :                          pszName);
     201               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     202                 :             
     203                 :             osSQL.Printf("CREATE UNIQUE INDEX SBP_HP ON '%s' (HP_ID)",
     204               1 :                          pszName);
     205               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     206                 :             
     207                 :             osSQL.Printf("CREATE UNIQUE INDEX SBP_DPM ON '%s' (DPM_ID)",
     208               1 :                          pszName);
     209               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     210                 :             
     211                 :             osSQL.Printf("CREATE UNIQUE INDEX SBP_OB_HP_DPM ON '%s' (OB_ID,HP_ID,DPM_ID)",
     212               1 :                          pszName);
     213               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     214                 :             
     215                 :             osSQL.Printf("CREATE UNIQUE INDEX SBP_HP_POR ON '%s' (HP_ID,PORADOVE_CISLO_BODU)",
     216               1 :                          pszName);
     217               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     218                 :             
     219                 :             osSQL.Printf("CREATE UNIQUE INDEX SBP_DPM_POR ON '%s' (DPM_ID,PORADOVE_CISLO_BODU)",
     220               1 :                          pszName);
     221               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     222                 :         }
     223               3 :         else if (EQUAL(pszName, "HP")) {
     224                 :             /* create extra indices for HP */
     225                 :             osSQL.Printf("CREATE UNIQUE INDEX HP_PAR1 ON '%s' (PAR_ID_1)",
     226               1 :                          pszName);
     227               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     228                 :             
     229                 :             osSQL.Printf("CREATE UNIQUE INDEX HP_PAR2 ON '%s' (PAR_ID_2)",
     230               1 :                          pszName);
     231               1 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     232                 :             
     233                 :         }
     234               2 :         else if (EQUAL(pszName, "OP")) {
     235                 :             /* create extra indices for OP */
     236                 :             osSQL.Printf("CREATE UNIQUE INDEX OP_BUD ON '%s' (BUD_ID)",
     237               0 :                          pszName);
     238               0 :             sqlite3_exec(m_poDB, osSQL.c_str(), 0, 0, 0);
     239                 :             
     240                 :         }
     241                 :         
     242               4 :         sqlite3_exec(m_poDB, "COMMIT", 0, 0, 0);
     243                 :     }
     244                 :         
     245               8 :     return nDataRecords;
     246                 : }
     247                 : 
     248             122 : IVFKDataBlock *VFKReaderSQLite::CreateDataBlock(const char *pszBlockName)
     249                 : {
     250             122 :     return new VFKDataBlockSQLite(pszBlockName, (IVFKReader *) this);
     251                 : }
     252                 : 
     253                 : /*!
     254                 :   \brief Create DB table from VFKDataBlock (SQLITE only)
     255                 : 
     256                 :   \param poDataBlock pointer to VFKDataBlock instance
     257                 : */
     258              61 : void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDefn)
     259                 : {
     260              61 :     CPLString osCommand, osColumn;
     261                 :     VFKPropertyDefn *poPropertyDefn;
     262                 :     
     263                 :     sqlite3_stmt *hStmt;
     264                 : 
     265                 :     /* register table in 'vfk_blocks' */
     266                 :     osCommand.Printf("SELECT COUNT(*) FROM 'vfk_blocks' WHERE "
     267                 :                      "file_name = '%s' AND table_name = '%s'",
     268              61 :                      m_pszFilename, poDataBlock->GetName());
     269              61 :     hStmt = PrepareStatement(osCommand.c_str());
     270              61 :     if (ExecuteSQL(hStmt) == OGRERR_NONE &&
     271                 :         sqlite3_column_int(hStmt, 0) == 0) {
     272                 :         
     273              61 :         osCommand.Printf("CREATE TABLE '%s' (", poDataBlock->GetName());
     274             636 :         for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
     275             575 :             poPropertyDefn = poDataBlock->GetProperty(i);
     276             575 :             if (i > 0)
     277             514 :                 osCommand += ",";
     278                 :             osColumn.Printf("%s %s", poPropertyDefn->GetName(),
     279             575 :                             poPropertyDefn->GetTypeSQL().c_str());
     280             575 :             osCommand += osColumn;
     281                 :         }
     282              61 :         osCommand += ",ogr_fid INTERGER);";
     283                 :         
     284              61 :         ExecuteSQL(osCommand.c_str()); /* CREATE TABLE */
     285                 : 
     286                 :         osCommand.Printf("INSERT INTO 'vfk_blocks' (file_name, table_name, "
     287                 :                          "num_records, table_defn) VALUES ('%s', '%s', 0, '%s')",
     288              61 :                          m_pszFilename, poDataBlock->GetName(), pszDefn);
     289              61 :         ExecuteSQL(osCommand.c_str());
     290                 : 
     291              61 :         sqlite3_finalize(hStmt);
     292                 :     }
     293                 :         
     294              61 :     return VFKReader::AddDataBlock(poDataBlock, NULL);
     295                 : }
     296                 : 
     297                 : /*!
     298                 :   \brief Prepare SQL statement
     299                 :   
     300                 :   \param pszSQLCommand SQL statement to be prepared
     301                 : 
     302                 :   \return pointer to sqlite3_stmt instance
     303                 :   \return NULL on error
     304                 : */
     305             161 : sqlite3_stmt *VFKReaderSQLite::PrepareStatement(const char *pszSQLCommand)
     306                 : {
     307                 :     int rc;
     308             161 :     sqlite3_stmt *hStmt = NULL;
     309                 :     
     310                 :     rc = sqlite3_prepare(m_poDB, pszSQLCommand, strlen(pszSQLCommand),
     311             161 :                          &hStmt, NULL);
     312                 :     
     313             161 :     if (rc != SQLITE_OK) {
     314                 :         CPLError(CE_Failure, CPLE_AppDefined, 
     315                 :                  "In PrepareStatement(): sqlite3_prepare(%s):\n  %s",
     316               0 :                  pszSQLCommand, sqlite3_errmsg(m_poDB));
     317                 :         
     318               0 :         if(hStmt != NULL) {
     319               0 :             sqlite3_finalize(hStmt);
     320                 :         }
     321                 :         
     322               0 :         return NULL;
     323                 :     }
     324                 : 
     325             161 :     return hStmt;
     326                 : }
     327                 : 
     328                 : /*!
     329                 :   \brief Execute prepared SQL statement
     330                 : 
     331                 :   \param hStmt pointer to sqlite3_stmt 
     332                 : 
     333                 :   \return OGRERR_NONE on success
     334                 : */
     335             354 : OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
     336                 : {
     337                 :     int rc;
     338                 :     
     339                 :     // assert
     340                 : 
     341             354 :     rc = sqlite3_step(hStmt);
     342             354 :     if (rc != SQLITE_ROW) {
     343              14 :         if (rc == SQLITE_DONE) {
     344              14 :             sqlite3_finalize(hStmt);
     345              14 :             return OGRERR_NOT_ENOUGH_DATA;
     346                 :         }
     347                 :         
     348                 :         CPLError(CE_Failure, CPLE_AppDefined, 
     349                 :                  "In ExecuteSQL(): sqlite3_step:\n  %s", 
     350               0 :                  sqlite3_errmsg(m_poDB));
     351               0 :         if (hStmt)
     352               0 :             sqlite3_finalize(hStmt);
     353               0 :         return OGRERR_FAILURE;
     354                 :     }
     355                 :     
     356             340 :     return OGRERR_NONE;
     357                 : 
     358                 : }
     359                 : 
     360                 : /*!
     361                 :   \brief Execute SQL statement (SQLITE only)
     362                 : 
     363                 :   \return OGRERR_NONE on success
     364                 :   \return OGRERR_FAILURE on failure
     365                 : */
     366             176 : OGRErr VFKReaderSQLite::ExecuteSQL(const char *pszSQLCommand)
     367                 : {
     368                 :     int rc;
     369             176 :     sqlite3_stmt *hSQLStmt = NULL;
     370                 : 
     371                 :     rc = sqlite3_prepare(m_poDB, pszSQLCommand, strlen(pszSQLCommand),
     372             176 :                          &hSQLStmt, NULL);
     373                 :     
     374             176 :     if (rc != SQLITE_OK) {
     375                 :         CPLError(CE_Failure, CPLE_AppDefined, 
     376                 :                  "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
     377               0 :                  pszSQLCommand, sqlite3_errmsg(m_poDB));
     378                 :         
     379               0 :         if(hSQLStmt != NULL) {
     380               0 :             sqlite3_finalize(hSQLStmt);
     381                 :         }
     382                 :         
     383               0 :         return OGRERR_FAILURE;
     384                 :     }
     385                 : 
     386             176 :     rc = sqlite3_step(hSQLStmt);
     387             176 :     if (rc != SQLITE_DONE) {
     388                 :         CPLError(CE_Failure, CPLE_AppDefined, 
     389                 :                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s", 
     390               0 :                  pszSQLCommand, sqlite3_errmsg(m_poDB));
     391                 :         
     392               0 :         sqlite3_finalize(hSQLStmt);
     393                 :         
     394               0 :         return OGRERR_FAILURE;
     395                 :     }
     396                 : 
     397             176 :     sqlite3_finalize(hSQLStmt);
     398                 :     
     399             176 :     return OGRERR_NONE;
     400                 : }
     401                 : 
     402                 : /*!
     403                 :   \brief Add feature
     404                 : 
     405                 :   \param poNewDataBlock pointer to VFKDataBlock instance
     406                 :   \param poNewFeature pointer to VFKFeature instance
     407                 : */
     408              53 : void VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFeature)
     409                 : {
     410              53 :     CPLString     osCommand;
     411              53 :     CPLString     osValue;
     412                 :     
     413                 :     OGRFieldType  ftype;
     414                 : 
     415                 :     VFKFeatureSQLite  *poNewFeature;
     416                 :     const VFKProperty *poProperty;
     417                 :     
     418              53 :     osCommand.Printf("INSERT INTO '%s' VALUES(", poDataBlock->GetName());
     419                 :     
     420             705 :     for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
     421             652 :         ftype = poDataBlock->GetProperty(i)->GetType();
     422             652 :         poProperty = poFeature->GetProperty(i);
     423             652 :         if (i > 0)
     424             599 :             osCommand += ",";
     425             652 :         if (poProperty->IsNull())
     426             180 :             osValue.Printf("NULL");
     427                 :         else {
     428             472 :             switch (ftype) {
     429                 :             case OFTInteger:
     430             139 :                 osValue.Printf("%d", poProperty->GetValueI());
     431             139 :                 break;
     432                 :             case OFTReal:
     433              26 :                 osValue.Printf("%f", poProperty->GetValueD());
     434              26 :                 break;
     435                 :             case OFTString:
     436             307 :                 if (poDataBlock->GetProperty(i)->IsIntBig())
     437             239 :                     osValue.Printf("%lu", strtoul(poProperty->GetValueS(), NULL, 0));
     438                 :                 else
     439              68 :                     osValue.Printf("'%s'", poProperty->GetValueS());
     440             307 :                 break;
     441                 :             default:
     442               0 :                 osValue.Printf("'%s'", poProperty->GetValueS());
     443                 :                 break;
     444                 :             }
     445                 :         }
     446             652 :         osCommand += osValue;
     447                 :     }
     448              53 :     osValue.Printf(",%lu);", poFeature->GetFID());
     449              53 :     osCommand += osValue;
     450                 :     
     451              53 :     ExecuteSQL(osCommand.c_str());
     452                 : 
     453              53 :     poNewFeature = new VFKFeatureSQLite(poFeature);
     454              53 :     poDataBlock->AddFeature(poNewFeature);
     455              53 :     delete poFeature;
     456              53 : }
     457                 : 
     458                 : #endif /* HAVE_SQLITE */

Generated by: LCOV version 1.7