From 3abaa234c93b5566241b24f3ed0ab0d35c9ae22c Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Wed, 21 Nov 2012 00:13:21 +0100 Subject: [PATCH 1/4] ogr2ogr: add debug output when non-existing destination fields are skipped nas: also accept XML files that have AAA-Fachschema.xsd in header (and remove trailing whitespace) --- gdal/apps/ogr2ogr.cpp | 3 + gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp | 71 ++++++++++--------- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/gdal/apps/ogr2ogr.cpp b/gdal/apps/ogr2ogr.cpp index cf51ac183fdb..e3b20d381c48 100644 --- a/gdal/apps/ogr2ogr.cpp +++ b/gdal/apps/ogr2ogr.cpp @@ -2631,6 +2631,9 @@ static TargetLayerInfo* SetupTargetLayer( OGRDataSource *poSrcDS, int iDstField = poDstFDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef()); if (iDstField >= 0) panMap[iField] = iDstField; + else + CPLDebug("OGR2OGR", "Skipping field '%s' not found in destination layer '%s'.", + poSrcFieldDefn->GetNameRef(), poDstLayer->GetName() ); } } diff --git a/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp index 88a11ab354b8..f26dd94bfe31 100644 --- a/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp +++ b/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp @@ -33,12 +33,12 @@ CPL_CVSID("$Id$"); -static const char *apszURNNames[] = -{ - "DE_DHDN_3GK2_*", "EPSG:31466", - "DE_DHDN_3GK3_*", "EPSG:31467", - "ETRS89_UTM32", "EPSG:25832", - NULL, NULL +static const char *apszURNNames[] = +{ + "DE_DHDN_3GK2_*", "EPSG:31466", + "DE_DHDN_3GK3_*", "EPSG:31467", + "ETRS89_UTM32", "EPSG:25832", + NULL, NULL }; /************************************************************************/ @@ -66,7 +66,7 @@ OGRNASDataSource::~OGRNASDataSource() for( int i = 0; i < nLayers; i++ ) delete papoLayers[i]; - + CPLFree( papoLayers ); if( poReader ) @@ -90,8 +90,8 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) if( fp == NULL ) { if( !bTestOpen ) - CPLError( CE_Failure, CPLE_OpenFailed, - "Failed to open NAS file `%s'.", + CPLError( CE_Failure, CPLE_OpenFailed, + "Failed to open NAS file `%s'.", pszNewName ); return FALSE; @@ -114,7 +114,7 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) /* -------------------------------------------------------------------- */ /* Check for a UTF-8 BOM and skip if found */ /* */ -/* TODO: BOM is variable-lenght parameter and depends on encoding. */ +/* TODO: BOM is variable-length parameter and depends on encoding. */ /* Add BOM detection for other encodings. */ /* -------------------------------------------------------------------- */ @@ -131,34 +131,35 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) /* -------------------------------------------------------------------- */ /* Here, we expect the opening chevrons of NAS tree root element */ /* -------------------------------------------------------------------- */ - if( szPtr[0] != '<' - || strstr(szPtr,"opengis.net/gml") == NULL - || strstr(szPtr,"NAS-Operationen.xsd") == NULL ) + if( szPtr[0] != '<' + || strstr(szPtr,"opengis.net/gml") == NULL + || (strstr(szPtr,"NAS-Operationen.xsd") == NULL && + strstr(szPtr,"AAA-Fachschema.xsd") == NULL ) ) { VSIFClose( fp ); return FALSE; } } - + /* -------------------------------------------------------------------- */ /* We assume now that it is NAS. Close and instantiate a */ /* NASReader on it. */ /* -------------------------------------------------------------------- */ VSIFClose( fp ); - + poReader = CreateNASReader(); if( poReader == NULL ) { - CPLError( CE_Failure, CPLE_AppDefined, + CPLError( CE_Failure, CPLE_AppDefined, "File %s appears to be NAS but the NAS reader can't\n" "be instantiated, likely because Xerces support wasn't\n" - "configured in.", + "configured in.", pszNewName ); return FALSE; } poReader->SetSourceFile( pszNewName ); - + pszName = CPLStrdup( pszNewName ); /* -------------------------------------------------------------------- */ @@ -175,9 +176,9 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) if( sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime ) { - CPLDebug( "NAS", + CPLDebug( "NAS", "Found %s but ignoring because it appears\n" - "be older than the associated NAS file.", + "be older than the associated NAS file.", pszGFSFilename ); } else @@ -192,8 +193,8 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) /* information. */ /* -------------------------------------------------------------------- */ CPLErrorReset(); - if( !bHaveSchema - && !poReader->PrescanForSchema( TRUE ) + if( !bHaveSchema + && !poReader->PrescanForSchema( TRUE ) && CPLGetLastErrorType() == CE_Failure ) { // we assume an errors have been reported. @@ -209,7 +210,7 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) FILE *fp = NULL; pszGFSFilename = CPLResetExtension( pszNewName, "gfs" ); - if( CPLStat( pszGFSFilename, &sGFSStatBuf ) != 0 + if( CPLStat( pszGFSFilename, &sGFSStatBuf ) != 0 && (fp = VSIFOpen( pszGFSFilename, "wt" )) != NULL ) { VSIFClose( fp ); @@ -217,7 +218,7 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) } else { - CPLDebug("NAS", + CPLDebug("NAS", "Not saving %s files already exists or can't be created.", pszGFSFilename ); } @@ -235,7 +236,7 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) papoLayers[nLayers] = TranslateNASSchema(poReader->GetClass(nLayers)); nLayers++; } - + poRelationLayer = new OGRNASRelationLayer( this ); // keep delete the last layer @@ -250,7 +251,7 @@ int OGRNASDataSource::Open( const char * pszNewName, int bTestOpen ) } nLayers++; - + return TRUE; } @@ -262,7 +263,7 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass ) { OGRNASLayer *poLayer; - OGRwkbGeometryType eGType + OGRwkbGeometryType eGType = (OGRwkbGeometryType) poClass->GetGeometryType(); if( poClass->GetFeatureCount() == 0 ) @@ -278,7 +279,7 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass ) int i; poSRS = new OGRSpatialReference(); - + const char *pszHandle = strrchr( pszSRSName, ':' ); if( pszHandle != NULL ) pszHandle += 1; @@ -300,10 +301,10 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass ) pszSRSName = apszURNNames[i*2+1]; } } - + if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE) { - CPLDebug( "NAS", "Failed to translate srsName='%s'", + CPLDebug( "NAS", "Failed to translate srsName='%s'", pszSRSName ); delete poSRS; poSRS = NULL; @@ -340,7 +341,7 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass ) eFType = OFTRealList; else eFType = OFTString; - + OGRFieldDefn oField( poProperty->GetName(), eFType ); if ( EQUALN(oField.GetNameRef(), "ogr:", 4) ) oField.SetName(poProperty->GetName()+4); @@ -397,19 +398,19 @@ void OGRNASDataSource::PopulateRelations() int nGMLIdIndex = poFeature->GetClass()->GetPropertyIndex( "gml_id" ); const GMLProperty *psGMLId = (nGMLIdIndex >= 0) ? poFeature->GetProperty(nGMLIdIndex ) : NULL; char *pszName = NULL; - const char *pszValue = CPLParseNameValue( papszOBProperties[i], + const char *pszValue = CPLParseNameValue( papszOBProperties[i], &pszName ); - if( EQUALN(pszValue,"urn:adv:oid:",12) + if( EQUALN(pszValue,"urn:adv:oid:",12) && psGMLId != NULL && psGMLId->nSubProperties == 1 ) { poRelationLayer->AddRelation( psGMLId->papszSubProperties[0], - pszName, + pszName, pszValue + 12 ); } CPLFree( pszName ); } - + delete poFeature; } From ec624e2ba20dcad5100bc04114f032221c300fe8 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Wed, 21 Nov 2012 00:12:23 +0100 Subject: [PATCH 2/4] space out remainder of step evenly between start and end of arcs --- gdal/ogr/gml2ogrgeometry.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gdal/ogr/gml2ogrgeometry.cpp b/gdal/ogr/gml2ogrgeometry.cpp index 466191631735..68f851a0a299 100644 --- a/gdal/ogr/gml2ogrgeometry.cpp +++ b/gdal/ogr/gml2ogrgeometry.cpp @@ -885,7 +885,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode, int nSign = (det >= 0) ? 1 : -1; - double alpha; + double alpha, dfRemainder; double dfStep = atof(CPLGetConfigOption("OGR_ARC_STEPSIZE","4")) / 180 * PI; // make sure the segments are not too short @@ -915,16 +915,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode, dfStep *= nSign; + dfRemainder = fmod(alpha1 - alpha0, dfStep) / 2.0; + poLine->addPoint(x0, y0); - for(alpha = alpha0 + dfStep; (alpha - alpha1) * nSign < 0; alpha += dfStep) + for(alpha = alpha0 + dfStep + dfRemainder; (alpha + dfRemainder - alpha1) * nSign < 0; alpha += dfStep) { poLine->addPoint(cx + R * cos(alpha), cy + R * sin(alpha)); } poLine->addPoint(x1, y1); - for(alpha = alpha1 + dfStep; (alpha - alpha2) * nSign < 0; alpha += dfStep) + dfRemainder = fmod(alpha2 - alpha1, dfStep) / 2.0; + + for(alpha = alpha1 + dfStep + dfRemainder; (alpha + dfRemainder - alpha2) * nSign < 0; alpha += dfStep) { poLine->addPoint(cx + R * cos(alpha), cy + R * sin(alpha)); } From e0e49060c49def228e4fb5f641dc01b4af601092 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Sat, 19 Jan 2013 21:10:27 +0100 Subject: [PATCH 3/4] add EPSG:25833 to NAS driver --- gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp index f26dd94bfe31..f8815481a747 100644 --- a/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp +++ b/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp @@ -38,6 +38,7 @@ static const char *apszURNNames[] = "DE_DHDN_3GK2_*", "EPSG:31466", "DE_DHDN_3GK3_*", "EPSG:31467", "ETRS89_UTM32", "EPSG:25832", + "ETRS89_UTM33", "EPSG:25833", NULL, NULL }; From 9ba949b47993b5215491961c738c3b4ed0efdfa9 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Tue, 22 Jan 2013 18:31:09 +0100 Subject: [PATCH 4/4] OCI driver: - continue fid counting when importing to existing tables - recognize pre-existing tables with laundered names - recognize tables with reserved names (like "DELETE" from NAS) --- gdal/ogr/ogrsf_frmts/nas/nashandler.cpp | 2 +- gdal/ogr/ogrsf_frmts/nas/nasreader.cpp | 15 ---- gdal/ogr/ogrsf_frmts/oci/ogr_oci.h | 3 + gdal/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp | 48 ++++++++++- gdal/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp | 84 ++++++++++++++----- 5 files changed, 116 insertions(+), 36 deletions(-) diff --git a/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp b/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp index 9b044b04460d..1093580f0b5f 100644 --- a/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp +++ b/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp @@ -456,7 +456,7 @@ void NASHandler::endElement(const XMLCh* const uri, { int iId = poState->m_poFeature->GetClass()->GetPropertyIndex( "gml_id" ); const GMLProperty *poIdProp = poState->m_poFeature->GetProperty(iId); -#if DEBUG_VERBOSE +#ifdef DEBUG_VERBOSE char *pszOldGeom = CPLSerializeXMLTree( poState->m_poFeature->GetGeometryList()[0] ); CPLDebug("NAS", "Overwriting other geometry (%s; replace:%s; with:%s)", diff --git a/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp b/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp index ee7d8732a025..d1a60fb07411 100644 --- a/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp +++ b/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp @@ -625,21 +625,6 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement, } return; } -#if 0 - else if( strcmp(poClass->GetProperty(iProperty)->GetName(),"signaturnummer") == 0 || - strcmp(poClass->GetProperty(iProperty)->GetName(),"anlass") == 0 ) - { - if( isalpha( pszValue[0] ) && isalpha( pszValue[1] ) && isdigit( pszValue[2] ) ) - { - poFeature->SetPropertyDirectly( iProperty, CPLStrdup( pszValue+2 ) ); -#ifdef DEBUG_VERBOSE - CPLDebug( "NAS", "Skipping two letter prefix of '%s'", pszValue ); -#endif - CPLFree(pszValue); - return; - } - } -#endif else if( strcmp(poClass->GetProperty(iProperty)->GetName(),"kartendarstellung") == 0 || strcmp(poClass->GetProperty(iProperty)->GetName(),"rechtsbehelfsverfahren") == 0 ) { diff --git a/gdal/ogr/ogrsf_frmts/oci/ogr_oci.h b/gdal/ogr/ogrsf_frmts/oci/ogr_oci.h index 96d52f555db1..8c6335790925 100644 --- a/gdal/ogr/ogrsf_frmts/oci/ogr_oci.h +++ b/gdal/ogr/ogrsf_frmts/oci/ogr_oci.h @@ -464,6 +464,8 @@ class OGROCITableLayer : public OGROCIWritableLayer // following methods are not base class overrides int IsValid() { return bValidTable; } + + int GetMaxFID(); }; /************************************************************************/ @@ -516,6 +518,7 @@ class OGROCIDataSource : public OGRDataSource const char *GetName() { return pszName; } int GetLayerCount() { return nLayers; } OGRLayer *GetLayer( int ); + OGRLayer *GetLayerByName(const char * pszName); virtual OGRErr DeleteLayer(int); virtual OGRLayer *CreateLayer( const char *, diff --git a/gdal/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp b/gdal/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp index fd67b3eb2b92..64c275b1a263 100644 --- a/gdal/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp +++ b/gdal/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp @@ -419,7 +419,7 @@ void OGROCIDataSource::DeleteLayer( const char *pszLayerName ) if( iLayer == nLayers ) { CPLDebug( "OCI", "DeleteLayer: %s not found in layer list." \ - " Layer * not* deleted.", pszLayerName ); + " Layer *not* deleted.", pszLayerName ); return; } @@ -964,3 +964,49 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS ) else return nSRSId; } + + +/************************************************************************/ +/* GetLayerByName() */ +/************************************************************************/ + +OGRLayer *OGROCIDataSource::GetLayerByName( const char *pszName ) + +{ + OGROCILayer *poLayer; + int i, count; + + if ( !pszName ) + return NULL; + + count = GetLayerCount(); + + /* first a case sensitive check */ + for( i = 0; i < count; i++ ) + { + poLayer = papoLayers[i]; + + if( strcmp( pszName, poLayer->GetName() ) == 0 ) + { + return poLayer; + } + } + + char *pszSafeLayerName = CPLStrdup( pszName ); + poSession->CleanName( pszSafeLayerName ); + + /* then case insensitive and laundered */ + for( i = 0; i < count; i++ ) + { + poLayer = papoLayers[i]; + + if( EQUAL( pszSafeLayerName, poLayer->GetName() ) ) + { + break; + } + } + + CPLFree( pszSafeLayerName ); + + return i < count ? poLayer : NULL; +} diff --git a/gdal/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp b/gdal/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp index 8dbbb8a4f34f..5e80c020fb6e 100644 --- a/gdal/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp +++ b/gdal/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp @@ -59,7 +59,7 @@ OGROCITableLayer::OGROCITableLayer( OGROCIDataSource *poDSIn, bNewLayer = bNewLayerIn; iNextShapeId = 0; - iNextFIDToWrite = 1; + iNextFIDToWrite = -1; bValidTable = FALSE; if( bNewLayerIn ) @@ -154,6 +154,9 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable ) poDefn->Reference(); + CPLString osQuotedTableName; + osQuotedTableName.Printf( "\"%s\"", pszTable ); + /* -------------------------------------------------------------------- */ /* Split out the owner if available. */ /* -------------------------------------------------------------------- */ @@ -175,20 +178,20 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable ) OCIParam *hAttrList = NULL; nStatus = - OCIDescribeAny( poSession->hSvcCtx, poSession->hError, - (dvoid *) pszTable, strlen(pszTable), OCI_OTYPE_NAME, + OCIDescribeAny( poSession->hSvcCtx, poSession->hError, + (dvoid *) osQuotedTableName.c_str(), osQuotedTableName.length(), OCI_OTYPE_NAME, OCI_DEFAULT, OCI_PTYPE_TABLE, poSession->hDescribe ); if( poSession->Failed( nStatus, "OCIDescribeAny" ) ) { CPLErrorReset(); nStatus = OCIDescribeAny(poSession->hSvcCtx, poSession->hError, - (dvoid *)pszTable, strlen(pszTable), OCI_OTYPE_NAME, + (dvoid *) osQuotedTableName.c_str(), osQuotedTableName.length(), OCI_OTYPE_NAME, OCI_DEFAULT, OCI_PTYPE_VIEW, poSession->hDescribe ); if( poSession->Failed( nStatus, "OCIDescribeAny" ) ) return poDefn; } - + if( poSession->Failed( OCIAttrGet( poSession->hDescribe, OCI_HTYPE_DESCRIBE, &hAttrParam, 0, OCI_ATTR_PARAM, poSession->hError ), @@ -264,13 +267,13 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable ) char **papszResult; int iDim = -1; - oDimCmd.Append( "SELECT COUNT(*) FROM ALL_SDO_GEOM_METADATA u," ); - oDimCmd.Append( " TABLE(u.diminfo) t" ); - oDimCmd.Append( " WHERE u.table_name = '" ); - oDimCmd.Append( osTableName ); - oDimCmd.Append( "' AND u.column_name = '" ); - oDimCmd.Append( pszGeomName ); - oDimCmd.Append( "'" ); + oDimCmd.Append( "SELECT COUNT(*) FROM ALL_SDO_GEOM_METADATA u," ); + oDimCmd.Append( " TABLE(u.diminfo) t" ); + oDimCmd.Append( " WHERE u.table_name = '" ); + oDimCmd.Append( osTableName ); + oDimCmd.Append( "' AND u.column_name = '" ); + oDimCmd.Append( pszGeomName ); + oDimCmd.Append( "'" ); oDimStatement.Execute( oDimCmd.GetString() ); @@ -283,7 +286,7 @@ OGRFeatureDefn *OGROCITableLayer::ReadTableDefinition( const char * pszTable ) char **papszResult2; CPLErrorReset(); - + oDimCmd2.Appendf( 1024, "select m.sdo_index_dims\n" "from all_sdo_index_metadata m, all_sdo_index_info i\n" @@ -1585,19 +1588,35 @@ int OGROCITableLayer::AllocAndBindForWrite(int eType) /* Collect the INSERT statement. */ /* -------------------------------------------------------------------- */ OGROCIStringBuf oCmdBuf; - + oCmdBuf.Append( "INSERT INTO " ); oCmdBuf.Append( poFeatureDefn->GetName() ); + oCmdBuf.Append( "(\"" ); + oCmdBuf.Append( pszFIDName ); + oCmdBuf.Append( "\"" ); - if (eType == wkbNone) - oCmdBuf.Append( " VALUES ( :fid" ); - else - oCmdBuf.Append( " VALUES ( :fid, :geometry" ); + if (eType != wkbNone) + { + oCmdBuf.Append( ",\"" ); + oCmdBuf.Append( pszGeomName ); + oCmdBuf.Append( "\"" ); + } + + for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ ) + { + oCmdBuf.Append( ",\"" ); + oCmdBuf.Append( poFeatureDefn->GetFieldDefn(i)->GetNameRef() ); + oCmdBuf.Append( "\"" ); + } + + oCmdBuf.Append( ") VALUES ( :fid " ); + + if (eType != wkbNone) + oCmdBuf.Append( ", :geometry" ); for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ ) { oCmdBuf.Append( ", " ); - oCmdBuf.Appendf( 20, " :field_%d", i ); } @@ -1882,6 +1901,7 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature ) } } + psInd->sdo_gtype = OCI_IND_NOTNULL; OCINumberFromInt( poSession->hError, &nGType, (uword)sizeof(int), OCI_NUMBER_SIGNED, &(psGeom->sdo_gtype) ); @@ -1891,7 +1911,14 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature ) /* Set the FID. */ /* -------------------------------------------------------------------- */ if( poFeature->GetFID() == OGRNullFID ) + { + if( iNextFIDToWrite < 0 ) + { + iNextFIDToWrite = GetMaxFID() + 1; + } + poFeature->SetFID( iNextFIDToWrite++ ); + } panWriteFIDs[iCache] = poFeature->GetFID(); @@ -2075,3 +2102,22 @@ void OGROCITableLayer::CreateSpatialIndex() } } } + +int OGROCITableLayer::GetMaxFID() +{ + if( pszFIDName == NULL ) + return 0; + + OGROCIStringBuf sCmd; + OGROCIStatement oSelect( poDS->GetSession() ); + + sCmd.Appendf( 10000, "SELECT MAX(\"%s\") FROM \"%s\"", + pszFIDName, + poFeatureDefn->GetName() + ); + + oSelect.Execute( sCmd.GetString() ); + + char **papszResult = oSelect.SimpleFetchRow(); + return CSLCount(papszResult) == 1 ? atoi( papszResult[0] ) : 0; +}