コード例 #1
0
int OGROCIDataSource::Open( const char * pszNewName,
                            char** papszOpenOptionsIn,
                            int bUpdate,
                            int bTestOpen )

{
    CPLAssert( nLayers == 0 && poSession == NULL );

/* -------------------------------------------------------------------- */
/*      Verify Oracle prefix.                                           */
/* -------------------------------------------------------------------- */
    if( !STARTS_WITH_CI(pszNewName,"OCI:") )
    {
        if( !bTestOpen )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "%s does not conform to Oracle OCI driver naming convention,"
                      " OCI:*\n", pszNewName );
        }
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Try to parse out name, password and database name.              */
/* -------------------------------------------------------------------- */
    char *pszUserid;
    const char *pszPassword = "";
    const char *pszDatabase = "";
    char **papszTableList = NULL;
    const char *pszWorkspace = "";

    int   i;

    if( pszNewName[4] == '\0' )
    {
        pszUserid = CPLStrdup(CSLFetchNameValueDef(papszOpenOptionsIn, "USER", ""));
        pszPassword = CSLFetchNameValueDef(papszOpenOptionsIn, "PASSWORD", "");
        pszDatabase = CSLFetchNameValueDef(papszOpenOptionsIn, "DBNAME", "");
        const char* pszTables = CSLFetchNameValue(papszOpenOptionsIn, "TABLES");
        if( pszTables )
            papszTableList = CSLTokenizeStringComplex(pszTables, ",", TRUE, FALSE );
        pszWorkspace = CSLFetchNameValueDef(papszOpenOptions, "WORKSPACE", "");
    }
    else
    {
        pszUserid = CPLStrdup( pszNewName + 4 );

        // Is there a table list?
        for( i = static_cast<int>(strlen(pszUserid))-1; i > 1; i-- )
        {
            if( pszUserid[i] == ':' )
            {
                papszTableList = CSLTokenizeStringComplex( pszUserid+i+1, ",",
                                                        TRUE, FALSE );
                pszUserid[i] = '\0';
                break;
            }

            if( pszUserid[i] == '/' || pszUserid[i] == '@' )
                break;
        }

        for( i = 0;
            pszUserid[i] != '\0' && pszUserid[i] != '/' && pszUserid[i] != '@';
            i++ ) {}

        if( pszUserid[i] == '/' )
        {
            pszUserid[i++] = '\0';
            pszPassword = pszUserid + i;
            for( ; pszUserid[i] != '\0' && pszUserid[i] != '@'; i++ ) {}
        }

        if( pszUserid[i] == '@' )
        {
            pszUserid[i++] = '\0';
            pszDatabase = pszUserid + i;
        }
    }

/* -------------------------------------------------------------------- */
/*      Try to establish connection.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "OCI", "Userid=%s, Password=%s, Database=%s",
              pszUserid, pszPassword, pszDatabase );

    if( EQUAL(pszDatabase, "") &&
        EQUAL(pszPassword, "") &&
        EQUAL(pszUserid, "") )
    {
        /* Use username/password OS Authentication and ORACLE_SID database */

        poSession = OGRGetOCISession( "/", "", "" );
    }
    else
    {
        poSession = OGRGetOCISession( pszUserid, pszPassword, pszDatabase );
    }

    if( poSession == NULL )
    {
        CPLFree(pszUserid);
        CSLDestroy(papszTableList);
        return FALSE;
    }

    if( ! EQUAL(pszWorkspace, "") )
    {
        OGROCIStringBuf oValidateCmd;
        OGROCIStatement oValidateStmt( GetSession() );

        oValidateCmd.Append( "call DBMS_WM.GotoWorkspace('" );
        oValidateCmd.Append( pszWorkspace );
        oValidateCmd.Append( "')" );

        oValidateStmt.Execute( oValidateCmd.GetString() );
    }

    pszName = CPLStrdup( pszNewName );

    bDSUpdate = bUpdate;

/* -------------------------------------------------------------------- */
/*      If no list of target tables was provided, collect a list of     */
/*      spatial tables now.                                             */
/* -------------------------------------------------------------------- */
    if( papszTableList == NULL )
    {
        OGROCIStatement oGetTables( poSession );

        if( oGetTables.Execute(
            "SELECT TABLE_NAME, OWNER FROM ALL_SDO_GEOM_METADATA" )
            == CE_None )
        {
            char **papszRow;

            while( (papszRow = oGetTables.SimpleFetchRow()) != NULL )
            {
                char szFullTableName[100];

                if( EQUAL(papszRow[1],pszUserid) )
                    strcpy( szFullTableName, papszRow[0] );
                else
                    snprintf( szFullTableName, sizeof(szFullTableName), "%s.%s",
                             papszRow[1], papszRow[0] );

                if( CSLFindString( papszTableList, szFullTableName ) == -1 )
                    papszTableList = CSLAddString( papszTableList,
                                                   szFullTableName );
            }
        }
    }
    CPLFree( pszUserid );

/* -------------------------------------------------------------------- */
/*      Open all the selected tables or views.                          */
/* -------------------------------------------------------------------- */
    for( i = 0; papszTableList != NULL && papszTableList[i] != NULL; i++ )
    {
        OpenTable( papszTableList[i], -1, bUpdate, FALSE, papszOpenOptionsIn );
    }

    CSLDestroy( papszTableList );

    return TRUE;
}
コード例 #2
0
int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )

{
    char                *pszWKT = NULL;
    int                 nSRSId;

    if( poSRS == NULL )
        return -1;

    if( !poSRS->IsProjected() && !poSRS->IsGeographic() )
        return -1;

/* ==================================================================== */
/*      The first strategy is to see if we can identify it by           */
/*      authority information within the SRS.  Either using ORACLE      */
/*      authority values directly, or check if there is a known         */
/*      translation for an EPSG authority code.                         */
/* ==================================================================== */
    const char *pszAuthName = NULL, *pszAuthCode = NULL;

    if( poSRS->IsGeographic() )
    {
        pszAuthName = poSRS->GetAuthorityName( "GEOGCS" );
        pszAuthCode = poSRS->GetAuthorityCode( "GEOGCS" );
    }
    else if( poSRS->IsProjected() )
    {
        pszAuthName = poSRS->GetAuthorityName( "PROJCS" );
        pszAuthCode = poSRS->GetAuthorityCode( "PROJCS" );
    }

    if( pszAuthName != NULL && pszAuthCode != NULL )
    {
        if( EQUAL(pszAuthName,"Oracle")
            && atoi(pszAuthCode) != 0 )
            return atoi(pszAuthCode);

        if( EQUAL(pszAuthName,"EPSG") )
        {
            int i, nEPSGCode = atoi(pszAuthCode);

            for( i = 0; anEPSGOracleMapping[i] != 0; i += 2 )
            {
                if( nEPSGCode == anEPSGOracleMapping[i+1] )
                    return anEPSGOracleMapping[i];
            }
        }
    }

/* ==================================================================== */
/*      We need to lookup the SRS in the existing Oracle CS_SRS         */
/*      table.                                                          */
/* ==================================================================== */

/* -------------------------------------------------------------------- */
/*      Convert SRS into old style format (SF-SQL 1.0).                 */
/* -------------------------------------------------------------------- */
    OGRSpatialReference *poSRS2 = poSRS->Clone();

    poSRS2->StripCTParms();

/* -------------------------------------------------------------------- */
/*      Convert any degree type unit names to "Decimal Degree".         */
/* -------------------------------------------------------------------- */
    double dfAngularUnits = poSRS2->GetAngularUnits( NULL );
    if( fabs(dfAngularUnits - 0.0174532925199433) < 0.0000000000000010 )
        poSRS2->SetAngularUnits( "Decimal Degree", 0.0174532925199433 );

/* -------------------------------------------------------------------- */
/*      Translate SRS to WKT.                                           */
/* -------------------------------------------------------------------- */
    if( poSRS2->exportToWkt( &pszWKT ) != OGRERR_NONE )
    {
        delete poSRS2;
        return -1;
    }

    delete poSRS2;

/* -------------------------------------------------------------------- */
/*      Try to find in the existing table.                              */
/* -------------------------------------------------------------------- */
    OGROCIStringBuf     oCmdText;
    OGROCIStatement     oCmdStatement( GetSession() );
    char                **papszResult = NULL;

    oCmdText.Append( "SELECT SRID FROM MDSYS.CS_SRS WHERE WKTEXT = '" );
    oCmdText.Append( pszWKT );
    oCmdText.Append( "'" );

    if( oCmdStatement.Execute( oCmdText.GetString() ) == CE_None )
        papszResult = oCmdStatement.SimpleFetchRow() ;

/* -------------------------------------------------------------------- */
/*      We got it!  Return it.                                          */
/* -------------------------------------------------------------------- */
    if( CSLCount(papszResult) == 1 )
    {
        CPLFree( pszWKT );
        return atoi( papszResult[0] );
    }

/* ==================================================================== */
/*      We didn't find it, so we need to define it as a new SRID at     */
/*      the end of the list of known values.                            */
/* ==================================================================== */

/* -------------------------------------------------------------------- */
/*      Get the current maximum srid in the srs table.                  */
/* -------------------------------------------------------------------- */
    if( oCmdStatement.Execute("SELECT MAX(SRID) FROM MDSYS.CS_SRS") == CE_None )
        papszResult = oCmdStatement.SimpleFetchRow();
    else
        papszResult = NULL;

    if( CSLCount(papszResult) == 1 )
        nSRSId = atoi(papszResult[0]) + 1;
    else
        nSRSId = 1;

/* -------------------------------------------------------------------- */
/*      Try adding the SRS to the SRS table.                            */
/* -------------------------------------------------------------------- */
    oCmdText.Clear();
    oCmdText.Append( "INSERT INTO MDSYS.CS_SRS (SRID, WKTEXT, CS_NAME) " );
    oCmdText.Appendf( 100, " VALUES (%d,'", nSRSId );
    oCmdText.Append( pszWKT );
    oCmdText.Append( "', '" );
    oCmdText.Append( poSRS->GetRoot()->GetChild(0)->GetValue() );
    oCmdText.Append( "' )" );

    CPLFree( pszWKT );

    if( oCmdStatement.Execute( oCmdText.GetString() ) != CE_None )
        return -1;
    else
        return nSRSId;
}
コード例 #3
0
void OGROCIDataSource::ValidateLayer( const char *pszLayerName )

{
    int iLayer;

/* -------------------------------------------------------------------- */
/*      Try to find layer.                                              */
/* -------------------------------------------------------------------- */
    for( iLayer = 0; iLayer < nLayers; iLayer++ )
    {
        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
            break;
    }

    if( iLayer == nLayers )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "ValidateLayer(): %s is not a recognised layer.",
                  pszLayerName );
        return;
    }

/* -------------------------------------------------------------------- */
/*      Verify we have an FID and geometry column for this table.       */
/* -------------------------------------------------------------------- */
    OGROCITableLayer *poLayer = (OGROCITableLayer *) papoLayers[iLayer];

    if( strlen(poLayer->GetFIDColumn()) == 0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "ValidateLayer(): %s lacks a fid column.",
                  pszLayerName );

        return;
    }

/* -------------------------------------------------------------------- */
/*      Prepare and execute the geometry validation.                    */
/* -------------------------------------------------------------------- */

    if( strlen(poLayer->GetGeometryColumn()) != 0 )
    {
        OGROCIStringBuf oValidateCmd;
        OGROCIStatement oValidateStmt( GetSession() );

        oValidateCmd.Append( "SELECT c." );
        oValidateCmd.Append( poLayer->GetFIDColumn() );
        oValidateCmd.Append( ", SDO_GEOM.VALIDATE_GEOMETRY(c." );
        oValidateCmd.Append( poLayer->GetGeometryColumn() );
        oValidateCmd.Append( ", m.diminfo) from " );
        oValidateCmd.Append( poLayer->GetLayerDefn()->GetName() );
        oValidateCmd.Append( " c, user_sdo_geom_metadata m WHERE m.table_name= '");
        oValidateCmd.Append( poLayer->GetLayerDefn()->GetName() );
        oValidateCmd.Append( "' AND m.column_name = '" );
        oValidateCmd.Append( poLayer->GetGeometryColumn() );
        oValidateCmd.Append( "' AND SDO_GEOM.VALIDATE_GEOMETRY(c." );
        oValidateCmd.Append( poLayer->GetGeometryColumn() );
        oValidateCmd.Append( ", m.diminfo ) <> 'TRUE'" );

        oValidateStmt.Execute( oValidateCmd.GetString() );

/* -------------------------------------------------------------------- */
/*      Report results to debug stream.                                 */
/* -------------------------------------------------------------------- */
        char **papszRow;

        while( (papszRow = oValidateStmt.SimpleFetchRow()) != NULL )
        {
            const char *pszReason = papszRow[1];

            if( EQUAL(pszReason,"13011") )
                pszReason = "13011: value is out of range";
            else if( EQUAL(pszReason,"13050") )
                pszReason = "13050: unable to construct spatial object";
            else if( EQUAL(pszReason,"13349") )
                pszReason = "13349: polygon boundary crosses itself";

            CPLDebug( "OCI", "Validation failure for FID=%s: %s",
                  papszRow[0], pszReason );
        }
    }
}
コード例 #4
0
ファイル: ogrociloaderlayer.cpp プロジェクト: 0004c/node-gdal
void OGROCILoaderLayer::FinalizeNewLayer()

{
    OGROCIStringBuf  sDimUpdate;

/* -------------------------------------------------------------------- */
/*      If the dimensions are degenerate (all zeros) then we assume     */
/*      there were no geometries, and we don't bother setting the       */
/*      dimensions.                                                     */
/* -------------------------------------------------------------------- */
    if( sExtent.MaxX == 0 && sExtent.MinX == 0
        && sExtent.MaxY == 0 && sExtent.MinY == 0 )
    {
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Layer %s appears to have no geometry ... not setting SDO DIMINFO metadata.", 
                  poFeatureDefn->GetName() );
        return;
                  
    }

/* -------------------------------------------------------------------- */
/*      Establish the extents and resolution to use.                    */
/* -------------------------------------------------------------------- */
    double           dfResSize;
    double           dfXMin, dfXMax, dfXRes;
    double           dfYMin, dfYMax, dfYRes;
    double           dfZMin, dfZMax, dfZRes;

    if( sExtent.MaxX - sExtent.MinX > 400 )
        dfResSize = 0.001;
    else
        dfResSize = 0.0000001;

    dfXMin = sExtent.MinX - dfResSize * 3;
    dfXMax = sExtent.MaxX + dfResSize * 3;
    dfXRes = dfResSize;
    ParseDIMINFO( "DIMINFO_X", &dfXMin, &dfXMax, &dfXRes );
    
    dfYMin = sExtent.MinY - dfResSize * 3;
    dfYMax = sExtent.MaxY + dfResSize * 3;
    dfYRes = dfResSize;
    ParseDIMINFO( "DIMINFO_Y", &dfYMin, &dfYMax, &dfYRes );
    
    dfZMin = -100000.0;
    dfZMax = 100000.0;
    dfZRes = 0.002;
    ParseDIMINFO( "DIMINFO_Z", &dfZMin, &dfZMax, &dfZRes );
    
/* -------------------------------------------------------------------- */
/*      Prepare dimension update statement.                             */
/* -------------------------------------------------------------------- */
    sDimUpdate.Append( "UPDATE USER_SDO_GEOM_METADATA SET DIMINFO = " );
    sDimUpdate.Append( "MDSYS.SDO_DIM_ARRAY(" );

    sDimUpdate.Appendf(200,
                       "MDSYS.SDO_DIM_ELEMENT('X',%.16g,%.16g,%.12g)",
                       dfXMin, dfXMax, dfXRes );
    sDimUpdate.Appendf(200,
                       ",MDSYS.SDO_DIM_ELEMENT('Y',%.16g,%.16g,%.12g)",
                       dfYMin, dfYMax, dfYRes );

    if( nDimension == 3 )
    {
        sDimUpdate.Appendf(200,
                           ",MDSYS.SDO_DIM_ELEMENT('Z',%.16g,%.16g,%.12g)",
                           dfZMin, dfZMax, dfZRes );
    }

    sDimUpdate.Append( ")" );

    sDimUpdate.Appendf( strlen(poFeatureDefn->GetName()) + 100,
                        " WHERE table_name = UPPER('%s')",
                        poFeatureDefn->GetName() );

/* -------------------------------------------------------------------- */
/*      Execute the metadata update.                                    */
/* -------------------------------------------------------------------- */
    OGROCIStatement oExecStatement( poDS->GetSession() );

    if( oExecStatement.Execute( sDimUpdate.GetString() ) != CE_None )
        return;
}
コード例 #5
0
ファイル: ogrociloaderlayer.cpp プロジェクト: 0004c/node-gdal
OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )

{
    OGROCIStringBuf oLine;

    if( fpData == NULL )
        return OGRERR_FAILURE;

/* -------------------------------------------------------------------- */
/*      Write the FID.                                                  */
/* -------------------------------------------------------------------- */
    oLine.Append( "00000000" );
    oLine.Appendf( 32, " %d|", poFeature->GetFID() );

/* -------------------------------------------------------------------- */
/*      Set the geometry                                                */
/* -------------------------------------------------------------------- */
    if( poFeature->GetGeometryRef() != NULL)
    {
        char szSRID[128];
        int  nGType;
        int  i;

        if( nSRID == -1 )
            strcpy( szSRID, "NULL" );
        else
            sprintf( szSRID, "%d", nSRID );

        if( TranslateToSDOGeometry( poFeature->GetGeometryRef(), &nGType )
            == OGRERR_NONE )
        {
            oLine.Appendf( 32, "%d|", nGType );
            for( i = 0; i < nElemInfoCount; i++ )
            {
                oLine.Appendf( 32, "%d|", panElemInfo[i] );
            }
            oLine.Append( "/" );

            for( i = 0; i < nOrdinalCount; i++ )
            {
                oLine.Appendf( 32, "%.16g|", padfOrdinals[i] );
            }
            oLine.Append( "/" );
        }
        else
        {
            oLine.Append( "0|/|/" );
        }
    }
    else
    {
        oLine.Append( "0|/|/" );
    }

/* -------------------------------------------------------------------- */
/*      Set the other fields.                                           */
/* -------------------------------------------------------------------- */
    int i;

    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
    {
        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(i);

        if( !poFeature->IsFieldSet( i ) )
        {
            if( poFldDefn->GetType() != OFTInteger 
                && poFldDefn->GetType() != OFTReal )
                oLine.Append( "0000" );
            else
                oLine.Append( "|" );
            continue;
        }

        const char *pszStrValue = poFeature->GetFieldAsString(i);

        if( poFldDefn->GetType() == OFTInteger 
            || poFldDefn->GetType() == OFTReal )
        {
            if( poFldDefn->GetWidth() > 0 && bPreservePrecision
                && (int) strlen(pszStrValue) > poFldDefn->GetWidth() )
            {
                ReportTruncation( poFldDefn );
                oLine.Append( "|" );
            }
            else
            {
                oLine.Append( pszStrValue );
                oLine.Append( "|" );
            }
        }
        else 
        {
            int nLength = strlen(pszStrValue);

            if( poFldDefn->GetWidth() > 0 && nLength > poFldDefn->GetWidth() )
            {
                ReportTruncation( poFldDefn );
                nLength = poFldDefn->GetWidth();
                ((char *) pszStrValue)[nLength] = '\0';
            }

            oLine.Appendf( 5, "%04d", nLength );
            oLine.Append( pszStrValue );
        }
    }

    oLine.Appendf( 3, "\n" );

/* -------------------------------------------------------------------- */
/*      Update the line's length, and write to disk.                    */
/* -------------------------------------------------------------------- */
    char szLength[9]; 
    size_t  nStringLen = strlen(oLine.GetString());

    sprintf( szLength, "%08d", (int) (nStringLen-8) );
    strncpy( oLine.GetString(), szLength, 8 );

    if( VSIFWrite( oLine.GetString(), 1, nStringLen, fpData ) != nStringLen )
    {
        CPLError( CE_Failure, CPLE_FileIO, 
                  "Write to loader file failed, likely out of disk space." );
        return OGRERR_FAILURE;
    }
    else
        return OGRERR_NONE;
}
コード例 #6
0
OGRErr OGROCIWritableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )

{
    OGROCISession      *poSession = poDS->GetSession();
    char                szFieldType[256];
    char                szFieldName[30];     // specify at most 30 characters, see ORA-00972
    OGRFieldDefn        oField( poFieldIn );

/* -------------------------------------------------------------------- */
/*      Do we want to "launder" the column names into Oracle            */
/*      friendly format?                                                */
/* -------------------------------------------------------------------- */
    if( bLaunderColumnNames )
    {
        char    *pszSafeName = CPLStrdup( oField.GetNameRef() );

        poSession->CleanName( pszSafeName );
        oField.SetName( pszSafeName );
        CPLFree( pszSafeName );
    }
    
/* -------------------------------------------------------------------- */
/*      Work out the Oracle type.                                       */
/* -------------------------------------------------------------------- */
    if( oField.GetType() == OFTInteger )
    {
        if( bPreservePrecision && oField.GetWidth() != 0 )
            sprintf( szFieldType, "NUMBER(%d)", oField.GetWidth() );
        else
            strcpy( szFieldType, "INTEGER" );
    }
    else if( oField.GetType() == OFTInteger64 )
    {
        if( bPreservePrecision && oField.GetWidth() != 0 )
            sprintf( szFieldType, "NUMBER(%d)", oField.GetWidth() );
        else
            strcpy( szFieldType, "NUMBER(20)" );
    }
    else if( oField.GetType() == OFTReal )
    {
        if( bPreservePrecision && oField.GetWidth() != 0 )
            sprintf( szFieldType, "NUMBER(%d,%d)", 
                     oField.GetWidth(), oField.GetPrecision() );
        else
            strcpy( szFieldType, "FLOAT(126)" );
    }
    else if( oField.GetType() == OFTString )
    {
        if( oField.GetWidth() == 0 || !bPreservePrecision )
            strcpy( szFieldType, "VARCHAR2(2047)" );
        else
            sprintf( szFieldType, "VARCHAR2(%d)", oField.GetWidth() );
    }
    else if ( oField.GetType() == OFTDate )
    {
        sprintf( szFieldType, "DATE" );
    }
    else if ( oField.GetType() == OFTDateTime )
    {
        sprintf( szFieldType, "TIMESTAMP" );
    }
    else if( bApproxOK )
    {
        oField.SetDefault(NULL);
        CPLError( CE_Warning, CPLE_NotSupported,
                  "Can't create field %s with type %s on Oracle layers.  Creating as VARCHAR.",
                  oField.GetNameRef(),
                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
        strcpy( szFieldType, "VARCHAR2(2047)" );
    }
    else
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Can't create field %s with type %s on Oracle layers.",
                  oField.GetNameRef(),
                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );

        return OGRERR_FAILURE;
    }

/* -------------------------------------------------------------------- */
/*      Create the new field.                                           */
/* -------------------------------------------------------------------- */
    OGROCIStringBuf     oCommand;
    OGROCIStatement     oAddField( poSession );

    oCommand.MakeRoomFor( 70 + strlen(poFeatureDefn->GetName())
                          + strlen(oField.GetNameRef())
                          + strlen(szFieldType)
                          + (oField.GetDefault() ? strlen(oField.GetDefault()) : 0) );

    snprintf( szFieldName, sizeof( szFieldName ), "%s", oField.GetNameRef());
    szFieldName[sizeof( szFieldName )-1] = '\0';
    if ( strlen(oField.GetNameRef()) > sizeof ( szFieldName ) )
    {
        szFieldName[sizeof( szFieldName ) - 1] = '_';
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Column %s is too long (at most 30 characters). Using %s.", 
                  oField.GetNameRef(), szFieldName );
        oField.SetName(szFieldName);
    }
    sprintf( oCommand.GetString(), "ALTER TABLE %s ADD \"%s\" %s", 
             poFeatureDefn->GetName(), szFieldName, szFieldType);
    if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
    {
        sprintf( oCommand.GetString() + strlen(oCommand.GetString()),
                 " DEFAULT %s", oField.GetDefault() );
    }
    if( !oField.IsNullable() )
        strcat( oCommand.GetString(), " NOT NULL");
    
    if( oAddField.Execute( oCommand.GetString() ) != CE_None )
        return OGRERR_FAILURE;

    poFeatureDefn->AddFieldDefn( &oField );

    return OGRERR_NONE;
}