/********************************************************************** * CreateIndex() * * Create index for specified field in an existing TAB dataset. **********************************************************************/ static int CreateIndex(const char *pszSrcFname, const char *pszField) { IMapInfoFile *poSrcFile = NULL; int nFeatureId, iField; TABFeature *poFeature; TABINDFile *poINDFile; /*--------------------------------------------------------------------- * Try to open source file *--------------------------------------------------------------------*/ if ((poSrcFile = IMapInfoFile::SmartOpen(pszSrcFname)) == NULL) { printf("Failed to open %s\n", pszSrcFname); return -1; } if (poSrcFile->GetFileClass() != TABFC_TABFile) { printf("Indexes cannot be added to this type of TAB datasets\n"); poSrcFile->Close(); delete poSrcFile; return -1; } /*--------------------------------------------------------------------- * Make sure field exists and is not already indexed *--------------------------------------------------------------------*/ OGRFeatureDefn *poDefn = poSrcFile->GetLayerDefn(); if ( poDefn == NULL || (iField = poDefn->GetFieldIndex(pszField)) == -1 || poSrcFile->IsFieldIndexed(iField)) { printf("Cannot create index: field '%s' not found or is already indexed.\n", pszField); poSrcFile->Close(); delete poSrcFile; return -1; } /*--------------------------------------------------------------------- * Things seem OK... open IND file for update * (Note that TABINDFile automagically adjusts file extension) *--------------------------------------------------------------------*/ poINDFile = new TABINDFile; if ( poINDFile->Open(pszSrcFname, "r+", TRUE) != 0 && poINDFile->Open(pszSrcFname, "w", TRUE) != 0) { printf("Unable to create IND file for %s.\n", pszSrcFname); delete poINDFile; poSrcFile->Close(); delete poSrcFile; return -1; } int nNewIndexNo = -1; OGRFieldDefn *poFieldDefn = poDefn->GetFieldDefn(iField); TABFieldType eFieldType = poSrcFile->GetNativeFieldType(iField); if (poFieldDefn == NULL || (nNewIndexNo = poINDFile->CreateIndex(eFieldType, poFieldDefn->GetWidth()) ) < 1) { // Failed... an error has already been reported. delete poINDFile; poSrcFile->Close(); delete poSrcFile; return -1; } printf("Index number %d will be created for field %s...\n\n" "This program does not update the TAB header file (yet!) so you \n" "should edit %s and add 'Index %d' at the end of the definition \n" "of field %s.\n\n", nNewIndexNo, pszField, pszSrcFname, nNewIndexNo, pszField); /*--------------------------------------------------------------------- * Add index entries until we reach EOF *--------------------------------------------------------------------*/ nFeatureId = -1; while ( (nFeatureId = poSrcFile->GetNextFeatureId(nFeatureId)) != -1 ) { poFeature = poSrcFile->GetFeatureRef(nFeatureId); if (poFeature) { GByte *pKey = NULL; switch(eFieldType) { case TABFChar: pKey = poINDFile->BuildKey(nNewIndexNo, poFeature->GetFieldAsString(iField)); break; case TABFInteger: case TABFSmallInt: pKey = poINDFile->BuildKey(nNewIndexNo, poFeature->GetFieldAsInteger(iField)); break; case TABFDecimal: case TABFFloat: case TABFLogical: pKey = poINDFile->BuildKey(nNewIndexNo, poFeature->GetFieldAsDouble(iField)); break; default: case TABFDate: CPLAssert(FALSE); // Unsupported for now. } if (poINDFile->AddEntry(nNewIndexNo, pKey, nFeatureId) != 0) return -1; } else break; // GetFeatureRef() failed: Abort the loop } /*--------------------------------------------------------------------- * Cleanup and exit. *--------------------------------------------------------------------*/ poINDFile->Close(); delete poINDFile; poSrcFile->Close(); delete poSrcFile; MITABFreeCoordSysTable(); return 0; }
OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML) { /* -------------------------------------------------------------------- */ /* Parse the XML. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psRoot = CPLParseXMLString( pszRawXML ); if( psRoot == nullptr ) return OGRERR_FAILURE; /* -------------------------------------------------------------------- */ /* Open the index file. */ /* -------------------------------------------------------------------- */ poINDFile = new TABINDFile(); if (pszMIINDFilename == nullptr) pszMIINDFilename = CPLStrdup(CPLGetXMLValue(psRoot,"MIIDFilename","")); if( pszMIINDFilename == nullptr ) return OGRERR_FAILURE; /* NOTE: Replaced r+ with r according to explanation in Ticket #1620. * This change has to be observed if it doesn't cause any * problems in future. (mloskot) */ if( poINDFile->Open( pszMIINDFilename, "r" ) != 0 ) { CPLDestroyXMLNode( psRoot ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open index file %s.", pszMIINDFilename ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Process each attrindex. */ /* -------------------------------------------------------------------- */ for( CPLXMLNode *psAttrIndex = psRoot->psChild; psAttrIndex != nullptr; psAttrIndex = psAttrIndex->psNext ) { if( psAttrIndex->eType != CXT_Element || !EQUAL(psAttrIndex->pszValue,"OGRMIAttrIndex") ) continue; int iField = atoi(CPLGetXMLValue(psAttrIndex,"FieldIndex","-1")); int iIndexIndex = atoi(CPLGetXMLValue(psAttrIndex,"IndexIndex","-1")); if( iField == -1 || iIndexIndex == -1 ) { CPLError( CE_Warning, CPLE_AppDefined, "Skipping corrupt OGRMIAttrIndex entry." ); continue; } AddAttrInd( iField, iIndexIndex ); } CPLDestroyXMLNode( psRoot ); CPLDebug( "OGR", "Restored %d field indexes for layer %s from %s on %s.", nIndexCount, poLayer->GetLayerDefn()->GetName(), pszMetadataFilename ? pszMetadataFilename : "--unknown--", pszMIINDFilename ); return OGRERR_NONE; }
OGRErr OGRMILayerAttrIndex::CreateIndex( int iField ) { /* -------------------------------------------------------------------- */ /* Do we have an open .ID file yet? If not, create it now. */ /* -------------------------------------------------------------------- */ if( poINDFile == NULL ) { poINDFile = new TABINDFile(); if( poINDFile->Open( pszMIINDFilename, "w+" ) != 0 ) { delete poINDFile; poINDFile = NULL; CPLError( CE_Failure, CPLE_OpenFailed, "Failed to create %s.", pszMIINDFilename ); return OGRERR_FAILURE; } } else if (bINDAsReadOnly) { poINDFile->Close(); if( poINDFile->Open( pszMIINDFilename, "r+" ) != 0 ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s as write-only.", pszMIINDFilename ); if( poINDFile->Open( pszMIINDFilename, "r" ) != 0 ) { CPLError( CE_Failure, CPLE_OpenFailed, "Cannot re-open %s as read-only.", pszMIINDFilename ); delete poINDFile; poINDFile = NULL; } return OGRERR_FAILURE; } else { bINDAsReadOnly = FALSE; } } /* -------------------------------------------------------------------- */ /* Do we have this field indexed already? */ /* -------------------------------------------------------------------- */ OGRFieldDefn *poFldDefn=poLayer->GetLayerDefn()->GetFieldDefn(iField); for( int i = 0; i < nIndexCount; i++ ) { if( papoIndexList[i]->iField == iField ) { CPLError( CE_Failure, CPLE_AppDefined, "It seems we already have an index for field %d/%s\n" "of layer %s.", iField, poFldDefn->GetNameRef(), poLayer->GetLayerDefn()->GetName() ); return OGRERR_FAILURE; } } /* -------------------------------------------------------------------- */ /* What is the corresponding field type in TAB? Note that we */ /* don't allow indexing of any of the list types. */ /* -------------------------------------------------------------------- */ TABFieldType eTABFT; int nFieldWidth = 0; switch( poFldDefn->GetType() ) { case OFTInteger: eTABFT = TABFInteger; break; case OFTReal: eTABFT = TABFFloat; break; case OFTString: eTABFT = TABFChar; if( poFldDefn->GetWidth() > 0 ) nFieldWidth = poFldDefn->GetWidth(); else nFieldWidth = 64; break; default: CPLError( CE_Failure, CPLE_AppDefined, "Indexing not support for the field type of field %s.", poFldDefn->GetNameRef() ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Create the index. */ /* -------------------------------------------------------------------- */ int iINDIndex; iINDIndex = poINDFile->CreateIndex( eTABFT, nFieldWidth ); // CreateIndex() reports it's own errors. if( iINDIndex < 0 ) return OGRERR_FAILURE; AddAttrInd( iField, iINDIndex ); bUnlinkINDFile = FALSE; /* -------------------------------------------------------------------- */ /* Save the new configuration. */ /* -------------------------------------------------------------------- */ return SaveConfigToXML(); }