LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogr_miattrind.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 248 190 76.6 %
Date: 2011-12-18 Functions: 30 19 63.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr_miattrind.cpp 20104 2010-07-18 17:34:53Z tamas $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements interface to MapInfo .ID files used as attribute
       6                 :  *           indexes.  
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2003, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "ogr_attrind.h"
      32                 : #include "mitab/mitab_priv.h"
      33                 : #include "cpl_minixml.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogr_miattrind.cpp 20104 2010-07-18 17:34:53Z tamas $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            OGRMIAttrIndex                            */
      39                 : /*                                                                      */
      40                 : /*      MapInfo .ID implementation of access to one fields              */
      41                 : /*      indexing.                                                       */
      42                 : /************************************************************************/
      43                 : 
      44                 : class OGRMILayerAttrIndex;
      45                 : 
      46                 : class OGRMIAttrIndex : public OGRAttrIndex
      47                 : {
      48                 : public:
      49                 :     int         iIndex;
      50                 :     TABINDFile  *poINDFile;
      51                 :     OGRMILayerAttrIndex *poLIndex;
      52                 :     OGRFieldDefn *poFldDefn;
      53                 : 
      54                 :     int         iField;
      55                 : 
      56                 :                 OGRMIAttrIndex( OGRMILayerAttrIndex *, int iIndex, int iField);
      57                 :                ~OGRMIAttrIndex();
      58                 : 
      59                 :     GByte      *BuildKey( OGRField *psKey );
      60                 :     long        GetFirstMatch( OGRField *psKey );
      61                 :     long       *GetAllMatches( OGRField *psKey );
      62                 :     long       *GetAllMatches( OGRField *psKey, long* panFIDList, int* nFIDCount, int* nLength );
      63                 : 
      64                 :     OGRErr      AddEntry( OGRField *psKey, long nFID );
      65                 :     OGRErr      RemoveEntry( OGRField *psKey, long nFID );
      66                 : 
      67                 :     OGRErr      Clear();
      68                 : };
      69                 : 
      70                 : /************************************************************************/
      71                 : /* ==================================================================== */
      72                 : /*                         OGRMILayerAttrIndex                          */
      73                 : /*                                                                      */
      74                 : /*      MapInfo .ID specific implementation of a layer attribute        */
      75                 : /*      index.                                                          */
      76                 : /* ==================================================================== */
      77                 : /************************************************************************/
      78                 : 
      79                 : class OGRMILayerAttrIndex : public OGRLayerAttrIndex
      80                 : {
      81                 : public:
      82                 :     TABINDFile  *poINDFile;
      83                 : 
      84                 :     int         nIndexCount;
      85                 :     OGRMIAttrIndex **papoIndexList;
      86                 : 
      87                 :     char        *pszMetadataFilename;
      88                 :     char        *pszMIINDFilename;
      89                 : 
      90                 :     int         bINDAsReadOnly;
      91                 :     int         bUnlinkINDFile;
      92                 : 
      93                 :                 OGRMILayerAttrIndex();
      94                 :     virtual     ~OGRMILayerAttrIndex();
      95                 : 
      96                 :     /* base class virtual methods */
      97                 :     OGRErr      Initialize( const char *pszIndexPath, OGRLayer * );
      98                 :     OGRErr      CreateIndex( int iField );
      99                 :     OGRErr      DropIndex( int iField );
     100                 :     OGRErr      IndexAllFeatures( int iField = -1 );
     101                 : 
     102                 :     OGRErr      AddToIndex( OGRFeature *poFeature, int iField = -1 );
     103                 :     OGRErr      RemoveFromIndex( OGRFeature *poFeature );
     104                 : 
     105                 :     OGRAttrIndex *GetFieldIndex( int iField );
     106                 : 
     107                 :     /* custom to OGRMILayerAttrIndex */
     108                 :     OGRErr      SaveConfigToXML();
     109                 :     OGRErr      LoadConfigFromXML();
     110                 :     OGRErr      LoadConfigFromXML(const char* pszRawXML);
     111                 :     void        AddAttrInd( int iField, int iINDIndex );
     112                 : 
     113              10 :     OGRLayer   *GetLayer() { return poLayer; }
     114                 : };
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                        OGRMILayerAttrIndex()                         */
     118                 : /************************************************************************/
     119                 : 
     120              26 : OGRMILayerAttrIndex::OGRMILayerAttrIndex()
     121                 : 
     122                 : {
     123              26 :     poINDFile = NULL;
     124              26 :     nIndexCount = 0;
     125              26 :     papoIndexList = NULL;
     126              26 :     bUnlinkINDFile = FALSE;
     127              26 :     bINDAsReadOnly = TRUE;
     128              26 :     pszMIINDFilename = NULL;
     129              26 :     pszMetadataFilename = NULL;
     130              26 : }
     131                 : 
     132                 : /************************************************************************/
     133                 : /*                        ~OGRMILayerAttrIndex()                        */
     134                 : /************************************************************************/
     135                 : 
     136              26 : OGRMILayerAttrIndex::~OGRMILayerAttrIndex()
     137                 : 
     138                 : {
     139              26 :     if( poINDFile != NULL )
     140                 :     {
     141               6 :         poINDFile->Close();
     142               6 :         delete poINDFile;
     143               6 :         poINDFile = NULL;
     144                 :     }
     145                 : 
     146              26 :     if (bUnlinkINDFile)
     147               1 :         VSIUnlink( pszMIINDFilename );
     148                 : 
     149              34 :     for( int i = 0; i < nIndexCount; i++ )
     150               8 :         delete papoIndexList[i];
     151              26 :     CPLFree( papoIndexList );
     152                 : 
     153              26 :     CPLFree( pszMIINDFilename );
     154              26 :     CPLFree( pszMetadataFilename );
     155              26 : }
     156                 : 
     157                 : /************************************************************************/
     158                 : /*                             Initialize()                             */
     159                 : /************************************************************************/
     160                 : 
     161              26 : OGRErr OGRMILayerAttrIndex::Initialize( const char *pszIndexPathIn, 
     162                 :                                         OGRLayer *poLayerIn )
     163                 : 
     164                 : {
     165              26 :     if( poLayerIn == poLayer )
     166               0 :         return OGRERR_NONE;
     167                 : 
     168                 : /* -------------------------------------------------------------------- */
     169                 : /*      Capture input information and form static pathnames.            */
     170                 : /* -------------------------------------------------------------------- */
     171              26 :     poLayer = poLayerIn;
     172                 : 
     173              26 :     pszIndexPath = CPLStrdup( pszIndexPathIn );
     174                 : 
     175                 :     /* try to process the XML string directly */
     176              26 :     if (EQUALN(pszIndexPathIn, "<OGRMILayerAttrIndex>", 21))
     177               0 :         return LoadConfigFromXML(pszIndexPathIn);
     178                 :     
     179                 :     pszMetadataFilename = CPLStrdup(
     180              26 :         CPLResetExtension( pszIndexPathIn, "idm" ) );
     181                 :     
     182              26 :     pszMIINDFilename = CPLStrdup(CPLResetExtension( pszIndexPathIn, "ind" ));
     183                 : 
     184                 : /* -------------------------------------------------------------------- */
     185                 : /*      If a metadata file already exists, load it.                     */
     186                 : /* -------------------------------------------------------------------- */
     187                 :     OGRErr eErr;
     188                 :     VSIStatBuf sStat;
     189                 : 
     190              26 :     if( VSIStat( pszMetadataFilename, &sStat ) == 0 )
     191                 :     {
     192               3 :         eErr = LoadConfigFromXML();
     193               3 :         if( eErr != OGRERR_NONE )
     194               0 :             return eErr;
     195                 :     }
     196                 : 
     197              26 :     return OGRERR_NONE;
     198                 : }
     199                 : 
     200                 : /************************************************************************/
     201                 : /*                         LoadConfigFromXML()                          */
     202                 : /************************************************************************/
     203                 : 
     204               3 : OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
     205                 : 
     206                 : {
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      Parse the XML.                                                  */
     209                 : /* -------------------------------------------------------------------- */
     210               3 :     CPLXMLNode *psRoot = CPLParseXMLString( pszRawXML );
     211                 : 
     212               3 :     if( psRoot == NULL )
     213               0 :         return OGRERR_FAILURE;
     214                 : 
     215                 : /* -------------------------------------------------------------------- */
     216                 : /*      Open the index file.                                            */
     217                 : /* -------------------------------------------------------------------- */
     218               3 :     poINDFile = new TABINDFile();
     219                 :     
     220               3 :     if (pszMIINDFilename == NULL)
     221               0 :         pszMIINDFilename = CPLStrdup(CPLGetXMLValue(psRoot,"MIIDFilename",""));
     222                 :     
     223               3 :     if( pszMIINDFilename == NULL )
     224               0 :         return OGRERR_FAILURE;
     225                 : 
     226                 :     /* NOTE: Replaced r+ with r according to explanation in Ticket #1620.
     227                 :      * This change has to be observed if it doesn't cause any
     228                 :      * problems in future. (mloskot)
     229                 :      */
     230               3 :     if( poINDFile->Open( pszMIINDFilename, "r" ) != 0 )
     231                 :     {
     232               0 :         CPLDestroyXMLNode( psRoot );
     233                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     234                 :                   "Failed to open index file %s.", 
     235               0 :                   pszMIINDFilename );
     236               0 :         return OGRERR_FAILURE;
     237                 :     }
     238                 : /* -------------------------------------------------------------------- */
     239                 : /*      Process each attrindex.                                         */
     240                 : /* -------------------------------------------------------------------- */
     241                 :     CPLXMLNode *psAttrIndex;
     242                 : 
     243              10 :     for( psAttrIndex = psRoot->psChild; 
     244                 :          psAttrIndex != NULL; 
     245                 :          psAttrIndex = psAttrIndex->psNext )
     246                 :     {
     247                 :         int iField, iIndexIndex;
     248                 : 
     249               7 :         if( psAttrIndex->eType != CXT_Element 
     250                 :             || !EQUAL(psAttrIndex->pszValue,"OGRMIAttrIndex") )
     251               3 :             continue;
     252                 : 
     253               4 :         iField = atoi(CPLGetXMLValue(psAttrIndex,"FieldIndex","-1"));
     254               4 :         iIndexIndex = atoi(CPLGetXMLValue(psAttrIndex,"IndexIndex","-1"));
     255                 : 
     256               4 :         if( iField == -1 || iIndexIndex == -1 )
     257                 :         {
     258                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     259               0 :                       "Skipping corrupt OGRMIAttrIndex entry." );
     260               0 :             continue;
     261                 :         }
     262                 : 
     263               4 :         AddAttrInd( iField, iIndexIndex );
     264                 :     }
     265                 : 
     266               3 :     CPLDestroyXMLNode( psRoot );
     267                 : 
     268                 :     CPLDebug( "OGR", "Restored %d field indexes for layer %s from %s on %s.",
     269               3 :               nIndexCount, poLayer->GetLayerDefn()->GetName(), 
     270               6 :               pszMetadataFilename, pszMIINDFilename );
     271                 : 
     272               3 :     return OGRERR_NONE;
     273                 : }
     274                 : 
     275               3 : OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
     276                 : {
     277                 :     FILE *fp;
     278                 :     int  nXMLSize;
     279                 :     char *pszRawXML;
     280                 : 
     281               3 :     CPLAssert( poINDFile == NULL );
     282                 : 
     283                 : /* -------------------------------------------------------------------- */
     284                 : /*      Read the XML file.                                              */
     285                 : /* -------------------------------------------------------------------- */
     286               3 :     fp = VSIFOpen( pszMetadataFilename, "rb" );
     287               3 :     if( fp == NULL )
     288               0 :         return OGRERR_NONE;
     289                 : 
     290               3 :     VSIFSeek( fp, 0, SEEK_END );
     291               3 :     nXMLSize = VSIFTell( fp );
     292               3 :     VSIFSeek( fp, 0, SEEK_SET );
     293                 : 
     294               3 :     pszRawXML = (char *) CPLMalloc(nXMLSize+1);
     295               3 :     pszRawXML[nXMLSize] = '\0';
     296               3 :     VSIFRead( pszRawXML, nXMLSize, 1, fp );
     297                 : 
     298               3 :     VSIFClose( fp );
     299                 : 
     300               3 :     OGRErr eErr = LoadConfigFromXML(pszRawXML);
     301               3 :     CPLFree(pszRawXML);
     302                 : 
     303               3 :     return eErr;
     304                 : }
     305                 : 
     306                 : /************************************************************************/
     307                 : /*                          SaveConfigToXML()                           */
     308                 : /************************************************************************/
     309                 : 
     310               7 : OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
     311                 : 
     312                 : {
     313               7 :     if( nIndexCount == 0 )
     314               0 :         return OGRERR_NONE;
     315                 : 
     316                 : /* -------------------------------------------------------------------- */
     317                 : /*      Create the XML tree corresponding to this layer.                */
     318                 : /* -------------------------------------------------------------------- */
     319                 :     CPLXMLNode *psRoot;
     320                 : 
     321               7 :     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "OGRMILayerAttrIndex" );
     322                 : 
     323                 :     CPLCreateXMLElementAndValue( psRoot, "MIIDFilename", 
     324               7 :                                  CPLGetFilename( pszMIINDFilename ) );
     325                 :     
     326              17 :     for( int i = 0; i < nIndexCount; i++ )
     327                 :     {
     328              10 :         OGRMIAttrIndex *poAI = papoIndexList[i];
     329                 :         CPLXMLNode *psIndex;
     330                 : 
     331              10 :         psIndex = CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
     332                 : 
     333                 :         CPLCreateXMLElementAndValue( psIndex, "FieldIndex", 
     334              10 :                                      CPLSPrintf( "%d", poAI->iField ) );
     335                 :                                      
     336                 :         CPLCreateXMLElementAndValue( psIndex, "FieldName", 
     337              10 :                                      poLayer->GetLayerDefn()->GetFieldDefn(poAI->iField)->GetNameRef() );
     338                 : 
     339                 :                                      
     340                 :         CPLCreateXMLElementAndValue( psIndex, "IndexIndex", 
     341              10 :                                      CPLSPrintf( "%d", poAI->iIndex ) );
     342                 :     }
     343                 : 
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*      Save it.                                                        */
     346                 : /* -------------------------------------------------------------------- */
     347               7 :     char *pszRawXML = CPLSerializeXMLTree( psRoot );
     348                 :     FILE *fp;
     349                 : 
     350               7 :     CPLDestroyXMLNode( psRoot );
     351                 : 
     352               7 :     fp = VSIFOpen( pszMetadataFilename, "wb" );
     353               7 :     if( fp == NULL )
     354                 :     {
     355                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     356                 :                   "Failed to pen `%s' for write.", 
     357               0 :                   pszMetadataFilename );
     358               0 :         CPLFree( pszRawXML );
     359               0 :         return OGRERR_FAILURE;
     360                 :     }
     361                 : 
     362               7 :     VSIFWrite( pszRawXML, 1, strlen(pszRawXML), fp );
     363               7 :     VSIFClose( fp );
     364                 : 
     365               7 :     CPLFree( pszRawXML );
     366                 :     
     367               7 :     return OGRERR_NONE;
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                          IndexAllFeatures()                          */
     372                 : /************************************************************************/
     373                 : 
     374               6 : OGRErr OGRMILayerAttrIndex::IndexAllFeatures( int iField )
     375                 : 
     376                 : {
     377                 :     OGRFeature *poFeature;
     378                 : 
     379               6 :     poLayer->ResetReading();
     380                 :     
     381               6 :     while( (poFeature = poLayer->GetNextFeature()) != NULL )
     382                 :     {
     383              82 :         OGRErr eErr = AddToIndex( poFeature, iField );
     384                 :         
     385              82 :         delete poFeature;
     386                 : 
     387              82 :         if( eErr != CE_None )
     388               0 :             return eErr;
     389                 :     }
     390                 : 
     391               6 :     poLayer->ResetReading();
     392                 : 
     393               6 :     return OGRERR_NONE;
     394                 : }
     395                 : 
     396                 : /************************************************************************/
     397                 : /*                            CreateIndex()                             */
     398                 : /*                                                                      */
     399                 : /*      Create an index corresponding to the indicated field, but do    */
     400                 : /*      not populate it.  Use IndexAllFeatures() for that.              */
     401                 : /************************************************************************/
     402                 : 
     403               6 : OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
     404                 : 
     405                 : {
     406                 : /* -------------------------------------------------------------------- */
     407                 : /*      Do we have an open .ID file yet?  If not, create it now.        */
     408                 : /* -------------------------------------------------------------------- */
     409               6 :     if( poINDFile == NULL )
     410                 :     {
     411               3 :         poINDFile = new TABINDFile();
     412               3 :         if( poINDFile->Open( pszMIINDFilename, "w+" ) != 0 )
     413                 :         {
     414               0 :             delete poINDFile;
     415               0 :             poINDFile = NULL;
     416                 :             
     417                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     418                 :                       "Failed to create %s.",
     419               0 :                       pszMIINDFilename );
     420               0 :             return OGRERR_FAILURE;
     421                 :         }
     422                 :     }
     423               3 :     else if (bINDAsReadOnly)
     424                 :     {
     425               3 :         poINDFile->Close();
     426               3 :         if( poINDFile->Open( pszMIINDFilename, "r+" ) != 0 )
     427                 :         {
     428                 :             CPLError( CE_Failure, CPLE_OpenFailed, 
     429                 :                       "Failed to open %s as write-only.",
     430               0 :                       pszMIINDFilename );
     431                 : 
     432               0 :             if( poINDFile->Open( pszMIINDFilename, "r" ) != 0 )
     433                 :             {
     434                 :                 CPLError( CE_Failure, CPLE_OpenFailed, 
     435                 :                       "Cannot re-open %s as read-only.",
     436               0 :                       pszMIINDFilename );
     437               0 :                 delete poINDFile;
     438               0 :                 poINDFile = NULL;
     439                 :             }
     440                 : 
     441               0 :             return OGRERR_FAILURE;
     442                 :         }
     443                 :         else
     444                 :         {
     445               3 :             bINDAsReadOnly = FALSE;
     446                 :         }
     447                 :     }
     448                 : 
     449                 : /* -------------------------------------------------------------------- */
     450                 : /*      Do we have this field indexed already?                          */
     451                 : /* -------------------------------------------------------------------- */
     452                 :     int i;
     453               6 :     OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField);
     454                 : 
     455               9 :     for( i = 0; i < nIndexCount; i++ )
     456                 :     {
     457               3 :         if( papoIndexList[i]->iField == iField )
     458                 :         {
     459                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     460                 :                       "It seems we already have an index for field %d/%s\n"
     461                 :                       "of layer %s.", 
     462                 :                       iField, poFldDefn->GetNameRef(),
     463               0 :                       poLayer->GetLayerDefn()->GetName() );
     464               0 :             return OGRERR_FAILURE;
     465                 :         }
     466                 :     }
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      What is the corresponding field type in TAB?  Note that we      */
     470                 : /*      don't allow indexing of any of the list types.                  */
     471                 : /* -------------------------------------------------------------------- */
     472                 :     TABFieldType eTABFT;
     473               6 :     int           nFieldWidth = 0;
     474                 : 
     475               6 :     switch( poFldDefn->GetType() )
     476                 :     {
     477                 :       case OFTInteger:
     478               3 :         eTABFT = TABFInteger;
     479               3 :         break;
     480                 : 
     481                 :       case OFTReal:
     482               1 :         eTABFT = TABFFloat;
     483               1 :         break;
     484                 : 
     485                 :       case OFTString:
     486               2 :         eTABFT = TABFChar;
     487               2 :         if( poFldDefn->GetWidth() > 0 )
     488               2 :             nFieldWidth = poFldDefn->GetWidth();
     489                 :         else
     490               0 :             nFieldWidth = 64;
     491               2 :         break;
     492                 : 
     493                 :       default:
     494                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     495                 :                   "Indexing not support for the field type of field %s.",
     496               0 :                   poFldDefn->GetNameRef() );
     497               0 :         return OGRERR_FAILURE;
     498                 :     }
     499                 : 
     500                 : /* -------------------------------------------------------------------- */
     501                 : /*      Create the index.                                               */
     502                 : /* -------------------------------------------------------------------- */
     503                 :     int iINDIndex;
     504                 : 
     505               6 :     iINDIndex = poINDFile->CreateIndex( eTABFT, nFieldWidth );
     506                 : 
     507                 :     // CreateIndex() reports it's own errors.
     508               6 :     if( iINDIndex < 0 )
     509               0 :         return OGRERR_FAILURE;
     510                 : 
     511               6 :     AddAttrInd( iField, iINDIndex );
     512                 : 
     513               6 :     bUnlinkINDFile = FALSE;
     514                 : 
     515                 : /* -------------------------------------------------------------------- */
     516                 : /*      Save the new configuration.                                     */
     517                 : /* -------------------------------------------------------------------- */
     518               6 :     return SaveConfigToXML();
     519                 : }
     520                 : 
     521                 : /************************************************************************/
     522                 : /*                             DropIndex()                              */
     523                 : /*                                                                      */
     524                 : /*      For now we don't have any capability to remove index data       */
     525                 : /*      from the MapInfo index file, so we just limit ourselves to      */
     526                 : /*      ignoring it from now on.                                        */
     527                 : /************************************************************************/
     528                 : 
     529               2 : OGRErr OGRMILayerAttrIndex::DropIndex( int iField )
     530                 : 
     531                 : {
     532                 : /* -------------------------------------------------------------------- */
     533                 : /*      Do we have this field indexed already?                          */
     534                 : /* -------------------------------------------------------------------- */
     535                 :     int i;
     536               2 :     OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField);
     537                 : 
     538               2 :     for( i = 0; i < nIndexCount; i++ )
     539                 :     {
     540               2 :         if( papoIndexList[i]->iField == iField )
     541               2 :             break;
     542                 : 
     543                 :     }
     544                 : 
     545               2 :     if( i == nIndexCount )
     546                 :     {
     547                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     548                 :                   "DROP INDEX on field (%s) that doesn't have an index.",
     549               0 :                   poFldDefn->GetNameRef() );
     550               0 :         return OGRERR_FAILURE;
     551                 :     }
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Remove from the list.                                           */
     555                 : /* -------------------------------------------------------------------- */
     556               2 :     OGRMIAttrIndex *poAI = papoIndexList[i];
     557                 : 
     558                 :     memmove( papoIndexList + i, papoIndexList + i + 1, 
     559               2 :              sizeof(void*) * (nIndexCount - i - 1) );
     560                 : 
     561               2 :     delete poAI;
     562                 : 
     563               2 :     nIndexCount--;
     564                 :              
     565                 : /* -------------------------------------------------------------------- */
     566                 : /*      Save the new configuration, or if there is nothing left try     */
     567                 : /*      to clean up the index files.                                    */
     568                 : /* -------------------------------------------------------------------- */
     569                 : 
     570               2 :     if( nIndexCount > 0 )
     571               1 :         return SaveConfigToXML();
     572                 :     else
     573                 :     {
     574               1 :         bUnlinkINDFile = TRUE;
     575               1 :         VSIUnlink( pszMetadataFilename );
     576                 : 
     577               1 :         return OGRERR_NONE;
     578                 :     }
     579                 : }
     580                 : 
     581                 : /************************************************************************/
     582                 : /*                             AddAttrInd()                             */
     583                 : /************************************************************************/
     584                 : 
     585              10 : void OGRMILayerAttrIndex::AddAttrInd( int iField, int iINDIndex )
     586                 : 
     587                 : {
     588              10 :     OGRMIAttrIndex *poAttrInd = new OGRMIAttrIndex( this, iINDIndex, iField);
     589                 : 
     590              10 :     nIndexCount++;
     591                 :     papoIndexList = (OGRMIAttrIndex **) 
     592              10 :         CPLRealloc(papoIndexList, sizeof(void*) * nIndexCount);
     593                 :     
     594              10 :     papoIndexList[nIndexCount-1] = poAttrInd;
     595              10 : }
     596                 : 
     597                 : /************************************************************************/
     598                 : /*                         GetFieldAttrIndex()                          */
     599                 : /************************************************************************/
     600                 : 
     601             131 : OGRAttrIndex *OGRMILayerAttrIndex::GetFieldIndex( int iField )
     602                 : 
     603                 : {
     604             151 :     for( int i = 0; i < nIndexCount; i++ )
     605                 :     {
     606              44 :         if( papoIndexList[i]->iField == iField )
     607              24 :             return papoIndexList[i];
     608                 :     }
     609                 : 
     610             107 :     return NULL;
     611                 : }
     612                 : 
     613                 : /************************************************************************/
     614                 : /*                             AddToIndex()                             */
     615                 : /************************************************************************/
     616                 : 
     617              82 : OGRErr OGRMILayerAttrIndex::AddToIndex( OGRFeature *poFeature,
     618                 :                                         int iTargetField )
     619                 : 
     620                 : {
     621              82 :     OGRErr eErr = OGRERR_NONE;
     622                 : 
     623              82 :     if( poFeature->GetFID() == OGRNullFID )
     624                 :     {
     625                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     626               0 :                   "Attempt to index feature with no FID." );
     627               0 :         return OGRERR_FAILURE;
     628                 :     }
     629                 : 
     630             205 :     for( int i = 0; i < nIndexCount && eErr == OGRERR_NONE; i++ )
     631                 :     {
     632             123 :         int iField = papoIndexList[i]->iField;
     633                 : 
     634             123 :         if( iTargetField != -1 && iTargetField != iField )
     635              41 :             continue;
     636                 : 
     637              82 :         if( !poFeature->IsFieldSet( iField ) )
     638               0 :             continue;
     639                 : 
     640                 :         eErr = 
     641             246 :             papoIndexList[i]->AddEntry( poFeature->GetRawFieldRef( iField ),
     642             328 :                                         poFeature->GetFID() );
     643                 :     }
     644                 : 
     645              82 :     return eErr;
     646                 : }
     647                 : 
     648                 : /************************************************************************/
     649                 : /*                          RemoveFromIndex()                           */
     650                 : /************************************************************************/
     651                 : 
     652               0 : OGRErr OGRMILayerAttrIndex::RemoveFromIndex( OGRFeature * /*poFeature*/ )
     653                 : 
     654                 : {
     655               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     656                 : }
     657                 : 
     658                 : /************************************************************************/
     659                 : /*                     OGRCreateDefaultLayerIndex()                     */
     660                 : /************************************************************************/
     661                 : 
     662              26 : OGRLayerAttrIndex *OGRCreateDefaultLayerIndex()
     663                 : 
     664                 : {
     665              26 :     return new OGRMILayerAttrIndex();
     666                 : }
     667                 : 
     668                 : /************************************************************************/
     669                 : /* ==================================================================== */
     670                 : /*                            OGRMIAttrIndex                            */
     671                 : /* ==================================================================== */
     672                 : /************************************************************************/
     673                 : 
     674                 : /* class declared at top of file */
     675                 : 
     676                 : /************************************************************************/
     677                 : /*                           OGRMIAttrIndex()                           */
     678                 : /************************************************************************/
     679                 : 
     680              10 : OGRMIAttrIndex::OGRMIAttrIndex( OGRMILayerAttrIndex *poLayerIndex, 
     681              10 :                                 int iIndexIn, int iFieldIn )
     682                 : 
     683                 : {
     684              10 :     iIndex = iIndexIn;
     685              10 :     iField = iFieldIn;
     686              10 :     poLIndex = poLayerIndex;
     687              10 :     poINDFile = poLayerIndex->poINDFile;
     688                 : 
     689              10 :     poFldDefn = poLayerIndex->GetLayer()->GetLayerDefn()->GetFieldDefn(iField);
     690              10 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                          ~OGRMIAttrIndex()                           */
     694                 : /************************************************************************/
     695                 : 
     696              10 : OGRMIAttrIndex::~OGRMIAttrIndex()
     697                 : {
     698              10 : }
     699                 : 
     700                 : /************************************************************************/
     701                 : /*                              AddEntry()                              */
     702                 : /************************************************************************/
     703                 : 
     704              82 : OGRErr OGRMIAttrIndex::AddEntry( OGRField *psKey, long nFID )
     705                 : 
     706                 : {
     707              82 :     GByte *pabyKey = BuildKey( psKey );
     708                 : 
     709              82 :     if( psKey == NULL )
     710               0 :         return OGRERR_FAILURE;
     711                 : 
     712              82 :     if( poINDFile->AddEntry( iIndex, pabyKey, nFID+1 ) != 0 )
     713               0 :         return OGRERR_FAILURE;
     714                 :     else
     715              82 :         return OGRERR_NONE;
     716                 : }
     717                 : 
     718                 : /************************************************************************/
     719                 : /*                            RemoveEntry()                             */
     720                 : /************************************************************************/
     721                 : 
     722               0 : OGRErr OGRMIAttrIndex::RemoveEntry( OGRField * /*psKey*/, long /*nFID*/ )
     723                 : 
     724                 : {
     725               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     726                 : }
     727                 : 
     728                 : /************************************************************************/
     729                 : /*                              BuildKey()                              */
     730                 : /************************************************************************/
     731                 : 
     732             106 : GByte *OGRMIAttrIndex::BuildKey( OGRField *psKey )
     733                 : 
     734                 : {
     735             106 :     switch( poFldDefn->GetType() )
     736                 :     {
     737                 :       case OFTInteger:
     738              57 :         return poINDFile->BuildKey( iIndex, psKey->Integer );
     739                 :         break;
     740                 : 
     741                 :       case OFTReal:
     742               8 :         return poINDFile->BuildKey( iIndex, psKey->Real );
     743                 :         break;
     744                 : 
     745                 :       case OFTString:
     746              41 :         return poINDFile->BuildKey( iIndex, psKey->String );
     747                 :         break;
     748                 : 
     749                 :       default:
     750               0 :         CPLAssert( FALSE );
     751                 : 
     752               0 :         return NULL;
     753                 :     }
     754                 : }
     755                 : 
     756                 : /************************************************************************/
     757                 : /*                           GetFirstMatch()                            */
     758                 : /************************************************************************/
     759                 : 
     760               0 : long OGRMIAttrIndex::GetFirstMatch( OGRField *psKey )
     761                 : 
     762                 : {
     763               0 :     GByte *pabyKey = BuildKey( psKey );
     764                 :     long nFID;
     765                 : 
     766               0 :     nFID = poINDFile->FindFirst( iIndex, pabyKey );
     767               0 :     if( nFID < 1 )
     768               0 :         return OGRNullFID;
     769                 :     else
     770               0 :         return nFID - 1;
     771                 : }
     772                 : 
     773                 : /************************************************************************/
     774                 : /*                           GetAllMatches()                            */
     775                 : /************************************************************************/
     776                 : 
     777              24 : long *OGRMIAttrIndex::GetAllMatches( OGRField *psKey, long* panFIDList, int* nFIDCount, int* nLength )
     778                 : {
     779              24 :     GByte *pabyKey = BuildKey( psKey );
     780                 :     long nFID;
     781                 : 
     782              24 :     if (panFIDList == NULL)
     783                 :     {
     784              24 :         panFIDList = (long *) CPLMalloc(sizeof(long) * 2);
     785              24 :         *nFIDCount = 0;
     786              24 :         *nLength = 2;
     787                 :     }
     788                 : 
     789              24 :     nFID = poINDFile->FindFirst( iIndex, pabyKey );
     790              69 :     while( nFID > 0 )
     791                 :     {
     792              21 :         if( *nFIDCount >= *nLength-1 )
     793                 :         {
     794               0 :             *nLength = (*nLength) * 2 + 10;
     795               0 :             panFIDList = (long *) CPLRealloc(panFIDList, sizeof(long)* (*nLength));
     796                 :         }
     797              21 :         panFIDList[(*nFIDCount)++] = nFID - 1;
     798                 :         
     799              21 :         nFID = poINDFile->FindNext( iIndex, pabyKey );
     800                 :     }
     801                 : 
     802              24 :     panFIDList[*nFIDCount] = OGRNullFID;
     803                 :     
     804              24 :     return panFIDList;
     805                 : }
     806                 : 
     807               0 : long *OGRMIAttrIndex::GetAllMatches( OGRField *psKey )
     808                 : {
     809                 :     int nFIDCount, nLength;
     810               0 :     return GetAllMatches( psKey, NULL, &nFIDCount, &nLength );
     811                 : }
     812                 : 
     813                 : /************************************************************************/
     814                 : /*                               Clear()                                */
     815                 : /************************************************************************/
     816                 : 
     817               0 : OGRErr OGRMIAttrIndex::Clear()
     818                 : 
     819                 : {
     820               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     821                 : }

Generated by: LCOV version 1.7