OGRErr OGRShapeLayer::DeleteFeature( long nFID ) { if( !bUpdateAccess ) { CPLError( CE_Failure, CPLE_AppDefined, "The DeleteFeature() operation is not permitted on a read-only shapefile." ); return OGRERR_FAILURE; } if( nFID < 0 || (hSHP != NULL && nFID >= hSHP->nRecords) || (hDBF != NULL && nFID >= hDBF->nRecords) ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to delete shape with feature id (%ld) which does " "not exist.", nFID ); return OGRERR_FAILURE; } if( !hDBF ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to delete shape in shapefile with no .dbf file.\n" "Deletion is done by marking record deleted in dbf\n" "and is not supported without a .dbf file." ); return OGRERR_FAILURE; } if( DBFIsRecordDeleted( hDBF, nFID ) ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to delete shape with feature id (%ld), but it is marked deleted already.", nFID ); return OGRERR_FAILURE; } if( !DBFMarkRecordDeleted( hDBF, nFID, TRUE ) ) return OGRERR_FAILURE; bHeaderDirty = TRUE; if( CheckForQIX() ) DropSpatialIndex(); return OGRERR_NONE; }
OGRFeature *OGRShapeLayer::GetNextFeature() { OGRFeature *poFeature = NULL; /* -------------------------------------------------------------------- */ /* Collect a matching list if we have attribute or spatial */ /* indices. Only do this on the first request for a given pass */ /* of course. */ /* -------------------------------------------------------------------- */ if( (m_poAttrQuery != NULL || m_poFilterGeom != NULL) && iNextShapeId == 0 && panMatchingFIDs == NULL ) { ScanIndices(); } /* -------------------------------------------------------------------- */ /* Loop till we find a feature matching our criteria. */ /* -------------------------------------------------------------------- */ while( TRUE ) { if( panMatchingFIDs != NULL ) { if( panMatchingFIDs[iMatchingFID] == OGRNullFID ) { return NULL; } // Check the shape object's geometry, and if it matches // any spatial filter, return it. poFeature = FetchShape(panMatchingFIDs[iMatchingFID]); iMatchingFID++; } else { if( iNextShapeId >= nTotalShapeCount ) { return NULL; } if ( hDBF && DBFIsRecordDeleted( hDBF, iNextShapeId ) ) { poFeature = NULL; } else { // Check the shape object's geometry, and if it matches // any spatial filter, return it. poFeature = FetchShape(iNextShapeId); } iNextShapeId++; } if( poFeature != NULL ) { if( poFeature->GetGeometryRef() != NULL ) { poFeature->GetGeometryRef()->assignSpatialReference( GetSpatialRef() ); } m_nFeaturesRead++; if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) { return poFeature; } delete poFeature; } } /* * NEVER SHOULD GET HERE */ CPLAssert(!"OGRShapeLayer::GetNextFeature(): Execution never should get here!"); }
int main( int argc, char ** argv ) { DBFHandle hDBF; int *panWidth, i, iRecord; char szFormat[32], *pszFilename = NULL; int nWidth, nDecimals; int bHeader = 0; int bRaw = 0; int bMultiLine = 0; char szTitle[12]; /* -------------------------------------------------------------------- */ /* Handle arguments. */ /* -------------------------------------------------------------------- */ for( i = 1; i < argc; i++ ) { if( strcmp(argv[i],"-h") == 0 ) bHeader = 1; else if( strcmp(argv[i],"-r") == 0 ) bRaw = 1; else if( strcmp(argv[i],"-m") == 0 ) bMultiLine = 1; else pszFilename = argv[i]; } /* -------------------------------------------------------------------- */ /* Display a usage message. */ /* -------------------------------------------------------------------- */ if( pszFilename == NULL ) { printf( "dbfdump [-h] [-r] [-m] xbase_file\n" ); printf( " -h: Write header info (field descriptions)\n" ); printf( " -r: Write raw field info, numeric values not reformatted\n" ); printf( " -m: Multiline, one line per field.\n" ); exit( 1 ); } /* -------------------------------------------------------------------- */ /* Open the file. */ /* -------------------------------------------------------------------- */ hDBF = DBFOpen( pszFilename, "rb" ); if( hDBF == NULL ) { printf( "DBFOpen(%s,\"r\") failed.\n", argv[1] ); exit( 2 ); } /* -------------------------------------------------------------------- */ /* If there is no data in this file let the user know. */ /* -------------------------------------------------------------------- */ if( DBFGetFieldCount(hDBF) == 0 ) { printf( "There are no fields in this table!\n" ); exit( 3 ); } /* -------------------------------------------------------------------- */ /* Dump header definitions. */ /* -------------------------------------------------------------------- */ if( bHeader ) { for( i = 0; i < DBFGetFieldCount(hDBF); i++ ) { DBFFieldType eType; const char *pszTypeName; char chNativeType; chNativeType = DBFGetNativeFieldType( hDBF, i ); eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals ); if( eType == FTString ) pszTypeName = "String"; else if( eType == FTInteger ) pszTypeName = "Integer"; else if( eType == FTDouble ) pszTypeName = "Double"; else if( eType == FTInvalid ) pszTypeName = "Invalid"; printf( "Field %d: Type=%c/%s, Title=`%s', Width=%d, Decimals=%d\n", i, chNativeType, pszTypeName, szTitle, nWidth, nDecimals ); } } /* -------------------------------------------------------------------- */ /* Compute offsets to use when printing each of the field */ /* values. We make each field as wide as the field title+1, or */ /* the field value + 1. */ /* -------------------------------------------------------------------- */ panWidth = (int *) malloc( DBFGetFieldCount( hDBF ) * sizeof(int) ); for( i = 0; i < DBFGetFieldCount(hDBF) && !bMultiLine; i++ ) { DBFFieldType eType; eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals ); if( (int) strlen(szTitle) > nWidth ) panWidth[i] = strlen(szTitle); else panWidth[i] = nWidth; if( eType == FTString ) sprintf( szFormat, "%%-%ds ", panWidth[i] ); else sprintf( szFormat, "%%%ds ", panWidth[i] ); printf( szFormat, szTitle ); } printf( "\n" ); /* -------------------------------------------------------------------- */ /* Read all the records */ /* -------------------------------------------------------------------- */ for( iRecord = 0; iRecord < DBFGetRecordCount(hDBF); iRecord++ ) { if( bMultiLine ) printf( "Record: %d\n", iRecord ); for( i = 0; i < DBFGetFieldCount(hDBF); i++ ) { DBFFieldType eType; eType = DBFGetFieldInfo( hDBF, i, szTitle, &nWidth, &nDecimals ); if( bMultiLine ) { printf( "%s: ", szTitle ); } /* -------------------------------------------------------------------- */ /* Print the record according to the type and formatting */ /* information implicit in the DBF field description. */ /* -------------------------------------------------------------------- */ if( !bRaw ) { if( DBFIsAttributeNULL( hDBF, iRecord, i ) ) { if( eType == FTString ) sprintf( szFormat, "%%-%ds", nWidth ); else sprintf( szFormat, "%%%ds", nWidth ); printf( szFormat, "(NULL)" ); } else { switch( eType ) { case FTString: sprintf( szFormat, "%%-%ds", nWidth ); printf( szFormat, DBFReadStringAttribute( hDBF, iRecord, i ) ); break; case FTInteger: sprintf( szFormat, "%%%dd", nWidth ); printf( szFormat, DBFReadIntegerAttribute( hDBF, iRecord, i ) ); break; case FTDouble: sprintf( szFormat, "%%%d.%dlf", nWidth, nDecimals ); printf( szFormat, DBFReadDoubleAttribute( hDBF, iRecord, i ) ); break; default: break; } } } /* -------------------------------------------------------------------- */ /* Just dump in raw form (as formatted in the file). */ /* -------------------------------------------------------------------- */ else { sprintf( szFormat, "%%-%ds", nWidth ); printf( szFormat, DBFReadStringAttribute( hDBF, iRecord, i ) ); } /* -------------------------------------------------------------------- */ /* Write out any extra spaces required to pad out the field */ /* width. */ /* -------------------------------------------------------------------- */ if( !bMultiLine ) { sprintf( szFormat, "%%%ds", panWidth[i] - nWidth + 1 ); printf( szFormat, "" ); } if( bMultiLine ) printf( "\n" ); fflush( stdout ); } if( DBFIsRecordDeleted(hDBF, iRecord) ) printf( "(DELETED)" ); printf( "\n" ); } DBFClose( hDBF ); free( panWidth ); return( 0 ); }
OGRErr OGRShapeLayer::Repack() { if( !bUpdateAccess ) { CPLError( CE_Failure, CPLE_AppDefined, "The REPACK operation is not permitted on a read-only shapefile." ); return OGRERR_FAILURE; } if( hDBF == NULL ) { CPLError( CE_Failure, CPLE_NotSupported, "Attempt to repack a shapefile with no .dbf file not supported."); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Build a list of records to be dropped. */ /* -------------------------------------------------------------------- */ int *panRecordsToDelete = (int *) CPLMalloc(sizeof(int)*(nTotalShapeCount+1)); int nDeleteCount = 0; int iShape = 0; OGRErr eErr = OGRERR_NONE; for( iShape = 0; iShape < nTotalShapeCount; iShape++ ) { if( DBFIsRecordDeleted( hDBF, iShape ) ) panRecordsToDelete[nDeleteCount++] = iShape; } panRecordsToDelete[nDeleteCount] = -1; /* -------------------------------------------------------------------- */ /* If there are no records marked for deletion, we take no */ /* action. */ /* -------------------------------------------------------------------- */ if( nDeleteCount == 0 ) { CPLFree( panRecordsToDelete ); return OGRERR_NONE; } /* -------------------------------------------------------------------- */ /* Find existing filenames with exact case (see #3293). */ /* -------------------------------------------------------------------- */ CPLString osDirname(CPLGetPath(pszFullName)); CPLString osBasename(CPLGetBasename(pszFullName)); CPLString osDBFName, osSHPName, osSHXName; char **papszCandidates = CPLReadDir( osDirname ); int i = 0; while(papszCandidates != NULL && papszCandidates[i] != NULL) { CPLString osCandidateBasename = CPLGetBasename(papszCandidates[i]); CPLString osCandidateExtension = CPLGetExtension(papszCandidates[i]); if (osCandidateBasename.compare(osBasename) == 0) { if (EQUAL(osCandidateExtension, "dbf")) osDBFName = CPLFormFilename(osDirname, papszCandidates[i], NULL); else if (EQUAL(osCandidateExtension, "shp")) osSHPName = CPLFormFilename(osDirname, papszCandidates[i], NULL); else if (EQUAL(osCandidateExtension, "shx")) osSHXName = CPLFormFilename(osDirname, papszCandidates[i], NULL); } i++; } CSLDestroy(papszCandidates); papszCandidates = NULL; if (osDBFName.size() == 0) { /* Should not happen, really */ CPLFree( panRecordsToDelete ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Cleanup any existing spatial index. It will become */ /* meaningless when the fids change. */ /* -------------------------------------------------------------------- */ if( CheckForQIX() ) DropSpatialIndex(); /* -------------------------------------------------------------------- */ /* Create a new dbf file, matching the old. */ /* -------------------------------------------------------------------- */ DBFHandle hNewDBF = NULL; CPLString oTempFile(CPLFormFilename(osDirname, osBasename, NULL)); oTempFile += "_packed.dbf"; hNewDBF = DBFCloneEmpty( hDBF, oTempFile ); if( hNewDBF == NULL ) { CPLFree( panRecordsToDelete ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to create temp file %s.", oTempFile.c_str() ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy over all records that are not deleted. */ /* -------------------------------------------------------------------- */ int iDestShape = 0; int iNextDeletedShape = 0; for( iShape = 0; iShape < nTotalShapeCount && eErr == OGRERR_NONE; iShape++ ) { if( panRecordsToDelete[iNextDeletedShape] == iShape ) iNextDeletedShape++; else { void *pTuple = (void *) DBFReadTuple( hDBF, iShape ); if( pTuple == NULL ) eErr = OGRERR_FAILURE; else if( !DBFWriteTuple( hNewDBF, iDestShape++, pTuple ) ) eErr = OGRERR_FAILURE; } } if( eErr != OGRERR_NONE ) { CPLFree( panRecordsToDelete ); VSIUnlink( oTempFile ); return eErr; } /* -------------------------------------------------------------------- */ /* Cleanup the old .dbf and rename the new one. */ /* -------------------------------------------------------------------- */ DBFClose( hDBF ); DBFClose( hNewDBF ); hDBF = hNewDBF = NULL; VSIUnlink( osDBFName ); if( VSIRename( oTempFile, osDBFName ) != 0 ) { CPLDebug( "Shape", "Can not rename DBF file: %s", VSIStrerror( errno ) ); CPLFree( panRecordsToDelete ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Now create a shapefile matching the old one. */ /* -------------------------------------------------------------------- */ if( hSHP != NULL ) { SHPHandle hNewSHP = NULL; if (osSHPName.size() == 0 || osSHXName.size() == 0) { /* Should not happen, really */ CPLFree( panRecordsToDelete ); return OGRERR_FAILURE; } oTempFile = CPLFormFilename(osDirname, osBasename, NULL); oTempFile += "_packed.shp"; hNewSHP = SHPCreate( oTempFile, hSHP->nShapeType ); if( hNewSHP == NULL ) { CPLFree( panRecordsToDelete ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy over all records that are not deleted. */ /* -------------------------------------------------------------------- */ iNextDeletedShape = 0; for( iShape = 0; iShape < nTotalShapeCount && eErr == OGRERR_NONE; iShape++ ) { if( panRecordsToDelete[iNextDeletedShape] == iShape ) iNextDeletedShape++; else { SHPObject *hObject; hObject = SHPReadObject( hSHP, iShape ); if( hObject == NULL ) eErr = OGRERR_FAILURE; else if( SHPWriteObject( hNewSHP, -1, hObject ) == -1 ) eErr = OGRERR_FAILURE; if( hObject ) SHPDestroyObject( hObject ); } } if( eErr != OGRERR_NONE ) { CPLFree( panRecordsToDelete ); VSIUnlink( CPLResetExtension( oTempFile, "shp" ) ); VSIUnlink( CPLResetExtension( oTempFile, "shx" ) ); return eErr; } /* -------------------------------------------------------------------- */ /* Cleanup the old .shp/.shx and rename the new one. */ /* -------------------------------------------------------------------- */ SHPClose( hSHP ); SHPClose( hNewSHP ); hSHP = hNewSHP = NULL; VSIUnlink( osSHPName ); VSIUnlink( osSHXName ); oTempFile = CPLResetExtension( oTempFile, "shp" ); if( VSIRename( oTempFile, osSHPName ) != 0 ) { CPLDebug( "Shape", "Can not rename SHP file: %s", VSIStrerror( errno ) ); CPLFree( panRecordsToDelete ); return OGRERR_FAILURE; } oTempFile = CPLResetExtension( oTempFile, "shx" ); if( VSIRename( oTempFile, osSHXName ) != 0 ) { CPLDebug( "Shape", "Can not rename SHX file: %s", VSIStrerror( errno ) ); CPLFree( panRecordsToDelete ); return OGRERR_FAILURE; } } CPLFree( panRecordsToDelete ); panRecordsToDelete = NULL; /* -------------------------------------------------------------------- */ /* Reopen the shapefile */ /* */ /* We do not need to reimplement OGRShapeDataSource::OpenFile() here */ /* with the fully featured error checking. */ /* If all operations above succeeded, then all necessery files are */ /* in the right place and accessible. */ /* -------------------------------------------------------------------- */ CPLAssert( NULL == hSHP ); CPLAssert( NULL == hDBF && NULL == hNewDBF ); CPLPushErrorHandler( CPLQuietErrorHandler ); const char* pszAccess = NULL; if( bUpdateAccess ) pszAccess = "r+"; else pszAccess = "r"; hSHP = SHPOpen ( CPLResetExtension( pszFullName, "shp" ) , pszAccess ); hDBF = DBFOpen ( CPLResetExtension( pszFullName, "dbf" ) , pszAccess ); CPLPopErrorHandler(); if( NULL == hSHP || NULL == hDBF ) { CPLString osMsg(CPLGetLastErrorMsg()); CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() ); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Update total shape count. */ /* -------------------------------------------------------------------- */ nTotalShapeCount = hDBF->nRecords; return OGRERR_NONE; }
/* Return an allocated string representation of a specified record item */ int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord) { SHPObject *obj = NULL; stringbuffer_t *sb; stringbuffer_t *sbwarn; char val[MAXVALUELEN]; char *escval; char *geometry=NULL, *ret; char *utf8str; int res, i; int rv; /* Clear the stringbuffers */ sbwarn = stringbuffer_create(); stringbuffer_clear(sbwarn); sb = stringbuffer_create(); stringbuffer_clear(sb); /* If we are reading the DBF only and the record has been marked deleted, return deleted record status */ if (state->config->readshape == 0 && DBFIsRecordDeleted(state->hDBFHandle, item)) { *strrecord = NULL; return SHPLOADERRECDELETED; } /* If we are reading the shapefile, open the specified record */ if (state->config->readshape == 1) { obj = SHPReadObject(state->hSHPHandle, item); if (!obj) { snprintf(state->message, SHPLOADERMSGLEN, _("Error reading shape object %d"), item); return SHPLOADERERR; } /* If we are set to skip NULLs, return a NULL record status */ if (state->config->null_policy == POLICY_NULL_SKIP && obj->nVertices == 0 ) { SHPDestroyObject(obj); *strrecord = NULL; return SHPLOADERRECISNULL; } } /* If not in dump format, generate the INSERT string */ if (!state->config->dump_format) { if (state->config->schema) { stringbuffer_aprintf(sb, "INSERT INTO \"%s\".\"%s\" %s VALUES (", state->config->schema, state->config->table, state->col_names); } else { stringbuffer_aprintf(sb, "INSERT INTO \"%s\" %s VALUES (", state->config->table, state->col_names); } } /* Read all of the attributes from the DBF file for this item */ for (i = 0; i < DBFGetFieldCount(state->hDBFHandle); i++) { /* Special case for NULL attributes */ if (DBFIsAttributeNULL(state->hDBFHandle, item, i)) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\\N"); else stringbuffer_aprintf(sb, "NULL"); } else { /* Attribute NOT NULL */ switch (state->types[i]) { case FTInteger: case FTDouble: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } /* If the value is an empty string, change to 0 */ if (val[0] == '\0') { val[0] = '0'; val[1] = '\0'; } /* If the value ends with just ".", remove the dot */ if (val[strlen(val) - 1] == '.') val[strlen(val) - 1] = '\0'; break; case FTString: case FTLogical: case FTDate: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } break; default: snprintf(state->message, SHPLOADERMSGLEN, _("Error: field %d has invalid or unknown field type (%d)"), i, state->types[i]); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } if (state->config->encoding) { char *encoding_msg = _("Try \"LATIN1\" (Western European), or one of the values described at http://www.postgresql.org/docs/current/static/multibyte.html."); rv = utf8(state->config->encoding, val, &utf8str); if (rv != UTF8_GOOD_RESULT) { if ( rv == UTF8_BAD_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), utf8str, strerror(errno), state->config->encoding, encoding_msg); else if ( rv == UTF8_NO_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), strerror(errno), state->config->encoding, encoding_msg); else snprintf(state->message, SHPLOADERMSGLEN, _("Unexpected return value from utf8()")); if ( rv == UTF8_BAD_RESULT ) free(utf8str); return SHPLOADERERR; } strncpy(val, utf8str, MAXVALUELEN); free(utf8str); } /* Escape attribute correctly according to dump format */ if (state->config->dump_format) { escval = escape_copy_string(val); stringbuffer_aprintf(sb, "%s", escval); } else { escval = escape_insert_string(val); stringbuffer_aprintf(sb, "'%s'", escval); } /* Free the escaped version if required */ if (val != escval) free(escval); } /* Only put in delimeter if not last field or a shape will follow */ if (state->config->readshape == 1 || i < DBFGetFieldCount(state->hDBFHandle) - 1) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\t"); else stringbuffer_aprintf(sb, ","); } /* End of DBF attribute loop */ } /* Add the shape attribute if we are reading it */ if (state->config->readshape == 1) { /* Handle the case of a NULL shape */ if (obj->nVertices == 0) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\\N"); else stringbuffer_aprintf(sb, "NULL"); } else { /* Handle all other shape attributes */ switch (obj->nSHPType) { case SHPT_POLYGON: case SHPT_POLYGONM: case SHPT_POLYGONZ: res = GeneratePolygonGeometry(state, obj, &geometry); break; case SHPT_POINT: case SHPT_POINTM: case SHPT_POINTZ: res = GeneratePointGeometry(state, obj, &geometry, 0); break; case SHPT_MULTIPOINT: case SHPT_MULTIPOINTM: case SHPT_MULTIPOINTZ: /* Force it to multi unless using -S */ res = GeneratePointGeometry(state, obj, &geometry, state->config->simple_geometries ? 0 : 1); break; case SHPT_ARC: case SHPT_ARCM: case SHPT_ARCZ: res = GenerateLineStringGeometry(state, obj, &geometry); break; default: snprintf(state->message, SHPLOADERMSGLEN, _("Shape type is not supported, type id = %d"), obj->nSHPType); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* The default returns out of the function, so res will always have been set. */ if (res != SHPLOADEROK) { /* Error message has already been set */ SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* Now generate the geometry string according to the current configuration */ if (!state->config->dump_format) { if (state->to_srid != state->from_srid) { stringbuffer_aprintf(sb, "ST_Transform("); } stringbuffer_aprintf(sb, "'"); } stringbuffer_aprintf(sb, "%s", geometry); if (!state->config->dump_format) { stringbuffer_aprintf(sb, "'"); /* Close the ST_Transform if reprojecting. */ if (state->to_srid != state->from_srid) { /* We need to add an explicit cast to geography/geometry to ensure that PostgreSQL doesn't get confused with the ST_Transform() raster function. */ if (state->config->geography) stringbuffer_aprintf(sb, "::geometry, %d)::geography", state->to_srid); else stringbuffer_aprintf(sb, "::geometry, %d)", state->to_srid); } } free(geometry); } /* Tidy up everything */ SHPDestroyObject(obj); } /* Close the line correctly for dump/insert format */ if (!state->config->dump_format) stringbuffer_aprintf(sb, ");"); /* Copy the string buffer into a new string, destroying the string buffer */ ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1); strcpy(ret, (char *)stringbuffer_getstring(sb)); stringbuffer_destroy(sb); *strrecord = ret; /* If any warnings occurred, set the returned message string and warning status */ if (strlen((char *)stringbuffer_getstring(sbwarn)) > 0) { snprintf(state->message, SHPLOADERMSGLEN, "%s", stringbuffer_getstring(sbwarn)); stringbuffer_destroy(sbwarn); return SHPLOADERWARN; } else { /* Everything went okay */ stringbuffer_destroy(sbwarn); return SHPLOADEROK; } }