示例#1
0
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;
}
示例#2
0
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!");
}
示例#3
0
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 );
}
示例#4
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;
}
示例#5
0
/* 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;
	}
}